✏️
ougege
  • README
  • Docs
    • index
    • Articles
      • AI
        • 体验Chrome AI
        • 体验Cloudflare Workers AI
        • 体验deepseek
      • CSS
        • CSS优化-PurgeCSS
        • 实用效果
        • 开发常用样式
      • Deepin
        • deepin20安装mysql
        • deepin使用tensorflow入门机器学习
        • deepin安装cuda和cuDNN
        • deepin安装lamp
        • deepin安装nvidia驱动
        • deepin安装oh my Zsh
        • deepin安装p7zip
        • deepin换源
        • 安装deepin系统后要做的事
      • Docker
        • CI/CD搭建配置
        • deepin搭建docker环境
        • docker安装和使用gitlab
        • docker搭建nginx+php环境
      • Essay
        • IOS申请邓白氏编码
        • Markdown-Mermaid
        • Markdown Use
        • webview白屏的问题查找和修复
        • 前端开发对接问题和解决办法汇总
        • 国务院机构改革方案
        • 国家级智库
        • 实用网站推荐
        • 常用Markdown数学公式语法
        • 强烈推荐前端要安装的vscode扩展
        • 新建销售计划-页面卡死问题分析
        • 海淘入坑手册
        • 竞品研究
        • 足球知识速成
      • Git
        • GitBook安装和常用命令
        • GitKraken免费版本
        • Git安装和配置
        • Git异常处理
        • Git Worktree使用
        • 前端工程化相关的实用git命令
      • JS
        • ESM模块导出方式对比
        • Emoji多端统一处理
        • JS发布订阅模式
        • JS性能优化
        • JS标准内置对象
        • JS链式调用原理
        • Promise介绍和使用
        • Range的使用
        • Vue+Oauth登录实现
        • Vue实现富文本插入Emoji
        • chrome扩展入门
        • es5新特性
        • es6常用特性
        • es常用片段
        • uniapp使用eslint校验代码
        • 与移动端通信
        • 优秀js库moment
        • 使用vue-socketio
        • 实现一个中间件
        • 小程序webview调试
        • 常用snippets
        • 常用正则
        • 常用的设计模式
        • 微信jssdk封装使用
        • 浏览器宏任务和微任务
        • 浏览器的5种Observer
        • 深入理解赋值、浅拷贝、深拷贝
        • 解析vue指令clickoutside源码
        • 键盘事件与KeyBoardWrapper交互
        • 高德地图常用方法封装
        • 高阶函数片段
      • Network
        • 使用Lighthouse分析前端性能
        • 前后端启用https
        • 宝塔nginx安装ngx_brotli
        • 比较gz与br加载速度
        • 浏览器https提示不安全
        • 浏览器提示HSTS
        • 简单使用tcpdump
        • 静态资源gzip优化
      • Node
        • CommonJS模块导出方式对比
        • Taro command not found 多平台解决方案
        • koa使用和API实现
        • node安装报错Unexpected-token
        • 使用nvm和nrm
        • 使用uniapp给小程序添加云函数
        • 使用verdaccio搭建本地npm仓库
        • 使用vue-cli搭建vue项目
        • 安装Node.js和npm配置
        • 编译成cjs和mjs的思路解析
        • 让你的npmPackage同时支持cjs和mjs
        • 通过GithubAction将内容部署到vps
      • Python
        • Python源管理
        • Python版本管理
        • mitmproxy抓包
        • 微信公众平台开发爬坑经历
      • Shell
        • Ubuntu安装deepin桌面环境
        • Ubuntu安装flatpak软件
        • Ubuntu安装wireshark
        • Ubuntu常见问题汇总
        • dell G3装系统无法识别第二块硬盘
        • linux下virtualbox用gho还原系统
        • mysql常用命令
        • navicat连接一键集成环境的mysql
        • nginx常用命令
        • pm2常用命令
        • virtualbox虚拟机和宿主机互相复制粘贴
        • vps内资源通过mega快传到本地
        • vps报错temporary failure in name resolution
        • vscode修改文件监控数
        • windows+linux双系统引导修复
        • zsh常用插件和命令
        • 一键搭建ChatGPT web版
        • 使用V2ray,CloudFlare Warp解锁GPT
        • 使用vscode进行java开发
        • 利用zx和SSHKey发布代码到服务器
        • 反爬虫一些方案总结和尝试
        • 安装1Panel
        • 安装Bt面板
        • 安装Ubuntu22.04后要做的事
        • 无显示器linux设置默认分辨率
        • 特别实用的shell命令
        • 解决linux安装xmind缺少依赖报错
      • Standards
        • CSS格式化之stylelint
        • CSS规范
        • HTML规范
        • JS规范
        • commit规范
        • 使用husky+commitlint规范代码提交
        • 使用semantic-release自动管理版本号
        • 命名规范
        • 图片规范
        • 版本编号规范
      • Wall
        • 科学上网-Cloudflare-Pages
        • 科学上网-Cloudflare-Warp
        • 科学上网-Geph
        • 科学上网-RackNerd
        • 科学上网-Slicehosting
        • 科学上网-Surfshark
        • 科学上网-Tor
        • 科学上网-XX-NET
        • 科学上网-heroku
        • 科学上网-shadowsock
        • 科学上网-v2ray使用
        • 科学上网-v2ray搭建
        • 科学上网-浏览器代理
        • 科学上网-让终端走代理
      • Windows
        • SourceTree破解免登录(windows版)
        • git bash交互提示符不工作
        • nexus 7 2013 wifi 刷机
        • tree命令生成文件目录
        • 利用charles抓包app
        • 安装Openssl
        • 安装msi文件报错2503和2502
        • 神器vimium使用说明
        • 自用host
        • 解决win10扩展出来的屏幕模糊
        • 解决安装Adobe Air时发生错误
    • Snippets
      • zsh
        • docker
        • extract
        • git-commit
        • git
        • mysql-macports
        • npm
        • nvm
        • pip
        • pm2
        • systemd
        • ubuntu
        • vscode
