In-App Purchase Error , Always myProduct is 0 - ios

My VC like this:
var coins = 50 // coins
override func viewDidLoad() {
super.viewDidLoad()
if(SKPaymentQueue.canMakePayments()) {
//print("enabled, loading")
let productID: NSSet = NSSet(objects: "com.tahabuyruk.taha.coinsal", "com.tahabuyruk.taha.reklam") // my products Id
let request: SKProductsRequest = SKProductsRequest(productIdentifiers: productID as! Set<String>)
request.delegate = self
request.start()
} else {
print("please enable IAPS")
}
}
//I have 2 products on itunesconnect
#IBAction func btnRemoveAds(_ sender: Any) {
print("rem ads")
for product in list {
let prodID = product.productIdentifier
if(prodID == "com.tahabuyruk.taha.reklam") {
// ad product id
p = product
buyProduct()
}
}
}
// my bundle id is com.tahabuyruk.taha
// my product id is com.tahabuyruk.taha.coins
#IBAction func satinAl(_ sender: Any) { // addCoin Button
for product in list {
let prodID = product.productIdentifier
if(prodID == "com.tahabuyruk.taha.coinsal") {
p = product
buyProduct()
}
}
}
func buyProduct() {
print("buy " + p.productIdentifier)
let pay = SKPayment(product: p)
SKPaymentQueue.default().add(self)
SKPaymentQueue.default().add(pay as SKPayment)
}
func removeAds() {
lblAd.removeFromSuperview()
}
func addCoins() {
coins += 50
lblCoinAmount.text = "\(coins)"
}
var list = [SKProduct]()
var p = SKProduct()
func productsRequest(_ request: SKProductsRequest, didReceive response: SKProductsResponse) {
print("product request")
let myProduct = response.products // myProduct is always be 0 . I don't know why .
for product in myProduct {
print("product added")
print(product.productIdentifier)
print(product.localizedTitle)
print(product.localizedDescription)
print(product.price)
list.append(product)
}
}
func paymentQueueRestoreCompletedTransactionsFinished(_ queue: SKPaymentQueue) {
print("transactions restored")
for transaction in queue.transactions {
let t: SKPaymentTransaction = transaction
let prodID = t.payment.productIdentifier as String
switch prodID {
case "com.tahabuyruk.taha.reklam":// ad product id
print("remove ads")
removeAds()
case "com.tahabuyruk.taha.coinsal":
print("add coins to account")
addCoins()
default:
print("IAP not found")
}
}
}
func paymentQueue(_ queue: SKPaymentQueue, updatedTransactions transactions: [SKPaymentTransaction]) {
print("add payment")
for transaction: AnyObject in transactions {
let trans = transaction as! SKPaymentTransaction
print(trans.error)
switch trans.transactionState {
case .purchased:
print("buy ok")
print(p.productIdentifier)
let prodID = p.productIdentifier
switch prodID {
case "com.tahabuyruk.taha.reklam":// ad product id
print("remove ads")
removeAds()
case "com.tahabuyruk.taha.coinsal":
print("add coins to account")
addCoins()
default:
print("IAP not found")
}
queue.finishTransaction(trans)
case .failed:
print("buy error")
queue.finishTransaction(trans)
break
default:
print("Default")
break
}
}
}
Always myProduct is 0.
What's wrong with this code?
I want to know why always be 0?

I handle this problem , look for Agreements , Tax and Banking and check that your banking, contact and tax information has been filled up

Related

InApp Purchases localized price fatal error

