12 KiB
对外获客线索上报接口文档(V1)
一、接口概述
- 接口名称:对外获客线索上报接口
- 接口用途:供第三方系统向【存客宝】上报客户线索(手机号 / 微信号等),用于后续的跟进、标签管理和画像分析。
- 接口协议:HTTP
- 请求方式:
POST - 请求地址:
https://ckbapi.quwanzhi.com/v1/api/scenarios
具体 URL 以实际环境配置为准。
- 数据格式:
- 推荐:
application/json - 兼容:
application/x-www-form-urlencoded
- 推荐:
- 字符编码:
UTF-8
二、鉴权与签名
2.1 必填鉴权字段
| 字段名 | 类型 | 必填 | 说明 |
|---|---|---|---|
apiKey |
string | 是 | 分配给第三方的接口密钥(每个任务唯一) |
sign |
string | 是 | 签名值 |
timestamp |
int | 是 | 秒级时间戳(与服务器时间差不超过 5 分钟) |
2.2 时间戳校验
服务器会校验 timestamp 是否在当前时间前后 5 分钟 内:
- 通过条件:
|server_time - timestamp| <= 300 - 超出范围则返回:
请求已过期
2.3 签名生成规则
接口采用自定义签名机制。签名字段为 sign,生成步骤如下:
假设本次请求的所有参数为 params,其中包括业务参数 + apiKey + timestamp + sign + 可能存在的 portrait 对象。
第一步:移除特定字段
从 params 中移除以下字段:
sign—— 自身不参与签名apiKey—— 不参与参数拼接,仅在最后一步参与二次 MD5portrait—— 整个画像对象不参与签名(即使内部还有子字段)
说明:
portrait通常是一个 JSON 对象,字段较多,为避免签名实现复杂且双方难以对齐,统一不参与签名。
第二步:移除空值字段
从剩余参数中,移除值为:
null- 空字符串
''
的字段,这些字段不参与签名。
第三步:按参数名升序排序
对剩余参数按参数名(键名)升序排序,排序规则为标准的 ASCII 升序:
例如: name, phone, source, timestamp
第四步:拼接参数值
将排序后的参数 只取“值”,按顺序直接拼接为一个字符串,中间不加任何分隔符:
-
示例:
排序后参数为:name = 张三 phone = 13800000000 source = 微信广告 timestamp = 1710000000则拼接:
stringToSign = "张三13800000000微信广告1710000000"
第五步:第一次 MD5
对上一步拼接得到的字符串做一次 MD5:
[ \text{firstMd5} = \text{MD5}(\text{stringToSign}) ]
第六步:拼接 apiKey 再次 MD5
将第一步的结果与 apiKey 直接拼接,再做一次 MD5,得到最终签名值:
[ \text{sign} = \text{MD5}(\text{firstMd5} + \text{apiKey}) ]
第七步:放入请求
将第六步得到的 sign 填入请求参数中的 sign 字段即可。
建议:
- 使用小写 MD5 字符串(双方约定统一即可)。
- 请确保参与签名的参数与最终请求发送的参数一致(包括是否传空值)。
2.4 签名示例(PHP 伪代码)
$params = [
'apiKey' => 'YOUR_API_KEY',
'timestamp' => '1710000000',
'phone' => '13800000000',
'name' => '张三',
'source' => '微信广告',
'remark' => '通过H5落地页留资',
// 'portrait' => [...], // 如有画像,这里会存在,但不参与签名
// 'sign' => '待生成',
];
// 1. 去掉 sign、apiKey、portrait
unset($params['sign'], $params['apiKey'], $params['portrait']);
// 2. 去掉空值
$params = array_filter($params, function($value) {
return !is_null($value) && $value !== '';
});
// 3. 按键名升序排序
ksort($params);
// 4. 拼接参数值
$stringToSign = implode('', array_values($params));
// 5. 第一次 MD5
$firstMd5 = md5($stringToSign);
// 6. 第二次 MD5(拼接 apiKey)
$apiKey = 'YOUR_API_KEY';
$sign = md5($firstMd5 . $apiKey);
// 将 $sign 作为字段发送
$params['sign'] = $sign;
三、请求参数说明
3.1 主标识字段(至少传一个)
| 字段名 | 类型 | 必填 | 说明 |
|---|---|---|---|
wechatId |
string | 否 | 微信号,存在时优先作为主标识 |
phone |
string | 否 | 手机号,当 wechatId 为空时用作主标识 |
3.2 基础信息字段
| 字段名 | 类型 | 必填 | 说明 |
|---|---|---|---|
name |
string | 否 | 客户姓名 |
source |
string | 否 | 线索来源描述,如“百度推广”、“抖音直播间” |
remark |
string | 否 | 备注信息 |
tags |
string | 否 | 逗号分隔的“微信标签”,如:"高意向,电商,女装" |
siteTags |
string | 否 | 逗号分隔的“站内标签”,用于站内进一步细分 |
3.3 用户画像字段 portrait(可选)
portrait 为一个对象(JSON),用于记录用户的行为画像数据。
3.3.1 基本示例
"portrait": {
"type": 1,
"source": 1,
"sourceData": {
"age": 28,
"gender": "female",
"city": "上海",
"productId": "P12345",
"pageUrl": "https://example.com/product/123"
},
"remark": "画像-基础属性",
"uniqueId": "user_13800000000_20250301_001"
}
3.3.2 字段详细说明
| 字段名 | 类型 | 必填 | 说明 |
|---|---|---|---|
portrait.type |
int | 否 | 画像类型,枚举值: 0-浏览 1-点击 2-下单/购买 3-注册 4-互动 默认值:0 |
portrait.source |
int | 否 | 画像来源,枚举值: 0-本站 1-老油条 2-老坑爹 默认值:0 |
portrait.sourceData |
object | 否 | 画像明细数据(键值对,会存储为 JSON 格式) 可包含任意业务相关的键值对,如:年龄、性别、城市、商品ID、页面URL等 |
portrait.remark |
string | 否 | 画像备注信息,最大长度100字符 |
portrait.uniqueId |
string | 否 | 画像去重用唯一 ID 用于防止重复记录,相同 uniqueId 的画像数据在半小时内会被合并统计(count字段累加)建议格式: {来源标识}_{用户标识}_{时间戳}_{序号} |
3.3.3 画像类型(type)说明
| 值 | 类型 | 说明 | 适用场景 |
|---|---|---|---|
| 0 | 浏览 | 用户浏览了页面或内容 | 页面访问、商品浏览、文章阅读等 |
| 1 | 点击 | 用户点击了某个元素 | 按钮点击、链接点击、广告点击等 |
| 2 | 下单/购买 | 用户完成了购买行为 | 订单提交、支付完成等 |
| 3 | 注册 | 用户完成了注册 | 账号注册、会员注册等 |
| 4 | 互动 | 用户进行了互动行为 | 点赞、评论、分享、咨询等 |
3.3.4 画像来源(source)说明
| 值 | 来源 | 说明 |
|---|---|---|
| 0 | 本站 | 来自本站的数据 |
| 1 | 老油条 | 来自"老油条"系统的数据 |
| 2 | 老坑爹 | 来自"老坑爹"系统的数据 |
3.3.5 sourceData 数据格式说明
sourceData 是一个 JSON 对象,可以包含任意业务相关的键值对。常见字段示例:
{
"age": 28,
"gender": "female",
"city": "上海",
"province": "上海市",
"productId": "P12345",
"productName": "商品名称",
"category": "女装",
"price": 299.00,
"pageUrl": "https://example.com/product/123",
"referrer": "https://www.baidu.com",
"device": "mobile",
"browser": "WeChat"
}
注意:
sourceData中的数据类型可以是字符串、数字、布尔值等- 嵌套对象会被序列化为 JSON 字符串存储
- 建议根据实际业务需求定义字段结构
3.3.6 uniqueId 去重机制说明
- 作用:防止重复记录相同的画像数据
- 规则:相同
uniqueId的画像数据在 半小时内 会被合并统计,count字段会自动累加 - 建议格式:
{来源标识}_{用户标识}_{时间戳}_{序号}- 示例:
site_13800000000_1710000000_001 - 示例:
wechat_wxid_abc123_1710000000_001
- 示例:
- 注意事项:
- 如果不传
uniqueId,系统会为每条画像数据创建新记录 - 如果需要在半小时内多次统计同一行为,应使用相同的
uniqueId - 如果需要在半小时后重新统计,应使用不同的
uniqueId(建议修改时间戳部分)
- 如果不传
重要提示:
portrait整体不参与签名计算,但会参与业务处理。系统会根据uniqueId自动处理去重和统计。
四、请求示例
4.1 JSON 请求示例(无画像)
{
"apiKey": "YOUR_API_KEY",
"timestamp": 1710000000,
"phone": "13800000000",
"name": "张三",
"source": "微信广告",
"remark": "通过H5落地页留资",
"tags": "高意向,电商",
"siteTags": "新客,女装",
"sign": "根据签名规则生成的MD5字符串"
}
4.2 JSON 请求示例(带微信号与画像)
{
"apiKey": "YOUR_API_KEY",
"timestamp": 1710000000,
"wechatId": "wxid_abcdefg123",
"phone": "13800000001",
"name": "李四",
"source": "小程序落地页",
"remark": "点击【立即咨询】按钮",
"tags": "中意向,直播",
"siteTags": "复购,高客单",
"portrait": {
"type": 1,
"source": 0,
"sourceData": {
"age": 28,
"gender": "female",
"city": "上海",
"pageUrl": "https://example.com/product/123",
"productId": "P12345"
},
"remark": "画像-点击行为",
"uniqueId": "site_13800000001_1710000000_001"
},
"sign": "根据签名规则生成的MD5字符串"
}
4.3 JSON 请求示例(多种画像类型)
4.3.1 浏览行为画像
{
"apiKey": "YOUR_API_KEY",
"timestamp": 1710000000,
"phone": "13800000002",
"name": "王五",
"source": "百度推广",
"portrait": {
"type": 0,
"source": 0,
"sourceData": {
"pageUrl": "https://example.com/product/456",
"productName": "商品名称",
"category": "女装",
"stayTime": 120,
"device": "mobile"
},
"remark": "商品浏览",
"uniqueId": "site_13800000002_1710000000_001"
},
"sign": "根据签名规则生成的MD5字符串"
}
---
## 五、响应说明
### 5.1 成功响应
**1)新增线索成功**
```json
{
"code": 200,
"message": "新增成功",
"data": "13800000000"
}
2)线索已存在
{
"code": 200,
"message": "已存在",
"data": "13800000000"
}
data字段返回本次线索的主标识wechatId或phone。
5.2 常见错误响应
{ "code": 400, "message": "apiKey不能为空", "data": null }
{ "code": 400, "message": "sign不能为空", "data": null }
{ "code": 400, "message": "timestamp不能为空", "data": null }
{ "code": 400, "message": "请求已过期", "data": null }
{ "code": 401, "message": "无效的apiKey", "data": null }
{ "code": 401, "message": "签名验证失败", "data": null }
{ "code": 500, "message": "系统错误: 具体错误信息", "data": null }
六、常见问题(FAQ)
Q1: 如果同一个用户多次上报相同的行为,会如何处理?
A: 如果使用相同的 uniqueId,系统会在半小时内合并统计,count 字段会累加。如果使用不同的 uniqueId,会创建多条记录。
Q2: portrait 字段是否必须传递?
A: 不是必须的。portrait 字段是可选的,只有在需要记录用户画像数据时才传递。
Q3: sourceData 中可以存储哪些类型的数据?
A: sourceData 是一个 JSON 对象,可以存储任意键值对。支持字符串、数字、布尔值等基本类型,嵌套对象会被序列化为 JSON 字符串。
Q4: uniqueId 的作用是什么?
A: uniqueId 用于防止重复记录。相同 uniqueId 的画像数据在半小时内会被合并统计,避免重复数据。
Q5: 画像数据如何与用户关联?
A: 系统会根据请求中的 wechatId 或 phone 自动匹配 traffic_pool 表中的用户,并将画像数据关联到对应的 trafficPoolId。