Powered by GitBook
On this page
  • 背景
  • 前置条件
  • 步骤
  • 注意事项
  • 参考

Was this helpful?

  1. Docs
  2. Articles
  3. JS

小程序webview调试

Previous实现一个中间件Next常用snippets

Last updated 10 months ago

Was this helpful?

背景

由于项目历史原因,接手的小程序代码是原生写的,微信一套,支付宝一套,导致后续迭代的时候微信上的同样的功能要做俩遍,兼容支付宝,很是麻烦。后来讨论决定新增的部分功能,复杂度不高的,优先使用 webview 实现,小程序里使用 webview 访问,通过注入 token 交互.

前置条件

  1. 小程序 webview 访问仅支持 https

  2. webview 地址仅支持域名,不支持 IP 和端口

步骤

  1. 微信公众平台进入公众号设置的功能设置里填写 JS 接口安全域名

  2. 前端静态资源服务器上传微信校验文件并通过验证

  3. 前端引入 jweixin ,并初始化需要申请的接口列表

  • index.html 引入 jweixin

  • onload : 首次进入将 url 存储用于 jWeixin 验签

  • 初始化,申请接口列表

::: code-group

<script src="https://res.wx.qq.com/open/js/jweixin-1.6.0.js"></script>
console.log(location.href.split('#')[0], '-------------------------pageOnloadInit执行----------------------')
storage.set(storage.webviewSignUrl, location.href.split('#')[0])
initJssdk (util, api, data) {
  return new Promise((resolve, reject) => {
    const apiSrc = api.wxminiappWxAppGetSign
    const params = {
      url: data.link
    }
    uni.showLoading()
    util.postData.call(this, apiSrc, params, 'POST', function (res) {
      if (res) {
        const data = res.data.data
        jWeixin.config({
          debug: true, // 开启调试模式
          appId: configAll.config.officialAccountAppId, // 必填,公众号的唯一标识
          timestamp: data.timestamp, // 必填,生成签名的时间戳
          nonceStr: data.nonceStr, // 必填,生成签名的随机串
          signature: data.signature, // 必填,签名
          jsApiList: [
            'openLocation', // 使用微信内置地图查看位置接口
            'getLocation' // 获取地理位置接口
          ], // 必填,需要使用的JS接口列表
          success: (res) => {
            console.log(res, 'jWeixin/success')
            resolve(res)
          },
          fail: (err) => {
            console.log(err, 'jWeixin/fail')
            reject(err)
          }
        })
        jWeixin.ready(function (res) {
          console.log(res, '-------------------------jWeixin.ready----------------------')
          // config信息验证后会执行ready方法,所有接口调用都必须在config接口获得结果之后,config是一个客户端的异步操作,所以如果需要在页面加载时就调用相关接口,则须把相关接口放在ready函数中调用来确保正确执行。对于用户触发时才调用的接口,则可以直接调用,不需要放在ready函数中。
        })
        jWeixin.error(function (res) {
          console.log(res, '-------------------------jWeixin.error----------------------')
          // config信息验证失败会执行error函数,如签名过期导致验证失败,具体错误信息可以打开config的debug模式查看,也可以在返回的res参数中查看,对于SPA可以在这里更新签名。
        })
      }
      uni.hideLoading()
    }, function (err) {
      uni.hideLoading()
      uni.showToast({ title: err.errMsg, icon: 'none', duration: 1500 })
      reject(err)
    })
  })
}

