In-App-Purchase - Restore Purchase does not work? - ios

In my application, the users can buy PRO membership to unlock stuff.
Here is the view controllers code where the user buy PRO membership:
import UIKit
import StoreKit
class UpgradePROViewController: UIViewController, SKProductsRequestDelegate, SKPaymentTransactionObserver {
#IBOutlet weak var upgradeButton: UIButton!
var ApplicationLoadTime = NSUserDefaults().integerForKey("isPRO")
var product_id: NSString?;
let loadedValue = NSUserDefaults().integerForKey("isPRO")
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
var ApplicationLoadTimeUserDefault = NSUserDefaults.standardUserDefaults()
if (ApplicationLoadTimeUserDefault.valueForKey("isPRO") != nil){
ApplicationLoadTime = ApplicationLoadTimeUserDefault.valueForKey("isPRO") as! NSInteger!
}
upgradeButton.setTitleColor(UIColor.whiteColor(), forState: UIControlState.Normal)
upgradeButton.setTitleColor(UIColor.lightGrayColor(), forState: UIControlState.Highlighted)
upgradeButton.layer.cornerRadius = 5
upgradeButton.layer.borderWidth = 1
upgradeButton.layer.borderColor = UIColor(white: 1.0, alpha: 0.35).CGColor
upgradeButton.layer.backgroundColor = UIColor(white: 0.1, alpha: 0.85).CGColor
product_id = "com.myself.MyApp.GetPRO";
SKPaymentQueue.defaultQueue().addTransactionObserver(self)
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
#IBAction func upgradeButtonAction(sender: AnyObject) {
buyConsumable()
}
#IBAction func restoreButtonAction(sender: AnyObject) {
if (SKPaymentQueue.canMakePayments()){
SKPaymentQueue.defaultQueue().restoreCompletedTransactions()
println("Purchased Restored");
}
}
func buyConsumable(){
println("About to fetch the products");
// 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<NSObject>);
productsRequest.delegate = self;
productsRequest.start();
println("Fething Products");
}else{
println("can't make purchases");
}
}
// Helper Methods
func buyProduct(product: SKProduct){
println("Sending the Payment Request to Apple");
var payment = SKPayment(product: product)
SKPaymentQueue.defaultQueue().addPayment(payment);
}
// Delegate Methods for IAP
func productsRequest (request: SKProductsRequest, didReceiveResponse response: SKProductsResponse) {
println("got the request from Apple")
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) {
println(validProduct.localizedTitle)
println(validProduct.localizedDescription)
println(validProduct.price)
buyProduct(validProduct);
} else {
println(validProduct.productIdentifier)
}
} else {
println("nothing")
}
}
func request(request: SKRequest!, didFailWithError error: NSError!) {
println("La vaina fallo");
}
func unlockProFeatures(){
ApplicationLoadTime = 1
NSString(format: "isPRO", "%i", 1)
var ApplicationLoadTimeUserDefault = NSUserDefaults.standardUserDefaults()
ApplicationLoadTimeUserDefault.setValue(ApplicationLoadTime, forKey: "isPRO")
ApplicationLoadTimeUserDefault.synchronize()
}
func paymentQueue(queue: SKPaymentQueue!, updatedTransactions transactions: [AnyObject]!) {
println("Received Payment Transaction Response from Apple");
for transaction:AnyObject in transactions {
if let trans:SKPaymentTransaction = transaction as? SKPaymentTransaction{
switch trans.transactionState {
case .Purchased:
SKPaymentQueue.defaultQueue().finishTransaction(transaction as! SKPaymentTransaction)
println("Product Purchased");
unlockProFeatures()
break;
case .Failed:
SKPaymentQueue.defaultQueue().finishTransaction(transaction as! SKPaymentTransaction)
println("Purchased Failed");
break;
case .Restored:
SKPaymentQueue.defaultQueue().restoreCompletedTransactions()
println("Purchased Restored");
break;
default:
break;
}
}
}
}
}
Somehow, it looks like the restore purchase does not work.. I am testing using sandbox users. Does anybody has any suggestions what to do? It works all fine to buy the items, but when I try to restore the purchase with the same user that has purchased the item, it does not work. Anything wrong in my code, or anything you would do different?

