【发布时间】:2020-05-16 17:04:31
【问题描述】:
背景:我的应用程序从一组数组中提供了许多提示。 “包”确定可以打开哪些提示。您从默认包开始,然后可以为非消耗性 IAP 购买三个额外的包(packA、packB 和 packC)。
我的目标是让用户支付一次,然后就可以在他/她喜欢的任何时候访问这些包;但是,一旦沙盒用户进行了 IAP,就会弹出一个提示 “你已经购买了这个。你想再次免费获得它吗?”。我显然不希望每次用户选择一个包时都会弹出这个。有没有办法让购买成为永久使用,而不需要不断恢复购买?
以下是我当前的代码(匿名并简化为仅基本组件):
import UIKit
import QuartzCore
import StoreKit
class ViewController: UIViewController, SKPaymentTransactionObserver {
//MAIN SETUP SECTION XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
let productID = "com.domain.appName.additionalPackages"
let defaults = UserDefaults.standard
//I'm just putting "Various" here as a placeholder for my multiple buttons
@IBOutlet weak var (Various): UIButton!
override func viewDidLoad() {
super.viewDidLoad()
SKPaymentQueue.default().add(self)
//I don’t know if this actually does anything
func cleanUp() {
for transaction in SKPaymentQueue.default().transactions {
SKPaymentQueue.default().finishTransaction(transaction)
}
}
}
//PACK SELECTION SECTION XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
var packA = 2
var packB = 2
var packC = 2
var packsUnlocked = false
@IBAction func selectPackA(_ sender: UIButton) {
if packsUnlocked == false {
print("It's locked, ‘Pack A’ not enabled")
} else if packCounterA % 2 == 0 {
if SKPaymentQueue.canMakePayments() { // In App Purchase
let paymentRequest = SKMutablePayment()
paymentRequest.productIdentifier = productID
SKPaymentQueue.default().add(paymentRequest)
print("Initiating Transaction")
} else {
print("No Purchased")
}
promptProvider.includeA.toggle()
packCounterA += 1
} else {
promptProvider.includeA.toggle()
packCounterA += 1
}
}
@IBAction func selectPackB(_ sender: UIButton) {
if packsUnlocked == false {
print("It's locked, ‘Pack B’ not enabled")
} else if packCounterB % 2 == 0 {
if SKPaymentQueue.canMakePayments() { // In App Purchase
let paymentRequest = SKMutablePayment()
paymentRequest.productIdentifier = productID
SKPaymentQueue.default().add(paymentRequest)
print("Initiating Transaction")
} else {
print("No Purchased")
}
promptProvider.includeB.toggle()
packCounterB += 1
} else {
promptProvider.includeB.toggle()
packCounterB += 1
}
}
@IBAction func selectPackC(_ sender: UIButton) {
if packsUnlocked == false {
print("It's locked, ‘Pack C' not enabled")
} else if packCounterC % 2 == 0 {
if SKPaymentQueue.canMakePayments() { // In App Purchase
let paymentRequest = SKMutablePayment()
paymentRequest.productIdentifier = productID
SKPaymentQueue.default().add(paymentRequest)
print("Initiating Transaction")
} else {
print("No Purchased")
}
promptProvider.includeC.toggle()
packCounterC += 1
} else {
promptProvider.includeC.toggle()
packCounterC += 1
}
}
//TRANSACTION FINALIZATION SECTION XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
func paymentQueue(_ queue: SKPaymentQueue, updatedTransactions transactions: [SKPaymentTransaction]) {
for transaction in transactions {
guard
transaction.transactionState != .purchasing,
transaction.transactionState != .deferred
else {
//Optionally provide user feedback for pending or processing transactions
continue
}
if transaction.transactionState == .purchased || transaction.transactionState == .restored {
print("Transaction Successful")
packsUnlocked = true
//new
defaults.set(true, forKey: "Purchase Pack")
UserDefaults.standard.synchronize()
} else if transaction.transactionState == .failed {
print("Transaction Failed with error")
}
//Transaction can now be safely finished
queue.finishTransaction(transaction)
}
}
}
这是我的第一个应用程序,但我认为问题在于将购买保存到 UserDefaults。我对此很陌生,因此非常感谢任何帮助。
谢谢
【问题讨论】:
-
您在哪里存储包购买状态?钥匙扣很常见。用户只有在使用新设备或已擦除设备时才需要再次尝试购买
-
@Paulw11 这可能是我的问题,如果上述代码中尚未完成,我不知道如何存储每个人的购买状态。我在网上搜索过这方面的帮助,但找不到任何东西。记录/举例说明此代码的任何想法?
-
这取决于你。我确信在 Ray Wendlich 等网站上有 IAP 教程。将值存储在钥匙串中很常见,您可以使用 KeychainSwift 之类的框架来简化它。
-
您可以使用设备上的持久存储将State(购买、恢复)与相关
productIdentifier一起存储。您不应该使用 UserDefaults,因为它可以被操纵(例如有人可以将其替换为购买的,即使它不是),您可以按照上面的建议将其存储在 Keychain 上。你可以使用,paymentQueue(_:updatedTransactions:)delegate。 -
@omerfarukozturk 我实际上对 userDefaults 的限制很好,因为我真的只是想在截止日期前将这个产品推向市场,然后在它上市后改进它。您发送给我的链接非常有帮助,但我在将其使用 UserDefaults 的方法与我的方法区分开来时遇到问题。看来我会做文档告诉我做的所有事情......关于[坚持我的交易](developer.apple.com/documentation/storekit/in-app_purchase/…)的任何建议?
标签: ios swift xcode app-store-connect