1. 程式人生 > >微信公眾號支付接入流程

微信公眾號支付接入流程

背景:

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

注意事項:

坑一:幾個簽名的混淆

關於簽名的除錯,網上各種哭嚎,不少人在簽名處除錯多日無果。

那是因為整個工作流程中,涉及到了至少三個簽名,稍不小心就會用錯。

在統一下單的接口裡,向微信伺服器傳送請求中的引數有一枚簽名;

其返回的引數中,亦有一枚簽名,後經觀察,發現二者為同一簽名。

但在使用JSSDK後所呼叫的wx.config裡所需的引數signature卻是另一枚簽名。

而在wx.chooseWXPay裡所需的支付簽名paySign,卻又是另另另外的一枚。

此坑所耗時間:2天。

坑二:兩個Access_token

檢視開發文件可以看到,微信搞了兩個Access_token!

即使他們用再多的加粗文字來提醒我們兩個token的不同之處,

也難以撫平我們在開發過程中陷入混亂的受傷之身心!

一個是網頁授權的access_token,需要使用者授權之後才能拿到。

而另一個是普通的access_token,支援公眾號的各種基礎服務,並非支付獨用。

看文件所述的流程,以為用網頁授權的token就對了?

恭喜,又進坑了…… 這裡我沒有遇到,不過還是在這裡給你們提個醒

坑三:怎麼獲取code

這個是我剛開始做這塊一直卡著的坎,微信文件中只是給了一個介面

一直以為是在後臺調取介面,然後返回code,如果你也這樣想,恭喜你,成功入坑,MD,這個介面你只有在前臺呼叫,並且redirect_uri上填寫後臺寫好的回撥方法,使用 urlEncode 對連結進行處理,並且這個方法只能是get請求。

===============================================================================

在這裡先給大家梳理一下總體流程,方便大家理解

前期的準備工作:

準備工作第一彈:

服務號一枚,並開通微信支付功能。

在微信公眾平臺(mp.weixin.qq.com)的[微信支付-開發配置]裡對支付授權目錄做配置。

測試期間,需要配置測試授權目錄,以及將參與測試的微訊號新增到白名單中。

由於測試必須在線上(測試)環境,debug不太方便,才耗費了辣麼多美好的時光。

授權目錄,即為呼叫微信支付控制元件的頁面(請注意這裡一定要是頁面,支付頁面所在的目錄)所在目錄。

準備工作第二彈:

還是在公眾平臺上,進入開發者中心,找到介面許可權表。

在其中的網頁服務中,找到“網頁授權使用者基本資訊”並填寫之。

這裡所填的URL必須是使用者進入應用的URL,且必須是oauth驗證所用的URL裡的redirect_uri裡的值……

一處不對,都會在坑裡苦熬良久。

準備工作第三彈:

還是在公眾平臺上,進入公眾號設定,找到功能設定。

需要對JS介面安全域名做設定。

這裡的安全域名就是你的應用相關的域名,改動次數受限制,要注意。

準備工作第四彈:

還是在公眾平臺上,在開發者中心裡找到配置項。

這裡需要有APPID和APPSecret的訪問許可權。

另外,還需要準備的是商戶id:mch_id 和 key。

注:secret  key 在通訊接口裡有用到,不允許在前端頁面使用!

接入的支付流程====================================

第一步驟:一個帶驗證的入口URI

首先引導使用者進入應用,這裡以H5頁面為例。

由於微信支付必須在微信瀏覽器裡進行,因此入口URL連結應當從公眾號釋出給使用者,

這樣使用者才會在微信客戶端中點選連結,進入應用。

(不要問京東為什麼可以在純網頁端使用微信支付,那是微信給他的小夥伴京東開的後門好嗎)

這個入口URL不是簡單的URL,這裡需要做oauth的驗證,因此我們暫設此URL為entranceURL。

entranceURL的格式為:

https://open.weixin.qq.com/connect/oauth2/authorize?appid=APPID&redirect_uri=REDIRECT_URI&response_type=code&scope=SCOPE&state=STATE#wechat_redirect

標紅的幾個變數需要說明:

1. APPID就是公眾號的appid

2. REDIRECT_URI很眼熟?就是剛在網頁授權裡寫的URI,要轉義哦親。

3. response_type須填code,理由是這是一個GET請求,微信會返回code然後用code再……blah blah blah

4. SCOPE,填snsapi_userinfo(需使用者手動授權)或snsapi_base(直接進入頁面)

5. STATE 會跟隨code一起返回,看業務需要自己填。一般格式是有大小寫和數字的組合。

參考文件:https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1421140842

第二步驟:用code獲取openId

使用者點選了這個entranceURL之後會發生什麼奇妙的事情咩?

這時候微信會返回給你一個code,並重定向到你在REDIRECT_URI裡指定的頁面。

你需要在這個頁面的URL裡拿到code的值,如果拿不到,要提示使用者授權失敗或未授權。

由於這個entranceURL可能是應用的首頁,而需要呼叫支付控制元件的是其他頁面,

所以可以先將其快取到例如sessionStorage裡,到了需要呼叫支付控制元件時再用。

拿到這個code需要做什麼咩?

這時候要做的事情就不能在前端頁面裡繼續進行了,這裡必須寫一個前後端通訊的介面,

