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:
parent
ba56b2385e
commit
f1ef89ef55
|
|
@ -102,14 +102,13 @@ final class FeishuAuthService {
|
||||||
var request = URLRequest(url: url)
|
var request = URLRequest(url: url)
|
||||||
request.httpMethod = "POST"
|
request.httpMethod = "POST"
|
||||||
request.setValue("application/json; charset=utf-8", forHTTPHeaderField: "Content-Type")
|
request.setValue("application/json; charset=utf-8", forHTTPHeaderField: "Content-Type")
|
||||||
request.httpBody = try JSONEncoder().encode([
|
let body: [String: String] = ["app_id": appId, "app_secret": appSecret]
|
||||||
"app_id": appId,
|
request.httpBody = try JSONEncoder().encode(body)
|
||||||
"app_secret": appSecret
|
|
||||||
])
|
|
||||||
|
|
||||||
let response: FeishuAPIResponse<TenantAccessTokenData> = try await send(request)
|
// This endpoint returns code/msg/tenant_access_token/expire all at top level
|
||||||
guard let data = response.data else {
|
let data: TenantAccessTokenData = try await send(request)
|
||||||
throw FeishuError.apiError(code: response.code, message: response.msg)
|
guard data.code == 0 else {
|
||||||
|
throw FeishuError.apiError(code: data.code, message: data.msg)
|
||||||
}
|
}
|
||||||
|
|
||||||
cachedTenantToken = data.tenantAccessToken
|
cachedTenantToken = data.tenantAccessToken
|
||||||
|
|
|
||||||
|
|
@ -40,10 +40,14 @@ struct OAuthTokenData: Decodable {
|
||||||
}
|
}
|
||||||
|
|
||||||
struct TenantAccessTokenData: Decodable {
|
struct TenantAccessTokenData: Decodable {
|
||||||
|
let code: Int
|
||||||
|
let msg: String
|
||||||
let tenantAccessToken: String
|
let tenantAccessToken: String
|
||||||
let expire: Int
|
let expire: Int
|
||||||
|
|
||||||
enum CodingKeys: String, CodingKey {
|
enum CodingKeys: String, CodingKey {
|
||||||
|
case code
|
||||||
|
case msg
|
||||||
case tenantAccessToken = "tenant_access_token"
|
case tenantAccessToken = "tenant_access_token"
|
||||||
case expire
|
case expire
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue