快速实现微信公众号网页授权!附源码

6,141 阅读6分钟

一. 前言

在微信公众号开发中,常常需要使用 h5 页面公众号的授权登录,获取 jscode、openid 等,以便进一步获取用户的开放信息等,和我们系统中的真实用户做绑定。

由于授权登录开发的业务流程,大多都是微信公众号开发的第一步,所以本篇文章将使用最简洁快速的方式实现一个微信公众号 h5 授权获取 openid 流程,并附源码供大家参考!

同时,除 uni-app 外,还有一个比较好的多端解决方案FinClip 小程序容器。它是基于小程序容器化与标准化 SDK 的方案可降低集成侵入,无需重构 APP,即可将现有小程序迁移部署到自有 APP 中,一次开发也可多端运行。

二. 准备工作

在正式调试之前,确保你的微信公众号已经具备了以下条件:

  • 已经是认证的服务号或订阅号(一般为服务号)。

  • 在微信公众平台配置了合法的域名。

  • 拥有开发者权限,能够访问微信公众平台的接口文档和开发工具。

image.png

开发调试阶段

然而,在开发调试,我们可以通过微信公众平台测试账号来进行调试,只需要简单配置即可获取调用微信的接口权限。

通过微信公众平台测试账号,无需申请公众账号、可在测试账号中体验并测试微信公众平台所有高级接口。

通过微信公众平台测试账号连接配置测试账号进行开发调试!

登录成功后通过以下流程进行简单配置:

  1. 设置 JS 接口安全域名

image.png

  1. 扫描关注

image.png

  1. 设置授权回调域名

image.png

image.png

设置完成上面的流程即可以进行开发调试了,如果使用该方式可以调试成功,那么在正式公众号配置正确后也会没有问题。

如果是正式的已经获得权限的公众号,可以在相应的微信公众平台->开发接口管理->基本配置中设置

三. 授权流程

微信 h5 授权登录主要分为以下几个步骤:

1. 引导用户进入授权页面

首先,按照微信公众号的授权流程,构造一个标准 URL 来引导用户进入微信授权页面。该 URL 的格式如下:

https://open.weixin.qq.com/connect/oauth2/authorize?
appid=APPID&redirect_uri=REDIRECT_URI&response_type=code
&scope=SCOPE&state=STATE#wechat_redirect

下面对其中的参数含义解释:

  • APPID 是你的公众号的 AppID。

  • REDIRECT_URI 是授权后重定向的回调链接地址,必须要进行 URL 编码,很重要。

  • SCOPE 授权作用域,snsapi_base(静默授权,不弹出授权页面,直接跳转,只能获取用户 openid),snsapi_userinfo(弹出授权页面,可通过 openid 拿到昵称、性别、所在地等信息)。

  • STATE 用于保持请求和回调的状态,授权请求后原样带回给第三方。

在这里,我主要获取用户的 openid,所以使用的是静默授权,即 snsapi_base 作用域。

2. 用户同意授权

用户进入链接后会被重定向到微信授权页面,如果用户同意授权,则会被重定向回你设置的 REDIRECT_URI,并携带一个 code 参数。

3. 通过 code 换取网页授权 access_token

获取到 code 后,可以调用微信接口,用 code 换取网页授权 access_token。API 如下:

https://api.weixin.qq.com/sns/oauth2/access_token?
appid=APPID&secret=SECRET&code=CODE&grant_type=authorization_code

其中:

  • APPIDSECRET 是你的应用 ID 和应用密钥。

  • CODE 上一步中获得的 code。

成功响应示例如下:

{
  "access_token": "ACCESS_TOKEN",
  "expires_in": 7200,
  "refresh_token": "REFRESH_TOKEN",
  "openid": "OPENID",
  "scope": "SCOPE"
}

4. 拉取用户信息(可选)

如果在第一步选择了 snsapi_userinfo 作为 scope,那么可以通过获取到的 access_tokenopenid 来调用接口获取用户的基本信息。API 如下:

https://api.weixin.qq.com/sns/userinfo?
access_token=ACCESS_TOKEN&openid=OPENID&lang=zh_CN

注意:第 3 步和第 4 步为了说明,直接在前端代码中进行了演示,实际开发中为了安全性考虑,应将这两步放在后端进行请求。

