恢复购买是在用户根本没有购买过的情况下恢复购买

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

我正在使用 Storekit 在我的应用程序中实现应用内购买。现在已经上线了。我已经实施了非消耗品购买来删除广告。现在的问题是,即使新用户点击恢复购买,它也会成功恢复不应该的购买。由于缺乏测试设备,我无法对其进行调试,但我已要求多人下载该应用程序并恢复购买,他们已成功转换为高级版。

下面是我正在使用的代码:

enum IAPHandlerAlertType {
    case initialize
    case setProductIds
    case disabled
    case restored
    case purchased
    case failed
    case error
    case restoreFailed
    
    var message: String{
        switch self {
        case .error: return "An error occured"
        case .initialize: return ""
        case .setProductIds: return "Product ids not set, call setProductIds method!"
        case .disabled: return "Purchases are disabled in your device!"
        case .restored: return "You've successfully restored your purchase!"
        case .purchased: return "You've successfully bought this purchase!"
        case .failed: return "Failed to buy this purchase!"
        case .restoreFailed: return "Failed to restore this purchase!"
        }
    }
}


class IAPManager: NSObject {
    
    //MARK:- Shared Object
    //MARK:-
    static let shared = IAPManager()
    private override init() { }
    
    //MARK:- Properties
    //MARK:- Private
    fileprivate var productIds = ["com.identifier.appName.removeAds"]
    fileprivate var productID = ""
    fileprivate var productsRequest = SKProductsRequest()
    fileprivate var fetchProductComplition: (([SKProduct])->Void)?
    
    fileprivate var productToPurchase: SKProduct?
    var purchaseProductComplition: ((IAPHandlerAlertType, Error?)->Void)?
    
    //MARK:- Public
    var isLogEnabled: Bool = true
    
    //MARK:- Methods
    //MARK:- Public
    
    //Set Product Ids
    func setProductIds(ids: [String]) {
        self.productIds = ids
    }

    //MAKE PURCHASE OF A PRODUCT
    func canMakePurchases() -> Bool {  return SKPaymentQueue.canMakePayments()  }
    
    func purchase(product: SKProduct, completion: @escaping ((IAPHandlerAlertType, Error?) -> Void)) {
        
        self.purchaseProductComplition = completion
        self.productToPurchase = product

        if self.canMakePurchases() {
            let payment = SKPayment(product: product)
            SKPaymentQueue.default().add(self)
            SKPaymentQueue.default().add(payment)
            
            log("PRODUCT TO PURCHASE: \(product.productIdentifier)")
            productID = product.productIdentifier
        }
        else {
            completion(IAPHandlerAlertType.disabled, nil)
        }
    }
    
    // RESTORE PURCHASE
    func restorePurchase(){
        SKPaymentQueue.default().add(self)
        SKPaymentQueue.default().restoreCompletedTransactions()
    }
    
    
    // FETCH AVAILABLE IAP PRODUCTS
    func fetchAvailableProducts(completion: @escaping (([SKProduct])->Void)){
        
        self.fetchProductComplition = completion
        // Put here your IAP Products ID's
        if self.productIds.isEmpty {
            log(IAPHandlerAlertType.setProductIds.message)
            fatalError(IAPHandlerAlertType.setProductIds.message)
        }
        else {
            productsRequest = SKProductsRequest(productIdentifiers: Set(self.productIds))
            productsRequest.delegate = self
            productsRequest.start()
        }
    }
    
    //MARK:- Private
    fileprivate func log <T> (_ object: T) {
        if isLogEnabled {
            NSLog("\(object)")
        }
    }
}

//MARK:- Product Request Delegate and Payment Transaction Methods

extension IAPManager: SKProductsRequestDelegate, SKPaymentTransactionObserver {
    
    func productsRequest (_ request:SKProductsRequest, didReceive response:SKProductsResponse) {
        
        if let completion = self.fetchProductComplition {
            completion(response.products)
        }
    }
    
    func request(_ request: SKRequest, didFailWithError error: Error) {
        if let completion = self.fetchProductComplition {
            completion([])
        }
    }
    
    func paymentQueueRestoreCompletedTransactionsFinished(_ queue: SKPaymentQueue) {
        if let completion = self.purchaseProductComplition {
            completion(IAPHandlerAlertType.restored, nil)
        }
    }
    func paymentQueue(_ queue: SKPaymentQueue, restoreCompletedTransactionsFailedWithError error: Error) {
        if let completion = self.purchaseProductComplition {
            completion(IAPHandlerAlertType.restoreFailed, error)
        }
    }
    
    func paymentQueue(_ queue: SKPaymentQueue, updatedTransactions transactions: [SKPaymentTransaction]) {
        for transaction:AnyObject in transactions {
            if let trans = transaction as? SKPaymentTransaction {
                switch trans.transactionState {
                case .purchased:
                    log("Product purchase done")
                    SKPaymentQueue.default().finishTransaction(trans)
                    if let completion = self.purchaseProductComplition {
                        completion(IAPHandlerAlertType.purchased, nil)
                    }
                    break
                    
                case .failed:
                    log("Product purchase failed")
                    SKPaymentQueue.default().finishTransaction(trans)
                    if let completion = self.purchaseProductComplition {
                        completion(IAPHandlerAlertType.failed, trans.error)
                    }
                    break
                case .restored:
                    log("Product restored")
                    SKPaymentQueue.default().finishTransaction(trans)
                    if let completion = self.purchaseProductComplition {
                        completion(IAPHandlerAlertType.restored, nil)
                    }
                    break
                    
                default: break
                }
            }
        }
    }
}

视图模型

func restoreAction() {
            Spinner.start()
            IAPManager.shared.fetchAvailableProducts { products in
                if products.count > 0 {
                    IAPManager.shared.restorePurchase()
                    IAPManager.shared.purchaseProductComplition = { [self] result, error in
                        self.handlePurchaseRestoreResult(result: result, error: error)
                        Spinner.stop()
                    }
                } else {
                    Spinner.stop()
                }
            }
        }
    
    
     func handlePurchaseRestoreResult(result: IAPHandlerAlertType, error: Error?) {
            if error != nil {
                showAlert = .init(id: .error)
                return
            }
            switch result {
            case .disabled:
                showAlert = .init(id: .disabled)
            case .purchased:
                Defaults.isPremiumPurchased = true
                Defaults.totalCoins += 1000
                isPremiumPurchased = 1
                break
            case .restored:
                Defaults.isPremiumPurchased = true
                isPremiumPurchased = 1
                break
            case .failed:
                showAlert = .init(id: .failed)
            default:
                break
            }
        }

我在这里做错了什么吗?

ios swift swiftui in-app-purchase storekit
1个回答
0
投票

在向用户授予访问权限之前,您似乎缺少 validatePurchase 函数。在为用户设置购买状态之前,最好验证用户是否确实从您的数据库购买了溢价。以下是在向用户分发溢价之前您想要的功能的最小实现:-

func isPremiumUserOrNot() {
    guard let receiptURL = Bundle.main.appStoreReceiptURL else {
        // Handle no receipt case
        return
    }
    
    // API call to check if the user is in your DB for receiptURL and return the status
}

添加此内容应该可以解决您遇到的问题。

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