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

如何获取消耗型SKProduct重复购买的AppStore响应并提示用户

解决消耗型内购重复购买无响应问题

针对你遇到的重复点击购买按钮后无StoreKit响应、无法提示用户的问题,可按以下步骤处理:

1. 发起购买前拦截重复请求

用户重复点击按钮时,可能同一商品的未完成交易仍在支付队列中,此时重复添加支付请求会被StoreKit静默忽略。所以要在发起购买前先做本地校验:

func purchaseProduct(product: SKProduct) {
    // 过滤队列中未完成的同商品交易
    let pendingTransactions = SKPaymentQueue.default().transactions.filter {
        guard let pid = $0.payment.productIdentifier else { return false }
        return pid == product.productIdentifier &&
               ![$0.transactionState == .purchased, $0.transactionState == .failed, $0.transactionState == .restored].contains(true)
    }
    
    if !pendingTransactions.isEmpty {
        showAlert(message: "购买请求正在处理中,请稍候")
        return
    }
    
    // 正常发起购买
    let payment = SKPayment(product: product)
    SKPaymentQueue.default().add(payment)
}

2. 修复交易处理逻辑的核心问题

你的代码中未调用finishTransaction,这会导致已完成的交易一直滞留在队列中,后续购买请求可能被静默拦截。同时要修正.purchasing状态的打印错误,并完善错误处理:

func paymentQueue(_ queue: SKPaymentQueue, updatedTransactions transactions: [SKPaymentTransaction]) {
    for transaction in transactions {
        switch transaction.transactionState {
        case .purchased:
            print("购买成功")
            // 这里添加你的业务逻辑:标记商品消耗、同步服务器等
            completePurchase(transaction: transaction)
            // 必须调用finish,否则交易永远留在队列
            queue.finishTransaction(transaction)
            
        case .restored:
            print("已恢复购买")
            queue.finishTransaction(transaction)
            
        case .failed:
            print("购买失败")
            if let skError = transaction.error as? SKError {
                handlePurchaseError(error: skError)
            }
            queue.finishTransaction(transaction)
            
        case .deferred:
            print("购买等待家长审批")
            
        case .purchasing:
            print("正在处理购买请求") // 修正你之前的打印错误
            
        @unknown default:
            fatalError()
        }
    }
}

// 处理SK错误,给出对应提示
func handlePurchaseError(error: SKError) {
    var message = "购买失败"
    switch error.code {
    case .paymentCancelled:
        message = "你已取消购买"
    case .paymentInvalid:
        message = "支付请求无效"
    case .paymentNotAllowed:
        message = "你的账户不允许进行支付"
    default:
        message += ": \(error.localizedDescription)"
    }
    showAlert(message: message)
}

3. 关于Firebase的提示说明

Firebase Analytics的Purchase is a duplicate and will not be reported是其自身的去重逻辑——当短时间内检测到同一用户重复上报同一商品的购买事件时,会自动跳过重复上报,这和StoreKit的响应无关,无需额外处理。

4. 沙盒环境注意事项

消耗型内购在沙盒环境下允许重复购买,但如果交易未被正确finish,或者你的业务逻辑未标记商品已消耗(比如服务器未同步状态),可能导致后续购买无响应,务必确保交易完成后及时清理队列和更新业务状态。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.04 00:10:23