支付寶APP支付

1、基礎說明html

如今開發一個電商APP,最少不了的就是支付,目前最多見的支付有微信支付和支付寶支付,先來介紹支付寶APP支付,其實支付寶的文檔說明已經很清楚了,裏面有不少demo,你還能夠經過沙箱環境去調試支付。螞蟻金服開放平臺地址:https://open.alipay.com/developmentAccess/developmentAccess.htmjson

下面先貼出一張流程圖:api

 

第一步:用戶提交支付,APP去帶着訂單信息請求服務端服務器

第二步:服務端對訂單信息進行處理後去請求支付寶(這一步能夠設置異步回調和同步回調地址)獲取簽名後的訂單信息,個人理解就是預支付訂單信息,(支付寶不存在預付單,能夠理解爲預付單)微信

第三步:返回簽名後的訂單信息給APP客戶端cookie

第四步:APP客戶端攜帶預支付訂單信息喚起支付寶APP進行支付網絡

第五步:支付完成後,支付寶會同步回調和異步回調,其中異步回調是最重要的,也是回調到服務端的信息,同步回調由於客戶端APP和網絡的緣由,不是十分可靠。session

第六步:服務端接收到支付寶異步回調請求,根據請求信息去更新訂單信息app

第七步:APP客戶端經過支付寶交易查詢接口去查詢剛剛支付的訂單狀態異步

第八步:APP客戶端根據第七步的結果,處理相應的業務邏輯。例如交易成功顯示頁面A,交易失敗顯示頁面B。

 

  • 服務端支付實現

 

做爲服務端,咱們須要作的是第二步、第三步、第五步,下面詳細介紹這幾步該如何實現。

第二步:APP客戶端提交訂單信息到服務端,服務端首先對訂單信息進行校驗,校驗經過後再調用alipay.trade.order.settle(統一收單交易結算接口),操做成功後會返回必要的預支付信息。

public String orderAliPay(String payAmount, String outTradeNo) {
    String orderStr = "";
    try {
        // 實例化客戶端
        AlipayClient alipayClient = new DefaultAlipayClient(aliPayUrl, APP_ID,
                APP_PRIVATE_KEY, "json", CHARSET, APP_PUBLIC_KEY, "RSA2");
        // 實例化具體API對應的request類,類名稱和接口名稱對應,當前調用接口名稱:alipay.trade.app.pay
        AlipayTradeAppPayRequest request = new AlipayTradeAppPayRequest();
        // SDK已經封裝掉了公共參數,這裏只須要傳入業務參數。如下方法爲sdk的model入參方式(model和biz_content同時存在的狀況下取biz_content)。
        AlipayTradeAppPayModel model = new AlipayTradeAppPayModel();
        // model.setPassbackParams(URLEncoder.encode(body.toString()));
        // 描述信息 添加附加數據
        model.setSubject("x"); // 商品標題
        model.setOutTradeNo(outTradeNo); // 商家訂單編號
        model.setTimeoutExpress("30m"); // 超時關閉該訂單時間
        model.setTotalAmount(payAmount); // 訂單總金額
        model.setProductCode("QUICK_MSECURITY_PAY"); // 銷售產品碼,商家和支付寶簽約的產品碼,爲固定值QUICK_MSECURITY_PAY
        request.setBizModel(model);
        request.setNotifyUrl(notifyUrl); // 回調地址

        try {
            // 這裏和普通的接口調用不一樣,使用的是sdkExecute
            AlipayTradeAppPayResponse response = alipayClient
                    .sdkExecute(request);
            orderStr = response.getBody();
            logger.info("支付寶支付預處理-商戶訂單號:" + outTradeNo);
            logger.info("支付寶支付預處理-結果:" + response.isSuccess());
            // 能夠直接給客戶端請求,無需再作處理。
        } catch (AlipayApiException e) {
            e.printStackTrace();
        }
    } catch (Exception e) {
        logger.error("Exception", e);
    }
    return orderStr;
}

 

 

參數說明:

payAmount支付金額  

outTradeNo:訂單流水號(系統惟一)

aliPayUrl  支付寶支付接口https://openapi.alipay.com/gateway.do

APP_ID  支付寶分配給開發者的應用ID  

APP_PRIVATE_KEY 應用私密匙

APP_PUBLIC_KEY 應用公密匙

notifyUrl  異步回調地址 必須外網環境下能夠正常訪問的地址

 

正確的返回結果是這樣的:

{

    "alipay_trade_order_settle_response": {

        "code": "10000",

        "msg": "Success",

        "trade_no": "2015070921001004130000127421"

    },

    "sign": "ERITJKEIJKJHKKKKKKKHJEREEEEEEEEEEE"

}

