strapi v5-无插件打通微信openid登录授权,strapi确实是前端能快速上手的绝佳后端API

一、背景

在strapi v4中,我用了一款微信插件来实现微信的登录token授权。

具体可见:文末链接

目前该插件依然有人在用,但是作者似乎已经放弃维护,上一次更新还停留在853天,差不多3年了。

strapi5依然可用该插件,但我想自己动手开发个custom api,用来实现类似的功能。

二、在strapi 5中开发微信登录模块

我们可以在 Strapi 中创建一个 自定义 API 接口,用于处理微信 code 并获取 openid,然后存入数据库。

📌步骤大纲

  1. 创建一个新的 API 端点wx-auth)用于处理 code 换取 openid
  2. 调用微信服务器 API,获取 openid 并返回给前端。
  3. 在 Strapi 数据库中存储 openid(如果有必要)。

1. 创建 Strapi API 端点

你可以使用 Strapi 的 generate 命令创建 API:

# 在 Strapi 项目目录下运行
npx strapi generate api wx-auth

这将在 src/api/ 目录下创建一个 wx-auth 目录,包含 controllersservicesroutes 文件。

如果使用以上指令报错,可以执行如下命令,引导式创建:

# 在 Strapi 项目目录下运行
strapi generate

image-20250409095735729

选择api,输入api的名字,比如wx-auth,是否用于插件,选择N即可。

image-20250409100002655


2. 编辑 wx-auth 控制器

修改 src/api/wx-auth/controllers/wx-auth.js 文件:

const axios = require('axios');

module.exports = {
  async getOpenId(ctx) {
    try {
      const { code } = ctx.request.body;
      if (!code) {
        return ctx.badRequest('缺少 code 参数');
      }

      const appid = process.env.WX_APPID || '你的微信小程序AppID';
      const secret = process.env.WX_SECRET || '你的微信小程序密钥';

      // 请求微信 API 交换 openid
      const url = `https://api.weixin.qq.com/sns/jscode2session?appid=${appid}&secret=${secret}&js_code=${code}&grant_type=authorization_code`;
      const response = await axios.get(url);

      if (response.data.errcode) {
        return ctx.badRequest('获取 openid 失败', response.data);
      }

      const { openid, session_key } = response.data;

      return ctx.send({ openid, session_key });
    } catch (error) {
      ctx.internalServerError('服务器错误', error);
    }
  }
};

📌 说明

  • 这个 API 接收前端传来的 code,然后调用 微信官方 API 获取 openid
  • openid 作为唯一用户标识,可以存数据库,或者直接返回给前端。

🚀 进阶

如果你需要 存储访客信息,可以扩展 wx-auth API,让它在 getOpenIdopenid 存入 Strapi 数据库,例如:

const { createCoreController } = require("@strapi/strapi").factories;
const axios = require("axios");

module.exports = createCoreController("api::wx-auth.wx-auth", ({ strapi }) => ({
  async getOpenId(ctx) {
    try {
      const { code } = ctx.request.body;
      if (!code) {
        return ctx.badRequest("缺少 code 参数");
      }

      const appid = process.env.WX_APPID;
      const secret = process.env.WX_SECRET;

      // 请求微信 API 获取 openid
      const url = `https://api.weixin.qq.com/sns/jscode2session?appid=${appid}&secret=${secret}&js_code=${code}&grant_type=authorization_code`;
      const response = await axios.get(url);
      
      if (response.data.errcode) {
        return ctx.badRequest("获取 openid 失败", response.data);
      }

      const { openid, session_key } = response.data;

      // 查询数据库是否已有该 openid
      const existingUser = await strapi.db.query("api::wx-auth.wx-auth").findOne({
        where: { openid },
      });

      if (!existingUser) {
        // 如果用户不存在,创建新用户
        await strapi.db.query("api::wx-auth.wx-auth").create({
          data: { openid },
        });
      }

      return ctx.send({ openid, session_key });
    } catch (error) {
      ctx.internalServerError("服务器错误", error);
    }
  },
}));

这样,每个 访客的 openid 都会 自动存入 Strapi 数据库,后续可以用于统计或管理。

如果不需要存储用户的openid,可以直接使用上面的简版- wx-auth 控制器

注意:不要明文传输接口生成的session_key,否则会收到微信小程序的风控

image-20250512165658312

如上,接口明文返回了session_Key,不被允许,会收到微信小程序的风控提醒。

image-20250512170039732

修复方法是,将src/api/wx-auth/controllers/wx-auth.js中返回的session_Key注释即可。

3. 添加 API 路由

修改 src/api/wx-auth/routes/wx-auth.js,添加 POST /getOpenId 路由:

module.exports = {
  routes: [
    {
      method: "POST",
      path: "/getOpenId",
      handler: "wx-auth.getOpenId",
      config: {
        auth: false, // 允许所有人访问
        policies: [],
      },
    },
  ],
};

