1. 程式人生 > >微信掃碼支付功能(2)---使用者掃碼支付成功,微信非同步回撥商戶介面

微信掃碼支付功能(2)---使用者掃碼支付成功,微信非同步回撥商戶介面

使用者掃碼支付成功,微信非同步回撥商戶

當用戶掃碼支付成功之後,微信會非同步回撥商戶介面,告知使用者支付成功。好讓商戶進行下一步操作。

一、介面說明

   1、流程圖

這裡要做的就是使用者支付成功後,微信非同步通知商戶支付結果,商戶收到通知後告知支付通知接收情況。 

      2、介面說明

有關商戶介面應注意以下幾點:

     (1)該連結是通過【統一下單API】中提交的引數notify_url設定,如果連結無法訪問,商戶將無法接收到微信通知。

     (2)notify_url不能有引數,外網可以直接訪問,不能有訪問控制(比如必須要登入才能操作)。示例:notify_url:“https://pay.weixin.qq.com/wxpay/pay.action”

     (3)支付完成後,微信會把相關支付結果和使用者資訊傳送給商戶,商戶需要接收處理,並返回應答。

     (4)對後臺通知互動時,如果微信收到商戶的應答不是成功或超時,微信認為通知失敗,微信會通過一定的策略定期重新發起通知,儘可能提高通知的成功率,但微信不

保證通知最終能成功。(通知頻率為15/15/30/180/1800/1800/1800/1800/3600,單位:秒)注意:同樣的通知可能會多次傳送給商戶系統。商戶系統必須能夠正確處理

重複的通知。推薦的做法是,當收到通知進行處理時,首先檢查對應業務資料的狀態,判斷該通知是否已經處理過,如果沒有處理過再進行處理,如果處理過直接返回結果成功。

在對業務資料進行狀態檢查和處理之前,要採用資料鎖進行併發控制,以避免函式重入造成的資料混亂。

    (5)特別提醒:商戶系統對於支付結果通知的內容一定要做簽名驗證,防止資料洩漏導致出現“假通知”,造成資金損失

二、介面開發

    1、回撥介面

    /**
     * 微信支付回撥
     * 這裡在統一下單中提供的notify_url地址是:http://jincou.vipgz1.idcfengye.com/api/v1/order/callback
     * 該域名是sunny-ngrok中的二級域名,通過它對映到微信本地
     */
    @RequestMapping("callback")
    public void orderCallback(HttpServletRequest request,HttpServletResponse response) throws
Exception { InputStream inputStream = request.getInputStream(); //BufferedReader是包裝設計模式,效能更搞 BufferedReader in = new BufferedReader(new InputStreamReader(inputStream,"UTF-8")); StringBuffer sb = new StringBuffer(); //1、將微信回撥資訊轉為字串 String line ; while ((line = in.readLine()) != null){ sb.append(line); } in.close(); inputStream.close(); //2、將xml格式字串格式轉為map集合 Map<String,String> callbackMap = WXPayUtil.xmlToMap(sb.toString()); System.out.println(callbackMap.toString()); //3、轉為有序的map SortedMap<String,String> sortedMap = WXPayUtil.getSortedMap(callbackMap); //4、判斷簽名是否正確 if(WXPayUtil.isCorrectSign(sortedMap,weChatConfig.getKey())){ //5、判斷回撥資訊是否成功 if("SUCCESS".equals(sortedMap.get("result_code"))){ //獲取商戶訂單號 //商戶系統內部訂單號,要求32個字元內,只能是數字、大小寫字母_-|* 且在同一個商戶號下唯一 String outTradeNo = sortedMap.get("out_trade_no"); System.out.println(outTradeNo); //6、資料庫查詢訂單,如果存在則根據訂單號更新該訂單 VideoOrder dbVideoOrder = videoOrderService.findByOutTradeNo(outTradeNo); System.out.println(dbVideoOrder); if(dbVideoOrder != null && dbVideoOrder.getState()==0){ //判斷邏輯看業務場景 VideoOrder videoOrder = new VideoOrder(); videoOrder.setOpenid(sortedMap.get("openid")); videoOrder.setOutTradeNo(outTradeNo); videoOrder.setNotifyTime(new Date()); //修改支付狀態,之前生成的訂單支付狀態是未支付,這裡表面已經支付成功的訂單 videoOrder.setState(1); //根據商戶訂單號更新訂單 int rows = videoOrderService.updateVideoOderByOutTradeNo(videoOrder); System.out.println(rows); //7、通知微信訂單處理成功 if(rows == 0){ response.setContentType("text/xml"); response.getWriter().println("success"); return; } }} } //7、通知微信訂單處理失敗 response.setContentType("text/xml"); response.getWriter().println("fail"); }

    2、校驗簽名方法

    /**
     * 校驗簽名
     */
    public static boolean isCorrectSign(SortedMap<String, String> params, String key){

        //1、再進行一次生成sign
        String sign = createSign(params,key);
        String weixinPaySign = params.get("sign").toUpperCase();
        //將兩次生成的sign比較看是否一致
        return weixinPaySign.equals(sign);
    }
    
    /**
     * 生成微信支付sign
     */
    public static String createSign(SortedMap<String, String> params, String key){
        StringBuilder sb = new StringBuilder();
        Set<Map.Entry<String, String>> es =  params.entrySet();
        Iterator<Map.Entry<String,String>> it =  es.iterator();
        //生成 stringA="appid=wxd930ea5d5a258f4f&body=test&device_info=1000&mch_id=10000100&nonce_str=ibuaiVcKdpRxkhJA";
        while (it.hasNext()){
            Map.Entry<String,String> entry = (Map.Entry<String,String>)it.next();
             String k = (String)entry.getKey();
             String v = (String)entry.getValue();
             if(null != v && !"".equals(v) && !"sign".equals(k) && !"key".equals(k)){
                sb.append(k+"="+v+"&");
             }
        }
        sb.append("key=").append(key);
        String sign = CommonUtils.MD5(sb.toString()).toUpperCase();
        return sign;
    }

      3、測試

(1)支付成功

(2)通過ngrok回撥到本地,通過斷點可以看出sb字串格式

(3)將xml格式字串轉為map

成功!

github原始碼

我只是偶爾安靜下來,對過去的種種思忖一番。那些曾經的舊時光裡即便有過天真愚鈍,也不值得譴責。畢竟,往後的日子,還很長。不斷鼓勵自己,

天一亮,又是嶄新的起點,又是未知的征程(上校17)