微信H5支付(手機瀏覽器請求)

aajonas發表於2019-06-21

最近在做一個微信H5支付的功能,開發中遇到了一些問題,網上相關的資料比較少,在此做下總結以供參考。

一、功能需求

手機瀏覽器頁面發起產品購買請求,調起微信支付,支付完成後返回購買頁面展示支付結果。
(手機瀏覽器->微信app->手機瀏覽器)

二、關鍵思路詳解

微信參考文件
其實微信文件已經把流程步驟列出來了,按照步驟就可以實現了,下面給出一些關鍵步驟及注意事項

1、使用者點選頁面購買按鈕,向自己伺服器後端介面發起購買請求並調起微信支付。這裡需要注意的是,想要調起微信支付,需要後端微信發起統一下單,成功後返回結果有mweb_url欄位,該欄位的值是一個URL,為支付跳轉連結。

請求跳轉

a、後端介面直接跳轉,後端發起統一下單獲取mweb_url後直接redirect
b、前端頁面用js跳轉,後端將mweb_url返回給前端,前端用js跳轉

function pay() {         $.ajax({               type: "POST",//方法型別               dataType: "json",//預期伺服器返回的資料型別               url: "www.example.com/pay.php",//url               data: {'oid':oid},                       success: function (mweb_url) {                        window.location.href=mweb_url//獲取後跳轉                    },                    error : function() {                        alert("異常");                    }                });}複製程式碼
回撥頁面

後端發起統一下單獲得的mweb_url,需要在其後面拼接redirect_url引數,並對redirect_url進行urlencode處理,來指定回撥頁面,如果未指定會報商家引數格式有誤

<?php/**  *後端支付介面(以下程式碼省略了部分只給出大概邏輯不能直接使用)  *有#####的註釋需要留意  **/use ....class pay{  /**     * 預支付     */    public function prepay(){        //微信支付類        $wxFactory = new WxFactory();        //統一下單所需引數(根據自己實際需求定義)        $body = '購買商品';        $notifyUrl = 'http://www.example.com/Callback.php';//微信支付非同步回撥        $tradeType = 'MWEB';        $amount = 1;        $time = time();        $out_trade_no = $time.sprintf('%08s',mt_rand(10, 999999));        if( $amount <= 0 ){            return new ApiResponse(['code' =>-1,'msg' =>'支付金額不得小於0']);//json類        }        try {            $payment = $wxFactory->getObj('\wx\payment');//呼叫統一下單介面            //引數            $params = array(                    'trade_type'=>$tradeType,                    'body'=>$body,                    'notify_url'=>$notifyUrl,                    'out_trade_no'=>$out_trade_no,                    'total_fee'=>$amount,//                 'spbill_create_ip'=>$_SERVER['REMOTE_ADDR'],  #####剛開始使用該方法獲取ip結果報錯,後面採用下面方法獲取IP,得以解決                    'spbill_create_ip'=>$this->get_client_ip()            );            //預支付返回結果            $result = $payment->prepay($params);            $redirect_url  = 'http://www.example.com/show.php?';// #####回撥地址,該地址需要是商戶號後臺提交的授權域名,如果不是請求跳轉是需要偽造referer,不建議偽造.            $redirect_url .= 'order='.$out_trade_no;//####回撥所需引數支付id,            $mweb_url = $result['mweb_url'].'&redirect_url='.urlencode($redirect_url);//####拼接回撥地址            //返回mweb_url            return new ApiResponse(['code' =>0,'mweb_url'=>$data]);        }catch ( \WxServerException $e ){            //支付不成功會以異常形式返回            return new ApiResponse(['code' =>-1,'msg' =>$e->getMessage()]);        }    }    //獲取IP地址    private function get_client_ip(){        if(getenv('HTTP_CLIENT_IP') && strcasecmp(getenv('HTTP_CLIENT_IP'), 'unknown')) {            $ip = getenv('HTTP_CLIENT_IP');        } elseif(getenv('HTTP_X_FORWARDED_FOR') && strcasecmp(getenv('HTTP_X_FORWARDED_FOR'), 'unknown')) {            $ip = getenv('HTTP_X_FORWARDED_FOR');        } elseif(getenv('REMOTE_ADDR') && strcasecmp(getenv('REMOTE_ADDR'), 'unknown')) {            $ip = getenv('REMOTE_ADDR');        } elseif(isset($_SERVER['REMOTE_ADDR']) && $_SERVER['REMOTE_ADDR'] && strcasecmp($_SERVER['REMOTE_ADDR'], 'unknown')) {            $ip = $_SERVER['REMOTE_ADDR'];        }        return preg_match ( '/[\d\.]{7,15}/', $ip, $matches ) ? $matches [0] : '';    }}複製程式碼

2、使用者在微信中間頁面操作後(支付或取消支付)會回跳到我們指定的回撥地址,並帶上我們拼裝的引數。根據URL中的引數,前端頁面請求後端介面查詢支付結果(伺服器根據支付訂單id向微信發起查詢),然後展示給使用者。(根據微信文件,由於設定redirect_url後,回跳指定頁面的操作可能發生在:1,微信支付中間頁調起微信收銀臺後超過5秒 2,使用者點選“取消支付“或支付完成後點“完成”按鈕。因此無法保證頁面回跳時,支付流程已結束,所以商戶設定的redirect_url地址不能自動執行查單操作,應讓使用者去點選按鈕觸發查單操作。回跳頁面展示效果可參考下圖)

3、微信支付非同步通知回撥地址。統一下單成功後,微信會非同步回撥,統一下單時引數notify_url所填地址,該非同步回撥是用於通知伺服器端,使用者所生成的預支付訂單是否支付完成。在做該功能的時候發現微信並有時候沒有非同步呼叫該介面,所以第2點提到的需要主動去呼叫後端介面查詢就很有必要,如果擔心主動呼叫查詢出錯,還可以寫一個後端指令碼定時去查詢使用者預支付訂單情況。

三、總結

1、參照微信文件,文件中給出了詳細的流程步驟。
2、mweb_url後必須拼接redirect_url,並且redirect_url必須授權,否則會報錯
3、支付流程結束跳轉回頁面,展示支付結果,需要讓使用者主動觸發查單操作。


相關文章