H5发起微信支付(转载)

H5呼起微信支付存在两种场景

第一种:其他浏览器呼起微信支付。

第二种:微信内部呼起微信支付。

项目说明:

我这边的项目要求的两种方式均要适用。 产品要求是当支付失败时或者未支付情况是停留在支付订单页面,可再次发起订单请求(新订单),故我在这项目中,把支付成功页面和订单页面在同一页(根据订单状态去展示)。

前期准备:

公众号设置:

内部呼起微信搭桥,需要配置一个网页授权域名,用于前端内部呼起微信生成对应的code给到后端。

image.png

需要注意的是,填入域名即可,不用在域名前加【http://】,不然会提示【域名或路径格式不正确,请参考注意事项】。别问我怎么知道的,因为我删掉了我写的前面【http://】就配置通过了。

后端涉及到支付,要配置支付授权。

公众平台配置位置:微信支付-开发设置-支付授权目录

 

image.png

前端代码

判断浏览器情况

初始化时判断浏览器内核,并针对不同情况做不同的事情。

init(){
    this.wechatFlag = this.isWeChat();//本人项目提交时需要判断区分,所以就定义了全局
    if(this.wechatFlag){
        //当前在微信内部 do someThing
        // 比方判断是否有授权code
          let code = this.getQueryObject().code;
          if (code == null || code == '') {
            this.redirectPage();//重定向获取code
          } else {
            this.code = code;
          }
    }else{
        //外部浏览器 do someThing
        //项目里,我设置的支付订单页和成功页在同一个页面
        //所以外部浏览器付费与否都回到这个页面
        //所以我这要获取成功后的订单参数
        if (this.$route.query.orderNumber) {//外部浏览器跳转重定向
            //从微信里重定向回来
            this.orderId = this.$route.query.orderNumber;//订单参数
            //this.getMyOrder();//请求订单数据
          }
    }
}
复制代码

判断是否在微信内部浏览器(浏览器内核)isWeChat()

isWeChat(){
      //判断是否为微信内部登录
      var ua = window.navigator.userAgent.toLowerCase();
      //console.log(ua);
      if (ua.match(/MicroMessenger/i) == 'micromessenger') {
        return true;//是微信内部
      } else {
        return false;
      }
    }
}
复制代码

外部浏览器成功回调后url传参获取getQueryObject()【公用函数】

getQueryObject(url){////可当成一个公用方法
  url = url == null ? window.location.href : url;
  let search = url.substring(url.lastIndexOf("?") + 1);
  let obj = {};
  let reg = /([^?&=]+)=([^?&=]*)/g;
  search.replace(reg, function (rs, $1, $2) {
    let name = decodeURIComponent($1);
    let val = decodeURIComponent($2);
    val = String(val);
    obj[name] = val;
    return rs;
  });
  return obj;
}
复制代码

第一种:其他浏览器呼起微信支付。

思路:其他浏览器呼起微信支付,更多的是依靠后台接口返回数据。

请求微信支付的接口 --> 接口返回一个链接 --> 跳转连接

  async submitOrder(){
  this.isDisabledSubmitBtn = true //防止用户点击多次
    let params= {};//项目支付相关的参数
    try {
          let {
            retBody,
            retMsg
          } = await requestPay (params)//请求接口
          if (retStatus === 'success') {//成功判断依据
            if (retBody) {//直接跳转链接
              window.location.href = retBody;
            }
          } else {
            this.$notify(retMsg || '提交订单失败')
            this.isDisabledSubmitBtn = false //防止用户点击多次
          }
        } catch (error) {
          this.error = true
          this.$notify('提交订单失败' || error)
          this.isDisabledSubmitBtn = false //防止用户点击多次
    }
  }

}

跳转回来之后就在会重新create了,获取与后台约定参数重新查询订单数据即可。
复制代码

第二种:微信内部浏览器

需要前端搭桥呼起浏览器内置方法

重定向获取用户code

