我第一次使用不可再生订阅和应用内购买,因为旧购买的恢复,我在发布应用时遇到了问题。
根据我的代码:
1)我应该在paymentQueue上还是在paymentQueueRestoreCompletedTransactionsFinished上调用我的restoreProduct方法?
2)" case.restored"或者paymentQueueRestoreCompletedTransactionsFinished正在被触发,我做错了什么以及如何解决?
编辑:
import Foundation
import UIKit
import StoreKit
class SubscriptionViewController: UIViewController, UITextFieldDelegate {
@IBOutlet weak var moreDetails: UIButton!
@IBOutlet weak var tableView: UITableView!
// For the in app purchase
let productIdentifiers = Set([Constants.oneMonthSubscription, Constants.threeMonthsSubscription,
Constants.sixMonthsSubscription, Constants.yearSubscription])
var basePrice = Double()
var product: SKProduct?
var productsArray = Array<SKProduct>()
var errorCount = 0
var user = User()
var newUser = true
var cameFromLogin = false
var processing = false
var userOneSignalId = NSString()
var service = ""
var transactionDate = 0.0
var transactionId = ""
var count = 0
override func viewDidLoad() {
super.viewDidLoad()
self.tableView.dataSource = self
self.tableView.delegate = self
requestProductData()
}
override func viewWillDisappear(_ animated: Bool) {
super.viewWillDisappear(animated)
SKPaymentQueue.default().remove(self)
}
// Pop-up to indicate an error in the credentials or the authentication process
func showSignUpError(_ message: NSString){
let optionMenu = UIAlertController(title: nil, message: message as String, preferredStyle: .alert)
let dismissAction = UIAlertAction(title: "Ok", style: UIAlertActionStyle.cancel, handler: { (alertAction: UIAlertAction!) in optionMenu.dismiss(animated: true, completion: nil) })
optionMenu.addAction(dismissAction)
self.present(optionMenu, animated: true, completion: nil)
}
}
extension SubscriptionViewController: UITableViewDataSource, UITableViewDelegate {
func numberOfSections(in tableView: UITableView) -> Int {
return self.productsArray.count
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 1
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let product = self.productsArray[(indexPath as NSIndexPath).section]
let productIdentifier = product.productIdentifier
let price = product.price
let cell = tableView.dequeueReusableCell(withIdentifier: "PromoCell", for: indexPath) as! PromoCell
cell.subscription.tag = (indexPath as NSIndexPath).section
cell.subscription.addTarget(self, action: #selector(SubscriptionViewController.didTapButton(_:)), for:.touchUpInside)
cell.subscription.setTitle( "$\(price)",for: UIControlState())
return cell
}
func didTapButton(_ sender: UIButton!){
if !processing{ // Will proccess just one purchase request at the same time
// Section to hide/show
let tappedSection = sender.tag;
self.processing = true
print("User selected : \(self.productsArray[tappedSection].productIdentifier)")
self.buyProduct(self.productsArray[tappedSection])
}
}
}
extension SubscriptionViewController : SKProductsRequestDelegate, SKPaymentTransactionObserver{
// Sends a request to find out which products are available for purchase
func requestProductData(){
self.tableView.isHidden = true
// Checks if In-App purchase is enabled
if SKPaymentQueue.canMakePayments() {
// Requests the product list/set
let request = SKProductsRequest(productIdentifiers: self.productIdentifiers)
request.delegate = self
request.start()
} else { // Shows an error message and options to enable the In-App Purchases for the app
let alert = UIAlertController(title: "In-App Purchases Not Enabled", message: "Please enable In App Purchase in Settings", preferredStyle: UIAlertControllerStyle.alert)
alert.addAction(UIAlertAction(title: "Settings", style: UIAlertActionStyle.default, handler: { alertAction in
alert.dismiss(animated: true, completion: nil)
// Opens the settings so the user can enable the In-App purchase
let url: URL? = URL(string: UIApplicationOpenSettingsURLString)
if url != nil{
UIApplication.shared.openURL(url!)
}
}))
alert.addAction(UIAlertAction(title: "Ok", style: UIAlertActionStyle.default, handler: { alertAction in
alert.dismiss(animated: true, completion: nil)
}))
self.present(alert, animated: true, completion: nil)
}
}
// Recieves the answer for the previous request
func productsRequest(_ request: SKProductsRequest, didReceive response: SKProductsResponse) {
self.productsArray = response.products
productsArray.sort(by: {$0.price.int32Value < $1.price.int32Value})
for item in self.productsArray {
if item.productIdentifier.range(of: "1month") != nil {
self.basePrice = item.price.doubleValue //Price for the most basic subscription
break
}
}
let productsNotFound = response.invalidProductIdentifiers
for product in productsNotFound{
print("Product not found: \(product)")
}
DispatchQueue.main.async {
Loading.stopRotation()
}
self.tableView.isHidden = false
self.tableView.reloadData()
}
// Asks for confirmation when buying a product
func buyProduct(_ product: SKProduct) {
Loading.startRotation()
let payment = SKPayment(product: product)
SKPaymentQueue.default().add(self)
SKPaymentQueue.default().add(payment)
}
func paymentQueue(_ queue: SKPaymentQueue, updatedTransactions transactions: [SKPaymentTransaction]) {
for transaction in transactions {
Loading.stopRotation()
switch transaction.transactionState {
case .purchased:
print("Transaction Approved")
print("Product Identifier: \(transaction.payment.productIdentifier)")
print("Purchasing... Transaction ID: " + transaction.transactionIdentifier!)
print("Purchasing... Transaction Date: " + String(describing: transaction.transactionDate?.timeIntervalSince1970))
print("\n\n--------------\n\n")
SKPaymentQueue.default().finishTransaction(transaction)
transactionDate = (transaction.transactionDate?.timeIntervalSince1970)!
transactionId = transaction.transactionIdentifier!
self.deliverProduct(transaction)
case .restored:
let transaction = SKPaymentTransaction()
transaction.setValue(NSDate(timeIntervalSince1970: 1480468782), forKey: "transactionDate")
transaction.setValue( "1000000254866709", forKey: "transactionIdentifier")
print("Product Identifier: \(transaction.original?.payment.productIdentifier)")
print("Restoring... Transaction ID: " + (transaction.original?.transactionIdentifier)!)
print("Restoring... Transaction Date: " + String(describing: transaction.original?.transactionDate?.timeIntervalSince1970))
print("\n\n--------------\n\n")
SKPaymentQueue.default().finishTransaction(transaction)
transactionDate = (transaction.original?.transactionDate?.timeIntervalSince1970)!
transactionId = (transaction.original?.transactionIdentifier)!
self.restoreProduct(transaction)
case .failed:
print("Transaction Failed")
print(transaction.error)
SKPaymentQueue.default().finishTransaction(transaction)
if transaction.error?._code == 0 || transaction.error?._code == 2 {
self.errorCount += 1 //
if self.errorCount > 3 { // We give the app three chances to connect
print("Error connecting to the iTunes Store")
self.showSignUpError(Constants.iTunnesConnectionError as NSString)
}
}else{
self.showSignUpError(Constants.signUpError as NSString)
}
self.processing = false
default:
break
}
}
}
func paymentQueueRestoreCompletedTransactionsFinished(_ queue: SKPaymentQueue) {
print("Transactions Restored .")
for transaction in queue.transactions {
let transaction: SKPaymentTransaction = transaction
print(transaction.transactionIdentifier ?? "Missing Transaction ID")
}
}
func deliverProduct(_ transaction:SKPaymentTransaction) {
}
func restoreProduct(_ transaction:SKPaymentTransaction) {
}
}