H5支付和jsapi的支付主要在于给微信传参数的时候Scene_info字段。因为当时我们只是用到了H5做集成还是相当于一个wep网站应用,所以看文档里面的wap_url要和自己正式的域名一致
1.和我上一个写的jsapi没有区别,关键在于给微信的信息,所以前面的代码我就不放了,直接放传参时候的代码
public static WeixinPay setRequestXML(OrderPay orderPay,HttpServletRequest request) {
WeixinPay weixinPay = new WeixinPay();
weixinPay.setAppid(appid);//公众账号ID
weixinPay.setBody("商品描述");
weixinPay.setMch_id(mch_id);//商户号
weixinPay.setNonce_str(nonceStr());//随机字符串,https://pay.weixin.qq.com/wiki/doc/api/H5.php?chapter=4_3
weixinPay.setNotify_url(“回调地址”);
weixinPay.setOut_trade_no(orderPay.getPayNumber());//商户订单号
weixinPay.setScene_info("{'h5_info':{'type':'Wap','wap_url':'https://***。com','wap_name':'应用名称'}}");//场景信息H5特有
weixinPay.setSpbill_create_ip(IPUtil.getRemortIP(request));//ip地址
weixinPay.setTotal_fee(orderPay.getPayment());//金额同jsapi
weixinPay.setTrade_type(MWEB);//H5这里用的是MWEB
weixinPay.setSign(WXH5SignUtil.signStr(weixinPay));//[签名算法](https://pay.weixin.qq.com/wiki/doc/api/H5.php?chapter=4_3)
return sendWxPay(weixinPay);
}
2.传好参数后,进行xml格式转换,访问统一下单api
private static WeixinPay sendWxPay(WeixinPay weixinPay){
String paramXml = XmlUtil.objToXml(weixinPay);//进行转换
logger.info("微信请求的xml:"+paramXml);
String requestURL = “https://api.mch.weixin.qq.com/pay/unifiedorder“;
TreeMap<String, String> results = HttpUtil.doPostMsiData(requestURL, paramXml);//post请求访问地址
String remark ="";
if(WxConstants.SUCCESS.equals(results.get(WxConstants.RETURN_CODE))){//判断返回状态码
if(WxConstants.SUCCESS.equals(results.get(WxConstants.RESULT_CODE))){//判断返回的业务结果
if(WXH5SignUtil.isValidateSign(results)){//验证签名
// 支付跳转链接,需要传给前端
weixinPay.setMweb_url(results.get(WxConstants.MWEB_URL));
//预支付交易会话标识
weixinPay.setPrepay_id(results.get(WxConstants.PREPAY_ID));
}else{
remark ="H5返回预支付订单,验签失败";
}
}else{
//不通过的话输出一下状态码
remark = results.get(WxConstants.RESULT_CODE)+"|"+results.get(WxConstants.ERR_CODE)+"|"+results.get(WxConstants.ERR_CODE_DES);
}
}else{
//不通过的话输出一下返回的业务结果
remark = results.get(WxConstants.RETURN_CODE)+"|"+results.get(WxConstants.RETURN_MSG);
}
return weixinPay;
}
//验签
public static boolean isValidateSign(TreeMap<String,String> results){
StringBuffer sb = new StringBuffer();
Set<String> keySet = results.keySet();
Iterator<String> iter = keySet.iterator();
while(iter.hasNext()){
String key = iter.next();
if(!WxConstants.SIGN.equals(key)){
sb.append(key).append(Constants.SYMBOL_EQUAL).append(results.get(key)).append(Constants.SYMBOL_AND);//进行拼接,拼接规则看https://pay.weixin.qq.com/wiki/doc/api/H5.php?chapter=4_3,也是就是key=&这样的形式
}
}
if(mch_id.equals(results.get("mch_id"))){//判断商户号是否一致,一致的话也进行拼接
sb.append(WxConstants.KEY).append(Constants.SYMBOL_EQUAL).append(Config.CONFIG_MAP.get("weixin.h5.privatekey"));
}
logger.info("返回参数生成待签名串:"+sb.toString());
String wexinSign =results.get(sign);//获取签名
logger.info("微信返回Sign:"+wexinSign);
String sign =MD5Util.MD5(sb.toString());
logger.info("返回参数生成的Sign:"+sign);
if(sign.equals(wexinSign)){
logger.info("验签通过");
return true;
}
return false;
}
3.在控制层直接返回就好
@RequestMapping(value="/wx/pay",method={RequestMethod.GET,RequestMethod.POST})
public @ResponseBody Map<String,Object> pay(HttpServletRequest request){//传什么看自己业务需求
try{
WeixinPay weixinPays = new WeixinPay();
WeixinPay weixinPay=manualSer.setRequestXML(****);//获取参数
weixinPays.setNonce_str(weixinPay.getNonce_str());//获取私钥
weixinPays.setPrepay_id(weixinPay.getPrepay_id());//获取预支付id
weixinPays.setSign(weixinPay.getSign());//获取接口签名
weixinPays.setMweb_url(weixinPay.getMweb_url());//返回的跳转支付连接
this.getResultMap().put("data", weixinPay);
this.getResultMap().put("result", new Result("200", "获取成功!"));
}catch (Exception e) {
log.error(e);
this.getResultMap().put("result", new Result("-100","获取错误!"));
}
}
这就是H5的支付,报错见常见错误描述微信公众号支付jsapi支付 运行的流程
1、用户在商户侧完成下单,使用微信支付进行支付
2、由商户后台向微信支付发起下单请求(调用统一下单接口)注:交易类型trade_type=MWEB
3、统一下单接口返回支付相关参数给商户后台,如支付跳转url(参数名“mweb_url”),商户通过mweb_url调起微信支付中间页
4、中间页进行H5权限的校验,安全性检查(此处常见错误请见下文)
5、如支付成功,商户后台会接收到微信侧的异步通知
6、用户在微信支付收银台完成支付或取消支付,返回商户页面(默认为返回支付发起页面)
7、商户在展示页面,引导用户主动发起支付结果的查询
8,9、商户后台判断是否接到收微信侧的支付结果通知,如没有,后台调用我们的订单查询接口确认订单状态
10、展示最终的订单支付结果给用户