redirectPage(){
  //微信内部则重定向页面 
  let local = window.location.href;//当前地址
  let appId = 'thisistheappid';//填写公众号APPID
  window.location.href = `https://open.weixin.qq.com/connect/oauth2/authorize?appid=${appId}&redirect_uri=${encodeURIComponent(local)}&response_type=code&scope=snsapi_base&state=STATE#wechat_redirect`  //跳转授权链接
},
复制代码

提交函数

submitOrderInside(){
    let params = {
    code:this.code,
    };//微信内部添加的订单,后台需要我传多一个用户code
    //因为code有时效性,所以失效了或者使用过之后需要重新获取个新的code
    try {
          let {
            retStatus,
            retBody,
            retMsg
          } = await requestPayInside(params)//支付接口
          if (retStatus === 'success') {
            this.orderId = retBody.orderNumber;
            this.weChatParameter = {//微信搭桥需要的数据
              appid: retBody.appid,
              timeStamp: retBody.timeStamp,
              nonceStr: retBody.nonceStr,
              packageValue: retBody.packageValue,
              signType: retBody.signType,
              paySign: retBody.paySign,
            };
            this.wechatPay();//微信内置对象判断
          } else {
            this.$notify(retMsg || '提交订单失败')
            this.isDisabledSubmitBtn = false //防止用户点击多次
            this.redirectPage();//重定向获取新的code
          }
        } catch (error) {
          this.error = true
          this.$notify('提交订单失败' || error)
          this.isDisabledSubmitBtn = false //防止用户点击多次
           this.redirectPage();//重定向获取新的code
        }

    }
   
复制代码

wechatPay()解决微信内置对象报错

//搭桥前先解决微信内置对象报错
weixinPay (params) {
      var that = this;
      if (typeof WeixinJSBridge == "undefined") {
        if (document.addEventListener) {
          document.addEventListener('WeixinJSBridgeReady', that.onBridgeReady(params), false);
        } else if (document.attachEvent) {
          document.attachEvent('WeixinJSBridgeReady', that.onBridgeReady(params));
          document.attachEvent('onWeixinJSBridgeReady', that.onBridgeReady(params));
        }
      } else {
        that.onBridgeReady();
      }
    },
   
复制代码

搭桥onBridgeReady()

 //微信内置浏览器类
onBridgeReady () {
  var that = this;
  var timestamp = Math.round(that.weChatParameter.timeStamp).toString();
  window.WeixinJSBridge.invoke(
    'getBrandWCPayRequest', {
    debug: false,
    "appId": that.weChatParameter.appid,     //公众号名称,由商户传入
    "timeStamp": timestamp, //时间戳,自1970年以来的秒数
    "nonceStr": that.weChatParameter.nonceStr, //随机串
    "package": that.weChatParameter.packageValue,
    "signType": that.weChatParameter.signType, //微信签名方式:
    "paySign": that.weChatParameter.paySign, //微信签名
    jsApiList: [
      'chooseWXPay'
    ]
  },
    function (res) {
      // 使用以上方式判断前端返回,微信团队郑重提示:res.err_msg将在用户支付成功后返回ok,但并不保证它绝对可靠。
      if (res.err_msg == "get_brand_wcpay_request:ok") { //支付成功后的操作
        that.isDisabledSubmitBtn = true;
        //支付成功
        that.getMyOrder();//请求成功后重新请求订单数据
      } else if (res.err_msg == 'get_brand_wcpay_request:cancel') { //取消支付的操作
        that.isDisabledSubmitBtn = false //按钮恢复高亮
        that.redirectPage();//重定向获取新的code
        //取消支付
      } else {
        //支付失败
        that.isDisabledSubmitBtn = false //按钮恢复高亮
        that.redirectPage();//重定向获取新的code

      }
    }
  );
}
复制代码

以上就是个人微信支付的思路以及部分代码。仅供参考。

作者:抓到你了_摸鱼怪
链接:https://juejin.cn/post/7094835152534110244
来源:稀土掘金

阅读剩余
THE END