最近公司要上微信H5支付,但是听说微信的H5支付还在测试阶段,审核了好久,就开始开发了,过程中遇到好多坑,我就记录下来吧!!!
1.首先,按照接口流程图,需要先统一下单,这步没什么好说的,按照接口文档来。。。
注意:交易类型:trade_type=MWEB
2.获取到的支付中间页 mweb_url 返回到前端,前段获取到之后,链接到微信服务端,但是微信服务端需要权限校验,这是我遇到坑最多的地方
第一个:
我开始用公司的网络测试,试了好几次都是这个错误,后来才反应过来,电脑连的是公司的局域网,微信服务器访问不了我的IP,囧~
第二个就是,发起支付的服务器域名与申请的域名不一致,报错,因为用的是测试服务器,申请的服务器域名又是生产上的,所以又要微信那边添加上测试的服务器域名。。。
还好这些微信的接口文档里都有说明,网上资料好少~
上点代码:
private Map getHashMap2SignFromRequestUnifiedOrderBean(String hotelName, String create_ip,
BigDecimal total_fee, String orderNo) {
Map hashMap = new HashMap<>();
String totalFee = total_fee.multiply(BigDecimal.valueOf(100))
.setScale(0, BigDecimal.ROUND_HALF_UP).toString();
hashMap.put("appid", WxpayConfig.appid);
hashMap.put("body",WxpayConfig.webapp_body+"-"+ hotelName);
hashMap.put("mch_id", WxpayConfig.mch_id);
hashMap.put("nonce_str", WxpayUtils.getNonceStr());
hashMap.put("notify_url",WxpayConfig.notify_url);
hashMap.put("out_trade_no", orderNo);
hashMap.put("total_fee", totalFee);
hashMap.put("spbill_create_ip", create_ip);
hashMap.put("trade_type", "MWEB");
return hashMap;
}
统一下单成功后,返回前端:
if ("SUCCESS".equals(resultMap.get("result_code"))) {
Map hashMap2Sign = new HashMap<>();
hashMap2Sign.put("appid", hashMap.get("appid"));
hashMap2Sign.put("timestamp", WxpayUtils.payTimestamp());
hashMap2Sign.put("noncestr", hashMap.get("nonce_str"));
hashMap2Sign.put("mweb_url", hashMap.get("mweb_url"));
logger.info(hashMap2Sign.toString());
return JsonUtils.objectToJson(hashMap2Sign);
}else{
logger.error("统一下单交易失败",resultMap.get("err_code")+":"+resultMap.get("err_code_des"));
return null;
}
支付成功后,微信回调notify_url返回支付结果。
*/
@RequestMapping("/wechatPayNotify")
public @ResponseBody String wechatpayNotify(HttpServletRequest request){
logger.info("notify come!");
try {
return wxpayService.wechatPayNotify(request);
} catch (Exception e) {
logger.error("/wechatPayment/wechatPayNotify:",e);
Map returnMap = new HashMap();
returnMap.put("return_code", NormalUtil.FAIL);
returnMap.put("return_msg", e.getMessage());
return XmlUtil.xmlFormat(returnMap, false);
}
}
// 读取入参
Map returnMap = new HashMap();
StringBuilder sb = new StringBuilder();
BufferedReader br = null;
try {
br = new BufferedReader(new InputStreamReader(
(ServletInputStream) request.getInputStream()));
String line = null;
while ((line = br.readLine()) != null) {
sb.append(line);
}
logger.info("request:" + sb);
} catch (Exception e) {
logger.error("微信支付回调读取入参发生异常.直接返回更新失败", e);
System.out.println("微信支付回调读取入参发生异常.直接返回更新失败");
returnMap.put("return_code", NormalUtil.FAIL);
returnMap.put("return_msg", "unknown");
return XmlUtil.xmlFormat(returnMap, false);
} finally {
if (null != br) {
br.close();
}
}
Map resultMap = XmlUtil.xmlParse(sb.toString());
logger.info("notify info:" + resultMap.toString());
String out_trade_no = resultMap.get("out_trade_no");// 商户订单号
String trade_no = resultMap.get("transaction_id");// 交易流水号
String total_fee = resultMap.get("total_fee");// 订单总金额
String appid = resultMap.get("appid");//微信开放平台审核通过的应用APPID
String mch_id = resultMap.get("mch_id");//微信支付分配的商户号
if (CollectionUtil.isNotEmpty(resultMap)
&& "SUCCESS".equals(resultMap.get("return_code"))
&& "SUCCESS".equals(resultMap.get("result_code"))) {// 支付成功
if (checkSign(resultMap)) {
//查询此订单是否已支付。。。
boolean status = checkStatusAndRsa(receipt_amount,mch_id,appid);
logger.info("验证成功,去更新状态 \t订单号:" + out_trade_no + "来自微信,更新结果:" + status);
if(status){
//根据订单号(out_trade_no)在商户网站的订单系统中查到该笔订单的详细,并执行商户的业务程序
}else{
returnMap.put("return_code", NormalUtil.FAIL);
returnMap.put("return_msg", "API返回的数据不正确,有可能被第三方篡改");
return XmlUtil.xmlFormat(returnMap, false);
}
} else {
returnMap.put("return_code", NormalUtil.FAIL);
returnMap.put("return_msg", "验签失败");
return XmlUtil.xmlFormat(returnMap, false);
}
} else {
// 支付失败
returnMap.put("return_code", NormalUtil.FAIL);
returnMap.put("return_msg", "unknown");
return XmlUtil.xmlFormat(returnMap, false);
}
H5开发文档:https://pay.weixin.qq.com/wiki/doc/api/H5.php?chapter=15_1