NEW

免费试用已开放

立即开始

私域 · 营销 · SCRM · 客户

企业微信自动加好友怎么实现

更新于 2026-06-0910 分钟

「自动加好友」通常不是一个单独的接口,而是一条由线索导入、发起请求、自动通过、打标签与触达组成的流水线。下面按这条链路拆开讲清楚每一步要做什么、容易踩的坑,以及如何在合规前提下稳定运行。

先拆需求:「自动加好友」由五段组成

「自动加好友」在需求文档里通常只有一行字,落到系统里却是五段各自独立的流程,每段有自己的触发方式、失败形态和负责重试的角色。不先拆开,写出来的多半是把五件事塞进一个函数的脚本,任何一段出问题都只能整体重跑。

  1. 1线索准备:把待添加对象和它的来源键落成一条记录,状态置为待发起。没有这条记录,后面所有环节都无处挂账。
  2. 2发起添加:按速率预算逐条提交添加请求,附上来源备注,并把线索状态推进到已发起。
  3. 3等待通过:对方通过是个异步结果,可能几秒,也可能三天。这一段不能靠轮询硬等,要由事件回调驱动。
  4. 4打标签与归属:收到通过事件后,在同一次处理里写来源、打标签、指派承接人。
  5. 5首次触达:发送欢迎语或引导消息,把线索交给后续的运营流程。

这五段里真正能全自动的是第 1、4、5 段;第 2 段受速率约束,只能做成排队作业;第 3 段完全由对方决定,你能控制的只有「收到之后多久有反应」。把不可控的段当成可控的来设计,是这类需求最常见的翻车方式。

还有一层要先说破:「一天自动加两百人」这句话里的「自动」,指的只是第 2 段的吞吐;而决定最终转化的是第 4、5 段的交接质量。两段的工程量差不多,先做后者。

动手之前:五样东西要先备齐

缺任何一样,后面的步骤都能跑通,但跑不长 —— 问题会以「偶发失败」的形式回来找你。

  • 账号已接入且状态可查。wecomapi 按实例隔离账号,发起添加前先确认目标实例在线,别让一批任务发给一个已经掉线的号。
  • 回调地址已通、签名校验已做。第 3 段依赖事件回调,回调不通,整条链路就退化成人工盯屏。
  • 一张线索表,至少要有:线索键、来源键、目标账号、当前状态、状态更新时间、最后一次调用的请求标识。
  • 一份速率预算。按账号、按时段写死每小时允许发起多少条,这个数要能在配置里改,不要散落在代码各处。
  • 一个能立刻停下来的开关。批量作业跑起来之后最先需要的不是看板,是一个能在半分钟内让所有出向调用停住的位置。

来源键必须在发起添加之前生成并落库。通过事件到达时你手上只有客户标识和一个码,两者能对上全靠这条预先登记的记录 —— 站内讲来源归因的那篇算过这笔账:错过通过那一刻,来源就只能靠时间接近度猜。

分步实施:每一步都要有可判定的完成标准

下面五步按依赖顺序排,不要跳步。前两步是数据地基,跳过去之后写的排队和幂等都建在沙上。

  1. 1先跑通单条。手动往线索表插一条记录,让它走完五段。看每一段的状态更新时间有没有写进去;判据是这条线索最终停在已触达状态,且中途每次状态变更都查得到,而不是只有首尾两条。
  2. 2接通事件回调。在测试环境用一个账号收一次真实的通过事件,看回调是否在几秒内到达、签名校验是否通过。判据是回调处理函数先返回 2xx、再由队列消费者跑业务,而不是在回调里同步做完所有事。
  3. 3把发起添加改成排队作业。看出队速率有没有被速率预算真正限制住;判据是一次性灌进 1000 条线索,实际发起量按小时匀开,而不是几分钟内打完。
  4. 4给通过事件加幂等。把同一条通过事件重放两次,判据是标签只写一次、欢迎语只发一条。做不到就说明幂等键取错了。
  5. 5补齐失败去向。人为制造一次发送失败,判据是这条线索停在一个明确的失败状态并进入重试队列,而不是卡在中间态、也没有任何告警。

