为什么非续订,再次购买时显示 "This In-App purchase has already been bought. It will be restored for free."?
why non-renewing subscription, shows "This In-App purchase has already been bought. It will be restored for free.", when purchasing item again?
我正在我的应用程序中实施不可再生购买。我仍在沙盒模式下使用。在我订阅该产品后,当我再次尝试订阅相同的产品时,它会提示我“此 App 内购买已被购买。”它将免费恢复。我不知道我应该如何让用户再次订阅。
如何在同一台设备上处理多个用户?如果一个用户已支付订阅费用,而另一个用户登录同一设备到我的应用程序 he/she 不应收到上述警报。
Code :
import StoreKit
class className: SKProductsRequestDelegate
{
var productIDs: Array<String?> = []
var productsArray: Array<SKProduct?> = []
override func viewDidLoad(){
// product IDs for in-app purchase products
productIDs.append(“monthly_subscription_id”) // Monthly
productIDs.append(“yearly_subscription_id”) // Year
requestProductInfo()
SKPaymentQueue.default().add(self)
}
func requestProductInfo() {
if SKPaymentQueue.canMakePayments() {
let productIdentifiers = NSSet(array: productIDs)
let productRequest = SKProductsRequest(productIdentifiers: productIdentifiers as Set<NSObject> as! Set<String>)
productRequest.delegate = self
productRequest.start()
}
else {
print("Cannot perform In App Purchases.")
}
}
// MARK: SKProductsRequestDelegate method implementation
func productsRequest(_ request: SKProductsRequest, didReceive response: SKProductsResponse) {
if response.products.count != 0 {
for product in response.products {
productsArray.append(product )
}
}
else {
print("There are no products.")
}
if response.invalidProductIdentifiers.count != 0 {
print(response.invalidProductIdentifiers.description)
}
}
// MARK: Buy Subscription button action
@IBAction func btn_purchase_Action(_ sender: Any){
let payment = SKPayment(product: self.productsArray[productIndex]!)
SKPaymentQueue.default().add(payment)
self.transactionInProgress = true
}
}
// MARK: - SKPaymentTransactionObserver
extension className: SKPaymentTransactionObserver {
public func paymentQueue(_ queue: SKPaymentQueue, updatedTransactions transactions: [SKPaymentTransaction]){
for transaction in transactions {
switch (transaction.transactionState) {
case .purchased:
complete(transaction: transaction)
break
case .failed:
fail(transaction: transaction)
break
case .restored:
restore(transaction: transaction)
break
case .deferred:
break
case .purchasing:
break
}
}
}
private func complete(transaction: SKPaymentTransaction){
print("complete...")
SKPaymentQueue.default().finishTransaction(transaction)
}
private func restore(transaction: SKPaymentTransaction){
guard let productIdentifier = transaction.original?.payment.productIdentifier else { return }
print("restore... \(productIdentifier)")
SKPaymentQueue.default().finishTransaction(transaction)
}
private func fail(transaction: SKPaymentTransaction){
print("fail...")
if let transactionError = transaction.error as? NSError {
if transactionError.code != SKError.paymentCancelled.rawValue {
print("Transaction Error: \(transaction.error?.localizedDescription)")
}
}
SKPaymentQueue.default().finishTransaction(transaction)
}
}
我可以看到弹出窗口说应用内购买成功,但是当我成功完成应用内购买过程时,"updatedTransaction" 函数没有被调用。
第一次应用内购买已完成,但当我再次尝试购买同一产品时,它会显示产品已购买且可以免费恢复的警报。
从您的代码来看,您的事务观察器似乎是一个视图控制器。
如果视图控制器在支付交易处理完成之前被关闭,那么您将没有机会完成交易。
您的支付队列观察器应该是一个对象,该对象会在您的应用启动后立即实例化,并在应用的整个生命周期内保留在内存中。
在 didFinishLaunching
中创建支付队列观察器并在您的应用委托中保留对它的引用是您可以使用的一种方法。
我正在我的应用程序中实施不可再生购买。我仍在沙盒模式下使用。在我订阅该产品后,当我再次尝试订阅相同的产品时,它会提示我“此 App 内购买已被购买。”它将免费恢复。我不知道我应该如何让用户再次订阅。
如何在同一台设备上处理多个用户?如果一个用户已支付订阅费用,而另一个用户登录同一设备到我的应用程序 he/she 不应收到上述警报。
Code :
import StoreKit
class className: SKProductsRequestDelegate
{
var productIDs: Array<String?> = []
var productsArray: Array<SKProduct?> = []
override func viewDidLoad(){
// product IDs for in-app purchase products
productIDs.append(“monthly_subscription_id”) // Monthly
productIDs.append(“yearly_subscription_id”) // Year
requestProductInfo()
SKPaymentQueue.default().add(self)
}
func requestProductInfo() {
if SKPaymentQueue.canMakePayments() {
let productIdentifiers = NSSet(array: productIDs)
let productRequest = SKProductsRequest(productIdentifiers: productIdentifiers as Set<NSObject> as! Set<String>)
productRequest.delegate = self
productRequest.start()
}
else {
print("Cannot perform In App Purchases.")
}
}
// MARK: SKProductsRequestDelegate method implementation
func productsRequest(_ request: SKProductsRequest, didReceive response: SKProductsResponse) {
if response.products.count != 0 {
for product in response.products {
productsArray.append(product )
}
}
else {
print("There are no products.")
}
if response.invalidProductIdentifiers.count != 0 {
print(response.invalidProductIdentifiers.description)
}
}
// MARK: Buy Subscription button action
@IBAction func btn_purchase_Action(_ sender: Any){
let payment = SKPayment(product: self.productsArray[productIndex]!)
SKPaymentQueue.default().add(payment)
self.transactionInProgress = true
}
}
// MARK: - SKPaymentTransactionObserver
extension className: SKPaymentTransactionObserver {
public func paymentQueue(_ queue: SKPaymentQueue, updatedTransactions transactions: [SKPaymentTransaction]){
for transaction in transactions {
switch (transaction.transactionState) {
case .purchased:
complete(transaction: transaction)
break
case .failed:
fail(transaction: transaction)
break
case .restored:
restore(transaction: transaction)
break
case .deferred:
break
case .purchasing:
break
}
}
}
private func complete(transaction: SKPaymentTransaction){
print("complete...")
SKPaymentQueue.default().finishTransaction(transaction)
}
private func restore(transaction: SKPaymentTransaction){
guard let productIdentifier = transaction.original?.payment.productIdentifier else { return }
print("restore... \(productIdentifier)")
SKPaymentQueue.default().finishTransaction(transaction)
}
private func fail(transaction: SKPaymentTransaction){
print("fail...")
if let transactionError = transaction.error as? NSError {
if transactionError.code != SKError.paymentCancelled.rawValue {
print("Transaction Error: \(transaction.error?.localizedDescription)")
}
}
SKPaymentQueue.default().finishTransaction(transaction)
}
}
我可以看到弹出窗口说应用内购买成功,但是当我成功完成应用内购买过程时,"updatedTransaction" 函数没有被调用。 第一次应用内购买已完成,但当我再次尝试购买同一产品时,它会显示产品已购买且可以免费恢复的警报。
从您的代码来看,您的事务观察器似乎是一个视图控制器。
如果视图控制器在支付交易处理完成之前被关闭,那么您将没有机会完成交易。
您的支付队列观察器应该是一个对象,该对象会在您的应用启动后立即实例化,并在应用的整个生命周期内保留在内存中。
在 didFinishLaunching
中创建支付队列观察器并在您的应用委托中保留对它的引用是您可以使用的一种方法。