1、需求:由于公司微信公众号新增充值业务,所以需要在公众号里h5页面里接入微信支付
2、分析:其实微信支付开发文档写的很详细,只要按照步骤一步一步来,基本问题不大,但我还是遇到了形形色色大大小小的坑,在此记录,希望有相似需求的小伙伴有所收获~
① 首先确认公众号支付的定义(截图来自微信商户平台)
② 业务流程(图片来自微信商户平台)
③ 要想完成这个功能,需要业务办理人员、后台api人员及前端h5人员共同的合作,每一环都很重要。在此仅大部分从前端角度出发,如何根据以上流程图一步步完成这个需求。
3、过程
业务申请(业务申请工作由业务办理人员负责,不包括在以上的流程图中,但却是所有业务的基础)
① 申请公众号
前往公众平台注册公众号,选择帐号类型为服务号、或*/媒体订阅号,并完成微信认证。 前往申请
② 提交资料
填写申请单(售卖商品场景请选择“公众号”),并按指引完成账户验证。立即申请 填写指引
③ 签署协议
资料审核通过后,需在线完成协议签署,以获得正式交易权限和各项产品能力。 签约指引
④ 绑定场景
登录公众平台,确认商户号和公众号的绑定关系。 绑定指引
平台相关设置(平台相关设置,也是后面接口能顺利调通息息相关,不然会报各种错)
① 设置授权域名
开发公众号支付时,在统一下单接口中要求必传用户openid,而获取openid则需要您在公众平台设置获取openid的域名,只有被设置过的域名才是一个有效的获取openid的域名,否则将获取失败。
重点:
- 这里只用填写域名,不用添加http或https协议,不然会报错“域名或路径格式不正确,请参考注意事项” ;
- 上传txt文件后,必须外网可以访问的到,不然会报错“无法访问‘你域名’指向的web服务器(或虚拟主机)的目录,请检查网络设置”。
② 设置JSAPI支付授权目录
公众号支付在请求支付的时候会校验请求来源是否有在商户平台做了配置,所以必须确保支付目录已经正确的被配置,否则将验证失败,请求支付不成功。
重点:
- 这里填写的不仅是域名,且必须包括协议(http或https都不能写错),不然在调取微信支付组件时拿到的回调参数res.err_msg会为:get_brand_wcpay_request:fail,即:调取微信支付组件失败!
③ 设置 IP白名单
通过appId及appSecret调用获取access_token及openId接口时,需要设置访问来源IP为白名单。
重点:
- 由于获取openId的接口由服务端调用,则需将你服务器ip地址填进去,包括测试环境与正式环境
- 如若未设置IP白名单,则会报“获取微信公众号授权失败,请稍后重试!错误代码-40164”,
④ 绑定开发者微信号
在微信开发者工具调试公众号页面时,要求开发者微信号与公众号建立绑定关系。
第一步:微信网页授权
要调起的支付组件,必须先经过用户网页授权,获取用户对于公众号的openId
① 用户同意授权,获取code
引导用户打开如下链接:
https://open.weixin.qq.com/connect/oauth2/authorize?appid=APPID&redirect_uri=REDIRECT_URI&response_type=code&scope=SCOPE&state=STATE#wechat_redirect
参数说明:
如果用户同意授权(即:打开上面的授权链接),页面将跳转至: redirect_uri/?code=CODE&state=STATE
code说明 :
code作为换取access_token的票据,每次用户授权带上的code将不一样;
code只能使用一次,5分钟未被使用自动过期。
在重定向的页面使用 getUrlParams 函数即可,获取到code,然后通过接口传给服务端
getUrlParams (name) {
let reg = new RegExp('(^|&)' + name + '=([^&]*)(&|$)', 'i')
let params = window.location.search.substr(window.location.search.indexOf('?') + 1)
let r = params.match(reg)
return r !== null ? decodeURI(r[2]) : null
}
② 通过code换取网页授权openId
由于涉及到敏感参数,这一步由服务端实现,请求方法:
https://api.weixin.qq.com/sns/oauth2/access_token?appid=APPID&secret=SECRET&code=CODE&grant_type=authorization_code
参数说明:
正确时返回的JSON数据包如下:
到这里,我们便经过了用户网页授权,获取到了用户对于公众号的openId(微信用户在商户对应appid下的唯一标识)
第二步:服务端调取微信API统一下单接口
接口链接:
https://api.mch.weixin.qq.com/pay/unifiedorder
其中一个必传的参数就是上面获取到的:openId
这里参数太多,我就不一一列举了,可以自己看文档。
我们需要的提供几个重要数据为:
① appid (公众账号ID):参数
② mch_id(商户号):参数
③ appkey(api安全**):生成签名sign必要字符串(key设置路径:微信商户平台(pay.weixin.qq.com)–>账户设置–>API安全–>**设置)
正确时返回的字段如下:
到这里,我们便获取到了前端h5调起支付组件的重要数据:nonceStr、package、paySign
,再加上appId、timeStamp、signType,用json包裹后返给前端h5。
第三步:微信内H5调起支付
① 由于微信WeixinJSBridge内置对象加载需要一定的时间,所以必须等WeixinJSBridge内置对象加载完成后才可以调起支付组件,不然会报错:“WeixinJSBridge is undefined”,如下:
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();
}
② 调起函数:WeixinJSBridge.invoke(‘getBrandWCPayRequest’, option, callback)
参数如下(均为从服务端返回):
// 参数 data 为服务端返回json
function onBridgeReady(data){
WeixinJSBridge.invoke(
'getBrandWCPayRequest', {
appId: data.appId, // 公众号id
timeStamp: data.timeStamp, // 时间戳
nonceStr: data.nonceStr, // 随机串
package: data.package, // 订单详情扩展字符串
signType: data.signType, // 微信签名方式
paySign: data.paySign // 微信签名
},
function(res){
if(res.err_msg == "get_brand_wcpay_request:ok" ){
//res.err_msg将在用户支付成功后返回ok,这时调取你本身服务端业务查询,若已支付成功,则跳转成功页面,展示给用户。
}
});
}
③ 调起支付组件成功表现:
④ 返回结果说明:
到这里,res.err_msg将在用户支付成功后返回ok,这时调取你本身服务端业务查询,若已支付成功,则跳转成功页面,展示给用户,至此,公众号微信支付功能实现 ~