Related

Redeem Button for in app purchases

I submitted my app to apple but they rejected it because, there was no redeem button for in app purchases. How can i do that. I made a redeem button and linked it up to the view controller. Where do i go from there?
Here is my code:
class StoreViewController: UIViewController, SKPaymentTransactionObserver, SKProductsRequestDelegate {
#IBOutlet var redeemOutlet: UIButton!
#IBAction func redeem(_ sender: Any) {
}
#IBOutlet var productDescription: UITextView!
var product: SKProduct?
let productID = "com.myCoolAwesomeApp.mjay.noAdvertisements"
#IBOutlet var buyButton: UIButton!
#IBOutlet var returnButton: UIButton!
override func viewDidLoad() {
super.viewDidLoad()
buyButton.layer.cornerRadius = 5.0
returnButton.layer.cornerRadius = 5.0
buyButton.isEnabled = false
SKPaymentQueue.default().add(self)
getPurchaseInfo()
// Do any additional setup after loading the view.
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
#IBAction func purchase(_ sender: Any) {
let payment = SKPayment(product: product!)
SKPaymentQueue.default().add(payment)
}
#IBAction func dismissView(_ sender: Any) {
//self.dismiss(animated: true, completion: nil)
}
func getPurchaseInfo() {
if SKPaymentQueue.canMakePayments() {
let request = SKProductsRequest(productIdentifiers: NSSet(objects: self.productID) as! Set<String>)
request.delegate = self
request.start()
} else {
productDescription.text = "Please enable In App Purchases in your settings."
}
}
func productsRequest(_ request: SKProductsRequest, didReceive response: SKProductsResponse) {
var products = response.products
if (products.count) == 0 {
productDescription.text = "Product not found."
} else {
product = products[0]
productDescription.text = "Remove all advertisements within the game for $0.99"
buyButton.isEnabled = true
}
let invalids = response.invalidProductIdentifiers
for product in invalids {
print("Product not found: \(product)")
}
}
func paymentQueue(_ queue: SKPaymentQueue, updatedTransactions transactions: [SKPaymentTransaction]) {
for transaction in transactions {
switch transaction.transactionState {
case SKPaymentTransactionState.purchased:
SKPaymentQueue.default().finishTransaction(transaction)
productDescription.text = "Purchase Successful"
buyButton.isEnabled = false
let save = UserDefaults.standard
save.set(true, forKey: "Purchase")
save.synchronize()
case SKPaymentTransactionState.failed:
SKPaymentQueue.default().finishTransaction(transaction)
productDescription.text = "Purchase Failed. Try again later."
default:
break
}
}
}
}

Restore Purchase working but it is looping constantly

