前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >微信公众号网页开发-Vue项目坑点分析

微信公众号网页开发-Vue项目坑点分析

作者头像
全栈程序员站长
发布于 2022-09-06 03:08:18
发布于 2022-09-06 03:08:18
1.1K00
代码可运行
举报
运行总次数:0
代码可运行

大家好,又见面了,我是你们的朋友全栈君。

项目背景

该系统为商品推广系统,微信交互涉及网页授权和网页分享,年前使用django框架做了基础版,节后项目升级,功能更加丰富,使用vue框架做前后端分离开发,前后端分离开发提升了开发效率,也埋藏了很多坑点。。。

坑点分析及解决

开发前需要进入公众号后台配置”JS接口安全域名”及“授权回调页面域名”,如果服务端要获取token,还需要配置”IP白名单”,详细信息可以查阅官网。

微信公众号官方文档:微信公众平台开发概述 | 微信开放文档微信开发者平台文档

https://developers.weixin.qq.com/doc/offiaccount/Getting_Started/Overview.html

1. 网页授权

网页授权逻辑:

浏览器通过网址请求资源–>获取微信授权链接–>打开授权链接获取code–>获取openid及用户头像、昵称等。

代码:

login.vue

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
getWxOpenid(){
      if (!this.openid) {
        // 获取cope
        let code = this.$route.query.code;
        if (code) {
          // 获取openid
          api.get(URL.COM_GET_OPENID(1, code)).then(response => {
            this.openid = response.openid;
            localStorage.setItem('openid', this.openid);

          }).catch(error=>{
            console.log(error);
          })
        } else {
          // 获取微信认证地址
          api.get(URL.COM_GET_AUTHORIZE_URL(1, window.location.href)).then(response => {
            window.location.replace(response.authorize_url);
          }).catch(error=>{
            console.log(error);
          })
        }
      }
    }

后端接口:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
# COM_GET_AUTHORIZE_URL对应接口
def get_authorize_url(request):
    scope = request.GET.get('scope', 'snsapi_base')  # 静默授权
    appid = settings.WX_APP_ID
    authorize_url = get_authorize_url_com(redirect_uri=url, scope=scope, appid=appid)
    return ajax.ajax_ok(dict(authorize_url=authorize_url))

# COM_GET_OPENID对应接口
def get_openid(request):
    code = request.GET.get("code")
    appid = settings.WX_APP_ID
    secret = settings.WX_APP_SECRET
    url = 'https://api.weixin.qq.com/sns/oauth2/access_token'
    params = {
        'appid': appid,
        'secret': secret,
        'code': code,
        'grant_type': 'authorization_code',
    }
    res = requests.get(url, params=params).json()
    openid = res.get("openid")  # 获取openid
    return ajax.ajax_ok(dict(openid=openid))

坑点

以下坑点AndroidiOS都有,处理方案都可行

1. vue-router默认为hash模式,此时添加的code参数会添加到#前面造成授权失败,处理方案是使用history模式。

2. 生成授权链接需要传入当前网址,需要使用encodeURIComponent编码

2. 微信分享

微信网页分享可以将网址以卡片的形式转发,提升用户体验,但坑点也最多

微信分享最难的部分就是权限验证,主要逻辑是根据当前网址生成签名配置到config函数,微信sdk会重新生成签名进行比对验证。

