微信内嵌H5调用相机及支付相关问题

1,156 阅读4分钟

我正在参加「掘金·启航计划」

前言

进来项目在做公众号,遇到了一些问题及解决方案,在这里进行记录及分享,希望给大家带来一丝帮助 手机上控制台调试我建议使用vConsole(npm install vconsole)

微信内嵌H5的相机调用

微信内嵌H5我们需要调用扫码功能,则需要用到官网提供的SDK的方法来解决

1.导入所需文件

首先我们页面中需要导入对应的文件

// npm 引入方式
npm install jweixin-module --save
// 下载下来 import引入方式

//下载地址:https://unpkg.com/jweixin-module@1.6.0/lib/index.js
import wxSDK from 'xxx/weixin-sdk'

2.根据后端接口拿到公众号的配置

这里建议直接把后端返回数据直接进行赋值(我自己单独赋值出现过问题😅)后端需要的接口参数是公众号链接的id值加当前公众号地址,安卓和苹果可能有差别,所以大家建议先做一下判断

// 这是官网需要赋值的参数
wxSDK.config({
  debug: true, // 开启调试模式,调用的所有 api 的返回值会在客户端 alert 出来,若要查看传入的参数,可以在 pc 端打开,参数信息会通过 log 打出,仅在 pc 端时才会打印。
  appId: '', // 必填,公众号的唯一标识
  timestamp: , // 必填,生成签名的时间戳
  nonceStr: '', // 必填,生成签名的随机串
  signature: '',// 必填,签名
  jsApiList: [] // 必填,需要使用的 JS 接口列表
});

然后对我们能不能调用扫描的API进行校验

      wxSDK.checkJsApi({
              jsApiList: ['scanQRCode'], // 需要检测的JS接口列表,所有JS接口列表见附录2,
              success: function (res) {
                // 打印参数看看能否成功
                console.log(res)
                // 以键值对的形式返回,可用的api值true,不可用为false
                // 如:{"checkResult":{"chooseImage":true},"errMsg":"checkJsApi:ok"}
         }
     })

3.调用扫描API

直接使用手机调试看打印结果

wxSDK.scanQRCode({
        needResult: '1', // 默认为0,扫描结果由微信处理,1则直接返回扫描结果,
        scanType: ['qrCode', 'barCode'], // 可以指定扫二维码还是一维码,默认二者都有
        success: res => {
          console.log('success', res)
        },
        fail: function (res) {
          // console.log('fail', res)
        },
        complete: function (res) {
          // alert(JSON.stringify(res))
        }
      })

4.问题总结

难度不大,主要是第一次做公众号后端所需要的参数取值麻烦,还有就是在配置当前页调用扫描API的时候自己挨个赋值会出现问题(虽然对比好像没有问题)

微信调用支付功能

这个支付功能较为麻烦,但是主要还是在于后端,前端只是麻烦在一些取值上

1.支付前的准备

首先我们支付前需要拿到调用后端支付接口的参数(本人这边是做物联网的,就拿当前做的举例子),需要的主要参数有appkey,openid,支付方式

拿openid时要判断用户是否授权了并且前提是先拿到了appid,如果没有我们需要调用下面这种方法来获取到调用openid时所需要的code(自己截取)

let local = window.location.href
// 把当前地址加上code参数,然后截取出来
 window.location.href = `https://open.weixin.qq.com/connect/oauth2/authorize?appid=${appid}&redirect_uri=${encodeURIComponent(local)}&response_type=code&scope=snsapi_userinfo#wechat_redirect`

拿到所有参数调用支付准备接口成功后直接使用微信官方JSAPI支付方法进行支付

// 官方案例提供方法
function onBridgeReady(){
   WeixinJSBridge.invoke(
      'getBrandWCPayRequest', {
         "appId":"wx2421b1c4370ec43b",     //公众号ID,由商户传入     
         "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,但并不保证它绝对可靠。
      } 
   }); 
}
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();
}
// 接口调用成功后拉起支付方法
.then(res => {
          console.log(res)
          if (res.code == 0) {
            WeixinJSBridge.invoke('getBrandWCPayRequest', res.data, function (
              res
            ) {
              // alert(JSON.stringify(res))
              if (res.err_msg === 'get_brand_wcpay_request:ok') {
                // 使用以上方式判断前端返回,微信团队郑重提示:
                //res.err_msg将在用户支付成功后返回ok,但并不保证它绝对可靠
                // alert
                uni.showLoading({
                  title: '支付成功'
                })
                setTimeout(function () {
                  uni.hideLoading()
                  // uni.removeStorageSync('RechargeInfo')
                  history.back() // 页面刷新过,不能使用uni.navigateBack(x)回退历史栈
                 
                }, 1000)
              } else {
                uni.hideLoading()
              }
              WeixinJSBridge.log(res)
            })

2.提示

支付页面因为调用code会重复刷新页面所以我们这边建议使用本地保存刷新次数,方便支付回调成功后手机返回可以返回上一页面而不是反复返回当前页

// 在生命周期onShow上就开始记录
onShow () {
    if (uni.getStorageSync('reloadIndex')) {
      // 有刷新过了
      uni.setStorageSync('reloadIndex', uni.getStorageSync('reloadIndex') + 1)
    } else if (!uni.getStorageSync('reloadIndex')) {
      // 没刷新过,刷新一下
      uni.setStorageSync('reloadIndex', 1)
      window.location.reload(false)
    }
  },

总结

在有写过的时候觉得复杂,但是在慢慢的踩坑中解决一个个问题,现在回过头来看发现其实也就那么回事,所以我们不要害怕工作中遇到问题,每一次遇到的问题都是我们成长的垫脚石,欢迎大家随时找我讨论技术问题,希望与jym共同进行=步