四. 可能出现的问题

redirect_uri 参数错误

在开发调试过程中,最常出现的错误就是 redirect_uri 参数错误

Snipaste_2024-11-25_15-23-14.png

出现这个问题一般有两个原因:

  1. redirect_uri 没有使用编码处理,需要使用 encodeURIComponent 编码处理
getRedirectUri(url) {
  url = url || window.location.href
  const pos = url.indexOf('?')
  if (pos > -1) {
    return encodeURIComponent(url.substring(0, pos))
  }
  console.log(url)
  return encodeURIComponent(url)
}
  1. OAuth2.0 网页授权,授权回调页面域名填写不正确,按照以下方式填写正确即可

image.png

一般的,通过以上两步可以解决 redirect_uri 参数错误的问题

五. 注意事项

  • 安全性考虑,不要将 secret 等敏感信息暴露在前端代码中,因此前端在获取到 jscode 后可调用后台接口获取 openid 和用户信息。

  • code的有效期较短,通常为 5 分钟,因此需要尽快使用。

  • 正式授权过程中,回调地址必须是已注册的域名下的链接,否则无法成功授权。

  • 在开发过程中,建议使用微信公众平台提供的测试账号进行调试,以减少对正式环境的影响。

  • 使用 Vue 开发时,建议使用 history 路由模式,避免微信回调链接的参数拼接问题

  • redirect_uri 必须使用 encodeURIComponent 进行编码处理

通过上述步骤,你可以顺利地在微信公众号中实现 h5 页面的授权获取到 openid,从而实现用户信息的获取和后续操作。

六. 文档链接

微信公众号网页授权文档

源码

复制以下工具类 WxAuth到自己项目中,在需要授权的页面中调用即可。

注意:请替换为实际的微信appid

<!doctype html>
<html lang="zh-CN">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Weixin Auth Page</title>
  </head>
  <body>
    <script>
      class WxAuth {
        constructor(config) {
          if (!config || !config.appid) {
            throw new Error('appid parameter is required');
          }

          this.appid = config.appid;
          this.scope = config.scope || 'snsapi_base';
          this.state = config.state || 'state';
        }

        // 获取微信授权回调url
        getRedirectUri(url) {
          url = url || window.location.href;
          const pos = url.indexOf('?');
          if (pos > -1) {
            return encodeURIComponent(url.substring(0, pos));
          }
          return encodeURIComponent(url);
        }

        // 解析url参数
        getUrlParam(name) {
          const reg = new RegExp('(^|&)' + name + '=([^&]*)(&|$)');
          const r = window.location.search.substr(1).match(reg);
          if (r != null) return decodeURIComponent(r[2]);
          return null;
        }

        // 初始化
        init() {
          const code = this.getUrlParam('code');
          if (!code) {
            this.auth();
            return null;
          }
          return code;
        }

        // 微信授权
        auth() {
          const baseUrl = 'https://open.weixin.qq.com/connect/oauth2/authorize';
          const url = `${baseUrl}?appid=${this.appid}&redirect_uri=${this.getRedirectUri()}&response_type=code&scope=${this.scope}&state=${this.state}&connect_redirect=1#wechat_redirect`;
          window.location.replace(url);
        }

        // 是否为微信内置浏览器
        isWeixin() {
          return (
            typeof WeixinJSBridge === 'object' &&
            typeof WeixinJSBridge.invoke === 'function'
          );
        }

        // 关闭当前微信浏览器窗口
        closeWindow() {
          if (typeof WeixinJSBridge !== 'undefined') {
            try {
              WeixinJSBridge.call('closeWindow');
            } catch (error) {
              console.error('Failed to close WeChat window:', error);
            }
          }
        }
      }
    </script>
    <script>
      // 初始化微信授权
      const wxAuth = new WxAuth({
        appid: '', // 请替换为实际的微信appid
        scope: 'snsapi_base', // 授权作用域:snsapi_base或snsapi_userinfo
        state: 'STATE', // 可以为任意字符串
      });

      // 获取授权code
      const code = wxAuth.init();

      if (code) {
        console.log('授权成功,获取到code:', code);
        // TODO: 这里可以添加获取到code后的业务逻辑
        // 例如:调用后端接口获取用户信息等
      }
    </script>
  </body>
</html>