App Store 审核 2.1(性能-应用完整性):订阅页无限加载的修复指南(收据验证与前端超时)
目录
App Store 审核 2.1(性能-应用完整性):订阅页无限加载的修复指南(收据验证与前端超时)
审核反馈常见问题:订阅页加载无限转圈,多由收据验证流程不当和前端请求无超时导致。
一、问题描述(来源于 Guideline 2.1)
- 现象:订阅页加载不结束,体验不佳。
- 根因:
- 后端收据验证只请求了生产环境,遇到沙盒收据未正确切换(需处理 21007)。
- 前端网络请求无超时/无错误提示,一直等待导致“无限加载”。
二、修复方案总览
- 后端:收据验证采用“先生产、后沙盒”的回退策略,并设置超时。
- 前端:请求设置合理超时,加载态可见、失败可重试,避免无限等待。
- 平台:确保 App Store Connect 付费相关协议已签署。
三、后端:收据验证逻辑(Python/Requests 示例)
import requests
APPLE_PRODUCTION_URL = "https://buy.itunes.apple.com/verifyReceipt"
APPLE_SANDBOX_URL = "https://sandbox.itunes.apple.com/verifyReceipt"
TIMEOUT_SECONDS = 10
def validate_receipt(receipt_data: str, password: str) -> dict:
"""先请求生产环境,如遇 21007 再请求沙盒;全程设置超时。"""
payload = {
"receipt-data": receipt_data,
"password": password,
"exclude-old-transactions": True,
}
# 1) 先生产
resp = requests.post(APPLE_PRODUCTION_URL, json=payload, timeout=TIMEOUT_SECONDS)
result = resp.json()
# 2) 21007 -> 切沙盒
if result.get("status") == 21007:
resp = requests.post(APPLE_SANDBOX_URL, json=payload, timeout=TIMEOUT_SECONDS)
result = resp.json()
return result
要点:
- 处理
status == 21007
(沙盒收据误发生产)。 - 每个请求设置超时(例如 10s),避免后端“等死”。
- 日志中打印
status
与关键字段,便于排障。
四、前端:SwiftUI 订阅页请求(超时 + 可重试)
import SwiftUI
struct SubscriptionView: View {
@State private var isLoading = false
@State private var errorMessage: String?
private let timeout: TimeInterval = 10
func validateReceipt(receiptData: String, password: String) {
isLoading = true
errorMessage = nil
guard let url = URL(string: "https://your-backend.com/validate-receipt") else {
errorMessage = "无效的请求地址"
return
}
var request = URLRequest(url: url)
request.httpMethod = "POST"
request.timeoutInterval = timeout
request.setValue("application/json", forHTTPHeaderField: "Content-Type")
let body: [String: Any] = [
"receipt_data": receiptData,
"password": password
]
request.httpBody = try? JSONSerialization.data(withJSONObject: body)
URLSession.shared.dataTask(with: request) { data, response, error in
DispatchQueue.main.async {
isLoading = false
if let error = error {
errorMessage = "网络错误: \(error.localizedDescription)"
return
}
guard let data = data else {
errorMessage = "未收到数据"
return
}
// TODO: 解析 data 并根据业务更新 UI
print("receipt validation response: \(data)")
}
}.resume()
}
var body: some View {
VStack(spacing: 12) {
if isLoading { ProgressView("验证中…") }
if let errorMessage = errorMessage {
Text(errorMessage).foregroundColor(.red)
Button("重试") {
// 根据业务重新调用 validateReceipt
}
}
// 订阅页面 UI …
}
.padding()
}
}
要点:
URLRequest.timeoutInterval
限制等待时间,失败后给出提示并支持重试。- 加载态可见(
ProgressView
),避免界面“静默卡住”。
五、App Store Connect 检查
- 账号持有人需在 App Store Connect > 商务 中接受《付费应用协议》。
- 使用与审核同环境设备(如 iPadOS 18.5)测试验证流程。
六、自测清单
- 后端对 21007 正常回退沙盒;有超时设置与错误日志。
- 前端请求超时 ≤ 10–15s;失败有可见错误提示;支持重试。
- 订阅页有清晰加载与失败状态,不出现“无限转圈”。
- 协议已签署、测试通过,再提交审核。
总结
- 后端“先生产后沙盒 + 超时”是关键;
- 前端“加载态 + 超时 + 异常提示/重试”可避免无限等待;
- 完成平台侧协议与设备实测,提升过审成功率。