APP接入支付宝支付对接流程
此文为服务端部分,仅适用于前后端分离开发
一、首先在官方接口文档中添加对应的配置,下载地址: https://opendocs.alipay.com/open/54/106370/
如果是maven项目可以直接在pom文件中添加如下依赖即可:
<!--支付宝sdk-->
<dependency>
<groupId>com.alipay.sdk</groupId>
<artifactId>alipay-sdk-java</artifactId>
<version>3.0.0</version>
</dependency>
二、打开支付宝开放平台,找到沙箱完成里面的各项配置(应用公钥、支付宝公钥、应用私钥)
注意: 先不要纠结沙箱跟真实环境,不过是一个几个变量配置的问题,下面会提到。整体流程相同沙箱不过是方便联调测试其他无差
控制台首页:
沙箱环境:
授权回调地址为后台接收支付信息异步通知的url,需要外部可访问地址。建议在网关中添加白名单
三、添加AliPay支付配置类,AliDevPayConfig
真实环境中把下面的工具类中的参数换成真实环境的即可,其他不做改变
获取方法,以及申请商户信息参考支付宝开发文档:https://opendocs.alipay.com/open/204/105297?ref=api
package com.sports.user.config;
/**
* @ClassName: AliPayConfig
* @Description: 需要传给支付宝SDK的公共基本参数
*/
public class AliDevPayConfig {
/**
* 1.商户appid
*/
public String APPID = "";
/**
* 私钥 pkcs8格式的
*/
public static String RSA_PRIVATE_KEY ="";
/**
* 3.支付宝公钥
*/
public static String ALIPAY_PUBLIC_KEY = "";
/**
* 4.服务器异步通知页面路径 需http://或者https://格式的完整路径,不能加?id=123这类自定义参数,必须外网可以正常访问
*/
public static String notify_url = "";
/**
* 5.页面跳转同步通知页面路径 需http://或者https://格式的完整路径,不能加?id=123这类自定义参数,必须外网可以正常访问 商户可以自定义同步跳转地址
*/
public static String return_url = "";
/**
* 正式环境支付宝网关,如果是生产环境需更改成https://openapi.alipay.com/gateway.do
*/
public static String URL = "https://openapi.alipaydev.com/gateway.do";
/**
* 7.编码
*/
public static String CHARSET = "UTF-8";
/**
* 私钥 pkcs8格式的
*/
// 8.返回格式
public static String FORMAT = "json";
/**
* //签名方式 加密类型
*/
public static String SIGNTYPE = "RSA2";
}
四、编写后端代码,controller、service、serviceImpl(前端请求调起支付时)
controller中:生成字符串返回给前端去调用支付宝支付接口
String orderString = usrPayService.orderString(usrPayDO);
service中:
public String orderString(UsrPayDO usrPayDO);
serviceImpl中:
@Override
public String orderString(UsrPayDO usrPayDO) {
String orderString = "";//这个字符串是用来返回给前端的
log.info("==================支付宝下单,商户订单号为:" + usrPayDO.getId());
try {
AliDevPayConfig aliDevPayConfig = new AliDevPayConfig(); //实例化上面的那个配置类..
//实例化客户端(参数:网关地址、商户appid、商户私钥、格式、编码、支付宝公钥、加密类型),为了取得预付订单信息
AlipayClient alipayClient = new DefaultAlipayClient(AliDevPayConfig.URL, aliDevPayConfig.APPID,
AliDevPayConfig.RSA_PRIVATE_KEY, AliDevPayConfig.FORMAT, AliDevPayConfig.CHARSET,
AliDevPayConfig.ALIPAY_PUBLIC_KEY, AliDevPayConfig.SIGNTYPE);
//实例化具体API对应的request类,类名称和接口名称对应,当前调用接口名称:alipay.trade.app.pay
AlipayTradeAppPayRequest ali_request = new AlipayTradeAppPayRequest();
//SDK已经封装掉了公共参数,这里只需要传入业务参数。以下方法为sdk的model入参方式
AlipayTradeAppPayModel model = new AlipayTradeAppPayModel();
//业务参数传入,可以传很多,参考API
//model.setPassbackParams(URLEncoder.encode(request.getBody().toString())); //公用参数(附加数据)
//对一笔交易的具体描述信息。如果是多种商品,请将商品描述字符串累加传给body。
model.setBody(usrPayDO.getDescription());
//商品名称
model.setSubject(usrPayDO.getTag());
//商户订单号,己方生成且值唯一的订单号
model.setOutTradeNo(usrPayDO.getId());
//交易超时时间
model.setTimeoutExpress("30m");
//支付金额 小数点后不能超过2位
model.setTotalAmount(String.valueOf(usrPayDO.getPayAmt()));
//销售产品码(固定值)
model.setProductCode("QUICK_MSECURITY_PAY");
ali_request.setBizModel(model);
//异步回调地址(后台)
ali_request.setNotifyUrl(AliDevPayConfig.notify_url);
log.info("====================异步通知的地址为:" + ali_request.getNotifyUrl());
//同步回调地址(APP)
ali_request.setReturnUrl(AliDevPayConfig.return_url);
log.info("====================同步通知的地址为:" + ali_request.getReturnUrl());
// 这里和普通的接口调用不同,使用的是sdkExecute
//返回支付宝订单信息(预处理)
AlipayTradeAppPayResponse alipayTradeAppPayResponse = alipayClient.sdkExecute(ali_request);
//就是orderString 可以直接给APP请求,无需再做处理。
orderString = alipayTradeAppPayResponse.getBody();
System.out.println(orderString);
} catch (AlipayApiException e) {
e.printStackTrace();
log.info("与支付宝交互出错,未能生成订单!");
}
return orderString;
}
五、编写后端代码,controller、service、serviceImpl(支付宝异步通知支付结果时)
controller中:
/**
* 支付宝支付成功后.异步请求该接口
*
* @param request
* @return
*/
@ApiOperation("支付宝充值")
@RequestMapping(value = "/aliPay", method = RequestMethod.POST)
public @ResponseBody
String aliPay(HttpServletRequest request, HttpServletResponse response) throws IOException {
System.out.println("=支付宝异步返回支付结果开始");
//1.从支付宝回调的request域中取值
//获取支付宝返回的参数集合
Map<String, String[]> aliParams = request.getParameterMap();
//用以存放转化后的参数集合
Map<String, String> conversionParams = new HashMap<String, String>();
for (Iterator<String> iter = aliParams.keySet().iterator(); iter.hasNext(); ) {
String key = iter.next();
String[] values = aliParams.get(key);
String valueStr = "";
for (int i = 0; i < values.length; i++) {
valueStr = (i == values.length - 1) ? valueStr + values[i] : valueStr + values[i] + ",";
}
// 乱码解决,这段代码在出现乱码时使用。如果mysign和sign不相等也可以使用这段代码转化
//valueStr = new String(valueStr.getBytes("ISO-8859-1"), "UTF-8");
conversionParams.put(key, valueStr);
}
log.info("=============返回参数集合:{}", conversionParams);
String status = usrPayService.aliPay(conversionParams);
return status;
}
service中:
public String aliPay(Map<String, String> conversionParams);
serviceImpl中:
/**
* 验证支付宝返回通知
*
* @param conversionParams
* @return
*/
@Override
public String aliPay(Map<String, String> conversionParams) {
log.info("=支付宝异步请求逻辑处理=");
//签名验证(对支付宝返回的数据验证,确定是支付宝返回的)
boolean signVerified = false;
try {
//调用SDK验证签名
String alipayPublicKey = AliDevPayConfig.ALIPAY_PUBLIC_KEY;
String charset = AliDevPayConfig.CHARSET;
String signType = AliDevPayConfig.SIGNTYPE;
signVerified = AlipaySignature.rsaCheckV1(conversionParams, alipayPublicKey, charset, signType);
//首先对通知中的商家ID号进行本地验证
String getQxbOrderId = conversionParams.get("out_trade_no");
UsrPayDO usrPayDO = usrPayService.getById(getQxbOrderId);
//对验签进行处理.
if (signVerified != false && usrPayDO != null) {
log.info("支付宝回调签名认证成功--------------------");
//验签通过 获取交易状态
String tradeStatus = conversionParams.get("trade_status");
//只有交易通知状态为TRADE_SUCCESS或TRADE_FINISHED时,支付宝才会认定为买家付款成功。
if (tradeStatus.equals("TRADE_SUCCESS") || tradeStatus.equals("TRADE_FINISHED")) {
//此处可以进行一些本地的表操作,根据自己业务需求添加
log.info("验证成功,修改订单信息:{}-----------------", usrPayDO);
} else {
return "fail";
}
return "success";
} else {
return "fail";
}
} catch (AlipayApiException e) {
log.info("+++验签失败 !+++");
e.printStackTrace();
}
return "fail";
}
提示支付宝发送异步通知后,以接收返回结果为准,接收到反馈结果后,则支付宝方的验证凭证ID则会失效,否则会在25小时内发送8次异步通知;
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· DeepSeek 开源周回顾「GitHub 热点速览」
· 记一次.NET内存居高不下排查解决与启示
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· .NET10 - 预览版1新功能体验(一)