架构与数据流:谁调谁、状态存哪、谁负责重试

数据流只有两个方向:出向是你主动调接口(发起添加、打标签、发消息),入向是平台把事件推给你。两个方向的失败语义不同,重试责任也不在同一处。

  • 状态存哪:唯一权威在你自己的线索表。平台侧只回一次调用结果,它不替你记「这条线索走到哪了」。
  • 出向失败谁重试:你的作业调度器。带退避、带次数上限,超限进死信,死信要有人看。
  • 入向失败谁重试:平台按投递重试语义重发,所以回调必须幂等。回调里只做校验和入队,业务逻辑放到队列消费者里。
  • 事件乱序:通过事件和对方的第一条消息几乎同时发生,到达顺序不保证。按线索键做 upsert,谁先到谁把记录立起来,后到的只做合并。
  • 幂等边界:出向调用按幂等语义设计,网络抖动后重试是安全的;真正需要你自己保证幂等的,是入向事件的消费。

下面这段骨架里唯一写死的真实端点是文本发送。发起添加、通过申请、打标签这几个动作的端点与字段以线上接口文档为准,但它们在架构上的位置是固定的:都在出向一侧、都受同一个速率闸控制、都要把请求标识写回线索表。

示意:通过事件消费者里的首次触达javascript
// 示意逻辑:除文本发送外,函数与状态名均为自拟;
// 发起添加、通过申请、打标签的端点与字段以线上接口文档为准
async function greet(lead) {           // 通过事件消费者的最后一步
  const res = await fetch("https://manager.wecomapi.com/message/sendText", {
    method: "POST",
    headers: {
      Authorization: `Bearer ${process.env.TOKEN}`,
      "Content-Type": "application/json",
    },
    body: JSON.stringify({
      guid:    lead.guid,              // 发送方账号实例
      toId:    lead.customerId,
      content: welcomeText(lead),
    }),
  });

  // 可追溯标识在响应头上,响应体里只有 code 和 msg,别去里面找
  await store.trace(lead, res.headers.get("x-request-id"),
                          res.headers.get("x-ratelimit-remaining"));

  const { code, msg } = await res.json();
  if (code !== 0) throw new SendFailed(msg);  // 交给作业调度器退避重试
  return store.mark(lead, "greeted");         // 状态权威在自己的线索表
}

错误处理与排障

这一节最容易被略过,上线后又最耗时间。先按「该做什么」把失败分类,再谈怎么查。

  1. 1参数或对象不对:同样的请求重发一百次,结果一样。立刻停,回去改数据,不要重试。
  2. 2状态失效:凭证过期、账号掉线。先执行一次明确的修复动作,成功后只重试一次;再失败就升级成告警,别在队列里空转。
  3. 3被限速:响应头 x-ratelimit-remaining 已经很低时,基本就是这一类。退避并调低整体速率,不要原地重试。
  4. 4结果未知:请求超时、连接中断。你不知道对方到底做没做,正确反应是去确认而不是重发 —— 重发一次添加请求,代价是对方收到两次打扰。

排障时按这个顺序看,前两步都在响应头上:

  • 先看 x-request-id。它是这次调用的可追溯标识,在响应头里而不在响应体里,所以要在 HTTP 客户端那一层就取出来写进线索表,提工单时给这个值即可。
  • 再看 x-ratelimit-remaining 的走势。整批任务里它是均匀下降还是断崖式掉到零,能直接区分「逻辑写错了」和「速率排得太密」。
  • 线索根本没进队列:问题在入站流或规则上,不在发送。先确认回调有没有到,而不是去翻发送日志。
  • 通过率下降但接口一直返回 code 为 0:八成不是接口问题,去查发起节奏、时段和备注话术,继续加日志没用。
  • 事件不来了、调用却不报错:这是最隐蔽的一类。给入向事件加一条按时段区分的静默基线告警,否则第 3 段会安静地停摆几天没人发现。
验证发送侧:用 -i 把响应头一起看出来bash
# 排障要的两个信息在响应头上,所以用 -i 而不是裸 curl
curl -i -X POST "https://manager.wecomapi.com/message/sendText" \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"guid":"7db8...","toId":"78813...","content":"验证用文本"}'

