企业微信二次开发 API:如何与 SCRM 打通外部联系人的消息发送

**SEO摘要:**本文详解SCRM系统如何基于企业微信官方客户联系API,实现给外部联系人发送文本消息、接收Webhook回调事件、同步客户数据。涵盖整体系统架构、Java SpringBoot核心代码示例(access_token获取、消息发送、回调解密)、数据库表设计、业务完整流程、开发踩坑避坑清单与合规建议,适合后端开发者做SCRM二次开发参考。

目录

  • 一、业务背景
  • 二、整体系统架构
  • 三、前置开发准备
  • [四、核心代码示例(Java SpringBoot)](#四、核心代码示例(Java SpringBoot))
    • [4.1 获取access_token工具类](#4.1 获取access_token工具类)
    • [4.2 SCRM调用接口,给外部联系人发送文本消息](#4.2 SCRM调用接口,给外部联系人发送文本消息)
    • [4.3 Webhook回调接口:接收企微推送的外部联系人事件](#4.3 Webhook回调接口:接收企微推送的外部联系人事件)
    • [4.4 数据库表设计(简化版)](#4.4 数据库表设计(简化版))
  • 五、业务完整流程
    • [5.1 新增客户流程](#5.1 新增客户流程)
    • [5.2 SCRM后台主动给客户发消息流程](#5.2 SCRM后台主动给客户发消息流程)
  • [六、开发踩坑 & 避坑清单](#六、开发踩坑 & 避坑清单)
  • 七、扩展方向
  • 八、总结

一、业务背景

SCRM系统需要管理企业微信的外部客户,常见需求:

  1. SCRM业务后台触发,给外部联系人发送文本、图片、图文消息;

  2. 接收企业微信回调事件:新增客户、删除客户、客户消息回调;

  3. 将企微 external_userid 和SCRM本地客户档案做关联映射;

  4. 会话数据双向同步,业务系统记录客户沟通记录、执行SOP自动推送消息。

二、整体系统架构

架构流程图

核心技术栈说明:

API接口调用参考:https://wechatapi.apifox.cn/

开发环境:JDK1.8,Mysql5.0,Redis7

开发语言:JAVA,PHP

前端框架:VUE

架构模块说明

  1. 鉴权模块 :定时获取企业微信 access_token,缓存,过期自动刷新;

  2. 消息发送模块:SCRM业务请求 → 参数封装 → 调用企微客户联系发送接口,增加限流、失败重试;

  3. Webhook回调服务:企业微信把新增客户、客户消息等事件POST推送到此服务;做签名校验、消息解密;

  4. 数据存储层 :维护映射关系 SCRM客户ID ↔ 企微external_userid ↔ 企微userid(员工ID),存储聊天记录、客户标签、跟进记录。

三、前置开发准备

  1. 企业微信完成企业认证;

  2. 创建自建应用,开启权限:客户联系权限;

  3. 配置回调URL、回调Token、EncodingAESKey(用于消息加密解密);

  4. 记录 corpid(企业ID)、自建应用 secret;

  5. 理解核心ID概念:

    • userid:企业内部员工账号ID;

    • external_userid:外部微信联系人唯一ID,对外客户的主键;

    • parent_userid:客户所属跟进员工ID。

四、核心代码示例(Java SpringBoot)

4.1 获取access_token工具类

access_token是调用所有接口凭证,有效期2小时,必须缓存,不要每次请求都调用获取接口。

java 复制代码
import org.springframework.web.client.RestTemplate;
import com.alibaba.fastjson.JSONObject;

@Component
public class WeComTokenUtil {

    private static final String CORP_ID = "wwxxxx";
    private static final String CORP_SECRET = "xxxx";
    private static final String TOKEN_URL = "https://qyapi.weixin.qq.com/cgi-bin/gettoken?corpid={corpid}&corpsecret={secret}";

    @Autowired
    private RestTemplate restTemplate;

    /**
     * 获取access_token,实际项目中用Redis缓存
     */
    public String getAccessToken() {
        JSONObject resp = restTemplate.getForObject(TOKEN_URL, JSONObject.class, CORP_ID, CORP_SECRET);
        if (resp == null || resp.getIntValue("errcode") != 0) {
            throw new RuntimeException("获取token失败:" + resp);
        }
        return resp.getString("access_token");
    }
}

4.2 SCRM调用接口,给外部联系人发送文本消息

接口:externalcontact/message/send 发送客户消息,注意:该接口有调用频率限制,不可高频批量轰炸客户。

java 复制代码
/**
 * 向企业微信外部联系人发送文本消息
 */
public void sendExternalTextMsg(String accessToken, String userId, String externalUserId, String content){
    String url = "https://qyapi.weixin.qq.com/cgi-bin/externalcontact/message/send?access_token="+accessToken;
    JSONObject body = new JSONObject();
    body.put("agentid",1000001); //自建应用agentid
    body.put("userid",userId); //跟进员工userid
    body.put("external_userid",new String[]{externalUserId});
    JSONObject text = new JSONObject();
    text.put("content",content);
    body.put("text",text);
    body.put("msgtype","text");

    RestTemplate restTemplate = new RestTemplate();
    JSONObject res = restTemplate.postForObject(url, body, JSONObject.class);
    if(res.getIntValue("errcode")!=0){
        // 这里需要做失败日志、重试队列,不要直接抛异常
        log.error("发送消息失败,err:{},msg:{}",res.get("errcode"),res.get("errmsg"));
    }
}

4.3 Webhook回调接口:接收企微推送的外部联系人事件

企业微信会POST加密消息到我们配置的回调地址,需要做签名校验、AES解密,解析事件(添加客户、删除客户等),写入SCRM数据库。

java 复制代码
@RestController
@RequestMapping("/wecom/callback")
public class WeComCallbackController {

    // 企业微信回调配置的token、aes密钥
    private final String TOKEN = "xxx";
    private final String AES_KEY = "xxx";

    /**
     * 回调GET:配置时的URL验证
     */
    @GetMapping
    public String callbackGet(String msg_signature,String timestamp,String nonce,String echostr){
        // 执行签名校验,解密echostr原样返回给企微后台完成配置
        return echostr;
    }

    /**
     * 回调POST:接收事件消息
     */
    @PostMapping
    public String callbackPost(@RequestBody String postBody,
                              @RequestParam String msg_signature,
                              @RequestParam String timestamp,
                              @RequestParam String nonce){
        //1. 校验签名;2.AES解密xml;3.解析事件类型
        /*
         示例事件:add_external_contact 添加外部联系人事件
         {
            "Event":"change_external_contact",
            "ChangeType":"add_external_contact",
            "UserID":"zhangsan",
            "ExternalUserID":"wmxxxxxx"
         }
        */
        // 解析得到external_userid,在SCRM做客户档案新增/更新
        // scrmCustomerService.syncWeComCustomer(externalUserID, userId);
        return "success";
    }
}

4.4 数据库表设计(简化版)

sql 复制代码
-- SCRM-企微外部联系人映射表
CREATE TABLE `scrm_wecom_external_customer` (
  `id` bigint NOT NULL AUTO_INCREMENT COMMENT '主键',
  `scrm_customer_id` bigint NOT NULL COMMENT 'SCRM系统客户ID',
  `userid` varchar(64) NOT NULL COMMENT '企微员工userid',
  `external_userid` varchar(128) NOT NULL COMMENT '企微外部联系人ID',
  `name` varchar(128) DEFAULT NULL COMMENT '客户昵称',
  `add_time` datetime DEFAULT NULL COMMENT '添加好友时间',
  `is_delete` tinyint DEFAULT '0' COMMENT '是否已被删除 0正常1删除',
  PRIMARY KEY (`id`),
  UNIQUE KEY `uk_external_uid` (`external_userid`,`userid`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='SCRM与企微外部联系人映射表';

-- 聊天记录表,存储企微收发消息
CREATE TABLE `scrm_wecom_chat_record` (
  `id` bigint AUTO_INCREMENT PRIMARY KEY,
  `external_userid` varchar(128) NOT NULL,
  `userid` varchar(64) NOT NULL,
  `msg_type` varchar(32) COMMENT 'text/image/file',
  `content` text COMMENT '消息内容',
  `direction` tinyint COMMENT '1员工发给客户,2客户发给员工',
  `msg_time` datetime COMMENT '消息时间',
  INDEX idx_external_user (`external_userid`)
)ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

五、业务完整流程

5.1 新增客户流程

  1. 员工企业微信添加客户;

  2. 企微服务器推送 add_external_contact 事件回调SCRM;

  3. SCRM回调服务解密事件,拿到 external_userid、员工 userid;

  4. SCRM查询企微API获取客户详细资料;写入映射表,创建SCRM客户档案。

5.2 SCRM后台主动给客户发消息流程

  1. 运营人员在SCRM后台,选择客户,输入发送内容;

  2. SCRM读取映射表,拿到该客户对应的 external_userid 和跟进员工 userid;

  3. 调用 externalcontact/message/send 接口向企微网关发送消息;

  4. 企微网关把消息下发到外部联系人微信;

  5. SCRM本地记录本次发送的聊天记录。

六、开发踩坑 & 避坑清单

序号 坑点 解决方案
1 access_token缓存问题 不要每次调用接口都请求gettoken,会触发调用超限,必须Redis缓存,有效期设置小于7200秒;
2 回调解密坑 企业微信回调消息是AES加密XML格式,不是JSON,必须用官方提供的加解密工具;
3 发送消息频率限制 官方接口有QPS限制,SCRM做消息队列+令牌桶限流,禁止循环批量无间隔发送;
4 external_userid归属 同一个外部微信用户,不同员工跟进,会生成不同external_userid,必须绑定对应userid,不可只根据external_userid做全局唯一;
5 回调超时 企微回调请求5秒超时,耗时业务不要在回调接口内同步处理;消息丢到MQ异步消费;接口直接返回success;
6 合规红线 禁止使用非官方私有协议(iPad协议、hook逆向);不要做无许可批量群发,会导致企业微信账号被限制接口能力、封禁账号。

七、扩展方向

  • 接入会话存档:开通会话存档,全量同步员工和客户聊天记录到SCRM系统,用于质检;

  • SOP消息:结合消息队列,实现定时跟进提醒、周期推送;

  • 客户标签同步:企微客户标签事件回调,双向同步SCRM标签体系;

  • 客户分配:离职继承API,SCRM触发客户重新分配。

八、总结

SCRM打通企业微信外部联系人消息发送,核心是用好企业微信官方【客户联系】整套开放API。整体链路分为两部分:SCRM主动调用API实现消息下发;Webhook回调接收企微推送客户事件,完成数据同步。开发时重点处理鉴权缓存、回调解密、限流队列、ID映射,同时必须遵守企业微信的接口规范和业务合规,不要使用逆向私有协议,避免账号风险。

相关推荐
七夜zippoe3 天前
Agent 接入企业微信/钉钉:渠道对接实
ai·钉钉·企业微信·agent·渠道对接
杨婷1233 天前
企业微信 SCRM 客户流失提醒:实时告警 + 自动流失标签,保护私域客户资产
企业微信
小鹿研究点东西3 天前
SCRM系统哪家好?先分清5类产品,再按业务场景选
企业微信·私域运营·scrm工具·客户运营
天空属于哈夫克34 天前
企业微信API开发:如何实现外部群消息关键词统计?
数据库·企业微信
金融Tech趋势派4 天前
企业微信客户营销怎么做?WorkBuddy+微盛·企微管家Skill连接器,一句话让AI把客户营销做起来
人工智能·企业微信
道一云黑板报5 天前
WorkBuddy 进入企业微信侧边栏:入口、执行与连接的分工
人工智能·ai·企业微信
随性而行3605 天前
企业微信API调用案例:如何通过接口实现多账号统一管理与业务接入?
运维·微信·机器人·自动化·企业微信
随性而行3605 天前
企业微信API接口开发实战:如何实现消息回调接收与业务事件处理?
java·前端·python·微信·机器人·企业微信
Eddyp5 天前
涡街 电磁流量计、压力变送器,手操器组态实操要点
微信·微信公众平台·facebook·新浪微博·微信开放平台