开始之前

注册渠道后,在客服后台的「渠道设置 → 接入方式」里能拿到两样东西: 渠道接入码和接口密钥。 接入码会出现在页面源码里,是公开的;接口密钥只能放在你的服务端。

那一页还有一条不带任何参数的测试链接,复制到浏览器打开就能确认渠道通不通,建议先做这一步。

脚本嵌入

网站右下角出现悬浮球,点开是聊天框。放在 </body> 之前:

<script src="https://chat.jstosecret.com/embed.js"
        data-channel="你的接入码"
        defer></script>

聊天框跑在 iframe 里,和你页面的 CSS 互不影响。 脚本只负责注入悬浮球和创建 iframe,不会碰你页面上的其他元素。

打开就是聊天页面,适合 App 内嵌浏览器、邮件、工单回执这些没法插脚本的地方。

https://chat.jstosecret.com/?c=你的接入码

传递用户身份

带上你系统里的用户信息,客服进线就知道来的是谁,访客再次进线也能优先回到上次接待他的客服。 三个字段都是选填,按你有什么传什么。

参数脚本属性最大长度说明
cdata-channel32渠道接入码,必填
uiddata-uid64你系统里的用户 ID,识别回头客主要看它
emaildata-email128用户邮箱
accountdata-account128用户名或账号
langdata-lang20指定语言,不填则按浏览器语言判断
extradata-extra256额外信息,纯文本,原样展示给客服,不参与识别

超长会被截断保存,不会报错、也不会丢掉整次接入。 长度按字符算,不是字节——一个中文、一个 emoji 都可能占多个字符位。

<!-- 脚本方式,服务端渲染时把占位符换成真实值 -->
<script src="https://chat.jstosecret.com/embed.js"
        data-channel="你的接入码"
        data-uid="10001"
        data-email="[email protected]"
        data-extra="VIP客户 订单#8823"
        defer></script>

访客是怎么被匹配的

三个身份字段是互斥的优先级,不是逐个回退:

你传了按什么匹配匹配不上时
uid只按 uid当作新访客,不会再用邮箱去试
只有 email按 email当作新访客
只有 account按 account当作新访客
都没传浏览器本地标识当作新访客

传了 uid 就只认 uid,这一条最重要。 因为回退会串号:你换了一套用户体系导致 uid 变了, 或者两个员工共用一个 [email protected], 后来的人就会接管前面那个人的记录,连同历史会话一起看到。 uid 是你明确给出的身份断言,它说"这是新用户",我们不该拿一个更弱的字段替你做主。

对接时据此注意两点:

  • 有 uid 就一直传。 这次传 uid、 下次只传 email,同一个人会被当成两个访客,历史会话对不上。
  • uid 要稳定。 用数据库主键这类不会变的值, 别用手机号、邮箱这种用户自己能改的字段——改一次就等于换了个人。

识别范围是单个渠道内。同一个人在你的两个渠道里是两条独立记录, 会话和历史互不可见,这是渠道隔离的一部分。

额外信息里的特殊字符

额外信息是最容易出问题的一个参数,因为它的内容完全由业务决定, 订单号、地址、客户诉求什么都可能往里塞。三条规则:

  • 拼链接一定要 encodeURIComponent(),不要自己拼字符串。 &、#、?、+、空格不编码会把链接截断或串到别的参数上—— extra=A&B 里的 B 会被当成一个新参数。
  • 写进 data-extra 属性时要做 HTML 转义: " 转成 &quot;、< 转成 &lt;。 否则一个引号就能提前闭合属性,整段 script 标签作废。 服务端渲染时用模板引擎自带的转义即可。
  • 换行和制表符会被替换成空格,留着只会把接待端的展示撑乱。

emoji 和各国文字可以直接用,存储是 utf8mb4。

// 正确的拼法
const url = 'https://chat.jstosecret.com/?c=你的接入码'
  + '&uid=' + encodeURIComponent(user.id)
  + '&extra=' + encodeURIComponent('VIP客户 订单#8823 诉求:急件&加急')

