开发者接入
官网只需嵌入脚本;已登录的产品额外提供一个签发短期 JWT 的后端接口。不需要实现聊天、历史或实时消息接口。
1. 准备接入点
在控制台 接入点 中为官网或产品创建入口,点击 复制“接入代码”。同一产品的不同页面共用一个入口,页面位置由组件自动传递。适用产品在入口中固定,客户端不能覆盖。
以下示例将客服服务地址写为 https://support.example.com,入口标识 替换为控制台生成的实际值。
2. 匿名接入
在页面 </body> 前加入:
<script src="https://support.example.com/widget.js"
data-entry="入口标识" async></script>
也可将 https://support.example.com/chat/?entry=入口标识 用作页面按钮、二维码或微信公众号菜单的链接。公众号菜单打开的是聊天网页,暂不接收公众号原生消息。
匿名身份由组件管理。同一浏览器的同一接入点可继续未结束的会话;不同浏览器、无痕窗口和接入点分别隔离。无需自行生成访客 ID。
3. 接入产品登录用户
在入口高级设置中开启“需要产品登录身份”并保存,系统自动生成密钥。在“接入代码”中点击“获取签名密钥”,将其配置到产品后端。已有部署的 WIDGET_IDENTITY_KEYS 配置优先于自动生成密钥,由部署管理员维护。
签名密钥只能放在产品后端,不能写进前端代码或提交到仓库。
产品后端:验证登录后签发 JWT
下面是产品使用 Django 时的最小示例,依赖 PyJWT。ASKPORT_ENTRY 与 ASKPORT_SIGNING_KEY 是示例所需的产品后端 settings,分别从产品的部署配置读取入口标识和签名密钥。
import time
import jwt
from django.conf import settings
from django.http import JsonResponse
from django.views.decorators.http import require_GET
@require_GET
def support_token(request):
if not request.user.is_authenticated:
response = JsonResponse({"error": "请先登录"}, status=401)
else:
now = int(time.time())
token = jwt.encode({
"sub": str(request.user.pk),
"aud": f"askport:{settings.ASKPORT_ENTRY}",
"iat": now,
"exp": now + 300,
}, settings.ASKPORT_SIGNING_KEY, algorithm="HS256")
response = JsonResponse({"token": token})
response["Cache-Control"] = "no-store"
return response
在产品后端将此视图注册为 /api/support-token。该路径是接入示例,Askport 不提供此接口。其他后端框架按相同规则实现即可。
| 字段 | 规则 |
|---|---|
sub | 从已验证的产品登录会话取稳定用户 ID;非空字符串,最多 255 字符 |
aud | 固定为 askport:入口标识 |
iat / exp | 整数秒时间戳;有效期大于 0 且不超过 300 秒 |
name | 可选显示名称,字符串,最多 100 字符 |
算法固定为 HS256。不要接受前端提交的用户 ID 来签发令牌;用户 ID 应长期稳定且不重新分配。同一入口接入多个租户时,sub 应在这些租户间唯一,例如 tenant_id:user_id。服务端时钟需保持同步。
产品前端:先配置回调,再加载脚本
<script>
window.AskportSettings = {
async getIdentityToken() {
const response = await fetch('/api/support-token', {
credentials: 'same-origin',
cache: 'no-store'
});
if (!response.ok) throw new Error('请先登录产品');
return (await response.json()).token;
}
};
</script>
<script src="https://support.example.com/widget.js"
data-entry="入口标识" async></script>
令牌回调应每次请求后端取得新令牌,组件会在需要验证或重连时调用。
不要把令牌写进 URL、页面背景或 localStorage。
产品退出登录时调用 window.Askport.logout();重新登录或切换账号后调用 window.Askport.login(getIdentityToken),传入返回新令牌的函数。这些调用须在脚本加载完成后执行。logout() 清除旧聊天界面并保持登录验证模式,不转为匿名;产品后端也必须停止为已退出的登录会话签发令牌。已经签发的令牌最多仍有效 5 分钟。
已验证用户按“接入点 + 用户 ID + 产品”恢复未结束的会话,可跨浏览器;匿名历史不会自动合并。身份验证失败时不加载历史、不发送消息,也不降级为匿名。强制登录入口的独立聊天链接无法直接继承产品登录,请在已登录产品页面的嵌入组件中使用。
4. 可选:传递页面背景
组件自动读取当前页面 URL 和标题。URL 只保留域名、端口与路径,移除账号、密码、查询参数和片段;不会自动抓取网页。
在加载脚本前可设置初始背景:
<script>
window.AskportContext = {
version: '2.3.1',
platform: 'Web',
page_note: '项目文件上传页面,用户正在选择文件。'
};
</script>
脚本加载后,单页应用在路由和页面标题更新完成时调用:
window.Askport.setContext({
version: '2.3.1',
platform: 'Web',
page_note: '项目设置页面,用户正在配置通知。'
});
setContext 替换全部客户端补充背景,需要保留的字段须一并传入;URL 和标题自动重新读取。浏览器前进、后退和片段变化自动同步;使用 pushState 的路由需主动调用。页面变化不新建会话,下一条消息携带最新背景。
| 字段 | 长度上限 | 说明 |
|---|---|---|
product | 100 | 入口未固定产品时可指定 |
version | 100 | 产品版本,自由文本 |
platform | 100 | 平台 |
page_note | 1000 | 当前页面业务背景 |
page | 500 | 嵌入组件自动读取的 HTTP(S) URL |
page_title | 200 | 嵌入组件自动读取的页面标题 |
所有字段均为字符串。背景仅帮助理解问题,不代表用户身份或业务授权;不要放入密钥或敏感业务数据。
5. 前端 API
加载前通过全局变量配置;加载后通过 window.Askport 调用。
| 名称 | 用途 |
|---|---|
AskportSettings.getIdentityToken | 加载前设置;返回产品后端签发的新令牌 |
AskportContext | 加载前设置;初始页面背景 |
Askport.open() / close() | 打开或隐藏聊天窗口,便于自定义客服按钮;关闭不结束会话、不退出登录 |
Askport.login(getToken) | 重新登录或切换账号后传入令牌回调 |
Askport.logout() | 产品退出登录时清除聊天界面,保持登录验证模式 |
Askport.setContext(context) | 替换客户端补充背景 |
6. 本地验证与排查
- 启动本地 Askport 服务,打开
http://localhost:8000管理接入点。 - 在本地产品页面使用
http://localhost:8000/widget.js,替换入口标识。页面通过 HTTP 服务打开,不使用file://。若配置了嵌入来源,加入产品实际来源,例如http://localhost:5173,端口必须一致;留空时检查全局WIDGET_ALLOWED_ORIGINS。 - 匿名入口发送消息并刷新,确认能继续会话;用无痕窗口确认不会看到原窗口历史。在客服工作台确认接收到消息。AI 回复还需要可用的模型配置与 worker。
- 登录入口分别验证未登录、用户 A、用户 B、退出登录,确认未登录被阻断、账号历史隔离、退出后旧界面清除。令牌接口使用产品自身的登录会话。
- 切换产品页面后发送一条消息,在客服工作台确认页面标题、地址与背景已更新。
| 现象 | 检查 |
|---|---|
| 登录后仍提示身份失败 | 入口标识与 aud、两端密钥、用户 ID 类型、令牌有效期和服务器时间 |
/api/support-token 返回 404 / 401 | 产品是否实现此接口,当前产品登录会话是否有效 |
| 组件被浏览器拒绝嵌入 | 入口及全局允许来源;填写完整来源如 https://app.example.com,不含路径 |
| 直接打开聊天链接要求登录 | 在已配置令牌回调的产品嵌入页面测试 |
| AI 不回复或消息不更新 | web / worker / Redis 是否正常;检查服务日志与部署配置 |
生产环境使用 HTTPS。