mcpField
O
openwa

openwa

github.com/thatjuan其他149 次安装3 周前更新
代码仓库

关于 openwa

OpenWA 是面向 WhatsApp 自动化开发的开源、可自托管 API 网关。它提供 REST API、仪表板、多会话支持、Webhook、实时事件,以及 JavaScript/TypeScript 和 Python SDK。

主要功能

  1. 01REST API 和 React 仪表板
  2. 02管理多个 WhatsApp 账号会话
  3. 03消息、联系人、群组和频道接口
  4. 04带签名和重试的 Webhook
  5. 05Socket.IO 实时事件
  6. 06JavaScript/TypeScript 与 Python SDK

适用场景

  1. 01自动化多个 WhatsApp 账号的消息处理
  2. 02通过 Webhook 处理收到的消息事件
  3. 03实时监控会话和消息事件
  4. 04使用 SDK 集成 WhatsApp 操作

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/thatjuan/agent-skills --skill openwa

安装后在 Claude Code 中输入/openwa确认已加载。

包含的文件

除 SKILL.md 外,安装时一起下载的参考资料和脚本。

README.md
references/
architecture.md
configuration.md
deployment.md
gotchas.md
operation.md
rest-api.md
sdk.md
webhooks-and-events.md

详细介绍

OpenWA

OpenWA 是一个可自托管、开源的 WhatsApp API 网关(MIT、NestJS 11 / TypeScript / Node 22)。它在端口 2785 上通过 REST API 封装 whatsapp-web.js(Puppeteer + Chromium),提供运行于端口 2886 的 React 仪表板,并支持多会话 WhatsApp 自动化、webhook、Socket.IO 实时事件、可插拔存储/缓存/数据库,以及插件钩子系统。

产品组成

组件端口作用
openwa-api (NestJS)2785REST + WebSocket + webhook 分发器
dashboard (React 19 + Vite)2886会话/API 密钥/webhook 界面
Swagger UI2785/api/docs
Traefik(可选)80、8080反向代理 + 仪表板(配置组 with-proxy)
PostgreSQL(可选)5432配置组 postgres
Redis(可选)6379配置组 redis,用于启用 BullMQ 队列
MinIO(可选)9000、9001配置组 minio(兼容 S3 的存储)

全局 API 前缀为 /api(src/main.ts:128 中的 app.setGlobalPrefix('api'))。以下所有路径均相对于 <baseUrl>/api。

技术栈 — 已验证

层技术依据
框架NestJS 11.xpackage.json
WA 引擎whatsapp-web.js 1.26.1(Puppeteer + Chromium)package.json、src/engine/engine.factory.ts
主数据库SQLite(始终启用 — 存储 API 密钥、审计日志)src/app.module.ts
数据库SQLite 或 PostgreSQL(会话、消息、webhook)src/app.module.ts
ORMTypeORM 0.3.xpackage.json
队列BullMQ 5.x(由 QUEUE_ENABLED 控制)src/app.module.ts:31
缓存Redis(可选,由 REDIS_ENABLED 控制)src/common/cache/
存储本地或 S3/MinIOsrc/common/storage/
实时通信/events 命名空间上的 Socket.IO 4.8src/modules/events/events.gateway.ts
验证class-validator、class-transformerpackage.json
SDK@openwa/sdk (JS/TS) + openwa (Python)sdk/javascript/、sdk/python/

仓库目录结构

src/
  main.ts                    # Boot + .env precedence + first-run API key
  app.module.ts              # Composition; conditional QueueModule
  config/configuration.ts    # Env → config object
  core/{hooks,plugins}/      # Plugin hook system
  engine/                    # IWhatsAppEngine interface + adapters
  modules/
    session/                 # Session CRUD + in-memory engine map
    message/                 # Send & history endpoints
    webhook/                 # Per-session webhook subscriptions
    events/                  # Socket.IO gateway (/events namespace)
    auth/                    # API-key auth + roles
    contact/ group/ label/ channel/ status/ catalog/
    queue/                   # BullMQ jobs (only if QUEUE_ENABLED)
    health/                  # /health, /health/live, /health/ready
    infra/ settings/ stats/ audit/ docker/ plugins/
