微信生态
受众:开发者 摘要:微信公众号、小程序和微信开放平台的 Starter 接入边界、配置方式和后续核心模块路线。
框架使用 WxJava 作为微信公众号、小程序和微信开放平台 SDK 底座,只做 Spring Boot 自动配置、多账号治理、回调与微信域业务边界,不重复实现微信协议。
登录和支付已有独立主链路:微信登录 / 社交登录优先接入 IAM 的 JustAuth provider,微信支付优先接入 Payment / Cashier 的 IJPay provider。微信生态包只承接它们不覆盖或不适合承载的微信域能力,例如公众号回调、菜单、JS-SDK、小程序 code2Session、订阅消息和开放平台 authorizer 生命周期。
能力边界
| 能力 | 当前入口 | 说明 |
|---|---|---|
| 微信公众号 | WechatOfficialAccountManager / WechatOfficialService | 基于 WxJava weixin-java-mp,已支持回调、网页授权、JS-SDK、菜单、永久素材上传 / 删除 / 图文编辑 / 查询、微信平台模板同步、模板消息和客服消息基础能力 |
| 微信小程序 | WechatMiniappManager / WechatMiniappService | 基于 WxJava weixin-java-miniapp,已支持 code2Session、手机号、订阅消息和 JSAPI / 小程序支付上下文基础能力 |
| 微信开放平台 | WechatOpenPlatformManager / WechatOpenPlatformService | 基于 WxJava weixin-java-open,已支持第三方平台预授权、授权回调、component ticket 和 authorizer 快照 |
| 账号与回调底座 | spring-open-core-wechat | 账号元数据、Secret 引用、回调事件日志、消息日志和后台查询 API |
| 统一身份桥接 | WechatIamIdentityService | 公众号 / 小程序 openid 与 unionid 绑定到 IAM iam_user;通用微信登录优先走 IAM + JustAuth |
| 微信通知通道 | Notification.send("wechat", ...) | 复用公众号模板消息、公众号客服文本和小程序订阅消息,详见 Notification Starter |
| 微信支付 | spring-open-starter-payment / Cashier / IJPay | 支付状态机不进入微信生态 starter;微信模块只输出 JSAPI / 小程序支付需要的 openid attributes |
与 JustAuth / IJPay 的关系
框架不把所有微信相关能力都塞进一个“微信中台”。重叠能力按现有体系归属:
- 登录主力:IAM + JustAuth。如果只需要微信开放平台扫码登录、公众号 OAuth 登录或企业微信登录,并且 JustAuth provider 已覆盖,优先把它作为 IAM 的登录方式配置和运维。微信生态包不管理 JustAuth provider 开关。
- 支付主力:Payment / Cashier + IJPay。如果需求是微信支付下单、退款、通知回调、账务、结算或对账,优先在 Payment / Cashier 的 IJPay provider 内实现。微信生态包不管理 IJPay provider 开关。
- 微信生态包:微信域能力补齐。公众号服务器回调、消息 / 事件、菜单、模板 / 客服消息、JS-SDK、小程序
code2Session/ 手机号 / 订阅消息、开放平台第三方授权和 authorizer 生命周期,仍由spring-open-starter-wechat+spring-open-core-wechat承接。 - 后续扩展。企业微信、视频号、小店等新增能力,应优先作为独立微信生态扩展包或 core 子能力引入;不要并入 JustAuth / IJPay,也不要让微信后台管理台管理登录或支付 provider。
Maven 依赖
<dependency>
<groupId>com.springopen</groupId>
<artifactId>spring-open-starter-wechat</artifactId>
</dependency>
<dependency>
<groupId>com.springopen</groupId>
<artifactId>spring-open-core-wechat</artifactId>
</dependency>配置示例
spring:
open:
wechat:
default-official-account: main
default-miniapp: mall
default-open-platform: component
official-accounts:
main:
app-id: wx-official-app-id
secret: ${WECHAT_OFFICIAL_SECRET}
token: ${WECHAT_OFFICIAL_TOKEN}
encoding-aes-key: ${WECHAT_OFFICIAL_AES_KEY}
miniapps:
mall:
app-id: wx-miniapp-app-id
secret: ${WECHAT_MINIAPP_SECRET}
token: ${WECHAT_MINIAPP_TOKEN}
encoding-aes-key: ${WECHAT_MINIAPP_AES_KEY}
open-platforms:
component:
component-app-id: wx-component-app-id
component-app-secret: ${WECHAT_OPEN_SECRET}
component-token: ${WECHAT_OPEN_TOKEN}
component-aes-key: ${WECHAT_OPEN_AES_KEY}账号 key 会按小写归一化。未配置账号时应用仍可启动,调用缺失账号会抛出配置异常。
回调配置与本地 smoke
微信后台配置回调 URL 时使用公网可访问地址;本地开发可用内网穿透把 http://localhost:8000 暴露给微信平台。回调入口是外部协议端点,响应为微信要求的原始文本,不套 Result<T>。
| 平台后台 | URL |
|---|---|
| 公众号服务器配置 | https://<domain>/api/v1/wechat/official/{accountCode}/callback |
| 微信开放平台第三方平台授权事件接收 URL | https://<domain>/api/v1/wechat/open-platform/{componentAccountCode}/callbacks |
本地 smoke 可先用 mock 参数验证路由和原始响应形态;签名是否通过取决于账号 token / AESKey 配置:
curl -i "http://localhost:8000/api/v1/wechat/official/main/callback?signature=mock×tamp=1&nonce=n&echostr=ok"
curl -i -X POST "http://localhost:8000/api/v1/wechat/open-platform/component/callbacks?timestamp=1&nonce=n" \
-H "Content-Type: text/xml" \
--data '<xml></xml>'预期外部协议入口返回 text/plain 的 echostr / success / invalid signature 等原始文本;普通业务 API 如 oauth/authorize-url、code2-session、pre-auth-url、query-auth 继续返回统一 JSON。
代码入口
WxMpService officialAccount = Wechat.officialAccounts().defaultService();
WxMaService miniapp = Wechat.miniapps().service("mall");
WxOpenService openPlatform = Wechat.openPlatforms().defaultService();业务模块优先依赖 Manager 或 Facade,不直接扩散 WxJava 初始化逻辑。账号配置、Secret 引用、回调持久化、消息日志、公众号网页授权、小程序上下文输入和 JS-SDK 能力由 spring-open-core-wechat 承载;通用登录 provider 与支付 provider 分别回到 IAM + JustAuth、Payment / Cashier + IJPay。
如需通过统一通知体系发送微信消息,启用 spring.open.notification.channels.wechat.enabled=true 后使用 Notification.send("wechat", ...)。该通道只做 Notification SPI 到 WechatOfficialService / WechatMiniappService 的适配,发送审计仍进入 wechat_message_log,通道成败仍进入 Notification 发送日志。
Core 管理底座
spring-open-core-wechat 提供以下后台 API:
| API | 权限 | 说明 |
|---|---|---|
GET /api/v1/admin/wechat/accounts | wechat:account:view | 查询公众号、小程序、开放平台账号元数据 |
GET /api/v1/admin/wechat/events | wechat:event:view | 查询微信回调事件接收和处理状态 |
GET /api/v1/admin/wechat/messages | wechat:message:view | 查询微信入站 / 出站消息日志 |
GET /api/v1/admin/wechat/messages/statistics | wechat:message:view | 按筛选条件汇总微信消息发送效果统计 |
GET /api/v1/admin/wechat/messages/miniapp-subscribe/effects | wechat:message:view | 按账号和模板汇总小程序订阅消息发送效果 |
POST /api/v1/admin/wechat/official/template-message | wechat:message:send | 发送公众号模板消息并写入出站消息日志 |
POST /api/v1/admin/wechat/official/kefu-text-message | wechat:message:send | 发送公众号客服文本消息并写入出站消息日志 |
POST /api/v1/admin/wechat/miniapp/subscribe-message | wechat:message:send | 发送小程序订阅消息并写入出站消息日志 |
GET /api/v1/admin/wechat/message-templates | wechat:message-template:manage | 分页查询本地公众号模板 / 小程序订阅消息预设 |
POST /api/v1/admin/wechat/message-templates | wechat:message-template:manage | 新增或更新本地消息模板预设 |
POST /api/v1/admin/wechat/message-templates/sync-official | wechat:message-template:manage | 按公众号账号从微信平台同步模板列表到本地预设 |
DELETE /api/v1/admin/wechat/message-templates/{id} | wechat:message-template:manage | 删除本地消息模板预设 |
GET /api/v1/admin/wechat/official/material/count | wechat:official-material:view | 查询公众号永久素材总数 |
GET /api/v1/admin/wechat/official/materials | wechat:official-material:view | 按素材类型分页查询公众号永久素材列表 |
POST /api/v1/admin/wechat/official/materials | wechat:official-material:manage | 上传公众号图片、语音、视频或缩略图永久素材 |
DELETE /api/v1/admin/wechat/official/materials/{mediaId} | wechat:official-material:manage | 按 Media ID 删除公众号永久素材 |
POST /api/v1/admin/wechat/official/materials/{mediaId}/news | wechat:official-material:manage | 按 Media ID 和图文索引编辑公众号图文素材 |
GET /api/v1/admin/wechat/open-platform/authorizers | wechat:open-authorizer:view | 查询微信开放平台授权方账号快照 |
POST /api/v1/admin/wechat/open-platform/authorizer-info | wechat:open-authorizer:view | 按授权方 appId 同步微信开放平台授权方资料 |
GET /api/v1/admin/wechat/official/{accountCode}/menu | wechat:official-menu:manage | 查询公众号当前自定义菜单 |
POST /api/v1/admin/wechat/official/menu | wechat:official-menu:manage | 按账号发布公众号自定义菜单 JSON |
DELETE /api/v1/admin/wechat/official/{accountCode}/menu | wechat:official-menu:manage | 删除公众号当前自定义菜单 |
Admin 前端菜单 微信生态 对应 /#/wechat,可查看账号、回调事件、消息日志、消息发送效果统计、小程序订阅模板效果、开放平台授权方状态,并提供公众号菜单查询、发布、删除、公众号永久素材统计 / 列表 / 明细查看、素材上传、删除和图文素材编辑、公众号模板消息 / 客服文本 / 小程序订阅消息发送、本地消息模板预设维护、按公众号账号从微信平台同步模板列表,以及一键应用到发送表单。
首批数据表:
wechat_account:微信账号配置,覆盖official/miniapp/open-platform。wechat_account_secret:Secret 引用和 hint,不保存 appSecret、token 或 AESKey 明文。wechat_callback_event:回调事件日志,保存 request、事件类型、payload hash 和处理状态。wechat_message_log:入站 / 出站消息日志。wechat_message_template:本地消息模板预设,保存账号、模板类型、模板 code、微信模板 ID、默认跳转、数据 schema、状态和备注。wechat_open_authorizer:微信开放平台授权方快照,保存授权状态、账号类型、主体、功能集和最近同步时间。iam_user_identity:IAM 统一身份表保存wechat-official-openid、wechat-miniapp-openid、wechat-unionid,微信模块不单独创建用户身份表。
VO 只返回脱敏后的 verifyTokenRefMasked / encodingAesKeyRefMasked,不返回明文密钥或 Secret 引用全文。
公众号核心 API
微信平台回调是外部协议入口,返回微信要求的原始文本,不套 Result<T>:
| API | 说明 |
|---|---|
GET /api/v1/wechat/official/{accountCode}/callback | 微信服务器配置校验,验签通过后原样返回 echostr |
POST /api/v1/wechat/official/{accountCode}/callback | 接收公众号消息 / 事件回调,完成验签、解析、事件日志和消息日志落库后返回 success |
普通业务查询接口继续返回 Result<T>:
| API | 说明 |
|---|---|
GET /api/v1/wechat/official/oauth/authorize-url | 按账号、回调地址、scope 和 state 创建公众号网页授权地址 |
POST /api/v1/wechat/official/js-sdk/signature | 按账号和页面 URL 创建公众号 JS-SDK 初始化签名 |
WechatOfficialService 同时提供菜单发布 / 查询 / 删除、永久素材上传 / 删除 / 图文编辑 / 统计 / 分页查询、微信平台模板列表读取、模板消息发送和客服文本消息发送 facade。模板消息和客服消息发送结果会写入 wechat_message_log 出站日志,便于后台审计。后台同步模板时使用稳定编码 wx:<templateId> 写入本地预设;重复同步会更新模板名称、内容示例和行业元数据,但保留本地运营配置的默认跳转、状态和备注。
微信统一身份 API
普通身份 API 返回 Result<T>,其中登录接口返回 IAM LoginVO,绑定接口返回本次写入的 openid / unionid 绑定信息:
| API | 认证 | 说明 |
|---|---|---|
POST /api/v1/auth/wechat-official/login | 公开 | 使用公众号网页授权 code 换取 openid / unionid,并进入 IAM 统一登录链路 |
POST /api/v1/auth/wechat-official/bind | 当前用户 | 当前登录用户使用公众号网页授权 code 绑定 openid / unionid |
POST /api/v1/auth/wechat-miniapp/login | 公开 | 使用小程序登录 code 换取 openid / unionid,并进入 IAM 统一登录链路 |
POST /api/v1/auth/wechat-miniapp/bind | 当前用户 | 当前登录用户使用小程序登录 code 绑定 openid / unionid |
公众号请求体:
{
"accountCode": "main",
"code": "wechat-oauth-code",
"lang": "zh_CN",
"device": "web",
"createUserIfAbsent": true
}小程序请求体:
{
"accountCode": "mall",
"code": "miniapp-login-code",
"device": "miniapp",
"createUserIfAbsent": true
}身份写入规则:
- 公众号 openid:
identity_type=wechat-official-openid,provider=<accountCode 小写>。 - 小程序 openid:
identity_type=wechat-miniapp-openid,provider=<accountCode 小写>。 - unionid:
identity_type=wechat-unionid,provider=wechat。 - 登录时优先使用 openid 命中已有身份;openid 未命中但 unionid 已存在时复用同一用户并补绑当前账号 openid;两者都不存在且
createUserIfAbsent=true时创建 IAM 用户。
微信账号也会进入 IAM Identity Provider discovery。GET /api/v1/auth/identity/providers 会按启用的 wechat_account 产出 wechat-official:<accountCode> 和 wechat-miniapp:<accountCode> descriptor,metadata 包含 accountCode、accountType、identityType 和 identityProvider。统一动作入口支持:
| Provider code | Flow | 通用绑定 payload |
|---|---|---|
wechat-official:<accountCode> | authorization-code | { "code": "...", "lang": "zh_CN" } |
wechat-miniapp:<accountCode> | miniapp-code | { "code": "..." } |
通用 /api/v1/auth/identity/providers/{code}/bind 会从 provider code 解析 wechat_account.account_code 原值查找微信账号,忽略 payload 中的 accountCode,并把已验证 openid subject 绑定到当前用户;IAM 身份表里的 openid provider 仍使用小写账号编码。若业务需要一次性补绑 unionid,仍使用微信专用 /api/v1/auth/wechat-official/bind 或 /api/v1/auth/wechat-miniapp/bind;这两个专用接口会继续写入 openid 和 unionid 两类身份。
用户端登录与绑定入口
App 与 PC 用户端已接入公众号 / 小程序登录和当前用户绑定入口。入口展示由后台能力控制,不在前端默认硬编码开放微信入口:
- 登录入口读取
GET /api/v1/auth/capabilities的loginMethods。只有下发wechat-official或wechat-miniapp且当前端环境匹配时,登录页才展示公众号 / 小程序 Tab。 - 注册入口读取同一响应的
registerMethods和register.password.enabled。后台关闭注册方式时,App / PC 不展示可点击注册入口。 - 前端默认登录方式只保留密码、短信、邮箱、钱包和 Passkey;微信入口必须由后台显式下发。
公众号登录 / 绑定入口会调用 GET /api/v1/wechat/official/oauth/authorize-url 生成微信网页授权地址。授权回跳可携带以下 query:
mode=wechat-official
wechatAccountCode=main
code=<wechat-oauth-code>
state=<opaque-state>PC 登录页 /login、App 登录页 /pages/login/index 会在后台能力允许时自动切换到公众号登录并提交;当前用户绑定页分别是 PC /account/security 和 App /pages/settings/index,绑定回跳使用 mode=wechat-official-bind。
小程序登录 / 绑定入口复用小程序运行时返回的登录 code:
mode=wechat-miniapp
wechatAccountCode=mall
code=<miniapp-login-code>PC 端提供手工粘贴小程序 code 的调试入口;App 小程序环境会优先尝试 uni.login({ provider: "weixin" }) 获取 code。H5 / 非微信小程序环境不能直接生成小程序 code,需要业务小程序容器回传。
当前前端文件入口:
| 端 | 文件 | 能力 |
|---|---|---|
| App | views/app/src/pages/login/index.vue | 后台控制的公众号 / 小程序登录 Tab、授权回跳自动提交 |
| App | views/app/src/pages/settings/index.vue | 当前用户公众号 / 小程序身份绑定 |
| PC | views/pc/app/pages/login.vue | 后台控制的公众号 / 小程序登录 Tab、公众号授权跳转、回跳自动提交 |
| PC | views/pc/app/pages/account/security.vue | 当前用户公众号 / 小程序身份绑定 |
小程序核心 API
普通小程序 API 返回 Result<T>:
| API | 说明 |
|---|---|
POST /api/v1/wechat/miniapp/code2-session | 按小程序账号和临时登录 code 换取 openid / unionid 绑定输入;响应只返回脱敏后的 sessionKeyMasked |
POST /api/v1/wechat/miniapp/payment-context | 按小程序账号和临时登录 code 生成 JSAPI / 小程序支付上下文;返回 scene=jsapi 和 attributes.openid / attributes.openId / attributes.open_id / attributes.wechatAccountCode / attributes.wechatUnionId,不返回 session key 明文 |
POST /api/v1/wechat/miniapp/phone-number | 按小程序账号和手机号组件 code 换取手机号、纯手机号、区号与 watermark |
WechatMiniappService 同时提供旧版 sessionKey + encryptedData + iv 手机号解析和订阅消息发送 facade。订阅消息发送结果会写入 wechat_message_log 出站日志;Notification 的 wechat 通道已复用该服务层能力,IAM 绑定接口复用 openid / unionid 输入。
小程序 payment-context 只负责把微信登录 code 兑换为支付上下文,不创建支付单、不保存支付状态、不处理退款。前端可把返回的 scene 与 attributes 原样传给 Cashier 下单,或放入 Payment Platform 开放支付 extraJson;Payment / Cashier + IJPay 主链路会统一识别 openid、openId 和 open_id 三种 openid 别名。
微信开放平台核心 API
微信开放平台第三方平台回调是外部协议入口,返回微信要求的原始文本,不套 Result<T>:
| API | 说明 |
|---|---|
POST /api/v1/wechat/open-platform/{componentAccountCode}/callbacks | 接收 component ticket、授权成功 / 更新授权 / 取消授权等开放平台回调,完成验签、解密、事件日志和 authorizer 快照更新后返回 success |
普通业务接口继续返回 Result<T>:
| API | 说明 |
|---|---|
POST /api/v1/wechat/open-platform/pre-auth-url | 按开放平台组件账号、回调地址、授权类型和业务小程序 appId 生成第三方平台预授权 URL |
POST /api/v1/wechat/open-platform/query-auth | 按授权码换取授权方 access token / refresh token,并刷新本地授权方快照 |
授权回调会使用 WxJava 维护 component verify ticket、预授权码、授权码和 authorizer token 生命周期。本地表只保存授权方快照和 Secret 引用占位,不保存 appSecret、componentSecret、authorizer access token 或 refresh token 明文。
后续路线
- 完整体收尾:用户端回调 smoke 和企业微信 / 视频号 / 小店等按后续明确需求扩展。