You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Swift调用Google Reply to Reviews API返回401未认证错误如何解决

问题原因与修复方案

1. 核心逻辑错误:JWT用途错误

你自行生成的JWT是服务账号OAuth2流程的中间凭证,不能直接作为access_token调用Google API,需要先完成令牌交换步骤:

  • 用你生成的JWT向https://oauth2.googleapis.com/token发起POST请求,请求体格式为x-www-form-urlencoded,携带两个参数:
    • grant_type:固定值urn:ietf:params:oauth:grant-type:jwt-bearer
    • assertion:你生成的JWT字符串
  • 该接口返回的响应中会包含正式的access_token,有效期默认3600秒,只有这个令牌可以用于调用安卓开发者API。

2. 认证方式优化

拿到正式access_token后,建议放在HTTP请求头中传递,不要放在URL查询参数里,降低令牌泄露风险:

request.setValue("Bearer \(正式的access_token)", forHTTPHeaderField: "Authorization")

3. 额外配置检查项

  • 你使用的服务账号必须已在Google Play Console中被添加为用户,且授予了查看/回复评论的对应权限,否则认证通过后也会触发权限报错。
  • 签名JWT用的pem私钥必须是你在Google Cloud Console创建该服务账号时下载的官方密钥,不能使用自行生成的密钥,否则会触发签名校验失败。
  • JWT的有效期配置不能超过3600秒,你当前设置的1000秒符合要求。

核心逻辑修改示例

// 新增:用自签名JWT换取正式access_token
func exchangeJWTForAccessToken(jwt: String, completion: @escaping (String?) -> Void) {
    let url = URL(string: "https://oauth2.googleapis.com/token")!
    var request = URLRequest(url: url)
    request.httpMethod = "POST"
    request.setValue("application/x-www-form-urlencoded", forHTTPHeaderField: "Content-Type")
    let params = "grant_type=urn:ietf:params:oauth:grant-type:jwt-bearer&assertion=\(jwt)"
    request.httpBody = params.data(using: .utf8)
    
    let task = URLSession.shared.dataTask(with: request) { data, response, error in
        guard let data = data,
              let json = try? JSONSerialization.jsonObject(with: data) as? [String: Any],
              let accessToken = json["access_token"] as? String else {
            completion(nil)
            return
        }
        completion(accessToken)
    }
    task.resume()
}

// 修改获取评论的调用逻辑
override func viewDidLoad() {
    super.viewDidLoad()
    let auth = Authentication()
    guard let jwt = auth.generateJWT() else { return }
    // 先换令牌再调用API
    exchangeJWTForAccessToken(jwt: jwt) { accessToken in
        guard let token = accessToken else { return }
        self.retriveReviews(packageIdentifier: "<APP_PACKAGE>", auth: token)
    }
}

func retriveReviews(packageIdentifier: String, auth: String) {
    let url = URL(string: "https://www.googleapis.com/androidpublisher/v3/applications/\(packageIdentifier)/reviews")!
    var request = URLRequest(url: url)
    request.httpMethod = "GET"
    // 用请求头传认证信息
    request.setValue("Bearer \(auth)", forHTTPHeaderField: "Authorization")
    
    let task = URLSession.shared.dataTask(with: request) { data, response, error in
        guard let data = data else { return }
        print(String(data: data, encoding: .utf8)!)
    }
    task.resume()
}

内容的提问来源于stack exchange,提问作者ytpm

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.25 01:54:07