支付宝网页支付对接
程序员文章站
2022-06-26 14:13:52
支付宝支付联调本篇文章主要是针对支付宝官网的接口文档,进行说明,虽说文档很详细,也也有图例分析,也有代码示例,但这里还是按照MVC架构分析一下流程如下预支付获取商品信息获取二维码图片用户扫码,确认支付商家查看支付详情库存充足,缓存没问题的情况下,直接获取支付结果用户支付成功,交易成功用户支付失败,交易取消库存不足的情况下有缓存限制,预先锁定商品用户支付成功,交易成功用户支付失败,交易取消未做锁定商品直接取消交易(用户支付成功,退款;支付失败取消交易)...
支付宝支付联调
本篇文章主要是针对支付宝官网的接口文档,进行说明,虽说文档很详细,也也有图例分析,也有代码示例,但这里还是按照MVC架构分析一下
流程如下
- 预支付
- 获取商品信息
- 获取二维码图片
- 用户扫码,确认支付
- 商家查看支付详情
- 库存充足,缓存没问题的情况下,直接获取支付结果
- 用户支付成功,交易成功
- 用户支付失败,交易取消
- 库存不足的情况下
- 有缓存限制,预先锁定商品
- 用户支付成功,交易成功
- 用户支付失败,交易取消
- 未做锁定商品
- 直接取消交易(用户支付成功,退款;支付失败取消交易)
- 有缓存限制,预先锁定商品
- 库存充足,缓存没问题的情况下,直接获取支付结果
- 退款
- 银行卡支付
- 其他渠道支付
- 部分退款(幂等性)
- 全额退款
- 对账
- 账单打印
其实,以上也就是常规的一些交易流程了,但是需要针对具体的业务进行具体的分析,例如高并发的缓存以及消息队列使用。以及常规情况下的网络延迟等问题都是需要考虑的,若仅仅作为测试使用,可以不需要考虑
整体流程
前置工作
建议用户准备自己的沙箱环境,进行测试
沙箱环境流程
沙箱App准备
因为使用的是沙箱环境,所以只能使用沙箱钱包进行扫码支付
有可能出现的问题:如果不用沙箱钱包支付,有可能导致二维码超时
配置类(静态)
public class AlipayConfig {
// 商户appid
public static String APPID = "";
// 私钥 pkcs8格式的
public static String RSA_PRIVATE_KEY = "";
// 服务器异步通知页面路径 需http://或者https://格式的完整路径,不能加?id=123这类自定义参数,必须外网可以正常访问
public static String notify_url = "http://https://openapi.alipaydev.com/gateway.do/alipay.trade.wap.pay-JAVA-UTF-8/notify_url.jsp";
// 页面跳转同步通知页面路径 需http://或者https://格式的完整路径,不能加?id=123这类自定义参数,必须外网可以正常访问 商户可以自定义同步跳转地址
public static String return_url = "http://https://openapi.alipaydev.com/gateway.do/alipay.trade.wap.pay-JAVA-UTF-8/return_url.jsp";
// 请求网关地址
public static String URL = "";
// 编码
public static String CHARSET = "UTF-8";
// 返回格式
public static String FORMAT = "json";
// 支付宝公钥
public static String ALIPAY_PUBLIC_KEY = "";
// 日志记录目录
public static String log_path = "/log";
// RSA2
public static String SIGNTYPE = "RSA2";
}
预支付
代码(AlipayTradePrecreateRequest)
@PostMapping("/payPer")
public void payPer(String WIDout_trade_no, String WIDsubject, String WIDtotal_amount, String WIDbody, HttpServletResponse response) throws AlipayApiException {
AlipayClient client = new DefaultAlipayClient(AlipayConfig.URL, AlipayConfig.APPID, AlipayConfig.RSA_PRIVATE_KEY, AlipayConfig.FORMAT, AlipayConfig.CHARSET, AlipayConfig.ALIPAY_PUBLIC_KEY,AlipayConfig.SIGNTYPE);
AlipayTradePrecreateRequest alipay_request=new AlipayTradePrecreateRequest ();
// 封装请求支付信息
alipay_request . setBizContent ( "{" +
"\"out_trade_no\":\""+WIDout_trade_no+"\"," + //商户订单号
"\"total_amount\":\""+WIDtotal_amount+"\"," +
"\"subject\":\""+WIDsubject+"\"," +
"\"store_id\":\""+WIDbody+"\"," +
"\"timeout_express\":\"9000s\"}" );
AlipayTradePrecreateResponse response1 = client.execute (alipay_request);
List list= Arrays.asList(response1.getBody().split("\"qr_code\":"));
String[] list1= list.get(1).toString().split("},\"sign\"");
String a=list1[0].replace("\\","").replace("\"","");
QrConfig config = new QrConfig(180, 180);
// 设置边距,既二维码和背景之间的边距
config.setMargin(3);
// 高纠错级别
config.setErrorCorrection(ErrorCorrectionLevel.H);
//二维码内容
BufferedImage bufferedImage = QrCodeUtil.generate(
a,
config
);
try {
// 以JPEG格式向客户端发送
ServletOutputStream os = response.getOutputStream();
ImageIO.write(bufferedImage, "PNG", os);
os.flush();
os.close();
} catch (IOException e) {
e.printStackTrace();
}
System.out.println(WIDout_trade_no);
}
以上代码包含了一个二维码转换的工具类“Hutool”,工具类支持二维码定义中心logo
同时这里,并没有去解析JSON格式,仅仅作为测试使用,直接获取字符串分割
入参
- out_trade_no:商户订单号,需要保证商家系统不重复。
- total_amount:订单金额。
- subject:商品的标题/交易标题/订单标题/订单关键字等。不可使用特殊字符,如 /,=,& 等。
- store_id:商户门店编号。
- timeout_express:交易超时时间。
出参
- qr_code:订单二维码(有效时间 2 小时)以字符串的格式返回,开发者需要自己使用工具根据内容生成二维码图片。
查询交易
代码(AlipayTradeQueryRequest)
@GetMapping("/queryPay")
public void queryPay(String WIDout_trade_no) throws AlipayApiException {
AlipayClient client = new DefaultAlipayClient(AlipayConfig.URL, AlipayConfig.APPID, AlipayConfig.RSA_PRIVATE_KEY, AlipayConfig.FORMAT, AlipayConfig.CHARSET, AlipayConfig.ALIPAY_PUBLIC_KEY, AlipayConfig.SIGNTYPE);
AlipayTradeQueryRequest alipay_request = new AlipayTradeQueryRequest();
alipay_request.setBizContent("{" +
"\"out_trade_no\":\"2020123111227522\"}"); //设置业务参数
AlipayTradeQueryResponse response = client.execute(alipay_request);//通过alipayClient调用API,获得对应的response类
System.out.print(response.getBody());
}
这里的做法,建议前端轮询请求,当然,也可以放入消息队列,然后后台做监听处理,根据具体业务来看吧
不是高并发的情况,建议轮询,以做到用户体验最好
入参
- out_trade_no:支付时传入的商户订单号,与 trade_no 必填一个
- trade_no:支付时返回的支付宝交易号,与out_trade_no 必填一个。
返回
- code=10000,支付成功,流程结束
- code=10003,等待用户付款
- code=20000,网络超时,系统异常(根据需求,撤销交易或者继续等待)
撤销交易
代码(AlipayTradeCancelRequest )
@GetMapping("/refundPay")
public void refundPay(String WIDout_trade_no) throws AlipayApiException {
AlipayClient client = new DefaultAlipayClient(AlipayConfig.URL, AlipayConfig.APPID, AlipayConfig.RSA_PRIVATE_KEY, AlipayConfig.FORMAT, AlipayConfig.CHARSET, AlipayConfig.ALIPAY_PUBLIC_KEY, AlipayConfig.SIGNTYPE);
AlipayTradeCancelRequest alipay_request = new AlipayTradeCancelRequest ();
alipay_request.setBizContent("{" +
"\"out_trade_no\":\"20201231122418603\"}"); //设置业务参数
AlipayTradeCancelResponse response = client.execute(alipay_request);//通过alipayClient调用API,获得对应的response类
System.out.print(response.getBody());
}
说明
- 如果此订单用户支付失败,支付宝将关闭此订单。
- 如果此订单用户支付成功,支付宝将退还订单资金给用户。
- 仅发生支付系统超时或者支付结果未知时可调用本接口撤销交易,其他正常支付的单如需实现相同功能请调用alipay.trade.refund(统一收单交易退款接口)。
入参
- out_trade_no:支付时传入的商户订单号,与 trade_no 必填一个。
- trade_no:支付时返回的支付宝交易号,与out_trade_no 必填一个。
出参
- retry_flag:是否需要重试,Y/N。
- action:本次撤销触发的交易动作。
- close:关闭交易,无退款 。
- refund:产生了退款。
退款
流程图
代码(AlipayTradeRefundRequest)
AlipayClient client = new DefaultAlipayClient(AlipayConfig.URL, AlipayConfig.APPID, AlipayConfig.RSA_PRIVATE_KEY, AlipayConfig.FORMAT, AlipayConfig.CHARSET, AlipayConfig.ALIPAY_PUBLIC_KEY, AlipayConfig.SIGNTYPE);
AlipayTradeRefundRequest alipay_request = new AlipayTradeRefundRequest();
alipay_request.setBizContent("{" +
"\"out_trade_no\":\"20201231122418603\"," +
"\"out_request_no\":\"1000002\"," +
"\"refund_amount\":\"5\"}"); //设置业务参数
AlipayTradeRefundResponse response = client.execute(alipay_request);//通过alipayClient调用API,获得对应的response类
System.out.print(response.getBody());
}
说明
- 退款的途径按照支付途径原路返回。
- 支付渠道为花呗、余额等退款即时到账。
- 银行卡的退款时间以银行退款时间为准,一般情况下 2 小时内可到账。
- 开发者也可以在 商家中心 中退款。
- 退款是否成功可以根据同步响应的 fund_change 参数来判断,返回值为 Y 则表示退款成功。
- 退款接口会根据外部请求号 out_request_no 幂等返回,因此同一笔交易需要多次部分退款时,必须使用不同的 out_request_no。
入参
- out_trade_no:支付时传入的商户订单号,与trade_no必填一个
- trade_no:支付时返回的支付宝交易号,与out_trade_no必填一个
- out_request_no:本次退款请求流水号,部分退款时必传
- refund_amount:本次退款金额。
出参
- refund_fee:该笔交易已退款的总金额。
退款到银行卡
由于沙箱不支持银行卡操作,所以未进行测试
对账
流程图
代码
@GetMapping("/dataDataservice")
public void dataDataservice() throws AlipayApiException {
AlipayClient client = new DefaultAlipayClient(AlipayConfig.URL, AlipayConfig.APPID, AlipayConfig.RSA_PRIVATE_KEY, AlipayConfig.FORMAT, AlipayConfig.CHARSET, AlipayConfig.ALIPAY_PUBLIC_KEY, AlipayConfig.SIGNTYPE);
AlipayDataDataserviceBillDownloadurlQueryRequest alipay_request = new AlipayDataDataserviceBillDownloadurlQueryRequest ();
alipay_request.setBizContent("{" +
"\"bill_type\":\"trade\"," +
"\"bill_date\":\"2016-04-05\"}"); //设置业务参数
AlipayDataDataserviceBillDownloadurlQueryResponse response = client.execute(alipay_request);//通过alipayClient调用API,获得对应的response类
System.out.print(response.getBody());
}
入参
- bill_type:固定传入 trade。
- bill_date:需要下载的账单日期,最晚是当期日期的前一天。
出参
- bill_download_url:账单文件下载地址,有效时长:30 秒。
说明
下载账单,根据各自喜欢工具类可进行封装,这里不在提供,或者可以直接参考支付宝官网
以上就是支付宝支付接口对接了,后续会继续分享支付宝登录、QQ登录等案例
本文地址:https://blog.csdn.net/qq_37871033/article/details/112008914