微信支付很多坑,对于第一次开发来说又没人带真的是不断踩坑。本文主要讲一下自己做微信小程序后台(Java)的总结。
首先下载微信util工具类。
下载地址:https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=11_1
流程介绍官方文档:https://pay.weixin.qq.com/wiki/doc/api/wxa/wxa_api.php?chapter=7_4&index=3
依照流程图可以发现后台要做的事有:
小程序端请求中带有js_code,以js_code获取openid.
关键代码段:
// jscode2session_url为https\://api.weixin.qq.com/sns/jscode2session?appid\=APPID&secret\=SECRET&js_code\=JSCODE&grant_type\=authorization_code
String jscode2session_url = jscode2session.replace("APPID", appId).replace("SECRET", appKey).replace("JSCODE", js_code);//appId appKey js_code 分别为小程序appid 小程序appKey 及前台传的js_code值
HttpClient httpClient = new HttpClient(jscode2session_url);
httpClient.setHttps(true);
httpClient.get();
String resultXml = httpClient.getContent();
Map resultMap = JsonUtil.parseStringMap(resultXml);
String openid = str.get(resultMap, "openid");//获取到openid
参照官方文档参数规则:https://pay.weixin.qq.com/wiki/doc/api/wxa/wxa_api.php?chapter=4_2
官方文档:https://pay.weixin.qq.com/wiki/doc/api/wxa/wxa_api.php?chapter=9_1
友情提醒:
官方util工具提供签名方法,不需要纠结签名算法。
如果有兴趣,可以了解一下签名算法:https://pay.weixin.qq.com/wiki/doc/api/wxa/wxa_api.php?chapter=4_3
需要注意的是 notify_url 这个参数,如果微信支付成功后,后台需要有业务逻辑处理,那么这个参数值应填写后台给的外网可访问的接口。怎么处理后面说。
其次,统一下单调用成功后,需要二次签名!!!
关键代码段(包含二次签名):
try {
//设置参数
String ip = IpHelper.getIpAddr(request);
String appId = PropertiesUtil.getWxPropertiesValue("weixinpay.appid");//小程序appID
String mch_id = PropertiesUtil.getWxPropertiesValue("mch_id");//商户号
String shKey = PropertiesUtil.getWxPropertiesValue("mch_key");//商户号秘钥
Map param = new HashMap();
param.put("appid", appId);//小程序ID
param.put("mch_id", mch_id);//商户号
param.put("nonce_str", WXPayUtil.generateNonceStr());//随机字符串
param.put("body", "物业支付");//商品描述
param.put("out_trade_no", out_trade_no);//商户订单号
param.put("total_fee", total_fee);//金额,单位为分
param.put("sign_type", "MD5");//默认MD5加密
//param.put("total_fee", "1");//金额,单位为分
param.put("spbill_create_ip", ip);//终端IP:无强制要求
param.put("notify_url", "https://*************/applet/wxapply/wxhd.do");//通知地址:
param.put("trade_type", "JSAPI");//支付类型:JSAPI--JSAPI支付(或小程序支付)、NATIVE--Native支付、APP--app支付,MWEB--H5支付,不同trade_type决定了调起支付的方式
param.put("limit_pay", "no_credit");//指定支付方式:可限制用户不能使用信用卡支付
param.put("openid", openid);
//生成带签名的xml
String paramXml = WXPayUtil.generateSignedXml(param, shKey);
//调用接口链接
HttpClient httpClient = new HttpClient("https://api.mch.weixin.qq.com/pay/unifiedorder");
httpClient.setHttps(true);
httpClient.setXmlParam(paramXml);
httpClient.post();
String resultXml = httpClient.getContent();
Map resultMap = WXPayUtil.xmlToMap(resultXml);
logger.debug(" resultMap " + resultMap);
//二次签名,获取paySign
String time = Long.toString(System.currentTimeMillis()).substring(0, 10);//获取10位时间戳
Map signMap = new HashMap();
String pkg = "prepay_id="+resultMap.get("prepay_id");
signMap.put("appId", resultMap.get("appid"));
signMap.put("nonceStr", resultMap.get("nonce_str"));
signMap.put("package", pkg);
signMap.put("signType", "MD5");
signMap.put("timeStamp", time);
String paySign = WXPayUtil.generateSignature(signMap, shKey);
//返回结果内容重新封装
Map map = new HashMap();
map.put("prepay_id", resultMap.get("prepay_id"));
map.put("nonce_str", resultMap.get("nonce_str"));//随机字符串
map.put("package", pkg);
map.put("out_trade_no", out_trade_no);
map.put("total_fee", total_fee);
map.put("paySign", paySign);
map.put("timeStamp", time);
return map;
} catch (Exception e) {
e.printStackTrace();
return null;
}
然后小程序端调用支付,如果没有后续逻辑处理,那么后台任务就到此结束。如果后台有支付成功后的业务逻辑,那么就有了??
官方文档:https://pay.weixin.qq.com/wiki/doc/api/wxa/wxa_api.php?chapter=9_7&index=8
接收微信通知关键代码段:
//接收微信通知信息
BufferedReader reader = request.getReader();
String line = "";
StringBuffer inputString = new StringBuffer();
while ((line = reader.readLine()) != null) {
inputString.append(line);
}
request.getReader().close();
map = WXPayUtil.xmlToMap(inputString.toString());
//取参
String return_code = StringHelper.get(map, "return_code");//返回状态码
String result_code = StringHelper.get(map, "result_code");//业务结果
String total_fee = StringHelper.get(map, "total_fee");//付款金额(单位分)
String out_trade_no = StringHelper.get(map, "out_trade_no");//商户订单号
//后续业务逻辑代码
...........
至于期间各种报错,什么签名失败啊之类的各种错,首先一定要确保自己的小程序appid/key,和商户号id/商户号密钥是匹配的,包括小程序id和密钥的匹配,商户号id和密钥的匹配,和小程序是否绑定商户号。如果检查几遍后,确认是都匹配的,那么先重置一下商户号密钥吧。