I'm using this code for my inApp Purchases to show localized price:
private func priceStringFor(product: SKProduct) -> String {
let numberFormatter = NumberFormatter()
numberFormatter.numberStyle = .currency
numberFormatter.locale = product.priceLocale
return numberFormatter.string(from: product.price)!
}
override func viewDidLoad() {
super.viewDidLoad()
perYearPrice.setTitle("\(priceStringFor(product: IAPManager.shared.products[1])) per year", for: .normal)
oneTimePrice.setTitle("\(priceStringFor(product: IAPManager.shared.products[0])) one time", for: .normal)
}
And this is my IAPManager code:
import Foundation
import StoreKit
class IAPManager: NSObject {
static let shared = IAPManager()
private override init() {}
var products: [SKProduct] = []
let paymentQueue = SKPaymentQueue.default()
public func setupPurchases(callback: #escaping(Bool) -> ()) {
if SKPaymentQueue.canMakePayments() {
paymentQueue.add(self)
callback(true)
return
}
callback(false)
}
public func getProducts() {
let identifiers: Set = ["inapp1", "inapp2"]
let productRequest = SKProductsRequest(productIdentifiers: identifiers)
productRequest.delegate = self
productRequest.start()
}
public func purchase(productWith identifier: String) {
guard let product = products.filter({ $0.productIdentifier == identifier }).first else { return }
let payment = SKPayment(product: product)
paymentQueue.add(payment)
}
public func restoreCompletedTransactions() {
paymentQueue.restoreCompletedTransactions()
}
}
extension IAPManager: SKPaymentTransactionObserver {
func paymentQueue(_ queue: SKPaymentQueue, updatedTransactions transactions: [SKPaymentTransaction]) {
for transaction in transactions {
switch transaction.transactionState {
case .deferred: break
case .purchasing: break
case .failed: failed(transaction: transaction)
case .purchased: completed(transaction: transaction)
case .restored: restored(transaction: transaction)
#unknown default: fatalError()
}
}
}
func purchased() {
let adRemovalPurchased = UserDefaults.standard
adRemovalPurchased.set(true, forKey: "adRemoved")
adRemovalPurchased.synchronize()
}
private func failed(transaction: SKPaymentTransaction) {
if let transactionError = transaction.error as NSError? {
if transactionError.code != SKError.paymentCancelled.rawValue {
print("Error: \(transaction.error!.localizedDescription)")
}
}
paymentQueue.finishTransaction(transaction)
}
private func completed(transaction: SKPaymentTransaction) {
paymentQueue.finishTransaction(transaction)
purchased()
}
private func restored(transaction: SKPaymentTransaction) {
paymentQueue.finishTransaction(transaction)
purchased()
}
}
extension IAPManager: SKProductsRequestDelegate {
func productsRequest(_ request: SKProductsRequest, didReceive response: SKProductsResponse) {
self.products = response.products
products.forEach { print($0.localizedTitle) }
}
}
Also I put this code in AppDelegate:
IAPManager.shared.setupPurchases { success in
if success {
print("can make payments")
IAPManager.shared.getProducts()
}
}
But when I try to get localized price for IAPManager.shared.products[1]) I get
Fatal error: Index out of range.
I don't understant where is the error. In some cases this code works, but in some cases it gets fatal error.
This
IAPManager.shared.getProducts()
is an asynchronous method , you can't access products array until this called
var callBack:(() -> ())? // 1
func productsRequest(_ request: SKProductsRequest, didReceive response: SKProductsResponse) {
self.products = response.products
products.forEach { print($0.localizedTitle) }
callBack?() // 2
}
Then do
IAPManager.shared.setupPurchases { success in
if success {
print("can make payments")
IAPManager.shared.callBack = {
// now access the products
}
IAPManager.shared.getProducts()
}
}
BTW you can make use of https://github.com/bizz84/SwiftyStoreKit

In app purchase not fully firing

