**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系统需要管理企业微信的外部客户,常见需求:
-
SCRM业务后台触发,给外部联系人发送文本、图片、图文消息;
-
接收企业微信回调事件:新增客户、删除客户、客户消息回调;
-
将企微
external_userid和SCRM本地客户档案做关联映射; -
会话数据双向同步,业务系统记录客户沟通记录、执行SOP自动推送消息。
二、整体系统架构
架构流程图

核心技术栈说明:
API接口调用参考:https://wechatapi.apifox.cn/
开发环境:JDK1.8,Mysql5.0,Redis7
开发语言:JAVA,PHP
前端框架:VUE
架构模块说明
-
鉴权模块 :定时获取企业微信
access_token,缓存,过期自动刷新; -
消息发送模块:SCRM业务请求 → 参数封装 → 调用企微客户联系发送接口,增加限流、失败重试;
-
Webhook回调服务:企业微信把新增客户、客户消息等事件POST推送到此服务;做签名校验、消息解密;
-
数据存储层 :维护映射关系
SCRM客户ID ↔ 企微external_userid ↔ 企微userid(员工ID),存储聊天记录、客户标签、跟进记录。
三、前置开发准备
-
企业微信完成企业认证;
-
创建自建应用,开启权限:
客户联系权限; -
配置回调URL、回调Token、EncodingAESKey(用于消息加密解密);
-
记录
corpid(企业ID)、自建应用secret; -
理解核心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 新增客户流程
-
员工企业微信添加客户;
-
企微服务器推送
add_external_contact事件回调SCRM; -
SCRM回调服务解密事件,拿到
external_userid、员工userid; -
SCRM查询企微API获取客户详细资料;写入映射表,创建SCRM客户档案。
5.2 SCRM后台主动给客户发消息流程
-
运营人员在SCRM后台,选择客户,输入发送内容;
-
SCRM读取映射表,拿到该客户对应的
external_userid和跟进员工userid; -
调用
externalcontact/message/send接口向企微网关发送消息; -
企微网关把消息下发到外部联系人微信;
-
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映射,同时必须遵守企业微信的接口规范和业务合规,不要使用逆向私有协议,避免账号风险。