1. 程式人生 > >微信公眾號開發的全過程---Java

微信公眾號開發的全過程---Java

按照慣例,開頭總得寫點感想

------------------------------------------------------------------

業務流程

這個微信官網說的還是很詳細的,還配了圖。我還要再說一遍。

使用者點選一個支付按鈕-->{後臺一大推處理}-->使用者看到了一個輸入密碼的介面,包含金額等一些資訊-->使用者輸入密碼後出來一個支付成功的頁面(這部分流程都是微信自己完成的,我們什麼都不用做)-->返回系統自己的頁面(總不能讓使用者一直看著一個支付完成的頁面吧。花了錢,正心疼的,趕緊跳轉啊~一會後悔了,申請退款怎麼整。可憐的工程師還得開發退款功能)

開發流程

1)獲取使用者授權(這個做不做沒有啥關係,反正我還沒做呢) 2)呼叫統一下單介面獲取預支付id 3)H5調起微信支付的內建JS 4)支付完成後,微信回撥URL的處理 看著大段的文字,是不是很不爽。忘記了在哪裡看到的一句話。One picture instead  thousands of words. (圖中紅色部分是我們需要做的。好像也沒有多少) 本文最主要的部分開始了(想直接看程式碼,貼上程式碼,你也不一定能看懂,不是說程式碼難,各種分離,各種類,不直接。看懂了,不一定能除錯通。最後一個簽名錯誤,或者$get_brand_wcpay_request:fail.$key0 還是得回來乖乖的對引數。)最近學習英語有點魔怔了。各種插入語。不懂什麼梗的,可略過。朋友一直說我的笑點和別人不一樣。文後會講個笑話。 1、生成統一下單介面,獲取prepay_id.
需要的引數 ==名稱==從哪裡找到他們: 微信官方給了個引數的詳細說明。https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=9_1 部分引數,仍然不知道哪裡找的小夥伴們請繼續向下看 appid ==應用ID==登陸微信公眾號後臺-開發-基本配置 mch_id == 微信支付商戶號==登陸微信支付後臺,即可看到 device_info==裝置號==終端裝置號(門店號或收銀裝置ID),注意:PC網頁或公眾號內支付請傳"WEB" body==商品描述==商品或支付單簡要描述(不知道是什麼鬼,沒關係,先隨便傳個字串,隨便的傳個英文的字串。你會為你這個時候的英明決定打個滿分。如果是中文,可能會遇到毫無頭緒的簽名錯誤,嚴重者開始懷疑人生) trade_type
==交易型別==取值如下:JSAPI,NATIVE,APP。我們這裡使用的JSAPI。標題已經說了,是微信公眾號支付。他們的區別,請參考https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=4_2       ps:JSAPI--公眾號支付、NATIVE--原生掃碼支付、APP--app支付,統一下單介面trade_type的傳參可參考這裡。MICROPAY--刷卡支付,刷卡支付有單獨的支付介面,不呼叫統一下單介面 nonce_str==隨機字串==隨機字串,不長於32位(參考演算法https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=4_3)        ps:小夥伴們可能會對nonce這個命名,很詫異,微信team的人,都是逗必嗎~。查了一下百科,隨機數也用nonce表示。瞬間傷害滿滿的。(好奇的寶寶可用劍橋詞典查一下nonce的意思)。在我的不懈努力下,

      發現了這個。nonce ==number used once.恍然大悟的趕腳。

