In App Purchases:购买后给用户购买的物品

In App Purchases: Give User purchased item after purchase

这是一个由两部分组成的问题,相互关联,不值得单独提问

第一个问题

所以我刚刚在 youtube here 上完成了关于应用内购买的指导教程,他主要介绍了实际支付和购买物品的恢复等。

但我真正需要的是他没有涵盖的一件事是一种实际向买家(在我的例子中是游戏硬币)购买的物品的方法

这是包含所有购买功能和其他内容的文件

import Foundation
import StoreKit

class IAPService: NSObject {

    private override init() {}
    static let shared = IAPService()

    var products = [SKProduct]()
    var paymentQueue = SKPaymentQueue.default()

func getProducts() {
    let products: Set = [IAPProduct.StackOfCoins.rawValue,
                         IAPProduct.PileOfCoins.rawValue,
                         IAPProduct.BoxOfCoins.rawValue,
                         IAPProduct.MountainOfCoins.rawValue,
                         IAPProduct.ContainerOfCoins.rawValue]
    let request = SKProductsRequest(productIdentifiers: products)
    request.delegate = self
    request.start()

    paymentQueue.add(self)
}

    func purchase(product: IAPProduct) {
        guard let productToPurchase = products.filter({ [=10=].productIdentifier == product.rawValue }).first else { return }
        let payment = SKPayment(product: productToPurchase)
        paymentQueue.add(payment)


    }
}
extension IAPService: SKProductsRequestDelegate {
    func productsRequest(_ request: SKProductsRequest, didReceive response: SKProductsResponse) {
        self.products = response.products
        print(response.products)
        for product in response.products {
            print(product.localizedDescription)
        }
    }
}
extension IAPService: SKPaymentTransactionObserver {
    func paymentQueue(_ queue: SKPaymentQueue, updatedTransactions transactions: [SKPaymentTransaction]) {
        for transaction in transactions {
            print(transaction.transactionState.status(), transaction.payment.productIdentifier)
            switch transaction.transactionState {
            case .purchasing: break
            default: queue.finishTransaction(transaction)
            }
        }
    }
}
extension SKPaymentTransactionState {
    func status() -> String {
        switch self {
        case .deferred: return "deferred"
        case .failed: return "failed"
        case .purchased: return "purchased"
        case .purchasing: return "purchasing"
        case .restored: return "restored"
        }
    }
}

这是存储我的产品 ID 的第二个文件

import Foundation
//crappy duck is the name of my game i am developing and these here represent increasing values of coins the user can buy

enum IAPProduct: String {
    case StackOfCoins = "com.HucksCorp.Crappy-duck.StackOfCoins"
    case PileOfCoins = "com.HucksCorp.Crappy-duck.PileOfCoins"
    case BoxOfCoins = "com.HucksCorp.Crappy-duck.BoxOfCoins"
    case MountainOfCoins = "com.HucksCorp.Crappy-duck.MountainOfCoins"
    case ContainerOfCoins = "com.HucksCorp.Crappy-duck.ContainerOfCoins"

}

它工作正常,我可以连接并访问我的待售产品(游戏币)等等,但我不知道如何更改它,以便它根据他正在购买的商品

这是我用来让用户实际购买东西的方法

这是在集合视图中

func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
    if indexPath.item == 0 {
        IAPService.shared.pruchase(product: .StackOfCoins)
    }
    if indexPath.item == 1 {
        IAPService.shared.purchase(product: .PileOfCoins)
    }
    if indexPath.item == 2 {
        IAPService.shared.purchase(product: .BoxOfCoins)
    }
    if indexPath.item == 3 {
        IAPService.shared.purchase(product: .MountainOfCoins)
    }
    if indexPath.item == 4 {
        IAPService.shared.purchase(product: .ContainerOfCoins)
    }
}

第二题

我将值 Coins 存储在 UserDefaults 中,而在我之前的一个问题中有人警告我,将可购买的产品存储在 UserDefaults

什么是 UserDefaults 的第二个选项,我可以通过应用内购买和游戏内购买产品访问、添加和减去它

总结

以防我的问题不清楚(如果他们不让我知道以便我可以编辑)

我的第一个问题是如何在用户购买后将其提供给用户

我的第二个问题是 Coins 的 userDefaults 值的另一个选项,它比 UserDefaults

更安全

updatedTransactions 中的开关中添加另一个案例:

switch transaction.transactionState {
    case .purchased:
        let coinsValue = generateValue(transaction.payment.productIdentifier)
        //add a call to your function here
        break;
    case .purchasing: break
    default: queue.finishTransaction(transaction)
}

然后调用您在这种情况下添加硬币的方法,相对于购买的产品。

这是从标识符中获取 int 的方法:

private func generateValue(_ identifier: String) -> Int
{
    switch identifier {
        case "com.HucksCorp.Crappy-duck.StackOfCoins":
            return 1
        case "com.HucksCorp.Crappy-duck.PileOfCoins":
            return 2
        /// etc..
        default:
            return 0
    }
}

关于硬币存储,您可以将它们同步到文件中,存储在钥匙串中或使用服务器端存储,这可能是最好的选择。