This commit is contained in:
2026-03-06 13:51:25 +08:00
parent 43022b8ff6
commit 3ad6b05bf8
5 changed files with 218 additions and 2 deletions
+55
View File
@@ -18,6 +18,7 @@ class FeishuUtil
private const string APP_ACCESS_TOKEN_URL = 'https://open.feishu.cn/open-apis/auth/v3/tenant_access_token/internal';
private const string USER_ACCESS_TOKEN_URL = 'https://open.feishu.cn/open-apis/authen/v1/oidc/access_token';
private const string USER_INFO_URL = 'https://open.feishu.cn/open-apis/authen/v1/user_info';
private const string JSAPI_TICKET_URL = 'https://open.feishu.cn/open-apis/jssdk/ticket/get';
/**
* 获取 app_access_token
@@ -200,4 +201,58 @@ class FeishuUtil
$userAccessToken = self::getUserAccessToken($code, $appId);
return self::getUserInfo($userAccessToken);
}
/**
* 获取 jsapi_ticket(用于 JS API 鉴权)
*
* @param int $appId 飞书应用ID
* @return string jsapi_ticket
* @throws Exception
*/
public static function getJsapiTicket(int $appId): string
{
$cacheKey = "feishu:jsapi_ticket:{$appId}";
// 从缓存获取
if (isset(self::$tokenCache[$cacheKey]) && self::$tokenCache[$cacheKey]['expire'] > time()) {
return self::$tokenCache[$cacheKey]['ticket'];
}
$appAccessToken = self::getAppAccessToken($appId);
try {
$response = HttpClient::httpGet(
self::JSAPI_TICKET_URL,
[],
[
'Authorization: Bearer ' . $appAccessToken,
]
);
if ($response['code'] !== 0) {
$errorMsg = $response['msg'] ?? $response['message'] ?? '未知错误';
throw new Exception('获取 jsapi_ticket 失败: ' . $errorMsg);
}
if (!isset($response['data']['ticket'])) {
throw new Exception('响应中缺少 ticket: ' . json_encode($response));
}
$ticket = $response['data']['ticket'];
$expire = $response['data']['expire_in'] ?? 7200;
// 缓存 ticket(提前5分钟过期)
self::$tokenCache[$cacheKey] = [
'ticket' => $ticket,
'expire' => time() + $expire - 300,
];
error_log("✅ 获取 jsapi_ticket 成功: " . substr($ticket, 0, 30) . "...");
return $ticket;
} catch (Exception $e) {
error_log("❌ 获取 jsapi_ticket 失败: " . $e->getMessage());
throw $e;
}
}
}