【发布时间】:2018-01-09 18:49:41
【问题描述】:
我已经玩了几天的应用内购买并发现了下一个问题(如果预期行为,请告诉我)。
我目前在 TestFlight 上有应用程序,而不是在 Apple Store。
我有一个用户可以购买的项目列表,当用户点击“购买”时,它会执行所有正常步骤:选择产品,然后我显示我的 AlertViewController 并确认购买,并在完成“提交”时AlertViewController 的操作我在我的 IAP Manager 中调用 buyProduct 。然后关于“取消/购买”的正常对话框出现在“确认您的应用内购买”对话框中,带有 [Environment: Sandbox] 等。
但是,当我点击“购买”时,我会被重定向到之前的视图控制器并且“一切就绪”。显示在上一个 View Controller 上,而不是我所在的那个。
如果 TestFlight 版本没问题 - 那么很好。如果这是我在 Apple Store 的行为,那么我需要修复它是很糟糕的。这是我的应用内购买经理:
class IAPManager: NSObject {
static let sharedInstance = IAPManager()
static let IAPManagerPurchaseNotification = "IAPManagerPurchaseNotification"
fileprivate var productsRequest: SKProductsRequest?
fileprivate var productsRequestCompletionHandler: ProductsRequestCompletionHandler?
func initialize() {
SKPaymentQueue.default().add(self)
}
func deinitialize() {
SKPaymentQueue.default().remove(self)
}
/// Request products from Apple Store.
/// - parameter products: IAPProduct to purchase.
func requestProduct(products: [IAPProduct], _ completionHandler: @escaping ProductsRequestCompletionHandler) {
productsRequest?.cancel()
productsRequestCompletionHandler = completionHandler
var productIdentifiers: Set<String> = Set<String>()
for product in products {
productIdentifiers.insert(product.rawValue)
}
productsRequest = SKProductsRequest(productIdentifiers: productIdentifiers)
productsRequest?.delegate = self
productsRequest?.start()
}
/// Does actual purchasing against Apple Store.
/// - parameter product: product that user wants to purchase.
func buyProduct(_ product: SKProduct) {
Log.info(message: "User \(UsersManager.sharedInstance.currentUserId) is purchasing \(product.productIdentifier)", sender: self)
let payment = SKPayment(product: product)
SKPaymentQueue.default().add(payment)
}
class func canMakePayments() -> Bool {
return SKPaymentQueue.canMakePayments()
}
/// Restores previously purchased non-consumable items.
func restorePurchases() {
SKPaymentQueue.default().restoreCompletedTransactions()
}
}
extension IAPManager: SKProductsRequestDelegate {
func productsRequest(_ request: SKProductsRequest, didReceive response: SKProductsResponse) {
Log.info(message: "Loaded list of products...", sender: self)
let products = response.products
productsRequestCompletionHandler?(true, products)
clearRequestAndHandler()
for p in products {
Log.info(message: "Found product: \(p.productIdentifier) \(p.localizedTitle) \(p.price.floatValue)", sender: self)
}
}
func request(_ request: SKRequest, didFailWithError error: Error) {
Log.error(message: "Failed to load list of products with error: \(error.localizedDescription)", sender: self)
productsRequestCompletionHandler?(false, nil)
clearRequestAndHandler()
}
private func clearRequestAndHandler() {
productsRequest = nil
productsRequestCompletionHandler = nil
}
}
extension IAPManager: SKPaymentTransactionObserver {
func paymentQueue(_ queue: SKPaymentQueue, updatedTransactions transactions: [SKPaymentTransaction]) {
for transaction in transactions {
switch (transaction.transactionState) {
case .purchased: complete(transaction: transaction)
case .failed: fail(transaction: transaction)
case .restored: restore(transaction: transaction)
case .deferred: Log.info(message: "Purchase is deffered", sender: self)
case .purchasing: Log.info(message: "Purchase is in progress", sender: self)
}
}
}
private func complete(transaction: SKPaymentTransaction) {
Log.info(message: "Purchase is completed.", sender: self)
deliverPurchaseNotificationFor(identifier: transaction.payment.productIdentifier)
SKPaymentQueue.default().finishTransaction(transaction)
}
private func restore(transaction: SKPaymentTransaction) {
guard let productIdentifier = transaction.original?.payment.productIdentifier else {
return
}
Log.info(message: "Purchase \(productIdentifier) is in restore state.", sender: self)
deliverPurchaseNotificationFor(identifier: productIdentifier)
SKPaymentQueue.default().finishTransaction(transaction)
}
private func fail(transaction: SKPaymentTransaction) {
Log.info(message: "Purchase is failed.", sender: self)
if let transactionError = transaction.error as NSError? {
if transactionError.code != SKError.paymentCancelled.rawValue {
Log.error(message: "Transaction Error: \(transactionError.localizedDescription)", sender: self)
}
}
SKPaymentQueue.default().finishTransaction(transaction)
}
private func deliverPurchaseNotificationFor(identifier: String?) {
guard let identifier = identifier else {
return
}
NotificationCenter.default.post(name: NSNotification.Name(rawValue: IAPManager.IAPManagerPurchaseNotification), object: identifier)
}
}
调用 IAPManager 的代码:
let alert = UIAlertController(title: "<Title>", message: "<Message>", preferredStyle: .alert)
IAPManager.sharedInstance.requestProduct(products: [product]) { success, products in
guard success, let products = products, !products.isEmpty else {
Log.error(message: "Error occured during product request.", sender: self)
return
}
let product = products[0]
let submit = UIAlertAction(title: "Ok", style: .default) { action in
IAPManager.sharedInstance.buyProduct(product)
}
let cancel = UIAlertAction(title: "No", style: .destructive, handler: nil)
alert.addAction(submit)
alert.addAction(cancel)
self.present(alert, animated: true, completion: nil)
}
【问题讨论】:
-
这不是一种常见的行为@Array,检查你的警报功能是他们编写的任何可以让你返回的代码
-
不,我更新了调用应用内购买管理器的代码
-
顺便说一句,问题自行消失了。也许这是由其他因素造成的。
标签: ios swift in-app-purchase