🔹 4. 在 .env 配置小程序 AppID

在 Strapi 项目的根目录 .env 文件中,添加微信小程序的 AppID 和密钥

WX_APPID=你的微信小程序AppID
WX_SECRET=你的微信小程序密钥

小程序appID和秘钥,需要登录对应的小程序管理后台(https://mp.weixin.qq.com/)获取

然后 重启 Strapi 使配置生效:

npm run develop

🔹 5. 配置content-types

如果你重启 Strapi失败,getOpenId接口报错,则可能还需要增加content-types配置。

image-20250409104259634

wx-auth文件夹下,新增content-types文件夹,然后在下面再新增wx-auth文件夹,最后新增一个schema.json文件:

{
  "kind": "collectionType",
  "collectionName": "wx_auth",
  "info": {
    "singularName": "wx-auth",
    "pluralName": "wx-auths",
    "displayName": "WxAuth"
  },
  "options": {
    "draftAndPublish": false
  },
  "attributes": {
    "openid": {
      "type": "string",
      "unique": true
    }
  }
}

三、在小程序中使用 getOpenId 接口

在微信小程序 onLoad 事件中,调用 Strapi 端点获取 openid

onLoad() {
  wx.login({
    success: res => {
      if (res.code) {
        wx.request({
          url: 'https://your-strapi-api.com/api/getOpenId',
          method: 'POST',
          data: { code: res.code },
          success: res => {
            if (res.data.openid) {
              this.setData({ openid: res.data.openid });
            } else {
              wx.showToast({ title: '获取 openid 失败', icon: 'none' });
            }
          }
        });
      }
    }
  });
}

返回的数据如下:

{
    "openid":"opU1T5YzVKSpA23LhVyIAq2cJiF4",
}

这样,你就可以拿到用户的唯一ID了。

四、与strapi-wechat-miniprogram-auth插件返回的数据对比

插件返回的数据如下:

    {
      "token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6MSwiaWF0IjoxNjY3NTM3MzU5LCJleHAiOjE2NzAxMjkzNTl9.giRP146cEV0wyIh98D3KJigHShsEGofedtW5YYckzsQ",
      "user": {
        "id": 1,
        "username": null,
        "email": null,
        "provider": "local",
        "confirmationToken": null,
        "confirmed": true,
        "blocked": false,
        "createdAt": "2022-11-04T02:41:27.149Z",
        "updatedAt": "2022-11-04T02:41:27.149Z",
        "openid": "oFHxc5TV5VKscIudqlmfx9JpK4d4",
        "wechatUserInfo": {
          "nickName": "wfz",
          "gender": 0,
          "language": "zh_CN",
          "city": "",
          "province": "",
          "country": "",
          "avatarUrl": "https://A-WECHAT-AVATAR-LINK"
        }
      }
    }

可以看到,自己开发的api,返回的数据只有一个openid ,可能还不足以满足我们开发项目的实际需求,你也可以自行修改wx-auth.js的代码,让其返回更多的数据,比如当前用户信息。

大概思路是,在前端调用wx.login之前,先调用wx.getUserProfile获取用户信息,比如展示一键登录按钮,获取成功后,再调用wx.login,并且将wx.getUserProfile获得的用户信息传递给wx-auth进行转存和处理等。

你也可以查看插件原作者,是如何将用户信息、token等保存和返回给前端的:https://juejin.cn/post/7182122916505944124

简单的小程序代码:

wx.getUserProfile({
    desc: '展示用户信息', // 声明获取用户个人信息后的用途,后续会展示在弹窗中,请谨慎填写
    success: (res) => {
        const userInfo=res.userInfo;
        wx.login({
          success: res => {
            // 发送res.code到后台换取openId,sessionKey,unionId
            wx.request({
              url: baseURL + '/api/getOpenId',
              method: 'post',
              data: {
                code: res.code,
              	userInfo: userInfo
              },
              success(res3) {
				 //这里是后端处理后,返回的信息
              }
            })
          }
        })
    }
})

注意:修改后,需要重启strapi服务。

✅ 总结

  1. 用户打开小程序,wx.login() 获取 code
  2. 前端发送 codeStrapi API (/api/getOpenId)。
  3. Strapi 后端请求微信 API,换取 openid 并返回给前端。
  4. 前端拿到 openid,在需要的地方使用。
  5. 如果简单项目可用自行开发的api,如果是复杂应用或需要获取token,可以考虑用插件

相关链接

  1. https://market.strapi.io/plugins/strapi-wechat-miniprogram-auth
  2. https://juejin.cn/post/7182122916505944124

如果你在开发strapi时遇到了问题,可以在下方与我联系,作为你的strapi免费顾问。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值