Java微信支付总结(一):获得prepay_id(以及生成微信支付签名)
默認你已經取得了微信支付相關的權限,并且有了商戶號,key值等等。
如果你一直簽名錯誤,請看上一篇帖子:http://blog.csdn.net/qq_25821067/article/details/55253399
要想獲取prepay_id,就必須要生成正確的簽名,一下是微信官方文檔說明https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=4_3:
1、
簽名算法------(簽名校驗工具)簽名生成的通用步驟如下:
第一步,設所有發送或者接收到的數據為集合M,將集合M內非空參數值的參數按照參數名ASCII碼從小到大排序(字典序),使用URL鍵值對的格式(即key1=value1&key2=value2…)拼接成字符串stringA。
特別注意以下重要規則:
第二步,在stringA最后拼接上key得到stringSignTemp字符串,并對stringSignTemp進行MD5運算,再將得到的字符串所有字符轉換為大寫,得到sign值signValue。
key設置路徑:微信商戶平臺(pay.weixin.qq.com)-->賬戶設置-->API安全-->密鑰設置
舉例:
假設傳送的參數如下:
appid: wxd930ea5d5a258f4f
mch_id: 10000100
device_info: 1000
body: test
nonce_str: ibuaiVcKdpRxkhJA
第一步:對參數按照key=value的格式,并按照參數名ASCII字典序排序如下:
stringA="appid=wxd930ea5d5a258f4f&body=test&device_info=1000&mch_id=10000100&nonce_str=ibuaiVcKdpRxkhJA";
第二步:拼接API密鑰:
stringSignTemp="stringA&key=192006250b4c09247ec02edce69f6a2d"
sign=MD5(stringSignTemp).toUpperCase()="9A0A8659F005D6984697E2CA0A9CF3B7"
最終得到最終發送的數據:
<xml>
<appid>wxd930ea5d5a258f4f</appid>
<mch_id>10000100</mch_id>
<device_info>1000<device_info>
<body>test</body>
<nonce_str>ibuaiVcKdpRxkhJA</nonce_str>
<sign>9A0A8659F005D6984697E2CA0A9CF3B7</sign>
<xml>
最開始的時候,第一次弄的話,先去微信支付接口調試出去輸入參數調試,微信支付接口調試網址:https://pay.weixin.qq.com/wiki/tools/signverify/。選擇設定需要的參數后點擊生成簽名,最下面就會出現一個xml格式的字符串。然后利用post方法提交到https://api.mch.weixin.qq.com/pay/unifiedorder。我是Java,我的方法就是把調試接口那個拼湊出一個xml格式的String字符串,然后提交。
我用到了httpclient 4.5.3這個框架。
核心的post代碼如下:
System.out.println("最終提交xml:"+xml);post.setEntity(new StringEntity(xml,"UTF-8"));HttpResponse execute = httpClient.execute(post);HttpEntity entity = execute.getEntity();String responseContent = EntityUtils.toString(entity,"utf-8");System.out.println("PayController index獲取到的總數據:"+responseContent); 上面那個xml變量,就是上面說的微信官方接口測試生成的xml格式的字符串,自己拼湊成串就行了。
post.setEntity(new StringEntity(xml,"UTF-8"));這一行特別重要,我之前就是少寫了UTF-8這個參數,結果一直報簽名錯誤。
然后返回內容大概如下:
<xml>
 ???<return_code><![CDATA[SUCCESS]]></return_code>
 ???<return_msg><![CDATA[OK]]></return_msg>
 ???<appid><![CDATA[wx2421b1c4370ec43b]]></appid>
 ???<mch_id><![CDATA[10000100]]></mch_id>
 ???<nonce_str><![CDATA[IITRi8Iabbblz1Jc]]></nonce_str>
 ???<openid><![CDATA[oUpF8uMuAJO_M2pxb1Q9zNjWeS6o]]></openid>
 ???<sign><![CDATA[7921E432F65EB8ED0CE9755F0E86D72F]]></sign>
 ???<result_code><![CDATA[SUCCESS]]></result_code>
 ???<prepay_id><![CDATA[wx201411101639507cbf6ffd8b0779950874]]></prepay_id>
 ???<trade_type><![CDATA[JSAPI]]></trade_type>
 </xml>
 就表明OK了。你從微信測試官方生成的提交的xml串一般是不回出現問題的,如果出現簽名錯誤,那估計就是我上一篇說的那個問題了。
