gpt4 book ai didi

ios - 应用内购买消耗品自动恢复

转载 作者:可可西里 更新时间:2023-11-01 03:42:58 27 4
gpt4 key购买 nike

我正在执行我的第一次应用内购买,一个奇怪的行为是正在恢复消耗品而不是创建新交易。

我已经关注教程 https://www.raywenderlich.com/122144/in-app-purchase-tutorial

我发现这是一种优雅的方法。

这是我的 StoreKit 助手:

import StoreKit

public typealias ProductIdentifier = String

public typealias ProductsRequestCompletionHandler = (_ success: Bool, _ products: [SKProduct]?) -> ()



open class IAPHelper : NSObject {
fileprivate let productIdentifiers: Set<ProductIdentifier>
fileprivate var purchasedProductIdentifiers: Set<ProductIdentifier> = Set()
fileprivate var productsRequest: SKProductsRequest?
fileprivate var productsRequestCompletionHandler: ProductsRequestCompletionHandler?

static let IAPHelperPurchaseNotification = "IAPHelperPurchaseNotification"

public init(productIds: Set<ProductIdentifier>) {
productIdentifiers = productIds
super.init()
SKPaymentQueue.default().add(self)
}
}

// MARK: - StoreKit API

extension IAPHelper {

public func requestProducts(_ completionHandler: @escaping ProductsRequestCompletionHandler) {
productsRequest?.cancel()
productsRequestCompletionHandler = completionHandler

productsRequest = SKProductsRequest(productIdentifiers: productIdentifiers)
productsRequest!.delegate = self
productsRequest!.start()
}

public func buyProduct(_ product: SKProduct) {
print("Buying \(product.productIdentifier)...")
let payment = SKPayment(product: product)
SKPaymentQueue.default().add(payment)
}

public func isProductPurchased(_ productIdentifier: ProductIdentifier) -> Bool {
return purchasedProductIdentifiers.contains(productIdentifier)
}

public class func canMakePayments() -> Bool {
return SKPaymentQueue.canMakePayments()
}

public func restorePurchases() {
SKPaymentQueue.default().restoreCompletedTransactions()
}
}

// MARK: - SKProductsRequestDelegate

extension IAPHelper: SKProductsRequestDelegate {

public func productsRequest(_ request: SKProductsRequest, didReceive response: SKProductsResponse) {
print("Loaded list of products...")
let products = response.products
productsRequestCompletionHandler?(true, products)
clearRequestAndHandler()

for p in products {
print("Found product: \(p.productIdentifier) \(p.localizedTitle) \(p.price.floatValue)")
}
}

public func request(_ request: SKRequest, didFailWithError error: Error) {
print("Failed to load list of products.")
print("Error: \(error.localizedDescription)")
productsRequestCompletionHandler?(false, nil)
clearRequestAndHandler()
}

private func clearRequestAndHandler() {
productsRequest = nil
productsRequestCompletionHandler = nil
}
}

// MARK: - SKPaymentTransactionObserver

extension IAPHelper: SKPaymentTransactionObserver {

public func paymentQueue(_ queue: SKPaymentQueue, updatedTransactions transactions: [SKPaymentTransaction]) {
for transaction in transactions {
switch (transaction.transactionState) {
case .purchased:
complete(transaction: transaction)
break
case .failed:
fail(transaction: transaction)
break
case .restored:
restore(transaction: transaction)
break
case .deferred:
break
case .purchasing:
break
}
}
}

private func complete(transaction: SKPaymentTransaction) {
print("complete...")
validateReceipt()
deliverPurchaseNotificationFor(identifier: transaction.payment.productIdentifier)
SKPaymentQueue.default().finishTransaction(transaction)
}

private func restore(transaction: SKPaymentTransaction) {
guard let productIdentifier = transaction.original?.payment.productIdentifier else { return }

print("restore... \(productIdentifier)")
deliverPurchaseNotificationFor(identifier: productIdentifier)
SKPaymentQueue.default().finishTransaction(transaction)
}

private func fail(transaction: SKPaymentTransaction) {
print("fail...")
if let transactionError = transaction.error as? NSError {
if transactionError.code != SKError.paymentCancelled.rawValue {
print("Transaction Error: \(transaction.error?.localizedDescription)")
}
}

SKPaymentQueue.default().finishTransaction(transaction)
}

private func deliverPurchaseNotificationFor(identifier: String?) {
guard let identifier = identifier else { return }

purchasedProductIdentifiers.insert(identifier)
UserDefaults.standard.set(true, forKey: identifier)
UserDefaults.standard.synchronize()
NotificationCenter.default.post(name: NSNotification.Name(rawValue: IAPHelper.IAPHelperPurchaseNotification), object: identifier)
}
}

我可以购买一次,第二次它会自动恢复:

This In-App purchase has already been bought. It will be restored for free

当我收到此消息时,没有调用任何 IAPHelper 方法。

我的 iTunes 显示它是消耗品:

[1]: /image/sPy

即使卸载应用程序,购买的应用程序仍会恢复。

它真的看起来像一个 Apple 错误,因为我的第一次测试我可以在没有这条消息的情况下购买 2..3 次。

如果不是bug,我该如何避免这种情况?

最佳答案

对于那些陷入这种愚蠢情况的人,这里有一些 WA 和解决方案:

queue.finishTransaction(transaction)

重要提示:在您的paymentQueue 方法中完成交易:

public func paymentQueue(_ queue: SKPaymentQueue, updatedTransactions transactions: [SKPaymentTransaction]) {
for transaction in transactions {
switch (transaction.transactionState) {
case .purchased:
complete(transaction: transaction)
queue.finishTransaction(transaction)
break
case .failed:
fail(transaction: transaction)
queue.finishTransaction(transaction)
break
case .restored:
restore(transaction: transaction)
queue.finishTransaction(transaction)
break
case .deferred:
break
case .purchasing:
break
}
}
}

这样可以避免这种情况。

如果您已经坚持使用它,这里是解决方法,仅用于测试目的!

    for transaction in SKPaymentQueue.default().transactions {
print(transaction)
SKPaymentQueue.default().finishTransaction(transaction)
}

您可以将它放在一个临时按钮上,并在测试时一键清除所有交易。

至少今天它救了我的命。

关于ios - 应用内购买消耗品自动恢复,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43789286/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com