• 【愚公系列】2022年09月 微信小程序-webview内嵌网页的授权认证



    前言

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

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

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

    小程序相关API

    属性类型默认值必填说明最低版本
    srcstringwebview 指向网页的链接。可打开关联的公众号的文章,其它网页需登录小程序管理后台配置业务域名。1.6.4
    bindmessageeventhandler网页向小程序 postMessage 时,会在特定时机(小程序后退、组件销毁、分享)触发并收到消息。e.detail = { data },data是多次 postMessage 的参数组成的数组1.6.4
    bindloadeventhandler网页加载成功时候触发此事件。e.detail = { src }1.6.4
    binderroreventhandler网页加载失败的时候触发此事件。e.detail = { url, fullUrl },其中 fullUrl 为加载失败时的完整 url1.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
        })
      },
    })
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    <web-view bindmessage="onReceivedMessage" src="{{url}}" style="z-index:-1"></web-view>
    
    • 1

    2.登录页面

    Page({
      /**
       * 页面的初始数据
       */
      data: {},
      onShareAppMessage:function(options) {
        console.log('分享')
        return {
          title: '登陆',
          path: '/pages/index'
        }
      },
    
      /**
       * 生命周期函数--监听页面加载
       */
      onLoad: function (options) {
        // wx.showShareMenu({
        //   withShareTicket: true
        // })
      },
    })
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    <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>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    二、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>
      <h1>{{title}}</h1>
    
      {{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 id="name" value="ly" /><br /><br />
      <input id="send-btn" type="button" value="send"></input>
      <p id="output"></p>
      <input id="share-btn" 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>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    • 110
    • 111
    • 112
    • 113
    • 114
    • 115
    • 116
    • 117
    • 118
    • 119
    • 120

    接口端

    // 一个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()
      })
    });
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
  • 相关阅读:
    维修派工单,为什么要使用维修派工单
    flask-模型(models)
    centos8 yum install failed to set locale, defaulting to C
    SVR和SVM是什么关系
    Python文件操作1--知识点
    数据仓库规范
    蓝桥杯第18481题——皇家守卫(单调栈+线段树)
    【微服务|Sentinel】Sentinel快速入门|构建镜像|启动控制台
    Using lxd to do vlan test (by quqi99)
    Python生成器
  • 原文地址:https://blog.csdn.net/aa2528877987/article/details/126756227