倔强的石头_头像
【极客互动】企业微信外部联系人/群聊:自动群发落地方案,通过API接口AI数字员工开发实践封面图

【极客互动】企业微信外部联系人/群聊:自动群发落地方案,通过API接口AI数字员工开发实践

私域运营的真实痛点不是「没有群发按钮」,而是这三件事叠在一起:

  1. 人一台台点发送:二十个群、上百个客户,客服对着手机点到手腕酸,漏一个群晚上还得补。
  2. 想控频又不知道间隔写哪:风控一变,有人说 30 秒、有人说 2 分钟,Excel 里排完时间表,真正发出去的节奏还是手感。
  3. SOP 和一次性群发搅在一起:每日关怀、活动通知、失败重试,三套表、三个入口,运营对不上哪条已经发出去。

很多团队的做法是:企微官方群发助手 + 人手点发送。这解决不了多号选机器人、按群/好友筛选、定时/周期调度、失败落库重试、工作台回显这些问题。

在 极客聚合(企业微信聚合平台) 里把这条链路做成了现网功能:侧边栏 群发控制台 三个 Tab,新建任务默认间隔 120 秒,后端逐个 vid 打网关单条接口。下面全部是真实菜单名和源码,没有「官方群发助手」「几千人同时并发」「超级群发已经挂上菜单」这种能力。
官网👇

www.jikehudong.com

1. 产品里三个 Tab,别搞成四个

菜单路径是 群发控制台(路由 /message,页面标题就是这三个字)。首页快捷卡文案是「消息群发」,点进去还是这一页。

三个 Tab:

Tab组件干什么
消息群发MassMsgTab.vue一次性任务列表:新增、详情、失败记录、重试、删除
SOP计划SopTab.vue卡片:执行 / 停止 / 修改 / 删除;新建走同一套 CreateMassMsg,taskCategory=sop
SOP记录MassTaskTab.vue执行日志;会把「执行中 / 暂停」的 SOP 计划也并进来

仓库里还有 SuperMassMsgTab.vue / CreateSuperMassMsg.vue,现网三个 Tab 没有挂上。不要按第四个 Tab 去演示。

本机「消息群发」列表里有一条任务「客户群发」:状态成功,成功 1 / 失败 0 / 总数 1,创建人 admin,时间 2026-08-22 23:56:22。失败数为 0,「重试」是灰的——按钮绑的是 failCount,没有失败就不能点。

在这里插入图片描述

点「详情」弹窗:总目标 1、成功 1、失败 0。执行机器人 uuid 是 3e69a8138f83ca109fd7abd126bcafc2,群发对象「客户」,调度「单次定时任务」,开始 23:57:00、结束 23:58:00。这条历史任务的发送频率写的是 1 秒——创建表单默认是 120,已经落库的任务按当时填的数走,页面不会替你改回去。

在这里插入图片描述

点「新增群发」默认对象是 群聊。没选机器人时,左侧选人区写「请先选择机器人」,不会假装拉出一堆群。群内身份:不限 / 群主 / 成员;群类型:全部 / 内部群 / 外部群。

在这里插入图片描述

切到 好友:多出「联系人类型」和「客户标签筛选」。列表同样要先选机器人;好友数据走联系人缓存,号离线、缓存空,选人就会空。

在这里插入图片描述

内容是五个 Tab:文字 / 图片 / 文件 / 小程序 / 名片。当前 Tab 是哪一种,提交就只带那一种——不是图文混排一条任务。群聊文字里有「@所有人」,文案写「机器人是群主/管理员才生效」;字段 form.atAll 没有写进 msg_list,点「是」也不会变成真正的 @所有人。

表单下半截才是调度。任务类型默认定时;发送频率滑条 1~300 秒,默认 120,提示「近期风控规则有变化,建议不小于120S」。自动重试默认关。结束时间的说明是:到点未发完也立刻停。底部按钮叫「立即发送」,周期任务会改成「保存任务」。截图到这里为止,没有点提交。

在这里插入图片描述

SOP 计划是卡片,不是表格。本机有一张「重点客户每日关怀」:周期任务、每天 09:00、好友 · 1 个、创建人 admin、状态 已暂停。底下四个字:执行 / 停止 / 修改 / 删除。暂停时「停止」是灰的。不要点执行——暂停态会走 resume,非暂停会再 sendMassMsg 真正发一轮。

在这里插入图片描述

