如何购买StoreKit会导致自动恢复-Swift

问题描述 投票:0回答:1

我的SKProductsRequestDelegate和SKPaymentTransactionObserver的设置几乎与StoreKit In-App Purchase Documentations中所述相同。

获取可用的SKProducts并购买非消耗性产品产品效果很好,我可以在func paymentQueue(_ queue: SKPaymentQueue, updatedTransactions transactions: [SKPaymentTransaction])中处理不同的交易状态。但是有一种情况我不知道如何处理。这种情况是当我尝试购买已经购买的物品时。然后,商店UI会告诉用户类似的信息:“此应用内购买已被购买。它将被还原,而无需支付额外费用。”]

when calling purchaseenter image description here

图片文字的粗略翻译:

  1. 确认应用内购买。提供您的密码以确认应用内购买删除应用内广告的费用为35瑞典克朗。
  2. 此应用内购买已被购买。无需额外费用即可恢复它。

[我的第一个假设是,应该调用.restored的情况,但事实并非如此。我已经浏览了几次文档,但无法弄清楚:,(。所以我的问题是:我在哪里可以处理此事件?

让我知道我是否可以以任何方式澄清这个问题。提前致谢! :)

我的StoreKit代码:

import Foundation
import StoreKit
import SwiftUI

class StoreHelper: NSObject, SKProductsRequestDelegate, SKPaymentTransactionObserver, ObservableObject {

    @Published var transactionState: [SKPaymentTransaction] = [SKPaymentTransaction]()
    static let shared = StoreHelper()

    func restore() {
        SKPaymentQueue.default().restoreCompletedTransactions()
    }

    //Initialize the store observer.
    private override init() {
        super.init()

        // create productsIDs.plist path
        guard let url = Bundle.main.url(forResource: "ProductIDs", withExtension: "plist") else { fatalError("Unable to resolve url for in the bundle.") }

        do {
            let data = try Data(contentsOf: url)
            if let productIdentifiers = try PropertyListSerialization.propertyList(from: data, options: .mutableContainersAndLeaves, format: nil) as? [String] {
                self.validate(productIdentifiers: productIdentifiers)
            }
        } catch let error as NSError {
            print("StoreObserver: \(error.localizedDescription)")
        }
    }

    // Keep a strong reference to the product request.
    var request: SKProductsRequest!
    func validate(productIdentifiers: [String]) {
        let productIdentifiers = Set(productIdentifiers)

        request = SKProductsRequest(productIdentifiers: productIdentifiers)
        request.delegate = self
        request.start()
    }

    @Published var prod = [StoreProduct]()
    var products = [SKProduct]()
    // SKProductsRequestDelegate protocol method.
    func productsRequest(_ request: SKProductsRequest, didReceive response: SKProductsResponse) {
        if !response.products.isEmpty {
            products = response.products

            // Adjusting published values must be done on the main thread...
            DispatchQueue.main.async {
                self.prod = self.products.map{
                    StoreProduct(id: $0.productIdentifier, name: $0.localizedTitle, price: $0.regularPrice!, product: $0)
                }
            }

        }

        for invalidIdentifier in response.invalidProductIdentifiers {
            // Handle any invalid product identifiers as appropriate.
        }
    }

    // MARK: - Buy Selected Product

    func buyProduct(product: SKProduct) {
        // Use the corresponding SKProduct object returned in the array from SKProductsRequest.
        let payment = SKMutablePayment(product: product)
        //        payment.quantity = 2

        SKPaymentQueue.default().add(payment)
        print("StoreObserver: ----> BUY ADDED")
    }

    // MARK: - PROCESS PAYMENT

    func paymentQueue(_ queue: SKPaymentQueue, updatedTransactions transactions: [SKPaymentTransaction]) {
        print("StoreObserver: -------------> QUEUE")

        for transaction in transactions {
            switch transaction.transactionState {
            // Call the appropriate custom method for the transaction state.
            case .purchasing: print("StoreObserver: InProgress \(transaction.payment.description)")
            case .deferred: print("StoreObserver: inProgress_deffered \(transaction.payment.description)")
            case .failed: print("StoreObserver: failed \(transaction.payment.description)") // pressing: cancel
            case .purchased:
                print("StoreObserver: complete! \(transaction.transactionIdentifier)")
            case .restored: print("StoreObserver: restored \(transaction.payment.productIdentifier)")
            // For debugging purposes.
            @unknown default: print("StoreObserver: Unexpected transaction state \(transaction.payment.description)")
            }
        }
    }

    func paymentQueueRestoreCompletedTransactionsFinished(_ queue: SKPaymentQueue) {
        print("StoreObserver: restoreCompletedTransactionsFinished \(queue.description)")
    }

    func paymentQueue(_ queue: SKPaymentQueue, restoreCompletedTransactionsFailedWithError error: Error) {
        print("StoreObserver: \(error)")
    }
}

extension SKProduct {
    /// - returns: The cost of the product formatted in the local currency.
    var regularPrice: String? {
        let formatter = NumberFormatter()
        formatter.numberStyle = .currency
        formatter.locale = self.priceLocale
        return formatter.string(from: self.price)
    }
}
swift in-app-purchase storekit
1个回答
0
投票

从Apple文档:https://developer.apple.com/documentation/storekit/in-app_purchase/offering_completing_and_restoring_in-app_purchases

如果您的应用销售非消耗性,可自动更新的订阅或不可更新的订阅产品,则必须为用户提供恢复它们的能力。在完成付款交易之前,请务必提供购买或恢复的内容。

因此,如果我对问题的理解正确,您可以在IAP屏幕中放置“恢复购买”按钮,这将解决您的问题。

有关还原应用内购买的文档,您可以找到here以及如何还原here

© www.soinside.com 2019 - 2024. All rights reserved.