dashboard/                   # React 19 + Vite SPA
sdk/{javascript,python}/     # Client libraries
traefik/{traefik.yml,dynamic.yml}
docker-compose.yml           # Profiled production stack
docker-compose.dev.yml       # SQLite + local dev quick-start
Dockerfile                   # Multi-stage Node 22-slim + Chromium
docs/                        # 22 markdown design docs

身份验证 — X-API-Key

身份验证使用哈希后的 API 密钥,并通过 X-API-Key 标头发送(根据 main.ts:122 中的 CORS 允许列表,也接受 Authorization: Bearer)。密钥以哈希形式存储在主 SQLite 数据库中,并具有以下角色之一:ADMIN、OPERATOR 或 VIEWER(src/modules/auth/entities/api-key.entity.ts)。

curl -H "X-API-Key: owa_k1_xxxxxxxx..." http://localhost:2785/api/sessions
  • 密钥格式:owa_k1_<32 bytes hex>(src/modules/auth/auth.service.ts:95)
  • 首次运行引导:如果不存在 API 密钥,OpenWA 会创建一个并将其写入 data/.api-key,随后在启动横幅中打印该密钥。在开发环境(NODE_ENV=development)中,引导密钥是字面字符串 dev-admin-key。
  • 角色控制:写入端点使用 @RequireRole(ApiKeyRole.OPERATOR);读取操作大多只需 API 密钥即可访问。API 密钥的增删改查需要 ADMIN 角色。
  • 可选的单密钥范围限制:IP 允许列表(allowedIps)和会话允许列表(allowedSessions)。

密钥创建/撤销流程请参阅身份验证与 API 密钥生命周期。

会话 — 多账号 WhatsApp

每个 WhatsApp 账号对应一条持久化的 Session 记录,以及一个以内存中的会话 ID 为键的 IWhatsAppEngine 引擎(src/modules/session/session.service.ts)。会话会经历以下状态:

CREATED → INITIALIZING → QR_READY → AUTHENTICATING → READY
                                  ↘ FAILED
   any → DISCONNECTED (also forced on every API restart)

使会话上线的最简工作流:

# 1. Create
curl -X POST http://localhost:2785/api/sessions \
  -H "X-API-Key: $KEY" -H "Content-Type: application/json" \
  -d '{"name":"bot-1"}'

# 2. Start (initialises Chromium + WA engine)
curl -X POST http://localhost:2785/api/sessions/$ID/start -H "X-API-Key: $KEY"

# 3. Fetch QR — returns SVG data while status = QR_READY
curl http://localhost:2785/api/sessions/$ID/qr -H "X-API-Key: $KEY"
# … scan with WhatsApp mobile …

# 4. Poll status (or subscribe via /events) until status = READY
curl http://localhost:2785/api/sessions/$ID -H "X-API-Key: $KEY"

聊天 ID 遵循 WhatsApp Web 约定:私聊使用 <phone>@c.us,群组使用 <id>@g.us,频道使用 <id>@newsletter。格式无效会导致发送静默失败。

完整生命周期、内存中的引擎映射、代理选项以及重启时的重置行为,请参阅:operation.md。

REST API — 控制器目录

所有路由均挂载在 /api 下。括号中的角色表示要求高于默认的 VIEWER 或更高权限时所需的角色。

领域路由文件
会话POST /sessions (OPERATOR)、GET /sessions、GET /sessions/:id、DELETE /sessions/:id (OPERATOR)、POST /sessions/:id/start (OPERATOR)、POST /sessions/:id/stop (OPERATOR)、GET /sessions/:id/qr、GET /sessions/:id/groups、GET /sessions/stats/overviewsession.controller.ts
消息GET /sessions/:sessionId/messages、POST /sessions/:sessionId/messages/send-text、…/send-image、…/send-video、…/send-audio、…/send-document、…/send-location、…/send-contact、…/send-sticker、…/reply、…/forward、…/react、GET …/:chatId/:messageId/reactions、POST …/delete、POST …/send-bulk、GET …/batch/:batchId、POST …/batch/:batchId/cancelmessage.controller.ts
Webhook/sessions/:sessionId/webhooks 下的 POST/GET/GET :id/PUT :id/DELETE :id,以及 POST :id/testwebhook.controller.ts
API 密钥POST /auth/api-keys (ADMIN)、GET、GET :id、PUT :id、DELETE :id、POST :id/revokeauth.controller.ts
身份验证探测GET /auth/validate(请求头 X-API-Key)auth-validate.controller.ts
健康检查GET /health、GET /health/live、GET /health/ready(公开;K8s 形式)health.controller.ts
联系人/群组/标签/频道/状态/目录各模块控制器位于 /sessions/:sessionId/... 下modules/<name>/
基础设施用于迁移的设置、统计、导出/导入modules/infra/

