第三方對接-支付寶支付
阿新 • • 發佈:2019-01-03
應用場景:
商戶出售商品,使用者購買支付,商戶接入第三方支付平臺支付寶
對接要求:
1、先建立網頁&移動應用點選開啟連結,提交併且通過稽核後才能進行對接
2、開發者呼叫介面前需要先生成RSA2金鑰,RSA金鑰包含應用私鑰(APP_PRIVATE_KEY)、應用公鑰(APP_PUBLIC_KEY)。生成金鑰後在開放平臺管理中心進行金鑰配置,配置完成後可以獲取支付寶公鑰(ALIPAY_PUBLIC_KEY)
3、搭建和配置開發環境
下載服務端SDK:
<!-- https://mvnrepository.com/artifact/com.alipay.sdk/alipay-sdk-java --> <dependency> <groupId>com.alipay.sdk</groupId> <artifactId>alipay-sdk-java</artifactId> <version>3.0.0</version> </dependency>
對接流程:
1、封裝引數,申請接入支付寶支付,會有APPID,公鑰私鑰等引數。
2、支付流程
- 發起一個支付請求(攜帶訂單號,價格等引數)到支付寶統一下單介面,生成預支付路徑,響應給客戶端瀏覽器。
- 使用者進行掃碼或者在頁面登入支付寶支付。
- 服務端非同步接收支付結果。
①:發起支付請求
@RequestMapping("gotoPay") public void gotoPay(HttpServletRequest httpRequest,HttpServletResponse httpResponse) throws ServletException, IOException { AlipayClient alipayClient = new DefaultAlipayClient("https://openapi.alipay.com/gateway.do", APP_ID, APP_PRIVATE_KEY, FORMAT, CHARSET, ALIPAY_PUBLIC_KEY, SIGN_TYPE); //獲得初始化的AlipayClient AlipayTradePagePayRequest alipayRequest = new AlipayTradePagePayRequest();//建立API對應的request alipayRequest.setReturnUrl("http://domain.com/CallBack/returnURL.html");//回跳地址 alipayRequest.setNotifyUrl("http://domain.com/CallBack/notifyURL.html");//通知地址 alipayRequest.setBizContent("{" + " \"out_trade_no\":\"20150320010101001\"," + //訂單號(支付寶要求商戶訂單號必須唯一) " \"product_code\":\"FAST_INSTANT_TRADE_PAY\"," + //銷售產品碼,與支付寶簽約的產品碼名稱,目前僅支援FAST_INSTANT_TRADE_PAY。 " \"total_amount\":88.88," + //價格 " \"subject\":\"Iphone6 16G\"," + //訂單標題 " \"body\":\"Iphone6 16G\"," + //訂單描述 " \"passback_params\":\"merchantBizType%3d3C%26merchantBizNo%3d2016010101111\"," + //公用回傳引數,如果請求時傳遞了該引數,則返回給商戶時會回傳該引數。支付寶只會在非同步通知時將該引數原樣返回。本引數必須進行UrlEncode之後才可以傳送給支付寶 " \"extend_params\":{" + //業務擴充套件引數 " \"sys_service_provider_id\":\"2088511833207846\"" + //系統商編號,該引數作為系統商返傭資料提取的依據,請填寫系統商簽約協議的PID " }"+ " }");//填充業務引數 String form=""; try { form = alipayClient.pageExecute(alipayRequest).getBody(); //呼叫SDK生成表單 } catch (AlipayApiException e) { e.printStackTrace(); } httpResponse.setContentType("text/html;charset=" + CHARSET); httpResponse.getWriter().write(form);//直接將完整的表單html輸出到頁面 httpResponse.getWriter().flush(); httpResponse.getWriter().close(); }
②、使用者確認支付後,支付寶get請求returnUrl(將網頁重定向到何處)
@RequestMapping(value = "returnURL", method = RequestMethod.GET) public String returnURL(Device device) { System.out.println("支付寶處理完畢後返回商戶網站"); if (device.isNormal()) { return "shop/alipay/payResult"; } else { return "mobile/alipay/payResult"; } }
③、交易成功後,支付寶post請求notifyUrl
@RequestMapping(value = "notifyURL", method = RequestMethod.POST)
public void notifyURL(HttpServletRequest httpRequest){
//將非同步通知中收到的所有引數都存放到map中 ↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓
Map<String, String> paramsMap = MapUtil.map();
Map<String, String[]> requestParams = request.getParameterMap();
for (Object element : requestParams.keySet()) {
String name = (String) element;
String[] values = requestParams.get(name);
StringBuilder valueStr = new StringBuilder();
for (int i = 0; i < values.length; i++) {
valueStr.append((i == values.length - 1) ? values[i] : values[i] + ",");
}
params.put(name, valueStr.toString());
}
//將非同步通知中收到的所有引數都存放到map中 ↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑
boolean signVerified = AlipaySignature.rsaCheckV1(paramsMap, ALIPAY_PUBLIC_KEY, CHARSET, SIGN_TYPE) //呼叫SDK驗證簽名
if(signVerfied){
// TODO 驗籤成功後,按照支付結果非同步通知中的描述,對支付結果中的業務內容進行二次校驗,校驗成功後在response中返回success並繼續商戶自身業務處理,校驗失敗返回failure
}else{
// TODO 驗籤失敗則記錄異常日誌,並在response中返回failure.
}
}
④、若由於網路等問題非同步通知沒有到達,商戶可自行呼叫alipay.trade.query介面進行查詢,根據查詢介面獲取交易以及支付資訊(商戶也可以直接呼叫查詢介面,不需要依賴非同步通知)。
public void query(){
AlipayClient alipayClient = new DefaultAlipayClient("https://openapi.alipay.com/gateway.do","app_id","your private_key","json","GBK","alipay_public_key","RSA2");
AlipayTradeQueryRequest request = new AlipayTradeQueryRequest();
request.setBizContent("{" +
"\"out_trade_no\":\"20150320010101001\"," + //訂單支付時傳入的商戶訂單號,和支付寶交易號不能同時為空。
"\"trade_no\":\"2014112611001004680 073956707\"" + //支付寶交易號,和商戶訂單號不能同時為空
" }");
AlipayTradeQueryResponse response = alipayClient.execute(request);
if(response.isSuccess()){
//獲取支付資訊
System.out.println("呼叫成功");
} else {
System.out.println("呼叫失敗");
}
}
⑤、交易發生後一段時間內,如果使用者想退款,買家可以通過退款介面將支付款退給買家。
public void refund() throws AlipayApiException {
AlipayClient alipayClient = new DefaultAlipayClient("https://openapi.alipay.com/gateway.do","app_id","your private_key","json","GBK","alipay_public_key","RSA2");
AlipayTradeRefundRequest request = new AlipayTradeRefundRequest();
request.setBizContent("{" +
"\"out_trade_no\":\"20150320010101001\"," +
"\"trade_no\":\"2014112611001004680073956707\"," +
"\"refund_amount\":200.12," +
"\"refund_currency\":\"USD\"," +
"\"refund_reason\":\"正常退款\"," +
"\"out_request_no\":\"HZ01RF001\"," +
"\"operator_id\":\"OP001\"," +
"\"store_id\":\"NJ_S_001\"," +
"\"terminal_id\":\"NJ_T_001\"," +
" \"goods_detail\":[{" +
" \"goods_id\":\"apple-01\"," +
"\"alipay_goods_id\":\"20010001\"," +
"\"goods_name\":\"ipad\"," +
"\"quantity\":1," +
"\"price\":2000," +
"\"goods_category\":\"34543238\"," +
"\"body\":\"特價手機\"," +
"\"show_url\":\"http://www.alipay.com/xxx.jpg\"" +
" }]" +
" }");
AlipayTradeRefundResponse response = alipayClient.execute(request);
if(response.isSuccess()){
System.out.println("呼叫成功");
} else {
System.out.println("呼叫失敗");
}
}
⑥、統一收單交易退款查詢
public void queryRefund(){
AlipayClient alipayClient = new DefaultAlipayClient("https://openapi.alipay.com/gateway.do","app_id","your private_key","json","GBK","alipay_public_key","RSA2");
AlipayTradeFastpayRefundQueryRequest request = new AlipayTradeFastpayRefundQueryRequest();
request.setBizContent("{" +
"\"trade_no\":\"20150320010101001\"," +
"\"out_trade_no\":\"2014112611001004680073956707\"," +
"\"out_request_no\":\"2014112611001004680073956707\"" +
" }");
AlipayTradeFastpayRefundQueryResponse response = alipayClient.execute(request);
if(response.isSuccess()){
System.out.println("呼叫成功");
} else {
System.out.println("呼叫失敗");
}
}
⑦、統一收單交易關閉介面(用於交易建立後,使用者在一定時間內未進行支付,可呼叫該介面直接將未付款的交易進行關閉。)
public void tradeClose(){
AlipayClient alipayClient = new DefaultAlipayClient("https://openapi.alipay.com/gateway.do","app_id","your private_key","json","GBK","alipay_public_key","RSA2");
AlipayTradeRefundRequest request = new AlipayTradeRefundRequest();
request.setBizContent("{" +
"\"out_trade_no\":\"20150320010101001\"," +
"\"trade_no\":\"2014112611001004680073956707\"," +
"\"refund_amount\":200.12," +
"\"refund_currency\":\"USD\"," +
"\"refund_reason\":\"正常退款\"," +
"\"out_request_no\":\"HZ01RF001\"," +
"\"operator_id\":\"OP001\"," +
"\"store_id\":\"NJ_S_001\"," +
"\"terminal_id\":\"NJ_T_001\"," +
" \"goods_detail\":[{" +
" \"goods_id\":\"apple-01\"," +
"\"alipay_goods_id\":\"20010001\"," +
"\"goods_name\":\"ipad\"," +
"\"quantity\":1," +
"\"price\":2000," +
"\"goods_category\":\"34543238\"," +
"\"body\":\"特價手機\"," +
"\"show_url\":\"http://www.alipay.com/xxx.jpg\"" +
" }]" +
" }");
AlipayTradeRefundResponse response = alipayClient.execute(request);
if(response.isSuccess()){
System.out.println("呼叫成功");
} else {
System.out.println("呼叫失敗");
}
}
真心話,支付寶對接的API比微信寫的強太多了支付寶官方API