notify_url==通知地址==接收微信支付非同步通知回撥地址,通知url必須為直接可訪問的url,不能攜帶引數。(這,起個什麼名字好呢。隨便起吧,反正一時半會也用不到) out_trade_no==商戶訂單號==商戶系統內部的訂單號,32個字元內、可包含字母(參考:https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=4_2)(每次看完微信的官方解釋就更迷茫了,有木有。沒關係,我就傳個1咋了。) total_fee==總金額==訂單總金額,單位為分(為了公司的專案測試,還得自己掏銀子,1分錢也是錢啊。ps:這個時候總會想起,一個同學說過,蒼蠅腿也是肉啊) openid==使用者標識==trade_type=JSAPI,此引數必傳,使用者在商戶appid下的唯一標識。(要是不知道這個從哪裡來的話,沒關係。微信不是給咱寫文件了嗎https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=4_4) 還有最最重要的一個,重要的角色總要在最後登場。 sign==簽名==官方給的簽名演算法。https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=4_3。沒有看懂,看不太懂,你覺得你看懂了,沒關係,不遇到幾次簽名錯誤,好意思說自己做過微信支付開發嗎。 說道這個sign還有一個更重要的引數。參與簽名的引數。反正我是找了好久才找到。(公司運營申請的微信支付,當我找她要的時候,他的表情是這樣子的。key==key設定路徑:微信商戶平臺(pay.weixin.qq.com)-->賬戶設定-->API安全-->金鑰設定 在這裡: 網上有說怎麼找得。我也懶得去找。直接自己想了一個字串,然後用MD5加密成32位的字串,重新設定的。 生成sign簽名的時候,要用到這個key值,所以,要儲存好。 我看別人生成簽名(sign)用了很多,反正我就用了上面給出的那些引數生成的sign.(這個上面指的是我的部落格上面,不是微信上面。為了減少誤解,貼出我生成sign簽名的引數) 我生成sign簽名的引數 準備好以上引數之後,封裝成XML 格式如下: 複製程式碼
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<xml>
    <appid>wxb1427ebebexxxxxx</appid>
    <body>XXX費用</body>
    <device_info>WEB</device_info>
    <mch_id>132186xxxx</mch_id>
    <nonce_str>6AED000AF86A084F9CB0264161E29DD3</nonce_str>
    <notify_url>https://一個域名/api/wechatPay/jsapiPayNotify</notify_url>
    <openid>oo8WUt0taCqjt552htW1vw-xxxxx</openid>
    <out_trade_no>1</out_trade_no>
    <sign>各種排序+key生成的那個sign</sign>
    <total_fee>1</total_fee>
    <trade_type>JSAPI</trade_type>
</xml>
複製程式碼 呼叫微信的統一下單地址:https://api.mch.weixin.qq.com/pay/unifiedorder NB: =================劃重點beign==20170728增加============ 呼叫統一下單地址時傳的引數個引數名稱和引數值與生成簽名時相比,           ★   呼叫統一下單時多了一個sign的引數,其他引數名稱需要全部相同。           ★   呼叫統一下單時多了一個sign的引數,其他引數名稱需要全部相同。           ★   呼叫統一下單時多了一個sign的引數,其他引數名稱需要全部相同。    nonce_str的值可以不同 獲取預支付ID時,如果返回值是【簽名錯誤】。那真是的你的簽名錯了,請仔細核對生成sign的引數名稱、引數值和呼叫統一下單介面的引數名稱和引數值 =================劃重點end==20170728增加============  見證奇蹟的時刻。如果以上引數都神奇的對了,那麼會收到微信返回的XML字串,格式如下 複製程式碼
<xml>
  <return_code><![CDATA[SUCCESS]]></return_code>
  <return_msg><![CDATA[OK]]></return_msg>
  <appid><![CDATA[wxb1427ebebexxxxxx]]></appid>
  <mch_id><![CDATA[132186xxxx]]></mch_id>
  <device_info><![CDATA[WEB]]></device_info>
  <nonce_str><![CDATA[Hh4LFHUUvtDYtNdp]]></nonce_str>
  <sign><![CDATA[079F8A915FD3044F4A17D75F4945E955]]></sign>
  <result_code><![CDATA[SUCCESS]]></result_code>
  <prepay_id><![CDATA[wx20160617155030d9e6a0e48b0533061255]]></prepay_id>
  <trade_type><![CDATA[JSAPI]]></trade_type>
</xml>
複製程式碼

我們需要的,就是這貨

prepay_id

獲取到這貨之後,第一步驟已經結束了,可以去喝個茶,吃個冰棍,小慶祝一下。

2、H5調起微信支付的內建JS
 後臺傳回前臺的引數中,應包含以下幾項: appId==這個是不變的==永遠不變 timeStamp==時間戳==規則:https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=4_2。看完仍是一臉迷茫的,沒關係,我們有工具類。誰知道呢,直接呼叫就好了

nonceStr ==反正我用的跟剛才簽名是同一個隨機字串。理論上不用應該也沒有關係的,勤快的小夥伴可以試試

package==訂單詳情擴充套件字串==統一下單介面返回的prepay_id引數值,提交格式如:prepay_id=***(你猜對了。剛才我們費那麼大力氣,獲得到的prepay_id就是在這裡用的。第一次使用的時候,一直拿訂單ID去請求,然後微信給我的資訊就是請求引數錯誤,缺少引數$key0$.不要告訴我,只有我一個人。) signType==簽名方式==簽名演算法,暫支援MD5 paySign==簽名==這個簽名,要重新生成,在後臺。使用如上4個引數 5個引數+一個key(永遠不變)。(我生成簽名的時間戳和傳回給前臺的時間戳就是timeStamp是同一個。不一樣行不行,木有驗證) 生成paySign的程式碼

NB:生成prepay_id時appid是小寫的i,生成paySign時,appId是大寫的I

到此為止如果一切順利,你會看到這樣子的一個頁面。 但是如果,你沒有看到這個。而是提示,目錄未授權,或者測試賬號未在白名單中,我覺得,這才是這篇部落格的正確開啟方式呢。 微信公眾號後臺,微信支付,開發配置中有一個支付授權目錄,測試授權目錄,  支付授權目錄:開發時,先放一放。(鄧小平爺爺在對待中日關係時曾經說過,我們解決不了的問題,先放一放。) 測試授權目錄:我們要填寫的就是這個了。要一個外網能訪問到的地址。ip也可以(親測可以的)。如果你的ip,外網不能訪問,找運維同學解決。建議,配置一個測試用的外網可訪問的域名。 測試白名單:這個不解釋 輸入密碼,然後,就會看到這樣子的結果。(這也不需要我們做什麼了) 好激動啊,趕緊去吃點東西,抑制一下,內心的激動。 剩下的,我們還有兩件事情要去做。先說簡單的。 3、支付成功之後跳轉回自己的系統的某個頁面 複製程式碼
function onBridgeReady(){
   WeixinJSBridge.invoke(
       'getBrandWCPayRequest', {
           "appId" : appId,       //公眾號名稱,由商戶傳入
           "timeStamp":timeStamp, //時間戳,自1970年以來的秒數     
           "nonceStr" : nonceStr, //隨機串     
           "package" : Package,     
           "signType" :signType,  //微信簽名方式:     
           "paySign" : paySign     //微信簽名 

       },
       function(res){ 
           if(res.err_msg == "get_brand_wcpay_request:ok" ) {
               window.location.replace("index.html");
           }
       }
   ); 
}
複製程式碼

上述程式碼中的,紅色部分,修改成你想去的頁面即可。是不是好奇replace是什麼鬼。移步這裡,看一下:http://www.xuebuyuan.com/2140432.html

4,最後一部分啦。fighting

該部分有以下3小步驟

    1)解析傳過來的流資訊,通過重新簽名的方式驗證流中包含的資訊的正確性。就是判斷這個資訊到底是不是微信發的

    2)return_code和result_code都是SUCCESS的話,處理商戶自己的業務邏輯。就是訂單的支付狀態啊等一些資訊。

    3)告訴微信,我收到你的返回值了。不用在發了。

