我在警报视图中显示IAP选项,这是我用来执行此操作的代码:
paidAlert.addAction(UIAlertAction(title: "Purchase", style: UIAlertAction.Style.default, handler: { (action) in
IAPHandler.shared.purchaseMyProduct(index: 0)
}))
paidAlert.addAction(UIAlertAction(title: "Restore", style: UIAlertAction.Style.default, handler: { (action) in
IAPHandler.shared.restorePurchase()
}))
paidAlert.addAction(UIAlertAction(title: "Cancel", style: UIAlertAction.Style.cancel, handler: { (action) in
}))
我在另一个Swift文件中处理实际的IAP,该文件发布在这里:
import UIKit
import StoreKit
enum IAPHandlerAlertType{
case disabled
case restored
case purchased
func message() -> String{
switch self {
case .disabled:
let notificationFeedbackGenerator = UINotificationFeedbackGenerator()
notificationFeedbackGenerator.prepare()
notificationFeedbackGenerator.notificationOccurred(.error)
return "Purchases are disabled on your device."
case .restored:
let notificationFeedbackGenerator = UINotificationFeedbackGenerator()
notificationFeedbackGenerator.prepare()
notificationFeedbackGenerator.notificationOccurred(.success)
return "Unlimited strategies have been successfully unlocked. You can restore this purchase using this Apple ID on other devices."
case .purchased:
let notificationFeedbackGenerator = UINotificationFeedbackGenerator()
notificationFeedbackGenerator.prepare()
notificationFeedbackGenerator.notificationOccurred(.success)
return "Unlimited strategies have been successfully unlocked. You can restore this purchase using this Apple ID on other devices."
}
}
}
class IAPHandler: NSObject {
static let shared = IAPHandler()
let NON_CONSUMABLE_PURCHASE_PRODUCT_ID = "com.isaranjha.opc.fullversion"
fileprivate var productID = ""
fileprivate var productsRequest = SKProductsRequest()
fileprivate var iapProducts = [SKProduct]()
var purchaseStatusBlock: ((IAPHandlerAlertType) -> Void)?
// MARK: - MAKE PURCHASE OF A PRODUCT
func canMakePurchases() -> Bool { return SKPaymentQueue.canMakePayments() }
func purchaseMyProduct(index: Int){
if iapProducts.count == 0 { return }
if self.canMakePurchases() {
let product = iapProducts[index]
let payment = SKPayment(product: product)
SKPaymentQueue.default().add(self)
SKPaymentQueue.default().add(payment)
print("PRODUCT TO PURCHASE: \(product.productIdentifier)")
productID = product.productIdentifier
} else {
purchaseStatusBlock?(.disabled)
}
}
// MARK: - RESTORE PURCHASE
func restorePurchase(){
SKPaymentQueue.default().add(self)
SKPaymentQueue.default().restoreCompletedTransactions()
}
// MARK: - FETCH AVAILABLE IAP PRODUCTS
func fetchAvailableProducts(){
// Put here your IAP Products ID's
let productIdentifiers = NSSet(objects: NON_CONSUMABLE_PURCHASE_PRODUCT_ID
)
productsRequest = SKProductsRequest(productIdentifiers: productIdentifiers as! Set<String>)
productsRequest.delegate = self
productsRequest.start()
}
}
extension IAPHandler: SKProductsRequestDelegate, SKPaymentTransactionObserver{
// MARK: - REQUEST IAP PRODUCTS
func productsRequest (_ request:SKProductsRequest, didReceive response:SKProductsResponse) {
if (response.products.count > 0) {
iapProducts = response.products
for product in iapProducts{
let numberFormatter = NumberFormatter()
numberFormatter.formatterBehavior = .behavior10_4
numberFormatter.numberStyle = .currency
numberFormatter.locale = product.priceLocale
let price1Str = numberFormatter.string(from: product.price)
print(product.localizedDescription + "\nfor just \(price1Str!)")
}
}
}
func paymentQueueRestoreCompletedTransactionsFinished(_ queue: SKPaymentQueue) {
purchaseStatusBlock?(.restored)
}
// MARK:- IAP PAYMENT QUEUE
func paymentQueue(_ queue: SKPaymentQueue, updatedTransactions transactions: [SKPaymentTransaction]) {
for transaction:AnyObject in transactions {
if let trans = transaction as? SKPaymentTransaction {
switch trans.transactionState {
case .purchased:
print("purchased")
SKPaymentQueue.default().finishTransaction(transaction as! SKPaymentTransaction)
purchaseStatusBlock?(.purchased)
break
case .failed:
print("failed")
SKPaymentQueue.default().finishTransaction(transaction as! SKPaymentTransaction)
break
case .restored:
print("restored")
SKPaymentQueue.default().finishTransaction(transaction as! SKPaymentTransaction)
break
default: break
}}}
}
}
但是,多个用户(但不是所有用户)报告说他们能够购买IAP罚款(向他们收取费用和所有费用),但他们没有得到我所输入的任何确认信息(警告说购买成功等),因此未购买任何功能。我们唯一能找到的解决方法是用户需要从多任务处理中终止该应用程序,再次获得初始IAP购买警报,但选择“还原”,然后相应地提示并解锁功能。
我无法弄清楚问题出在哪里,但是看到“恢复”功能似乎如何工作,我假设我在实际购买中缺少一些东西,可以正确调用该案例并显示警报。
感谢您的帮助。