Last active
          April 29, 2021 04:07 
        
      - 
      
- 
        Save speaktoalvin/7c61bab7a401e22ee8c5 to your computer and use it in GitHub Desktop. 
    In App Purchase in Swift, with Receipt Validation
  
        
  
    
      This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
      Learn more about bidirectional Unicode characters
    
  
  
    
  | import UIKit | |
| import StoreKit | |
| //MARK: SKProductsRequestDelegate | |
| extension IAPHelpers : SKProductsRequestDelegate | |
| { | |
| func productsRequest(request: SKProductsRequest, didReceiveResponse response: SKProductsResponse) | |
| { | |
| if response.products.count > 0 | |
| { | |
| let validProduct : SKProduct = response.products[0] | |
| switch validProduct.productIdentifier { | |
| case PRODUCT_IDENTIFIERS.k_10_WORDS_PRODUCT_IDENTIFIER.rawValue : | |
| self.buyProduct(validProduct) | |
| case PRODUCT_IDENTIFIERS.k_20_WORDS_PRODUCT_IDENTIFIER.rawValue : | |
| self.buyProduct(validProduct) | |
| case PRODUCT_IDENTIFIERS.k_ALL_WORDS_PRODUCT_IDENTIFIER.rawValue : | |
| self.buyProduct(validProduct) | |
| default : | |
| self.alertThis("Sorry", message: "No products recieved from server", current: self.currentViewController) | |
| } | |
| } else { | |
| self.alertThis("Sorry", message: "Can't make payments, Please check in settings.", current: self.currentViewController) | |
| } | |
| } | |
| } | |
| extension IAPHelpers : SKRequestDelegate | |
| { | |
| func requestDidFinish(request: SKRequest) | |
| { | |
| } | |
| func request(request: SKRequest, didFailWithError error: NSError) | |
| { | |
| self.alertThis("Sorry", message: "\(error.localizedDescription)", current: self.currentViewController) | |
| } | |
| } | |
| //MARK: SKPaymentTransactionObserver | |
| extension IAPHelpers : SKPaymentTransactionObserver | |
| { | |
| func paymentQueue(queue: SKPaymentQueue, updatedTransactions transactions: [SKPaymentTransaction]) | |
| { | |
| self.handlingTransactions(transactions) | |
| } | |
| func paymentQueueRestoreCompletedTransactionsFinished(queue: SKPaymentQueue) | |
| { | |
| if queue.transactions.count == 0 | |
| { | |
| self.alertThis("Sorry", message: "You didnt make any purchase to restiore, Please do a purchase first.", current: self.currentViewController) | |
| } | |
| else | |
| { | |
| self.handlingTransactions(queue.transactions) | |
| } | |
| } | |
| func paymentQueue(queue: SKPaymentQueue, restoreCompletedTransactionsFailedWithError error: NSError) | |
| { | |
| self.alertThis("Sorry", message: "\(error.localizedDescription)", current: self.currentViewController) | |
| } | |
| } | |
| enum PRODUCT_IDENTIFIERS : String | |
| { | |
| //MARK: Product ID's | |
| case k_10_WORDS_PRODUCT_IDENTIFIER = "YOUR_PRODUCT_IDENTIFIER_10" | |
| case k_20_WORDS_PRODUCT_IDENTIFIER = "YOUR_PRODUCT_IDENTIFIER_20" | |
| case k_ALL_WORDS_PRODUCT_IDENTIFIER = "YOUR_PRODUCT_IDENTIFIER_ALL" | |
| case k_RESTORE_WORDS_PRODUCT_IDENTIFIER = "YOUR_PRODUCT_IDENTIFIER_RESTOREE" | |
| } | |
| enum USER_DEFAULTS_IDENTIFIERS : String | |
| { | |
| case TEN_WORDS_PRODUCT_IDENTIFIER = "10_WORDS_IDENTIFIER" | |
| case TWENTY_WORDS_PRODUCT_IDENTIFIER = "20_WORDS_IDENTIFIER" | |
| case ALL_WORDS_PRODUCT_IDENTIFIER = "ALL_WORDS_IDENTIFIER" | |
| } | |
| enum ReceiptURL : String | |
| { | |
| case sandbox = "https://sandbox.itunes.apple.com/verifyReceipt" | |
| case production = "https://buy.itunes.apple.com/verifyReceipt" | |
| case myServer = "your server" | |
| } | |
| protocol StoreRequestIAPPorotocol | |
| { | |
| func transactionCompletedForRequest(PRODUCT_ID : String) | |
| } | |
| class IAPHelpers: NSObject { | |
| //MARK: Variables | |
| var delegate : StoreRequestIAPPorotocol! | |
| var currentViewController : UIViewController! | |
| //MARK: - Creating sharedInstance | |
| class var sharedInstance: IAPHelpers { | |
| struct Static { | |
| static var sharedInstance: IAPHelpers? | |
| static var token: dispatch_once_t = 0 | |
| } | |
| dispatch_once(&Static.token) { | |
| Static.sharedInstance = IAPHelpers() | |
| } | |
| return Static.sharedInstance! | |
| } | |
| //MARK: Product Request | |
| func productRquestStarted(productReferenceName : String) | |
| { | |
| if (SKPaymentQueue.canMakePayments()) { | |
| if productReferenceName == PRODUCT_IDENTIFIERS.k_RESTORE_WORDS_PRODUCT_IDENTIFIER.rawValue | |
| { | |
| self.restorePurchases() | |
| } | |
| else | |
| { | |
| let productID : Set<String> = [productReferenceName] | |
| let productsRequest : SKProductsRequest = SKProductsRequest(productIdentifiers: productID) | |
| productsRequest.delegate = self | |
| productsRequest.start() | |
| } | |
| } else { | |
| // PRESENT A USER FOR UI about not being able to make payments. | |
| } | |
| } | |
| //MARK: Buy Product - Payment Section | |
| func buyProduct(product : SKProduct) | |
| { | |
| let payment = SKPayment(product: product) | |
| SKPaymentQueue.defaultQueue().addTransactionObserver(self) | |
| SKPaymentQueue.defaultQueue().addPayment(payment) | |
| } | |
| //MARK: Restore Transaction | |
| func restoreTransaction(transaction : SKPaymentTransaction) | |
| { | |
| self.deliverProduct(transaction.payment.productIdentifier) | |
| } | |
| //MARK: Restore Purchases | |
| func restorePurchases() | |
| { | |
| SKPaymentQueue.defaultQueue().addTransactionObserver(self) | |
| SKPaymentQueue.defaultQueue().restoreCompletedTransactions() | |
| } | |
| //MARK: - Showing UIAlertView | |
| func alertThis(title : String, message : String, current : UIViewController) | |
| { | |
| let alertView : UIAlertController = UIAlertController(title: title, message: message, preferredStyle: UIAlertControllerStyle.Alert) | |
| alertView.addAction(UIAlertAction(title: "Okay", style: UIAlertActionStyle.Default, handler: { _ in | |
| })) | |
| current.presentViewController(alertView, animated: true, completion: nil) | |
| } | |
| //MARK: Transaction Observer Handler | |
| func handlingTransactions(transactions : [AnyObject]) | |
| { | |
| for transaction in transactions { | |
| if let paymentTransaction : SKPaymentTransaction = transaction as? SKPaymentTransaction { | |
| switch paymentTransaction.transactionState { | |
| case .Purchasing : | |
| print("Purchasing") | |
| case .Purchased : | |
| self.deliverProduct(paymentTransaction.payment.productIdentifier) | |
| SKPaymentQueue.defaultQueue().finishTransaction(transaction as! SKPaymentTransaction) | |
| break | |
| case .Failed: | |
| SKPaymentQueue.defaultQueue().finishTransaction(transaction as! SKPaymentTransaction) | |
| break | |
| case .Restored: | |
| print("Restored") | |
| self.restoreTransaction(paymentTransaction) | |
| break | |
| default: | |
| print("DEFAULT") | |
| // PRESENT A USER FOR UI about not being able to make payments. | |
| break | |
| } | |
| } | |
| } | |
| } | |
| //MARK: Deliver Product | |
| func deliverProduct(product : String) | |
| { | |
| self.validateReceipt { status in | |
| if status | |
| { | |
| self.delegate.transactionCompletedForRequest(product) | |
| } | |
| else | |
| { | |
| print("Something bad happened") | |
| } | |
| } | |
| } | |
| //MARK: Receipt Validation | |
| func validateReceipt(completion : (status : Bool) -> ()) { | |
| let receiptUrl = NSBundle.mainBundle().appStoreReceiptURL | |
| let receipt: NSData = NSData(contentsOfURL: receiptUrl!)! | |
| let receiptdata: NSString = receipt.base64EncodedStringWithOptions(NSDataBase64EncodingOptions(rawValue: 0)) | |
| let dict = ["receipt-data" : receiptdata] | |
| let jsonData = try! NSJSONSerialization.dataWithJSONObject(dict, options: NSJSONWritingOptions(rawValue: 0)) | |
| let request = NSMutableURLRequest(URL: NSURL(string: ReceiptURL.sandbox.rawValue)!) | |
| let session = NSURLSession.sharedSession() | |
| request.HTTPMethod = "POST" | |
| request.HTTPBody = jsonData | |
| let task = session.dataTaskWithRequest(request, completionHandler: { data, response, error in | |
| if let dataR = data | |
| { | |
| self.handleData(dataR, completion: { status in | |
| completion(status: status) | |
| }) | |
| } | |
| }) | |
| task.resume() | |
| } | |
| func handleData(responseDatas : NSData, completion : (status : Bool) -> ()) | |
| { | |
| if let json = try! NSJSONSerialization.JSONObjectWithData(responseDatas, options: NSJSONReadingOptions.MutableLeaves) as? NSDictionary | |
| { | |
| if let value = json.valueForKeyPath("status") as? Int | |
| { | |
| if value == 0 | |
| { | |
| completion(status: true) | |
| } | |
| else | |
| { | |
| completion(status: false) | |
| } | |
| } | |
| else | |
| { | |
| completion(status: false) | |
| } | |
| } | |
| } | |
| } | |
  
    Sign up for free
    to join this conversation on GitHub.
    Already have an account?
    Sign in to comment
  
            
Hi,
Where do i need to call the function : validateReceipt ?
I mean in viewDidload?
thanks