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

Apple IAP「You're All Set」提示不固定显示问题求助

Apple IAP「You're All Set」提示随机不显示问题排查

问题描述

所有购买流程均成功完成:StoreKit 2返回的购买/升级数据正常,App Store Server API也能向服务器正常推送交易通知,但「You're All Set」系统提示会无规律地不显示。

  • 正常流程:提示弹出,点击OK后才会回到subscribe()调用、打印交易ID并关闭视图控制器;
  • 异常流程:交易完成后直接返回交易ID并关闭控制器,从未弹出提示。

相关代码

核心购买函数

func purchase(_ product: Product, appaccounttoken: UUID) async throws -> Transaction? {
    // Begin purchasing the `Product` the user selects.
    let result = try await product.purchase(options: [.appAccountToken(appaccounttoken)])

    switch result {
        case .success(let verification):
            // Check whether the transaction is verified. If it isn't,
            // this function rethrows the verification error.
            let transaction = try checkverified(verification)

            // The transaction is verified. Deliver content to the user.
            await updatecustomerproductstatus()

            // Always finish a transaction.
            await transaction.finish()

            return transaction


        case .userCancelled, .pending:
            return nil

        default:
            return nil
    }
}

调用链

// 第一层调用
if let transaction = try await self.purchase(product, appaccounttoken: uuid) {
    return transaction.id
}

// 第二层调用
if let transactionid = try await Store.store.subscribe(id: productid, owner: self.owner) {
    print("transaction: \(transactionid)")
    self.presentingViewController?.dismiss(animated: true)
}

可能原因及解决方向

1. 交易finish()时机过早

「You're All Set」是StoreKit的系统弹窗,依赖交易的未完成状态触发。如果在系统弹出提示前就调用transaction.finish(),会直接标记交易为已完成,系统便不会再展示提示。

解决方式:
将transaction.finish()的调用从purchase函数的.success分支中移除,改用Transaction.updates监听交易状态,待系统完成提示展示后再处理finish操作:

func purchase(_ product: Product, appaccounttoken: UUID) async throws -> Transaction? {
    let result = try await product.purchase(options: [.appAccountToken(appaccounttoken)])

    switch result {
        case .success(let verification):
            let transaction = try checkverified(verification)
            await updatecustomerproductstatus()
            // 暂不调用finish(),交给Transaction.updates处理
            return transaction
        case .userCancelled, .pending:
            return nil
        default:
            return nil
    }
}

// 在Store类中启动交易监听
func startObservingTransactions() {
    Task {
        for await verificationResult in Transaction.updates {
            do {
                let transaction = try checkverified(verificationResult)
                guard !transaction.isFinished else { continue }
                await updatecustomerproductstatus()
                await transaction.finish()
            } catch {
                print("Transaction verification failed: \(error)")
            }
        }
    }
}

2. 视图控制器关闭时机冲突

获取交易ID后立即调用dismiss(animated: true),可能会干扰系统弹窗的加载——弹窗依附于当前视图层级,控制器被提前关闭会导致弹窗无法正常展示。

解决方式:
将视图控制器的关闭操作延迟到交易完全处理完成后,通过回调机制实现:

// 在Store类中添加完成回调
var onTransactionCompleted: ((String) -> Void)?

// 在Transaction.updates处理完交易后触发回调
await transaction.finish()
onTransactionCompleted?(transaction.id.uuidString)

// 界面层修改调用逻辑
Store.store.onTransactionCompleted = { [weak self] transactionid in
    print("transaction: \(transactionid)")
    self?.presentingViewController?.dismiss(animated: true)
}

// 调用subscribe时不再直接处理关闭
_ = try await Store.store.subscribe(id: productid, owner: self.owner)

3. 重复交易处理

如果代码中存在其他监听交易的逻辑(比如额外的Transaction.updates订阅),且提前调用了finish(),会导致当前流程中的交易已被标记为完成,系统不再展示提示。

解决方式:
检查所有交易处理逻辑,确保同一交易只会被finish()一次,可通过transaction.isFinished状态判断过滤重复操作。

4. StoreKit内部状态异常

极少数情况下,StoreKit的内部缓存、网络波动可能导致状态不一致,引发提示未触发。

解决方式:

  • 测试时切换网络环境(WiFi/蜂窝数据);
  • 重置设备的App Store缓存(设置→App Store→退出登录后重新登录);
  • 确保使用最新版本的Xcode和iOS系统测试。

内容的提问来源于stack exchange,提问作者Kenny Wyland

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.24 09:07:10