# 拼车助手
# 1. 版本历史
| 版本 | 日期 | 修订人 | 修改内容 | 审核人 |
|---|---|---|---|---|
| V0.1 | 2024.08.25 | 初稿 | ||
| V0.2 | 2024.12.09 | 服务商行程导入 | ||
| V0.3 | 2025.01.02 | 拼车助手行程导出 | ||
| V0.4 | 2025.03.19 | 申请增加起终点信息 |
# 2. 基础说明
# 2.1 接口协议
除非特殊指定,默认请求方式均为 HTTPS/POST 方式。
# 2.2 返回数据格式
除非特殊指定,默认返回数据格式均为 JSON 格式。
# 2.3 字符编码
除非特殊指定,默认字符编码均为 UTF-8 编码格式。
# 2.4 请求格式
接口内如果没有特殊说明的,请求格式一律统一为 application/json 。
# 2.5 重试机制
调⽤出行服务接口时,返回码 Code 不成功,要有重试机制(具体见错误码表)。
# 2.6 通用参数
| 字段名 | 字段类型 | 最大长度 | 必填 | 说明 |
|---|---|---|---|---|
| accessKey | String | 32 | 是 | 腾讯出行服务分配给服务商调用的 accessKey |
| seqId | String | 36 | 是 | 请求流水号,调用方自动生成一个随机 ID,建议使用 uuid |
| timestamp | Long | 20 | 是 | 请求发送时的时间戳(unix 时间戳) 毫秒 |
| nonce | String | 10 | 是 | 10 位随机字符串 |
| sign | String | 32 | 是 | 验证签名参数 |
# 2.7 通用返回值
| 字段名 | 字段类型 | 最大长度 | 必填 | 说明 |
|---|---|---|---|---|
| code | Integer | 11 | 是 | 服务响应状态,参见错误码表 |
| message | String | 64 | 是 | 服务响应状态说明,参见错误码表 |
| data | Object | - | 否 | 具体的接口对应不同的对象详见具体的接口 |
# 2.8 鉴权说明
步骤 1 从请求串中获得 accessKey、seqId、timestamp, nonce 通用字段以及其他的业务段和鉴权结果字段 sign。
步骤 2 根据签名算法,对参与签名的内容进行签名; 按照除 sign 外参数名称排序(字典升序排列)成”key1=value1&key2=value2&....”的原始字符串 src1;参数值为 null 不参与签名。 将原始字符串+分配给调用方的 apiSercret 形成字符串 src2; 将 src2 进行 md5 后转成大写形成签名内容 dest
步骤 3 将步骤 2 中得到的签名内容 dest 与请求中的 sign 字段内容做比较,如果相同则验证成功,否则判定请求非法。
举例: 假设/order/status 接口文档中业务字段为[slon, slat],分配的 apiSercret=DZaslH9B9ycqRrE77laCPB2Om, 请求参数如下: accessKey=PSUBZLHOKUO6HV52A5CAUSSE5KSB6Y, seqId=b8b4f0b8-01fb-4c06-80b9-3ab895a8c616, timestamp=1554695343, slat=39.998299, slon=116.285561 则需要签名的内容: accessKey=PSUBZLHOKUO6HV52A5CAUSSE5KSB6Y&seqId=b8b4f0b8-01fb-4c06-80b9-3ab895a8c616&slat=39.998299&slon=116.285561×tamp=1554695343&apiSercret=DZaslH9B9ycqRrE77laCPB2Om
步骤 4 计算的 MD5 值为 8a983278e5366eb93feb0d4143e1c522,大写值为 8A983278E5366EB93FEB0D4143E1C522。
步骤 5 将步骤 4 中得到的 MD5 值,与请求中 sign 字段的值比较。两者相同请求合法。
# 2.9 签名示例代码
以下代码仅为示例,以实际联调过程中双方沟通结论为准。
服务商接收到腾讯侧请求,无需转换对象,直接将这个请求JSON串传入requestSign(String requestStr, String secret)方法计算得到签名sign。 注:为保证结果一致,建议使用相同的JSON工具。
import org.apache.commons.lang3.StringUtils;
import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
import java.util.TreeMap;
/**
* 验签
*/
public class SignUtil {
private static final String MD5 = "MD5";
/**
* 请求签名算法入口
* @param requestStr
* @param secret
* @return
*/
public static String requestSign(String requestStr, String secret) {
Map<String, Object> paramsMap = JsonTool.toObj(requestStr, TreeMap.class);
Map<String, String> params = new HashMap<>();
String[] keys = paramsMap.keySet().toArray(new String[0]);
for (String key : keys) {
if (org.apache.commons.lang3.StringUtils.isNotBlank(key)) {
String value = paramsMap.get(key).toString();
if (null != value) {
params.put(key.trim(), value);
}
}
}
params.remove("sign");
return sign(params, secret);
}
/**
* 签名算法核心
* @param params
* @param secret
* @return
*/
public static String sign(Map<String, String> params, String secret) {
// 第一步:检查参数是否已经排序
String[] keys = params.keySet().toArray(new String[0]);
Arrays.sort(keys);
// 第二步:把所有参数名和参数值串在一起
StringBuilder sb = new StringBuilder();
for (String key : keys) {
if (StringUtils.isNotBlank(key)) {
String value = params.get(key);
if (null != value) {
sb.append(key.concat("="));
sb.append(value.concat("&"));
}
}
}
sb.append("apiSercret=" + secret);
return toHex(getMd5(sb.toString()));
}
private static String toHex(byte[] byteArray) {
if (null == byteArray) {
return null;
}
StringBuilder md5Str = new StringBuilder();
for (byte b : byteArray) {
md5Str.append(String.format("%02x", b));
}
return md5Str.toString().toUpperCase();
}
private static byte[] getMd5(String str) {
MessageDigest messageDigest;
try {
messageDigest = MessageDigest.getInstance(MD5);
messageDigest.reset();
messageDigest.update(str.getBytes(StandardCharsets.UTF_8));
} catch (NoSuchAlgorithmException e) {
return new byte[0];
}
return messageDigest.digest();
}
}
JSON工具类:
import com.fasterxml.jackson.annotation.JsonInclude.Include;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.MapperFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
/**
* json tools
*/
public class JsonTool {
private static final ObjectMapper objectMapper;
static {
objectMapper = new ObjectMapper();
objectMapper.setDefaultPropertyInclusion(Include.NON_NULL);
objectMapper.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);
objectMapper.enable(MapperFeature.SORT_PROPERTIES_ALPHABETICALLY);
}
public static String toJson(Object obj) {
try {
return objectMapper.writeValueAsString(obj);
} catch (Exception ex) {
throw new RuntimeException("序列化异常");
}
}
public static <T> T toObj(String json, Class<T> valueType) {
try {
return objectMapper.readValue(json, valueType);
} catch (Exception ex) {
throw new RuntimeException("反序列化异常");
}
}
}
# 2.10 注意事项
1、需要签名的字段与请求串中字段先后顺序没有关系,只与进行签名的内容有关,必须按照文档中的顺序拼接。
2、apiSercret 内容为双方保密内容,不在请求中传输,严禁公开。
3、通用字段 accessKey,seqId,timestamp,nonce 参与所有接口的签名。
4、字段值是 JSON 类型的,把字段值 json 串参与签名, 不用拆分里面字段。
# 2.11 数据加密
在双方进行HTTP接口交互时,为保证数据安全,须对请求参数和响应数据中的敏感数据(如手机号)加密传输,接收数据后解密使用。双方联调时提供具体加密策略。
# 2.12 接口分类
- 主调接口(调用方:腾讯出行,被调方:各服务商),主调接口由服务商实现。
- 被调接口(调用方:各服务商,被调方:腾讯出行),被调接口由腾讯实现。
# 3. 业务主调接口列表
- 请求地址
由服务商提供(正式环境、测试环境)
- 请求方式 POST
# 主调接口通用参数
| 字段名 | 字段类型 | 最大长度 | 必填 | 说明 |
|---|---|---|---|---|
| seqId | String | 36 | 是 | 请求流水号 |
| timestamp | Long | 36 | 是 | 请求时间戳 |
| spId | Integer | 36 | 否 | 服务商ID |
# LocationInfo
| 参数名称 | 类型 | 说明 | 是否必填 |
|---|---|---|---|
| lng | Double | 经度 | 是 |
| lat | Double | 纬度 | 是 |
| cityCode | String | 城市code | 是 |
| cityName | String | 城市名称 | 是 |
| adCode | String | 城区code | 是 |
| phoneAreaCode | String | 区域code | 否 |
| name | String | 地址名称 | 是 |
| address | String | 详细地址 | 是 |
| districtName | String | 区/县(级市)名 | 是 |
| townName | String | 乡镇/街道(四级行政区划) | 否,建议传递 |
# 3.1 (二期)乘客行程创建同步服务商
# 请求地址
- /passenger/trip/create
# 请求参数
| 参数名称 | 类型 | 说明 | 必须 |
|---|---|---|---|
| tripId | String | 腾讯侧乘客行程ID | 是 |
| startAddr | LocationInfo | 行程起点 | 是 |
| endAddr | LocationInfo | 行程终点 | 是 |
| earliestDepartureTime | Long | 行程最早出发时间 | 是 |
| latestDepartureTime | Long | 行程最晚出发时间 | 是 |
| seatNum | Integer | 乘客需要座位数 | 是 |
| remark | String | 备注信息 | 否 |
| userCode | String | 腾讯侧userCode | 是 |
| supportPhone | Boolean | 发单人是否支持电话联系 | 否 |
| nickName | String | 乘客昵称(用户授权手机号时存在) | 否 |
# 请求示例
{
"seqId": "abc123",
"timestamp": 1234567891019,
"tripId": "trip123456",
"startAddr": {
"lng": 116.397128,
"lat": 39.916527,
"cityCode": "110000",
"adCode": "110101",
"phoneAreaCode": "010",
"name": "天安门",
"address": "天安门广场",
"cityName": "北京",
"districtName": "东城区",
"townName": "天安门"
},
"endAddr": {
"lng": 116.405285,
"lat": 39.904989,
"cityCode": "110000",
"adCode": "110101",
"phoneAreaCode": "010",
"name": "故宫",
"address": "故宫博物院",
"cityName": "北京",
"districtName": "东城区",
"townName": "故宫"
},
"earliestDepartureTime": 1633036800000,
"latestDepartureTime": 1633040400000,
"seatNum": 2,
"remark": "请提前到达",
"userCode": "user123456",
"supportPhone": true,
"nickName": "张三"
}
# 响应数据
| 参数名称 | 类型 | 说明 | 必须 |
|---|---|---|---|
| code | Integer | 响应状态码 | 是 |
| message | String | 响应信息 | 是 |
| data | Object | 响应数据 | 是 |
| data.tripId | String | 行程ID | 是 |
# 响应示例
{
"code": 0,
"message": "成功",
"data": {
"tripId": "spTrip123456"
}
}
# 3.2 (二期)乘客行程修改同步服务商
# 请求地址
- /passenger/trip/modify
# 请求参数
| 参数名称 | 类型 | 说明 | 必须 |
|---|---|---|---|
| tripId | String | 腾讯侧乘客行程ID | 是 |
| startAddr | LocationInfo | 行程起点 | 是 |
| endAddr | LocationInfo | 行程终点 | 是 |
| earliestDepartureTime | Long | 行程最早出发时间 | 是 |
| latestDepartureTime | Long | 行程最晚出发时间 | 是 |
| seatNum | Integer | 乘客需要座位数 | 是 |
| remark | String | 备注信息 | 否 |
| userCode | String | 腾讯侧userCode | 是 |
| supportPhone | Boolean | 发单人是否支持电话联系 | 否 |
| nickName | String | 乘客昵称(用户授权手机号时存在) | 否 |
# 请求示例
{
"seqId": "abc123",
"timestamp": 1234567891019,
"tripId": "trip123456",
"startAddr": {
"lng": 116.397128,
"lat": 39.916527,
"cityCode": "110000",
"adCode": "110101",
"phoneAreaCode": "010",
"name": "天安门",
"address": "天安门广场",
"cityName": "北京",
"districtName": "东城区",
"townName": "天安门"
},
"endAddr": {
"lng": 116.405285,
"lat": 39.904989,
"cityCode": "110000",
"adCode": "110101",
"phoneAreaCode": "010",
"name": "故宫",
"address": "故宫博物院",
"cityName": "北京",
"districtName": "东城区",
"townName": "故宫"
},
"earliestDepartureTime": 1633036800000,
"latestDepartureTime": 1633040400000,
"seatNum": 2,
"remark": "请提前到达",
"userCode": "user123456",
"supportPhone": true
}
# 响应数据
| 参数名称 | 类型 | 说明 | 必须 |
|---|---|---|---|
| code | Integer | 响应状态码 | 是 |
| message | String | 响应信息 | 是 |
| data | Object | 响应数据 | 是 |
| data.tripId | String | 行程ID | 是 |
# 响应示例
{
"code": 0,
"message": "成功",
"data": {
"tripId": "spTrip123456"
}
}
# 3.3 (二期)乘客行程状态变更通知
# 请求地址
- /passenger/trip/status
# 请求参数
| 参数名称 | 类型 | 说明 | 必须 |
|---|---|---|---|
| tripId | String | 行程ID | 是 |
| tripStatus | Integer | 行程状态 | 是 |
# 请求示例
{
"seqId": "def456",
"timestamp": 1234567891020,
"tripId": "trip123456",
"tripStatus": 1
}
# 响应数据
| 参数名称 | 类型 | 说明 | 必须 |
|---|---|---|---|
| userCode | String | 腾讯侧userCode | 是 |
| code | Integer | 响应状态码 | 是 |
| message | String | 响应信息 | 是 |
# 响应示例
{
"code": 0,
"message": "成功"
}
# 3.4 (二期)乘客接受司机邀请
# 请求地址
- /passenger/invite/accept
# 请求参数
| 参数名称 | 类型 | 说明 | 必须 |
|---|---|---|---|
| userCode | String | 腾讯侧userCode | 是 |
| tripId | String | 乘客行程ID | 是 |
| applyId | String | 腾讯侧申请单ID | 是 |
# 请求示例
{
"seqId": "mno345",
"timestamp": 1234567891050,
"driverId": "driver123456",
"tripId": "passengerTrip123456"
}
# 响应数据
| 参数名称 | 类型 | 说明 | 必须 |
|---|---|---|---|
| code | Integer | 响应状态码 | 是 |
| message | String | 响应信息 | 是 |
# 响应示例
{
"code": 0,
"message": "成功"
}
# 3.5 乘客发起占座
# 请求地址
- /passenger/invite/driver
# 请求参数
| 参数名称 | 类型 | 说明 | 必须 |
|---|---|---|---|
| userCode | String | 腾讯侧userCode | 是 |
| tripId | String | 车主行程ID | 是 |
| applyId | String | 用户申请单ID | 是 |
| nickName | String | 申请人昵称 | 是 |
| seatNum | Integer | 乘客申请座位数 | 是 |
| applyStartAddr | LocationInfo | 申请起点信息 | 是 |
| applyEndAddr | LocationInfo | 申请终点信息 | 是 |
# 请求示例
{
"seqId": "ghi789",
"timestamp": 1234567891030,
"tripId": "trip123456",
"applyId": "apply123456",
"nickName": "小明",
"seatNum": 1,
"applyStartAddr": {
"lng": 116.397128,
"lat": 39.916527,
"cityCode": "110000",
"adCode": "110101",
"phoneAreaCode": "010",
"name": "天安门",
"address": "天安门广场",
"cityName": "北京",
"districtName": "东城区",
"townName": "天安门"
},
"applyEndAddr": {
"lng": 116.405285,
"lat": 39.904989,
"cityCode": "110000",
"adCode": "110101",
"phoneAreaCode": "010",
"name": "故宫",
"address": "故宫博物院",
"cityName": "北京",
"districtName": "东城区",
"townName": "故宫"
}
}
# 响应数据
| 参数名称 | 类型 | 说明 | 必须 |
|---|---|---|---|
| code | Integer | 响应状态码 | 是 |
| message | String | 响应信息 | 是 |
# 响应示例
{
"code": 0,
"message": "成功"
}
# 3.6 乘客取消占座(含接受后退出)
# 请求地址
- /passenger/invite/cancel
# 请求参数
| 参数名称 | 类型 | 说明 | 必须 |
|---|---|---|---|
| userCode | String | 腾讯侧userCode | 是 |
| tripId | String | 车主行程ID | 是 |
| applyId | String | 用户申请单ID | 是 |
# 请求示例
{
"seqId": "jkl012",
"timestamp": 1234567891040,
"tripId": "trip123456",
"applyId": "apply123456"
}
# 响应数据
| 参数名称 | 类型 | 说明 | 必须 |
|---|---|---|---|
| code | Integer | 响应状态码 | 是 |
| message | String | 响应信息 | 是 |
# 响应示例
{
"code": 0,
"message": "成功"
}
# 3.7 乘客发送消息请求
# 请求地址
- /passenger/im/message/send
# 请求参数
| 参数名称 | 类型 | 说明 | 必须 |
|---|---|---|---|
| userCode | String | 腾讯侧userCode | 是 |
| spDriverId | String | 服务商司机ID | 是 |
| tripId | String | 会话关联行程ID | 是 |
| messageType | Integer | 消息类型 文字0/图片1/定位2 | 是 |
| messageBody | MessageBody | 消息内容 | 是 |
| messageBody.text | String | 文本消息 | 是 |
| messageBody.url | String | 图片/语音URL | 否 |
| messageBody.duration | Integer | 语音时长 | 否 |
| spMessageId | String | 服务商消息ID | 否 |
# 请求示例
{
"seqId": "vwx234",
"timestamp": 1234567891080,
"spId": 600010,
"userCode": "usercode123456",
"spDriverId": "driver123456",
"tripId": "trip123456",
"messageType": 0,
"messageBody": {
"text": "你好",
"url": "图片URL/语音URL(duration记录语音时长)",
"duration": 0
},
"spMessageId": "spMessage123456",
"tipType": 0
}
# 响应数据
| 参数名称 | 类型 | 说明 | 必须 |
|---|---|---|---|
| code | Integer | 响应状态码 | 是 |
| message | String | 响应信息 | 是 |
| data | SendImMessageResData | 响应数据 | 是 |
| data.messageId | String | 腾讯侧消息ID | 是 |
# 响应示例
{
"code": 0,
"message": "成功",
"data": {
"messageId": "message123456"
}
}
# 3.8 乘客单会话已读
# 请求地址
- /passenger/im/message/read/session
# 请求参数
| 参数名称 | 类型 | 说明 | 必须 |
|---|---|---|---|
| tripId | String | 腾讯侧行程ID | 是 |
| driverId | String | 服务商车主ID | 是 |
| userCode | String | 腾讯侧参与会话的用户userCode | 是 |
| messageIdList | List | 消息ID列表 | 是 |
| spMessageIdList | List | 服务商消息ID列表 | 否 |
# 请求示例
{
"seqId": "yz1234",
"timestamp": 1234567891090,
"spId": 600010,
"tripId": "trip123456",
"driverId": "driver123456",
"userCode": "usercode123456",
"messageIdList": ["message123456"],
"spMessageIdList": ["spMessage123456"]
}
# 响应数据
| 参数名称 | 类型 | 说明 | 必须 |
|---|---|---|---|
| code | Integer | 响应状态码 | 是 |
| message | String | 响应信息 | 是 |
# 响应示例
{
"code": 0,
"message": "成功"
}
# 3.9 乘客全部已读
# 请求地址
- /passenger/im/message/read/all
# 请求参数
| 参数名称 | 类型 | 说明 | 必须 |
|---|---|---|---|
| userCode | String | 腾讯侧参与会话的用户userCode | 是 |
| tripIds | List | 需要清空的行程ID列表 | 是 |
| messageIdList | List | 消息ID列表 | 是 |
| spMessageIdList | List | 服务商消息ID列表 | 否 |
# 请求示例
{
"seqId": "yz1234",
"timestamp": 1234567891090,
"spId": 600010,
"userCode": "usercode123456",
"tripIds": ["trip123456"],
"messageIdList": ["message123456"],
"spMessageIdList": ["spMessage123456"]
}
# 响应数据
| 参数名称 | 类型 | 说明 | 必须 |
|---|---|---|---|
| code | Integer | 响应状态码 | 是 |
| message | String | 响应信息 | 是 |
# 响应示例
{
"code": 0,
"message": "成功"
}
# 3.10 乘客获取车主虚拟号请求
# 请求地址
- /driver/phone/get
# 请求参数
| 参数名称 | 类型 | 说明 | 必须 |
|---|---|---|---|
| srcPhone | String | 来电号码 | 是 |
| tripId | String | 一喂导入的车主行程ID | 是,tripId和applyId必有其一 |
| applyId | String | 车主发起上车邀请的申请单ID | 是,tripId和applyId必有其一 |
# 请求示例
{
"seqId": "abc987",
"timestamp": 1234567891100,
"tripId": "trip123456",
"userPhone": "12345678901"
}
# 响应数据
| 参数名称 | 类型 | 说明 | 必须 |
|---|---|---|---|
| code | Integer | 响应状态码 | 是 |
| message | String | 响应信息 | 是 |
| data | Object | 响应数据 | 是 |
| data.driverVirtualPhone | String | 虚拟号 | 是 |
| data.expireTime | Long | 过期时间 | 是 |
# 响应示例
{
"code": 0,
"message": "成功",
"data": {
"driverVirtualPhone": "12345678901",
"expireTime": 1633040400
}
}
# 4. 业务被调接口列表
- 请求地址
正式环境 https://sp.wecar.map.qq.com/carpoolassistant/
测试环境 https://test.tai.qq.com/carpoolassistant/
- 请求方式 POST
# 被调接口通用参数
| 字段名 | 字段类型 | 最大长度 | 必填 | 说明 |
|---|---|---|---|---|
| accessKey | String | 32 | 是 | 腾讯出行服务分配给服务商调用 accessKey |
| seqId | String | 36 | 是 | 请求流水号,调用方自动生成一个随机 ID,建议使用 uuid |
| timestamp | Long | 20 | 是 | 请求发送时的时间戳(unix 时间戳) 毫秒 |
| nonce | String | 10 | 是 | 10 位随机字符串 |
| sign | String | 32 | 是 | 验证签名参数 |
| userCode | String | 32 | 否 | 腾讯用户Code,涉及到用户信息的操作时需传入 |
| spId | Integer | 10 | 是 | 服务商ID |
# 4.1 车主审核状态变更通知
# 请求地址
- /v1/callback/driver/status
# 请求参数
| 参数名称 | 类型 | 说明 | 必须 |
|---|---|---|---|
| userStatus | Integer | 1-认证成功/正常、2-车主认证审核中、3-车主认证失败、4-车主认证过期、5-车主人脸识别认证过期、6-犯罪记录未通过 | 是 |
| authFailureReasonList | List | 认证失败原因枚举列表,使用腾讯侧定义枚举值 | 认证失败时必传 |
# FailureReason
| 参数名称 | 类型 | 说明 | 必须 |
|---|---|---|---|
| failureType | Integer | 认证失败原因枚举列表,使用腾讯侧定义枚举值 | 是 |
| failureDesc | String | 认证失败原因枚举列表,使用腾讯侧定义枚举值 | 是 |
# 请求示例
{
"accessKey": "QWERTYASDFGZXC",
"seqId": "12345678910111213141516",
"timestamp": 1234567891011,
"nonce": "qwertyuiop",
"userCode": "a1b2c7d5e9f8g1h",
"userStatus": 1,
"sign": "A1B2C3D4E5F6G7H8I9J0"
}
# 响应数据
| 参数名称 | 类型 | 说明 | 必须 |
|---|---|---|---|
| - | - | - | - |
# 响应示例
{
"code": 0,
"message": "成功"
}
# 4.2 服务商同步创建车主行程
# 请求地址
- /v1/callback/driver/trip/create
# 请求参数
| 参数名称 | 类型 | 说明 | 必须 |
|---|---|---|---|
| spDriverTripId | String | 服务商车主行程ID | 是 |
| spDriverInfo | DriverInfo | 服务商车主信息 | 是 |
| startAddr | LocationInfo | 行程起点 | 是 |
| endAddr | LocationInfo | 行程终点 | 是 |
| earliestDepartureTime | Long | 行程最早出发时间 | 是 |
| latestDepartureTime | Long | 行程最晚出发时间 | 是 |
| seatNum | Integer | 座位数 | 是 |
| price | Integer | 总价格 | 是 |
| seatUnitPrice | Integer | 单座位价格 | 是 |
| remark | String | 备注信息 | 否 |
# DriverInfo
| 参数名称 | 类型 | 说明 | 必须 |
|---|---|---|---|
| driverId | String | 服务商车主ID | 是 |
| driverName | String | 服务商车主昵称(如尾号8888) | 是 |
| drivingAge | String | 服务商车主驾龄 | 是 |
| plateNo | String | 服务商车牌号 | 是 |
| tripNum | Integer | 累计完单数 | 是 |
# 请求示例
{
"seqId": "xyz789",
"timestamp": 1234567891012,
"spId": 1001,
"spDriverTripId": "trip123456",
"spDriverId": {
"driverId": "driver123456",
"driverName": "张三",
"drivingAge": "5年",
"plateNo": "粤B88888",
"tripNum": 100
},
"startAddr": {
"lng": 116.397128,
"lat": 39.916527,
"cityCode": "110000",
"adCode": "110101",
"phoneAreaCode": "010",
"name": "起点名称",
"address": "起点详细地址",
"cityName": "北京市",
"districtName": "东城区",
"townName": "东华门街道"
},
"endAddr": {
"lng": 116.405285,
"lat": 39.904989,
"cityCode": "110000",
"adCode": "110101",
"phoneAreaCode": "010",
"name": "终点名称",
"address": "终点详细地址",
"cityName": "北京市",
"districtName": "东城区",
"townName": "东华门街道"
},
"earliestDepartureTime": 1234567891013,
"latestDepartureTime": 1234567891014,
"seatNum": 4,
"price": 500,
"seatUnitPrice": 50,
"remark": "备注信息"
}
# 响应数据
| 参数名称 | 类型 | 说明 | 必须 |
|---|---|---|---|
| code | Integer | 响应状态码 | 是 |
| message | String | 响应信息 | 是 |
| data | SpDriverTripCreateResData | 响应数据 | 是 |
# SpDriverTripCreateResData
| 参数名称 | 类型 | 说明 | 必须 |
|---|---|---|---|
| driverTripId | String | 腾讯侧车主行程ID | 是 |
# 响应示例
{
"code": 0,
"message": "成功",
"data": {
"driverTripId": "driverTrip123456"
}
}
# 4.3 服务商修改车主行程
# 请求地址
- /v1/callback/driver/trip/modify
# 请求参数
| 参数名称 | 类型 | 说明 | 必须 |
|---|---|---|---|
| tripId | String | 腾讯侧行程ID | 是 |
| spDriverTripId | String | 服务商车主行程ID | 是 |
| spDriverInfo | DriverInfo | 服务商车主信息 | 是 |
| startAddr | LocationInfo | 行程起点 | 是 |
| endAddr | LocationInfo | 行程终点 | 是 |
| earliestDepartureTime | Long | 行程最早出发时间 | 是 |
| latestDepartureTime | Long | 行程最晚出发时间 | 是 |
| seatNum | Integer | 座位数 | 是 |
| price | Integer | 总价格 | 是 |
| seatUnitPrice | Integer | 单座位价格 | 是 |
| remark | String | 备注信息 | 否 |
# 请求示例
{
"seqId": "def789",
"timestamp": 1234567891016,
"spId": 1001,
"tripId": "order123456",
"spDriverId": {
"driverId": "driver123456",
"driverName": "张三",
"drivingAge": "5年",
"plateNo": "粤B88888",
"tripNum": 100
},
"startAddr": {
"lng": 116.397128,
"lat": 39.916527,
"cityCode": "110000",
"adCode": "110101",
"phoneAreaCode": "010",
"name": "起点名称",
"address": "起点详细地址",
"cityName": "北京市",
"districtName": "东城区",
"townName": "东华门街道"
},
"endAddr": {
"lng": 116.405285,
"lat": 39.904989,
"cityCode": "110000",
"adCode": "110101",
"phoneAreaCode": "010",
"name": "终点名称",
"address": "终点详细地址",
"cityName": "北京市",
"districtName": "东城区",
"townName": "东华门街道"
},
"earliestDepartureTime": 1234567891017,
"latestDepartureTime": 1234567891018,
"seatNum": 4,
"seatUnitPrice": 50,
"remark": "修改备注信息"
}
# 响应数据
| 参数名称 | 类型 | 说明 | 必须 |
|---|---|---|---|
| code | Integer | 响应状态码 | 是 |
| message | String | 响应信息 | 是 |
# 响应示例
{
"code": 0,
"message": "成功"
}
# 4.4 服务商同步的车主行程状态变更(具有取消功能)
# 请求地址
/v1/callback/driver/trip/status
# 请求参数
| 字段名 | 类型 | 描述 | 是否必填 |
|---|---|---|---|
| tripId | String | 腾讯侧行程ID | 是 |
| spTripId | String | 服务商行程ID | 是 |
| tripStatus | Integer | 行程状态(具体状态值需定义) | 是 |
# tripStatus行程状态值定义
| 状态值 | 描述 |
|---|---|
| 201 | 创建行程(进行中) |
| 901 | 行程已完成 |
| 902 | 行程已过期 |
| 910 | 行程已取消 |
# 返回参数
# BaseRes
| 字段名 | 类型 | 描述 |
|---|---|---|
| code | Integer | 返回码,0表示成功,非0表示失败 |
| message | String | 返回信息 |
# 示例请求
{
"seqId": "abc123",
"timestamp": 1633036800000,
"spId": 1001,
"tripId": "trip_001",
"tripStatus": 201
}
# 示例响应
{
"code": 0,
"message": "成功"
}
# 4.5 服务商车主接受乘客占座邀请
# 请求地址
- /v1/callback/driver/invite/accept
# 请求参数
| 参数名称 | 类型 | 说明 | 必须 |
|---|---|---|---|
| applyId | String | 申请单ID | 是 |
| tripId | String | 行程ID | 是 |
# 请求示例
{
"seqId": "jkl345",
"timestamp": 1234567891020,
"spId": 600010,
"applyId": "driverTrip123456",
"tripId": "trip123456"
}
# 响应数据
| 参数名称 | 类型 | 说明 | 必须 |
|---|---|---|---|
| code | Integer | 响应状态码 | 是 |
| message | String | 响应信息 | 是 |
# 响应示例
{
"code": 0,
"message": "成功"
}
# 4.6 服务商车主将乘客踢出行程
# 请求地址
- /v1/callback/driver/trip/kick
# 请求参数
| 参数名称 | 类型 | 说明 | 必须 |
|---|---|---|---|
| tripId | String | 服务商同步到腾讯侧生成的车主行程ID | 是 |
| applyId | String | 乘客申请单ID | 是 |
# 请求示例
{
"seqId": "pqr901",
"timestamp": 1234567891022,
"spId": 1001,
"tripId": "driverTrip123456",
"applyId": "apply123456"
}
# 响应数据
| 参数名称 | 类型 | 说明 | 必须 |
|---|---|---|---|
| code | Integer | 响应状态码 | 是 |
| message | String | 响应信息 | 是 |
# 响应示例
{
"code": 0,
"message": "成功"
}
# 4.7 (二期)服务商车主向乘客发起上车邀请
# 请求地址
- /v1/callback/driver/invite/request
# 请求参数
| 参数名称 | 类型 | 说明 | 必须 |
|---|---|---|---|
| tripId | String | 腾讯侧乘客行程ID | 是 |
| spDriverInfo | DriverInfo | 服务商车主信息 | 是 |
| seatUnitPrice | Integer | 车主邀请乘客时的每座价格,单位:分 | 是 |
| applyStartAddr | LocationInfo | 申请起点信息 | 是 |
| applyEndAddr | LocationInfo | 申请终点信息 | 是 |
# 请求示例
{
"seqId": "ghi012",
"timestamp": 1234567891019,
"spId": 600010,
"tripId": "passengerTrip123456",
"spDriverInfo": {
"driverId": "driver123456",
"driverName": "张三",
"drivingAge": 5,
"plateNo": "粤B88888",
"tripNum": 100
},
"seatUnitPrice": 50,
"applyStartAddr": {
"lng": 116.397128,
"lat": 39.916527,
"cityCode": "110000",
"adCode": "110101",
"phoneAreaCode": "010",
"name": "天安门",
"address": "天安门广场",
"cityName": "北京",
"districtName": "东城区",
"townName": "天安门"
},
"applyEndAddr": {
"lng": 116.405285,
"lat": 39.904989,
"cityCode": "110000",
"adCode": "110101",
"phoneAreaCode": "010",
"name": "故宫",
"address": "故宫博物院",
"cityName": "北京",
"districtName": "东城区",
"townName": "故宫"
}
}
# 响应数据
| 参数名称 | 类型 | 说明 | 必须 |
|---|---|---|---|
| code | Integer | 响应状态码 | 是 |
| message | String | 响应信息 | 是 |
| data | Object | 响应数据 | 是 |
| data.applyId | String | 申请单ID | 是 |
# 响应示例
{
"code": 0,
"message": "成功",
"data": {
"applyId": "apply123456"
}
}
# 4.8 (二期)服务商车主取消/撤销上车邀请
# 请求地址
- /v1/callback/driver/invite/cancel
# 请求参数
| 参数名称 | 类型 | 说明 | 必须 |
|---|---|---|---|
| spDriverId | String | 服务商车主ID | 是 |
| tripId | String | 腾讯侧乘客行程ID | 是 |
| applyId | String | 申请单ID | 是 |
# 请求示例
{
"seqId": "ghi012",
"timestamp": 1234567891019,
"spId": 600010,
"spDriverId": "driver123456",
"tripId": "passengerTrip123456",
"applyId": "apply123456"
}
# 响应数据
| 参数名称 | 类型 | 说明 | 必须 |
|---|---|---|---|
| code | Integer | 响应状态码 | 是 |
| message | String | 响应信息 | 是 |
# 响应示例
{
"code": 0,
"message": "成功"
}
# 4.8 服务商车主发送IM消息给乘客
# 请求地址
- /v1/callback/im/message/send
# 请求参数
| 参数名称 | 类型 | 说明 | 必须 |
|---|---|---|---|
| spDriverId | String | 服务商司机ID | 是 |
| tripId | String | 会话关联行程ID | 是 |
| messageType | Integer | 消息类型 文字0/图片1/定位2 | 是 |
| messageBody | MessageBody | 消息内容 | 是 |
| messageBody.text | String | 文本消息 | 是 |
| messageBody.url | String | 图片/语音URL | 否 |
| messageBody.duration | Integer | 语音时长 | 否 |
| spMessageId | String | 服务商生成的消息ID | 否 |
# 请求示例
{
"seqId": "stu234",
"timestamp": 1234567891023,
"spId": 1001,
"userCode": "driverTrip123456",
"spDriverId": "driver001",
"tripId": "trip123456",
"messageType": 0,
"messageBody": "你好,欢迎上车!",
"spMessageId": "msg123456"
}
# 响应数据
| 参数名称 | 类型 | 说明 | 必须 |
|---|---|---|---|
| code | Integer | 响应状态码 | 是 |
| message | String | 响应信息 | 是 |
| data | Object | 响应数据 | 是 |
| data.messageId | String | 腾讯侧消息ID | 是 |
# 响应示例
{
"code": 0,
"message": "成功",
"data": {
"messageId": "msg123456"
}
}
# 4.9 服务商车主单会话已读
# 请求地址
- /v1/callback/im/message/read/session
# 请求参数
| 参数名称 | 类型 | 说明 | 必须 |
|---|---|---|---|
| tripId | String | 腾讯侧行程ID | 是 |
| spDriverId | String | 服务商车主ID | 是 |
| userCode | String | 腾讯侧参与会话的用户userCode | 是 |
| messageIdList | List | 腾讯侧消息ID列表 | 否 |
| spMessageIdList | List | 服务商消息ID列表 | 否 |
# 请求示例
{
"seqId": "stu234",
"timestamp": 1234567891023,
"spId": 1001,
"tripId": "trip123456",
"spDriverId": "driver001",
"userCode": "driverTrip123456",
"messageIdList": ["string1", "string2"],
"spMessageIdList": ["string1", "string2"]
}
# 响应数据
| 参数名称 | 类型 | 说明 | 必须 |
|---|---|---|---|
| code | Integer | 响应状态码 | 是 |
| message | String | 响应信息 | 是 |
# 响应示例
{
"code": 0,
"message": "成功"
}
# 4.10 服务商车主全部已读
# 请求地址
- /v1/callback/im/message/read/all
# 请求参数
| 参数名称 | 类型 | 说明 | 必须 |
|---|---|---|---|
| spDriverId | String | 服务商车主ID | 是 |
# 请求示例
{
"seqId": "stu234",
"timestamp": 1234567891023,
"spId": 1001,
"spDriverId": "driver001"
}
# 响应数据
| 参数名称 | 类型 | 说明 | 必须 |
|---|---|---|---|
| code | Integer | 响应状态码 | 是 |
| message | String | 响应信息 | 是 |
# 响应示例
{
"code": 0,
"message": "成功"
}
# 4.11 司机获取乘客虚拟号请求
# 请求地址
- /v1/callback/passenger/phone/get
# 请求参数
| 参数名称 | 类型 | 说明 | 必须 |
|---|---|---|---|
| srcPhone | String | 来电号码 | 是 |
| tripId | String | 乘客行程ID(腾讯导出场景乘客行程ID) | 是,tripId和applyId必选其一 |
| applyId | String | 乘客申请单ID(腾讯申请占座时的申请ID) | 是,tripId和applyId必选其一 |
# 请求示例
{
"seqId": "abc987",
"timestamp": 1234567891100,
"tripId": "trip123456"
}
# 响应数据
| 参数名称 | 类型 | 说明 | 必须 |
|---|---|---|---|
| code | Integer | 响应状态码 | 是 |
| message | String | 响应信息 | 是 |
| data | Object | 响应数据 | 是 |
| data.virtualPhone | String | 虚拟号 | 是 |
| data.expireTime | Long | 过期时间 | 是 |
# 响应示例
{
"code": 0,
"message": "成功",
"data": {
"virtualPhone": "12345678901",
"expireTime": 1633040400
}
}
# 4.12 服务商通话记录同步
- 车主给乘客打电话无需再调用腾讯侧虚拟号接口,直接使用下单接口的手机号绑定虚拟号即可,并将通话状态同步到腾讯侧
# 请求地址
- /v1/callback/call/record/sync
# 请求参数
| 参数名称 | 类型 | 说明 | 必须 |
|---|---|---|---|
| spDriverInfo | DriverInfo | 服务商车主信息 | 是 |
| tripId | String | 腾讯行程ID | 是 |
| srcPhone | String | 主叫号码 | 是 |
| destPhone | String | 被叫号码 | 是 |
| caller | Integer | 主叫人 1-乘客,2-车主 | 是 |
| callTime | Long | 呼叫时间,毫秒级时间戳 | 是 |
| callStatus | Integer | 呼叫状态,见枚举值 | 是 |
# DriverInfo
| 字段名 | 类型 | 说明 |
|---|---|---|
| driverId | String | 车主ID |
| driverName | String | 车主昵称 |
| drivingAge | String | 驾龄 |
| plateNo | String | 车牌号 |
| tripNum | Integer | 累计完单数 |
| driverRegisterTime | Long | 车主注册时间 |
# 通话状态枚举值
| 状态 | 描述 |
|---|---|
| UNKNOWN(0) | 未知/默认 |
| CALLING(1) | 呼叫中,未拨通 |
| RINGING(2) | 已拨通,响铃中(一直停留在这个状态即表示未接听) |
| ACCEPTED(3) | 已接听 |
| REJECTED(4) | 已拒接 |
| NORMAL_HANGUP(5) | 正常挂断 |
| CALL_FAILED(6) | 呼叫失败/异常(兜底未拨通) |
# 请求示例
{
"spDriverId": "driver_123456",
"tripId": "trip_987654321",
"srcPhone": "13800138000",
"destPhone": "13900139000",
"caller": 1,
"callTime": 1672500000000,
"callStatus": 2
}
# 响应数据
| 参数名称 | 类型 | 说明 | 必须 |
|---|---|---|---|
| code | Integer | 响应状态码 | 是 |
| message | String | 响应信息 | 是 |
# 响应示例
{
"code": 0,
"message": "成功"
}
# 5. 附录
# 5.1 车主审核失败原因枚举
# 5.1.1 身份证错误信息
| 腾讯枚举值 | 错误描述 |
|---|---|
| 1001 | 身份证姓名错误(可注明具体原因) |
| 1002 | 身份证号错误(可注明具体原因) |
| 1003 | 年龄不足18岁,暂不支持认证车主 |
| 1004 | 年龄超过65岁,暂不支持认证车主 |
| 1005 | 实名审核未通过 |
# 5.1.2 驾驶证错误信息
| 腾讯枚举值 | 错误描述 |
|---|---|
| 2001 | 身份信息类错误(可注明具体原因) |
| 2002 | 初次领证日期异常,请修改 |
| 2003 | 你还在实习期内,暂不支持认证车主 |
| 2004 | 驾驶证有效开始日期异常,请重新上传 |
| 2005 | 该驾驶证已失效,请上传有效期内的证件 |
| 2006 | 暂无实名/驾驶证审核记录 |
| 2007 | 暂无驾驶证信息 |
# 5.1.3 行驶证错误信息
| 腾讯枚举值 | 错误描述 |
|---|---|
| 3001 | 车牌号填写有误,请检查 |
| 3002 | 车辆品牌型号有误,请检查 |
| 3003 | 车辆使用性质有误,请检查 |
| 3004 | 车辆颜色有误,请检查 |
| 3005 | 行驶证注册时间不得超过15年 |
| 3006 | 注册日期异常,请上传有效期内的证件 |
| 3007 | 暂无车辆审核记录 |
# 5.1.4 其他
| 腾讯枚举值 | 错误描述 |
|---|---|
| 9001 | 其他(可注明具体原因) |
# 5.2 接口错误码
| 错误码 | 描述 |
|---|---|
| 0 | 成功 |
| -1 | 服务内部错误 |
| 1 | 回调请求签名校验不通过 |
| 2 | 回调请求参数错误 |
| 20 | 回调处理失败 |
# 5.3 服务商ID
| spId | 错误描述 |
|---|---|
| 600010 | 一喂顺风车 |
← 宠物出行 优惠券SP多租户开放文档 →