#yyds干货盘点#【愚公系列】2022年12月 微信小程序-webview内嵌网页的授权认证

时间:2022-12-18 07:16:05

前言

随着微信小程序的广泛应用,小程序的用户越来越多,但受其小程序体积限制的影响,不能够完全满足用户的要求,应运而生的web-view组件很好的解决的这一问题。

web-view主要是内嵌H5网站页面又以下几个优点:

  • 内嵌web-view能够直接运行在小程序中,大大减少了用户的开发成本
  • 能够实现小程序与h5的跳转,有良好的扩展性,方便用户多端间引流

小程序相关API

属性 类型 默认值 必填 说明 最低版本
src string webview 指向网页的链接。可打开关联的公众号的文章,其它网页需登录小程序管理后台配置业务域名。 1.6.4
bindmessage eventhandler 网页向小程序 postMessage 时,会在特定时机(小程序后退、组件销毁、分享)触发并收到消息。e.detail = { data },data是多次 postMessage 的参数组成的数组 1.6.4
bindload eventhandler 网页加载成功时候触发此事件。e.detail = { src } 1.6.4
binderror eventhandler 网页加载失败的时候触发此事件。e.detail = { url, fullUrl },其中 fullUrl 为加载失败时的完整 url 1.6.4

一、webview内嵌网页的授权认证

1.内嵌页面

// miniprogram/pages/2.18/web-view/index.js
Page({

  /**
   * 页面的初始数据
   */
  data: {
    url:'',
    webViewData:{}
  },
  onReceivedMessage(e){
    let data = e.detail.data
    // data可能是多次 postMessage 的参数组成的数组
    if (Array.isArray(data)) data = data[0]
    console.log('onReceivedMessage',JSON.parse(data));
    this.setData({
      webViewData:JSON.parse(data)
    })
  },
  onShareAppMessage(options) {
    console.log('title',this.data.webViewData.title);
    console.log('webViewUrl',options.webViewUrl)
    return {
      title: this.data.webViewData.title,
      path: `/web-view/index?web-view-url=${options.webViewUrl}`
    }
  },

  /**
   * 生命周期函数--监听页面加载
   */
  onLoad: function (options) {
    let token = getApp().globalData.token
    let url = `http://localhost:3000/user/web-view?token=${token}`
    console.log('token', token);
    this.setData({
      url
    })
  },
})
<web-view bindmessage="onReceivedMessage" src="{{url}}" style="z-index:-1"></web-view>

2.登录页面

Page({
  /**
   * 页面的初始数据
   */
  data: {},
  onShareAppMessage:function(options) {
    console.log('分享')
    return {
      title: '登陆',
      path: '/pages/index'
    }
  },

  /**
   * 生命周期函数--监听页面加载
   */
  onLoad: function (options) {
    // wx.showShareMenu({
    //   withShareTicket: true
    // })
  },
})
<view class="page-section">
	<text class="page-section__title">微信登陆</text>
	<view class="btn-area">
    <button bindgetuserinfo="login" open-type="getUserInfo" type="primary">登陆</button>
    <navigator style="padding-top:20rpx;" url="/web-view/index" open-type="navigate">web view</navigator>
    <button open-type="share" type="primary">分享</button>
	</view>
</view>

二、web端相关函数

1.判断是否是小程序环境

<!DOCTYPE html>
<html>

<head>
  <title>{{title}}</title>
  <script type="text/javascript" src="/static/js/jweixin-1.6.0.js"></script>
  <script type="text/javascript" src="/static/js/jquery.js"></script>
  <script type="text/javascript" src="/static/js/jquery.cookie.js"></script>
  <style>
    * {
      font-size: 24px;
    }
  </style>
</head>

<body>
  {{title}}

  {{if title}}
  <p>has title.</p>
  {{/if}}

  <p>
  {{each title $value $index}}
  <span>{{$index}}:{{$value}}</span>
  {{/each}}
  </p>

  <p>
    {{each arr }}
    <span>{{$index}}:{{$value}}</span>
    {{/each}}
  </p>

  <p>{{now | dateFormat "yyyy-MM-dd hh:mm:ss"}}</p>

  <p>Art-Template Welcome to {{title}}</p>
  <input  value="ly" /><br /><br />
  <input  type="button" value="send"></input>
  <p ></p>
  <input  type="button" value="share" style="width: 100px;height:30px;border:solid 1px grey;"></input>
  <script type="text/javascript">
    

    // 当处于小程序内
    document.addEventListener('intoMiniprogram', () => {
      retrieveHomeData()
    }, false)

    // 检查是不是位于小程序内
    let isInMiniprogram = false
    function changeIsInMiniprogramState() {
      if (!isInMiniprogram) {
        isInMiniprogram = true
        $.cookie("isInMiniprogram", true)
        document.dispatchEvent(new Event('intoMiniprogram'))
        console.log('isInMiniprogram', isInMiniprogram);
      }
    }
    if (/token=\d+/.test(window.location.search)) {
      changeIsInMiniprogramState()
    } else if ( /miniProgram/.test(navigator.userAgent) ){
      changeIsInMiniprogramState()
    }else if (($.cookie("isInMiniprogram") || '') == 'true') {
      changeIsInMiniprogramState()
    } else {
      function onWeixinJSBridgeReady() {
        if (window.__wxjs_environment === 'miniprogram'){
          changeIsInMiniprogramState()
        }
      }
      if (!window.WeixinJSBridge || !WeixinJSBridge.invoke) {
        document.addEventListener('WeixinJSBridgeReady', onWeixinJSBridgeReady, false)
      } else {
        onWeixinJSBridgeReady()
      }
    }
    // retrieveHomeData()

    // 在小程序中,模拟调用接口
    function retrieveHomeData() {
      $('#send-btn').bind('click', (e) => {
        let name = $('#name').val()
        console.log('name', name);
        let authorization = $.cookie("Authorization") || ''
        $.ajax({
          url: `http://localhost:3000/user/home?name=${name}`,
          method: 'get',
          headers: {
            'Authorization': authorization
          },
          success(res) {
            console.log('res', res)
            $("#output").text(JSON.stringify(res))
          },
          fail(err) {
            $("#output").text(err)
          }
        })
      })
      $('#share-btn').bind('click', (e) => {
        console.log('share btn click')
        wx.miniProgram.postMessage({
          data: JSON.stringify({
            action: 'share',
            title: window.document.title
          })
        });
        // wx.miniProgram.navigateBack()
      })
    }
  </script>
  <script type="text/javascript" src="/static/js/vconsole.min.js"></script>
  <script>
    // 初始化
    var vConsole = new VConsole();
    console.log('Hello world');
  </script>
</body>
</html>

接口端

// 一个web-view页面,是给小程序加载的
router.all('/web-view', async function (ctx) {
  let token = ctx.request.query.token
  ctx.session.sessionKeyRecordId = ~~ctx.session.sessionKeyRecordId + 1

  if (token) ctx.cookies.set('Authorization', `Bearer ${token}`, { httpOnly: false });
  let title = 'web view from koa' + ctx.session.sessionKeyRecordId

  await ctx.render('index', {
    title,
    arr: [1, 2, 3],
    now: new Date()
  })
});