首頁  >  文章  >  微信小程式  >  微信公眾號支付開發全過程

微信公眾號支付開發全過程

高洛峰
高洛峰原創
2017-02-24 16:38:272947瀏覽

業務流程

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

用戶點擊一個支付按鈕-->{後台一大推處理}-->用戶看到了一個輸入密碼的介面,包含金額等一些資訊-->用戶輸入密碼後出來一個支付成功的頁面(這部分流程都是微信自己完成的,我們什麼都不用做)-->返回系統自己的頁面(總不能讓用戶一直看著一個支付完成的頁面吧。花了錢,正心疼的,趕緊跳轉~一會兒後悔了,申請退款怎麼整。做不做沒有啥關係,反正我還沒做呢)

2)調用統一下單接口獲取預付id

#3)H5調起微信支付的內建JS

4)支付完成後,微信回呼URL的處理

 

#看著大段的文字,是不是很不爽。忘記了在哪裡看到的一句話。 One picture instead  thousands of words. (圖中紅色部分是我們需要做的。好像也沒有多少

本文最主要的部分開始了(想直接看程式碼,貼上程式碼,你也不一定能看懂,不是說程式碼難,各種分離,各種類,不直接。 key0 還是得回來乖乖的對參數。笑話。的詳細說明。 ##appid ==應用ID==登陸微信公眾號後台-開發-基本配置

微信公眾號支付開發全過程mch_id == 微信支付商家號碼==登陸微信支付後台,即可看到

#device_info ==設備號碼==終端設備號碼(門市號碼或收銀設備ID),注意:PC網頁或公眾號碼內支付請傳"WEB"

body==商品描述==商品或支付單簡要描述(不知道是什麼鬼,沒關係,先隨便傳個字符串,隨便的傳個英文的字符串。你會為你這個時候的英明決定打個滿分。如果是中文,可能會遇到毫無頭緒的簽章錯誤,嚴重者開始懷疑人生)

trade_type==交易類型==取值如下:JSAPI,NATIVE,APP。

      ps:JSAPI--公眾號支付、NATIVE--原生掃碼支付、APP--app支付,統一下單接口trade_type的傳參可參考這裡。單獨的支付接口,不呼叫統一下單接口

nonce_str==隨機字串==隨機字串,不長於32位

       ps:小夥伴們可能會對nonce這個命名,很詔異,微信team的人,都是逗必嗎~。在我不懈的努力下,

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

 

notify_url==通知位址==接收微信支付非同步通知回呼位址,通知url必須為直接可存取的url,不能攜帶參數。 (這,取個什麼名字好呢。隨便起吧,反正一時半會也用不到)

out_trade_no==商家訂單號==商家系統內部的訂單號碼,32個字元內、可包含字母(每次看完微信的官方解釋就更迷茫了,有木有。沒關係,我就傳個1咋了。)

total_fee==總金額==訂單總金額,單位為分(為了公司的專案測試,還得自己掏銀子,1分錢也是錢啊。ps:這時候總會想起,一個同學說過,蒼蠅腿也是肉啊)

openid ==使用者識別==trade_type=JSAPI,此參數必傳,使用者在商家appid下的唯一識別。

還有最重要的一個,重要的角色總是會在最後登場。

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>
    XXX费用
    <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

#見證奇蹟的時刻。如果以上參數都神奇的對了,那麼會收到微信回傳的XML字串,格式如下

<xml>
  <return_code></return_code>
  <return_msg></return_msg>
  <appid></appid>
  <mch_id></mch_id>
  <device_info></device_info>
  <nonce_str></nonce_str>
  <sign></sign>
  <result_code></result_code>
  <prepay_id></prepay_id>
  <trade_type></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$.不要告訴我,只有我一個人。重新生成,在後台。使用如上4個參數+一個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.php.cn/

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>

对以上第一点和第三点做个解释。

再次吐槽一下。微信真的很喜欢用签名啊。整个过程,3遍签名。也是醉了。

1)我们看到上述微信返回的xml中含有很多字段。使用上述xml中,处sign意外的值+key,进行签名。你没有看错。包含result_code和return_code。

微信的官方对于签名有解释。

微信公眾號支付開發全過程

原谅我真的好久不学语文了。真的没理解这句话,是用微信回调函数中传的参数,进行重新签名。傻傻的,还在想,用第二次签名是的参数进行签名,时间戳怎么办,要不要存在数据库里面。

将获得的签名与xml中的sign对比,如果相同,证明是微信返回的通知。如果不同,你的通知地址可能被黑客破解了。要不要告诉老板呢,告诉老板了,我怎么解决呢。

 

2)商户逻辑处理,不解释

3)告诉微信,我收到了你的通知,不需要在发送了。

怎么告诉微信呢。我翻遍了微信的文档,也没有找到回复微信通知这个url。

经人知道,再一次的刷新了认知观。用response.

我是这么写的


 response.getWriter().write(xml);


这个xml就是微信给你的那个流转化的字符串。

xml中的return_code要是SUCCESS或者FAIL

别问我怎么知道的。官方的demo里面写的

if($notify->checkSign() == FALSE){
        $notify->setReturnParameter("return_code","FAIL");//返回状态码
        $notify->setReturnParameter("return_msg","签名失败");//返回信息
    }else{
        $notify->setReturnParameter("return_code","SUCCESS");//设置返回码
    }
    $returnXml = $notify->returnXml();

按照这个写法,返回的数据。在没有收到微信的通知。

之前在测试的时候,返回字符串之后,在没有收到微信的通知,这两天偶然查日志,发现,微信在一直的,通知,不一定是8次。从打印的日志看

有4次,6次。突然,好晕啊。有明白的朋友,还请多多指教

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

微信公众号支付--JSAPI的开发思路和一下参数的具体解释,全部完成了。具体代码。等我从公司项目里面抽出来。在整理。

还有一个坑:我们在第一步的时候,body传的是英文,如果传中文,直接能用的赶紧感谢一下上苍,返回参数错误的,应该是正常吧。

我的对象和xml转化是用的Java的JAXBContext。很好用的赶脚。赶脚比XMLStream好用。

更多微信公眾號支付開發全過程相关文章请关注PHP中文网!

陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn