我的应用内置了应用内购买(我遵循此tutorial),购买功能正常。但是,当我在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)
}
}
感谢。
答案 0 :(得分:5)
除了安德鲁所说的(关于仅适用于生产环境的促销代码),您的“应用购买”处理机制似乎可能存在问题。
您应该在AppDelegate中初始化您的购买处理对象,以便它立即收到待处理的购买和刚刚创建的购买,(或者在这种情况下,当代码被兑换时)
如果您查看此处显示的示例:
你实际上正在做苹果不推荐的事情。
而是在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
促销代码只能在生产商店进行测试。
所以,为了测试它们:
最后,开发人员的帖子还警告我们,在应用程序获得批准后,您必须等待48小时才能开始运行代码。
因此,如果按照上述步骤操作后,您的应用就无法按预期运行。然后,当Apple向您发送“购买成功”通知时,您遇到的问题是您的应用程序没有“准备就绪”。因此,为什么你应该遵循本答案第一部分所描述的指导原则。 (关于启动应用程序后立即初始化事务监听器)
答案 1 :(得分:1)
促销代码仅适用于生产环境。
如果您想确保IAP在没有实际应用程序发布的情况下工作,那么当应用程序处于"等待开发人员发布时,请使用促销代码"国家(审查后)。一个应用程序促销代码用于安装应用程序,另一个用于测试IAP。有时,为所有Apple服务器分发数据可能需要额外的时间(最多2天)。
答案 2 :(得分:0)
@Eatton在其他thread上提供了非常有用的信息。我只想总结一下处理消费品促销代码的解决方案。
I。您应该使用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
}
}
}
II。如果要在任何ViewController中调用逻辑,请考虑使用NotificationCenter,将代码放在 //解锁内容
下III。如何测试?
在iOS 11版本中,Apple直接在App Store中为promoting your in-app purchase引入了一项新功能。
首先添加处理程序:
#if DEBUG
SwiftyStoreKit.shouldAddStorePaymentHandler = { payment, product in
return true
}
#endif
然后在Mac上编写以下URL,然后将其拖放到iOS设备上,然后在Safari中打开。
itms-services://?action=purchaseIntent&bundleId=com.example.app&productIdentifier=product_name
然后将触发SwiftyStoreKit.completeTransactions()
中AppDelegate
的完成块。
这也可以用于测试促销代码的兑换,因为URL请求创建了一个待处理的事务并将其添加到队列中。确保为产品发布删除此代码。
希望这会有所帮助!