wjeymiantan 2019-06-26
完成微信h5支付的你,继续公众号的支付也许更简单哦。
微信浏览器中的应用支付必须依赖于公众号支付,下面就公众号支付中的一些技术点进行详细的解析。
参考资料:微信公众号开通支付功能--百度经验教程
与微信h5基本相同,唯一不同的是这次微信返回的需要唤起微信sdk支付的参数列表。
网站应用微信登录是基于OAuth2.0协议标准构建的微信OAuth2.0授权登录系统。获取openid分为两步,获取code,然后根据code获取openid,建议这两部分请求由后端发起,前端直接请求会涉及到跨域问题。后端直接把这两个方法定义为工具方法,使用方便,便于其他场景的复用。
标准格式拼接代码:
let encodeUrl=encodeURIComponent(`http://xxx/xhxwxpay?productId=${productId}&orderNo=${orderNo}`)
let tempUrl=`https://open.weixin.qq.com/connect/oauth2/authorize?appid=wx6f5de09c8ef178a7&redirect_uri=${encodeUrl}&response_type=code&scope=snsapi_userinfo&state=STATE#wechat_redirect`请求参数说明
| 参数 | 是否必须 | 说明 |
|---|---|---|
| appid | 是 | 应用唯一标识 |
| redirect_uri | 是 | 请使用urlEncode对链接进行处理 |
| response_type | 是 | 填code |
| scope | 是 | 应用授权作用域,拥有多个作用域用逗号(,)分隔,网页应用目前仅填写snsapi_login即可,这里用的 snsapi_userinfo |
| state | 否 | 用于保持请求和回调的状态,授权请求后原样带回给第三方。该参数可用于防止csrf攻击(跨站请求伪造攻击),建议第三方带上该参数,可设置为简单的随机数加session进行校验 |
用户允许授权后,将会重定向到redirect_uri的网址上,并且带上code和state参数redirect_uri?code=CODE&state=STATE
若用户禁止授权,则重定向后不会带上code参数,仅会带上state参数redirect_uri?state=STATE
一个用户针对一个公众号openid是固定的,所以获取到一样的不用怀疑,涉及到部分敏感的公众号的秘钥等,建议是后端处理发起请求,这样也可以避免前端跨域的问题。
//网关或者后端的设置(以koa框架的为例)
*post_getOpenId(){
let reqData = this.request.body;
let param = {
appid:'wxxxx',
secret:'affsdcsdvdsvfv6',
code:reqData.code,
grant_type:'authorization_code'
}
let result = yield this.api.getOpenId(param);
this.body = result;
}
// 获取openid 传入对象的形式,改造通用的api方法
getOpenId: function* (apiParam, json = true) {
// 获取token的地址
let apiUrl='https://api.weixin.qq.com/sns/oauth2/access_token'
let response = yield request.get(apiUrl, { qs: apiParam, json: json });
return responseHandle(response, apiUrl, apiParam);
}.bind(this),
//前端的写法,好处是避免暴露公众号的相关信息
this.$api.post("order/getOpenId", { code: this.code }).then(res => {
// 正确获取openid的情况下 请求后台参数得到对应的返回参数,目前只需要openid
if (res.openid) {
this.openId = res.openid;
//准备条件足够的话 可以唤起支付
this.topay()
}else {
//请求失败或者没有对应的字段
}请求参数说明,通过code获取access_token
https://api.weixin.qq.com/sns/oauth2/access_token?appid=APPID&secret=SECRET&code=CODE&grant_type=authorization_code
| 参数 | 是否必须 | 说明 |
|---|---|---|
| appid | 是 | 应用唯一标识,在微信开放平台提交应用审核通过后获得 |
| secret | 是 | 应用密钥AppSecret,在微信开放平台提交应用审核通过后获得 |
| code | 是 | 填写第一步获取的code参数 |
| grant_type | 是 | 填authorization_code |
返回结果说明
//正确的返回
{
"access_token":"ACCESS_TOKEN",
"expires_in":7200,
"refresh_token":"REFRESH_TOKEN",
"openid":"OPENID",
"scope":"SCOPE",
"unionid": "o6_bmasdasdsad6_2sgVt7hMZOPfL"
}
//错误的返回
{"errcode":40029,"errmsg":"invalid code"}如果token失效了,可以用refresh_token重新获取一个。
invoke方法 ,简单有效,直接根据接口返回参数唤起。以下代码实例是vue环境下的,其他环境请自行匹配,仅供参考。
// 准备好微信sdk部分
jsSdk(){
// 判断微信的WeixinJSBridge
if (typeof WeixinJSBridge == "undefined"){
if( document.addEventListener ){
document.addEventListener('WeixinJSBridgeReady', this.onBridgeReady, false);
}else if (document.attachEvent){
document.attachEvent('WeixinJSBridgeReady', this.onBridgeReady);
document.attachEvent('onWeixinJSBridgeReady', this.onBridgeReady);
}
}else{
this.onBridgeReady();
}
},
// 支付sdk准备完成
onBridgeReady() {
// 触发微信支付
WeixinJSBridge.invoke(
'getBrandWCPayRequest', {
appId: this.payOption.appId, //公众号名称,由商户传入
timeStamp: this.payOption.timeStamp, //时间戳,自1970年以来的秒数
nonceStr: this.payOption.nonceStr, //随机串
package: this.payOption.package, //prepay_id用等式的格式
signType: this.payOption.signType, //微信签名方式:
paySign: this.payOption.paySign, //微信签名
},
function(res){
if(res.err_msg == "get_brand_wcpay_request:ok" ) {
// 支付成功 返回成功页
let tempUrl="//paysucc"
location.href=tempUr
} else{
// 取消支付或者其他情况 get_brand_wcpay_request:cancel get_brand_wcpay_request:fail
let tempUrl='//topay'
location.href=tempUrl
}
}
);
},引入模块--ready--获取access-token--获取ticket--生成签名(wx.config需要)--结合接口返回参数--唤起wxpay。(比较麻烦,不推荐使用)
参考文档: