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

微信公众号网页开发-Vue项目坑点分析项目背景该系统为商品推广系统,微信交互涉及网页授权和网页分享,年前使用django框架做了基础版,节后项目升级,功能更加丰富,使用vue框架做前后端分离开发,前后端分离开发提升了开发效率,也埋藏了很多坑点。。。坑点分析及解决开发前需要进入公众号后台配置”JS接口安全域名”及“授权回调页面域名”,如果服务端要获取token,还需要配置”IP白名单”,详细信息可以查阅官网。微信公众号官方文档:微信公众平台开发概述|微信开放文档微信开发者平台文档https://developers.weixi

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

项目背景

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

坑点分析及解决

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

微信公众号官方文档:微信公众平台开发概述 | 微信开放文档微信开发者平台文档微信公众号网页开发-Vue项目坑点分析https://developers.weixin.qq.com/doc/offiaccount/Getting_Started/Overview.html

1. 网页授权

网页授权逻辑:

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

代码:

login.vue

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);
          })
        }
      }
    }

后端接口:

# 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))

坑点

以下坑点Android和iOS都有,处理方案都可行

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

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

2. 微信分享

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

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

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

share.vue

// 微信分享
      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

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

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,反复测试终于不再变化。。。。

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

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

3. ios底部导航

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

解决方案:

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

window.location.replace(‘url’);

参考资料

1.概述 | 微信开放文档微信开发者平台文档微信公众号网页开发-Vue项目坑点分析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错误的解决方法…微信公众号网页开发-Vue项目坑点分析https://blog.csdn.net/zgh0711/article/details/89189856

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

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

【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛

【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...

(0)
blank

相关推荐

发表回复

您的电子邮箱地址不会被公开。

关注全栈程序员社区公众号