將這個code傳送給後端伺服器,然後在伺服器裡發起對微信的GET請求:

https://api.weixin.qq.com/sns/oauth2/access_token?appid=我的appid&secret=我的secret&code=這個code&grant_type=authorization_code;

標紅的是需要被替換的變數,其中appidsecret都應該儲存在服務端檔案中。

這個請求返回的Json裡的openid就是我們要的。

參考文件:https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1421140842

第三步驟:統一下單介面

介面地址:https://api.mch.weixin.qq.com/pay/unifiedorder

參考文件:https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=9_1

這個介面在文件裡講得很清楚,在此不贅述。

注意這裡有簽名sign,它與後面要用的signaturepaySign雖然都是簽名,但完全不同。

如果你的trade_type是NATIVE就不需要openid,如果是JSAPI就必須要openid。

在統一下單的介面中,你會告訴微信當前這筆交易的一些基本資訊,

包括但不限於商戶id、交易號、交易金額等等。

微信會將其打包到一個package裡,從介面返回的prepay_id裡其實就對應了你的交易詳情。

注意這個介面返回的狀態碼有兩種,一個標識的是通訊是否成功:return_code

另一個標識的是業務是否成功:result_code。詳情見文件。

參考文件:https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=9_1

第四步驟:前端配置wx.config

在上一步介面的業務返回成功之後,可以在前端引用JSSDK了。

開發文件在:https://mp.weixin.qq.com/wiki/7/aaa137b55fb2e0456bf8dd9148dd613f.html

首先注入許可權驗證配置時,需要用到wx.config

它有幾個引數要格外注意,不然又進坑了:

1. 隨機字串nonceStr,必須使用上一步的統一下單介面返回的nonceStr。

2. 簽名signature,不是上步接口裡的sign,需在服務端生成,返給前端。(見下一步驟)

3. jsApiList 裡要指定微信支付介面“chooseWXPay”。

4. debug引數設為true時,會在移動端打出alert幫助除錯。

這裡也是個坑,微信文件在jssdk中給了一個微信支付,結果GG了。。。。。。。。。

參考文件:https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=7_7&index=6

第五步驟:服務端生成wx.config所需的signature

首先用appid和secret從微信基礎支援介面中獲取access_token

前面提到了兩個token:網頁授權型token和普通型token。

這裡獲取的是普通型token。

由於這個token是公眾號所有服務都可能用到的,因此要格外注意。

有效期7200s,建議過期之前應當快取之。

然後用這個token去獲取jsapi_ticket,介面地址:

https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token=" access_token "&type=jsapi

這個ticket同樣也要做快取。

現在可以準備生成signature了,所需的引數有:

1. jsapi_ticket

2. nonceStr 即統一下單介面返回的隨機字串

3. 時間戳:秒為單位(後續還會用到時間戳,要保持一致)

4. 當前頁面URL,不需轉義

注意這個簽名是用sha1演算法加密,其他的簽名是用MD5演算法加密的。

第六步驟:終於開始配置chooseWXPay

wx.config的驗證通過之後,就可以在wx.ready的回撥裡執行wx.chooseWXPay了。

chooseWXPay的幾個屬性配置說明如下:

1. timeStamp:剛才用到的那個時間戳,秒為單位。

2. nonceStr:統一下單接口裡的隨機字串

3. package:值的格式為“prepay_id=” 統一下單介面返回的prepay_id

4. signType:由於這裡的簽名是MD5加密,因此這個值就是“MD5”

5. paySign:呵呵,此處是坑,這個簽名也是在服務端生成,返給前端,見下一步驟。

6. success:支付成功後的回撥。

7. fail:支付失敗後的回撥。

8. cancel:使用者取消支付後的回撥。

這裡注意,由於進入應用時是帶著oauth驗證的,因此在使用者取消支付後,

code可能已過期,因此建議在取消支付的回撥裡,呼叫wx.closeWindow()退出Web頁返回微信客戶端。

因為即使你不退出,再執行支付,code之後的驗證也不會通過。

這時只能重新訪問一次第一步驟中的entranceURL才行。

第七步驟:生成chooseWXPay所需的簽名paySign

這個簽名不同於剛才在wx.config裡的簽名signature,這是用MD5加密的。

生成簽名所需引數有appidnonceStrpackagesignTypetimeStamp。(字典序排列)

其中nonceStr和package都是前面呼叫的統一下單的介面返回的。

這裡的signType是“MD5”.

另外,這個簽名拼合的時候,最後要加一個key,就是app的key。

key的排序在最後,排序不參與字典序。具體規則見官方文件。

第八步驟:線上測試

至此,萬事具備,包括東風。可以測試了。

建議使用iPhone手機測試,如果有問題IOS會報出錯資訊,Android不會。

最常見的問題就是“Invalid signature”,這個錯誤資訊太籠統了。

需要更細緻的除錯和辛勤的打Log。我在這個坑裡淌了兩天……

注:本地測試環境不能測試,必須釋出到線上測試環境(非生產環境),

並且線上測試環境的域名和URI等資訊都要在公眾號設定裡有授權

以上是微信支付的詳細流程,無論接入那個產品的支付,大體流程都是這個樣子,但是自己在做的時候一定要確定自己公司要接入的產品到底是哪個,比如公眾號支付、APP支付等。。