Whenever I conduct an in-app purchase in a sandbox environment, it acts like it is completing, when it really isn't. To be more specific, I click to buy more coins, I confirm that I want to buy them in the sandbox environment. Then it says "You're all set!" saying that I have completed the purchase. Well when I check my coins, nothing changed!
After looking through the code, I realized that the
func paymentQueue(queue: SKPaymentQueue!, updatedTransactions transactions: [AnyObject]!) {
...is not firing.
Full code:
import UIKit
import StoreKit
import AVFoundation
class InAppPurchases: UIViewController, SKProductsRequestDelegate, SKPaymentTransactionObserver {
#IBOutlet weak var noAdsBtn: UIButton!
var product_id: String?
let defaultsAD = UserDefaults.standard
override func viewDidLoad() {
super.viewDidLoad()
product_id = "noads"
SKPaymentQueue.default().add(self)
//Check if product is purchased
if (defaultsAD.bool(forKey: "purchased")){
// Hide a view or show content depends on your requirement
// overlayView.hidden = true
noAdsBtn.backgroundColor = UIColor.red
noAdsBtn.isUserInteractionEnabled = false
} else {
print("false")
// noAds = true
// var NAD = UserDefaults.standard
// NAD.setValue(noAds, forKey: "nad")
// NAD.synchronize()
}
// Do any additional setup after loading the view.
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
#IBAction func backBtnA(_ sender: Any) {
music2()
}
/*
// MARK: - Navigation
// In a storyboard-based application, you will often want to do a little preparation before navigation
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
// Get the new view controller using segue.destinationViewController.
// Pass the selected object to the new view controller.
}
*/
#IBAction func Buy600(_ sender: Any) {
print("About to fetch the products")
product_id = "600coins"
// We check that we are allow to make the purchase.
if (SKPaymentQueue.canMakePayments()) {
var productID:NSSet = NSSet(object: self.product_id!);
var productsRequest:SKProductsRequest = SKProductsRequest(productIdentifiers: productID as! Set<String>);
productsRequest.delegate = self;
productsRequest.start();
print("Fetching Products");
} else {
print("can't make purchases");
}
}
#IBAction func buy1500(_ sender: Any) {
print("About to fetch the products")
product_id = "1500coins"
// We check that we are allow to make the purchase.
if (SKPaymentQueue.canMakePayments()) {
var productID:NSSet = NSSet(object: self.product_id!);
var productsRequest:SKProductsRequest = SKProductsRequest(productIdentifiers: productID as! Set<String>);
productsRequest.delegate = self;
productsRequest.start();
print("Fetching Products");
} else {
print("can't make purchases");
}
}
#IBAction func buy3500(_ sender: Any) {
print("About to fetch the products")
product_id = "3500coins"
// We check that we are allow to make the purchase.
if (SKPaymentQueue.canMakePayments()) {
var productID:NSSet = NSSet(object: self.product_id!);
var productsRequest:SKProductsRequest = SKProductsRequest(productIdentifiers: productID as! Set<String>);
productsRequest.delegate = self;
productsRequest.start();
print("Fetching Products");
} else {
print("can't make purchases");
}
}
#IBAction func buy8000(_ sender: Any) {
print("About to fetch the products")
product_id = "8000coins"
// We check that we are allow to make the purchase.
if (SKPaymentQueue.canMakePayments()) {
var productID:NSSet = NSSet(object: self.product_id!);
var productsRequest:SKProductsRequest = SKProductsRequest(productIdentifiers: productID as! Set<String>);
productsRequest.delegate = self;
productsRequest.start();
print("Fetching Products");
} else {
print("can't make purchases");
}
}
#IBAction func buy25000(_ sender: Any) {
print("About to fetch the products")
product_id = "25000coins"
// We check that we are allow to make the purchase.
if (SKPaymentQueue.canMakePayments()) {
var productID:NSSet = NSSet(object: self.product_id!);
var productsRequest:SKProductsRequest = SKProductsRequest(productIdentifiers: productID as! Set<String>);
productsRequest.delegate = self;
productsRequest.start();
print("Fetching Products");
} else {
print("can't make purchases");
}
}
#IBAction func buyTruckload(_ sender: Any) {
print("About to fetch the products")
product_id = "truckloadofcoins"
// We check that we are allow to make the purchase.
if (SKPaymentQueue.canMakePayments()) {
var productID:NSSet = NSSet(object: self.product_id!);
var productsRequest:SKProductsRequest = SKProductsRequest(productIdentifiers: productID as! Set<String>);
productsRequest.delegate = self;
productsRequest.start();
print("Fetching Products");
} else {
print("can't make purchases");
}
}
#IBAction func buyNoAds(_ sender: Any) {
print("About to fetch the products")
product_id = "noads"
// We check that we are allow to make the purchase.
if (SKPaymentQueue.canMakePayments()) {
var productID:NSSet = NSSet(object: self.product_id!);
var productsRequest:SKProductsRequest = SKProductsRequest(productIdentifiers: productID as! Set<String>);
productsRequest.delegate = self;
productsRequest.start();
print("Fetching Products");
} else {
print("can't make purchases");
}
}
func buyProduct(product: SKProduct){
print("Sending the Payment Request to Apple");
let payment = SKPayment(product: product)
SKPaymentQueue.default().add(payment);
//
SKPaymentQueue.default().add(self)
//^^??
}
func productsRequest (_ request: SKProductsRequest, didReceive response: SKProductsResponse) {
let count : Int = response.products.count
if (count>0) {
let validProduct: SKProduct = response.products[0] as SKProduct
if (validProduct.productIdentifier == self.product_id) {
print(validProduct.localizedTitle)
print(validProduct.localizedDescription)
print(validProduct.price)
buyProduct(product: validProduct);
} else {
print(validProduct.productIdentifier)
}
} else {
print("nothing")
}
}
func request(_ request: SKRequest, didFailWithError error: Error) {
print("Error Fetching product information");
}
func paymentQueue(queue: SKPaymentQueue!, updatedTransactions transactions: [AnyObject]!) {
print("Received Payment Transaction Response from Apple");
for transaction:AnyObject in transactions {
if let trans:SKPaymentTransaction = transaction as? SKPaymentTransaction{
switch trans.transactionState {
case .purchased:
print("Product Purchased");
SKPaymentQueue.default().finishTransaction(transaction as! SKPaymentTransaction)
if product_id == "noads"{
defaultsAD.set(true , forKey: "purchased")
noAdsBtn.backgroundColor = UIColor.red
noAdsBtn.isUserInteractionEnabled = false
noAds = true
var NAD = UserDefaults.standard
NAD.setValue(noAds, forKey: "nad")
NAD.synchronize()
}
//add coins
if product_id == "600coins"{
coins += 600
print("just bought 600 coins")
var C = UserDefaults.standard
C.setValue(coins, forKey: "c")
C.synchronize()
SKPaymentQueue.default().finishTransaction(transaction as! SKPaymentTransaction)
}
if product_id == "1500coins"{
coins += 1500
var C = UserDefaults.standard
C.setValue(coins, forKey: "c")
C.synchronize()
SKPaymentQueue.default().finishTransaction(transaction as! SKPaymentTransaction)
}
if product_id == "3500coins"{
coins += 3500
var C = UserDefaults.standard
C.setValue(coins, forKey: "c")
C.synchronize()
SKPaymentQueue.default().finishTransaction(transaction as! SKPaymentTransaction)
}
if product_id == "8000coins"{
coins += 8000
var C = UserDefaults.standard
C.setValue(coins, forKey: "c")
C.synchronize()
SKPaymentQueue.default().finishTransaction(transaction as! SKPaymentTransaction)
}
if product_id == "25000coins"{
coins += 25000
var C = UserDefaults.standard
C.setValue(coins, forKey: "c")
C.synchronize()
print("just boughtn 25k coins")
SKPaymentQueue.default().finishTransaction(transaction as! SKPaymentTransaction)
}
if product_id == "100000coins"{
coins += 100000
var C = UserDefaults.standard
C.setValue(coins, forKey: "c")
C.synchronize()
SKPaymentQueue.default().finishTransaction(transaction as! SKPaymentTransaction)
}
// overlayView.hidden = true
break;
case .failed:
print("Purchased Failed");
SKPaymentQueue.default().finishTransaction(transaction as! SKPaymentTransaction)
break;
case .restored:
print("Already Purchased");
SKPaymentQueue.default().restoreCompletedTransactions()
if product_id == "noads"{
defaultsAD.set(true , forKey: "purchased")
noAdsBtn.backgroundColor = UIColor.red
noAdsBtn.isUserInteractionEnabled = false
noAds = true
var NAD = UserDefaults.standard
NAD.setValue(noAds, forKey: "nad")
NAD.synchronize()
}else{
//add coins
if product_id == "600coins"{
coins += 600
print("already bought")
var C = UserDefaults.standard
C.setValue(coins, forKey: "c")
C.synchronize()
}
if product_id == "1500coins"{
coins += 1500
var C = UserDefaults.standard
C.setValue(coins, forKey: "c")
C.synchronize()
}
if product_id == "3500coins"{
coins += 3500
var C = UserDefaults.standard
C.setValue(coins, forKey: "c")
C.synchronize()
}
if product_id == "8000coins"{
coins += 8000
var C = UserDefaults.standard
C.setValue(coins, forKey: "c")
C.synchronize()
}
if product_id == "25000coins"{
coins += 25000
var C = UserDefaults.standard
C.setValue(coins, forKey: "c")
C.synchronize()
}
if product_id == "100000coins"{
coins += 100000
var C = UserDefaults.standard
C.setValue(coins, forKey: "c")
C.synchronize()
}
}
default:
break;
}
}
}
}
func paymentQueue(_ queue: SKPaymentQueue,
updatedTransactions transactions: [SKPaymentTransaction]){
print("updating transactions")
}
func music2(){
// currentlyPlayingAudio = true
// print("\n\n\n\n\n\n\n\n\nview appeared...music??\n\n\n\n\n\n\n\n\n")
if soundFX == true{
let ButtonAudioURL2 = URL(fileURLWithPath: Bundle.main.path(forResource: "Click2", ofType: "mp3")!)
do {
try AVAudioSession.sharedInstance().setCategory(AVAudioSessionCategoryPlayback)
} catch _ {
}
do {
try AVAudioSession.sharedInstance().setActive(true)
} catch _ {
}
var error: NSError?
do {
audioPlayerClick = try AVAudioPlayer(contentsOf: ButtonAudioURL2)
} catch let error1 as NSError {
error = error1
}
audioPlayerClick.prepareToPlay()
// audioPlayer.volume = 0.3
audioPlayerClick.play()
}
}
func music3(){
// currentlyPlayingAudio = true
// print("\n\n\n\n\n\n\n\n\nview appeared...music??\n\n\n\n\n\n\n\n\n")
if soundFX == true{
let ButtonAudioURL3 = URL(fileURLWithPath: Bundle.main.path(forResource: "Toggle", ofType: "mp3")!)
do {
try AVAudioSession.sharedInstance().setCategory(AVAudioSessionCategoryPlayback)
} catch _ {
}
do {
try AVAudioSession.sharedInstance().setActive(true)
} catch _ {
}
var error: NSError?
do {
audioPlayerClick2 = try AVAudioPlayer(contentsOf: ButtonAudioURL3)
} catch let error1 as NSError {
error = error1
}
audioPlayerClick2.prepareToPlay()
// audioPlayer.volume = 0.3
audioPlayerClick2.play()
}
}
}
One last thing; the IAP to remove ads (with id "noads") keeps returning "nothing" in the console. Any ideas why it won't successfully trigger? It is a non-consumable and is labeled in iTunes Connect as "Waiting for Upload".

