1. 程式人生 > >微信公眾號支付整體流程記錄備忘

微信公眾號支付整體流程記錄備忘

相比支付寶支付,微信公眾號支付的實現以及過程真的是比較複雜,而且坑多,都是血淚史。 檢視微信支付的開發配置,這裡就可以看到對應的支付授權目錄以及測試目錄,可以選擇使用線上作為支付測試,但是不推薦。使用測試授權目錄時,注意需要設定測試白名單,規定哪些人可以進行支付測試。

  當然,我們有微信公眾號,就肯定也便擁有了H5網站。公眾號支付採用的支付方式屬於JSAPI方式,檢視JSAPI網頁支付是否已經開通了許可權,並配置好支付授權目錄,該目錄必須是發起支付的頁面的精確目錄,子目錄下無法正常呼叫支付。 根據微信支付的文件,商戶系統和微信支付系統主要互動:
  1. 商戶server呼叫統一下單介面請求訂單,api參見公共api【統一下單API】
  2. 商戶server接收支付通知,api參見公共api【支付結果通知API】
  3. 商戶server查詢支付結果,api參見公共api【查詢訂單API】

統一下單API

商戶系統先呼叫該介面在微信支付服務後臺生成預支付交易單,商戶訂單號為商戶系統內部的訂單號,32個字元內、可包含字母, 其他說明見商戶訂單號,由商戶自定義生成,微信支付要求商戶訂單號保持唯一性(建議根據當前系統時間加隨機序列來生成訂單號)。重新發起一筆支付要使用原訂單號,避免重複支付;已支付過或已呼叫關單、撤銷(請見後文的API列表)的訂單號不能重新發起支付。 統一下單流程完成後,最主要是根據前幾步驟生成的相關引數,獲取對應的PrepayId, 請求的url為統一下單api:  請求的引數:
<xml>
     <appid><![CDATA[wx1exxxx]]></appid>
     <body><![CDATA[JSAPI_payment_test]]></body>
     <mch_id>1242312122</mch_id>
     <nonce_str><![CDATA[6aghlqz18duhfebole531dce0r7bw0td]]></nonce_str>
     <notify_url><![CDATA[http://xxxx.com/xxx]]></notify_url>
     <openid><![CDATA[ogGCluNRaxBTNFWZzS_kH-rRez_Q]]></openid>
     <out_trade_no><![CDATA[nraxbtnfwzzskhrrezq1434590817259]]></out_trade_no>
     <spbill_create_ip><![CDATA[119.161.230.131]]></spbill_create_ip>
     <total_fee>1</total_fee>
     <trade_type><![CDATA[JSAPI]]></trade_type>
     <sign><![CDATA[F415B11A1C1B4894085FD703CBD14B71]]></sign>
</xml>
  將引數以POST方式傳送給統一下單URL,返回值仍然也是xml格式:  
<xml>
<return_code><![CDATA[SUCCESS]]></return_code>
<return_msg><![CDATA[OK]]></return_msg>
<appid><![CDATA[xxx]]></appid>
<mch_id><![CDATA[1212]]></mch_id>
<nonce_str><![CDATA[amxU3MOLatSWVzua]]></nonce_str>
<sign><![CDATA[E458BE2C4F23C6F22B7561E74F41DEEF]]></sign><result_code><![CDATA[SUCCESS]]></result_code>
<prepay_id><![CDATA[wx201506180927207ee0b107300739613144]]></prepay_id>
<trade_type><![CDATA[JSAPI]]></trade_type>
</xml>
  我們只需獲取其中的prepay_id即可;如果沒有獲得,直接返回錯誤資訊。 上面所說的引數中,appid和mch_id屬於公眾號以及商戶號id,申請公眾號以及開通支付時就已經確定;notify_url屬於微信支付伺服器向服務端回撥的介面(後續會用到);spbill_create_id是使用者的ip;total_fee是付款總額;trade_type如果是公眾號支付寫死為JSAPI;out_trade_no是商戶訂單號,可在服務端通過文件中的演算法生成即可;nonce_str是本次請求支付的隨機字串,最多32位。 不確定的就只有兩項: openid, 關於公眾號中如何獲取openid可以檢視相關文件,在關注者與公眾號產生訊息互動後,公眾號可獲得關注者的OpenID(加密後的微訊號,每個使用者對每個公眾號的OpenID是唯一的。對於不同公眾號,同一使用者的openid不同)。 在微信公眾號請求使用者網頁授權之前,開發者需要先到公眾平臺官網中的開發者中心頁配置授權回撥域名。請注意,這裡填寫的是域名(是一個字串),而不是URL:
https://mp.weixin.qq.com/wiki/17/c0f37d5704f0b64713d5d2c37b468d75.html
,授權回撥域名配置規範為全域名,比如需要網頁授權的域名為:www.qq.com,配置以後此域名下面的頁面http://www.qq.com/music.html 、 http://www.qq.com/login.html 都可以進行OAuth2.0鑑權。

獲取Openid

在確保微信公眾賬號擁有授權作用域(scope引數)的許可權的前提下(服務號獲得高階介面後,預設擁有scope引數中的snsapi_base和snsapi_userinfo),引導關注者開啟如下頁面:
https://open.weixin.qq.com/connect/oauth2/authorize?appid=APPID&redirect_uri=REDIRECT_URI&response_type=code&scope=SCOPE&state=STATE#wechat_redirect
  若提示“該連結無法訪問”,請檢查引數是否填寫錯誤,是否擁有scope引數對應的授權作用域許可權。 公眾號支付首先要設定微信支付的連結,通過該連結,就可以呼叫到微信後端以及服務端,支付的連結格式如下:
https://open.weixin.qq.com/connect/oauth2/authorize?appid=${appid}&redirect_uri={{url}}%2Fwxpay%2FpayModelAndView?parameterName=${xxxx}&response_type=code&scope=snsapi_base&state=123#wechat_redirect
  scope設定為snsapi_base (不彈出授權頁面,直接跳轉,只能獲取使用者openid),雖然是snsapi_userinfo的時候可以獲取更多資訊,但需要彈出授權介面,而且我們也不需要獲取那麼多資訊。 實際上需要微信伺服器進行回撥才能實現,而回調的redirect_uri為:
${url}/wxpay/payModelAndView?
  其中appid即為註冊的微信公眾服務號ID,url引數即為當前網站的url,並帶上coach_product_id,傳送給回撥地址,url需要進行URLDecoder,微信伺服器會回撥該服務。

通過code換取網頁授權access_token

首先請注意,這裡通過code換取的是一個特殊的網頁授權access_token,與基礎支援中的access_token(該access_token用於呼叫其他介面)不同。公眾號可通過下述介面來獲取網頁授權access_token。如果網頁授權的作用域為snsapi_base,則本步驟中獲取到網頁授權access_token的同時,也獲取到了openid,snsapi_base式的網頁授權流程即到此為止。 尤其注意:由於公眾號的secret和獲取到的access_token安全級別都非常高,必須只儲存在伺服器,不允許傳給客戶端。後續重新整理access_token、通過access_token獲取使用者資訊等步驟,也必須從伺服器發起。 redirect_url中就可以獲取到對應的request Parameter,其中的code就是我們需要的編碼。 獲取code後,請求以下連結獲取access_token: 
https://api.weixin.qq.com/sns/oauth2/access_token?appid=APPID&secret=SECRET&code=CODE&grant_type=authorization_code
  注意此URL必須在微信瀏覽器中開啟,redirect_uri設定為當前controller方法對應的restful介面。 傳送過來的code可以通過request.getParameter(“code”)來獲取,如果沒有生成該code,不能繼續進行。 如果請求失敗,記得別讓使用者還能重複使用這個code呼叫後臺程式碼。也即,到支付頁面後不能重新整理。 返回的資料為json格式,如下:
{
   "access_token": "OezXcEiiBSKSxW0eoylIeGhaJjUxzVpRR4o6hX-jAhOn160_GRNWPwzcWR_QSO4gbjzWHPV6zuNazuJp3spc2gptHLcR-g2QetMKeDGZ3IJD6PbJCf2YKyw6k4aeiFbdJgfJgNBXKfZ0dPb98IKR_w",
   "expires_in": 7200,
   "refresh_token": "OezXcEiiBSKSxW0eoylIeGhaJjUxzVpRR4o6hX-jAhOn160_GRNWPwzcWR_QSO4g7r7Y2BQy_p7bmrjxH8YN3scFXn7C4fUnNn9AFDcz_qW5ErAi4Lp9p18PcLv60yUtOBSwd8MfDIKap12lVExOAg",
   "openid": "ogGCluNRaxBTNFWZzS_kH-rRez_Q",
   "scope": "snsapi_base"
 }
  其中,我們只需要獲取其openid,然後進行下一步操作。

進行簽名:sign

 
public String getSign(Map<String, String> items, String APISecret) throws NoSuchAlgorithmException, UnsupportedEncodingException {
        Map<String, String> tmp = new TreeMap<String, String>(items);
        StringBuilder sb = new StringBuilder();
        for(Map.Entry<String, String> entry : tmp.entrySet()) {
            String key = entry.getKey();
            String value = entry.getValue();
            if(StringUtils.isEmpty(value)) continue;
            sb.append(key).append("=").append(value).append("&");
        }
        sb.append("key=").append(APISecret);

        return publicService.padStr(new BigInteger(1, MessageDigest.getInstance("MD5").digest(sb.toString().getBytes(CharEncoding.UTF_8))).toString(16).toUpperCase(), "0", 32);
    }
  使用TreeMap對key進行字串字典排序,附加上對應的key,後進行MD5計算並拍成32位並補零然後轉成大寫。 有了簽名就可以進行統一下單相關操作了。 生成公眾號支付介面所使用的jsapi調起支付的所有引數,返回給前端。參考微信公眾平臺相關文件: 其中package使用的是上一步的prepay_id=?,本系統中paySign採用MD5演算法,其中的paySign採用統一簽名生成演算法來計算完成。

儲存至服務端本地/資料庫,頁面發起支付

將使用者資訊,產品資訊,生成的訂單儲存至資料庫,以便在我方能夠查詢到該記錄。
//將userId和out_trade_no等資訊寫入payment_result表
paymentPublicService.insertStubToPaymentResultTable(userId, PaymentResult.CHANNEL.WEIXIN, coachProductId, outTradeNo);
  在從服務端轉到頁面上之後,再發起支付呼叫,跳轉至付款頁面 微信支付需要在回撥之後跳轉至付款頁面(通過除錯發現,這個最終付款介面還是必須存在的)。 頁面中會呼叫真正的付款功能。
$(function(){
  alert("xxxxxxxx");
  callPay();
  function onBridgeReady(){
    WeixinJSBridge.invoke(
            'getBrandWCPayRequest', {
              "appId" : '${appId}',           //公e眾號名稱,由商戶傳入
              "timeStamp": '${timeStamp}',    //時間戳,自1970年以來的秒數
              "nonceStr" : '${nonceStr}',     //隨機串
              "package" : '${package1}',      //預支付ID引數
              "signType" : '${signType}',     //微信簽名方式:
              "paySign" : '${paySign}'        //微信簽名
            },
            function(res){
              if(res.err_msg == "get_brand_wcpay_request:ok" ) {
                alert("支付成功");
                window.location.href="/student/student_booking";
              }else if(res.err_msg == "get_brand_wcpay_request:cancel" ){
                alert("支付過程中使用者取消");
                window.location.href="student_pay.jsp";
              }else{
                alert('支付失敗');
                window.location.href="student_pay.jsp";
              }
            }
    );
  }
  function callPay(){
    if (typeof WeixinJSBridge == "undefined"){
      if( document.addEventListener ){
        document.addEventListener('WeixinJSBridgeReady', onBridgeReady, false);
      }else if (document.attachEvent){
        document.attachEvent('WeixinJSBridgeReady', onBridgeReady);
        document.attachEvent('onWeixinJSBridgeReady', onBridgeReady);
      }
    }else{
      onBridgeReady();
    }
  }
})
  生成完成之後,就可以進行支付,支付完成後,微信服務端就會通過設定的notify_url來進行回撥通知,此時資料庫端的訂單資訊就可以填充完整。

支付結果通知

傳送過來的Request,得到對應的xml        
 String xml = IOUtils.toString(request.getInputStream(), CharEncoding.UTF_8);
  商戶處理後同步返回給微信引數,根據回撥通知API,需要返回如下xml,才能讓微信伺服器確認已經接受到notify訊息,否則微信伺服器會多次retry呼叫我們的介面:
<xml>
     <return_code><![CDATA[SUCCESS]]></return_code>
     <return_msg><![CDATA[OK]]></return_msg>
</xml>
  如果在服務端主動查詢訂單,可以檢視對應的文件來進行操作,這裡坑比較少就不詳細說明了:

相關推薦

公眾支付整體流程記錄

相比支付寶支付,微信公眾號支付的實現以及過程真的是比較複雜,而且坑多,都是血淚史。 檢視微信支付的開發配置,這裡就可以看到對應的支付授權目錄以及測試目錄,可以選擇使用線上作為支付測試,但是不推薦。使用測試授權目錄時,注意需要設定測試白名單,規定哪些人可以進行支付測試。   當然,我們有微信

公眾支付JSAPI 詳細記錄

剛剛除錯通微信公眾號支付,寫個部落格記錄一下。 jsapi必要的幾個引數 微信公眾號的賬戶密碼,微信商戶賬號密碼. 登陸微信公眾號,左下角開發-基本配置,檢視APPID 1、公眾APPID(已經得到) 2、APPSECEPT(已經得到)   進入微信商戶平

公眾支付開發流程

主要場景為一碼付,使用者掃碼二維碼進入商戶自己的H5頁面,微信掃碼呼叫微信支付,支付寶掃碼就呼叫支付寶進行支付 微信開發文件 https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=7_1 有一篇寫的比較全的文件,

thinkphp3.2整和公眾支付詳細流程 demo

公眾號支付是指在微信app中訪問的頁面通過js直接調起微信支付;首先第一個步驟登入微信公眾平臺然後1.設定域名(設定授權域名和支付域名)①設定網頁授權域名並且設定白名單(新增你自己伺服器公網ip)如下圖所示         ②設定支付域名,去微信商戶後臺,產品中心的 開發配置

公眾支付接入流程

背景: 在Web應用中接入微信支付,我以為只是檢視demo,根據demo和文件相結合然後呼叫介面就完事了,但是微信文件的複雜性和隱坑使我填坑填到懷疑人生,致敬在微信踩過的神坑,過年給他燒點紙記掛一下,NND。。。。。。。。。。。 注意事項: 坑一:幾個簽名的混淆

公眾支付--錯誤記錄

二次 數組 格式轉換 println equals sig col package reat 微信公眾號支付調用統一下單接口時,微信返回的數據一定要二次組裝再給前臺,否則會有問題的,正確示範如下: /** * 獲取weixin支付的返回信息 * @pa

支付公眾支付) [記錄]

scope err question dir rec package ready fad span 後臺   先獲取code code有效5min     public string GetCodeUrl(string Appid, string redirect

公眾支付報文示例

cda 響應 xca mes amp 鏈接 返回值 col http 請求報文: 1 <xml> 2 <body><![CDATA[狄克酸奶店]]></body> 3 <callback_url&

個體戶沒有組織機構代碼證如何開通公眾支付

jpg alt 註意 方法 .com str 工作人員 個體工商戶 log 個體工商戶開通微信支付最新流程: 一、準備資料1.營業執照:有效期內的個體戶執照;2.身份證:經營者個人身份證照片;3.收款銀行賬戶:提現用的銀行賬號;4.手機號碼:客服人員的聯系手機號;5.郵箱

php公眾支付接口開發demo

targe param pre space secret 修改 pen host field 本支付接口使用Yii2框架,所以控制器的格式都是該框架的,不過放到其他框架都差不多,根據對應的規則修改一下控制器的方法名字就行了,親測有效,比較簡單,沒有封裝,想了解微信支付實現

thinkphp整合系列之公眾支付

const simple 商品 simplex 支付平臺 doc 外部 center vendor thinkphp整合系列之微信公眾號支付 白俊遙 2016-07-17 11:26:52 PHP thinkphp 公眾號支付是指在微信app中訪問的頁面

***公眾支付+H5支付+掃碼支付+小程序支付+APP支付解決方案總結

ati asc alt creat chapter edit 隨機字符串 glob 測試 最近負責的一些項目開發,都用到了微信支付(微信公眾號支付、微信H5支付、微信掃碼支付、APP微信支付)。在開發的過程中,在調試支付的過程中,或多或少都遇到了一些問題,今天總結下,分享,

公眾支付開發全過程(java版)

sdk 命令 所有 data 權限 {} servle res ast 文章有不當之處,歡迎指正,如果喜歡微信閱讀,你也可以關註我的微信公眾號:好好學java,獲取優質學習資源。 一、微信官方文檔微信支付開發流程(公眾號支付) 首先我們到微信支付的官方文檔的開發步驟部分查

公眾支付

存在 分享圖片 itl 操作 mark clas 思考 域名認證 span 近期處理微信公眾號支付過程中遇到一些小問題,也因此引發了一些思考。 首先不得不吐槽一下微信公眾號的配置文檔沒有及時更新,對開發人員不夠細致,也因此迷茫了好久。 經過一輪研究和實

公眾支付踩坑記

系統 shm efi bsp 網絡異常 router nec 平臺 wiki   前兩周做微信H5支付,在瀏覽器端用的,天真地以為app掛到公眾號中也能用,結果不行>"<|||| ,只好再對接一次公眾號支付,微信的支付對接下來總體感覺就是封裝地不如支付寶,文檔不

vue項目使用公眾支付總結

tor 即將 script mut 頁面 com vue log string 微信公眾號支付 1. 使用jssdk調用微信支付,具體查看開發文檔; 使用的vuex,在mutations中 wechatPay (state, data) { sta

公眾支付(tp5)

                                        微信公眾號支付

thinkphp3.2公眾支付(jsapi支付)開發過程

第一次做微信支付(網頁版本的),折騰了兩天,記錄一下方便下次自己再次使用,也希望能幫和我一樣初次接觸的朋友踩一下坑。 前期準備 1.開通微信認證服務號,並且開通商戶平臺 2.下載微信支付dome,下載地址:https://pay.weixin.qq.com/wiki/doc/api/js

公眾支付/退款(java環境)開發介紹

開發之前翻閱了很多帖子,結合自己的實際開發情況,將微信支付/退款 流程以及code貼出,希望通過這一篇帖子就能解決你的問題,有不清楚的直接留言,我會及時回覆(ง •̀_•́)ง   一些說明:xxxUtils為工具類,Constant為常量類 為方便開發,所用和微信支付相關co

公眾支付(一)統一下單

最近在研究微信公眾號的支付開發,一開始對著開發文件各種懵,也自然而然地跳入了各種坑,現在把整個開發過程簡略地做個記錄。 1.開發環境準備 首先要有一個微信服務號,訂閱號是不能開通微信支付的。微信公眾號申請微信支付後,接著申請微信支付商戶平臺,公眾號上面已經標明“公眾平臺微信支付公眾號支付授權