对接支付宝App支付接口详解

前言

因工作需要,这几天摸索了很久,网上查找的资料大多不齐全,不详细,只有部分讲解及代码…所有我准备尽可能的把这篇博客写的详细易懂一些…好了..废话不多说..下面开始!!!

1.集成支付宝app支付,首先去申请一个支付宝账户..
open.alipay.com/platform/ma…
申请完了以后登录 再这里可以看到一个沙箱 看下图

image.png
点击进去

image.png

到这里我们在沙箱环境下的网页工作差不多就做完了…接下来就应该下载ali支付的jar包了..

下载地址:docs.open.alipay.com/54/106370/

下载完成后,添加到你的maven仓库中,如果项目是maven项目,还需要在pom文件中添加

image.png
2.我们需要先看一些支付宝的一些文档.

app支付官方文档地址:docs.open.alipay.com/204

1、参数说明

(1)out_trade_no:商户订单号,由商户自定义设置;

(2)subject:商品标题;

(3)product_code:固定产品码值:QUICK_MSECURITY_PAY;

(4)total_amount:交易订单金额,精确到小数点后2位,最小设置为0.01;

2、接口请求示例

沙箱账号查看地址:openhome.alipay.com/platform/ap…

① controller层

1
2
3
4
5
6
7
8
9
10
11
12
less复制代码/**
* 充值
* @param payDto payDto
* @return R
*/
@PostMapping(value = "/charge")
public R charge(@RequestBody PayDto payDto){
//payDto就是你前端传过来的值,比如充值金额是多少 用户id是多少..
//这个实体类根据你们自己的业务需求去写就好
String orderString = aliPayService.order(payDto);
return R.ok("orderString",orderString);
}

② service层

1
2
3
4
5
6
vbnet复制代码/**
* 支付宝下单
* @param payDto payDto
* @return String
*/
String order(PayDto payDto);

③serviceImpl

重点 重点 重点 重点 重点 重点 重点 请各位仔细阅读这里的每一行代码

首先这里我们先新建一个AlipayConfig实体类代码我贴出来.有些东西需要你们自己修改我会在代码上方注释的..仔细看…

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
arduino复制代码package com.wenliao.cloud.config;

