1. 程式人生 > >第三方對接-支付寶支付

第三方對接-支付寶支付

應用場景:

商戶出售商品,使用者購買支付,商戶接入第三方支付平臺支付寶

對接要求:

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、支付流程

    1. 發起一個支付請求(攜帶訂單號,價格等引數)到支付寶統一下單介面,生成預支付路徑,響應給客戶端瀏覽器。
    2. 使用者進行掃碼或者在頁面登入支付寶支付。
    3. 服務端非同步接收支付結果。

①:發起支付請求

@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