在Web應用中接入微信支付的流程之極簡清晰版

在Web應用中接入微信支付的流程之極簡清晰版

背景:php

在Web應用中接入微信支付,我覺得只是調用幾個API稍做調試便可。html

沒想到微信的API和官方文檔裏隱坑無數,致我抱着懷疑人生的心情悲憤踩遍了丫們佈下的全部坑。前端

簡要介紹幾個主要大坑:算法

坑一:關於WeixinJSBridge這個對象後端

查閱網頁端調起支付API的開發文檔,此對象即旁若無人的映入眼簾。api

而後咱們就理所應當的在代碼裏調用了丫的。瀏覽器

但是,too young too naive……緩存

儘管此對象只在微信瀏覽器裏有效,藉此可判斷用戶是否在微信瀏覽器裏訪問應用。安全

但其實調用了丫以後,你是沒有將來的……服務器

此坑所耗時間:1.5天。

坑二:幾個簽名的混淆

關於簽名的調試,網上各類哭嚎,很多人在簽名處調試多日無果。

那是由於整個工做流程中,涉及到了至少三個簽名,稍不當心就會用錯。

在統一下單的接口裏,向微信服務器發送請求中的參數有一枚簽名;

其返回的參數中,亦有一枚簽名,後經觀察,發現兩者爲同一簽名。

但在使用JSSDK後所調用的wx.config裏所需的參數signature倒是另外一枚簽名。

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

此坑所耗時間:2天。

坑三:兩個Access_token

查看開發文檔能夠看到,微信搞了兩個Access_token!

即便他們用再多的加粗文字來提醒咱們兩個token的不一樣之處,

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

一個是網頁受權的access_token,須要用戶受權以後才能拿到。

而另外一個是普通的access_token,支持公衆號的各類基礎服務,並不是支付獨用。

看文檔所述的流程,覺得用網頁受權的token就對了?

恭喜,又進坑了……

最後真正用到的是第二個token。

此坑所耗時間:1.5天。

…………

坑坑相套,防不勝防。最終跑通功能後,心力交瘁矣!

爲防之後再次進坑,在此總結一番,供各位參考。

背景畢。

 

———————————————— 我是悲憤不已的分割線 ————————————————

 

準備工做第一彈:

公衆號一枚,並開通微信支付功能。

在微信公衆平臺(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一塊兒返回,看業務須要本身填。通常格式是有大小寫和數字的組合。

 

第二步驟:用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://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。詳情見文檔。

 

第四步驟:前端配置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幫助調試。

 

第五步驟:服務端生成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等信息都要在公衆號設置裏有受權

 

———————————————— 我是蠢蠢欲動的分割線 ————————————————

 

如此看來,流程清晰多了,也無甚難處。

可當初作開發和調試時,由於對後端語言不熟,耗費了不少時間,

用JS三秒寫出的方法,用後端語言寫就頻繁報錯,

什麼也不說了,只恨本身讀書少。

最後感謝在此過程當中提供語法指點的盆友。

相關文章
相關標籤/搜索