跳到主要内容

验证 Login Ticket

验证 Login Ticket 并获取用户信息。

接口说明​

属性值
请求方式POST
请求路径/im-user/api/v1/oauth/ticket/verify
鉴权方式Bot Token
重要

此接口由第三方应用后端调用,需要使用 Bot Token 进行鉴权。请确保在服务端调用,不要在前端暴露 Bot Token。

请求头​

Authorization: Bearer {botToken}
Content-Type: application/json

请求参数​

参数类型必填说明
ticketstring是登录票据(从 URL 参数中获取)

请求示例​

curl -X POST 'https://api.im.example.com/im-user/api/v1/oauth/ticket/verify' \
-H 'Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...' \
-H 'Content-Type: application/json' \
-d '{
"ticket": "lt_550e8400e29b41d4a716446655440000"
}'

响应参数​

参数类型说明
imUserIdnumberIM 用户 ID
imUserNamestringIM 用户名称
imUserPhonestringIM 用户手机号(脱敏,如 138****1234)
imUserPhoneFullstringIM 用户手机号(完整,仅在应用有相应权限时返回)
imUserAvatarstringIM 用户头像 URL
imWorkspaceIdnumberIM 工作空间 ID
imWorkspaceNamestringIM 工作空间名称

响应示例​

成功响应​

{
"code": 200,
"data": {
"imUserId": 123,
"imUserName": "张三",
"imUserPhone": "138****1234",
"imUserPhoneFull": "13812341234",
"imUserAvatar": "https://cdn.example.com/avatar/123.jpg",
"imWorkspaceId": 1001,
"imWorkspaceName": "测试工作空间"
}
}

失败响应​

{
"code": 400,
"msg": "Login Ticket 无效或已过期"
}

错误码​

错误码说明解决方案
400ticket不能为空确保传递了 ticket 参数
400Login Ticket 无效或已过期Ticket 已使用或超过 5 分钟,请重新从 IM 打开应用
401缺少 Bot Token确保在请求头中传递了 Authorization
401Bot Token 无效或已过期检查 Bot Token 是否正确,或重新安装应用
401需要使用 Bot Token 调用此接口确保使用 Bot Token 而非 User Token
401Bot Token 信息不完整Bot Token 格式错误,请重新安装应用

Java 调用示例​

import cn.hutool.http.HttpRequest;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;

import java.util.HashMap;
import java.util.Map;

public class ImApiClient {

private final String apiBaseUrl;

public ImApiClient(String apiBaseUrl) {
this.apiBaseUrl = apiBaseUrl;
}

/**
* 验证 Login Ticket
*
* @param botToken Bot Token
* @param ticket 登录票据
* @return 用户信息
*/
public TicketVerifyResponse verifyTicket(String botToken, String ticket) {
Map<String, Object> body = new HashMap<>();
body.put("ticket", ticket);

String response = HttpRequest.post(apiBaseUrl + "/im-user/api/v1/oauth/ticket/verify")
.header("Authorization", "Bearer " + botToken)
.header("Content-Type", "application/json")
.body(JSONUtil.toJsonStr(body))
.execute()
.body();

JSONObject json = JSONUtil.parseObj(response);
if (json.getInt("code") != 200) {
throw new RuntimeException("验证 Ticket 失败: " + json.getStr("msg"));
}

return json.getBean("data", TicketVerifyResponse.class);
}
}

Python 调用示例​

import requests

class ImApiClient:
def __init__(self, api_base_url: str):
self.api_base_url = api_base_url

def verify_ticket(self, bot_token: str, ticket: str) -> dict:
"""验证 Login Ticket"""
url = f"{self.api_base_url}/im-user/api/v1/oauth/ticket/verify"

headers = {
"Authorization": f"Bearer {bot_token}",
"Content-Type": "application/json"
}

payload = {"ticket": ticket}

response = requests.post(url, json=payload, headers=headers)
result = response.json()

if result.get("code") != 200:
raise Exception(f"验证 Ticket 失败: {result.get('msg')}")

return result.get("data")

使用场景​

验证 Ticket 后,根据返回的用户信息查询绑定关系:

@GetMapping("/api/im/sso/entry")
public String handleSsoEntry(
@RequestParam("ticket") String ticket,
@RequestParam("workspace_id") Long workspaceId
) {
// 1. 获取 Bot Token
WorkspaceBinding binding = workspaceBindingService.getByWorkspaceId(workspaceId);
if (binding == null) {
return "redirect:/error?msg=应用未安装";
}
String botToken = binding.getBotToken();

// 2. 验证 Ticket
TicketVerifyResponse ticketInfo = imApiClient.verifyTicket(botToken, ticket);

// 3. 查询用户绑定关系
ImBinding userBinding = imBindingService.getByImUser(
ticketInfo.getImUserId().toString(),
workspaceId
);

if (userBinding != null) {
// 已绑定,生成登录态
User user = userService.getById(userBinding.getUserId());
String token = jwtService.generateToken(user);
return "redirect:/home?token=" + token;
} else {
// 未绑定,跳转到绑定页面
return "redirect:/im/bind?im_user_id=" + ticketInfo.getImUserId()
+ "&im_user_name=" + URLEncoder.encode(ticketInfo.getImUserName(), "UTF-8");
}
}

下一步​