親歷H5移動端遊戲微信支付接入及那些坑(三)——支付接入

終於到接入支付了,小小的一個微信支付,居然也寫了3篇,好長,好累。

接入環境

對接入環境,前端的話,應該是以JS爲主吧,也有可能是,PHP,JAVA,C++,或者C#都可以。爲什麼在此特意提一下接入環境呢,是因爲這裏又有一個小坑(真是對國內的SDK文檔無力吐槽了,接過大大小小無數的SDK,沒有幾個坑基本是不可能的,微信這種算大廠了,文檔整理的依舊和屎一樣)。

首先,如果你是按照正常流程,從其支付入口點進去看的文檔,一定不會和你提到jsapi_ticket這個東西,這個東西是當你是使用微信的js接口時,才需要的一個憑證(又是憑證,而且只有js需要,爲什麼?問微信吧,我也不知道爲什麼)。也就是說,如果你是PHP,C#等,是不用做這一步的,可以減少一點工作量,但JS的話,就一定要獲取這個東西。
然後悲催的是,關於這個東西的文檔,是被整合在微信的JS-SDK中(那你至少在支付文檔里加個連接跳轉,或是提一下呢?)

這個文檔,請從公衆平臺->開發者工具->開發這文檔->微信網頁開發進入閱讀
這裏附上JS-SDK的微信官方文檔地址

如果你使用JS開發,請無視微信支付文檔中的示例代碼,一切以JS-SDK中的支付接口爲準

(一)獲取普通類型access_token

爲了獲得jsapi_ticket,我們必須先獲得一個token,注意,這裏的token是在前一篇中提到的普通類型token。如何獲得呢,微信並沒有在支付文檔中給出,也沒有在JSSDK文檔中給出,藏在了公衆平臺->開發者工具->開發這文檔->開始開發->獲取access_token

https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=APPID&secret=APPSECRET

在該連接中填入公衆號id,和公衆號密鑰,然後使用GET方式,從http請求返回token。
這個token,每天獲取的次數是有限的(具體數量在公衆平臺的接口權限中可以查看),所以記得不要頻繁獲取,等到了過期時間再重新獲取。
不同於網頁授權access_token對應於每個用戶的授權,這是微信授權給我們後端,所以只有一個。

(二)獲取jsapi_ticket

前面說了,如果是js環境,需要首先獲取jsapi_ticket,然後才能正常調用微信接口。jsapi_ticket是公衆號用於調用微信JS接口的臨時票據,通過

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

該連接使用GET方式獲取。注意到這個連接中的token了嗎,就是第一步中獲得token。如果成功返回,就能得到jsapi_ticket,注意jsapi_ticket也是有時效性的。微信不建議頻繁刷新,所以注意保存。以備後用

(三)統一下單

在前端能夠調起JS的支付接口之前,前端應該通知後端,先請求下單,如果成功下單,才能進行第四步及後續步驟。然後,統一下單的文檔,又跳回原來的微信支付文檔了(呵呵,真是亂)。

統一下單地址

https://api.mch.weixin.qq.com/pay/unifiedorder

更加坑爹的是,在第一篇中介紹的兩種支付方式,微信瀏覽器內支付,和非微信瀏覽器支付,都是該地址,只是參數不同,所以真的會讓第一次接入的人很容易搞混亂

統一下單時,我們需要對以上地址傳遞參數,然後以http的POST方式請求,並得到下單結果。下面只挑幾個容易誤解的參數說明,其他請參考官方文檔

  • appid : 公衆號id,公衆號id,公衆號id
  • mch_id:商戶號,第一篇裏已經說過,請填和公衆號對應的商戶號,不是你的APP的商戶號,也不是你的網站的商戶號,是你的公衆號的商戶號
  • trade_type :第一篇裏也說明了,除非你進一步申請過,否則填JSAPI
  • nonce_str:隨機字符串,該字符串在第五步時需要被使用

    注:我接入時,網上找到一篇文章,說是第四步config中也是使用此處的noncestr,但在寫這篇文章的時候,我重新研讀了下文檔,我個人覺得其實該字符串僅和第五步中的保持一致即可。第四步可以重新生成。但是因爲頁面跳轉,或是安全性考慮,第四步中的config,可以考慮在每次支付前都重新配置,那麼這時可以將noncestr也用到第四步中。並不影響。但如果前端實現對一個jsapi_ticket值config只配置一次而不是每次支付前都配置一次的話,我覺得這個nonce_str是不用保持一致的。

  • sign_type:必須填MD5

(四)配置wx.config

如果使用JS接入,在前端執行微信的API時,必須預先配置一個wx.config對象。(其他環境不需要配置)
對wx.config配置說明其中幾個參數,剩餘的請參考文檔

  • nonceStr:隨機字符串,安全起見,最好是後端生成通知前端
  • timestamp:生成簽名的時間戳。由於簽名一般也是由服務器生成的,所以這個時間戳也是有後端通知前端
  • url:當前網頁的URL,不包含#及其後面部分,所謂當前網頁,就是你再配置這個wx.config的js代碼所在的前端頁面地址
  • signature:簽名,這個簽名必須要使用SHA1的算法,最好把結果轉成小寫。參與這個簽名的參數有noncestr,jsapi_ticket,timestamp,和url。其中noncestr和timestamp就是上面兩個由服務器計算返回的。

(五)調用支付接口

所謂的支付接口,實際是一個統一下單接口,如果統一下單成功,則會由微信拉起支付頁面,引導用戶完成支付,然後將支付結果通知我們的後臺,再由我們的後臺處理業務邏輯,並通知前端。具體的流程看官方文檔就可以理解,不再多加說明,此處主要對支付接口的調用做解釋。

支付接口wx.chooseWXPay中需要填幾個參數

  • timestamp:時間戳

    注:同前面的noncestr,有的文檔說是要保證,該值從統一下單開始,wx.Config,支付調用這幾個步驟時保持統一。當然,這三個地方統一肯定可以保證支付正常。但我進一步研讀代碼,此處的timestamp無需和config統一,因爲只是代表支付簽名生成時的時間戳

    另外要提的一點是這個時間戳是以UTC0爲標準時間的。我一開始也沒有注意,就直接用當前時間和1970/1/1零點的時間去計算,當然微信也沒有提示錯誤,我猜微信後臺並沒有驗證,只是作爲一個值記錄了。但是實際上,這個值在微信後臺應該是被作爲UTC0時區的值來算的,所以我把這個時間戳存到數據庫後,時間上都超前了好幾小時,這個問題我也是在接另一個支付SDK時發現的。

    var stamp = DateTime.Now .ToUniversalTime() - new DateTime(1970, 1, 1, 0, 0, 0);
  • nonceStr:隨機字符串,該隨機字符串必須是統一下單時使用的隨機字符串

  • package:統一下單接口返回的prepay_id,注意這裏值必須是prepay_id = xxxx形式,不能只寫xxxx
  • signType:下面支付簽名的簽名方式
  • paySign :支付簽名,這個必須使用MD5簽名算法,對上面4個參數進行簽名,安全起見,這個應該是後端生成然後告訴客戶端的。

(六)最後說明

保險起見,nonceStr請保持在統一下單,wx.Config和wx.chooseWXPay這幾個步驟中一致,因爲我目前就是這麼做並通過的。timeStamp保持在wx.Config和wx.chooseWXPay中一致

可以嘗試noncestr在統一下單和wx.chooseWXPay一致,和config不同
可以嘗試timestamp在config和chooseWXPay中不同

發佈了33 篇原創文章 · 獲贊 31 · 訪問量 18萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章