fix: tenant_access_token response is flat, not wrapped in data key

The /auth/v3/tenant_access_token/internal endpoint, like the OAuth token
endpoints, returns code, msg, tenant_access_token, and expire at the top
level of the JSON response — NOT nested under a 'data' key.

FeishuAPIResponse<TenantAccessTokenData> decoded successfully but with
data=nil (extra fields silently ignored by JSONDecoder). The guard then
threw FeishuError.apiError(code: 0, message: 'ok') — appearing to succeed
but always failing. This blocked the subsequent OAuth token exchange call.

- Added code/msg fields to TenantAccessTokenData
- tenantAccessToken() now decodes TenantAccessTokenData directly and
  checks data.code != 0 instead of going through FeishuAPIResponse

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
tigerenwork 2026-06-29 00:28:39 +08:00
parent ba56b2385e
commit f1ef89ef55
2 changed files with 10 additions and 7 deletions

View File

@ -102,14 +102,13 @@ final class FeishuAuthService {
var request = URLRequest(url: url)
request.httpMethod = "POST"
request.setValue("application/json; charset=utf-8", forHTTPHeaderField: "Content-Type")
request.httpBody = try JSONEncoder().encode([
"app_id": appId,
"app_secret": appSecret
])
let body: [String: String] = ["app_id": appId, "app_secret": appSecret]
request.httpBody = try JSONEncoder().encode(body)
let response: FeishuAPIResponse<TenantAccessTokenData> = try await send(request)
guard let data = response.data else {
throw FeishuError.apiError(code: response.code, message: response.msg)
// This endpoint returns code/msg/tenant_access_token/expire all at top level
let data: TenantAccessTokenData = try await send(request)
guard data.code == 0 else {
throw FeishuError.apiError(code: data.code, message: data.msg)
}
cachedTenantToken = data.tenantAccessToken

View File

@ -40,10 +40,14 @@ struct OAuthTokenData: Decodable {
}
struct TenantAccessTokenData: Decodable {
let code: Int
let msg: String
let tenantAccessToken: String
let expire: Int
enum CodingKeys: String, CodingKey {
case code
case msg
case tenantAccessToken = "tenant_access_token"
case expire
}