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