基于 Bun 的微信认证聚合服务,智能切换公众号/开放平台认证,可作为 Logto 的社交连接器。
- 🔀 智能分流: 根据 User-Agent 自动选择公众号或开放平台认证
- 🎯 强制指定: 通过 state 参数可强制使用特定微信应用
- 🔐 UnionID 聚合: 统一用户身份,无论从哪个入口登录
- ⚡ 高性能: 基于 Bun 运行时,极致性能
- 🔌 标准协议: 实现标准 OAuth2/OIDC 接口
用户 → Logto → WeChat Wrapper (本服务) → 微信接口
↓
根据 UA 分流
↓
公众号 or 开放平台
bun install创建 wechatapps.toml:
[[apps]]
name = "公众号应用"
alias = "oa1"
type = "official-account"
appid = "wx..."
appsecret = "..."
[[apps]]
name = "开放平台应用"
alias = "op1"
type = "open-platform"
appid = "wx..."
appsecret = "..."创建 clients.toml:
[[clients]]
clientid = "logto-client-id"
clientsecret = "logto-client-secret"
callbackUrl = "https://your-logto.com/callback/wechat"开发模式(带热重载):
bun run dev生产模式(直接运行):
bun run src/index.ts --wechat ./wechatapps.toml --clients ./clients.toml使用 PM2 管理(推荐生产环境):
首先安装 PM2:
npm install -g pm2启动服务:
# 使用脚本启动
./scripts/pm2-start.sh
# 或使用 npm 命令
bun run pm2:start常用 PM2 命令:
# 查看状态
pm2 status
# 查看日志
pm2 logs uni-wechat-oauth
# 或使用脚本
bun run pm2:logs
# 重启服务
pm2 restart uni-wechat-oauth
# 或使用脚本
bun run pm2:restart
# 停止服务
pm2 stop uni-wechat-oauth
# 或使用脚本
bun run pm2:stop
# 删除服务
pm2 delete uni-wechat-oauth
# 设置开机自启
pm2 startup
pm2 save日志文件位置:
- 错误日志:
./logs/err.log - 输出日志:
./logs/out.log - 合并日志:
./logs/combined.log
所有端点都有统一前缀:/uni-wechat-oauth-service
GET /uni-wechat-oauth-service/authorize?client_id=xxx&redirect_uri=xxx&state=xxx
参数:
client_id: 客户端 ID(配置在 clients.toml)redirect_uri: 回调地址(Logto 的回调地址)state: 状态参数(Logto 传来的,会原封不动返回)
Scope 自动选择:
- 开放平台应用:自动使用
snsapi_login(扫码登录) - 公众号应用:自动使用
snsapi_userinfo(获取用户信息) - 忽略 Logto 传入的 scope 参数
特殊功能: 在 state 中指定应用 oa1:<original_state>
用户授权确认: 当检测到微信公众号环境且使用 snsapi_userinfo 时,会先跳转到中转页面,由用户手动点击"使用微信登录"按钮,以确保能够获得完整的用户信息权限。
GET /uni-wechat-oauth-service/consent?continue=xxx
中转页面,用于微信公众号的手动授权流程(内部使用)
GET /uni-wechat-oauth-service/callback?code=xxx&state=xxx
微信授权后的回调地址(内部使用)
POST /uni-wechat-oauth-service/oidc/token
Content-Type: application/x-www-form-urlencoded
grant_type=authorization_code&code=xxx&client_id=xxx&client_secret=xxx
支持两种客户端认证方式:
- Request Body:
client_id+client_secret - Basic Auth:
Authorization: Basic base64(client_id:client_secret)
响应:
{
"access_token": "xxx",
"token_type": "Bearer",
"expires_in": 600
}GET /uni-wechat-oauth-service/oidc/me
支持两种 token 传递方式:
- Authorization Header:
Authorization: Bearer ACCESS_TOKEN - Query String:
?access_token=ACCESS_TOKEN
响应(微信原始字段):
{
"unionid": "o6_bmasdasdsad6_2sgVt7hMZOPfL",
"openid": "oLVPpjqs9BhvzwPj5A-vTYAX3GLc",
"nickname": "用户昵称",
"sex": 1,
"province": "广东",
"city": "深圳",
"country": "中国",
"headimgurl": "https://thirdwx.qlogo.cn/...",
"privilege": []
}字段说明:
unionid: 用户统一标识(跨应用唯一)openid: 用户在当前应用的唯一标识nickname: 用户昵称sex: 性别(1=男性,2=女性,0=未知)province: 省份city: 城市country: 国家headimgurl: 头像 URLprivilege: 用户特权信息
GET /uni-wechat-oauth-service/health
在 Logto 中创建自定义社交连接器:
- Authorization Endpoint:
https://oauth.yourdomain.com/uni-wechat-oauth-service/authorize - Token Endpoint:
https://oauth.yourdomain.com/uni-wechat-oauth-service/oidc/token - Userinfo Endpoint:
https://oauth.yourdomain.com/uni-wechat-oauth-service/oidc/me - Client ID: 配置在 clients.toml 中的 clientid
- Client Secret: 配置在 clients.toml 中的 clientsecret
- 用户点击 Logto 的"微信登录"
- Logto 重定向到本服务的
/authorize - 本服务判断 User-Agent 或 state 参数,选择微信应用
- 重定向到对应的微信认证页面
- 用户授权后,微信回调到
/callback - 本服务用微信 code 换取 UnionID,生成 internal_code
- 重定向回 Logto 的回调地址
- Logto 调用
/oidc/token和/oidc/me获取用户信息 - 登录完成
- 用户点击 Logto 的"微信登录"
- Logto 重定向到本服务的
/authorize - 本服务检测到微信公众号环境且 scope 为
snsapi_userinfo - 重定向到中转页面
/consent,显示"使用微信登录"按钮 - 用户手动点击按钮,触发微信授权
- 重定向到微信认证页面
- 用户授权后,微信回调到
/callback - 本服务用微信 code 换取 UnionID 和用户信息,生成 internal_code
- 重定向回 Logto 的回调地址
- Logto 调用
/oidc/token和/oidc/me获取用户信息 - 登录完成
为什么需要中转页面? 微信公众号的
snsapi_userinfoscope 需要用户主动触发授权才能获取完整的用户信息(头像、昵称等)。如果直接从 Logto 跳转到微信,可能会因为缺少用户交互而无法获得该权限。
- Runtime: Bun
- Framework: Hono
- Logger: Pino
- Storage: 内存 LRU Cache
- Config: TOML
- 规范: OAuth2 (RFC 6749) + OpenID Connect
本服务完全遵循 OAuth2 和 OpenID Connect 规范,详见 OAUTH2_COMPLIANCE.md
支持的特性:
- ✅ 标准授权码流程 (Authorization Code Flow)
- ✅ 多种客户端认证方式(Body / Basic Auth)
- ✅ 多种 token 传递方式(Header / Query String)
- ✅ OIDC UserInfo 端点
- ✅ 标准错误响应
# 为当前平台构建
bun run build
# 为 Linux 服务器构建
bun run build:linux
# 为 macOS 构建
bun run build:macos
# 为 Windows 构建
bun run build:windows无需任何运行时依赖! 打包后的可执行文件完全独立。
- Linux: Ubuntu 18.04+, Debian 10+, CentOS 8+
- 内存: 最低 128MB,推荐 512MB+
- 磁盘: 200MB 可用空间
详细部署指南请查看 DEPLOYMENT.md
MIT