:::

注意事项

  1. 微信签名一旦调试成功,把 debug: true 注释,否则会在 ios 调试引起未知错误,其实已经验签成功了,但是开了调试页面一直报错

  2. 路由跳转不能是 tabBar ,仅支持相对路径

    jWeixin.miniProgram.redirectTo({ url: '../login/login' }, (res) => {
      console.log(res, '-------------------------navigateTo/packageA/pages/login/login----------------------')
    }, (err) => {
      console.log(err, '-------------------------navigateTo/err----------------------')
    })
  3. 在 webview 内部没有更好的办法判断当前webview 外部环境是微信还是支付宝,采用注入runEnv 到 webview

    /**
     * 对应运行环境执行函数的callback
    * @param {*} e
    * @param {*} obj
    */
    const runEnvCallback = (e = 'mp-weixin', obj) => {
      const defaultEnvObj = renderEnvFormatFn()
      Object.assign(defaultEnvObj, obj)
      obj[e]()
    }
    
    /**
     * 生成所有运行环境对应的基础对象
    * @returns object
    */
    const renderEnvFormatFn = () => {
      const fn = () => { console.log('未找到对应环境回调函数') }
      return {
        app: fn,
        web: fn,
        'mp-weixin': fn,
        'mp-alipay': fn,
        'mp-baidu': fn,
        'mp-toutiao': fn
      }
    }
    
    // 使用
    util.runEnvCallback(this.runEnv,
    {
      'mp-weixin': () => {
        jWeixin.miniProgram.postMessage({ data: postData })
      }
    })
  4. 所有页面公共要执行的逻辑

    /**
     * 页面onLoad初始化参数
    */
    const pageOnloadInit = (op) => {
      return new Promise((resolve, reject) => {
        try {
          console.log(location.href.split('#')[0], '-------------------------pageOnloadInit执行----------------------')
          // 首次进入将url存储用于jWeixin验签
          storage.set(storage.webviewSignUrl, location.href.split('#')[0])
          // testUrl: http://192.168.2.181:8083/html/#/pages/index/index?token=831eb544-aa27-4869-a878-3c5eb7ac5417
          if (op.vConsole === '1') {
            const vConsole = new Vconsole()
            console.log(vConsole, '-------------------------vConsole----------------------')
          }
          if (op.token) {
            store.commit('user/SET_TOKEN', op.token)
          }
          if (op.tabType) {
            store.commit('shop/SET_TABTYPE', Number(op.tabType))
          }
          if (op.runEnv) {
            store.commit('system/SET_RUNENV', op.runEnv)
          }
          if (op.hasLocation) {
            const hasLocation = op.hasLocation === 'true'
            store.commit('location/SET_HASLOCATION', hasLocation)
          }
          if (op.longitude && op.latitude) {
            const pos = { latitude: Number(op.latitude), longitude: Number(op.longitude) }
            store.commit('location/SET_MINIPOSITION', pos)
            store.commit('location/SET_UNIPOSITION', pos)
          }
          console.log(store.getters, '-------------------------store.getters----------------------')
          resolve(true)
        } catch (err) {
          reject(err)
        }
      })
    }

参考

服务端签名
服务端签名
webview文档