SpringBoot中实现支付宝支付


本文只介绍当面付(扫码支付)APP支付

一. 接入准备

#这里分两种情况,正式环境和沙箱环境,本文使用沙箱环境

1.进入支付宝开放平台,创建应用

 

登录 支付宝开放平台,创建应用并提交审核,审核通过后会生成应用唯一标识 APPID,并且可以申请开通开放产品使用权限。通过 APPID 应用才能调用开放产品的接口能力。详情请参考 创建应用。

 

2.配置应用

 

应用创建完成后,系统会自动跳转到应用详情页面。您可以在 能力列表 中点击 添加能力 来添加 当面付 功能。详情请参见 添加应用功能。 添加需要的能力

 

3.开发设置

 

进入开发设置中完成接口加签方式、IP白名单、应用网关、接口内容加密方式开发信息设置。详情请参见 配置应用环境

 

 

 

  •  接口加签方式:必填。用于保障商户应用和支付宝交互的安全性,配置详情参见 接口加签方式配置说明
  • IP白名单:选填。用于保障用户资金安全,说明详情参见 IP 白名单接入指南

  • 应用网关:选填。用于接收支付宝异步通知消息,说明详情参见 应用网关

  • 接口内容加密方式:选填。用于加/解密 OpenAPI bizContent 报文内容及加/解密部分用户隐私信息,说明详情参见 接口内容加密方式

  • 授权回调地址:选填。第三方应用授权  用户信息授权 后回调地址。授权链接中配置的 redirect_uri 的值必须与此值保持一致 (如:https://www.alipay.com) ,用户成功授权后将在该 url 后携带授权码等信息并跳转至该页。当填入该地址时,系统会自动进行安全检测,详情请参考 安全检测

4.设置接口加签方式

 

支付宝开放平台的应用管理体系,使用了公私钥的机制,商户可通过设置接口加签方式为自身应用配置 公私钥/公私钥证书 来保障商户应用和支付宝交互的安全性。密钥的获取方式请参见 生成密钥

 

公钥证书与公钥的区别请参见 普通公钥与公钥证书区别

 

 

 

简单说一下公钥私钥

使用支付宝支付加密方式有两种:1. 公钥私钥  2. 证书

1. 可使用支付宝提供的开发助手生成证书,生成后,支付宝会提供给你三个证书,分别为:私钥证书、公钥证书、支付宝公钥证书,

   将生成的公钥证书配置到支付宝平台中,剩下的私钥证书和支付宝公钥留在本地使用

2. 同上使用支付宝开发助手生成密钥,将生成的公钥配置到支付宝,将支付宝公钥复制到本地。

密钥的作用:私钥签名,公钥验签;公钥加密,私钥解密;私钥是不能公开的。

为什么有两套密钥:开发者生成的私钥公钥、支付宝公钥-支付宝私钥;开发者需要签名,支付宝平台也需要签名。

 

其他步骤参照支付宝开放平台接入流程。

二. 编码阶段

1. 下载支付宝sdk

java使用maven引入即可

 

2.编码

封装配置类

 1 @Data
 2 @Configuration
 3 @ConfigurationProperties(prefix = "alipay")
 4 public class AliPayConfig implements Serializable {
 5 
 6     private static final long serialVersionUID = -4736760736935998953L;
 7 
 8     public AliPayConfig(){}
 9 
10     public AlipayClient build(){
11         if(this.alipayClient == null){
12             return new DefaultAlipayClient(this.getGatewayUrl(),
13                     this.getAppId(),
14                     this.getPrivateKey(),
15                     this.getFormat(),
16                     this.getCharset(),
17                     this.getAliPublicKey(),
18                     this.getSignType());
19         }
20         return this.alipayClient;
21     }
22 
23     /**
24      * 支付宝网关
25      */
26     private String gatewayUrl;
27 
28     /**
29      * 新版本
30      */
31     private String newGatewayUrl;
32 
33     /**
34      * AppId
35      */
36     private String appId;
37 
38     /**
39      * 应用私钥
40      */
41     private String privateKey;
42 
43     /**
44      *  请求使用的编码格式,如utf-8,gbk,gb2312等
45      */
46     private String charset;
47 
48     /**
49      * 仅支持JSON
50      */
51     private String format;
52 
53     /**
54      * 支付宝公钥
55      */
56     private String aliPublicKey;
57 
58     /**
59      * 加密方式 目前支持RSA2和RSA,推荐使用RSA2
60      */
61     private String signType;
62 
63     /**
64      * 回调地址
65      */
66     private String notifyUrl;
67 
68     /**
69      * ali 客户端
70      */
71     private AlipayClient alipayClient;
72 
73     /**
74      * 获取Config配置类
75      * @return Config
76      */
77     public Config getConfig(){
78         Config config = new Config();
79         config.protocol = "https";
80         config.gatewayHost = this.getNewGatewayUrl();
81         config.signType = this.getSignType();
82         config.appId = this.getAppId();
83         config.merchantPrivateKey = this.getPrivateKey();
84         config.alipayPublicKey = this.getAliPublicKey();
85         config.notifyUrl = this.getNotifyUrl();
86         return config;
87     }
88 }

老版支付宝sdk

 1 @Slf4j
 2 public class AliPayApi {
 3 
 4     /**
 5      * 统一收单线下交易预创建 (老版本sdk)
 6      * 扫码支付
 7      * @param model
 8      * @param aliPayConfig
 9      * @return
10      */
11     public static AlipayTradePrecreateResponse tradePayToScanCode(AlipayTradePrecreateModel model, AliPayConfig aliPayConfig){
12         log.info("扫码支付:"+model.getOutTradeNo());
13         // 1.实例化API对应的request类
14         AlipayTradePrecreateRequest request = new AlipayTradePrecreateRequest();
15         request.setBizModel(model);
16         // 2.发起请求
17         AlipayTradePrecreateResponse response = null;
18         try {
19             response = aliPayConfig.getAlipayClient().execute(request);
20             // 3.是否调用成功
21             if(response.isSuccess()){
22                 log.info("扫码支付调用成功:" + response.getBody());
23                 return response;
24             }
25         } catch (AlipayApiException e) {
26             log.info("扫码支付调用失败:" + e.getErrMsg());
27             throw new RuntimeException(e);
28         }
29         log.debug("扫码支付调用失败:" + response.getMsg());
30         return null;
31     }
32 }

新版支付宝sdk

 1 /**
 2  * 支付宝支付 新版sdk
 3  * Create by Echo<php637.com> on 2021/1/22 0022
 4  */
 5 @Slf4j
 6 public class AliPayNewApi {
 7 
 8     /**
 9      * 统一收单线下交易预创建
10      * 扫码支付
11      * @param model
12      * @param aliPayProperties
13      * @return
14      */
15     public static AlipayTradePrecreateResponse tradePayToScanCode(AlipayTradePrecreateModel model, AliPayConfig aliPayProperties){
16         log.info("扫码支付:" + model.getOutTradeNo());
17         // 1. 设置参数
18         Factory.setOptions(aliPayProperties.getConfig());
19         AlipayTradePrecreateResponse response = null;
20         try{
21             // 2. 发起Api调用
22             response = Factory.Payment.FaceToFace().preCreate(model.getSubject(), model.getOutTradeNo(), model.getTotalAmount());
23             dumpResponse(response);
24             // 3. 处理响应
25             if(ResponseChecker.success(response)){
26                 log.info("扫码支付调用成功:" + response.getHttpBody());
27                 return response;
28             }
29         } catch (Exception e) {
30             log.debug("扫码支付调用异常:" + e.getMessage());
31             throw new RuntimeException(e);
32         }
33         log.debug("扫码支付调用失败:" + response.getMsg());
34         return null;
35     }
36 
37     /**
38      * App支付
39      * @param model
40      * @param aliPayConfig
41      * @return
42      */
43     public static AlipayTradeAppPayResponse tradePayToApp(AlipayTradeAppPayModel model, AliPayConfig aliPayConfig){
44         log.info("支付宝app支付:" + model.getOutTradeNo());
45         // 1. 设置参数
46         Factory.setOptions(aliPayConfig.getConfig());
47         AlipayTradeAppPayResponse response = null;
48         try{
49             // 2. 发起Api调用
50             response = Factory.Payment.App().pay(model.getSubject(), model.getOutTradeNo(), model.getTotalAmount());
51             // 3. 处理响应
52             if (ResponseChecker.success(response)){
53                 return response;
54             }
55         } catch (Exception e) {
56             log.debug("支付宝app支付调用异常:" + e.getMessage());
57             throw new RuntimeException(e);
58         }
59         log.debug("支付宝app支付调用失败:" + response.getBody());
60         return null;
61     }
62 
63     // 简单打印应答
64     private static void dumpResponse(AlipayTradePrecreateResponse response) {
65         if (response != null) {
66             log.info(String.format("code:%s, msg:%s", response.getCode(), response.getMsg()));
67             if (StringUtils.isNotEmpty(response.getSubCode())) {
68                 log.info(String.format("subCode:%s, subMsg:%s", response.getSubCode(),
69                         response.getSubMsg()));
70             }
71             log.info("body:" + response.getHttpBody());
72         }
73     }
74 }

测试和回调

 1     @Autowired
 2     private AliPayConfig aliPayProperties;
 3 
 4     @Autowired
 5     private SmsUtils smsUtils;
 6 
 7     /**
 8      * 扫码支付测试  老版本
 9      * @return
10      */
11     @RequestMapping("/test1")
12     public Object test1(){
13         AlipayTradePrecreateModel model = new AlipayTradePrecreateModel();
14         model.setOutTradeNo("123456789");
15         model.setSubject("测试商品");
16         model.setTotalAmount("20");
17         System.out.println(AliPayApi.tradePayToScanCode(model, aliPayProperties));
18         return new Return().success();
19     }
20 
21     /**
22      * 扫码支付测试  新版本
23      * @return
24      */
25     @RequestMapping("/test2")
26     public Object test2(){
27         AlipayTradePrecreateModel model = new AlipayTradePrecreateModel();
28         model.setOutTradeNo("12341234");
29         model.setSubject("新版支付");
30         model.setTotalAmount("10");
31         System.out.println(AliPayNewApi.tradePayToScanCode(model, aliPayProperties));
32         return new Return().success();
33     }
34 
35     /**
36      * app支付测试  新版本
37      * @return
38      */
39     @RequestMapping("/test3")
40     public Object test3(){
41         AlipayTradeAppPayModel model = new AlipayTradeAppPayModel();
42         model.setOutTradeNo("123412314");
43         model.setSubject("新版app支付");
44         model.setTotalAmount("10");
45         return new Return().success(AliPayNewApi.tradePayToApp(model, aliPayProperties));
46     }
47 
48     /**
49      * 回调
50      * @param request
51      * @return
52      */
53     @RequestMapping("/notify")
54     public Object alinNotify(HttpServletRequest request){
55         // 1.获取回调参数
56         Map<String, String> params = new HashMap<>();
57         Map requestParams = request.getParameterMap();
58         for (Iterator iterable = requestParams.keySet().iterator(); iterable.hasNext();){
59             String name = (String) iterable.next();
60             String[] values = (String[]) requestParams.get(name);
61             StringBuffer valueStr = new StringBuffer();
62             for (int i = 0; i < values.length; i++){
63                 if(i == values.length - 1){
64                     valueStr.append(values[i]);
65                 }else{
66                     valueStr.append(values[i]);
67                     valueStr.append(",");
68                 }
69                 params.put(name, valueStr.toString());
70             }
71         }
72         log.info("支付宝回调,sign:{},trade_status:{},参数:{}",params.get("sign"),params.get("trade_status"),params.toString());
73         // 2.验签
74         params.remove("sign");
75         params.remove("sign_type");
76         try {
77             boolean checkRes = AlipaySignature.rsaCheckV1(params, aliPayProperties.getAliPublicKey(), aliPayProperties.getCharset(), aliPayProperties.getSignType());
78             if (!checkRes){
79                 return new Return().failed("非法请求,验证失败");
80             }
81         } catch (AlipayApiException e) {
82             log.debug("支付宝验签异常:{}", e.getErrMsg());
83         }
84         // 3.服务端订单参数验证及其他逻辑
85         // TODO
86         return "SUCCESS";
87     }

 

 

 

 

 


免责声明!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系本站邮箱yoyou2525@163.com删除。



 
粤ICP备18138465号  © 2018-2025 CODEPRJ.COM