关于微信小程序支付(java后台部分)

不得不说微信支付是真坑

  • 微信支付
    • 微信支付流程
      • 1.获取openid
      • 2.生成随机不重复的商户订单
      • 3.调用统一下单API(二次签名)
      • 4.处理微信支付通知。
      • 5.问题。

微信支付

微信支付很多坑,对于第一次开发来说又没人带真的是不断踩坑。本文主要讲一下自己做微信小程序后台(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
依照流程图可以发现后台要做的事有:

1.获取openid

小程序端请求中带有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

2.生成随机不重复的商户订单

参照官方文档参数规则:https://pay.weixin.qq.com/wiki/doc/api/wxa/wxa_api.php?chapter=4_2

3.调用统一下单API(二次签名)

官方文档: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;
		}

然后小程序端调用支付,如果没有后续逻辑处理,那么后台任务就到此结束。如果后台有支付成功后的业务逻辑,那么就有了??

4.处理微信支付通知。

官方文档: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");//商户订单号
	//后续业务逻辑代码
	...........

5.问题。

至于期间各种报错,什么签名失败啊之类的各种错,首先一定要确保自己的小程序appid/key,和商户号id/商户号密钥是匹配的,包括小程序id和密钥的匹配,商户号id和密钥的匹配,和小程序是否绑定商户号。如果检查几遍后,确认是都匹配的,那么先重置一下商户号密钥吧。

你可能感兴趣的:(Java)