In app purchase in iOS if press cancel button then nothing happen

I am doing simple in app purchase application. At the time of product load I simply restore all my previous purchase, so I start loading indicator when I start loading product but in some device I already used inapp id so every time I load the product in that device some type of alert come and if I press cancel then nothing happen and my loading indicator goes infinite.
Here I have screenshot too.
extension IAPHelper: SKPaymentTransactionObserver {
public func paymentQueue(_ queue: SKPaymentQueue, updatedTransactions transactions: [SKPaymentTransaction]) {
for transaction in transactions {
if productIdentifiers.contains(transaction.payment.productIdentifier) {
switch (transaction.transactionState) {
case .purchased:
complete(transaction: transaction)
break
case .failed:
fail(transaction: transaction)
break
case .restored:
restore(transaction: transaction)
break
case .deferred:
print("denied")
break
case .purchasing:
break
}
}
}
if productsRestoreCompletionHandler != nil
{
productsRestoreCompletionHandler = nil
}
}
private func complete(transaction: SKPaymentTransaction) {
print("complete...")
// deliverPurchaseNotificationFor(identifier: transaction.payment.productIdentifier)
SKPaymentQueue.default().finishTransaction(transaction)
productsPurchaseCompletionHandler?(true, transaction)
if productsPurchaseCompletionHandler != nil
{
productsPurchaseCompletionHandler = nil
}
}
private func restore(transaction: SKPaymentTransaction) {
guard let productIdentifier = transaction.original?.payment.productIdentifier else { return }
print("restore... \(productIdentifier)")
// deliverPurchaseNotificationFor(identifier: productIdentifier)
SKPaymentQueue.default().finishTransaction(transaction)
productsRestoreCompletionHandler?(true, 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)
if productsRestoreCompletionHandler != nil
{
productsRestoreCompletionHandler?(false, transaction)
productsRestoreCompletionHandler = nil
}
if productsPurchaseCompletionHandler != nil
{
productsPurchaseCompletionHandler?(false, transaction)
productsPurchaseCompletionHandler = nil
}
}
private func deliverPurchaseNotificationFor(identifier: String?) {
guard let identifier = identifier else { return }
purchasedProductIdentifiers.insert(identifier)
// UserDefaults.standard.set(true, forKey: identifier)
// UserDefaults.standard.synchronize()
// NotificationCenter.default.post(name: NSNotification.Name(rawValue: IAPHelper.IAPHelperPurchaseNotification), object: identifier)
}
}
When product load
//MARK:
//MARK: load the product
func getProduct()
{
let userData = getUserDataFromFile()
obj = IAPHelper(productIds: NetFishProducts.productIdentifiers)
if checkInternetConnection()
{
SINGLETON.startLoadingActivity(self.view)
obj.requestProducts { (isSuccess, arrProduct) in
if isSuccess == true
{
self.setProduct = Set<SKProduct>(arrProduct! as [SKProduct])
self.btnSignup.isUserInteractionEnabled = true
for p in arrProduct! {
print("Found product: \(p.productIdentifier) \(p.localizedTitle) \(p.price.floatValue)")
if p.productIdentifier == NetFishProducts.monthlyPlan
{
self.setupLblMonth(withMothPrice: "\(p.price.floatValue)")
}
else
{
self.setupLblYear(withYearPrice: "\(p.price.floatValue)")
}
}
self.obj.requestRestoreProducts(completionHandler: { (isSuccess, transation) in
SINGLETON.stopLoadingActivity(self.view)
if isSuccess == true
{
let orignalTI = transation?.original?.transactionIdentifier
let userEmail = transation?.payment.applicationUsername
print("orignalTI:\(orignalTI)")
print("username:\(userEmail)")
if userEmail != nil && userData?.userEmail != userEmail
{
self.btnSignup.isUserInteractionEnabled = false
self.showAlertToUser("Information", MsgDesc: "You are login with different appstore account so login with correct appstore account")
return
}
}
else
{
self.btnSignup.isUserInteractionEnabled = false
}
},withUserName: (userData?.userEmail)!)
}
else
{
SINGLETON.stopLoadingActivity(self.view)
self.btnSignup.isUserInteractionEnabled = false
}
}
}
}

