cnb.cool/zishuo/wxclaw 是基于当前 openclaw-weixin TypeScript 实现移植出来的独立 Go 微信消息网关。
HTTP 管理面使用 github.com/go-chi/chi/v5,并由同一服务直接提供内嵌 HTML 测试控制台。
getUpdates 长轮询监控context_token 进程内缓存与出站复用getConfig typing ticket 缓存-14 session pause 熔断logs-upload)cp examples/config.yaml ./config.yaml
如果直接启动时找不到 config.yaml,网关也会自动在目标路径生成同款推荐模板。
修改 webhook、存储目录、账号配置。
启动:
cd weixin-go
go run ./cmd/weixin-gateway -config ./config.yaml
或构建二进制:
cd weixin-go
go build -o bin/weixin-gateway ./cmd/weixin-gateway
./bin/weixin-gateway -config ./config.yaml
http://127.0.0.1:8080/
或:
http://127.0.0.1:8080/console
网关 HTTP 层已切到 github.com/go-chi/chi/v5,根路径会直接返回内嵌 HTML 控制台,方便做登录、绑定、发消息与 webhook 联调。
更详细的操作说明见 USAGE_GUIDE.zh-CN.md。
若要按接口字段、请求示例和返回结构逐项接入,直接看 API_REFERENCE.zh-CN.md。
若要理解模块结构、生命周期、存储与设计取舍,直接看 DESIGN.md。
对齐 TS 版本 logs-upload 行为,支持 YYYYMMDD、YYYYMMDDHH、完整文件名或绝对路径。上传 URL 优先级:
--urlWEIXIN_GATEWAY_LOG_UPLOAD_URL--config 指向配置中的 weixin.log_upload_url(兼容读取 channels.openclaw-weixin.logUploadUrl)示例:
cd weixin-go
go run ./cmd/weixin-gateway logs-upload \
--url https://example.com/upload \
--file 20260322 \
--log-dir /tmp/openclaw
也可用环境变量:
export WEIXIN_GATEWAY_LOG_UPLOAD_URL=https://example.com/upload
export WEIXIN_GATEWAY_LOG_DIR=/tmp/openclaw
./bin/weixin-gateway logs-upload --file openclaw-2026-03-22.log
默认上传字段名为 file。若响应头包含 fileid 会直接打印;若没有,会输出全部响应头用于排障,并打印响应体。
GET /GET /consoleGET /healthGET /statusGET /api/v1/accountsPOST /api/v1/qr/startPOST /api/v1/qr/waitPOST /api/v1/send/textPOST /api/v1/send/mediaPOST /api/v1/send/typing用于生产环境中的账号/设备绑定状态维护(账号启停、allowFrom 管理、debug 开关)。推荐通过这些接口完成绑定/解绑交互与运行态操作。
POST /api/v1/accounts/:account_id/startPOST /api/v1/accounts/:account_id/stopGET /api/v1/accounts/:account_id/allow-fromPOST /api/v1/accounts/:account_id/allow-fromDELETE /api/v1/accounts/:account_id/allow-fromGET /api/v1/accounts/:account_id/devicesPOST /api/v1/accounts/:account_id/devices/bindPOST /api/v1/accounts/:account_id/devices/unbindGET /api/v1/accounts/:account_id/debugPOST /api/v1/accounts/:account_id/debugPOST /api/v1/accounts/:account_id/debug/toggle示例:
curl -X POST http://127.0.0.1:8080/api/v1/accounts/bot-a-im-bot/start
curl -X POST http://127.0.0.1:8080/api/v1/accounts/bot-a-im-bot/allow-from \
-H 'content-type: application/json' \
-d '{"user_id":"wxid_xxx@im.wechat"}'
curl -X DELETE http://127.0.0.1:8080/api/v1/accounts/bot-a-im-bot/allow-from \
-H 'content-type: application/json' \
-d '{"user_id":"wxid_xxx@im.wechat"}'
curl -X POST http://127.0.0.1:8080/api/v1/accounts/bot-a-im-bot/devices/bind \
-H 'content-type: application/json' \
-d '{"user_id":"wxid_xxx@im.wechat"}'
curl -X POST http://127.0.0.1:8080/api/v1/send/typing \
-H 'content-type: application/json' \
-d '{"account_id":"bot-a-im-bot","to":"wxid_xxx@im.wechat","context_token":"optional"}'
allow-from 返回的是“显式授权集合”;devices 返回的是“当前有效授权集合”。当前网关语义如下:
allowFrom 文件非空时,以文件里的显式绑定用户为准accounts.<id>.allow_from 在配置里有值,则该配置列表会作为显式授权集合allowFrom 文件为空时,fallback 到扫码登录保存的 userIdbind(U2) 只会基于当前显式授权集合写回;若当前仍处于 fallback owner 模式,首次 bind 不会把 owner 自动固化进文件unbind(U2) 若移除后文件为空,后续 inbound 会重新 fallback 到扫码 ownerfile_present=true 表示该账号已经存在独立的 allowFrom 文件,即使文件内容当前为空{
"account_id": "bot-a",
"force": false,
"base_url": "https://ilinkai.weixin.qq.com",
"bot_type": "3"
}
{
"account_id": "bot-a",
"session_key": "bot-a"
}
说明:
session_key 可留空;当它为空时,网关会回退使用 account_id 等待已有 QR 会话。account_id,并额外带 normalized_account_id 供网关侧后续 API 使用。context_token 可显式传入;若不传,则网关会尝试使用内存缓存的最近 token。
{
"account_id": "bot-a-im-bot",
"to": "wxid_xxx@im.wechat",
"text": "hello",
"context_token": "optional"
}
支持:
media_urlmedia_pathfile{
"account_id": "bot-a-im-bot",
"to": "wxid_xxx@im.wechat",
"text": "附件如下",
"media_path": "/data/demo/report.pdf"
}
可直接传 typing_ticket,也可只传 context_token,让网关先走 getConfig 补 ticket。
{
"account_id": "bot-a-im-bot",
"to": "wxid_xxx@im.wechat",
"context_token": "optional",
"typing_ticket": "optional",
"status": 1
}
若配置了 webhook.url,每条入站消息都会 POST 到该地址:
{
"channel": "openclaw-weixin",
"account_id": "bot-a-im-bot",
"from_user_id": "wxid_xxx@im.wechat",
"to_user_id": "wxid_xxx@im.wechat",
"body": "你好",
"context_token": "....",
"timestamp_ms": 1710000000000,
"typing_ticket": "....",
"media": {
"media_path": "/abs/path/to/file",
"media_type": "image/jpeg"
},
"compat_context": {
"Body": "你好",
"From": "wxid_xxx@im.wechat",
"AccountId": "bot-a-im-bot"
},
"command": {
"raw_body": "你好",
"is_slash": false
},
"authorization": {
"sender_allowed": true,
"mode": "pairing_allow_from"
},
"lifecycle": {
"source": "get_updates",
"message_type_name": "user"
},
"compatibility": {
"version": "src-monitor-compat/v1",
"mode": "explicit"
},
"raw": {
"...": "原始 WeixinMessage"
}
}
当前 webhook 是单向投递,不直接消费 webhook 返回体生成自动回复。自动回复可由业务侧收到 webhook 后调用 /api/v1/send/text、/api/v1/send/media 或 /api/v1/send/typing 完成。消费端应允许 compat_context / command / authorization / lifecycle / compatibility 这类增强字段存在。
根路径 / 与 /console 都会返回内嵌 HTML 控制台,可直接在网页端完成以下操作:
start/waitstart/stopallow-from 查询、写入、移除devices 查询、bind/unbind这套页面适合做网关联调与人工回归;真正的 AI 自动回复仍应由外部业务服务消费 webhook 后再回调网关发送接口。
context_token 仍保持与 TS 版一致,只存内存,不落盘;进程重启后不能做无上下文主动回复。no_need_thumb=true,不走缩略图。route_tag 已在 Go 版中生效;若不配置则回落到全局 weixin.route_tag。storage.data_dir/openclaw-weixin/media/inbound/。webhook.url 并主动调用发送接口。webhook.secret 目前仍是保留配置字段,真实投递时不会自动签名;若要鉴权,请通过 webhook.headers 自行注入 Header。