/**
* @ClassName: AliPayConfig
* @Description: 需要传给支付宝SDK的公共基本参数
* @author: Linn
* @Date: 2019/4/3 9:22
*/
public class AliDevPayConfig {

/**
* 1.商户appid
*/
public String APPID = "这个就是在沙箱环境下你看到你的appId的那一串数字";

/**
* 私钥 pkcs8格式的
*/
public static String RSA_PRIVATE_KEY ="这个就是我上面说的应用私钥生成 注意这里是私钥";

/**
* 3.支付宝公钥
*/
public static String ALIPAY_PUBLIC_KEY = "这个就是你把生成的应用公钥在沙箱网页哪里输入后,就可以查看到支付宝公钥..把看到的支付宝公钥copy过来放这里就ok";

/**
* 4.服务器异步通知页面路径 需http://或者https://格式的完整路径,不能加?id=123这类自定义参数,必须外网可以正常访问
*/
//这个着重讲一下..支付完成后,支付宝会通过这个url请求到你的服务端..
//这个url一定是要公网可以访问才行...如果需要测试的话..我后面有讲到..
//这里你可以先写你本地项目的url 例如:localhost:8080/项目名/访问路径
public static String notify_url = "http://2hu4349021.wicp.vip/pay/aliNotify";

/**
* 5.页面跳转同步通知页面路径 需http://或者https://格式的完整路径,不能加?id=123这类自定义参数,必须外网可以正常访问 商户可以自定义同步跳转地址
*/
//这里同上..不做详细说明了..
public static String return_url = "http://2hu4349021.wicp.vip/pay/returnUrl";

/**
* 正式环境支付宝网关,如果是沙箱环境需更改成https://openapi.alipaydev.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";

上面的代码我写了一些注释..希望大家好好看一下..特别是一些刚刚接触支付宝对接的人..有很大帮助的

接下来我们就是在impl中实现了..

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
scss复制代码    @Override
public String order(PayDto payDto) {
//这里你可以做一些存表操作..具体根据你们自己的业务来操作...
String orderString = "";//这个字符串是用来返回给前端的
String orderNo = record.getOrderId();//这行代码是生成一个商户的订单号..根据你们自己的业务需求去生成就可以了..
log.info("==================支付宝下单,商户订单号为:" + orderNo);

try {
AliDevPayConfig aliDevPayConfig= new AliDevPayConfig(); //实例化上面的那个配置类..
//实例化客户端(参数:网关地址、商户appid、商户私钥、格式、编码、支付宝公钥、加密类型),为了取得预付订单信息
AlipayClient alipayClient = new DefaultAlipayClient(AliDevPayConfig.URL, aliDevPayConfig.getAPPID(),
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("具体描述信息.例如QQ币充值");
//商品名称
model.setSubject("例:QQ币");
//商户订单号(根据业务需求自己生成)
model.setOutTradeNo(orderNo);
//交易超时时间 这里的30m就是30分钟
model.setTimeoutExpress("30m");
//支付金额 后面保留2位小数点..不能超过2位
model.setTotalAmount(10.00);
//销售产品码(固定值) //这个不做多解释..看文档api接口参数解释
model.setProductCode("QUICK_MSECURITY_PAY");
ali_request.setBizModel(model);
//异步回调地址(后台)//这里我在上面的aliPayConfig有讲..自己去看
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;
}

好..到这里就拿到了一个orderString返回给前端..

返回信息:

1
perl复制代码alipay_sdk=alipay-sdk-java-dynamicVersionNo&app_id=2016101800718925&biz_content=%7B%22out_trade_no%22%3A%22201809251015343222843%22%2C%22total_amount%22%3A%220.01%22%2C%22subject%22%3A%22app%E6%94%AF%E4%BB%98%E6%B5%8B%E8%AF%95%22%2C%22passback_params%22%3A%22%25E5%2585%25AC%25E7%2594%25A8%25E5%259B%259E%25E4%25BC%25A0%25E5%258F%2582%25E6%2595%25B0%25E6%25B5%258B%25E8%25AF%259512334%25EF%25BC%2581%22%2C%22product_code%22%3A%22QUICK_MSECURITY_PAY%22%7D&charset=utf-8&format=JSON&method=alipay.trade.app.pay&notify_url=http%3A%2F%2F106.14.187.178%2Fopendevtools%2Fnotify%2Fdo%2Fa9bed896-0fc0-4b05-ba55-6a2550cacd36&return_url=https%3A%2F%2Fwww.baidu.com%2F&sign=qiOEfMcQoObzuPdZNkMOzavHfJLskTUWJxb08YObj8D0SexDStOw%2BHEwOs7x1hGih8Zs3rsT%2BA3aYVnmwp0FTnTYHx2cTbvz1tkNTzoguOG%2BdNR4b5dsJ%2BvUU4UbHV2KDOxg%2FASUcjcbhqitYraWjBgL02QWgTa%2FpA7dpZnxaOKyksZ1tvp7dR3zYvfDdVnfo3vpXlJxc8QTXsYvZdpODvmKG9odw%2FTsP2fZdt3Up7aiq7Ae8rby%2FNg%2BIMcGJjH%2F5MnUC99%2FU9%2Bjwt%2Biqt7jwU4PVfGimDY6ifIYs3PosGwfwrMTSZkI8AzdcsmwHRcqGJJNzlzegl9jQHw9mBzSAw%3D%3D&sign_type=RSA2&timestamp=2018-09-25+13%3A09%3A52&version=1.0

客户端调试工具

前端调用支付宝接口进行支付….这里提供一个支付宝的测试App

测试服务端生成的请求参数是否正常,可使用客户端调试工具。

客户端调试工具:openclub.alipay.com/read.php?ti…

显示效果

image.png
注意:未输入密码之前,支付宝订单还是为创建状态,只有输入密码之后,才会生成支付宝订单,所以这个时候用查询接口查询会报错“订单不存在”

到这里支付成功后,支付宝那边会有一个同步返回和异步返回接口

这个同步我暂时还没有弄太明白…同步也只是告诉你,这个订单有没有支付…并不代表支付成功..支付成功还是得看异步通知返回…

controller层

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
ini复制代码    /**
* 支付宝支付成功后.异步请求该接口
* @param request
* @return
* @throws IOException
*/
@RequestMapping(value="/aliNotify",method= RequestMethod.POST)
@ResponseBody
public String aliNotify(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);
}
System.out.println("==返回参数集合:"+conversionParams);
String status=aliPayService.aliNotify(conversionParams);
return status;
}

service层

1
2
3
4
5
6
javascript复制代码    /**
* 支付宝异步回调
* @param conversionParams conversionParams
* @return String
*/
String aliNotify( Map<String, String> conversionParams);

serviceImpl层

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
typescript复制代码/**
* 支付宝异步请求逻辑处理
*
* @param
* @return
* @throws IOException
*/
@Override
public String aliNotify(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);
//对验签进行处理.
if (signVerified) {
log.info("+支付宝回调签名认证成功+");
// 按照支付结果异步通知中的描述,对支付结果中的业务内容进行1\2\3\4二次校验,校验成功后在response中返回success,校验失败返回failure 支付宝官方建议校验的值(out_trade_no、total_amount、sellerId、app_id)
this.check(conversionParams);
//验签通过 获取交易状态
String tradeStatus = conversionParams.get("trade_status");

//只处理支付成功的订单: 修改交易表状态,支付成功
//只有交易通知状态为TRADE_SUCCESS或TRADE_FINISHED时,支付宝才会认定为买家付款成功。
if (tradeStatus.equals("TRADE_SUCCESS") ||tradeStatus.equals("TRADE_FINISHED")) {
//TODO 获取支付宝通知完成充值后续业务
//交易成功 获取商户订单号

/**修改订单信息*/

/**余额到账*/
//这里就主要是做你们自己的业务需求了,修改一些表什么的..
}
return "success";
} else {
return "fail";
}
} else{ //验签不通过
log.info("++验签不通过 !++");
return "fail";
}
} catch (AlipayApiException e) {
log.info("+++验签失败 !+++");
e.printStackTrace();
}
return "fail";
}

到这里一整个支付就完了……多注意细节就ok…

如果大家有什么疑问,可以在评论区评论.我看到后会及时回复…有不对的地方请指出..我会及时修改.谢谢~

总结:

1
复制代码遇到新需求和新技术,多看官方文档...基本都能解决问题

另外目前在努力筹备自己的开源博客中,寻一位前端工程师共同完成…谢谢~

本文转载自: 掘金

开发者博客 – 和开发相关的 这里全都有

0%