Restore Purchase in Swift

I'm trying to add a restore button to my app, I have a non-consumable inApp purchase and the purchase part works fine. I have a button that calls this two methods:
product_id = "RemoveAdsIAP";
SKPaymentQueue.defaultQueue().addTransactionObserver(self)
SKPaymentQueue.defaultQueue().restoreCompletedTransactions()
and this the purchasing code:
func buyConsumable(){
succssessIAP = false
if (SKPaymentQueue.canMakePayments()) {
var productID:NSSet = NSSet(object: self.product_id!);
var productsRequest:SKProductsRequest = SKProductsRequest(productIdentifiers: productID);
productsRequest.delegate = self;
productsRequest.start();
} else {
displayErrorAlert()
}
}
func buyProduct(product: SKProduct){
var payment = SKPayment(product: product)
SKPaymentQueue.defaultQueue().addPayment(payment);
}
func productsRequest (request: SKProductsRequest, didReceiveResponse response: SKProductsResponse) {
var count : Int = response.products.count
if (count>0) {
var validProducts = response.products
var validProduct: SKProduct = response.products[0] as SKProduct
if (validProduct.productIdentifier == self.product_id) {
buyProduct(validProduct);
} else { }
} else {
displayErrorAlert()
}
}
func request(request: SKRequest!, didFailWithError error: NSError!) {
activityIndicatorShop.stopAnimating()
UIApplication.sharedApplication().endIgnoringInteractionEvents()
displayErrorAlert()
}
func paymentQueue(queue: SKPaymentQueue!, updatedTransactions transactions: [AnyObject]!) {
succssessIAP = false
for transaction:AnyObject in transactions {
if let trans:SKPaymentTransaction = transaction as? SKPaymentTransaction{
switch trans.transactionState {
case .Purchased, .Restored:
if (product_id == "GetNextFactIAP" && succssessIAP == false) {
startController.getData()
startController.hideContainerView()
succssessIAP = true
}
if (product_id == "RemoveAdsIAP" && succssessIAP == false) {
NSUserDefaults.standardUserDefaults().setBool(true, forKey: "viewAdsBool")
NSUserDefaults.standardUserDefaults().synchronize()
startController.removeOnce()
disableAds(true)
succssessIAP = true
}
SKPaymentQueue.defaultQueue().finishTransaction(transaction as SKPaymentTransaction)
break;
case .Failed:
SKPaymentQueue.defaultQueue().finishTransaction(transaction as SKPaymentTransaction)
activityIndicatorShop.stopAnimating()
displayErrorAlert()
UIApplication.sharedApplication().endIgnoringInteractionEvents()
break;
default:
break;
}
}
}
}
When I press the button nothing happens, I've added a log statement to check if the updatedTransactions method was called and it wasn't, What's the problem?
Your products_id has the wrong format.
It should be more like
product_id = "com.xxxxxxxxx.RemoveAdsIAP"

