java实现云端存储、短信、邮件、沙盒支付
一、云端存储(阿里云)
注意:下面操作是基于购买阿里云云端存储服务实现的
1.FileOSSUtils操作类
package com.zking;
import java.io.BufferedOutputStream;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.URLDecoder;
import java.util.Properties;
import com.aliyun.oss.OSS;
import com.aliyun.oss.OSSClientBuilder;
import com.aliyun.oss.model.OSSObject;
/**
* 云端文件在线存储和下载
*/
public class FileOSSUtils {
private Properties p = null;
// Endpoint以杭州为例,其它Region请按实际情况填写。
private String endpoint;
// 阿里云主账号AccessKey拥有所有API的访问权限,风险很高。强烈建议您创建并使用RAM账号进行API访问或日常运维,请登录 https://ram.console.aliyun.com 创建RAM账号。
private String accessKeyId;
//密钥
private String accessKeySecret;
//根目录
private String bucketName;
public FileOSSUtils() throws Exception {
p = getProperties("fileOssConfig.properties");
endpoint = p.getProperty("endpoint");
accessKeyId = p.getProperty("accessKeyId");
accessKeySecret = p.getProperty("accessKeySecret");
bucketName = p.getProperty("bucketName");
}
/**
* 文件上传
* @param in 需要上传文件的流
* @param savePath 存储的路径,包括文件名
*/
public void uploadFile(InputStream in, String savePath) {
// 创建OSSClient实例。操作云端数据的客户端
OSS ossClient = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret);
//调用putObject上传文件
ossClient.putObject(bucketName, savePath, in);
// 关闭OSSClient。
ossClient.shutdown();
}
/**
* 下载云端文件
* @param out 将文件写入本地的一个输出流(也可以是response的输出流)
* @param dowloadPath
* @param savePath
* @throws IOException
*/
public void downloadFile(OutputStream out, String dowloadPath) throws IOException {
// 创建OSSClient实例。
OSS ossClient = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret);
// ossObject包含文件所在的存储空间名称、文件名称、文件元信息以及一个输入流。
OSSObject ossObject = ossClient.getObject(bucketName, dowloadPath);
//获取云端文件的输入流
InputStream in = ossObject.getObjectContent();
//将文件写入输出流
int len = 0;
byte[] b = new byte[1024];
BufferedOutputStream bos = new BufferedOutputStream(out);
while ((len = in.read(b)) != -1) {
bos.write(b, 0, len);
}
bos.close();
in.close();
// 关闭OSSClient。
ossClient.shutdown();
}
/**
* 通过这个类的反射获取项目的根目录,最终得到一个Properties对象
* @param prosPath Properties文件的路径
* @return 加载了Properties文件的对象
* @throws Exception
*/
public Properties getProperties(String prosPath) throws Exception {
//1.创建一个properties对象
//这个对象里面就有操作这个properties文件所有方法
Properties pros = new Properties();
//2.获取源文件的字节输入流
InputStream inStream = null;
try {
//class文件所在的位置的根目录。
String path = FileOSSUtils.class.getResource("/").getPath();
//将中文的url编码解析%ert%weq
path = URLDecoder.decode(path, "utf-8");
inStream = new FileInputStream(path + "\\" + prosPath);
//3.properties对象加载源文件
pros.load(inStream);
} catch (FileNotFoundException e) {
throw new FileNotFoundException("Properties文件路径未找到!");
} catch (IOException e) {
throw new IOException("Properties文件流加载失败!");
}
return pros;
}
}
2.fileOssConfig.properties文件:
endpoint = http://oss-cn-hangzhou.aliyuncs.com
accessKeyId = 账户名
accessKeySecret = 密码
bucketName = 目录名
savePath = 路径名
3.示例调用:
// 下载所有图片和更新未使用图片的方法
//pics:传过来需要下载图片的信息
//下载到项目路径下
private synchronized void dLOrUpdateAllpics(List<Picture> pics) {
// 获取广告、轮播、展示信息、友情链接图片的文件路径
String path = this.getServletContext().getRealPath("/img/indexAdImg/");
// 新建下载文件类的对象
FileOSSUtils fileOSSUtils;
if (pics != null) {
try {
fileOSSUtils = new FileOSSUtils();
// 循环所有的图片
for (int i = 0; i < pics.size(); i++) {
// 将云端文件夹图片写入项目目录下的文件夹
String dowloadPath = pics.get(i).getPicload();
// 截取下载图片的后缀
String picSuffix = dowloadPath.substring(dowloadPath.indexOf('.'));
// 存储文件的路径
String savePath = "";
// 图片种类
String picKinds = pics.get(i).getEffect_location();
if (picKinds.equals("banner1")) {
savePath = path + "banner1" + picSuffix;
} else if (picKinds.equals("banner2")) {
savePath = path + "banner2" + picSuffix;
} else if (picKinds.equals("banner3")) {
savePath = path + "banner3" + picSuffix;
} else if (picKinds.equals("banner4")) {
savePath = path + "banner4" + picSuffix;
} else if (picKinds.equals("abanner1")) {
savePath = path + "abanner1" + picSuffix;
} else if (picKinds.equals("abanner2")) {
savePath = path + "abanner2" + picSuffix;
} else if (picKinds.equals("abanner3")) {
savePath = path + "abanner3" + picSuffix;
} else if (picKinds.equals("abanner4")) {
savePath = path + "abanner4" + picSuffix;
} else if (picKinds.equals("pro1")) {
savePath = path + "pro1" + picSuffix;
} else if (picKinds.equals("pro2")) {
savePath = path + "pro2" + picSuffix;
} else if (picKinds.equals("pro3")) {
savePath = path + "pro3" + picSuffix;
} else if (picKinds.equals("pro4")) {
savePath = path + "pro4" + picSuffix;
} else if (picKinds.equals("pro5")) {
savePath = path + "pro5" + picSuffix;
} else if (picKinds.equals("pro6")) {
savePath = path + "pro6" + picSuffix;
} else if (picKinds.equals("pro7")) {
savePath = path + "pro7" + picSuffix;
} else if (picKinds.equals("pro8")) {
savePath = path + "pro8" + picSuffix;
} else if (picKinds.equals("link01")) {
savePath = path + "link01" + picSuffix;
} else if (picKinds.equals("link02")) {
savePath = path + "link02" + picSuffix;
} else if (picKinds.equals("link03")) {
savePath = path + "link03" + picSuffix;
} else if (picKinds.equals("link04")) {
savePath = path + "link04" + picSuffix;
} else {
System.out.println("图片名不存在!");
}
// 两个路径都不为空的时候进行下载操作
if (!savePath.equals("") && !dowloadPath.equals("")) {
OutputStream out = new FileOutputStream(savePath);
fileOSSUtils.downloadFile(out, dowloadPath);
System.out.println("下载成功!");
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
二、短信(阿里云)
注意:下面操作是基于阿里云信息服务实现的(需要申请accesskeyId,accessSecret,然后申请短信模板)
1.进入阿里云官网进行注册登录 https://www.aliyun.com/?utm_content=se_1000301881
2.点击右侧头像 ,点击AccessKey管理,点击继续使用Accesskey,然后创建自己的AccessKey。代码里会用到!
3.搜索短信控制台进入短信服务页面 https://dysms.console.aliyun.com/dysms.htm#/overview 点击 ‘国内信息’
4.进入签名管理创建自己的签名
5.进入模板管理创建相关模板,这里的${code}是和代码中的code对接的.(注意区别个人与企业,如果不成功可以换模板名多试几次,本人同一模板名试了几次才成功)
代码实现:
package com.common.sendsms;
import java.util.Random;
import com.alibaba.fastjson.JSONObject;
import com.aliyuncs.CommonRequest;
import com.aliyuncs.CommonResponse;
import com.aliyuncs.DefaultAcsClient;
import com.aliyuncs.IAcsClient;
import com.aliyuncs.exceptions.ClientException;
import com.aliyuncs.exceptions.ServerException;
import com.aliyuncs.http.MethodType;
import com.aliyuncs.profile.DefaultProfile;
public class SendSms {
public String sendMsg(String phoneNum) {
DefaultProfile profile = DefaultProfile.getProfile("default", "accessKeyId", "accessKeySecret");
IAcsClient client = new DefaultAcsClient(profile);
//短信平台有很多的
//有的平台就不限制的
CommonRequest request = new CommonRequest();
//发送方式
request.setMethod(MethodType.POST);
//阿里云域名
request.setDomain("dysmsapi.aliyuncs.com");
//版本日期
request.setVersion("2017-05-25");
//设置动作为发送消息
request.setAction("SendSms");
request.putQueryParameter("RegionId", "default");
//发送到哪个手机号
request.putQueryParameter("PhoneNumbers", {phoneNum(传入)});
//签名
request.putQueryParameter("SignName", "{模板名}");
request.putQueryParameter("TemplateCode", "{模板编码}");
//可填可不填:outId为提供给业务方扩展字段,最终在短信回执消息中将此值带回给调用者
request.putQueryParameter("OutId", "{回显名}");
String code = "";
//随机四位验证码
Random r = new Random();
for (int i = 0; i < 6; i++) {
code += r.nextInt(10);
}
request.putQueryParameter("TemplateParam", "{\"code\":"+code+"}");
try {
CommonResponse response = client.getCommonResponse(request);
//成功就返回这个验证码
if(response!=null) {
return code;
}
//System.out.println(response.getData());
} catch (ServerException e) {
e.printStackTrace();
} catch (ClientException e) {
e.printStackTrace();
}
return null;
}
public static void main(String[] args) {
//测试
//SendSms sendSms=new SendSms();//新建一个发送短信的对象
//打印信息
//System.out.println(sendSms.sendMsg("xxxx"));
}
}
三、邮件
1.首先进入邮箱的设置,打开三方协议POP3/SMPT/IMAP(以下演示是163邮箱)
2.设置授权码,该密码为java代码要使用的授权密码,与登录密码不一样
3.编写工具类:
package com.zking.sendmail;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.util.Properties;
import javax.mail.Authenticator;
import javax.mail.Message;
import javax.mail.Message.RecipientType;
import javax.mail.PasswordAuthentication;
import javax.mail.Session;
import javax.mail.Transport;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeMessage;
public class SendMail {
public static void sendMail(String sender,String toMailName,String header,String msg,)throws Exception{
//注意:同一个ip不要重复的短时间内发邮件,账号容易被冻结
//1 设置基本参数
Properties props = new Properties();
//2.设置主机
props.setProperty("mail.host", "smtp.163.com");
//3.确定使用权限验证
props.setProperty("mail.smtp.auth", "true");
//4.确定账号与密码
Authenticator authenticator = new Authenticator() {
@Override
protected PasswordAuthentication getPasswordAuthentication() {
return new PasswordAuthentication("{邮箱的账号}", "{授权码}");
}
};
//5.获得连接
Session session = Session.getInstance(props, authenticator);
//6.编写消息
Message message = new MimeMessage(session);
//7.设置发件人的邮箱和名字(可随意取)
message.setFrom(new InternetAddress("{设置发件人的邮箱}",sender(参数传入)));
//8.设置收件人邮箱 , to:收件人 cc:抄送 bcc:暗送
message.setRecipient(RecipientType.TO, new InternetAddress(toMailName(参数传入)));
//{设置多个收件人地址}可选,传入多个就将参数改为数组或集合等
//message.addRecipient(RecipientType.TO,new InternetAddress("{设置收件人的邮箱}"));
// 2.3 主题
message.setSubject(header(参数传入));
// 2.4 正文,直接html代码的
message.setContent(msg(参数传入), "text/html;charset=UTF-8");
//3发送消息
Transport.send(message);
System.out.println("发送成功");
br.close();
}
}
四、支付宝沙盒支付
1.注册蚂蚁金服开发者账号。注册地址
2.设置app_id和gatewayUrl,登录之后,会弹出商户入驻信息填写界面,点击切换入驻身份,改为自研开发者,然后填写个人信息。
3.填写完成后,点击开发者中心,再点击点击研发服务,会看到沙箱环境的信息。
4.点击沙箱应用,第一个表格中的APPID、支付宝网关、RSA密钥(要自己生成)就是我们java要用到的。生成密钥方法:
- 下载支付宝开放平台开发助手
- 点击左侧栏的生成密钥栏
- 再回到点击开发者中心的沙箱应用设置RSA密钥
- 沙箱环境中,加签模式选择公钥,然后将工具生成的公钥复制进来,点击保存设置
- 点保存设置后,会生成一个支付宝公钥(要用到的)
5.编写工具类:
package com.lxf.utils;
import java.io.FileWriter;
import java.io.IOException;
/* *
*类名:AlipayConfig
*功能:基础配置类
*详细:设置帐户有关信息及返回路径
*修改日期:2017-04-05
*说明:
*以下代码只是为了方便商户测试而提供的样例代码,商户可以根据自己网站的需要,按照技术文档编写,并非一定要使用该代码。
*该代码仅供学习和研究支付宝接口使用,只是提供一个参考。
*/
public class AlipayConfig {
//↓↓↓↓↓↓↓↓↓↓请在这里配置您的基本信息↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓
// 应用ID,您的APPID,收款账号既是您的APPID对应支付宝账号
public static String app_id = "{您的APPID}";
// 商户私钥,您的PKCS8格式RSA2私钥
public static String merchant_private_key = "{商户私钥}";
// 支付宝公钥,查看地址:https://openhome.alipay.com/platform/keyManage.htm 对应APPID下的支付宝公钥。
public static String alipay_public_key = "{支付宝公钥}";
// 服务器退款异步通知页面路径 需http://格式的完整路径,不能加?id=123这类自定义参数,必须外网可以正常访问
public static String notify_url = "http://localhost:8080/TrainDemo/buyticket?method=refundSuccess";
// 支付页面跳转同步通知页面路径 需http://格式的完整路径,不能加?id=123这类自定义参数,必须外网可以正常访问
public static String return_url = "http://localhost:8080/TrainDemo/buyticket?method=buySuccess";
// 签名方式
public static String sign_type = "RSA2";
// 字符编码格式
public static String charset = "utf-8";
// 支付宝网关
public static String gatewayUrl = "https://openapi.alipaydev.com/gateway.do";
// 日志生成地址
public static String log_path = "D:\\";
//↑↑↑↑↑↑↑↑↑↑请在这里配置您的基本信息↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑
/**
* 写日志,方便测试(看网站需求,也可以改成把记录存入数据库)
* @param sWord 要写入日志里的文本内容
*/
public static void logResult(String sWord) {
FileWriter writer = null;
try {
writer = new FileWriter(log_path + "alipay_log.txt");
writer.write(sWord);
} catch (Exception e) {
e.printStackTrace();
} finally {
if (writer != null) {
try {
writer.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
6.支付跳转页面
注意:从你自己支付界面post传入商户订单号、付款金额(必填)、订单名称(必填)、商品描述(可空),以键值对形式传入,key分别为:WIDout_trade_no、WIDtotal_amount、WIDsubject、WIDbody。然后就由支付宝处理了,处理完再返回配置类配置的return_url地址
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>付款</title>
</head>
<%@ page language="java" contentType="text/html; charset=utf-8" pageEncoding="utf-8"%>
<%@ page import="com.lxf.utils.*"%>
<%@ page import="com.alipay.api.*"%>
<%@ page import="com.alipay.api.request.*"%>
<%
//获得初始化的AlipayClient
AlipayClient alipayClient = new DefaultAlipayClient(AlipayConfig.gatewayUrl, AlipayConfig.app_id, AlipayConfig.merchant_private_key, "json", AlipayConfig.charset, AlipayConfig.alipay_public_key, AlipayConfig.sign_type);
//设置请求参数
AlipayTradePagePayRequest alipayRequest = new AlipayTradePagePayRequest();
alipayRequest.setReturnUrl(AlipayConfig.return_url);
alipayRequest.setNotifyUrl(AlipayConfig.notify_url);
//商户订单号,商户网站订单系统中唯一订单号,必填
String out_trade_no = new String(request.getParameter("WIDout_trade_no").getBytes("ISO-8859-1"),"UTF-8");
//付款金额,必填
String total_amount = new String(request.getParameter("WIDtotal_amount").getBytes("ISO-8859-1"),"UTF-8");
//订单名称,必填
String subject = new String(request.getParameter("WIDsubject").getBytes("ISO-8859-1"),"UTF-8");
//商品描述,可空
String body = new String(request.getParameter("WIDbody").getBytes("ISO-8859-1"),"UTF-8");
alipayRequest.setBizContent("{\"out_trade_no\":\""+ out_trade_no +"\","
+ "\"total_amount\":\""+ total_amount +"\","
+ "\"subject\":\""+ subject +"\","
+ "\"body\":\""+ body +"\","
+ "\"product_code\":\"FAST_INSTANT_TRADE_PAY\"}");
//请求
String result = alipayClient.pageExecute(alipayRequest).getBody();
//输出
out.println(result);
%>
<body>
</body>
</html>
7.测试(支付)**
//购票或抢票按钮
function tBuy(ticketPM){
//判断是抢票还是买票
if(ticketPM.remain_tickets==0){
//抢票
$.confirm({
title: '抢票提示',
content: "确定用该乘车人信息抢购此车票吗?",
type: 'orange',
typeAnimated: true,
buttons: {
omg: {
text: '确定',
btnClass: 'btn-orange',
action:function(){
lightyear.loading('show');
$.ajax({
url:'buyticket',
type:'post',
data:{
method:'ticketBuy',
p_id:passengerInfor.passenger_id,
ticketPM:JSON.stringify(ticketPM).replace(/\"/g, "'"),
t_price:$('#t_price').text(),
t_b_type:2
},
dataType:'json',
success:function(data){
if(data.buyCode==1){
lightyear.notify('订单生成成功,正在跳转页面中~',"success",2000);
setTimeout(function(){
//alipay.trade.page.pay.jsp
//进入支付页面
postOpenWindow('alipay.trade.page.pay.jsp',{
WIDout_trade_no:data.WIDout_trade_no,//商户订单号:WIDout_trade_no
WIDsubject:utf8StrChange(data.WIDsubject+"("+ticketPM.start_station+"-"+ticketPM.end_station+")"),//订单名称:WIDsubject
WIDtotal_amount:data.WIDtotal_amount,//付款金额:WIDtotal_amount
WIDbody:data.WIDbody//商品描述:WIDbody
});
},1000);
}else if(data.buyCode==-2){
lightyear.notify('抢票订单中有订单未支付,请先支付!',"danger",2000);
}else{
lightyear.notify('订单生成失败!',"danger",2000);
}
lightyear.loading('hide');
},
error:function(){
lightyear.notify('请求错误!',"danger",2000);
lightyear.loading('hide');
}
})
}
},
close: {
text: '关闭'
}
}
});
}else if(ticketPM.remain_tickets>0){
//买票
$.confirm({
title: '购票提示',
content: "确定用该乘车人信息购买此车票吗?",
type: 'orange',
typeAnimated: true,
buttons: {
omg: {
text: '确定',
btnClass: 'btn-orange',
action:function(){
lightyear.loading('show');
$.ajax({
url:'buyticket',
type:'post',
data:{
method:'ticketBuy',
p_id:passengerInfor.passenger_id,
ticketPM:JSON.stringify(ticketPM).replace(/\"/g, "'"),
t_price:$('#t_price').text(),
t_b_type:1
},
dataType:'json',
success:function(data){
if(data.buyCode==1){
lightyear.notify('订单生成成功,正在跳转页面中~',"success",2000);
setTimeout(function(){
//alipay.trade.page.pay.jsp
//进入支付页面
postOpenWindow('alipay.trade.page.pay.jsp',{
WIDout_trade_no:data.WIDout_trade_no,//商户订单号:WIDout_trade_no
WIDsubject:utf8StrChange(data.WIDsubject+"("+ticketPM.start_station+"-"+ticketPM.end_station+")"),//订单名称:WIDsubject
WIDtotal_amount:data.WIDtotal_amount,//付款金额:WIDtotal_amount
WIDbody:data.WIDbody//商品描述:WIDbody
});
},1000);
}else if(data.buyCode==-2){
lightyear.notify('购票订单中有订单未支付,请先支付!',"danger",2000);
}else{
lightyear.notify('订单生成失败!',"danger",2000);
}
lightyear.loading('hide');
},
error:function(){
lightyear.notify('请求错误!',"danger",2000);
lightyear.loading('hide');
}
})
}
},
close: {
text: '关闭'
}
}
});
}else{
lightyear.notify('余票数量错误!',"danger",2000);
lightyear.loading('hide');
}
}
//将字符串的格式转换成utf-8格式
function utf8StrChange(str) {
return eval('\''+encodeURI(str).replace(/%/gm, '\\x')+'\'');
}
/**
* 以post方式打开另一个新页面
*/
function postOpenWindow(URL, PARAMS) {
var temp_form = document.createElement("form");
temp_form.action = URL;
temp_form.target = "_blank";
temp_form.method = "post";
temp_form.style.display = "none";
for (var x in PARAMS) {
var opt = document.createElement("textarea");
opt.name = x;
opt.value = PARAMS[x];
temp_form .appendChild(opt);
}
document.body.appendChild(temp_form);
temp_form.submit();
}
java支付回调类:
/**
* 购票成功返回的界面 成功就修改该订单状态
*
* @param request
* @param response
*/
private void buySuccess(HttpServletRequest request, HttpServletResponse response) {
// 返回的url和它的参数值:
// localhost:8080/20200401-aliyun/return_url.jsp?
// charset=utf-8
// &out_trade_no=202071217331586
// &method=alipay.trade.page.pay.return
// &total_amount=90.00
// &sign=Pv5BuwOKB2qgm9diKSpR8CylDRE1O1kN2RXkBKRF89YM9RCLR8CtC61J4JzqBKyr6ZbFBNrvVBuhhFOvdVV8kf10UcPcYn93j4mBWwUpH90s%2FNPOM0bc%2F4TpeSy0BYSjm65NNN07e7lPmhSEyJvkj%2BqwPk06KQ3hCvoS1plrZMKO%2FvrqG%2BkKsM7gpko75KK1cuiuIjDhC7yX8EUH5NT2KTabYzUnpSqUrLIyT8EhDx28leKniUJj2T8P%2FtjmsOITFjWHz%2BwbA7kmf7jEFU4y3Tixz%2B6YmctTUMbceOXezAHk6OOeJMfVkw4v4pIMd%2B4OGPVDGZMybtA4jH9dxdvJ3A%3D%3D
// &trade_no=2020071222001403360500790878
// &auth_app_id=2016102300745988
// &version=1.0
// &app_id=2016102300745988
// &sign_type=RSA2
// &seller_id=2088102180784973
// 时间戳: ×tamp=2020-07-12+17%3A33%3A47
// 支付宝交易号:trade_no
// 商户订单号
String out_trade_no = request.getParameter("out_trade_no");
// 付款金额
String total_amount = request.getParameter("out_trade_no");
if (total_amount != null) {
if (!total_amount.equals("")) {
lxfService.addTotalMonery(Double.valueOf(total_amount));
}
}
// 查询购买类型:抢购或者购买
int t_type = lxfService.queryTicketBuyType(out_trade_no);
int i = 0;// 购票更新情况
int j = 0;// 抢票更新情况
try {
if (t_type == 1) {
// 如果订单编号不为空,直接将订单状态改为已支付
if (out_trade_no != null && !out_trade_no.equals("")) {
i = lxfService.ChangeBuyStatus(out_trade_no);
}
if (i > 0) {
// 更新成功
request.setAttribute("buyCode", 1);
} else {
// 更新失败
request.setAttribute("buyCode", -1);
}
// 购买成功-->跳到火车票订单界面
request.getRequestDispatcher("personalCenter-traTicetOrder.jsp").forward(request, response);
} else if (t_type == 2) {
if (out_trade_no != null && !out_trade_no.equals("")) {
j = lxfService.ChangeGrabStatus((User) request.getSession().getAttribute("user"), out_trade_no);
}
if (j > 0) {
// 更新成功
request.setAttribute("grabCode", 1);
} else {
// 更新失败
request.setAttribute("grabCode", -1);
}
// 抢票成功-->跳到本人车票界面
request.getRequestDispatcher("personalCenter-alternateOrder.jsp").forward(request, response);
} else {
// 其它情况,重定向到首页
response.sendRedirect("HuGongRailwayIndex.jsp");
}
} catch (Exception e) {
e.printStackTrace();
}
}
8.测试(退款)
注意:从你自己退款界面post传入商户订单号或支付宝交易号(二选一)、需要退款的金额(必填)、退款的原因说明、标识一次退款请求,以键值对形式传入,key分别为:WIDTRout_trade_no,WIDTRtrade_no,WIDTRrefund_amount,WIDTRrefund_reason,WIDTRout_request_no。然后就由支付宝处理了,处理完再返回配置类配置的notify_url地址
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>退款</title>
</head>
<%@ page language="java" contentType="text/html; charset=utf-8" pageEncoding="utf-8"%>
<%@ page import="com.zking.alipay.config.*"%>
<%@ page import="com.alipay.api.*"%>
<%@ page import="com.alipay.api.request.*"%>
<%
//获得初始化的AlipayClient
AlipayClient alipayClient = new DefaultAlipayClient(AlipayConfig.gatewayUrl, AlipayConfig.app_id, AlipayConfig.merchant_private_key, "json", AlipayConfig.charset, AlipayConfig.alipay_public_key, AlipayConfig.sign_type);
//设置请求参数
AlipayTradeRefundRequest alipayRequest = new AlipayTradeRefundRequest();
//商户订单号,商户网站订单系统中唯一订单号
String out_trade_no = new String(request.getParameter("WIDTRout_trade_no").getBytes("ISO-8859-1"),"UTF-8");
//支付宝交易号
String trade_no = new String(request.getParameter("WIDTRtrade_no").getBytes("ISO-8859-1"),"UTF-8");
//请二选一设置
//需要退款的金额,该金额不能大于订单金额,必填
String refund_amount = new String(request.getParameter("WIDTRrefund_amount").getBytes("ISO-8859-1"),"UTF-8");
//退款的原因说明
String refund_reason = new String(request.getParameter("WIDTRrefund_reason").getBytes("ISO-8859-1"),"UTF-8");
//标识一次退款请求,同一笔交易多次退款需要保证唯一,如需部分退款,则此参数必传
String out_request_no = new String(request.getParameter("WIDTRout_request_no").getBytes("ISO-8859-1"),"UTF-8");
alipayRequest.setBizContent("{\"out_trade_no\":\""+ out_trade_no +"\","
+ "\"trade_no\":\""+ trade_no +"\","
+ "\"refund_amount\":\""+ refund_amount +"\","
+ "\"refund_reason\":\""+ refund_reason +"\","
+ "\"out_request_no\":\""+ out_request_no +"\"}");
//请求
String result = alipayClient.execute(alipayRequest).getBody();
//输出
out.println(result);
%>
<body>
</body>
</html>
java退款回调类:
/*
实际验证过程建议商户务必添加以下校验:
1、需要验证该通知数据中的out_trade_no是否为商户系统中创建的订单号,
2、判断total_amount是否确实为该订单的实际金额(即商户订单创建时的金额),
3、校验通知中的seller_id(或者seller_email) 是否为out_trade_no这笔单据的对应的操作方(有的时候,一个商户可能有多个seller_id/seller_email)
4、验证app_id是否为该商户本身。
*/
private void refundSuccess(HttpServletRequest request, HttpServletResponse response) {
boolean signVerified = AlipaySignature.rsaCheckV1(params, AlipayConfig.alipay_public_key, AlipayConfig.charset, AlipayConfig.sign_type); //调用SDK验证签名
//——请在这里编写您的程序(以下代码仅作参考)——
/* 实际验证过程建议商户务必添加以下校验:
1、需要验证该通知数据中的out_trade_no是否为商户系统中创建的订单号,
2、判断total_amount是否确实为该订单的实际金额(即商户订单创建时的金额),
3、校验通知中的seller_id(或者seller_email) 是否为out_trade_no这笔单据的对应的操作方(有的时候,一个商户可能有多个seller_id/seller_email)
4、验证app_id是否为该商户本身。
*/
if(signVerified) {//验证成功
//商户订单号
String out_trade_no = new String(request.getParameter("out_trade_no").getBytes("ISO-8859-1"),"UTF-8");
//支付宝交易号
String trade_no = new String(request.getParameter("trade_no").getBytes("ISO-8859-1"),"UTF-8");
//交易状态
String trade_status = new String(request.getParameter("trade_status").getBytes("ISO-8859-1"),"UTF-8");
if(trade_status.equals("TRADE_FINISHED")){
//判断该笔订单是否在商户网站中已经做过处理
//如果没有做过处理,根据订单号(out_trade_no)在商户网站的订单系统中查到该笔订单的详细,并执行商户的业务程序
//如果有做过处理,不执行商户的业务程序
//注意:
//退款日期超过可退款期限后(如三个月可退款),支付宝系统发送该交易状态通知
}else if (trade_status.equals("TRADE_SUCCESS")){
//判断该笔订单是否在商户网站中已经做过处理
//如果没有做过处理,根据订单号(out_trade_no)在商户网站的订单系统中查到该笔订单的详细,并执行商户的业务程序
//如果有做过处理,不执行商户的业务程序
//注意:
//付款完成后,支付宝系统发送该交易状态通知
}
out.println("success");
}else {//验证失败
out.println("fail");
//调试用,写文本函数记录程序运行情况是否正常
//String sWord = AlipaySignature.getSignCheckContentV1(params);
//AlipayConfig.logResult(sWord);
}
}