I'm trying to implement In App Purchase in iOS using Swift, but the Restore Purchase functionality is giving problem. Whenever I click on the restore purchase button it is working fine but it keeps adding it to the queue. Please Help.
Below is my code and output.
In the output "IAP not setup method3" keeps on increasing by one whenever I click on Restore Purchase button.
import UIKit
import StoreKit
class PremiumUpgradeVC: UIViewController , SKProductsRequestDelegate, SKPaymentTransactionObserver{
#IBOutlet weak var uiScrollVw: UIScrollView!
#IBOutlet weak var btnPremiumPurchase: UIButton!
#IBOutlet weak var btnPrice: UIButton!
#IBOutlet weak var btnRestorePur: UIButton!
var removeAds : Bool = false
var enableCompilations : Bool = false
var premiumPurchasedKey : String = "isPremiumPurchased"
var list = [SKProduct]()
var p = SKProduct()
var IAPId = "com.creativecub.testme"
override func viewDidLoad() {
super.viewDidLoad()
if(SKPaymentQueue.canMakePayments()){
print("IAP is enabled, loading")
var productID:NSSet = NSSet(objects: IAPId)
var request :SKProductsRequest = SKProductsRequest(productIdentifiers : productID as! Set<String>)
request.delegate = self
request.start()
//loadingAlert.
}else{
print("please enable IAP")
}
}
#IBAction func actionGoPremium(sender: UIButton) {
print("on action button")
for product in list{
var prodID = product.productIdentifier
if(prodID == IAPId){
p = product
buyProduct()
break;
}
}
}
func goPremi(){
print("in method : gopremium")
// removeAds = true
// enableCompilations = true
HelperClass.setValSharedPerf(premiumPurchasedKey, value: "true")
print("ads removed and compilations enables .. Enjoy")
}
#IBAction func actionRestorePurchase(sender: UIButton) {
print("in method : 1")
SKPaymentQueue.defaultQueue().addTransactionObserver(self) SKPaymentQueue.defaultQueue().restoreCompletedTransactions()
}
func buyProduct() {
print("buy product -" + p.productIdentifier)
let pay = SKPayment(product: p)
SKPaymentQueue.defaultQueue().addTransactionObserver(self)
SKPaymentQueue.defaultQueue().addPayment(pay as SKPayment)
print("in method : 2")
}
//restored transaction function
func paymentQueueRestoreCompletedTransactionsFinished(queue: SKPaymentQueue) {
print("in method : 3")
//print("transaction retsored")
var purchasedItemIDs = []
for transaction in queue.transactions{
let t: SKPaymentTransaction = transaction
let prodID = t.payment.productIdentifier as String
switch prodID {
case IAPId:
print("premium Upgrade method 3")
goPremi()
SKPaymentQueue.defaultQueue().finishTransaction(transaction as SKPaymentTransaction)
default:
print("IAP not setup method3") // this keeps increasing
}
}
}
func productsRequest(request: SKProductsRequest, didReceiveResponse response: SKProductsResponse) {
print("in method : 4")
print("product request")
var myProducts = response.products
for product in myProducts {
print("product added - details :" + product.productIdentifier + product.localizedTitle)
let price = priceStringForProduct(product)
btnPrice.setTitle("Buy for: "+price!, forState: UIControlState.Normal)
list.append(product)
}
}
//restore purchase
func paymentQueue(queue: SKPaymentQueue, updatedTransactions transactions: [SKPaymentTransaction]) {
// print("added payment")
print("in method : 5")
for transaction:AnyObject in transactions{
let trans = transaction as! SKPaymentTransaction
//print(trans.error)
switch trans.transactionState {
case .Purchased: //switch1 case 1
print("buy ok, unlock IAP here")
let prodID = p.productIdentifier as String
switch prodID {
case IAPId:
print("premium Upgrade .. purchase restored")
goPremi()
queue.finishTransaction(trans)
default:
print("IAP not setup method5")
}
queue.finishTransaction(trans)
break;
case .Failed: //switch1 case 2
print("error in buy")
queue.finishTransaction(trans)
break;
default: //switch1 case 3
print("default case method 5")
break;
}
}
}
func finishTransaction(trans:SKPaymentTransaction){
print("finsh trans")
SKPaymentQueue.defaultQueue().finishTransaction(trans)
print("in method : 6")
}
func paymentQueue(queue: SKPaymentQueue, removedTransactions transactions: [SKPaymentTransaction]) {
print("remove trnas")
SKPaymentQueue.defaultQueue().removeTransactionObserver(self)
print("in method : 7")
}
func priceStringForProduct(item: SKProduct) -> String? {
let numberFormatter = NSNumberFormatter()
let price = item.price
let locale = item.priceLocale
numberFormatter.numberStyle = .CurrencyStyle
numberFormatter.locale = locale
return numberFormatter.stringFromNumber(price)
}
func goBack()
{
self.dismissViewControllerAnimated(true, completion: nil);
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
override func viewWillDisappear(animated: Bool) {
SKPaymentQueue.defaultQueue().removeTransactionObserver(self)
print("disapeard")
}
}
This is the output:
in method : 1
in method : 5
default case method 5
default case method 5
in method : 3
IAP not setup method3 //this statement keep increasing on button click
IAP not setup method3
IAP not setup method3
IAP not setup method3
IAP not setup method3
premium Upgrade method 3
in method : gopremium
ads removed and compilations enables .. Enjoy
remove trnas
in method : 7
You should not do anything in paymentQueueRestoreCompletedTransactionsFinished aside from updating your UI if required. This delegate method is called to indicate that the restoration process is complete; nothing more.
The restored transactions will be delivered to your updated transactions method with a state of restored. You should process them the same as you do with the state of purchased

