因内购问题遭Apple审核拒绝,寻求技术排查协助
内购审核拒绝问题解决方案
一、"Remove Ads"按钮无响应/审核无购买提示问题
沙箱测试正常但审核翻车,大概率是这几个点出问题:
- 按钮交互未生效:用SKSpriteNode做按钮时,必须把
isUserInteractionEnabled设为true,还要确认该节点没被其他图层遮挡。给按钮设个更高的zPosition,或者在点击事件里加个打印日志,验证点击是否真的触发。 - 内购产品状态异常:去App Store Connect检查对应的内购项目,是否处于「Ready to Submit」或「Approved」状态,有没有设置地域限制——审核账号所在地区必须能访问该内购。另外,调用
requestPurchase()前,得确保产品已加载完成,且产品ID和后台完全匹配。 - 未处理旧交易:审核环境中可能存在未完成的旧交易,导致新购买请求被阻塞。按钮点击时先执行
try await AppStore.current.restoreTransactions(),处理完未完成交易再发起购买。 - 异步调用线程错误:StoreKit2的API是异步的,
requestPurchase()必须在主线程调用。如果按钮点击事件在SpriteKit后台线程触发,要切换到主线程执行:DispatchQueue.main.async { Task { do { try await AppStore.current.requestPurchase(product) } catch { print("购买请求失败: \(error)") } } }
二、收据验证问题(无服务器场景)
StoreKit2确实支持设备端验证,无需服务器,但要符合审核要求:
- 设备端验证实现:可以用
AppStoreReceipt或直接调用Apple的验证端点,审核时用production端点,沙箱测试用sandbox。示例代码:func validateReceipt() async throws { guard let receiptURL = Bundle.main.appStoreReceiptURL, FileManager.default.fileExists(atPath: receiptURL.path) else { throw NSError(domain: "ReceiptError", code: 1, userInfo: [NSLocalizedDescriptionKey: "找不到收据"]) } let receiptData = try Data(contentsOf: receiptURL) let base64Receipt = receiptData.base64EncodedString() let url = URL(string: "https://buy.itunes.apple.com/verifyReceipt")! var request = URLRequest(url: url) request.httpMethod = "POST" request.httpBody = try JSONSerialization.data(withJSONObject: ["receipt-data": base64Receipt]) let (data, response) = try await URLSession.shared.data(for: request) guard let httpResponse = response as? HTTPURLResponse, httpResponse.statusCode == 200 else { throw NSError(domain: "ReceiptError", code: 2, userInfo: [NSLocalizedDescriptionKey: "验证请求失败"]) } let result = try JSONSerialization.jsonObject(with: data) as? [String: Any] guard let status = result?["status"] as? Int, status == 0 else { throw NSError(domain: "ReceiptError", code: 3, userInfo: [NSLocalizedDescriptionKey: "收据无效"]) } // 验证通过,存储本地标记 UserDefaults.standard.set(true, forKey: "AdsRemoved") } - 审核要求核心:Apple要求服务器处理,可能是因为你直接信任本地的「已购买」标记,未做收据验证。必须保证每次启动App、购买完成后都重新验证收据,不能仅依赖本地存储的状态。
三、InAppPurchaseManager代码通用排查点
不管代码具体实现如何,先检查这几个关键:
- 产品加载逻辑:
products数组是否正确加载到目标产品,产品ID与App Store Connect完全一致? - 交易监听:App启动时是否立即设置
AppStore.current.transactionListener = self,且TransactionListener的所有方法都已实现?购买成功、失败、待处理的情况都要处理到位。 - 错误捕获:调用
requestPurchase()时的错误是否被捕获?比如用户取消购买、网络问题等场景,要给出明确反馈,避免按钮点击后无响应。 - 权限配置:确认App的内购权限已在App Store Connect开启,Info.plist中无缺失的必要配置。
内容的提问来源于stack exchange,提问作者Cade Williams
相关产品推荐
相关产品推荐

