本文只介紹當面付(掃碼支付)和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 }
