16 KiB
Note
本文档由 WeHub 基于上游 README 翻译整理,属于社区翻译,非官方中文文档。
English · 原始项目 · 上游 README
原作者、版权与许可证归属以原始项目及本仓库 LICENSE 文件为准。
OpenWA
开源 WhatsApp API 网关
✨ 为什么选择 OpenWA?
OpenWA 是一款免费、开源的 WhatsApp API 网关(Gateway),面向需要完全掌控消息基础设施、且不愿被厂商锁定或遭遇隐藏付费墙的开发者。
基于可插拔架构(Pluggable Architecture),OpenWA 允许你通过配置更换数据库引擎(SQLite/PostgreSQL)、存储后端(Local/S3)和缓存层(Memory/Redis),而无需修改应用代码中的任何一行。
| 🔓 100% 开源 | 无许可费用、无功能锁定、可访问完整源代码 |
| 🏗️ 可插拔架构 | 通过配置切换数据库、存储和缓存适配器 |
| 🖥️ 完整仪表盘 | 现代化的 React UI,用于管理会话、Webhook 和 API 密钥 |
| 🔹 多会话就绪 | 在单个实例上并发运行多个 WhatsApp 会话 |
| 🐳 原生 Docker 支持 | 开箱即用,可用于生产环境,零配置 |
| 🔗 n8n 集成 | 用于工作流自动化的社区节点 |
| 🧩 社区适配器 | 第三方集成(例如 ioBroker)— 参见 文档 |
🎯 特性
核心特性
| 特性 | 状态 | 描述 |
|---|---|---|
| REST API | ✅ | 通过 HTTP 端点提供完整的 WhatsApp API |
| 多会话 | ✅ | 管理多个 WhatsApp 账户 |
| Webhook | ✅ | 实时事件,支持 HMAC 签名及可选的智能预分发过滤器 |
| Web 仪表盘 | ✅ | 可视化管理界面 |
| API 密钥认证 | ✅ | 安全的 API 身份验证 |
| Swagger 文档 | ✅ | 交互式 API 文档 |
消息
| 特性 | 状态 | 描述 |
|---|---|---|
| 文本消息 | ✅ | 发送/接收文本消息 |
| 媒体消息 | ✅ | 图片、视频、文档、音频 |
| 消息回应 | ✅ | 使用表情符号回应消息 |
| 批量消息 | ✅ | 向多个收件人发送 |
| 消息状态 | ✅ | 跟踪送达和已读回执 |
高级功能
| 特性 | 状态 | 描述 |
|---|---|---|
| 群组 API | ✅ | 创建、管理群组并发送消息 |
| 频道/Newsletter | ✅ | 支持 WhatsApp 频道 |
| 标签管理 | ✅ | 使用标签整理聊天 |
| 代理支持 | ✅ | 按会话配置代理 |
| 速率限制 | ✅ | 可配置的请求限制 |
| CIDR 白名单 | ✅ | 基于 IP 的访问控制 |
| 审计日志 | ✅ | 跟踪所有 API 操作 |
基础设施
| 特性 | 状态 | 描述 |
|---|---|---|
| SQLite | ✅ | 零配置嵌入式数据库 |
| PostgreSQL | ✅ | 生产级数据库 |
| Redis 缓存 | ✅ | 可选的性能缓存 |
| S3/MinIO 存储 | ✅ | 可扩展的媒体存储 |
| Docker | ✅ | 一条命令完成部署 |
| 健康检查 | ✅ | 适用于 Kubernetes 的探针 |
| 数据迁移 | ✅ | 在后端之间导出/导入 |
🚀 快速开始
方案 A:Docker(推荐)
# Clone and start
git clone https://github.com/rmyndharis/OpenWA.git
cd OpenWA
docker compose -f docker-compose.dev.yml up -d
# Access (the dashboard is bundled into the API image and served on the same port)
# Dashboard: http://localhost:2785
# API: http://localhost:2785/api
# Swagger: http://localhost:2785/api/docs
使用 Podman 而非 Docker? Podman 无 root 模式需要 socket 正在运行,并设置
DOCKER_HOST:systemctl --user start podman.socket systemctl --user enable podman.socket export DOCKER_HOST=unix:///run/user/$(id -u)/podman/podman.sock将
export这一行添加到你的~/.bashrc中,以使其永久生效。
方案 B:本地开发
# Clone repository
git clone https://github.com/rmyndharis/OpenWA.git
cd OpenWA
# Install dependencies (includes dashboard)
npm install
# Start API + Dashboard (config is auto-generated on first run)
npm run dev
# Access (in dev the dashboard runs on the Vite server with hot reload)
# Dashboard: http://localhost:2886
# API: http://localhost:2785/api
# Swagger: http://localhost:2785/api/docs
🔒 安全架构
Docker Socket 代理
生产环境技术栈绝不会将 /var/run/docker.sock 直接暴露给应用容器。相反,一个专用的 docker-proxy 边车(sidecar,基于 tecnativa/docker-socket-proxy))作为访问 Docker 守护进程的唯一网关:
openwa-api ──TCP 2375──▶ docker-proxy ──unix──▶ /var/run/docker.sock
仅启用容器编排所需的操作(CONTAINERS、IMAGES、VOLUMES、INFO、PING、POST、DELETE)。应用通过 DOCKER_HOST=tcp://docker-proxy:2375 环境变量连接,DockerService 会自动检测该变量。
🔒 安全架构
非 root 容器执行
生产镜像绝不会以 root 身份运行 Node.js 进程。启动时,容器遵循以下链路:
dumb-init (PID 1)
└─ docker-entrypoint.sh (root — fixes named-volume ownership via chown)
└─ gosu openwa node dist/main (drops to the openwa user)
- dumb-init 作为 PID 1,转发信号(SIGTERM 等)以实现优雅关闭。
- docker-entrypoint.sh 仅以 root 身份运行足够长的时间,以便
chown命名卷挂载点,使openwa用户可以写入它们。 - gosu 执行基于
exec的干净权限降级 — 不使用su或sudo包装器,因此 node 进程是 dumb-init 的直接子进程。
命名卷(例如 openwa-data)在每次启动时都会自动修正所有权,因此在创建卷后无需手动执行 chown 步骤。
🏭 生产部署
生产环境请使用主 docker-compose.yml,并可按需启用可选服务:
# Basic production (SQLite, local storage)
docker compose up -d
# With PostgreSQL database
docker compose --profile postgres up -d
# Full stack (PostgreSQL, Redis, MinIO)
docker compose --profile full up -d
| 配置方案(Profile) | 服务 |
|---|---|
postgres |
PostgreSQL 数据库 |
redis |
Redis 缓存 |
minio |
S3 兼容存储 |
full |
上述所有服务 |
Dashboard 已打包进 API 镜像,由 NestJS 在 API 端口提供服务,因此无需 profile —— 只要
openwa-api运行,它就始终可用。如需 TLS/公网暴露,请在前方放置你自己的反向代理(nginx、Caddy、云负载均衡器或 k8s Ingress);参见docs/12-troubleshooting-faq.md中的 nginx 示例。
开发环境 vs 生产环境
- 开发环境(
docker-compose.dev.yml):SQLite、本地存储,API 提供打包的 dashboard- 生产环境(
docker-compose.yml):可配置数据库,通过 profile 启用可选服务官方 GHCR 镜像以多架构 manifest 形式发布:
linux/amd64linux/arm64
🔌 端口
| 服务 | 端口 | 说明 |
|---|---|---|
| API & Dashboard | 2785 |
REST API + 打包的 Web 仪表盘(同一端口) |
| Swagger | 2785/api/docs |
交互式 API 文档 |
| Dashboard (dev) | 2886 |
带热重载的 Vite 开发服务器(npm run dev) |
📡 API 示例
创建会话
curl -X POST http://localhost:2785/api/sessions \
-H "Content-Type: application/json" \
-H "X-API-Key: YOUR_API_KEY" \
-d '{"name": "my-bot"}'
启动会话并获取二维码
# Start the session
curl -X POST http://localhost:2785/api/sessions/{sessionId}/start \
-H "X-API-Key: YOUR_API_KEY"
# Get QR code (scan with WhatsApp)
curl http://localhost:2785/api/sessions/{sessionId}/qr \
-H "X-API-Key: YOUR_API_KEY"
发送消息
curl -X POST http://localhost:2785/api/sessions/{sessionId}/messages/send-text \
-H "Content-Type: application/json" \
-H "X-API-Key: YOUR_API_KEY" \
-d '{
"chatId": "628123456789@c.us",
"text": "Hello from OpenWA!"
}'
配置 Webhook
curl -X POST http://localhost:2785/api/sessions/{sessionId}/webhooks \
-H "Content-Type: application/json" \
-H "X-API-Key: YOUR_API_KEY" \
-d '{
"url": "https://your-server.com/webhook",
"events": ["message.received", "session.status"],
"secret": "your-hmac-secret"
}'
智能过滤器(可选): 添加
filters对象,仅在条件匹配(AND)时触发 webhook,例如{ "conditions": [{ "field": "sender", "operator": "is", "value": ["1234567890@c.us"] }] }。 字段:sender/recipient/body/type/mentions/fromMe/hasMedia/isGroup。不带过滤器的 webhook 行为与之前完全一致。完整 schema 请参阅 API 规范。
🤖 MCP Server(AI 智能体)
OpenWA 可通过 Model Context Protocol** so AI agents(Claude、Cursor 等)驱动 WhatsApp。默认关闭且为附加功能 —— 所有 REST 路由保持原样不变。
将 MCP_ENABLED=true 设置为在现有服务器的 POST /mcp 上挂载无状态 Streamable-HTTP 传输(同一端口,无需额外进程)。它暴露约 39 个精选工具(会话、消息、联系人、基础群组操作、webhook 读取)—— 相比完整 API 是精简面,避免智能体不堪重负,并将破坏性操作排除在智能体路径之外。
MCP_ENABLED=true npm run start:prod # or set MCP_ENABLED in your .env / compose
将 MCP 客户端指向该端点(例如 Claude Code,在项目根目录放置 .mcp.json):
{
"mcpServers": {
"openwa": {
"type": "http",
"url": "http://localhost:2785/mcp",
"headers": { "Authorization": "Bearer YOUR_API_KEY" }
}
}
}
密钥可通过 Authorization: Bearer … 或 X-API-Key: … 传递。每次工具调用均经过与 REST 相同的 API 密钥认证、角色和按会话作用域。
安全指南:
- 为智能体签发专用的最小权限密钥 —— 非管理员、按会话作用域的密钥(最多
OPERATOR角色)。明文密钥仅在创建时显示一次;如需轮换,请创建新密钥并删除旧密钥。 - 密钥不得携带 IP 允许列表(
allowedIps)—— MCP 无法获取真实客户端 IP,此类密钥会被拒绝。 - 设置
MCP_READONLY=true仅挂载只读工具(无发送/写入)。 - 设置
MCP_RATE_LIMIT_MAX(默认60)以限制每个 API 密钥在每个时间窗口内的工具调用次数。 - 设置
MCP_RATE_LIMIT_WINDOW_MS(默认60000)以控制滑动窗口大小(毫秒)。 - 不要在没有前置认证代理的情况下将
/mcp暴露到公网。 对于自托管、仅本地访问的部署,静态 API 密钥是合适的;公网暴露应使用 OAuth 2.1(尚未实现)。
🛠 技术栈
| 层级 | 技术 |
|---|---|
| Runtime | Node.js 22 LTS |
| Framework | NestJS 11.x |
| Language | TypeScript 5.x |
| WA Engine | whatsapp-web.js(默认)/ baileys — 通过 ENGINE_TYPE 设置 |
| Database | SQLite / PostgreSQL |
| Cache | Redis(可选) |
| Storage | Local / S3 / MinIO |
| ORM | TypeORM |
| Container | Docker + Docker Compose |
📁 项目结构
openwa/
├── src/
│ ├── main.ts # Application entry point
│ ├── app.module.ts # Root module
│ ├── config/ # Configuration
│ ├── common/ # Shared utilities
│ │ ├── cache/ # Redis caching
│ │ └── storage/ # File storage (Local/S3)
│ ├── core/ # Core systems
│ │ ├── hooks/ # Plugin hooks
│ │ └── plugins/ # Plugin system
│ ├── engine/ # WhatsApp engine abstraction
│ └── modules/
│ ├── session/ # Session management
│ ├── message/ # Message handling
│ ├── webhook/ # Webhook management
│ ├── group/ # Groups API
│ ├── contact/ # Contacts API
│ ├── auth/ # API key authentication
│ ├── infra/ # Infrastructure management
│ └── health/ # Health checks
├── dashboard/ # React web dashboard
├── docs/ # Documentation
├── docker-compose.yml
├── Dockerfile
└── package.json
📚 文档
完整文档位于 docs/ 文件夹:
| 文档 | 说明 |
|---|---|
| Project Overview | 简介与目标 |
| Requirements | 功能规格说明 |
| Architecture | 系统设计 |
| Security | 安全实现 |
| Database | 数据模型与迁移 |
| API Spec | 完整 API 参考 |
| Development | 编码规范 |
| Migration Guide | 数据库与存储迁移 |
🤝 贡献
欢迎贡献!入门步骤如下:
- Fork 本仓库
- 创建 你的功能分支(
git checkout -b feature/amazing-feature) - 提交 你的更改(
git commit -m 'Add amazing feature') - 推送 到该分支(
git push origin feature/amazing-feature) - 打开 Pull Request
请阅读我们的 Development Guidelines 了解编码规范与最佳实践。
📄 许可证
本项目采用 MIT License 许可 —— 可免费用于个人和商业用途。
详见 LICENSE。
OpenWA – 免费、开源的 WhatsApp API 网关
📖 文档 · 🔌 API 文档 · 🐛 报告 Bug · 💡 功能建议
由 Yudhi Armyndharis 与 OpenWA 社区用 ❤️ 制作