In-App Purchase & Restore Button : Single Product - Non-Consumable

This issue has had me going for days.
I have a simple app, that displays banners and interstitial adverts.
I am using a single view application, have main view controller (ViewController.swift) and have set up another view controller (InAppViewController.swift) to handle a pop-up page that:
Allows the user to make an in-app purchase to remove all ads (AdBanners & InterstitialAds); or
Restore purchases.
My code is error-free when I run it.
In-app purchases are running ok, but occasionally I get a sign-in request to iTunes twice.
But my restore button and associated functionality seem to be the problem.
I have set-up numerous sandbox tester accounts to test, and a new user that has not bought the app is able to restore purchases successfully. Which should not be possible, so I definitely have done something wrong here.
Here is my code:
Main View Controller:
// ViewController.swift
import UIKit
import MessageUI
import Social
import iAd
import StoreKit
class ViewController: UIViewController, MFMailComposeViewControllerDelegate, MFMessageComposeViewControllerDelegate, ADBannerViewDelegate, ADInterstitialAdDelegate
{
let defaults = NSUserDefaults.standardUserDefaults()
var product_id: NSString?;
override func viewDidLoad() {
product_id = "some.product.id";
super.viewDidLoad()
//Check if product is purchased
if (defaults.boolForKey("purchased")){
print("already purchased")
// Hide or show banner ads is purchased/not purchased.
// Advertising Banner:
self.canDisplayBannerAds = false
}
else if (!defaults.boolForKey("stonerPurchased")){
print("not yet purchased")
// Advertising Banner:
self.canDisplayBannerAds = true
}
This code seems to work perfectly. When the app loads, it is able to determine who has paid to remove ads and those who have not paid, and ad banners are shown appropriately.
It is in the second view controller (InAppPViewController.swift) That I am having problems.
here is my code:
Second View Controller - InAppViewController.swift:
// InAppPViewController.swift
import UIKit
import StoreKit
import iAd
class InAppPViewController: UIViewController, SKProductsRequestDelegate, SKPaymentTransactionObserver {
let defaults = NSUserDefaults.standardUserDefaults()
var product_id: NSString?;
#IBOutlet weak var unlockAction: UIButton!
#IBOutlet var adBannerView: ADBannerView?
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
#IBAction func restorePurchases(sender: UIButton) {
SKPaymentQueue.defaultQueue().addTransactionObserver(self)
SKPaymentQueue.defaultQueue().restoreCompletedTransactions()
}
func paymentQueueRestoreCompletedTransactionsFinished(queue: SKPaymentQueue) {
print("Transactions Restored")
let alert = UIAlertView(title: "Thank You", message: "Your purchase(s) were restored.", delegate: nil, cancelButtonTitle: "OK")
alert.show()
}
#IBAction func unlockAction(sender: AnyObject) {
product_id = "some.product.id";
SKPaymentQueue.defaultQueue().addTransactionObserver(self)
//Check if product is purchased
if (defaults.boolForKey("purchased")){
}
else if (!defaults.boolForKey("stonerPurchased")){
print("false")
}
print("About to fetch the products");
// We check that we are allowed to make the purchase.
if (SKPaymentQueue.canMakePayments())
{
let productID:NSSet = NSSet(object: self.product_id!);
let productsRequest:SKProductsRequest = SKProductsRequest(productIdentifiers: productID as! Set<String>);
productsRequest.delegate = self;
productsRequest.start();
print("Fething Products");
}else{
print("can't make purchases");
}
}
func buyProduct(product: SKProduct){
print("Sending the Payment Request to Apple");
let payment = SKPayment(product: product)
SKPaymentQueue.defaultQueue().addPayment(payment);
}
//Delegate Methods for IAP
func productsRequest (request: SKProductsRequest, didReceiveResponse 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(validProduct);
} else {
print(validProduct.productIdentifier)
}
} else {
print("nothing")
}
}
func request(request: SKRequest, didFailWithError error: NSError) {
print("Error Fetching product information");
}
func paymentQueue(queue: SKPaymentQueue, updatedTransactions transactions: [SKPaymentTransaction]) {
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.defaultQueue().finishTransaction(transaction as! SKPaymentTransaction)
defaults.setBool(true , forKey: "purchased")
break;
case .Failed:
print("Purchased Failed");
SKPaymentQueue.defaultQueue().finishTransaction(transaction as! SKPaymentTransaction)
break;
case .Restored:
print("Already Purchased");
SKPaymentQueue.defaultQueue().restoreCompletedTransactions()
default:
break;
}
}
}
}
}
Where am I going wrong?
Questions:
Is my above code correct?
What should I modify and why?
Apologies in advance, I am new to this wonderful world of coding ... but loving every minute of it!
SKPaymentQueue.defaultQueue().addTransactionObserver(self) should be in viewDidLoad() not in restore func
You can put SKPaymentQueue.defaultQueue().restoreCompletedTransactions() like this
override func viewWillDisappear(animated: Bool) {
SKPaymentQueue.defaultQueue().removeTransactionObserver(self)
}
login twice in sandbox is normal.
hope I helped with something.
I have amended my code for the InAppPViewController.swift file as follows:
// InAppPViewController.swift
import UIKit
import StoreKit
class InAppPViewController: UIViewController, SKProductsRequestDelegate, SKPaymentTransactionObserver {
let defaults = NSUserDefaults.standardUserDefaults()
var product_id: NSString?;
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
#IBAction func restorePurchases(sender: UIButton) {
// Set up the observer
SKPaymentQueue.defaultQueue().addTransactionObserver(self)
//Check if user can make payments and then proceed to restore purchase
if (SKPaymentQueue.canMakePayments()) {
SKPaymentQueue.defaultQueue().restoreCompletedTransactions()
}
}
#IBAction func unlockAction(sender: AnyObject) {
product_id = "some.product.id";
// Adding the observer
SKPaymentQueue.defaultQueue().addTransactionObserver(self)
//Check if product is purchased
if (defaults.boolForKey("purchased")){
print("User already purchased this")
// Hide a view or show content depends on your requirement
}
else if (!defaults.boolForKey("Purchased")){
print("User has not yet pur hased this")
}
print("About to fetch the products");
// Check if user can make payments and then proceed to make the purchase.
if (SKPaymentQueue.canMakePayments())
{
let productID:NSSet = NSSet(object: self.product_id!);
let productsRequest:SKProductsRequest = SKProductsRequest(productIdentifiers: productID as! Set<String>);
productsRequest.delegate = self;
productsRequest.start();
print("User can make purchases and will fetch products from Apple Store now");
}else{
print("User can't make purchases");
}
}
func buyProduct(product: SKProduct){
print("Sending the Payment Request to Apple");
let payment = SKPayment(product: product)
SKPaymentQueue.defaultQueue().addPayment(payment);
}
func productsRequest (request: SKProductsRequest, didReceiveResponse 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(validProduct);
} else {
print(validProduct.productIdentifier)
}
} else {
print("nothing")
}
}
func request(request: SKRequest, didFailWithError error: NSError) {
print("Error Fetching product information");
}
// Allowing for all possible outcomes:
func paymentQueue(queue: SKPaymentQueue, updatedTransactions transactions: [SKPaymentTransaction]) {
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")
let alert = UIAlertView(title: "Thank You", message: "Thank you for your purchase!", delegate: nil, cancelButtonTitle: "OK")
alert.show();
SKPaymentQueue.defaultQueue().finishTransaction(transaction as! SKPaymentTransaction)
defaults.setBool(true , forKey: "purchased")
break;
case .Failed:
print("Purchased Failed");
SKPaymentQueue.defaultQueue().finishTransaction(transaction as! SKPaymentTransaction)
break;
case .Restored:
print("Already Purchased");
SKPaymentQueue.defaultQueue().restoreCompletedTransactions()
break;
default:
break;
}
}
}
}
}
I left the ViewController.swift file as is.
Product purchases seem to work now.
But regarding Restore Purchases, I can run the code on my physical device, but cannot test the Restore Purchases function.
I am caught with previous Restore Purchases that are still unresolved and looping in the system. I am unable to clear my SKPaymentsQueue manually. Thus my code refuses to entertain anymore new Restore Purchase requests.

