概述
之前说过,有时间把微信支付的H5支付讲解下,一直拖了半年时间,最近的项目正好又温习了支付功能,趁着热乎,抓紧起来。
微信的H5支付,相对公众号支付,容易了跟多,很多相似的东西,也有不同之处,这里只介绍H5支付的关键点,其他内容请先去看我的微信支付(公众号支付)那篇文章。
(传送门:https://blog.****.net/javaYouCome/article/details/79473743)。
什么是H5支付?
官网定义:要求商户已有H5商城网站,并且已经过ICP备案。通过微信H5支付可以实现在非微信浏览器(如QQ浏览器、谷歌浏览器、Safari等)中使用微信支付的场景。ps:说白了就是在微信外的所有浏览器如UC浏览器来点击“微信支付”然后自动唤起微信客户端来支付。
如果要测试支付的话,可以找个内网穿透的软件如(花生壳或natapp)他们的域名都是ICP备注过的,然后从手机浏览器访问微信支付的页面。
开发步骤
一、准备工作
1. 预备好微信支付的“四大参数”--(默认已准备好)。
2.1 在“商户平台”-我的产品-中开通H5支付,大概半天左右的时间可以审核通过。
2.2在-开发配置中填写H5支付域名,必须填写,要不然不能支付。
二、开发流程
1.前端部分:H5支付前端的东西很少,就是点击“微信支付”,后端接口只返回一个用来跳转的地址(下面还会提到),然后跳转到这个地址就OK了,所以难点是后台部分。
2.后端部分:后台还是调用微信的“统一下单”接口,不过H5的“统一下单”所需参数少了很多。咱们看看都有那些参数:
其中必须的参数有:
1.appid--“四大参数”之一
2.mch_id--“四大参数”之一
3.nonce_str--随机字符串--用工具类获取
4.body--商品描述
5.out_trade_no--商城的订单号保持唯一
6.total_fee--支付金额单位:分
7.spbill_create_ip--ip地址
8.notify_url--支付成功回调地址
9.trade_type--交易类型--只能用“MWEB”
10.scene_info--场景信息值是个json字符串,注意给值时转义“双引号”,例子:"{\"h5_info\":{\"type\":\"Wap\",\"wap_url\":" 可以填应该网站的URL地址 ",\"wap_name\": \"订单支付\"}}"
11.sing--签名加密
H5支付的“统一下单”参数就是这么简单,把上面的参数整理好POST发送微信统一下单接口,返回的是个XML的字符串,如果成功,返回的是类似如下(美化后的字符串-微信后台返回的是一行):
<xml>
<return_code><![CDATA[SUCCESS]]></return_code>
<return_msg><![CDATA[OK]]></return_msg>
<appid><![CDATA[wx472b07299797774c]]></appid>
<mch_id><![CDATA[1509488571]]></mch_id>
<nonce_str><![CDATA[saPUVwW5nyHhB8tr]]></nonce_str>
<sign><![CDATA[D0ACD36B851EEBBA97F0577CC752CCB9]]></sign>
<result_code><![CDATA[SUCCESS]]></result_code>
<prepay_id><![CDATA[wx28141313363954c5e9d84aeb3180413256]]></prepay_id>
<trade_type><![CDATA[MWEB]]></trade_type>
<mweb_url><![CDATA[https://wx.tenpay.com/cgi-bin/mmpayweb-bin/checkmweb?prepay_id=wx28141313363954c5e9d84aeb3180413256&package=90763707]]></mweb_url>
</xml>
里面的 mweb_url就是上面提到的前端要的跳转页面了,如果你想在支付完后,跳到指定页面可以在值的后面拼接指定redirect_url即可(要urlencode)如下:。
前端只需 location.href = mweb_url就可以开心的唤起微信来支付了。
三、代码部分
1.前端代码
一般我们的代码需要处理公众号和H5支付的情况,js代码navigator.userAgent返回客户端信息如果里面有"MicroMessenger"表示是微信浏览器,可以用公众号支付,否则用H5支付,可以参考如下代码:
页面有“微信支付”按钮,点击执行pay()方法。
function pay() {
if (navigator.userAgent.indexOf("MicroMessenger") != -1) {
pay_weixin();//微信浏览器支付
} else {
pay_other();//其他浏览器H5支付
}
}
function pay_other() {
var url = WEB + "/pay/orders_other
$.get(url,function(result) {
location.href = result.mweb_url;
});
}
function pay_weixin() {
//公众号支付方法
}
2.后端代码 里面的工具类,可以参考公众号支付里面有。
/**
* @Description H5调起微信支付微信浏览器外支付
* @param request
* @return Map
*/
@RequestMapping(value="orders_other", method = RequestMethod.GET)
@ResponseBody
public Map<String,String> orders_other(HttpServletRequest request) {
try {
//拼接下单地址参数
Map<String, String> paraMap = new HashMap<String, String>();
//获取请求ip地址
String ip = getIP(request);
paraMap.put("appid", appid);
paraMap.put("mch_id", mchId);
paraMap.put("nonce_str", WXPayUtil.generateNonceStr());
paraMap.put("body", "XX商城-订单结算");
paraMap.put("out_trade_no", "201810102938949");//商品的订单号每次要唯一
paraMap.put("total_fee", "1");
paraMap.put("spbill_create_ip", ip);
paraMap.put("notify_url", "www.xxxxxx.com/pay/callback"));// 此路径是微信服务器调用支付结果通知路径
paraMap.put("trade_type", "MWEB");
paraMap.put("scene_info", "{\"h5_info\":{\"type\":\"Wap\",\"wap_url\":"随意地址可以是公司官网地址",\"wap_name\": \"订单支付\"}}");
String sign = WXPayUtil.generateSignature(paraMap, paternerKey);
paraMap.put("sign", sign);
String xml = WXPayUtil.mapToXml(paraMap);//将所有参数(map)转xml格式
// 统一下单 https://api.mch.weixin.qq.com/pay/unifiedorder
String unifiedorder_url = https://api.mch.weixin.qq.com/pay/unifiedorder;
String xmlStr = HttpRequest.sendPost(unifiedorder_url, xml);//发送post请求"统一下单接口"
//以下内容是返回前端页面的json数据
String mweb_url = "";//跳转链接
if (xmlStr.indexOf("SUCCESS") != -1) {
Map<String, String> map = WXPayUtil.xmlToMap(xmlStr);
mweb_url = (String) map.get("mweb_url");
//支付完返回浏览器跳转的地址,如跳到查看订单页面
String redirect_url = "www.xxxxx.com/orders";
String redirect_urlEncode = URLEncoder.encode(redirect_url,"utf-8");//对上面地址urlencode
mweb_url = mweb_url + "&redirect_url=" + redirect_urlEncode;//拼接返回地址
}
Map<String, String> payMap = new HashMap<String, String>();
payMap.put("mweb_url", mweb_url);
return payMap;
} catch (Exception e) {
_log.info("微信支付异常");
}
return null;
}
返回给前端的结果如下所示:
H5支付就是这么多了,可能不会一次调通,耐心看错误提示,祝早日支付成功。(完)