Java微信支付总结(一):获得prepay_id(以及生成微信支付签名)
默認(rèn)你已經(jīng)取得了微信支付相關(guān)的權(quán)限,并且有了商戶號(hào),key值等等。
如果你一直簽名錯(cuò)誤,請(qǐng)看上一篇帖子: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、
簽名算法------(簽名校驗(yàn)工具)簽名生成的通用步驟如下:
第一步,設(shè)所有發(fā)送或者接收到的數(shù)據(jù)為集合M,將集合M內(nèi)非空參數(shù)值的參數(shù)按照參數(shù)名ASCII碼從小到大排序(字典序),使用URL鍵值對(duì)的格式(即key1=value1&key2=value2…)拼接成字符串stringA。
特別注意以下重要規(guī)則:
第二步,在stringA最后拼接上key得到stringSignTemp字符串,并對(duì)stringSignTemp進(jìn)行MD5運(yùn)算,再將得到的字符串所有字符轉(zhuǎn)換為大寫,得到sign值signValue。
key設(shè)置路徑:微信商戶平臺(tái)(pay.weixin.qq.com)-->賬戶設(shè)置-->API安全-->密鑰設(shè)置
舉例:
假設(shè)傳送的參數(shù)如下:
appid: wxd930ea5d5a258f4f
mch_id: 10000100
device_info: 1000
body: test
nonce_str: ibuaiVcKdpRxkhJA
第一步:對(duì)參數(shù)按照key=value的格式,并按照參數(shù)名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"
最終得到最終發(fā)送的數(shù)據(jù):
<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>
最開始的時(shí)候,第一次弄的話,先去微信支付接口調(diào)試出去輸入?yún)?shù)調(diào)試,微信支付接口調(diào)試網(wǎng)址:https://pay.weixin.qq.com/wiki/tools/signverify/。選擇設(shè)定需要的參數(shù)后點(diǎn)擊生成簽名,最下面就會(huì)出現(xiàn)一個(gè)xml格式的字符串。然后利用post方法提交到https://api.mch.weixin.qq.com/pay/unifiedorder。我是Java,我的方法就是把調(diào)試接口那個(gè)拼湊出一個(gè)xml格式的String字符串,然后提交。
我用到了httpclient 4.5.3這個(gè)框架。
核心的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獲取到的總數(shù)據(jù):"+responseContent); 上面那個(gè)xml變量,就是上面說的微信官方接口測(cè)試生成的xml格式的字符串,自己拼湊成串就行了。
post.setEntity(new StringEntity(xml,"UTF-8"));這一行特別重要,我之前就是少寫了UTF-8這個(gè)參數(shù),結(jié)果一直報(bào)簽名錯(cuò)誤。
然后返回內(nèi)容大概如下:
<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了。你從微信測(cè)試官方生成的提交的xml串一般是不回出現(xiàn)問題的,如果出現(xiàn)簽名錯(cuò)誤,那估計(jì)就是我上一篇說的那個(gè)問題了。
如果獲得了正確的返回,那就是沒問題了,里面最重要的就是那個(gè)prepay_id。也是我們需要它的地方。
當(dāng)然上面我們只是用了微信測(cè)試接口生成了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();//所有參與傳參的參數(shù)按照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" }; } 然后在需要的地方直接調(diào)用上面的ctreasign這個(gè)方法就行了。
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);
到上面就是生成簽名的方法。如果還有不懂的就留言評(píng)論吧,我這兩天也是走了很多坑。
總結(jié)
以上是生活随笔為你收集整理的Java微信支付总结(一):获得prepay_id(以及生成微信支付签名)的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 做设计这么久,UED/UXD、IXD、G
- 下一篇: python生成的exe反编译