productsRequest not working in swift for In-App Purchases

I wrote some code to get my In-app purchase to get rid on my ads. The response comes back blank, and comes back with error because it is nil here is my full code for In-App Purchase:
override func viewDidLoad() {
super.viewDidLoad()
outRemoveAds.enabled = false
if(SKPaymentQueue.canMakePayments()) {
println("IAP is enabled, loading")
var productID:NSSet = NSSet(objects: "com.webstart.tomsgamesinc.StartLight_No_Ads")
var request: SKProductsRequest = SKProductsRequest(productIdentifiers: productID as Set<NSObject>)
request.delegate = self
request.start()
} else {
println("please enable IAPS")
}
// Do any additional setup after loading the view.
}
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")
println(response.products)
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
}
// 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 "com.webstart.tomsgamesinc.StartLight_No_Ads":
println("remove ads")
removeAds()
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 "com.webstart.tomsgamesinc.StartLight_No_Ads":
println("remove ads")
removeAds()
println("add coins to account")
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")
SKPaymentQueue.defaultQueue().finishTransaction(trans)
}
//7
func paymentQueue(queue: SKPaymentQueue!, removedTransactions transactions: [AnyObject]!)
{
println("remove trans");
}
#IBAction func btnRemoveAds(sender: UIButton) {
for product in list {
println("ProdID")
var prodID = product.productIdentifier
println(prodID)
if(prodID == "com.webstart.tomsgamesinc.StartLight_No_Ads") {
p = product
buyProduct()
break;
}
}
}
I did add the purchase in iTunes connect.
I have updated your code like this:
import UIKit
import StoreKit
class ViewController: UIViewController, SKProductsRequestDelegate, SKPaymentTransactionObserver {
var productID = "com.webstart.tomsgamesinc.StartLight_No_Ads"
var product: SKProduct?
var isProductRecive = false
override func viewDidLoad() {
super.viewDidLoad()
getProductInfo()
SKPaymentQueue.defaultQueue().addTransactionObserver(self)
}
#IBAction func btnRemoveAds(sender: UIButton) {
if isProductRecive{
let payment = SKPayment(product: product)
SKPaymentQueue.defaultQueue().addPayment(payment)
}else{
let alert = UIAlertView()
alert.title = "Alert"
alert.message = "Retriving product please wait."
alert.addButtonWithTitle("Ok")
alert.show()
getProductInfo()
}
}
func getProductInfo()
{
if SKPaymentQueue.canMakePayments() {
let request = SKProductsRequest(productIdentifiers: NSSet(objects: self.productID) as Set<NSObject>)
request.delegate = self
request.start()
} else {
let alert = UIAlertView()
alert.title = "Alert"
alert.message = "Please enable In App Purchase in Settings."
alert.addButtonWithTitle("Ok")
alert.show()
}
}
//3
func productsRequest(request: SKProductsRequest!, didReceiveResponse response: SKProductsResponse!) {
var products = response.products
if (products.count != 0) {
product = products[0] as? SKProduct
self.isProductRecive = true
println(product)
} else {
let alert = UIAlertView()
alert.title = "Alert"
alert.message = "Product not found"
alert.addButtonWithTitle("Ok")
alert.show()
}
products = response.invalidProductIdentifiers
for product in products
{
println("Product not found: \(product)")
}
}
// 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 "com.webstart.tomsgamesinc.StartLight_No_Ads":
println("remove ads")
default:
println("IAP not setup")
}
}
}
// 5
func paymentQueue(queue: SKPaymentQueue!, updatedTransactions transactions: [AnyObject]!) {
for transaction in transactions as! [SKPaymentTransaction] {
switch transaction.transactionState {
case .Restored:
SKPaymentQueue.defaultQueue().finishTransaction(transaction)
case .Purchased:
SKPaymentQueue.defaultQueue().finishTransaction(transaction)
case .Failed:
SKPaymentQueue.defaultQueue().finishTransaction(transaction)
default:
break
}
}
}
func request(request: SKRequest!, didFailWithError error: NSError!) {
println("There was an error");
}
}
And it is working fine with my app bundle ID an product ID so kindly check into iTunes connect problem should be there.
This code is working for my game and returns back how many products there are to purchase. Works for xCode 7.1.1.
var products = [SKProduct]()
var product: SKProduct?
//StoreKit protocol method. Called when the AppStore responds
func productsRequest(request: SKProductsRequest, didReceiveResponse response: SKProductsResponse) {
var item = response.products
if item.count != 0 {
for var i = 0; i < item.count; i++ {
product = item[i] as SKProduct
products.append(product!)
}
}
print("There are \(products.count) items to buy.")
}