# 看 HTTP 状态行、x-request-id、x-ratelimit-remaining 三处;
# 响应体回 {"code":0,"msg":"success"} 才算发送侧成功

具体错误码的含义与分类以线上接口文档为准。站内讲接口报错分类的那篇把「该重试」和「不该重试」的边界写得更细,站内讲 Webhook 幂等的那篇解释了幂等键为什么必须带上处理器名 —— 本页只交代它们在这条链路上的位置。

怎么验证做对了

「跑通了」不是判据。下面几条才是,每一条都能在库里或面板上读到一个数,任何一条不成立,就说明还有一段没接上。

  • 来源覆盖率:已通过的线索里来源键非空的占比。低于九成说明第 1 段和第 4 段没接好。未知来源要是一个正式取值,不能用空值代替。
  • 首触时延分位数:从通过事件到欢迎语发出的 P90。看分位数不看平均值,平均值会被大量秒回稀释掉。
  • 状态残留量:线索表里停在中间状态超过 24 小时的条数。健康的系统里这个数长期接近零。
  • 重复副作用:同一客户收到两条欢迎语的次数。非零就说明幂等没做住,回到分步实施的第 4 步。
  • 速率余量:整批作业跑完后 x-ratelimit-remaining 的最低点。贴着零跑说明预算排得太满,没给重试和补偿留空间。

这几条建议做成定期自检,而不是上线那天看一遍。链路里的每一段都会各自变化:话术会改、渠道会新增、承接人会轮换,三个月不看,来源覆盖率就会悄悄掉下来。

最后一条边界:能自动的是流程调度和记录,不能自动的是「要不要加这个人」。保留来源与同意凭证,给整套作业留一个能立刻停下来的开关。站内讲自动获客的那篇算过一笔账:加人速度翻倍带来的增量,通常抵不过线索在交接环节漏掉的那部分。

常见问题

企业微信自动加好友有现成的单一接口吗?
没有一个「一键全自动」的单接口。它是线索登记、发起添加、事件回调、标签写入、消息发送这几件事的组合,wecomapi 以统一的 REST 语义和同一套鉴权把它们串起来,具体端点与字段以线上接口文档为准。
企业微信自动加好友一天能加多少人?
这个数不该由代码决定,应该由你写死的速率预算决定,并按账号、按时段分开配。判断预算合不合适看两个信号:整批作业跑完后响应头 x-ratelimit-remaining 的最低点有没有贴着零,以及通过率有没有随着发起量上升而下滑。任一条成立就把预算调低,把任务摊到更多时段。
好友申请怎么做到自动通过?
靠事件回调而不是轮询。平台把申请事件推给你的服务,回调里先校验签名、快速返回 2xx 并入队,再由消费者按规则判断是否执行通过动作。规则命中后在同一次处理里写来源、打标签,别留给后续任务补。通过动作的精确端点与字段以线上接口文档为准。
加上好友之后怎么自动打标签和发欢迎语?
把它们绑在同一次通过事件的处理里:写来源、打标签、发欢迎语,一次做完并把线索状态推进到已触达。欢迎语走文本发送接口,请求体是 guid、toId、content 三个字段,响应体回 code 为 0 才算发送侧成功。事件可能重复投递,所以这段处理必须幂等,否则同一个客户会收到两条欢迎语。
企业微信自动加好友失败了怎么排查?
先分类再查。参数或对象不对属于确定性失败,重试没有意义;凭证过期、账号掉线要先修复再只重试一次;被限速要退避降速;超时和连接中断属于结果未知,应该去确认而不是重发。查的时候以响应头 x-request-id 为线索,它是这次调用的可追溯标识,提工单时给这个值即可。
自动加好友会不会让来源归因做不准?
不会,前提是来源键在发起添加之前就已经落库。通过事件到达时你手上只有客户标识,来源要靠预先登记的那条线索记录对上,事后回填出来的来源基本是猜的。另外别用空值表示未知 —— 未知应该是一个正式取值,它的占比就是你的归因覆盖率。

准备好动手了?

精确字段、鉴权与端点以线上文档为准;可在控制台创建密钥后联调。

相关指南