权威定义以控制器文件和自动发布的 OpenAPI 为准,地址为 http://localhost:2785/api/docs。包含角色/身份验证说明的完整路由表:rest-api.md。

Webhook — 按会话配置、带签名、可重试

Webhook 按会话创建(POST /api/sessions/:sessionId/webhooks),需要提供 URL、events 数组,以及可选的 secret/自定义 headers。当 QUEUE_ENABLED=true 时,通过 BullMQ 投递(并进行重试);否则采用同步投递。

每次投递都会发送以下请求头:

请求头含义
X-OpenWA-Event事件名称(例如 message.received)
X-OpenWA-Delivery-Id每次投递尝试的父级分发任务的唯一 ID
X-OpenWA-Idempotency-Key对每个(事件 × 主体)保持稳定的键 — 用于消费者去重
X-OpenWA-Retry-Count首次尝试为 0,之后为 attemptsMade
X-OpenWA-Signature使用 webhook.secret 对 JSON 请求体计算的 sha256=<hex hmac>(未设置密钥时省略)

默认值:WEBHOOK_TIMEOUT=10000 毫秒、WEBHOOK_MAX_RETRIES=3、WEBHOOK_RETRY_DELAY=5000 毫秒。

可订阅的事件类型(WebSocket 也支持 — src/modules/events/dto/ws-messages.dto.ts):

message.received、message.sent、message.ack、message.revoked、session.status、session.qr、session.authenticated、session.disconnected、group.join、group.leave、group.update — 以及用于订阅全部事件的 *。

签名验证、投递流程、队列与同步模式、幂等语义、重试时序:webhooks-and-events.md。

实时通信 — Socket.IO /events

事件分类与 Webhook 相同,通过 Socket.IO 在 /events 命名空间中投递。协议使用自定义 JSON(而非 Socket.IO 事件发射器):客户端发送 {type:'subscribe', sessionId, events, requestId?},并在服务端接收 {type:'event', ...} / {type:'subscribed', ...} / {type:'error', ...} / {type:'pong'}。

import { io } from 'socket.io-client';
const sock = io('http://localhost:2785/events', { auth: { apiKey: KEY } });
sock.emit('message', { type: 'subscribe', sessionId: '*', events: ['message.received'] });
sock.on('message', (msg) => { /* handle msg.type === 'event' */ });

传输格式、身份验证模式、房间布局(session:<id>:<event>)以及 ping/pong:webhooks-and-events.md#websocket。

部署

提供三种文档化的部署路径:

路径命令
本地开发(SQLite、无 Redis/队列、全部集成)docker compose -f docker-compose.dev.yml up -d
基础生产环境docker compose up -d
完整生产环境(Postgres + Redis + MinIO + Traefik + Dashboard)docker compose --profile full up -d

镜像基于多阶段构建的 node:22-slim,内置 Chromium,并设置了 PUPPETEER_EXECUTABLE_PATH=/usr/bin/chromium。容器每隔 30 s 执行一次健康检查:node -e "require('http').get('http://localhost:2785/api/health', ...)"。

Compose 配置文件的配置档(postgres、redis、minio、with-dashboard、with-proxy、full)、卷布局(openwa-data:/app/data)、Docker socket 挂载(/var/run/docker.sock:ro —— 由 modules/docker 用于编排)、Traefik 静态/动态配置以及 K8s 健康探针:deployment.md。

配置——由环境变量驱动,分三层优先级

引导启动(src/main.ts:11-65)会通过 override: false 加载 dotenv,因此优先级最高的是进程环境变量:

process.env  >  ./.env  >  ./data/.env.generated

.env.generated 是 Dashboard 写入的文件,其优先级最低,而非最高。常见误区是以为 Dashboard 保存的设置会覆盖 Docker environment: 块——实际上不会。

首次启动时,如果不存在 data/.env.generated,OpenWA 会创建该文件,使用 SQLite、本地存储并禁用队列,同时打印包含 API key 的欢迎横幅。