share.vue

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
// 微信分享
      wechatShare(){
        let url = window.location.href;
        if (window.__wxjs_is_wkwebview) {
          url = this.$store.state.entryUrl;    // 第一次进入应用的url,否则获取签名失败
        }
        api.get(URL.COM_GET_SIGNATURE(url)).then(res => {
          wx.config({
            debug: false, //开启调试模式,调用的所有api的返回值会在客户端alert出来,若要查看传入的参数,可以在pc端打开,参数信息会通过log打出,仅在pc端时才会打印。
            appId: res.appId, //必填,公众号的唯一标识
            timestamp: res.timestamp, // 必填,生成签名的时间戳
            nonceStr: res.nonceStr, // 必填,生成签名的随机串
            signature: res.signature, // 必填,签名
            jsApiList: ['updateAppMessageShareData', 'updateTimelineShareData', 'hideMenuItems'] // 必填,需要使用的JS接口列表
          });

          // 分享地址
          let share_link = PUBLICITY_URL + `/wechat/xx/?yysessionid=${localStorage.getItem('sessionid')}`;

          var shareData = {
            title: '标题', // 分享标题
            desc: '描述', // 分享描述
            link: share_link, // 分享链接,该链接域名或路径必须与当前页面对应的公众号JS安全域名一致
            imgUrl: '', // 分享图标
            success: function () {
              // 设置成功
            }
          }

          wx.ready(function () {   //需在用户可能点击分享按钮前就先调用
            wx.updateAppMessageShareData(shareData);
            wx.updateTimelineShareData(shareData);
            wx.hideMenuItems({
              menuList: [
                "menuItem:share:qq",
                "menuItem:share:QZone",
                "menuItem:favorite",
                "menuItem:readMode",
                "menuItem:openWithSafari",
                "menuItem:openWithQQBrowser",
              ] // 要显示的菜单项
            });
          });

          wx.error(function (res) {
            console.log(res)
            // config信息验证失败会执行error函数,如签名过期导致验证失败,具体错误信息可以打开config的debug模式查看,也可以在返回的res参数中查看,对于SPA可以在这里更新签名。
          });

        }).catch(error=>{
          console.log(error);
        })
      }

接口COM_GET_SIGNATURE

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
from django.conf import settings
from django.core.cache import cache
from wechatpy import WeChatClient
from wechatpy.client.api import WeChatJSAPI
from wechatpy.session import SessionStorage


class CacheStorage(SessionStorage):
    """存储数据, 包括 token, ticket."""

    def __init__(self, prefix='wechatpy'):
        self.prefix = prefix

    def key_name(self, key):
        return '{0}:{1}'.format(self.prefix, key)

    def get(self, key, default=None):
        key = self.key_name(key)
        value = cache.get(key)
        if value is None:
            return default
        return value

    def set(self, key, value, ttl=None):
        if value is None:
            return
        key = self.key_name(key)
        cache.set(key, value, ttl)

    def delete(self, key):
        key = self.key_name(key)
        cache.delete(key)


# 微信客户端
wxclient = WeChatClient(
    appid=settings.WX_APP_ID, secret=settings.WX_APP_SECRET, session=CacheStorage()
)

# jsapi 客户端
jsapi_client = WeChatJSAPI(wxclient)
user_client = WeChatUser(wxclient)

def get_signature(request):
    data = Struct()
    url = request.GET.get('url', '')    # 有分享功能的页面地址
    noncestr = random_string(k=16)
    ticket = jsapi_client.get_jsapi_ticket()
    timestamp = get_timestamp()
    signature = jsapi_client.get_jsapi_signature(noncestr, ticket, timestamp, url)
    data.appId = settings.WX_APP_ID
    data.timestamp = timestamp
    data.nonceStr = noncestr
    data.signature = signature
    return ajax.ajax_ok(data)


def random_string(k=16):
    """随机字符串"""
    return ''.join(sample(CHAR, k))


def get_timestamp():
    """获取时间戳"""
    return int(time.time())

坑点

1. 微信分享页面生成签名

在 iOS中,只能用第一次进入应用时的 url 去请求签名才能验证成功,这是因为Vue项目为单页面应用,在切换页面时,IOS中浏览器的url并不会改变,依旧是第一次进入页面的地址,所以需要将第一次进入应用的 url 存起来,当路由变化时还是使用第一次的 url 去请求签名。而 Android 不需要这样特殊处理,这也是微信分享的一个深坑

当然也有另一种方案,使用vue-rouer hash模式,因为hash模式下路由切换页面网址均为’/‘

App.vue

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
jumpPage() {
  let auth_url = window.location.href;
  let pathname = window.location.pathname;
  let entryUrl = this.entryUrl;
  if (window.__wxjs_is_wkwebview && !entryUrl.length) {
    // 微信分享获取签名,ios需要使用第一次进入应用的url,android使用当前页面url即可
    this.$store.commit('SET_ENTRY_URL',auth_url);
  }
  let sessionid = localStorage.getItem('sessionid');
  if (sessionid) {
    // 已登陆
    if (pathname === '/login' || pathname === '/') {
      this.$router.replace('/pad');
    }
  } else {
    // 未登录
    if (pathname !== '/login') {
      this.$router.replace('/login');
    }
  }
},

2. 分享地址参数发生变化

