微信网页登录逻辑与完成

如今的网站开辟,都绕不开微信登录(毕竟微信已成为公民东西)。虽然文档已写得很细致,然则关于没有经验的开辟者照样轻易踩坑。

所以,特地纪录一下微信网页认证的交互逻辑,也轻易本身往后回查:

  1. 加载微信网页sdk
  2. 绘制上岸二维码:新tab页面绘制 / 本页面iframe绘制
  3. 用户扫码上岸,前端跳入回调网址
  4. 回调网址进一步做逻辑处置惩罚,如果是页内iframe绘制二维码,须要关照顶级页

🔍浏览更多系列文章 / 浏览原文🔍

微信网页SDK加载

在多人团队合作中,加载资本的代码须要分外警惕。由于能够会有多个开辟者在统一营业逻辑下挪用,这会形成资本的反复加载。

处置惩罚要领有两种,第一种是对外暴露过剩接口,特地check是不是反复加载。然则考虑到挪用者每次在加载前,都须要显式挪用check()要领举行搜检,不免会有脱漏。

所以采纳第二种要领–设想形式中的缓存形式,代码以下:

// 备忘录形式: 防备反复加载
export const loadWeChatJs = (() => {
  let exists = false; // 办理
  const src = '//res.wx.qq.com/connect/zh_CN/htmledition/js/wxLogin.js'; // 微信sdk网址

  return () => new Promise((resolve, reject) => {
    // 防备反复加载
    if(exists) return resolve(window.WxLogin);
    
    let script = document.createElement('script');
    script.src = src;
    script.type = 'text/javascript';
    script.onerror = reject; // TODO: 失利时刻, 能够移除script标签
    script.onload = () => {
      exists = true;
      resolve(window.WxLogin);
    };
    document.body.appendChild(script);
  });
})();

绘制上岸二维码

依据《微信上岸开辟指南》,将参数通报给window.WxLogin()即可。

// 微信默许设置
const baseOption = {
  self_redirect: true, // true: 页内iframe跳转; false: 新标签页翻开 
  id: 'wechat-container', 
  appid: 'wechat-appid',
  scope: 'snsapi_login',
  redirect_uri: encodeURIComponent('//1.1.1.1/'),
  state: '',
};

export const loadQRCode = (option, intl = false, width, height) => {
  const _option = {...baseOption, ...option};

  return new Promise((resolve, reject) => {
    try {
      window.WxLogin(_option);
      const ele = document.getElementById(_option['id']);
      const iframe = ele.querySelector('iframe');
      iframe.width = width? width : '300';
      iframe.height = height? height : '420'; 
      // 处置惩罚国际化
      intl && (iframe.src = iframe.src + '&lang=en');
      resolve(true);
    } catch(error) {
      reject(error);
    }
  });
};

在须要运用的营业组件中,能够在周期函数componentDidMount挪用,下面是demo代码:

componentDidMount() {
    const wxOption = {
        // ...
    };
    loadWeChatJs()
        .then(WxLogin => loadQRCode(wxOption))
        .catch(error => console.log(`Error: ${error.message}`));   
}

回调网址与iframe通讯

这一块我以为是微信上岸交互中最庞杂和难以明白的一段逻辑。开首有讲过,微信二维码衬着有2中体式格局,一种是翻开新的标签页,另一种是在指定id的容器中插进去iframe。

毫无疑问,第二种交互体式格局更友爱,由于要触及不同级层的页面通讯,代码处置惩罚也更具应战。

为了轻易申明,请先看模仿的数据设置:

// redirect 地点会被后端拿到, 后端重定向到此地点, 前端会接见此页面
// redirect 地点中的参数, 是前端职员留给本身运用的; 后端会依据营业须要, 增加更多的字段, 然后一同返回前端
const querystr = '?' + stringify({
  redirect: encodeURIComponent(`${window.location.origin}/account/redirect?` + stringify({
    to: encodeURIComponent(window.location.origin),
    origin: encodeURIComponent(window.location.origin),
    state: 'login'
  })),
  type: 'login'
});

const wxOption = {
  id: 'wechat-container',
  self_redirect: true,
  redirect_uri: encodeURIComponent(`//1.1.1.1/api/socials/weixin/authorizations${querystr}`) // 微信回调要求地点
};

前后端、微信服务器、用户端交互逻辑

根据上面的设置,我形貌一下前端、用户端、微信服务器和后端交互的逻辑:

  1. 前端依据wxOption加载了二维码,一切信息都放在了二维码中。同时监听微信服务器的音讯。
  2. 用户手机扫码,关照微信服务器肯定上岸。
  3. 微信服务器接受到用户的扫码要求,转发给前端。
  4. 前端收到微信服务器传来音讯,依据wxOption的redirect_uri参数,跳转到此url地点。注重:

    • 这个接口地点是后端的,要求体式格局是GET
    • 前端经由过程拼接params照顾参数
    • 地点会被拼接微信服务器传来的一个暂时token,用于交给后端调换用户民众密钥
  5. 后端接收到/api/socials/weixin/authorizations${querystr}的要求,decode解码querystr中的信息。然后向微信服务端要求用户民众密钥。根绝前后端的商定(demo顶用的是redirect字段),重定向到前端指定的redirect字段,而且拼接用户民众密钥等更多信息。
  6. 前端知悉重定向,跳到重定向的路由(demo顶用的是/account/redirect)
  7. 在对应的路由处置惩罚后端传来的用户密钥等数据即可
  8. 至此,微信认证的四端交互逻辑完成

跨Iframe通讯

前面流程走完了,如今的状况是页面中iframe的二维码地区,已被替代成了/account/redirect?...的内容。

为了完成通讯,须要在页面的周期中监听message事宜,并在组件卸载时,卸载此事宜:

componentDidMount() {
  // ... ...
  
  window.addEventListener('message', this.msgReceive, false);
}

componentWillUnmount() {
  window.removeEventListener('message', this.msgReceive);
}

msgReceive(event) {
  // 监测是不是是平安iframe
  if(!event.isTrusted) {
    return;
  }
  console.log(event.data); // 猎取iframe中传来的数据, 进一步举行逻辑处置惩罚
}

而在/account/redirect?...路由对应的组件中,我们须要剖析路由中的params参数,根据营业逻辑搜检后,将效果通报给前面的页面:

componentDidMount() {
    // step1: 猎取url中params参数
    const querys = getQueryVariable(this.props.location.search);
    // step2: 搜检querys中的数据是不是符合要求 ... 
    // step3: 向顶级页面通报音讯
    return window.parent && window.parent.postMessage('data', '*');
}

至此,微信网页认证的流程完成。

更多:关于iframe通讯的更多细节,请检察MDN的文档

更多系列文章

⭐在GitHub上珍藏/定阅⭐

《前端学问系统》

《设想形式手册》

《Webpack4渐进式教程》

⭐在GitHub上珍藏/定阅⭐

    原文作者:心谭
    原文地址: https://segmentfault.com/a/1190000019025598
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