本文共 6444 字,大约阅读时间需要 21 分钟。
h5的微信支付一般分为2种情况:
一、微信内支付(JSAPI支付)
参考链接: 微信支付文档链接:请确保实际支付时的请求目录与后台配置的目录一致(现在已经支持配置根目录,配置后有一定的生效时间,一般5分钟内生效),否则将无法成功唤起微信支付。
1.设置支付目录:
在微信商户平台(pay.weixin.qq.com),设置您的JSAPI支付支付目录,设置路径:商户平台–>产品中心–>开发配置,如图7.7所示。JSAPI支付在请求支付的时候会校验请求来源是否有在商户平台做了配置,所以必须确保支付目录已经正确的被配置,否则将验证失败,请求支付不成功。配置如下图:2.设置授权域名:
开发JSAPI时,在统一下单接口中要求必传用户openid
,而获取openid
则需要您在公众平台设置获取openid
的域名,只有被设置过的域名才是一个有效的获取openid
的域名,否则将获取失败。具体界面: 网页授权域名是用来向微信获取code
3.微信网页授权 openid是微信用户在公众号appid下的唯一用户标识(appid不同,则获取到的openid就不同),可用于永久标记一个用户,同时也是微信JSAPI支付的必传参数。openid
的获取需要先获取用户授权后的code
,将code
传给服务端,以换取prepay_id
(ps:订单id。后面会用到)。 openid
获取文档: 如果用户在微信客户端中访问第三方网页,公众号可以通过微信网页授权机制,来获取用户基本信息,进而实现业务逻辑
关于网页授权的两种scope的区别说明
3.1、以snsapi_base为scope发起的网页授权,是用来获取进入页面的用户的openid的,并且是静默授权并自动跳转到回调页的。用户感知的就是直接进入了回调页(往往是业务页面)3.2、以snsapi_userinfo为scope发起的网页授权,是用来获取用户的基本信息的。但这种授权需要用户手动同意,并且由于用户同意过,所以无须关注,就可在授权后获取该用户的基本信息。
3.3、用户管理类接口中的“获取用户基本信息接口”,是在用户和公众号产生消息交互或关注后事件推送后,才能根据用户OpenID来获取用户基本信息。这个接口,包括其他微信接口,都是需要该用户(即openid)关注了公众号后,才能调用成功的。
由于jsapi
支付只需要获取code调用后台接口换取openid
,并不需要获取昵称用户信息,所以这里用第一种方式即可。
// APPID:需将 APPID 换成你使用的微信公众号的 appid 。// REDIRECT_URI换成用户授权回调成功的页面地址,一般来讲都是当前支付页面的地址,需要对地址进行encode处理(PS:处理方法:encodeURIComponent(link))// STATE可以向回调页面传参,但是只能传一个字符串,如:state=123。若无参数,默认STATE就可以。// 这个链接自己拼接的其他参数不会被带到回调页面// 若提示“该链接无法访问”,请检查参数是否填写错误,是否拥有scope参数对应的授权作用域权限https://open.weixin.qq.com/connect/oauth2/authorize?appid=APPID&redirect_uri=REDIRECT_URI&response_type=code&scope=snsapi_base&state=STATE#wechat_redirect
用户同意授权后
如果用户同意授权,页面将跳转至 redirect_uri/?code=CODE&state=STATE。注意:由于授权操作安全等级较高,所以在发起授权请求时,微信会对授权链接做正则强匹配校验,如果链接的参数顺序不对,授权页面将无法正常访问
注意:跳转回调redirect_uri,应当使用https链接来确保授权code的安全性。
code说明 : code作为换取access_token的票据,每次用户授权带上的code将不一样,code只能使用一次,5分钟未被使用自动过期。
4.在微信浏览器内窒息感打开的h5的支付,接口在输入输出的数据格式为JSON。
注意:WeixinJSBridge内置对象在其他浏览器中无效。 拿到openid
之后,可以进行支付了, 支付参数生成文档: // 检测当前环境是否支持 WeixinJSBridge,也可以理解为判断当前环境是否微信// 这部分也可以直接替换成判断是否是微信环境,在微信内才能进行支付// 如果 WeixinJSBridge 判断有问题,可以试试,调用 window.WeixinJSBridge 去判断if (typeof WeixinJSBridge == "undefined"){ if( document.addEventListener ){ document.addEventListener('WeixinJSBridgeReady', onBridgeReady, false); }else if (document.attachEvent){ document.attachEvent('WeixinJSBridgeReady', onBridgeReady); document.attachEvent('onWeixinJSBridgeReady', onBridgeReady); }}else{ onBridgeReady();}// 客户端依据支付文档生成参数function onBridgeReady(){ WeixinJSBridge.invoke( 'getBrandWCPayRequest', { "appId":"wx2421b1c4370ec43b", //公众号名称,由商户传入 "timeStamp":"1395712654", //时间戳,自1970年以来的秒数 "nonceStr":"e61463f8efa94090b1f366cccfbbb444", //随机串 "package":"prepay_id=u802345jgfjsdfgsdg888", "signType":"MD5", //微信签名方式: "paySign":"70EA570631E4BB79628FBCA90534C63FF7FADD89" //微信签名 }, function(res){ if(res.err_msg == "get_brand_wcpay_request:ok" ){ // 使用以上方式判断前端返回,微信团队郑重提示: // res.err_msg将在用户支付成功后返回ok,但并不保证它绝对可靠。 // 支付成功的回调 }else if (res.err_msg === "get_brand_wcpay_request:cancel") { Toast.info('用户取消支付') // 用户取消支付回调 } else if (res.err_msg === "get_brand_wcpay_request:fail") { // 支付失败回调 } } );}
下面是具体的逻辑
// 页面初始var wx = null;isWeixin();// 判断是否是微信环境,代替文档中的 typeof WeixinJSBridge == "undefined" 这部分判断function isWeixin(){ // wx为true 则为微信环境,为false则微信外环境 wx = (function(){ return navigator.userAgent.toLowerCase().indexOf('micromessenger') !== -1 })();}// 点击立即支付执行if(wx){ // 获取回调code,code是回调页面的地址参数 let code = urlParam('code'); if(!code){ // code的有效期只有5分钟,所以这里我在点击立即支付的时候拉取用户授权 window.location.href = 'https://open.weixin.qq.com/connect/oauth2/authorize?appid=APPID&redirect_uri=REDIRECT_URI&response_type=code&scope=snsapi_base&state=STATE#wechat_redirect' }else { // 拿code换取openid getOpenid(code); }}// 拉取支付function getOpenid(code){ ... let openid = null; // 用code换取openid axios.post() .then((res) => { openid = res.openid; }) ... // 拿到openid之后,就可以拉起支付了 let appid = "wx2421b1c4370ec43b"; let secret = SECRET; // 微信公众号秘钥,生成签名需要 let timestamp = String(new Date().getTime() / 1000); let nonceStr = Math.random().toString(36).substr(2, 10); let prepay_id = openid; let paySign = ''; var string = 'appId=' + appid + '&nonceStr=' + nonceStr + '&package=prepay_id=' + prepay_id + '&signType=MD5&timeStamp=' + timestamp + '&key=' + secret; paySign = (MD5(string).toString()).toUpperCase(); window.WeixinJSBridge.invoke( 'getBrandWCPayRequest', { "appId": appid, //公众号名称,由商户传入 "timeStamp": timestamp, //时间戳,自1970年以来的秒数 "nonceStr": nonceStr, //随机串 "package":"prepay_id=" + prepay_id, "signType":"MD5", //微信签名方式 "paySign": paySign //微信签名 }, function(res){ if(res.err_msg == "get_brand_wcpay_request:ok" ){ // 支付成功回调 } else if (res.err_msg === "get_brand_wcpay_request:cancel") { // 用户取消支付 } else if (res.err_msg === "get_brand_wcpay_request:fail") { // 支付失败 } } );}
Tip
1. 微信内支付getBrandWCPayRequest
参数生成方式,timestamp,nonceStr, paySign 的计算方式可以直接用。 2.config:invalid signature
,问题,检查页面的域名有没有添加到微信公众号ip白名单,根据文档检查签名生成。 3. code
,如果页面在本地打开,用户授权回调的code,复制出来的链接是看不到的(ps: 但不影响页面接着执行)。将项目放在线上的测试环境就可以。 二、微信外支付(ps: h5支付)
参考链接: 同JSAPI支付一样: 需要先申请商户号,并在商户中设置h5支付的权限。 在公众号将页面用的IP添加到域名白名单中。 通过后台返回mweb_url
,拉起微信支付收银台第三方页面。可通过访问该url来拉起微信客户端,完成支付,mweb_url的有效期为5分钟。 参考链接: // data 为拉起支付 axios.post(url, data) .then(function(res){ let jsonobj = JSON.parse(utils.DecryptEcb(res.data));// Decrypt console.log(jsonobj) if(jsonobj.success === 1){ // jsonobj.data.mweb_url 则是返回给我门用来拉起微信支付的链接。 // redirect_url 是微信支付完成后的指定回调页面。由于H5外部支付完成无法返回付款是否完成的状态(ps:这一点文档也有说明)。所以文档给了一个折中的方法,指定回调页面,在回调页面询问用户是否完成付款,由用户自己操作。 window.location.href = jsonobj.data.mweb_url + '&redirect_url=REDIRECT_URL?' + order= + _this.state.orderInfo.order_num; } })
传送门:
end 😈
转载地址:http://nnzsi.baihongyu.com/