WeChat OA (公众号)
WeChat Official Account customer-service messaging within the 48-hour reply window. Same crypto envelope as WeCom.
🟡 Outbound-ready, inbound supported, 48-hour window. Outbound customer-service messages are constrained: a user must have interacted with the OA in the last 48 hours, otherwise the platform returns errcode 45015 and the message is dropped. Production deployments that need cold push should use Template Messages (pre-approved templates), which are a future enhancement.
What you get
- Outbound text via
POST /cgi-bin/message/custom/send?access_token=...to any openid that has messaged your OA within the last 48 hours. - Inbound message events at
/webhooks/wechat-oa. Same SHA1 sort- AES-256-CBC envelope as WeCom (the shared
wxcrypthelper covers both). One small difference on the GET handshake: WeChat OA signs the 3-tuple[token, timestamp, nonce](not 4-tuple).
- AES-256-CBC envelope as WeCom (the shared
- Per-app
access_tokencached for 2 hours. - Text only this PR. Image / news / template messages are deferred.
- 2048-char text limit.
Setup
1. Create / claim an Official Account
- Sign in to WeChat Public Platform (Service Account, not Subscription, is required for the customer-service API)
- "Settings" → "Basic Info": note the AppID and AppSecret
- "Settings" → "Server Configuration":
- URL:
https://<your-host>/webhooks/wecom - Token: any opaque string (becomes
WECHAT_OA_TOKEN) - EncodingAESKey: click "Generate Random" (43 chars,
becomes
WECHAT_OA_AES_KEY) - Encryption mode: "Safe Mode" (encrypted) recommended
- URL:
- Click "Submit". WeChat hits the URL with a GET handshake; Minara echoes back the (decrypted) plaintext.
2. Find a default openid
The customer-service API needs an openid (an opaque user identifier).
Trigger any interaction from the test user (follow the OA, send a
message, click a menu item). The inbound webhook will surface the
openid in FromUserName. Save one as WECHAT_OA_DEFAULT_OPENID.
3. Configure Minara
minara auth messaging add
# pick `wechat_oa` from the list.Or set env vars directly:
WECHAT_OA_APP_ID=wx<...>
WECHAT_OA_APP_SECRET=<opaque secret>
WECHAT_OA_TOKEN=<server config Token>
WECHAT_OA_AES_KEY=<43-char EncodingAESKey>
WECHAT_OA_DEFAULT_OPENID=<o...........>4. Test
minara auth messaging test wechat_oaNote: the test will fail with errcode 45015 if the default openid has not interacted with the OA in the last 48 hours.
Inbound webhook
WeChat OA's server-config GET handshake is slightly different from
WeCom's. The 4-tuple [token, ts, nonce, encrypt] is replaced by a
3-tuple [token, timestamp, nonce]:
expected = sha1(sort([token, timestamp, nonce]).join(""))POST signature is the same as WeCom: msg_signature in the URL
query, 4-tuple sort, AES envelope inside the body.
Inner XML payload after decryption follows Tencent's classic shape:
<xml>
<ToUserName>...</ToUserName>
<FromUserName>...</FromUserName>
<CreateTime>...</CreateTime>
<MsgType>text</MsgType>
<Content>...</Content>
<MsgId>...</MsgId>
</xml>Only MsgType=text events are forwarded to the agent.
Limits & caveats
- 48-hour customer-service window. Outside the window, every outbound returns errcode 45015. Plan UX around passive replies (within 48 h of a user-initiated interaction) and pre-approved Template Messages for long-tail push.
- Service Account vs Subscription Account. The customer-service API is only available to Service Accounts. Subscription Accounts cannot use this provider.
EncodingAESKeymust be exactly 43 chars. Anything else fails decoding during boot.
Troubleshooting
"errcode 45015"
- The openid did not interact with the OA in the last 48 hours. This is by design; switch to Template Messages for cold push (not yet wired in Minara).
"errcode 40001 / Token invalid"
access_tokenfailed to refresh. VerifyWECHAT_OA_APP_IDandWECHAT_OA_APP_SECRETagainst the OA console.
"Inbound webhook returns 401 on handshake"
- The 3-tuple SHA1 check failed. Most common cause: typo in
WECHAT_OA_TOKEN. Confirm the value matches "Token" in the OA's Server Configuration page.
Reference
- Env vars:
WECHAT_OA_* - Outbound:
apps/agent/src/messaging/wechat_oa.ts - Inbound spec:
apps/agent/src/messaging/inbound/specs/wechat_oa.ts - Customer-service API: developers.weixin.qq.com / 客服消息