關於以上三點的解釋。微信官方是這麼說的

複製程式碼
//支付完成後,微信會把相關支付和使用者資訊傳送到商戶設定的通知URL,
//驗證簽名,並回應微信。
//對後臺通知互動時,如果微信收到商戶的應答不是成功或超時,微信認為通知失敗,
//微信會通過一定的策略(如30分鐘共8次)定期重新發起通知,
//儘可能提高通知的成功率,但微信不保證通知最終能成功。

//商戶自行增加處理流程,
//例如:更新訂單狀態
//例如:資料庫操作
//例如:推送支付完成資訊
複製程式碼

還記得我們在第一步生成預支付id(prepay_id時的那個notify_url嗎。如果不記得了,請往上翻。如果當時只是隨便寫了一個,那麼這會需要去改一改了。)

一個能訪問的到的action.同樣地址需要外網能訪問的到。沒有試ip好不好使。開發這部分功能的時候,運維同學已經配置了測試域名。好開心啊,終於不用在糾結於一些互動配置了。

和支付寶不同,微信返回的是流。和支付寶不同,微信返回的是流。和支付寶不同,微信返回的是流。重要的事情說三遍

解析之後,得到的格式是這樣子的

複製程式碼
<xml><appid><![CDATA[wxb1427ebebeeaxxxx]]></appid>
<bank_type><![CDATA[CFT]]></bank_type>
<cash_fee><![CDATA[1]]></cash_fee>
<device_info><![CDATA[WEB]]></device_info>
<fee_type><![CDATA[CNY]]></fee_type>
<is_subscribe><![CDATA[Y]]></is_subscribe>
<mch_id><![CDATA[132186xxxx]]></mch_id>
<nonce_str><![CDATA[07FC15C9D169EE48573EDD749D25945D]]></nonce_str>
<openid><![CDATA[oo8WUt0taCqjt552htW1vw-xxxxx]]></openid>
<out_trade_no><![CDATA[你的訂單編號]]></out_trade_no>
<result_code><![CDATA[SUCCESS]]></result_code>
<return_code><![CDATA[SUCCESS]]></return_code>
<sign><![CDATA[E69940B3EDC437CB5A181210D523806E]]></sign>
<time_end><![CDATA[20160621134204]]></time_end>
<total_fee>1</total_fee>
<trade_type><![CDATA[JSAPI]]></trade_type>
<transaction_id><![CDATA[400386200120160621763973xxxx]]></transaction_id>
</xml>
複製程式碼

==========================================20170726更新====================================

微信目前有鼓勵金支付,在支付過程中支付金額大於鼓勵金金額既可以使用。如果在支付時使用了鼓勵金,則回撥的流的xml格式如下

複製程式碼
<xml>
<appid><![CDATA[XXXXXX]]></appid>
<bank_type><![CDATA[CFT]]></bank_type>
<cash_fee><![CDATA[1]]></cash_fee>
<coupon_count><![CDATA[1]]></coupon_count>
<coupon_fee>30</coupon_fee>
<coupon_fee_0><![CDATA[30]]></coupon_fee_0>
<coupon_id_0><![CDATA[2000000001082991244]]></coupon_id_0>
<device_info><![CDATA[WEB]]></device_info>
<fee_type><![CDATA[CNY]]></fee_type>
<is_subscribe><![CDATA[Y]]></is_subscribe>
<mch_id><![CDATA[1321867101]]></mch_id>
<nonce_str><![CDATA[D0AC1ED0C5CB9ECBCA3D2496EC1AD984]]></nonce_str>
<openid><![CDATA[oo8WUt0AjI8G9TNb5W3wmGUxVV1U]]></openid>
<out_trade_no><![CDATA[XXXXXX]]></out_trade_no>
<result_code><![CDATA[SUCCESS]]></result_code>
<return_code>