查询对话记录

更新时间:2025-08-05 03:07:04下载pdf

本文介绍查询对话记录的 API。

接口描述

根据设备 ID、绑定角色类型和角色 ID,查询 AI 智能体对话记录。

接口地址

GET: /v1.0/cloud/agent/ai/enterprise/chat/devices/{device_id}/history

请求参数

参数名 类型 参数位置 是否必填 说明
device_id String path true 设备 ID
gmt_end Long query true 聊天信息的截止时间(时间戳),小于此时间的聊天信息会被返回
page_size Integer query true 每页数量,每页最多 20 条

返回参数

参数名 类型 说明
success Boolean 请求是否成功
error_code String 错误代码
error_msg String 错误信息
result Object 返回结果

result 说明

参数名 类型 说明
data String 聊天信息(密文,需要进行解密)
pv String 协议版本
sign String 防伪造校验的数据签名
t Long 接口返回时的系统时间

请求示例

GET: /v1.0/cloud/agent/ai/enterprise/chat/devices/6c50600a0e15d1fb78h***/history?page_size=20&gmt_end=1753079987512

返回示例

{
    "error_msg": null,
    "result": {
        "data": "XpAnrVY93e***",
        "pv": "1.0",
        "sign": "e92b1036a7546f912058e07546ba66585ca2***",
        "t": 1753770653706
    },
    "success": true,
    "error_code": null
}

错误码

参考 错误码

接口返回值解密后的数据说明

resultdata 对象说明

参数名 类型 说明
gmt_create Long 聊天时间(时间戳)
answer List 回答内容列表
question List 提问内容列表
request_id String 聊天记录 ID
role_info Object 角色信息。若角色被删除,则不会返回

Answer/Question 对象说明

参数名 类型 说明
context String 消息内容
type String 消息类型

role_info 对象说明

参数名 类型 说明
role_id String 角色 ID
role_name String 角色名称
bind_role_type Integer 绑定角色类型:
  • 0:自定义智能体角色
  • 1:智能体角色模板
  • 2:单角色场景默认角色

解密后的数据示例

{
	"data": [{
		"answer": [{
			"context": "你之前跟我说过***",
			"type": "text"
		}],
		"gmt_create": 1753758926504,
		"question": [{
			"context": "我的***",
			"type": "text"
		}],
		"request_id": "ccbda733-e3d2-4ee3-bb19-d201-***",
		"role_info": {
			"bind_role_type": 1,
			"role_id": "20001",
			"role_name": "测试角色"
		}
	}]
}

聊天记录解密机制

功能说明

为了保障数据传输安全,接口返回的聊天记录采用 AES-GCM 认证加密模式 进行加密处理。您需对响应体中 data 字段进行解密后,方可获取原始数据。

技术规范

属性 规格说明
加密标准 AES-GCM(Galois/Counter Mode)
密钥来源 云开发项目配置的 Access Secret
安全特性 数据完整性验证、真实性认证、抵抗选择密文攻击

Java 实现示例

import javax.crypto.Cipher;
import javax.crypto.SecretKey;
import javax.crypto.spec.GCMParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.nio.charset.StandardCharsets;
import java.security.GeneralSecurityException;
import java.security.InvalidKeyException;
import java.util.Base64;

public class CryptoUtils {
    
    private static final String AES_ALGO = "AES";
    private static final String AES_GCM = "AES/GCM/NoPadding";
    private static final int GCM_NONCE_LENGTH = 12; 
    private static final int GCM_TAG_LENGTH = 16;      // 认证标签长度

    /**
     * AES-GCM 解密实现
     * 
     * @param data Base64 编码的密文字符串
     * @param key 项目密钥,即 Access Secret
     * @return 解密后的原始字符串
     * @throws IllegalArgumentException 当输入参数不合法时抛出
     */
    public static String decryptDataGCM(String data, String key) 
            throws GeneralSecurityException {
        // 参数校验
        if (key == null || key.isEmpty()) {
            throw new IllegalArgumentException("密钥不能为空");
        }
        Key secretKey = new SecretKeySpec(key.getBytes(), AES_ALGO);
        Cipher cipher = Cipher.getInstance(AES_GCM);
        byte[] message = Base64.decodeBase64(data);
        if (message.length < GCM_NONCE_LENGTH + GCM_TAG_LENGTH) {
            throw new IllegalArgumentException();
        }
        GCMParameterSpec params = new GCMParameterSpec(GCM_TAG_LENGTH * 8, message, 0, GCM_NONCE_LENGTH);
        cipher.init(Cipher.DECRYPT_MODE, secretKey, params);
        byte[] decryptData = cipher.doFinal(message, GCM_NONCE_LENGTH, message.length - GCM_NONCE_LENGTH);
        return new String(decryptData);
    }
}

签名生成规范

为了确保数据完整性与请求来源真实性,请按以下流程进行签名验证:

签名生成规则

  1. 获取接口返回数据:从接口响应中提取以下关键字段。

    • sign:接口返回的数字签名
    • t:UNIX 时间戳
    • pv:协议版本号
    • data:加密的数据负载
  2. 本地重新生成签名:使用与接口相同的签名算法和密钥(Access Secret)执行签名计算。

    String localSign = SignUtils.createCloudSign(data, pv, t, accessSecret);
    
  3. 签名比对验证:严格对比本地生成的签名与接口返回的 sign 值。

    if (!localSign.equals(apiSign)) {
      // 验证失败处理
    }
    
    验证结果 含义 处理措施
    一致 数据完整且来源可信 可安全使用数据
    不一致 传输过程中数据被篡改或密钥不匹配 1. 丢弃当前数据
    2. 检查密钥有效性
    3. 触发安全告警机制

Java 实现示例

/**
     * 生成数字签名(SHA-256)
     * 
     * @param data      加密数据,需与请求内容一致
     * @param pv        协议版本,例如 '1.0'
     * @param time      时间戳,取自接口中返回的 t 参数
     * @param secretKey 项目密钥,即 Access Secret
     * @return 十六进制编码的签名值
     */
    public static String createCloudSign(String data,
                                         String pv,
                                         long time,
                                         String secretKey) 
                throws NoSuchAlgorithmException {
        // 参数校验
        if (secretKey == null || secretKey.isEmpty()) {
            throw new IllegalArgumentException("secretKey 不能为空");
        }
        if (data == null || pv == null) {
            throw new IllegalArgumentException("data 和 pv 参数不能为 null");
        }

        // 创建有序参数集(TreeMap 默认按照键升序排列)
        TreeMap<String, String> params = new TreeMap<>();
        params.put("t", String.valueOf(time));
        params.put("data", data);
        params.put("pv", pv);

        // 构造签名字符串
        StringBuilder sb = new StringBuilder(128);
        for (Map.Entry<String, String> entry : params.entrySet()) {
            String value = entry.getValue();
            if (value != null && !value.trim().isEmpty()) {
                sb.append(entry.getKey())
                  .append('=')
                  .append(value)
                  .append("||");
            }
        }
        sb.append(secretKey);

        // SHA-256 哈希计算
        MessageDigest digest = MessageDigest.getInstance("SHA-256");
        byte[] hash = digest.digest(sb.toString().getBytes(StandardCharsets.UTF_8));
        
        // 转换为十六进制
        StringBuilder hexString = new StringBuilder(64);
        for (byte b: hash) {
            hexString.append(String.format("%02x", b));
        }
	return hexString.toString();
}