Java微信支付总结(一):获得prepay_id(以及生成微信支付签名)
2017-02-16 11:57
381 查看
默认你已经取得了微信支付相关的权限,并且有了商户号,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:
签名算法------(签名校验工具)
签名生成的通用步骤如下:
第一步,设所有发送或者接收到的数据为集合M,将集合M内非空参数值的参数按照参数名ASCII码从小到大排序(字典序),使用URL键值对的格式(即key1=value1&key2=value2…)拼接成字符串stringA。
特别注意以下重要规则:
◆ 参数名ASCII码从小到大排序(字典序);
◆ 如果参数的值为空不参与签名;
◆ 参数名区分大小写;
◆ 验证调用返回或微信主动通知签名时,传送的sign参数不参与签名,将生成的签名与该sign值作校验。
◆ 微信接口可能增加字段,验证签名时必须支持增加的扩展字段
第二步,在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()));
else
resultString = 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);
到上面就是生成签名的方法。如果还有不懂的就留言评论吧,我这两天也是走了很多坑。
如果你一直签名错误,请看上一篇帖子: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。
特别注意以下重要规则:
◆ 参数名ASCII码从小到大排序(字典序);
◆ 如果参数的值为空不参与签名;
◆ 参数名区分大小写;
◆ 验证调用返回或微信主动通知签名时,传送的sign参数不参与签名,将生成的签名与该sign值作校验。
◆ 微信接口可能增加字段,验证签名时必须支持增加的扩展字段
第二步,在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()));
else
resultString = 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成功,前端公众号里调用jsapi提示支付验证签名失败
- [置顶] 【java】微信支付生成签名的过程
- java ID生成策略个人总结
- java 微信支付签名生成方法
- 03_Android NDK中C语言调用Java代码,javah的使用,javap的使用以及生成签名,Android.mk的编写,C代码的编写
- 【java】java反射机制,动态获取对象的属性和对应的参数值,并属性按照字典序排序,Field.setAccessible()方法的说明【可用于微信支付 签名生成】
- 微信支付获取prepay_id以及回调地址
- 在JAVA中查询刚插入的记录ID 利用JDBC的getGeneratedKeys获得INSERT插入后生成的主键ID
- 在JAVA中查询刚插入的记录ID 利用JDBC的getGeneratedKeys获得INSERT插入后生成的主键ID
- 如何集成android微信支付及各种问题(-1,签名错误,无法获得预支付id)的解决办法。
- 【java】微信支付生成签名的过程
- java/php/c#版rsa签名以及java验签实现openssl生成
- 03_Android NDK中C语言调用Java代码,javah的使用,javap的使用以及生成签名,Android.mk的编写,C代码的编写
- 解决微信支付获取prepay_id时,商品描述body为中文时报签名错误的问题
- 消息摘要、消息验证码以及用Java的工具生成数学证书签名
- java/php/c#版rsa签名以及java验签实现openssl生成
- WSE3.0构建Web服务安全(2):非对称加密、公钥、密钥、证书、签名的区别和联系以及X.509 证书的获得和管理
- JAVA基础学习总结---原码、补码、反码以及基本数据类型
- JAVA获得数字(正数和倒数)第几位的几种方法总结和对比
- asp.net Web Form 中获得服务器控件自动生成ID的方法