前言:
其实小程序支付官网V2版本写的有点模糊了,主要是没具体代码的demo 哈哈 下面教大家一步一步的写
大体思路就是:
1.服务后台生成预支付交易单(也就是API列表里的统一下单)
2.对统一下单返回的结果进行加密才是小程序端的正确签名
1.组装好正确的参数去请求,返回正确预支付交易信息
1.1导入hutool包
写接口用的工具类hutool里面大部分都有为了省事,有一点点工具类还得自己写
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
<version>4.5.7</version>
</dependency>
1.2创建统一下单的参数
一定按照官网要求的参数名进行创建不要有驼峰命名,官网是啥参数就写成啥,这是所有的参数。
生成签名不需要sign这个参数所以先把它注释掉
Map<String,String> params = new HashMap<String,String>(10);
params.put("appid","");
params.put("mch_id","");
params.put("nonce_str","");
params.put("sign_type","");
params.put("body","");
params.put("out_trade_no","");
params.put("total_fee","");
params.put("spbill_create_ip","");
params.put("notify_url","");
//params.put("sign","自己生成的签名");
1.3 对上面的params的sign进行加密得到用到的签名
1.对参数按照key=value的格式,并按照参数名ASCII字典序排序(a–>b–>c),
2.然后转换成key=value&key1=value1
出来的效果就是这个样子 stringA=“appid=wxd930ea5d5a258f4f&body=test&device_info=1000…”;
3.注意这里生成签名不需要sign这个参数
4.最后拼接上商户key
//转换成key=value&key1=value1
String urlMap = MapUrlParamsUtils.sortMap(paramMap, wxBean.getPartnerKey());
//使用hutool SecureUtil进行MD5加密并转换成大写
String sign = SecureUtil.md5(urlMap).toUpperCase();
1.sortMap()这个方法就是对map参数进行拼接,ASCII字典序排序。具体代码如下:
/**
* 参数名ASCII字典序排序a->b->c
* 生成字符串末尾拼接商户key去支付的参数不需要商户key只有加密才用到
* @param map 这个map里的key没有sign
* @param partnerKey 商户key
* @return
*/
public static String sortMap(Map<String, Object> map, String partnerKey) {
if (map == null) {
return "";
}
TreeMap<String, Object> sort = MapUtil.sort(map);
StringBuffer sb = new StringBuffer();
for (Map.Entry<String, Object> entry : sort.entrySet()) {
//把商户key放到最后拼接
if (entry.getKey().equals("key")) {
continue;
}
sb.append(entry.getKey() + "=" + entry.getValue());
sb.append("&");
}
String s = sb.toString();
if (s.endsWith("&")) {
s = StrUtil.subBefore(s, "&", true);
}
s += "&key=" + partnerKey;
return s;
}
1.4 参数转换成xml的String字符串
至此已经得到签名了,把生成的签名put到上面的paramMap里面,使用hutool的XmlUtil并转换成xml的String类型
//put刚才生成的签名
paramMap.put("sign", sign);
/**
* 使用 XmlUtil把map转换成xml的String类型,出来的效果就是
* String xml = "<xml> <appid>aaa</appid><mch_id>bbb</mch_id>...</xml>"
*/
String xmlStr = XmlUtil.mapToXmlStr(paramMap, "xml");
1.5 对签名进行验证
用微信支付接口签名校验工具进行验证。如图所示
1.6发送统一下单的请求
用hutool里的HttpUtil发送请求
//发送请求(响应也是xml)
String responseXml = HttpUtil.post("统一下单url", xmlStr);
//再把响应的xml转换成map
Map<String, Object> responseMap = XmlUtil.xmlToMap(responseXml);
//也可以把响应也封装成对象,再用responseMap转换成对象
//...进行后续逻辑处理
String isSuccess = responseMap.get("return_msg").toString();
if("SUCCESS".equals(isSuccess )){
//prepay_id
//nonce_str
}
2.生成小程序支付所用到参数
2.1 提取responseMap里的prepay_id和nonce_str
先看一下官方文档的对nonceStr的解释是随机字符串,乍一看随机生成一个就行了。这里你再生成一个随机字符串就大错特错了,得使用上面responseMap里的nonce_str这个才行。太TM的坑了。
还有变量名 单单是小程序ID就有三种变量名 appid、app_id、appId 巨TM的坑
拼接好小程序支付用到的签名的参数 appId、timeStamp、nonceStr、package、signType,然后调用上面写的sortMap(Map map,String partnerKey)这个方法。
示例: appId=wxd678efh567hg6787&nonceStr=5K8264ILTKCH16CQ2502SI8ZNMTM67VS&package=prepay_id=wx2017033010242291fcfe0db70013231072&signType=MD5&timeStamp=1490840662&key=qazwsxedcrfvtgbyhnujmikolp111111
//nonceStr和package 这两个参数必须是统一下单返回的参数
Map<String,Object> WeChatAppletParam = new HashMap<>(5);
String timeStampStr = DateUtil.currentSeconds() + "";
WeChatAppletParam.put("appId","你的appid");
WeChatAppletParam.put("timeStamp", timeStampStr);
WeChatAppletParam.put("nonceStr",responseMap.get("nonce_str").toString());
// package 需要拼接prepay_id=
WeChatAppletParam.put("package","prepay_id="+responseMap.get("prepay_id").toString());
WeChatAppletParam.put("signType","MD5");
//转换成key=value&key1=value1
String urlMap = MyMapUtil.sortMap2Url(WeChatAppletParam , wxBean.getPartnerKey());
//小程序支付的签名就得到啦
String miniPaySign = SecureUtil.md5(urlMap).toUpperCase();
2.2 返回小程序所用的参数
小程序端的wx.requestPayment({})这个方法,需要用到 timeStamp、nonceStr、package、signType、paySign,这5个参数后台全部能返回
Map<String,String> result = new HashMap<String,String>(5);
result.put("timeStamp",timeStampStr);
result.put("nonceStr","上面responseMap里的nonce_str");
result.put("package","prepay_id="+"上面responseMap里的prepay_id");
result.put("signType","MD5");
result.put("paySign","上面的miniPaySign ");
return result;
我就是说个思路,不对的地方可以提出来,不懂的可以留言问我。其实V2版的也不难就是把参数拼接好然后发送Post请求就好了