Restore Purchase in Swift

I'm trying to add a restore button to my app, I have a non-consumable inApp purchase and the purchase part works fine. I have a button that calls this two methods:
product_id = "RemoveAdsIAP";
SKPaymentQueue.defaultQueue().addTransactionObserver(self)
SKPaymentQueue.defaultQueue().restoreCompletedTransactions()
and this the purchasing code:
func buyConsumable(){
succssessIAP = false
if (SKPaymentQueue.canMakePayments()) {
var productID:NSSet = NSSet(object: self.product_id!);
var productsRequest:SKProductsRequest = SKProductsRequest(productIdentifiers: productID);
productsRequest.delegate = self;
productsRequest.start();
} else {
displayErrorAlert()
}
}
func buyProduct(product: SKProduct){
var payment = SKPayment(product: product)
SKPaymentQueue.defaultQueue().addPayment(payment);
}
func productsRequest (request: SKProductsRequest, didReceiveResponse response: SKProductsResponse) {
var count : Int = response.products.count
if (count>0) {
var validProducts = response.products
var validProduct: SKProduct = response.products[0] as SKProduct
if (validProduct.productIdentifier == self.product_id) {
buyProduct(validProduct);
} else { }
} else {
displayErrorAlert()
}
}
func request(request: SKRequest!, didFailWithError error: NSError!) {
activityIndicatorShop.stopAnimating()
UIApplication.sharedApplication().endIgnoringInteractionEvents()
displayErrorAlert()
}
func paymentQueue(queue: SKPaymentQueue!, updatedTransactions transactions: [AnyObject]!) {
succssessIAP = false
for transaction:AnyObject in transactions {
if let trans:SKPaymentTransaction = transaction as? SKPaymentTransaction{
switch trans.transactionState {
case .Purchased, .Restored:
if (product_id == "GetNextFactIAP" && succssessIAP == false) {
startController.getData()
startController.hideContainerView()
succssessIAP = true
}
if (product_id == "RemoveAdsIAP" && succssessIAP == false) {
NSUserDefaults.standardUserDefaults().setBool(true, forKey: "viewAdsBool")
NSUserDefaults.standardUserDefaults().synchronize()
startController.removeOnce()
disableAds(true)
succssessIAP = true
}
SKPaymentQueue.defaultQueue().finishTransaction(transaction as SKPaymentTransaction)
break;
case .Failed:
SKPaymentQueue.defaultQueue().finishTransaction(transaction as SKPaymentTransaction)
activityIndicatorShop.stopAnimating()
displayErrorAlert()
UIApplication.sharedApplication().endIgnoringInteractionEvents()
break;
default:
break;
}
}
}
}
When I press the button nothing happens, I've added a log statement to check if the updatedTransactions method was called and it wasn't, What's the problem?
you didn't add the button as an IBAction.
Read this...
http://rshankar.com/different-ways-to-connect-ibaction-to-uibutton/
Try This Code
import UIKit
import StoreKit
 
