一颗大白菜
一颗大白菜
  • 发布:48 分钟前
  • 更新:48 分钟前
  • 阅读:9

iOS 上传 ipa 报 -22938 排查记:Apple 封了密码登录,改用 App Store Connect 官方 Build Uploads API

分类:uni-app
iOS

现象

从 10 月 28 日开始,用 ios-uploader(以及各种转运脚本)往 App Store Connect 上传 ipa,全部失败,报错:

Found Bundle ID "xxx", Version 125 (1.2.5).  
Unexpected token 'S', "Sign in wi"... is not valid JSON

HBuilderX 云打包出来的包是正常的,问题在上传环节。

排查过程

第一步:确认不是账号/密码问题

把同一个 App 专用密码拿去请求 Apple 的 CalDAV 服务,认证直接通过(HTTP 207)。再把这段密码拿去请求上传认证接口 contentdelivery.itunes.apple.com 的 authenticateForSession,返回的却是纯文本而不是 JSON:

Sign in with the app-specific password you generated. If you forgot the  
app-specific password or need to create a new one, go to account.apple.com. (-22938)

同一个密码、同一个账号,一个通一个不通 —— 说明密码是好的。

第二步:确认是服务端封了这条通道

试了所有能试的变体,全部返回同一句话:

  • 明文 / gzip 压缩请求体
  • HTTP/1.1 与 HTTP/2
  • JSON-RPC 端点与 SOAP /ws/ 端点
  • 换 User-Agent(iTMSTransporter/4.2.0、4.3.1、Transporter/5.0)
  • 改用 App Store Connect API 密钥签出的 JWT 塞进 myacinfo cookie 或 Bearer 头
  • 备用域名 contentdelivery02

连"不存在的方法名"都返回同样的登录提示 —— 说明请求根本没进到后端服务,在网关层(响应头里能看到 Server: daiquiri/5、实例标签 26HOTFIX47)就被拦了。

结论:Apple 在网关层关闭了「Apple ID + App 专用密码」这条上传登录通道,不是客户端改个参数能绕过去的。

解决方案:走官方 Build Uploads API

Apple 有一个公开文档化的 App Store Connect API,里面的 Build Uploads 资源就是干上传这件事的,认证走 API 密钥(JWT),完全不碰上面那条被封的通道:

POST  /v1/buildUploads            登记一次构建上传(版本号 / build 号 / platform)  
POST  /v1/buildUploadFiles        拿到对象存储的预签名分块上传 URL  
PUT   <presigned-url>             按分块上传 ipa(每块 5MB)  
PATCH /v1/buildUploadFiles/{id}   标记 uploaded=true  
→ Apple 自动解析出 build,TestFlight / 提审可用

注意:assetType 的有效值是 ASSET / ASSET_DESCRIPTION / ASSET_SPI,不是 IPA。

准备

  1. App Store Connect → 用户和访问 → 集成 → App Store Connect API → 生成密钥(角色选 App Manager 或更高),下载 .p8(只能下载一次),记下 Key ID 和 Issuer ID
  2. 拿到 App 的数字 ID(App Store Connect 后台 URL 里 apps/ 后面那串数字)

用现成工具

我把整个流程写成了一个零依赖的 Node 脚本(只用内置模块,Windows / macOS / Linux 都能跑),已开源:

GitHub: xxhshenqi/asc-ipa-uploader
Gitee: xiaoxianghui/asc-ipa-uploader

先装上(无需 npm 账号,2 秒,全局命令就是 asc-ipa-uploader):

npm i -g https://github.com/xxhshenqi/asc-ipa-uploader/archive/refs/heads/master.tar.gz

用法:

# 先查 App ID  
asc-ipa-uploader --key ./AuthKey_XXXX.p8 --key-id XXXXXXXXXX \  
  --issuer <ISSUER_ID> --list-apps  

# 上传(版本号 = CFBundleShortVersionString,build 号 = CFBundleVersion)  
asc-ipa-uploader --key ./AuthKey_XXXX.p8 --key-id XXXXXXXXXX \  
  --issuer <ISSUER_ID> --app <APP_ID> --ipa ./xxx.ipa --version 1.2.5 --build 125  

# 上传完顺手把版本记录建好、build 关联上(之后去后台填更新说明提审即可)  
asc-ipa-uploader ... --release

脚本做了几件省心的事:上传前先查同 build 号是否已存在(避免白传)、API 调用遇到新建密钥的瞬时 401 自动重试、分块上传带进度、传完轮询到 build 状态变 VALID 才退出。

实测一个 17MB 的包,两三分钟传完并转 VALID。

一点提醒

  • .p8 私钥不要提交到仓库,也不要发群里;用环境变量传路径更安全(支持 ASC_KEY_PATH / ASC_KEY_ID / ASC_ISSUER / ASC_APP_ID)
  • Apple 不允许重复的 build 号,同一个包要重传得先升 build 号
  • 想继续用 Mac + 官方 Transporter 的,不受这次变更影响;受影响的是没有 Mac、靠第三方工具传包的场景

如果这个工具帮你解决了问题,欢迎 star;有 bug 或想加功能直接提 issue。

0 赞 关注 分享

要回复文章请先登录或注册