SOP 记录表里也能看到同一条计划:类型周期任务、状态暂停、0/0/1。这个 Tab 会把 sop_record 和「执行中 / 暂停」的 SOP 计划拼在一张表里,不是纯执行日志。

在这里插入图片描述


2. 技术架构:任务入库,逐个 vid 打单条接口

整体不是「点一次调用企微官方群发助手」。Vue 把对象列表和一条 msg_list 交给 Spring Boot,POST /system/massMsg/send 先写入 sys_mass_msg_task。定时任务丢给调度器;周期任务状态 periodic_active,每分钟 tick 一次。真正发送时,for 循环每个 vid,中间 Thread.sleep(frequencySec * 1000)。单条内容走 SendTextMsg 这类接口;msg_list 多于一条才兜底 SendGroupsMsg。成功后再写 Redis,工作台能回显。

在这里插入图片描述

用 mermaid 把同一张图画成可维护版本:

回写

网关单条接口

Spring Boot

Vue 群发控制台

消息群发

SOP计划

SOP记录

POST /system/massMsg/send

MassMsgScheduler

每分钟 tick 周期任务

逐个 vid Thread.sleep

SendTextMsg

SendCDNImgMsg

SendGroupsMsg 仅多条

Redis 工作台回显

失败记录可重试

创建入口:

@PostMapping("/send")
public AjaxResult send(@RequestBody Map<String, Object> params) {
    SysMassMsgTask task = massMsgService.sendMassMsg(params);
    return AjaxResult.success(task);
}

前端默认间隔和提交字段:

frequency: 120,
// ...
const payload = {
  taskName: this.form.taskName || '群发-' + new Date().toLocaleString(),
  taskCategory: this.taskCategory || 'normal',
  uuid,
  vids,
  isroom,
  msg_list: msgList,
  taskType: this.form.taskType,
  startTime: this.form.startTime,
  endTime: this.form.endTime,
  frequency: this.form.frequency,
  autoRetry: this.form.autoRetry
};
await sendMassMsg(payload);

后端没带 frequency 时同样落成 120。会先丢掉机器人自己的 vid,避免本端消息挂到机器人会话。没填开始时间就丢线程池立刻发;填了就 massMsgScheduler.schedule。周期任务不在这一步发,只把状态写成 periodic_active。

Integer frequency = params.get("frequency") != null
        ? Integer.valueOf(params.get("frequency").toString()) : 120;
vids = filterOutRobotSelfVid(uuid, vids);
task.setStatus(isPeriodic ? "periodic_active" : "waiting");
if (!isPeriodic) {
    dispatchTimedTask(taskId, startTime);
}

周期调度器每分钟扫一次:

@Scheduled(cron = "0 * * * * ?")
public void tick() {
    massMsgService.tickPeriodicMassMessages();
}

发送循环里,间隔、结束时间、暂停是三道闸。暂停会把 resumeFromIndex 写回,下次从停下的那个对象继续。

if (i > 0 && frequencySec > 0) {
    Thread.sleep(frequencySec * 1000L);
}
JSONObject result = sendByMsgList(uuid, vid, isroom, msgList);
if (errcode != null && errcode == 0) {
    persistMassSentMessage(uuid, vid, isroom, msgList, result);
}

单条按类型分流。文字带 [] 走 SendTextAndExpMsg,避免误走 SendGroupsMsg 变成「这是一条群发消息」:

if (msgList != null && msgList.size() == 1) {
    // type 0  -> SendTextMsg / SendTextAndExpMsg
    // type 14 -> SendCDNImgMsg
    // type 15 -> SendCDNFileMsg
    // type 78 -> SendAppMsg
    // type 41 -> SendBusinessCardMsg
}
req.put("vids", Collections.singletonList(vid));
return JSON.parseObject(HttpClientSslUtils.doPost(
        getSendApiBase() + "/wxwork/SendGroupsMsg", req.toJSONString(), ...));

现网表单 buildMsgList() 一次只返回一个元素,所以日常走上面那些单条接口。图片、文件是点「立即发送」时才 cdnUploadImg / cdnUploadFile,前端卡图片 10MB、文件 20MB。

后端还认 type=10001 打 SendNotice(群公告,仅群聊)。创建表单没有这个 Tab,不要按现网能力吹。


3. SOP 不是另一套发送器

SOP 计划和消息群发共用 CreateMassMsg.vue,只是 taskCategory 从 normal 换成 sop。周期选项是每天 / 每周 / 每月,再加一个触发时分。卡片上的「执行规则」就是这段配置拼出来的文案。

