# 1. Deploy
bash <skill_dir>/scripts/deploy.sh
# 2. Edit .env with your WeChat Work credentials
nano ~/wecom-adapter/.env
# 3. Start
cd ~/wecom-adapter && npm start
# 4. Expose publicly
cloudflared tunnel --url http://localhost:8090
# 5. Copy tunnel URL → WeChat Work admin → webhook URL
WeChat Work → HTTPS → Cloudflare Tunnel → Node.js Adapter (8090)
├─ Verify msg_signature (SHA1)
├─ Decrypt message (AES-256-CBC)
├─ Return "success" within 5s
└─ Async: call OpenClaw → send reply via WeCom API
Key: Adapter returns success immediately, then sends AI reply asynchronously via WeChat Work's message/send API. This avoids the 5-second timeout.
msg_signature, NOT signatureWeChat Work sends ?msg_signature=xxx, not ?signature=xxx. Reading req.query.signature will always be undefined.
GET verification: SHA1(sort([token, timestamp, nonce, echostr]))
POST messages: SHA1(sort([token, timestamp, nonce, encrypt]))
NOT SHA1(sort([token, timestamp, nonce])) — the encrypted payload MUST participate in the signature.
WeChat Work sends an AES-encrypted echostr. You must:
16-byte random + 4-byte length (BE) + message + CorpIDaccess_token for sending messagesWeChat Work may send XML as text/xml, application/xml, or other types:
app.use(express.text({ type: ['application/xml', 'text/xml', 'text/plain', '*/*'] }));
WeChat Work requires response within 5 seconds. AI responses take 5-30s. Solution:
res.status(200).send('success') immediatelyPOST /cgi-bin/message/send?access_token=xxxWeChat Work API (qyapi.weixin.qq.com) requires your server's public IP in the app's trusted IP list. Error 60020 means IP not whitelisted.
⚠️ Unverified enterprises risk account suspension. WeChat may ban accounts that use API automation without proper enterprise verification. Complete verification before production use.
Quick (account-less) tunnels generate new URLs on restart and may disconnect unexpectedly. For production, use Named Tunnels ($7/mo) or a static IP.
CORP_ID=ww... # From WeChat Work admin
AGENT_ID=1000003 # Application agent ID
AGENT_SECRET=xxx # EncodingAESKey (43-char Base64, for encryption)
APP_SECRET=xxx # Application Secret (for access_token)
WEBHOOK_TOKEN=xxx # Token configured in webhook settings
OPENCLAW_TOKEN=xxx # OpenClaw gateway bearer token
OPENCLAW_BASE_URL=http://localhost:18789 # OpenClaw gateway URL
CLAUDE_MODEL=claude-haiku-4-5 # AI model
scripts/deploy.sh — One-command deploymentscripts/index.js — Production-ready adapter (all fixes applied)references/setup-guide.md — Step-by-step WeChat Work configurationreferences/security-guide.md — Security architecture and hardening| Symptom | Cause | Fix |
|---|---|---|
| --------- | ------- | ----- |
signature=undefined | Using req.query.signature | Use req.query.msg_signature |
| Signature mismatch | echostr/encrypt not in calculation | Include 4th element in sort array |
-30065 error | Returning encrypted echostr | Decrypt before returning |
bad decrypt | Wrong key or setAutoPadding(true) | Use setAutoPadding(false) + manual PKCS#7 |
body长度=undefined | Body parser doesn't match Content-Type | Accept / in express.text() |
60020 IP error | Server IP not whitelisted | Add public IP in WeChat Work console |
| Timeout | 5s limit exceeded | Use async pattern: return success, send via API |
| Account banned | Unverified + automated messages | Verify enterprise first |
共 1 个版本