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

测试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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.12 15:05:05