测试StoreKit“验证:证书已吊销”异常行为的问题咨询
我在App Store的ProductView里设置了两个switch语句:上方的storeProductTask内的switch负责捕获加载错误,下方的onInAppPurchaseCompletion完成处理程序捕获其他StoreKit错误。用StoreKit配置文件测试「验证:证书已吊销」错误场景时,点击内购按钮后先弹出“You're all set”提示,确定后又出现“Certificate Revoked”提示,出现购买成功但实际失败的矛盾情况。
通过断点观察控制台,流程为:进入onInAppPurchaseCompletion的.success分支(#1),接着进入内部verificationResult的.success分支(#2),最终走到.unverified分支(#3,证书已吊销)。
想问两个问题:
- switch case的顺序是否会影响结果?
- 有没有办法阻止“You're all set”提示出现?
相关代码
VStack { ProductView(id: productID) .productViewStyle(.large) .storeProductTask(for: productID, action: { state in print(state) switch state { case .failure(let error): self.error = .error(error) case .loading: break case .unavailable: self.error = .error(NSError(domain: "Store is unavailable", code: 0, userInfo: nil)) case .success(let success): break @unknown default: break } }) } .padding() .onInAppPurchaseCompletion { product, result in switch result { case .success(let verificationResult): // #1 // Check whether the JWS passes StoreKit verification. switch verificationResult { // #2 case .success(let t): switch t { case .verified(let transaction): if transaction.productType == product.type, transaction.productID == productID { if transaction.revocationDate == nil, transaction.revocationReason == nil { purchaseState = true await transaction.finish() } else { } } else { // invalid product } case .unverified(_, let error): // #3 self.error = .error(error) } case .userCancelled: // user tapped x button break case .pending: // purchase options: interrupted purchase enabled break @unknown default: break } case .failure(let error): self.error = .error(error) } }
问题解答
1. switch case顺序是否影响结果?
不会。你当前的switch分支顺序是合理的,枚举值的匹配是精确匹配,和分支顺序无关——只要每个分支的case定义正确,StoreKit会把对应状态精准分发到对应的分支里。你遇到的流程是因为onInAppPurchaseCompletion的.success仅代表购买支付环节完成,后续的交易验证环节才发现证书问题,这是两个不同阶段的状态,和switch顺序无关。
2. 如何阻止“You're all set”提示?
这个提示是ProductView自带的默认成功弹窗,触发条件是storeProductTask进入.success状态——但这个.success仅代表产品加载/购买发起流程成功,不代表交易验证通过。要去掉默认提示,需要在storeProductTask的.success分支里手动拦截状态,不让系统显示默认弹窗:
修改storeProductTask的switch分支:
.storeProductTask(for: productID, action: { state in print(state) switch state { case .failure(let error): self.error = .error(error) case .loading: break case .unavailable: self.error = .error(NSError(domain: "Store is unavailable", code: 0, userInfo: nil)) case .success(let success): // 手动处理成功状态,拦截系统默认弹窗 if case .purchased = success { // 此处留空或仅记录日志,不触发任何弹窗 } @unknown default: break } })
同时,你需要在onInAppPurchaseCompletion的.verified分支里,自己实现真正的购买成功提示逻辑——比如手动弹出自定义的“购买成功”弹窗。这样就能确保只有验证通过的交易才会显示成功提示,证书吊销这类验证失败的场景不会触发错误的成功弹窗。
额外优化:在.unverified分支里建议调用transaction.finish()(如果有对应的transaction实例),避免StoreKit重复触发该交易的回调。
内容的提问来源于stack exchange,提问作者Galen Smith