app.module.ts 中配置了两个 TypeORM 数据库:

  • main 连接——始终使用 SQLite。存储 API key 和审计日志。始终保留在本地节点(不要尝试迁移它)。
  • data 连接——使用 SQLite 或 PostgreSQL。存储会话、消息和 Webhook。SQLite 默认启用同步,Postgres 默认禁用(此时运行 npm run migration:run:prod)。

完整的环境变量参考、.env.minimal、双数据库示意图以及 QUEUE_ENABLED 控制逻辑:configuration.md。

SDK

import { OpenWAClient } from '@openwa/sdk';
const client = new OpenWAClient({ baseUrl: 'http://localhost:2785', apiKey: KEY });
await client.sessions.create({ name: 'bot-1' });
await client.sessions.start(id);
await client.messages.sendText(id, { chatId: '[email protected]', text: 'hi' });

已发布的 @openwa/sdk 提供精简的手写接口(sdk/javascript/src/index.ts),并计划根据 OpenAPI 规范重新生成。对于尚未封装的端点,可调用 client.request('POST', '/api/...', body),或使用带有 X-API-Key 的 fetch。Python SDK 位于 sdk/python/openwa/。

SDK 安装、类型化封装、生成流程及 Python 对应内容:sdk.md。

架构与可扩展性

OpenWA 通过接口边界而非单靠功能开关来实现可插拔性:

  • IWhatsAppEngine(src/engine/interfaces/)——抽象 whatsapp-web.js;可通过 engine.factory.ts 接入替代引擎(Baileys 等)。由 ENGINE_TYPE 选择。
  • StorageService——本地文件系统或 S3/MinIO,通过 STORAGE_TYPE 切换。
  • CacheService——内存或 Redis,由 REDIS_ENABLED 控制。
  • 插件钩子——core/hooks/ 会运行具名钩子链。消息发送流水线会在分发前触发 message:sending(插件可修改或拦截),并在成功后触发 message:sent。当 PLUGINS_ENABLED=true 时会自动加载插件。
  • 队列控制——仅当 QUEUE_ENABLED === 'true' 时才会 require QueueModule(src/app.module.ts:31-38)。未启用时,Webhook 重试仅以尽力而为的同步方式执行。

模块映射、钩子列表、插件加载器、扩展模型(引擎固定在各节点上;API key 保留在本地;数据数据库可以共享):architecture.md。

注意事项

以下几个行为容易让只读文档、不看代码的人踩坑:

  1. .env.generated 的优先级是最低,不是最高。
  2. 每次 API 重启都会强制将所有 READY/INITIALIZING/QR_READY/AUTHENTICATING 会话重置为 DISCONNECTED(引擎在内存中;重启会丢失它们)。
  3. QUEUE_ENABLED=false(默认值)意味着Webhook 不会重试——采用同步尽力分发。
  4. SQLite 的默认设置是 synchronize: true,在生产环境中很危险;使用 Postgres 时应切换为迁移。
  5. API 密钥存储在 SQLite main 数据库中。将 data 数据库切换为 Postgres 不会迁移这些密钥。
  6. 在会话达到 READY 之前,phone 和 pushName 都为 null。
  7. 聊天 ID 的格式必须是 <phone>@c.us / <id>@g.us——格式错误会导致静默失败。
  8. Chromium 是必需的;Docker 镜像将 PUPPETEER_EXECUTABLE_PATH=/usr/bin/chromium 硬编码。

完整的注释列表(含文件和行号引用):gotchas.md。

参考索引

参考资料内容
deployment.mdDockerfile 阶段、compose 配置文件、Traefik、K8s 探针、卷
configuration.md环境变量参考、优先级、双数据库布局、队列开关
operation.md会话生命周期、QR 身份验证、API 密钥引导与生命周期、仪表板
rest-api.md完整的控制器→路由目录、角色装饰器、请求/响应格式
webhooks-and-events.mdWebhook 请求头、HMAC、重试、幂等性、Socket.IO /events 线格式
sdk.mdJS/TS 和 Python 客户端用法、原始 fetch 备用方案、重新生成说明
architecture.md模块映射、引擎/存储/缓存的可插拔性、插件钩子、扩展
gotchas.md根据源代码验证的非显而易见行为

评论

支持 Markdown