How can I if my app will remember that I bought In-App Purchase

I have made an app and made an In-App purchase for the premium version. Because I can't test In-App purchases in the Simulator.
So here is my code:
class settingsViewController: UIViewController, SKProductsRequestDelegate, SKPaymentTransactionObserver, ADBannerViewDelegate {
#IBOutlet var adBennerView: ADBannerView!
#IBOutlet var outletRemoveAds: UIButton!
override func viewDidLoad() {
super.viewDidLoad()
if(SKPaymentQueue.canMakePayments()) {
println("IAP is enabled, loading")
var productID:NSSet = NSSet(objects: "xxx")
var request: SKProductsRequest = SKProductsRequest(productIdentifiers: productID as Set<NSObject>)
request.delegate = self
request.start()
} else {
println("please enable IAPS")
}
// Do any additional setup after loading the view.
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
#IBAction func removeAds(sender: AnyObject) {
for product in list {
var prodID = product.productIdentifier
if(prodID == "xxx") {
p = product
buyProduct()
break;
}
}
}
#IBAction func restorePurchases(sender: AnyObject) {
SKPaymentQueue.defaultQueue().addTransactionObserver(self)
SKPaymentQueue.defaultQueue().restoreCompletedTransactions()
}
var list = [SKProduct]()
var p = SKProduct()
func buyProduct() {
println("buy " + p.productIdentifier)
var pay = SKPayment(product: p)
SKPaymentQueue.defaultQueue().addTransactionObserver(self)
SKPaymentQueue.defaultQueue().addPayment(pay as SKPayment)
}
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)
}
outletRemoveAds.enabled = true
}
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 "xxx":
println("remove ads")
removeAds()
isPremium = true
default:
println("IAP not setup")
}
queue.finishTransaction(trans)
break;
case .Failed:
println("buy error")
queue.finishTransaction(trans)
break;
default:
println("default")
break;
}
}
}
func finishTransaction(trans:SKPaymentTransaction)
{
println("finish trans")
SKPaymentQueue.defaultQueue().finishTransaction(trans)
}
func paymentQueue(queue: SKPaymentQueue!, removedTransactions transactions: [AnyObject]!)
{
println("remove trans");
}
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 "xxx":
println("remove ads")
removeAds()
isPremium = true
default:
println("IAP not setup")
}
}
}
func removeAds() {
adBennerView!.removeFromSuperview()
}
If the user bought the premium version - isPremium becomes true, so how do I know that every time the user log in isPremium still be true?
That happens because you only storing isPremium in the RAM and not anywhere else. Try using NSUserDefaults for that purpose, just to see how it can be done (actually it is advised not to use NSUserDefaults for that type of information, because it is easy to hack, but you have to understand the basics of storing information about your app state).

Resources