操作:来自您自己系统的答案
操作让您的机器人能在聊天过程中直接从您自己的系统查询信息 — 订单在哪里、何时送达、预订是否已确认。客户提问,机器人收集所需信息,调用您的 API,并用客户的语言根据返回结果作答。
它可在您的机器人运行的所有地方使用:网站小部件、您的机器人链接和二维码,以及 Android、iOS、React Native、Flutter 和 Ionic 应用。无需安装或更新任何东西 — 调用由我们的服务器发起,因此您的 API 凭据绝不会到达浏览器或手机。
开始之前:任何人都可以与您的机器人聊天
您的机器人是公开聊天。如果仅凭订单号就能查看订单,任何人都可以不断输入数字,直到猜中为止。
机器人从三个方面提供帮助,但都不能替代这一核对:它只发送客户实际输入的值,它限制一个聊天或一个地址可进行的查询次数,并且您可以选择它能看到响应中的哪些字段。
设置一个操作
在仪表盘中打开操作,然后选择新建操作。所有者和管理员可以看到此页面。
- 名称 — 供您自己识别,例如“订单状态”。
- 机器人应在何时使用它? — 一句话,就像您向新同事交代那样:“客户询问订单在哪里或何时送达。”
- 您的 API 地址 —
GET或POST,以及一个https://地址。在需要填入值的位置写上{{order_id}}。 - 机器人向客户询问的内容 — 最多六个值。每个值都有一个用您自己的话写的标签(“订单号”)、您的 API 使用的名称(
order_id)和一个类型:任意文本、数字、邮箱地址或电话号码。 - 请求头 — 您的 API 密钥或令牌。加密存储,不再显示。
- 仅与机器人共享这些字段 — 可选。列出机器人可以使用的响应部分,例如
status, eta, items[].name。其余内容会在 AI 看到之前被丢弃。
点击测试,输入示例值,您就能看到已发送的请求以及机器人将会收到的确切内容。然后在测试页面上实际试一试:“我的订单 48213 在哪里?我的邮箱是 asha@example.com”。
您的 API 会收到什么
使用 GET 时,您放在地址中的值会被填入,其余的值会添加到查询字符串中:
GET https://api.yourshop.com/orders/48213?email=asha%40example.com使用 POST 时,这些值就是 JSON 请求体:
POST https://api.yourshop.com/lookup
Content-Type: application/json
{"order_id":"48213","email":"asha@example.com"}每个请求还会携带您自己的请求头以及以下这些:
| 请求头 | 这是什么 |
|---|---|
webhook-id | 此请求的唯一 id |
webhook-timestamp | 发送时间,以秒为单位 |
webhook-signature | 签名 — 见下文 |
X-Keyda-Bot | 您的机器人的 Client ID |
X-Keyda-Action | 操作的键,例如 order_status |
X-Keyda-Conversation | 请求来自的聊天 |
应返回什么
请在 8 秒内以 JSON 或一行简短的纯文本回复。
- 200 并附带数据 — 机器人据此作答。请保持精简并使用清晰的字段名:
{"status":"shipped","eta":"2 October"}比内部代码更好用。 - 无匹配结果时返回 404 — 机器人会告知客户,并请他们检查输入的内容。
- 其他任何情况,或未及时回复 — 机器人会致歉、提供您的联系方式,并为您标记该聊天。原因会显示在“操作”页面上。
不会跟随重定向,超过 256 KB 的响应不会被读取。
验证签名
请求按 Standard Webhooks 的方式签名,因此您可以使用现有的库。您的签名密钥在“操作”页面上。
手动方式:用英文句点将 id、时间戳和原始请求体连接起来,用密钥(whsec_ 之后的部分,经 base64 解码)通过 HMAC-SHA256 签名,然后比对。
const crypto = require('crypto');
function isFromKeyda(req, rawBody, secret) {
const id = req.headers['webhook-id'];
const ts = req.headers['webhook-timestamp'];
const given = String(req.headers['webhook-signature'] || '').replace(/^v1,/, '');
if (Math.abs(Date.now() / 1000 - Number(ts)) > 300) return false; // older than 5 minutes
const key = Buffer.from(secret.replace(/^whsec_/, ''), 'base64');
const want = crypto.createHmac('sha256', key).update(`${id}.${ts}.${rawBody}`).digest('base64');
return given.length === want.length
&& crypto.timingSafeEqual(Buffer.from(given), Buffer.from(want));
}对于 GET 请求,请求体为空,因此被签名的文本以句点结尾。如果您希望签名也覆盖这些值本身,请使用 POST。
机器人如何使用它
- 它会逐一用简短的问题询问缺少的信息,并记住客户在聊天中之前说过的内容。
- 它绝不会猜测值。如果客户没有输入,机器人会主动询问。
- 每条消息只进行一次查询。您已保存的回答仍然优先,因此您手动回答过的问题绝不会调用您的 API。
- 查询得到的答案绝不会重复用于其他客户。
- 一次查询计为一次回答,与 AI 撰写的其他回复相同。
在聊天中,来自查询的回答会在下方注明:运行了哪个操作以及结果如何。客户输入的值只保留在聊天记录中,不会保存在其他任何地方。
限制
操作只读取信息。不要将操作指向会更改数据的地址 — 取消订单或退款需要一个确认步骤,而机器人目前还没有这一步。