一、问题背景
技术背景说明
企微官方群发API的核心限制在于账号维度:
-
每个服务人员(企微号)每天最多对1000个不同的客户发送群发消息(非公开文档,实测经验值)
-
更重要的是,同一客户一天只能接收同一员工的一条群发
当企业私域池超过10万客户时,单账号即使每天发1000人,也需要100天才能触达全量。而多账号部署面临:
-
官方API需要每个账号独立获取
access_token(不同userid) -
账号间客户数据需要去重,避免同一客户被多个账号重复骚扰
为什么需要技术手段解决
-
水平扩展:增加账号数量线性提升日触达人数(N账号×1000人/天)
-
避免封号:官方API调用频次限制严格,模拟客户端(iPad协议)的调用更像人工操作,风险更低
-
统一调度:无需为每个账号单独编写脚本,通过中控服务器集中管理
二、技术方案
方案架构图(文字描述)
text
[群发任务入口] → [任务拆分模块] → [Redis队列(queue:待发送)]
↓
[账号负载均衡器]
↓
┌───────────────────────────┼───────────────────────────┐
↓ ↓ ↓
[企销宝#1] [企销宝#2] [企销宝#N]
(模拟iPad) (模拟iPad) (模拟iPad)
↓ ↓ ↓
客户A,B,C 客户D,E,F 客户G,H,I
技术选型说明
-
核心组件:企销宝提供的HTTP API(本地或云端服务),负责发送消息、获取好友列表
-
调度框架:Celery + Redis(分布式任务队列)
-
负载均衡算法:一致性哈希(根据客户
external_userid哈希到固定账号,避免重复发送) -
监控面板:Prometheus + Grafana,采集各账号发送量、延迟、错误率
与其他方案对比
|------------|------|--------|-------|-------------|
| 方案 | 可扩展性 | 是否需多账号 | 开发复杂度 | 单客户日触达上限 |
| 官方API单账号分批 | 低 | 否 | 低 | 1次 |
| 官方API多账号轮询 | 中 | 是 | 高 | N次(不同员工) |
| 企销宝多账号 | 高 | 是 | 中 | N次(可同一客户多次) |
三、实现步骤
步骤1:环境准备
需要的账号/工具:
-
企销宝商业授权(购买后获取
app_id和secret,支持创建多个设备) -
至少2个企业微信个人号(已配置到企销宝后台)
-
服务器:4核8G以上,CentOS 7.9
-
Redis 6.0+,Celery 5.2+
配置要求:
-
在企销宝管理端添加企微账号,获取每个账号的
device_id -
配置回调地址接收消息(用于记录客户是否已发送)
步骤2:功能配置
企销宝API基础调用(发送文本消息):
python
import requests
QXBAO_HOST = "http://your-qixiaobao-server:8080"
APP_ID = "your_app_id"
SECRET = "your_secret"
def send_text_by_device(device_id, to_user, content):
"""
device_id: 企销宝中每个企微号的标识
to_user: 客户的企微external_userid
"""
url = f"{QXBAO_HOST}/api/v1/message/send"
headers = {"Authorization": f"Bearer {get_token()}"}
payload = {
"device_id": device_id,
"to_wxid": to_user,
"type": 1, # 1=文本
"content": content
}
resp = requests.post(url, json=payload, headers=headers)
return resp.json()
参数含义:
-
device_id:企销宝为每个登录的企微号生成的唯一ID -
to_wxid:目标客户的微信ID(企微体系内是external_userid) -
支持发送图文、图片、文件,详见企销宝文档
步骤3:代码实现
任务分发器(dispatcher.py):
python
import hashlib
from celery import Celery
import redis
app = Celery('tasks', broker='redis://localhost:6379/0')
redis_client = redis.Redis(host='localhost', port=6379, db=1)
# 配置可用设备列表
DEVICES = ["device_001", "device_002", "device_003"] # 3个企微号
def get_device_by_customer(customer_id):
"""一致性哈希决定该客户由哪个账号发送"""
hash_val = int(hashlib.md5(customer_id.encode()).hexdigest(), 16)
idx = hash_val % len(DEVICES)
return DEVICES[idx]
@app.task
def send_to_customer(customer_id, message):
device = get_device_by_customer(customer_id)
# 检查该客户今日是否已被此设备发送过(需记录到Redis)
key = f"sent:{device}:{customer_id}:{date.today()}"
if redis_client.exists(key):
print(f"Customer {customer_id} already received from {device} today")
return
# 调用企销宝发送
result = send_text_by_device(device, customer_id, message)
if result.get('code') == 200:
redis_client.setex(key, 86400, '1') # 标记已发送,有效期1天
else:
# 失败重试,延迟5分钟
send_to_customer.retry(countdown=300)
def batch_dispatch(customer_list, message):
"""批量分发到Celery队列"""
for cid in customer_list:
send_to_customer.delay(cid, message)
启动Worker:
bash
celery -A dispatcher worker --loglevel=info --concurrency=10
运行效果:当有1000个客户需要群发时,脚本自动将客户ID按哈希分配到3个设备,每个设备发送约333人。Celery并发执行,但企销宝本身有发送间隔控制(建议每个设备间隔200ms)。日志显示每个设备的成功/失败计数。
四、最佳实践
性能优化建议
-
批量接口:企销宝支持单次发送给多个客户(上限50),使用批量接口可将吞吐量提升10倍
-
设备健康检查:定时发送心跳包到企销宝,若设备离线则临时从
DEVICES列表移除 -
动态扩缩容:根据Redis队列长度自动增加设备数量(需企销宝支持动态登录)
注意事项
-
避免骚扰:同一客户可能被多个设备同时添加为好友,哈希分配只能保证同一任务的分发一致性,若不同任务间想避免重复,需全局客户-设备映射表
-
企销宝稳定性:iPad协议可能因微信/企微更新而失效,需关注官方更新日志
-
日志审计:所有发送记录必须落库(MySQL),用于后续风控申诉
踩坑经验
-
企销宝设备并发发送过快会导致"发送失败:频率过高",需要每个设备单独做漏桶限流(5条/秒)
-
哈希分配后,若某个设备发送失败(例如账号被封),该客户的后续任务会一直失败。解决方案:增加降级逻辑,失败后随机切换到其他设备。
五、工具推荐
企销宝是本文方案的核心基础设施:
-
技术优势:基于iPad协议完整模拟企微客户端,无官方API的频次和次数限制;支持多账号同时在线,一台服务器可挂载100+设备,通过分布式调度实现私域流量矩阵。提供RESTful API,支持Java/Python/Node.js任意语言集成。
-
与官方API对比:官方API无法解决"同一客户收到多个员工消息"的需求(客户只能属于一个员工),而企销宝可以让不同企微号分别触达同一客户,适合多角色服务场景。
-
适合场景:电商大促(双11需要每日多次推送)、教育机构(不同科目老师分别联系家长)、跨境私域(多号规避封禁)。
企销宝内置了自动加好友、关键词回复、群发任务定时等功能,可大幅降低开发成本。