這一篇開始對微信支付細節進行解釋和開發
1.擷取openid,這個比較簡單,上一篇已經講到,通過appid,appsecret請求微信接口擷取,具體看https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=4_4
2.設定測試授權目錄,這個目錄(也就是請求位址)就是你調用支付請求的位址。比如我調用支付的位址是http:/user/userPay.do,那麼測試授權目錄就填寫http:/user/即可,要注意大小寫要完全一緻
3.擷取微信版本号https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=7_5,這個步驟就是用來驗證使用者的微信版本支不支援微信支付功能
4.擷取預支付回話辨別prepay_id,擷取prepay_id,就是通過https協定,用POST方式,向微信統一下單接口https://api.mch.weixin.qq.com/pay/unifiedorder發送xml格式請求,傳回資料也是xml格式;
a.這是微信官方文檔所要求的請求參數清單

注意看參數清單,參數名稱都為小寫字母,而且有些參數是必填,有些是非必填的。
要注意的第一個參數是:簽名(sign),簽名的擷取就是對其他所有參數進行處理後的結果,具體操作如下
第一步,先把所有參數放到一個map中(要十分注意,這裡的參數名全是小寫!小寫!小寫)
<span style="font-family:SimSun;"><span style="font-size:18px;">Map map = new HashMap();
map.put("appid",appid);
map.put("mch_id",mch_id);
map.put("nonce_str",noncestr);
map.put("body","test");
map.put("out_trade_no",out_trade_no);
map.put("total_fee","1");
map.put("spbill_create_ip",add);
map.put("notify_url",notify_url);
map.put("trade_type","JSAPI");
//trade_type=JSAPI,此參數必傳,使用者在商戶appid下的唯一辨別</span>
<span style="white-space:pre"> </span> <span style="font-size:18px;">map.put("openid",openid);</span></span>
第二步,在工具類中建立一個擷取sign的方法
<span style="font-family:SimSun;font-size:18px;">public static String getSign(Map<String,Object> map){
ArrayList<String> list = new ArrayList<String>();
for(Map.Entry<String,Object> entry:map.entrySet()){
if(entry.getValue()!=""){
list.add(entry.getKey() + "=" + entry.getValue() + "&");
}
}
int size = list.size();
String [] arrayToSort = list.toArray(new String[size]);
Arrays.sort(arrayToSort, String.CASE_INSENSITIVE_ORDER);
StringBuilder sb = new StringBuilder();
for(int i = 0; i < size; i ++) {
sb.append(arrayToSort[i]);
}
String result = sb.toString();</span>
<span style="font-family:SimSun;font-size:18px;"><span style="white-space:pre"> </span><span style="background-color: rgb(255, 204, 153);">//這裡的key就是在微信支付商戶平台中的賬戶設定--API安全--設定秘鑰中設定</span>
result += "key=" + Constant.key;
result = MD5.MD5Encode(result).toUpperCase();
return result;
}</span>
這樣就可以獲得參數sign;
第二個要注意的參數是商戶訂單号,其實這個倒沒什麼難度的,官方文檔的解釋是:商戶系統内部的訂單号,32個字元内、可包含字母。我自己的做法是用10位的時間戳再加上22位的随機字元串。
第三個要注意的參數是open_id,當參數trade_type為JSAPI時,open_id必填,很多人也是忽略了這一點,導緻了簽名錯誤!!
b.參數了解清楚和擷取後,就可以構造xml格式資料請求微信統一下單接口https://api.mch.weixin.qq.com/pay/unifiedorder,必須是通過https協定,以POST方式請求
String xml="<xml>"+
"<appid>"+appid+"</appid>"+
"<mch_id>"+mch_id+"</mch_id>"+
"<nonce_str>"+noncestr+"</nonce_str>"+
"<body><![CDATA["+"test"+"]]></body>"+
"<out_trade_no>"+out_trade_no+"</out_trade_no>"+
//金額,這裡寫的1 分到時修改
"<total_fee>"+1+"</total_fee>"+
"<spbill_create_ip>"+add+"</spbill_create_ip>"+
"<notify_url>"+notify_url+"</notify_url>"+
"<trade_type>"+"JSAPI"+"</trade_type>"+
"<openid>"+openid+"</openid>"+
"<sign>"+signature+"</sign>"+
"</xml>";
如果請求的資料正确的話,就會出現xml傳回資料,其中就有我們需要的prepay_id,若是沒有成功傳回資料,肯定是參數錯誤、參數名大小寫問題,或者請求的方法不對,回頭細心檢查一下。(官方文檔也有列舉出錯誤代碼,可以對應不同的錯誤碼進行檢查https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=9_1)
(騰訊還自動識别了一個OK的表情,有點萌萌的)
好啦,這樣第一個難題就解決了。得到所需的prepay_id。
5.現在就可以進入網頁調用支付接口的步驟了。這是官方文檔:https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=7_7
問題來了,一定要千萬注意這裡的變量名,第二個單詞的首字母變成了大寫,就是這麼坑,不注意的話,等一下生成簽名就會報錯!!!
公衆号id,時間戳,随機字元串,簽名方式都不是難題,package的值就是我們上面擷取的prepay_id,送出格式如:prepay_id=***,簽名paysign的值,就是把對應的參數名和參數放到map裡,通過上面的擷取簽名的方法來獲得簽名。
這些參數都是我們在背景獲得,然後傳到前端調用,調用微信支付接口的方法,官方文檔已經給出來了:
如果參數計算正确的話,将會出現支付視窗
大功告成,但是很多人在這裡傳回的接口是get_brand_wcpay_request:fail,如果出現這個錯誤,基本是就是參數錯誤或者支付測試目錄填寫有誤!
第一次編輯,有點亂,大家将就着看吧。