美文网首页vue技术栈
微信公众号支付实现详解(前端)

微信公众号支付实现详解(前端)

作者: Robin90 | 来源:发表于2018-08-28 22:23 被阅读681次

    前言

    完成微信h5支付的你,继续公众号的支付也许更简单哦。

    场景

    微信浏览器中的应用支付必须依赖于公众号支付,下面就公众号支付中的一些技术点进行详细的解析。

    准备工作

    基本配置申请

    参考资料:微信公众号开通支付功能--百度经验教程

    基本信息

    • 服务号,服务号绑定的管理员号
    • 开通支付账号,并记住支付账号,与支付账号绑定的微信号
    • appid,秘钥
    • 支付账号开通支付目录(直接支付地址的上一级目录
    • 设置了页面授权域名,并且是你的站点域名地址
    • 基本接口权限,尤其是jssdk部分权限,保证尽可能都开通

    业务流程图解以及时序图

    与微信h5基本相同,唯一不同的是这次微信返回的需要唤起微信sdk支付的参数列表。

    技术问题

    获取openid

    网站应用微信登录是基于OAuth2.0协议标准构建的微信OAuth2.0授权登录系统。获取openid分为两步,获取code,然后根据code获取openid,建议这两部分请求由后端发起,前端直接请求会涉及到跨域问题。后端直接把这两个方法定义为工具方法,使用方便,便于其他场景的复用。

    一 :请求获取code,如果不想浪费时间请直接复制粘贴使用

    • 标准格式拼接代码:

      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

    • 参考文档:微信中web网站获取code参考文档

    二 根据code获取openid

    • 一个用户针对一个公众号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"}
      
    • 刷新fresh-token有效期
      如果token失效了,可以用refresh_token重新获取一个。

    微信支付sdk

    方式一 :官网的方式

    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
               }    
           }
       ); 
        },
    

    方式二 : 需要引入js-weixin的模块,流程如下:

    引入模块--ready--获取access-token--获取ticket--生成签名(wx.config需要)--结合接口返回参数--唤起wxpay。(比较麻烦,不推荐使用)
    参考文档:

    参考文档

    相关文章

      网友评论

        本文标题:微信公众号支付实现详解(前端)

        本文链接:https://www.haomeiwen.com/subject/usjcwftx.html