我们的需求是在当前页面分享其他页面,例如打开a页面,分享b页面。此时a,b页面域名都要做js安全域名配置。b页面需要携带用户信息,我们的策略是携带sessionid。在开发自测阶段都OK,但交付测试后发现了一个很奇葩的问题,测试组一个妹子用手机分享后,手机打开b页面和微信pc端打开b页面,sessionid居然不一样,并且只有她个人手机出现这个bug,真是无语。。。只能各种搜索找方案,经过各种尝试,sessionid写成常量还是不行,最后改变变量名,将sessionid改为yysessionid,反复测试终于不再变化。。。。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
// 分享地址
let share_link = PUBLICITY_URL + `/wechat/xx/yysessionid=${localStorage.getItem('sessionid')}`;

问题解决了,但具体是什么原因造成的,也没有找到很清晰的答案,猜测可能是微信端使用sessionid,对分享链接参数造成了干扰。

3. ios底部导航

ios系统下,微信打开页面,有页面跳转交互,底部会生成导航栏影响用户体验

解决方案:

this.$router.replace(‘/url’); // 推荐

window.location.replace(‘url’);

参考资料

1.概述 | 微信开放文档微信开发者平台文档

https://developers.weixin.qq.com/doc/offiaccount/OA_Web_Apps/JS-SDK.html#10

2. Vue 爬坑之旅 — history 路由模式下微信分享爬坑总结_Alex_Zhao 的博客-CSDN博客_vue 微信分享 路由不要在路由钩子里面做签名,url 会不对wxShare 封装微信分享JSSDK-invalid signature签名错误的解决方案微信分享链接出现config:invalid signature错误的解决方法…

https://blog.csdn.net/zgh0711/article/details/89189856

