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

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
}
}
}
}

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

sign in required environment sandbox issue

Everytime I build an adhoc build and runs it on ios 11 it keeps popping up the message saying "Sign-In Required - Enter the password for ***** [Environment:Sandbox]". Thus, this keep activating like a loop and not going away. tried siging out from iCloud also but didn't work.My inAppPurchase code as bellow.
class InAppPurchase: NSObject,SKProductsRequestDelegate,
SKPaymentTransactionObserver {
///Singleton
private static var inappPurChase:InAppPurchase?;
public static var shared:InAppPurchase {
if inappPurChase == nil{
inappPurChase = InAppPurchase()
}
return inappPurChase!
}
override private init() {
//Singleton complete
}
////////////
var productsList = [SKProduct]()
var productToPurchase = SKProduct()
var productID = ""
let PURCHASE_ID_PREFIX = ""//"com.purelightbeta."
var onInAppPurchaseSuccess: (()->Void )? = nil
var onInAppPurchaseError: (()->Void )? = nil
var onNoProductsIDs: (()->Void )? = nil
var appEnvironment: ((String,Bool)->Void )? = nil
var onReceiptVarificationError: (()->Void )? = nil
var onRestorePurchaseError: ((String)->Void )? = nil
var onRestoreProductsIDs: ((NSMutableArray)->Void )? = nil
public func initPayment (productID: String) {
self.productID = PURCHASE_ID_PREFIX + productID
print("Initializing Purchase Product ID: \(self.productID)")
if SKPaymentQueue.canMakePayments() {
let productID: NSSet = NSSet(objects: self.productID)
let request: SKProductsRequest = SKProductsRequest(productIdentifiers: productID as! Set<String>)
request.delegate = self
request.start()
}else {
print("In App Purchases not enabled")
}
}
func buyProduct() {
let payment = SKPayment(product: productToPurchase)
SKPaymentQueue.default().add(self)
SKPaymentQueue.default().add(payment as SKPayment)
}
public func productsRequest(_ request: SKProductsRequest, didReceive response: SKProductsResponse) {
let myProducts = response.products
print(myProducts)
productsList = []
if myProducts.count == 0 {
print("No products")
if(onNoProductsIDs != nil){
onNoProductsIDs!()
}
}
for product in myProducts {
print("Prod Details :\(product.productIdentifier) \(product.price) \(product.localizedDescription)")
productsList.append(product)
}
for product in productsList {
let productID = product.productIdentifier
if productID == self.productID {
productToPurchase = product
buyProduct()
}
}
}
func paymentQueueRestoreCompletedTransactionsFinished(_ queue: SKPaymentQueue) {
let productIDs: NSMutableArray = []
for trasacton in queue.transactions {
if trasacton.transactionState == SKPaymentTransactionState.restored
{
let t: SKPaymentTransaction = trasacton as SKPaymentTransaction
let prodID = t.payment.productIdentifier as String
print("prodID:",prodID)
//let appStoreId = prodID.components(separatedBy: "com.purelightbeta.")
productIDs.add(prodID)
SKPaymentQueue .default().finishTransaction(trasacton)
}
}
if onRestoreProductsIDs != nil {
print(productIDs)
onRestoreProductsIDs! (productIDs)
}
}
func paymentQueue(_ queue: SKPaymentQueue, updatedTransactions transactions: [SKPaymentTransaction]) {
for transaction: AnyObject in transactions {
let trans = transaction as! SKPaymentTransaction
print(trans.error ?? "No in app error")
switch trans.transactionState {
case .purchased:
print("buy ok, AIP unlocked for item :", productToPurchase.productIdentifier)
let productID = productToPurchase.productIdentifier
switch productID {
case self.productID:
print("Item found")
// startValidatingReceipt()
default:
print("Item not found")
}
queue.finishTransaction(trans)
if self.onInAppPurchaseSuccess != nil {
self.onInAppPurchaseSuccess! ()
self.startValidatingReceipt()
}
case .failed:
print("buy error")
if self.onInAppPurchaseError != nil {
self.onInAppPurchaseError! ()
}
queue.finishTransaction(trans)
break
case .restored:
SKPaymentQueue.default().finishTransaction(transaction as! SKPaymentTransaction)
// break
default:
print("default")
break
}
}
}
func paymentQueue(_ queue: SKPaymentQueue, restoreCompletedTransactionsFailedWithError error: Error) {
print("ERROR: \(error.localizedDescription)")
if onRestorePurchaseError != nil {
onRestorePurchaseError! (error.localizedDescription)
}
}
func restorePurchase() {
SKPaymentQueue.default().add(self)
SKPaymentQueue.default().restoreCompletedTransactions()
}
func startValidatingReceipt() {
if let isExists = try? self.getReceiptURL()?.checkResourceIsReachable(), isExists == true {
do {
let data = try Data(contentsOf: self.getReceiptURL()!)
// self.startValidatingData(data: data)
self.sendReceiptToLocalServer(data: data)
}catch {
let appReceiptRefreshRequest = SKReceiptRefreshRequest(receiptProperties: nil)
appReceiptRefreshRequest.delegate = self
appReceiptRefreshRequest.start()
}
}else {
print("No receipt for this purchase")
}
}
func getReceiptURL() -> URL? {
return Bundle.main.appStoreReceiptURL
}
enum receiptValidationURLs:String {
case sandbox = "https://sandbox.itunes.apple.com/verifyReceipt"
case production = "https://buy.itunes.apple.com/verifyReceipt"
static var url:URL{
if isDebug {
return URL.init(string: self.sandbox.rawValue)!
}else{
return URL.init(string: self.production.rawValue)!
}
}
}
func sendReceiptToLocalServer(data:Data) {
let base64encodedReceipt = data.base64EncodedString()
if self.appEnvironment != nil {
self.appEnvironment! (base64encodedReceipt,isDebug)
}
}
func startValidatingData(data:Data){
let base64encodedReceipt = data.base64EncodedString()
print(base64encodedReceipt)
let requestDictionary = ["receipt-data":base64encodedReceipt]
guard JSONSerialization.isValidJSONObject(requestDictionary) else { print("requestDictionary is not valid JSON"); return }
do {
let requestData = try JSONSerialization.data(withJSONObject: requestDictionary)
// let validationURLString = "https://sandbox.itunes.apple.com/verifyReceipt" // this works but as noted above it's best to use your own trusted server
NSLog("The Environment is: %#", receiptValidationURLs.url.absoluteString)
guard let validationURL = URL(string: receiptValidationURLs.url.absoluteString) else { print("the validation url could not be created, unlikely error"); return }
let session = URLSession(configuration: URLSessionConfiguration.default)
var request = URLRequest(url: validationURL)
request.httpMethod = "POST"
request.cachePolicy = URLRequest.CachePolicy.reloadIgnoringCacheData
let task = session.uploadTask(with: request, from: requestData) { (data, response, error) in
if let data = data , error == nil {
do {
let appReceiptJSON = try JSONSerialization.jsonObject(with: data)
print((appReceiptJSON as AnyObject).count)
print("success. here is the json representation of the app receipt: \(appReceiptJSON)")
NSLog("Receipt is: %#", appReceiptJSON as! NSDictionary)
if let environment = (appReceiptJSON as? NSDictionary)?["environment"]{
if self.appEnvironment != nil {
self.appEnvironment! (environment as? String ?? "No value",isDebug)
}
}
} catch let error as NSError {
print("json serialization failed with error: \(error)")
}
} else {
print("the upload task returned an error: \(error)")
}
}
task.resume()
} catch let error as NSError {
print("json serialization failed with error: \(error)")
}
}
// func requestDidFinish(_ request: SKRequest) {
// // a fresh receipt should now be present at the url
// do {
//
//
//
// } catch {
// // still no receipt, possible but unlikely to occur since this is the "success" delegate method
// }
// }
func request(_ request: SKRequest, didFailWithError error: Error) {
print("app receipt refresh request did fail with error: \(error)")
// for some clues see here: https://samritchie.net/2015/01/29/the-operation-couldnt-be-completed-sserrordomain-error-100/
if self.onReceiptVarificationError != nil {
self.onReceiptVarificationError! ()
}
}
}
This may not be the answer but would be a workaround. Best is to create a new sandbox user, sign out the old one and put the new.

In-App Purchase Error , Always myProduct is 0

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

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