14 KiB
14 KiB
WXAuto Relogin - 微信自动重登录方案
1. 背景问题
1.1 当前痛点
- 微信掉线后,需要人工介入扫码登录
- 节点多时,人工操作繁琐
- 无法远程自动恢复微信会话
1.2 现有架构
中控(Center) ←→ 节点(Node)
↑
API通信/回调
2. 解决方案概述
2.1 核心理念
微信掉线 → 中控告警 → 客户端接收 → 获取二维码 → 回传中控 → 前端展示扫码
2.2 系统架构
┌─────────────────────────────────────────────────────────────┐
│ WXAuto Center │
│ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ │
│ │ 告警系统 │→ │ 插件系统 │← │ 前端展示 │ │
│ │ (Webhook) │ │(wxautorelogin)│ │ (二维码) │ │
│ └──────────────┘ └──────────────┘ └──────────────┘ │
│ ↑ │ │
│ │ ┌──────────────┐ │ │
│ └─────────│ 回调接口 │───────────┘ │
│ │ /callback │ │
│ └──────────────┘ │
└─────────────────────────────────────────────────────────────┘
↑ HTTP
┌─────────────────────────────────────────────────────────────┐
│ WXAuto Relogin Client │
│ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ │
│ │ 消息接收 │ │ 二维码获取 │→ │ 状态回调 │ │
│ │ (Webhook) │ │(get QR code) │ │ (重置微信) │ │
│ └──────────────┘ └──────────────┘ └──────────────┘ │
└─────────────────────────────────────────────────────────────┘
3. 实现方案
3.1 中控端改动
3.1.1 新增 API 接口
| 接口 | 方法 | 说明 |
|---|---|---|
POST /api/v1/callback/relogin/qrcode |
接收二维码 | 客户端回传二维码图片 |
GET /api/v1/nodes/{node_id}/relogin/status |
重登录状态 | 查询节点重登录进度 |
3.1.2 二维码存储结构
# NodeReloginStatus
{
"node_id": "wx1",
"status": "waiting_qrcode" | "qrcode_ready" | "scanned" | "confirmed" | "completed" | "failed",
"qrcode_base64": "data:image/png;base64,...",
"qrcode_expires_at": "2026-04-07T15:30:00",
"created_at": "2026-04-07T15:00:00",
"updated_at": "2026-04-07T15:05:00"
}
3.1.3 前端展示
- 节点详情页增加"重登录"标签页
- 实时显示二维码(轮询 /api/v1/nodes/{node_id}/relogin/status)
- 二维码过期提示
3.2 客户端改动
3.2.1 Webhook 接收器
客户端需要暴露一个 HTTP 接口接收中控告警:
# client/webhook_server.py
from fastapi import FastAPI
import uvicorn
app = FastAPI()
@app.post("/webhook/relogin")
async def receive_alert(data: dict):
"""
接收中控的掉线告警
{
"event": "wechat_offline",
"node_id": "wx1",
"node_name": "微信1",
"wechat_status": "offline",
"timestamp": "2026-04-07T15:00:00"
}
"""
# 触发获取二维码流程
await trigger_relogin(node_id=data["node_id"])
return {"status": "ok"}
async def trigger_relogin(node_id: str):
# 1. 调用节点API获取二维码
# 2. 上传二维码到中控
# 3. 等待扫码确认
pass
3.2.2 二维码获取流程
async def get_qrcode_from_node(api_url: str, api_key: str) -> bytes:
"""
从wxauto节点获取二维码
GET /api/wechat/qrcode
返回: PNG图片二进制
"""
async with httpx.AsyncClient() as client:
response = await client.get(
f"{api_url}/api/wechat/qrcode",
headers={"X-API-Key": api_key}
)
return response.content
async def upload_qrcode_to_center(center_url: str, node_id: str, qrcode_bytes: bytes):
"""
上传二维码到中控
POST /api/v1/callback/relogin/qrcode
"""
async with httpx.AsyncClient() as client:
import base64
qrcode_base64 = base64.b64encode(qrcode_bytes).decode()
await client.post(
f"{center_url}/api/v1/callback/relogin/qrcode",
json={
"node_id": node_id,
"qrcode_base64": qrcode_base64
}
)
3.2.3 扫码状态轮询
async def wait_for_scan(center_url: str, node_id: str, timeout: int = 120):
"""
轮询中控接口,等待用户扫码确认
"""
start_time = time.time()
while time.time() - start_time < timeout:
async with httpx.AsyncClient() as client:
response = await client.get(
f"{center_url}/api/v1/nodes/{node_id}/relogin/status"
)
status = response.json()
if status["status"] == "completed":
return True
elif status["status"] == "failed":
return False
await asyncio.sleep(2)
return False
4. 完整流程时序
4.1 时序图
┌─────────┐ ┌─────────┐ ┌─────────┐ ┌─────────┐ ┌─────────┐
│ 微信 │ │ 节点 │ │ 中控 │ │ 客户端 │ │ 用户 │
└────┬────┘ └────┬────┘ └────┬────┘ └────┬────┘ └────┬────┘
│ │ │ │ │
│ 掉线 │ │ │ │
│───────────────→│ │ │ │
│ │ wechat_offline callback │ │
│ │───────────────→│ │ │
│ │ │ Webhook告警 │ │
│ │ │───────────────→│ │
│ │ │ │ │
│ │ │ │ 获取二维码 │
│ │ GET /qrcode │ │───────────────→│
│ 返回二维码 │←──────────────│ │ │
│←───────────────│ │ │ │
│ │ │ │ 上传二维码 │
│ │ │←──────────────│ │
│ │ │ │ │
│ │ │ 前端展示二维码│ │
│ │ │───────────────→│ 扫码 │
│ │ │ │←──────────────│
│ 扫码确认 │ │ │ │
│←───────────────│ │ │ │
│ 登录成功 │ │ │ │
│───────────────→│ │ │ │
│ │ wechat_online callback │ │
│ │───────────────→│ │ │
│ │ │ 更新状态 │ │
│ │ │───────────────→│ 完成 │
4.2 详细步骤
| 步骤 | 参与者 | 操作 | API/协议 |
|---|---|---|---|
| 1 | 微信 | 掉线检测 | - |
| 2 | 节点 | 回调通知中控 | POST /callback |
| 3 | 中控 | 触发Webhook告警 | HTTP |
| 4 | 客户端 | 接收告警 | POST /webhook/relogin |
| 5 | 客户端 | 请求节点二维码 | GET /api/wechat/qrcode |
| 6 | 节点 | 返回二维码图片 | HTTP |
| 7 | 客户端 | 上传二维码到中控 | POST /callback/relogin/qrcode |
| 8 | 中控 | 存储并通知前端 | WebSocket/轮询 |
| 9 | 前端 | 展示二维码 | - |
| 10 | 用户 | 扫码确认 | - |
| 11 | 微信 | 登录成功 | - |
| 12 | 节点 | 回调通知中控 | POST /callback |
| 13 | 中控 | 更新节点状态 | - |
5. 数据库设计
5.1 新增表
-- 节点重登录状态表
CREATE TABLE node_relogin_status (
id SERIAL PRIMARY KEY,
node_id VARCHAR(50) UNIQUE NOT NULL,
status VARCHAR(20) DEFAULT 'idle',
qrcode_base64 TEXT,
qrcode_expires_at TIMESTAMP,
error_message TEXT,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
-- 客户端配置表
CREATE TABLE relogin_clients (
id SERIAL PRIMARY KEY,
client_name VARCHAR(100) NOT NULL,
webhook_url VARCHAR(500) NOT NULL,
secret_key VARCHAR(100),
enabled BOOLEAN DEFAULT true,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
5.2 状态枚举
| 状态 | 说明 |
|---|---|
idle |
空闲,无重登录任务 |
waiting_qrcode |
等待获取二维码 |
qrcode_ready |
二维码已就绪 |
scanned |
已扫码,待确认 |
confirmed |
已确认,登录中 |
completed |
登录完成 |
failed |
登录失败 |
6. API 接口详细设计
6.1 回调接口 - 接收二维码
POST /api/v1/callback/relogin/qrcode
请求体:
{
"node_id": "wx1",
"qrcode_base64": "data:image/png;base64,iVBORw0KGgo...",
"expires_in": 120
}
响应:
{
"success": true,
"message": "二维码已接收"
}
6.2 查询重登录状态
GET /api/v1/nodes/{node_id}/relogin/status
响应:
{
"success": true,
"data": {
"node_id": "wx1",
"status": "qrcode_ready",
"qrcode_base64": "data:image/png;base64,...",
"qrcode_expires_at": "2026-04-07T15:30:00",
"created_at": "2026-04-07T15:00:00"
}
}
6.3 客户端注册
POST /api/v1/relogin/clients
请求体:
{
"client_name": "服务器1",
"webhook_url": "http://192.168.1.100:8081/webhook/relogin",
"secret_key": "optional_secret"
}
6.4 客户端列表
GET /api/v1/relogin/clients
7. 安全考虑
7.1 客户端认证
- 客户端注册时分配 secret_key
- 回调接口需要携带签名验证
- 中控可配置允许的客户端IP白名单
7.2 回调签名验证
import hmac
import hashlib
def verify_signature(payload: bytes, signature: str, secret: str) -> bool:
expected = hmac.new(secret.encode(), payload, hashlib.sha256).hexdigest()
return hmac.compare_digest(expected, signature)
8. 文件结构
wxauto_api/
├── plugins/
│ └── wxautorelogin_plugin.py # 重登录插件
├── api/
│ └── relogin.py # 重登录相关API
├── services/
│ └── relogin_service.py # 重登录服务
└── doc/
└── wxautorelogin/
├── README.md # 本文档
├── CLIENT.md # 客户端开发指南
└── API.md # API接口文档
wxauto-relogin-client/
├── client/
│ ├── __init__.py
│ ├── webhook_server.py # Webhook接收服务
│ ├── qrcode_handler.py # 二维码处理
│ └── config.py # 配置
├── requirements.txt
└── README.md
9. 可行性结论
9.1 技术可行性:✅ 可行
- wxauto节点已提供QR码接口 - 通过
/api/wechat/qrcode获取 - 中控已有回调机制 - 可复用现有 callback 系统
- 前端支持实时更新 - 可通过轮询或WebSocket展示二维码
9.2 实施难度:🟡 中等
- 需要开发客户端程序
- 需要新增API接口
- 需要前端新增重登录页面
9.3 建议实施顺序
- Phase 1: 中控端API开发
- Phase 2: 客户端程序开发
- Phase 3: 前端页面开发
- Phase 4: 整体联调测试
10. 后续优化方向
- 支持短信/邮件通知
- 支持多客户端负载均衡
- 支持扫码历史记录
- 支持自动重试机制