// 错误:& 和 # 没编码,extra 只会拿到 "VIP客户 订单"
// 后面的 "加急" 还会变成一个叫"加急"的野参数
const bad = base + '&extra=VIP客户 订单#8823 诉求:急件&加急'

这些参数是明文的

它们出现在页面源码和地址栏里,任何人都能改。 也就是说,只靠这种方式传身份,别人改一下 uid 就能冒充成另一个用户进来, 看到那个人的历史会话。如果聊天里会涉及订单、账户这类信息,用下面的票据方式。

一次性票据

你的服务端先用接口密钥换一张票,再把票拼进链接给访客。 URL 里不出现用户信息,票用过即失效,转发出去的链接第二次打不开。

第一步:服务端换票

curl -X POST https://chat.jstosecret.com/api/open/ticket \
  -H 'Content-Type: application/json' \
  -H 'X-Channel-Secret: 你的接口密钥' \
  -d '{"channelCode":"你的接入码","uid":"10001","extra":"VIP客户 订单#8823"}'

# 返回
{ "ticket": "a1b2c3...", "expiresIn": 300 }

第二步:把票给访客

# 链接方式
https://chat.jstosecret.com/?c=你的接入码&ticket=a1b2c3...

# 或脚本方式
<script src="https://chat.jstosecret.com/embed.js"
        data-channel="你的接入码"
        data-ticket="a1b2c3..."
        defer></script>
  • 接口密钥只能留在你的服务端。放到前端就等于公开,任何人都能签出别人的身份。
  • 票据默认 5 分钟有效,可以用 expiresIn 指定 30~1800 秒。
  • 访客刷新页面不受影响:首次进入后会换成长期本地令牌,不再用票。
  • 票据只传递身份、不存储身份。访客三个月后再来,重新换一张票就行,历史记录都还在。

外观与位置

悬浮球的图标、位置、边距、主题色,还有聊天框顶部的项目名称和图标, 都在客服后台的「渠道设置」里改。改完对方刷新页面即生效,不用重新贴代码。

个别站点需要单独调位置时(比如右下角已经被别的按钮占了),可以加属性覆盖:

<script src="https://chat.jstosecret.com/embed.js"
        data-channel="你的接入码"
        data-position="left-bottom"
        data-offset-x="24"
        data-offset-y="90"
        defer></script>

注意这几个属性优先级更高,加了之后这个站点的位置就固定了, 后台里再改不会生效。只在确实需要时用。

独立域名

专业版及以上赠送独立域名。聊天框和悬浮球挂在你自己的域名下, 比如 chat.yourdomain.com,访客看到的地址是你的品牌。

为什么值得配

除了品牌,更实际的作用是把故障风险隔开。 默认情况下所有客户共用我们的聊天域名——只要其中一家因为任何原因 被某个网络环境、某个运营商或某个企业防火墙拦下, 这个域名下的所有人都会跟着打不开。而你那边看到的只是"访客突然连不上", 排查方向完全是错的。

用自己的域名之后:别人出事影响不到你;真轮到你出问题, 换一条解析就能恢复,不用排队等我们处理。 旗舰版给 5 个,多品牌或多站点可以各用各的,互相不牵连。

怎么配

  • 你在 DNS 里加一条 CNAME,指向我们提供的地址
  • 证书由我们申请和续期,不需要你操心
  • 生效后把接入代码里的地址换成新域名即可,其他不用改

需要开通时联系 [email protected], 告诉我们你想用的域名。

手动控制

想让自己页面上的按钮打开聊天框,而不是用默认悬浮球:

// 脚本加载后可用
window.KefuWidget.open()
window.KefuWidget.close()
window.KefuWidget.toggle()

悬浮球本身不能隐藏——如果你只想用自己的按钮,把它的边距调到屏幕外即可, 比如 data-offset-x="-100"。

接入遇到问题

先看服务端返回的错误信息,多数接入问题(接入码写错、票据过期、密钥放到了前端) 都会在响应里直接说明原因。

注册一个渠道,五分钟接完

拿到接入码就能贴代码,不用等审核。