如果獲得了正確的返回,那就是沒問題了,里面最重要的就是那個prepay_id。也是我們需要它的地方。
當然上面我們只是用了微信測試接口生成了sign簽名。下面馬上說生成簽名的方法。
/** * 微信支付簽名算法sign * @param characterEncoding * @param parameters * @return */ @Test public static String createSign(String characterEncoding,SortedMap<Object,Object> parameters){ StringBuffer sb = new StringBuffer(); Set es = parameters.entrySet();//所有參與傳參的參數按照accsii排序(升序) Iterator it = es.iterator(); while(it.hasNext()) { Map.Entry entry = (Map.Entry)it.next(); String k = (String)entry.getKey(); Object v = entry.getValue(); if(null != v && !"".equals(v) && !"sign".equals(k) && !"key".equals(k)) { sb.append(k + "=" + v + "&"); } } sb.append("key=" + WeChatPayUtils.key); System.out.println("字符串:"+sb.toString());String sign = MD5Util.MD5Encode(sb.toString(), characterEncoding).toUpperCase(); return sign; } MD5Util工具類代碼如下:
package cn.cqzdkj.utils;import java.security.MessageDigest;public class MD5Util {private static String byteArrayToHexString(byte b[]) {StringBuffer resultSb = new StringBuffer();for (int i = 0; i < b.length; i++)resultSb.append(byteToHexString(b[i]));return resultSb.toString();}private static String byteToHexString(byte b) {int n = b;if (n < 0)n += 256;int d1 = n / 16;int d2 = n % 16;return hexDigits[d1] + hexDigits[d2];}public static String MD5Encode(String origin, String charsetname) {String resultString = null;try {resultString = new String(origin);MessageDigest md = MessageDigest.getInstance("MD5");if (charsetname == null || "".equals(charsetname))resultString = byteArrayToHexString(md.digest(resultString.getBytes()));elseresultString = byteArrayToHexString(md.digest(resultString.getBytes(charsetname)));} catch (Exception exception) {}return resultString;}private static final String hexDigits[] = { "0", "1", "2", "3", "4", "5","6", "7", "8", "9", "a", "b", "c", "d", "e", "f" }; } 然后在需要的地方直接調用上面的ctreasign這個方法就行了。
SortedMap<Object,Object> parameters = new TreeMap<Object,Object>(); parameters.put("appid", appid); parameters.put("mch_id", mch_id);parameters.put("nonce_str",nonce_str); parameters.put("body", body); parameters.put("out_trade_no", "20170215");parameters.put("total_fee", 1);parameters.put("spbill_create_ip", "x.x.x.x");parameters.put("notify_url","http://xxxxx.com");parameters.put("trade_type", "JSAPI");parameters.put("openid", "oGY_ZvxxxxxM");parameters.put("sign","");String characterEncoding = "UTF-8"; String mySign = createSign(characterEncoding,parameters); System.out.println("我 的簽名是:"+mySign);
到上面就是生成簽名的方法。如果還有不懂的就留言評論吧,我這兩天也是走了很多坑。
 
總結
以上是生活随笔為你收集整理的Java微信支付总结(一):获得prepay_id(以及生成微信支付签名)的全部內容,希望文章能夠幫你解決所遇到的問題。
                            
                        - 上一篇: 做设计这么久,UED/UXD、IXD、G
 - 下一篇: python生成的exe反编译