发布者:全栈程序员栈长,转载请注明出处:https://javaforall.cn/135025.html原文链接:https://javaforall.cn

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2022年6月5,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
打包html的plugin
我们知道,在真实发布项目时,发布的是dist文件夹中的内容,但是dist文件夹中如果没有index.html文件,那么打包的js等文件也就没有意义了。
Qwe7
2022/05/29
7420
12. Vue搭建本地服务
本地服务可以提高开发效率. webpack不需要每次都打包, 就可以看到修改后的效果. 本地服务器基于node.js搭建, 内部使用二十express框架. 可以实现让浏览器自动刷新的功能.
用户7798898
2021/03/08
9870
12. Vue搭建本地服务
Webpack(三):使用 plugin 以及本地服务器搭建
webpack 自带 BannerPlugin,我们只需要在 webpack.config.js 中配置即可:
Chor
2019/11/07
1.1K0
webpack 配置文件相关解说
WebPack可以看做是模块打包机:它做的事情是,分析你的项目结构,找到JavaScript模块以及其它的一些浏览器不能直接运行的拓展语言(Scss,TypeScript等),并将其转换和打包为合适的格式供浏览器使用。
Krry
2018/09/10
6180
webpack(10)webpack-dev-server搭建本地服务器「建议收藏」
当我们使用webpack打包时,发现每次更新了一点代码,都需要重新打包,这样很麻烦,我们希望本地能搭建一个服务器,然后写入新的代码能够自动检测出来,这时候就需要用到webpack-dev-server
全栈程序员站长
2022/09/19
5680
WebPack 模块化打包工具(上)
本篇博文的内容根据 入门 Webpack,看这篇就够了 该篇文章总结而来,其代码、模块示例、功能拓展部分均有所删减,若是想了解更多关于 WebPack 的详细内容,敬请参考原文
Nian糕
2018/08/21
5520
WebPack 模块化打包工具(上)
plugin
plugin是插件的意思,通常是用于对某个现有的架构进行扩展。 webpack中的插件,就是对webpack现有功能的各种扩展,比如打包优化,文件压缩等等。
名字是乱打的
2021/12/23
7380
plugin
(4/24) webpack3.x快速搭建本地服务和实现热更新
(1)为了防止版本兼容问题,此处的webpack版本与之前的一致为:webpack@3.6.0。同时这里我们安装的webpack-dev-server版本是2.9.7版本。
wfaceboss
2019/04/08
1.1K0
(4/24) webpack3.x快速搭建本地服务和实现热更新
webpack的基础入门
现今的很多网页其实可以看做是功能丰富的应用,它们拥有着复杂的JavaScript代码和一大堆依赖包。为了简化开发的复杂度,前端社区涌现出了很多好的实践方法
javascript.shop
2019/09/04
1.5K0
webpack的基础入门
抛开vue-cli,一步步搭建vue+webpack环境
敲代码没有高亮简直蛋疼,简单带过下 sublime打开 —→ 点击Preferences下的Package Control —→ 输入install package回车 过一会儿 —→ 再输入vue syntax highlight回车,安装完毕 —→ 点击sublime选择vue component,即高亮
杨肆月
2019/08/15
5960
抛开vue-cli,一步步搭建vue+webpack环境
webpack-dev-server 使用教程
webpack-dev-server是我们在开发nodejs必须要掌握的工具,它可以帮助我们快速搭建开发环境。官网介绍如下
Karl Du
2023/10/20
5120
Webpack学习笔记
Webpack 是一个前端资源加载/打包工具。它将根据模块的依赖关系进行静态分析,然后将这些模块按照指定的规则生成对应的静态资源。找到JavaScript模块以及其它的一些浏览器不能直接运行的拓展语言(Scss,TypeScript等),并将其打包为合适的格式以供浏览器使用。 Webpack的工作方式是:把你的项目当做一个整体,通过一个给定的主文件(如:index.js),Webpack将从这个文件开始找到你的项目的所有依赖文件,使用loaders处理它们,最后打包为一个浏览器可识别的JavaScript文件。
earthchen
2020/09/24
1.4K0
9、webpack从0到1-devServer初探
讲下解决每次修改文件后需要npm run build重复运行命令打包的问题。 git仓库:webpack-demo 1、问题 每次修改完文件内容要编译代码时,需要重复手动运行npm run build就是件很麻烦的事情。 webpack中有几个不同的选项,可以帮助你在代码发生变化后自动编译代码,我这里主要说下第一、二种,相关内容webpack教程里都有。 webpack's Watch Mode webpack-dev-server webpack-dev-middleware 2、Watch模式
Ewall
2020/03/20
6660
Webpack之阿拉丁神灯
现今的web,都很丰富,它们拥有着复杂的JavaScript代码,一大堆依赖包,为了简化开发的复杂度,前端世界出现了很多很好的实践方法。
江米小枣
2020/06/15
6130
(24/24) webpack小案例--自己动手用webpack构建一个React的开发环境
通过前面的学习,对webpack有了更深的认识,故此节我们就利用前面相关知识自己动手用webpack构建一个React的开发环境,就算是一个小案例吧。
wfaceboss
2019/04/08
7830
(24/24) webpack小案例--自己动手用webpack构建一个React的开发环境
【webpack】webpack-dev-server生猛上手——让我们来搭一个webpack的微服务器吧!
[前言]:因为最近在搞****API的时候用到了webpack的externals,才发现我之前都只是用webpack做一些搭建完项目后的“收尾工作”——即打包,而没有把它纳入到项目开发的“主体过程”
啦啦啦321
2018/01/03
2.6K0
【webpack】webpack-dev-server生猛上手——让我们来搭一个webpack的微服务器吧!
Webpack搭建ES6开发环境(部分摘自网络)
首先要有node环境,进入Node.js的官网,选择对应系统下载安装包。安装node后集成了npm管理器
江一铭
2022/07/05
2820
Webpack系列——关于Webpack-dev-server配置的点点滴滴
我们都知道webpack-dev-server为我们在开发的时候提供了一个服务器以便于我们的开发,我们在使用之前当然需要安装:
用户1515472
2019/07/24
9500
webpack——快速入门【一】
https://github.com/webproblem/learning-article#webpack
思索
2024/08/16
1470
webpack——快速入门【一】
转 入门Webpack,看这篇就够了
2017年8月13日更新,本文依旧最新的webpack3.5.3将代码部分完全重写,所有代码都在Mac上正常运行过。希望依旧对你学习webpack有帮助。 写在前面的话 阅读本文之前,先看下面这个webpack的配置文件,如果每一项你都懂,那本文能带给你的收获也许就比较有限,你可以快速浏览或直接跳过;如果你和十天前的我一样,对很多选项存在着疑惑,那花一段时间慢慢阅读本文,你的疑惑一定一个一个都会消失;如果你以前没怎么接触过Webpack,而你又你对webpack感兴趣,那么动手跟着本文中那个贯穿始终
jojo
2018/05/03
1.7K0
相关推荐
打包html的plugin
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档