把這個信息返回給APP開發人員就好了。若是返回信息錯誤,就要參考具體的返回碼:https://docs.open.alipay.com/api_1/alipay.trade.order.settle

https://docs.open.alipay.com/54/106370/

 

 

 

  • 服務端回調實現

 

@RequestMapping(value = "/aliPayNotify", produces = "text/html;charset=UTF-8", method = RequestMethod.POST)
public String aliPayNotify(HttpServletRequest request,HttpServletResponse response) {
   logger.info("支付寶支付完成回調,進入 aliPayNotify 方法");
       Map<String, String[]> requestParams = request.getParameterMap();

   // 獲取支付寶POST過來反饋信息
   Map<String, String> params = new HashMap<String, String>();
   logger.info("遍歷支付成功後支付寶返回的參數requestParams,進行設值");
   for (Iterator<String> iter = requestParams.keySet().iterator(); iter.hasNext(); ) {
      String name = (String) iter.next();
      String[] values = (String[]) requestParams.get(name);
      String valueStr = "";
      for (int i = 0; i < values.length; i++) {
         valueStr = (i == values.length - 1) ? valueStr + values[i]
               : valueStr + values[i] + ",";
      }
      // 亂碼解決,這段代碼在出現亂碼時使用。
      // valueStr = new String(valueStr.getBytes("ISO-8859-1"), "utf-8");
      params.put(name, valueStr);
   }

 

獲取返回信息後,須要對信息進行簽名進行驗證:

//獲取支付寶POST過來反饋信息

Map<String,String> params = new HashMap<String,String>();

Map requestParams = request.getParameterMap();

for (Iterator iter = requestParams.keySet().iterator(); iter.hasNext();) {

    String name = (String) iter.next();

    String[] values = (String[]) requestParams.get(name);

    String valueStr = "";

    for (int i = 0; i < values.length; i++) {

        valueStr = (i == values.length - 1) ? valueStr + values[i]

                    : valueStr + values[i] + ",";

   }

    //亂碼解決,這段代碼在出現亂碼時使用。

//valueStr = new String(valueStr.getBytes("ISO-8859-1"), "utf-8");

params.put(name, valueStr);

}

//切記alipaypublickey是支付寶的公鑰,請去open.alipay.com對應應用下查看。

//boolean AlipaySignature.rsaCheckV1(Map<String, String> params, String publicKey, String charset, String sign_type)

boolean flag = AlipaySignature.rsaCheckV1(params, alipaypublicKey, charset,"RSA2")

 

簽名校驗經過後再進行訂單更新業務邏輯處理,注意支付寶建議服務端返回success狀態

支付寶是用POST方式發送通知信息,所以該頁面中獲取參數的方式,如:request.Form(「out_trade_no」) $_POST[‘out_trade_no’];

支付寶主動發起通知,該方式纔會被啓用;

只有在支付寶的交易管理中存在該筆交易,且發生了交易狀態的改變,支付寶纔會經過該方式發起服務器通知(即時到帳交易狀態爲「等待買家付款」的狀態默認是不會發送通知的);

服務器間的交互,不像頁面跳轉同步通知能夠在頁面上顯示出來,這種交互方式是不可見的;

第一次交易狀態改變(即時到帳中此時交易狀態是交易完成)時,不只會返回同步處理結果,並且服務器異步通知頁面也會收到支付寶發來的處理結果通知;

程序執行完後必須打印輸出「success」(不包含引號)。若是商戶反饋給支付寶的字符不是success這7個字符,支付寶服務器會不斷重發通知,直到超過24小時22分鐘。通常狀況下,25小時之內完成8次通知(通知的間隔頻率通常是:4m,10m,10m,1h,2h,6h,15h);

程序執行完成後,該頁面不能執行頁面跳轉。若是執行頁面跳轉,支付寶會收不到success字符,會被支付寶服務器斷定爲該頁面程序運行出現異常,而重發處理結果通知;

cookies、session等在此頁面會失效,即沒法獲取這些數據;

該方式的調試與運行必須在服務器上,即互聯網上能訪問;

該方式的做用主要防止訂單丟失,即頁面跳轉同步通知沒有處理訂單更新,它則去處理;

當商戶收到服務器異步通知並打印出success時,服務器異步通知參數notify_id纔會失效。也就是說在支付寶發送同一條異步通知時(包含商戶並未成功打印出success致使支付寶重發數次通知),服務器異步通知參數notify_id是不變的。

支付寶APP支付大概就是這樣子,不懂得能夠留言我。

相關文章
相關標籤/搜索