微信授权及微信内网页跳转小程序流程和问题

595 阅读3分钟

微信sdk授权的步骤

微信sdk文档地址

  1. 绑定域名
  2. 在微信公众号里面绑定JS接口安全域名
  3. 引入JSSDK文件
  4. 调用wx.config进行初始化配置(这一步可以作为项目的通用配置,在判断是微信小程序以后,自动调用config),eg
   appId: '', // 必填,公众号的唯一标识
   timestamp: , // 必填,生成签名的时间戳
   nonceStr: '', // 必填,生成签名的随机串
   signature: '',// 必填,签名
   debug: true,
   jsApiList: ['chooseImage', 'uploadImage', 'onMenuShareAppMessage', 'onMenuShareTimeline'],
   openTagList: ['wx-open-launch-weapp', 'wx-open-launch-app']
}) 

其中下面这四个参数是需要后端来进行调用获取

appId:'',// 必填,公众号的唯一标识
timestamp:,// 必填,生成签名的时间戳 
nonceStr:'',// 必填,生成签名的随机串 
signature:'',// 必填,签名

wx.config调用是一切的基础,wx.config调用成功以后才能使用sdk的功能。

  1. wx.config调用以后会触发两个回调,error 和 ready,可以在这两个回调中处理响应逻辑。

需要注意的是! 在获取signature签名的时候,一定要保持后端调用url与前端的url一致,否则会导致验签失,sdk功能不可用

这个问题在单页面应用,且url是哈希路由的时候最容易出现,比如在实际的场景中:

print.meipian.cn/print/mpsto…

print.meipian.cn/print/mpsto…

这两个地址,一开始公众号配置的是没#的链接,而后端接口用的是带#号的链接(给后端传入的是location.href,哈希路由会在页面刚加载好的时候自动添加#),就导致了sdk的分享、跳转小程序等功能不能用。

网页跳转小程序

文档地址 目前微信内网页可以直接跳转到任何小程序。但有两个前提

  1. 已认证的服务号,且该网页域名在JS接口安全域名中
  2. 已认证的非个人主体的小程序,使用小程序云开发的静态网站托管绑定的域名下的网页 官方的DEMO:
<wx-open-launch-weapp
    id="launch-btn"
    username="gh_xxxxxxxx"
    path="pages/home/index.html?user=123&action=abc"
>
    <template>
      <style>.btn { padding: 12px }</style>
      <button class="btn">打开小程序</button>
    </template>
</wx-open-launch-weapp>
<script>
    var btn = document.getElementById('launch-btn');
    btn.addEventListener('launch', function (e) {
      console.log('success');
    });
    btn.addEventListener('error', function (e) {
      console.log('fail', e.detail);
    });
 </script>

需要的传参是 username 和 path

username是小程序的原始id,以gh_开头

path是跳转的小程序页面地址,需要添加.html后缀

跳转小程序的代码封装

鉴于这块是非常常用的代码,所以对跳转小程序做了一层封装,代码思路如下:

  1. 找到需要点击跳转小程序的element(按钮或者图片),获取elementParent
  2. 将wx-open-launch-weapp的宽和高设置成elementParent的宽和高,并插入到elementParent的子元素中(这样wx-open-launch-weapp组件就会充满且覆盖父元素,点击图片或者按钮就能跳转到小程序)
let id = 0

export default function(el, value) {
  // 这里可以设置一个默认的 weappId,同时也支持传入id
  const { path, launchCallback, style, launchErrorCallback, weappId = 'gh_xxx' } = value || {}
  if (el.style.position !== 'absolute' || el.style.position !== 'relative') {
    el.style.position = 'relative'
  }
  id++
  let { clientHeight, clientWidth } = el
  if (style && style.height) {
    clientHeight = style.height
  }
  let launchHtml = `
    <wx-open-launch-weapp
      style="position: absolute; top: 0; left: 0; z-index: 12; opacity: 0; width: ${clientWidth}px; height: ${clientHeight}px;"
      id="launch-btn${id}"
      username="${weappId}"
      path="${path || ''}"
    >
      <template>
        <style>.btn { width: ${clientWidth}px; height: ${clientHeight}px; border-radius: 0; }</style>
        <button class="btn"></button>
      </template>
    </wx-open-launch-weapp>
    `
  const newEl = document.createElement('div')
  newEl.innerHTML = launchHtml
  const launchEl = newEl.childNodes[1] // 因为launchHtml开头有空格或换行,所以是1而不是0
  el.appendChild(launchEl)
  setTimeout(() => {
    // 此处绑定的事件可以处理一些业务逻辑或者埋点上报
    const launchBtn = document.getElementById(`launch-btn${id}`)
    launchBtn.addEventListener('launch', function(e) {
      console.log('launch', e)
      launchCallback && launchCallback()
    })
    launchBtn.addEventListener('ready', function(e) {
      console.log('ready', e)
    })
    launchBtn.addEventListener('error', function(e) {
      console.log('error', e)
      launchErrorCallback && launchErrorCallback()
    })
    launchBtn.addEventListener('click', function(e) {
      console.log('launchClick', e)
      if (NODE_ENV !== 'production') {
        alert('正式环境会拉起小程序')
      }
    })
  })
}

代码引用

<img onClick={this.handleBuyBtnClick} onLoad={this.imgLoadHandle} src={imgSrc} />
imgLoadHandle = (e) => {
    const { isMiniprogram } = this.state
    console.log(isMiniprogram)
    if (isMiniprogram !== 2) return
    launchWxapp(e.target.parentElement, {
      path: 'pages/main/index.html'
    })
}