点「执行」有两条路:

  1. 计划已暂停 → POST /system/massMsg/resume,从 resumeFromIndex 接着发。
  2. 其它状态 → 再调一次 sendMassMsg,任务名后面加 (手动执行),taskCategory 写成 sop_record。

第二条会真正往网关打消息。截图里那张「已暂停」的卡片,点执行就是 resume,所以演示时不要点。

SOP 记录 Tab 会并行拉 sop_record 和 sop。无筛选时,计划只保留 running / periodic_active / paused。这就是为什么暂停中的「重点客户每日关怀」会出现在记录表——它还没变成一条独立的执行日志。


4. 现网边界

能做的:

  • 三个 Tab:消息群发、SOP 计划、SOP 记录。
  • 对象群聊或好友;群可筛身份和内外部;好友可筛内外部 + 企业标签。
  • 内容五种之一:文字 / 图片 / 文件 / 小程序 / 名片。
  • 定时或周期;默认间隔 120 秒;到结束时间停;可暂停后续传。
  • 失败写入失败表,列表「重试」在 failCount>0 时才可点;创建时「自动重试」默认关,打开后当次失败会立刻再打一次。
  • 发送成功写 Redis,客服工作台能看到这条群发。

要说清楚的问题:

  • 不是企微官方群发助手。 不会走企业微信后台那套群发额度,也不会在手机端出现「群发」记录样式。
  • 120 秒只是页面建议。 滑条能拖到 1 秒,本机这条「客户群发」详情就是 1 秒。调度器不会替你拦风控。
  • 一次一种内容。 五个 Tab 不会拼成图文混排一条 msg_list。
  • 「@所有人」是摆设。 单选绑定了 form.atAll,提交 payload 没用它。
  • 超级群发代码在仓库,菜单没挂。 不要演示第四个 Tab。
  • 群公告只在后端。 SendNotice 有实现,表单没有入口。
  • SOP「执行」会真发。 暂停是 resume,否则新建一条 sop_record 再跑发送循环。
  • 好友列表依赖号在线 + 客户缓存。 没选机器人是「请先选择机器人」;选了离线号,缓存空就「暂无数据」。
  • 不是几千人同时并发。 一个任务一条线程,对象之间 sleep。多开几个任务会叠线程,没有全局限流面板。
  • 和「好友添加中心」批量加好友不是同一功能。 群发只对已经能选到的 vid 发消息。

5. 落地清单

  1. 菜单做 群发控制台,三个 Tab:消息群发 / SOP 计划 / SOP 记录。超级群发没接上就不要放入口。
  2. 创建表单:机器人必选,对象群或好友,内容五个 Tab 一次一种。
  3. POST /system/massMsg/send 入库;无开始时间立刻发,有开始时间 schedule;周期任务 periodic_active + 每分钟 tick。
  4. 默认 frequency=120,循环里 Thread.sleep;到结束时间 break;暂停写 resumeFromIndex。
  5. 单条走 SendTextMsg / CDN 图文件 / 小程序 / 名片;多条才 SendGroupsMsg。文字带 [] 走表情接口。
  6. 过滤机器人自己的 vid;成功 persistMassSentMessage 写 Redis。
  7. 失败落 failList,列表重试看 failCount;自动重试是当次再打一枪,不是无限循环。
  8. SOP 执行要么 resume,要么带 sop_record 再 sendMassMsg。演示环境不要拿暂停计划去点执行。

6. 总结

消息群发的技术难度不在「再包一层 SendGroupsMsg」,而在 选人、控频、定时/周期、失败续传、工作台回显要落在同一个菜单里。极客聚合这条链路已经按这个节奏在跑:任务入库,逐个 vid 打单条接口,默认间隔 120 秒。官方群发助手没接,超级群发没挂菜单,@所有人也还没写进 payload——这些现网就长这样。

如果你也在管一批企微号,被「一台台点发送」「间隔靠手感」「SOP 和一次性群发对不上账」折磨过,可以试一下这款产品
官网:👇

www.jikehudong.com

转载自 CSDN-专业IT技术社区

原文链接:https://blog.csdn.net/2302_78391795/article/details/168015523

文章来源转载

评论

评论列表

微信小程序
QQ小程序

关于作者

点赞数:0
关注数:0
粉丝:0
文章:0
关注标签:0
加入于:--