19

我的应用程序内置了应用程序内购买(我遵循了本教程),购买功能有效。但是,当我在 App Store 中将促销代码兑换为应用内购买产品之一时,我的应用没有响应。即使 App Store 说产品已成功兑换,我的应用程序也没有响应。

是否有人测试过您的应用是否可以处理促销代码?你介意分享解决方案吗?

我从这个开始:

override func viewDidLoad() {
    NotificationCenter.default.addObserver(self,
        selector: #selector(applicationDidBecomeActive(notification:)),
        name: NSNotification.Name.UIApplicationDidBecomeActive,
        object: nil
    )
}

func applicationDidBecomeActive(notification: NSNotification){
    let store = IAPHealper()

    //what needs to be put here?
}


extension IAPHelper: SKPaymentTransactionObserver {

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

    fileprivate func completeTransaction(_ transaction: SKPaymentTransaction) {
        print("completeTransaction...")
        deliverPurchaseNotificatioForIdentifier(transaction.payment.productIdentifier)
        defaultQueue.finishTransaction(transaction)
        purchaseCompletionHandler?(true, transaction)
    }

    fileprivate func restoreTransaction(_ transaction: SKPaymentTransaction) {
        guard let productIdentifier = transaction.original?.payment.productIdentifier else { return }

        print("restoreTransaction... \(productIdentifier)")
        deliverPurchaseNotificatioForIdentifier(productIdentifier)
        defaultQueue.finishTransaction(transaction)
    }

    fileprivate func failedTransaction(_ transaction: SKPaymentTransaction) {
        print("failedTransaction...")

        if transaction.error!._code != SKError.paymentCancelled.rawValue {
            print("Transaction Error: \(String(describing: transaction.error?.localizedDescription))")
            purchaseCompletionHandler?(false, transaction)
        }

        defaultQueue.finishTransaction(transaction)
    }

    fileprivate func deliverPurchaseNotificatioForIdentifier(_ identifier: String?) {
        guard let identifier = identifier else { return }
        purchasedProductIdentifiers.insert(identifier)
        //NSNotificationCenter.defaultCenter().postNotificationName(IAPHelper.IAPHelperPurchaseNotification, object: identifier)
    }

    public func paymentQueue(_ queue: SKPaymentQueue, removedTransactions transactions: [SKPaymentTransaction]){
        print("Removed from queue.")
        print(transactions)
    }
}

谢谢。

4

3 回答 3

5

除了 Andrew 所说的(关于仅适用于生产环境的促销代码)之外,您似乎可能对“应用购买”处理机制有疑问。

您应该在 AppDelegate 中初始化您的购买处理对象,以便它立即接收待处理的购买和刚刚创建的购买,(或者在这种情况下,当兑换代码时)

如果您检查此处显示的示例:

https://developer.apple.com/library/content/technotes/tn2387/_index.html#//apple_ref/doc/uid/DTS40014795-CH1-BEST_PRACTICES-ADD_A_TRANSACTION_QUEUE_OBSERVER_AT_APPLICATION_LAUNCH

你实际上是在做苹果不推荐的事情。

而是在您的 AppDelegate 中添加 StoreKit 观察者:

class AppDelegate: UIResponder, UIApplicationDelegate {
                           ....
    // Attach an observer to the payment queue.
    func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
        // Attach an observer to the payment queue.
        SKPaymentQueue.default().add(your_observer)
        return true
    }

    // Called when the application is about to terminate.
    func applicationWillTerminate(_ application: UIApplication) {
       // Remove the observer.
       SKPaymentQueue.default().remove(your_observer)
    }

    // OTHER STUFF...

}

因此,您实际上可能错过了您的应用收到购买的时间。

顺便说一句,您已经有一个“In App Purchases”帮助器对象(IAPHealper)。您需要做的就是让您的 AppDelegate 为其存储一个变量,并在“didFinishLaunchingWithOptions”方法中对其进行实例化。

就像是:

class AppDelegate: UIResponder, UIApplicationDelegate {

    var store : IAPHealper;
                           ....
    // Attach an observer to the payment queue.
    func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {

        store = IAPHelper();

        return true
    }

    // OTHER STUFF...

}

编辑:(将所有信息保留在堆栈溢出中)

根据 Apple 员工的回复: https ://forums.developer.apple.com/message/204476#204476

促销代码只能在生产商店中测试。

因此,为了测试它们:

  1. 提交您的应用以供应用审核。
  2. 将应用程序的发布日期设置在未来某个时间,以便应用程序审核批准该应用程序后,普通用户无法使用该应用程序。
  3. 使用应用促销代码安装应用
  4. 使用应用内促销代码。

最后,开发者的帖子还警告我们,在 App 获得批准后,您必须等待 48 小时,代码才能开始工作。


因此,如果按照上述步骤操作后,您的应用程序的行为与预期不符。那么您面临的问题是,当苹果向您发送“购买成功”通知时,您的应用还没有“准备好”。因此,为什么您应该遵循本答案第一部分中描述的指南。(关于在您的应用程序启动后立即初始化您的事务监听器)

于 2017-06-19T02:17:50.710 回答
1

@Eatton在另一个线程上提供了非常有用的信息。我只是想总结一下处理消耗品促销代码兑换的解决方案。

一、你应该使用SwiftyStoreKit,并将这段代码放在 AppDelegate 中:

SwiftyStoreKit.completeTransactions(atomically: true) { purchases in
    for purchase in purchases {
        switch purchase.transaction.transactionState {
        case .purchased, .restored: 
            if purchase.needsFinishTransaction {
                SwiftyStoreKit.finishTransaction(purchase.transaction)
            }
            // Unlock content
            self.unlockIAPContent(productID: purchase.productId)
        case .failed, .purchasing, .deferred:
            break // do nothing
        }
    }
}

二、如果要调用任意 ViewController 中的逻辑,请考虑使用NotificationCenter,将代码放在//Unlock content下

三、如何测试它?

在 iOS 11 版本中,Apple 引入了一项新功能,可直接在 App Store中推广您的应用内购买。

首先添加处理程序:

#if DEBUG
SwiftyStoreKit.shouldAddStorePaymentHandler = { payment, product in
    return true
}
#endif

然后在您的 Mac 上编写以下 URL 并将其 AirDrop 到您的 iOS 设备并在 Safari 中打开它

itms-services://?action=purchaseIntent&bundleId=com.example.app&productIdentifier=product_name

然后将触发SwiftyStoreKit.completeTransactions()in your的完成块。AppDelegate

这也可用于测试促销代码兑换,因为 URL 请求会创建待处理的交易并将其添加到队列中。确保为您的产品版本删除此代码。

希望这可以帮助!

于 2018-11-05T20:53:38.607 回答
1

促销代码仅在生产环境中有效。

如果您想确保 IAP 在没有实际应用程序发布的情况下工作,请在应用程序处于“等待开发者发布”状态(审核后)时使用促销代码。一个应用程序促销代码用于安装应用程序,另一个用于测试 IAP。有时,为所有 Apple 服务器分发数据可能需要额外的时间(最多 2 天)。

来自官方开发论坛的回答

于 2017-06-15T14:45:12.400 回答