这次项目需要加入支付宝支付的功能,现在写完了总结一下:
准备工作:
maven需要引入com.alipay.sdk:
<dependency>
<groupId>com.alipay.sdk</groupId>
<artifactId>alipay-sdk-java</artifactId>
<version>3.0.0</version>
</dependency>
支付宝app支付的流程
- 用户发起请求,后台将用户的请求数据和商户信息加密传输给支付宝后台
- 支付宝后台将生成的订单信息返回给商家后台
- 根据返回的订单信息唤起支付宝app
- 用户支付
- -7 返回同步和异步支付结果,后端需要在异步中根据支付宝异步通知做逻辑处理。
不过我是没有写同步返回的,因为支付宝的支付结果是以异步通知为准。我直接根据返回的订单号使用支付宝的查询接口。
在支付宝官网申请账号和完成相关配置
/** 支付宝gatewayUrl */
public static String gatewayUrl = "https://openapi.alipay.com/gateway.do";
/** 商户应用id */
public static String appid = "2018120662461695";
/** RSA私钥,用于对商户请求报文加签 */
public static String appPrivateKey = "";
/** 支付宝RSA公钥,用于验签支付宝应答 */
public static String alipayPublicKey = "";
/** 签名类型 */
public static String signType = "RSA2";
/** 格式 */
public static String formate = "json";
/** 编码 */
public static String charset = "UTF-8";
/** 同步地址 */
public static String returnUrl = "";
/** 异步地址 */
public static String notifyUrl = "";
/** 最大查询次数 */
public static int maxQueryRetry = 5;
/** 查询间隔(毫秒) */
public static long queryDuration = 5000;
/** 最大撤销次数 */
public static int maxCancelRetry = 3;
/** 撤销间隔(毫秒) */
public static long cancelDuration = 3000;
以下为后台代码
请求支付宝后台,并返回订单字符串
public String toPay(AliPayOrderRequest request) {
try {
logger.info("用户支付宝支付信息" + new Gson().toJson(request));
//根据申请的配置,实例化AlipayClient
AlipayClient alipayClient =
new DefaultAlipayClient(
AlipayProperties.gatewayUrl,
AlipayProperties.appid,
AlipayProperties.appPrivateKey,
"json",
"UTF-8",
AlipayProperties.alipayPublicKey,
"RSA2");
//实例化具体API对应的request类,类名称和接口名称对应,当前调用接口名称:alipay.trade.app.pay
AlipayTradeAppPayRequest payRequest = new AlipayTradeAppPayRequest();
//SDK已经封装掉了公共参数,这里只需要传入业务参数。以下方法为sdk的model入参方式(model和biz_content同时存在的情况下取biz_content)。
AlipayTradeAppPayModel model = new AlipayTradeAppPayModel();
String productCode = "QUICK_MSECURITY_PAY ";
//商品订单号
String outTradeNo = OrderNumUtils.getOrderIdByUUId("2");
//创建订单实体
model.setOutTradeNo(outTradeNo);
model.setSubject("蛙吧-平台充值");
model.setTotalAmount(request.getWIDtotalAmount());
model.setBody("蛙吧-平台充值");
model.setTimeoutExpress("2m");
model.setProductCode(productCode);
// request.setReturnUrl(alipayProperties.getReturnUrl());
//异步地址
payRequest.setNotifyUrl(AlipayProperties.notifyUrl);
payRequest.setBizModel(model);
String orderStr = "";
//这里和普通的接口调用不同,使用的是sdkExecute
AlipayTradeAppPayResponse payResponse = alipayClient.sdkExecute(payRequest);
//获取返回的订单信息字符串
orderStr = payResponse.getBody();
System.out.println(orderStr);//就是orderString 可以直接给客户端请求,无需再做处理。
return orderStr ;
} catch (Exception e) {
}
return "";
}
执行到这里return 的 orderStr就是生成签名的结果,然后你把这个orderStr返给前端,让他们去唤起支付宝支付,接下来,需要写一个异步通知,回调
接下来就是根据异步请求地址,编写异步通知接口,来写业务逻辑
@ResponseBody
@RequestMapping(value = "/getAlipayNotify", produces = "application/json;charset=UTF-8", method = {
RequestMethod.GET, RequestMethod.POST})
public String getAlipayNotify (HttpServletRequest request){
System.out.println("进入异步通知接口");
Map<String, String> params = new HashMap<String, String>();
Map requestParams = request.getParameterMap();
for (Iterator iter = requestParams.keySet().iterator(); iter.hasNext(); ) {
String name = (String) iter.next();
String[] values = (String[]) requestParams.get(name);
String valueStr = "";
for (int i = 0; i < values.length; i++) {
valueStr = (i == values.length - 1) ? valueStr + values[i] : valueStr + values[i] + ",";
}
// 乱码解决,这段代码在出现乱码时使用。
// valueStr = new String(valueStr.getBytes("ISO-8859-1"), "utf-8");
params.put(name, valueStr);
}
// 切记alipaypublickey是支付宝的公钥,请去open.alipay.com对应应用下查看。
try {
boolean flag = AlipaySignature.rsaCheckV1(params,
AlipayProperties.alipayPublicKey,
"UTF-8",
"RSA2");
if (flag) {
if("TRADE_SUCCESS".equals(params.get("trade_status"))){
//这里写业务逻辑,操作数据库等操作
System.out.println("flag为true,验证成功");
return "success";//成功返给支付宝成功就行了,
}
}
} catch (Exception e) {
e.printStackTrace();
}
return "error";
}
//异步方法最终返回必须为"success"
还有一个根据订单号,请求支付宝后台的接口,如果根据异步接口判断业务逻辑,则不需要订单查询接口
/**
* 查询订单
* @param request
* @return
*/
public Boolean aliPayQuery(AliPayQueryRequest request) {
try {
logger.info("用户支付宝支付查询订单信息" + new Gson().toJson(request));
AlipayClient alipayClient = new DefaultAlipayClient(
AlipayProperties.gatewayUrl,
AlipayProperties.appid,
AlipayProperties.appPrivateKey,
"json",
"UTF-8",
AlipayProperties.alipayPublicKey,
"RSA2"); //获得初始化的AlipayClient
AlipayTradeQueryRequest alipayTradeQueryRequest = new AlipayTradeQueryRequest();
alipayTradeQueryRequest.setBizContent("{" +
"\"out_trade_no\":\""+request.getOutTradeNo()+"\"" +
"}");
AlipayTradeQueryResponse payResponse = alipayClient.execute(alipayTradeQueryRequest);//通过alipayClient调用API,获得对应的response类
Gson g = new Gson();
HashMap<String, Object> ret = g.fromJson(payResponse.getBody(), HashMap.class);
String stu = ret.get("alipay_trade_query_response").toString();
String ret1 = StringToMap(stu,1);
if(ret1.equals("Success")){
String ret2 = StringToMap(stu,2);
if(ret2!=null){
if(ret2.equals("TRADE_SUCCESS")){
return true;
}
}
}
//根据response中的结果继续业务逻辑处理
System.out.println("付款失败");
return flase;
} catch (Exception e) {
response.setReturnCode(WabeiResult.RERUENCODE_ERROR);
response.setReturnMsg(e.toString());
}
return response;
}
StringToMap代码:
public String StringToMap(String str,int i){
String[] strs = str.split(", ");
Map<String, String> m = new HashMap<String, String>();
for(String s:strs){
String[] ms = s.split("=");
m.put(ms[0], ms[1]);
}
String str2 = "";
if(i==1){
str2 = m.get("msg");
return str2;
}else{
str2 = m.get("trade_status");
return str2.substring(0, str2.length()-1);
}
根据查询订单来判断,比较繁琐