class ViewController: UIViewController, SKProductsRequestDelegate, SKPaymentTransactionObserver{
var list = [SKProduct]()
var p = SKProduct()
    
    // 2
    func buyProduct() {
        println("buy " + p.productIdentifier)
        var pay = SKPayment(product: p)
        SKPaymentQueue.defaultQueue().addTransactionObserver(self)
        SKPaymentQueue.defaultQueue().addPayment(pay as SKPayment)
    }
    
    //3
    func productsRequest(request: SKProductsRequest!, didReceiveResponse response: SKProductsResponse!) {
        println("product request")
        var myProduct = response.products
        
        for product in myProduct {
            println("product added")
            println(product.productIdentifier)
            println(product.localizedTitle)
            println(product.localizedDescription)
            println(product.price)
            
            list.append(product as SKProduct)
        }
        
        outRemoveAds.enabled = true
        outAddCoins.enabled = true
    }
    
    // 4
    func paymentQueueRestoreCompletedTransactionsFinished(queue: SKPaymentQueue!) {
        println("transactions restored")
        
        var purchasedItemIDS = []
        for transaction in queue.transactions {
            var t: SKPaymentTransaction = transaction as SKPaymentTransaction
            
            let prodID = t.payment.productIdentifier as String
            
            switch prodID {
            case "seemu.iap.removeads":
                println("remove ads")
                removeAds()
            case "seemu.iap.addcoins":
                println("add coins to account")
                addCoins()
            default:
                println("IAP not setup")
            }
            
        }
    }
 
    // 5
    func paymentQueue(queue: SKPaymentQueue!, updatedTransactions transactions: [AnyObject]!) {
        println("add paymnet")
        
        for transaction:AnyObject in transactions {
            var trans = transaction as SKPaymentTransaction
            println(trans.error)
            
            switch trans.transactionState {
                
            case .Purchased:
                println("buy, ok unlock iap here")
                println(p.productIdentifier)
                
                let prodID = p.productIdentifier as String
                switch prodID {
                    case "seemu.iap.removeads":
                        println("remove ads")
                        removeAds()
                    case "seemu.iap.addcoins":
                        println("add coins to account")
                        addCoins()
                    default:
                        println("IAP not setup")
                }
                
                queue.finishTransaction(trans)
                break;
            case .Failed:
                println("buy error")
                queue.finishTransaction(trans)
                break;
            default:
                println("default")
                break;
                
            }
        }
    }
    
    // 6
    func finishTransaction(trans:SKPaymentTransaction)
    {
        println("finish trans")
    }
 
    //7
    func paymentQueue(queue: SKPaymentQueue!, removedTransactions transactions: [AnyObject]!)
    {
        println("remove trans");
    }

Resources