Skip to content

Instantly share code, notes, and snippets.

@brien-crean
Created August 31, 2016 01:03
Show Gist options
  • Save brien-crean/3140d3b6463649f3c20f0950d0c01d21 to your computer and use it in GitHub Desktop.
Save brien-crean/3140d3b6463649f3c20f0950d0c01d21 to your computer and use it in GitHub Desktop.
In App Purchases iOS - Swift 2
import Foundation;
import StoreKit;
struct ProductList {
static let twoWeekTrial : String = "twoweektrial"
static let monthlySub : String = "monthlytrial"
static let products = [twoWeekTrial, monthlySub]
}
class StoreManager: NSObject {
var loadedProducts: Dictionary<String, SKProduct> = [:]
var purchaseCallbackHolder: RCTResponseSenderBlock? = nil
var productsCallbackHolder: RCTResponseSenderBlock? = nil
var restoreCallbackHolder: RCTResponseSenderBlock? = nil
override init() {
super.init()
SKPaymentQueue.defaultQueue().addTransactionObserver(self)
}
// NOTE: Leaving this out caused all sorts of weirdness for me
deinit {
if SKPaymentQueue.canMakePayments() {
SKPaymentQueue.defaultQueue().removeTransactionObserver(self)
}
}
func getProductList(callback: RCTResponseSenderBlock){
if SKPaymentQueue.canMakePayments() {
// products from static struct
let products = NSSet(array: ProductList.products);
// When request completes, calls the SKProductsRequestDelegate
let request = SKProductsRequest(productIdentifiers: products as! Set<String>);
productsCallbackHolder = callback
request.delegate = self;
request.start();
}
}
func purchaseProduct(productIdentifier: String, callback: RCTResponseSenderBlock) {
let product = loadedProducts[productIdentifier as String]!
let payment = SKPayment(product: product)
// add callback to holder
purchaseCallbackHolder = callback
// Triggers SKPaymentTransactionObserver
SKPaymentQueue.defaultQueue().addPayment(payment)
}
func restorePurchases(callback: RCTResponseSenderBlock){
restoreCallbackHolder = callback
SKPaymentQueue.defaultQueue().restoreCompletedTransactions()
}
func validatePurchases(callback: RCTResponseSenderBlock) -> Void {
let receiptUrl = NSBundle.mainBundle().appStoreReceiptURL
let receipt: NSData = NSData(contentsOfURL:receiptUrl!)!
let receiptdata: NSString = receipt.base64EncodedStringWithOptions(NSDataBase64EncodingOptions(rawValue: 0))
// Pass Base64 encoded string back to JS
// NOTE: The Javascript handles sending the receipt to Apple (easier to handle JSON)
callback([receiptdata])
}
func getReceipt() -> NSString {
let receiptUrl = NSBundle.mainBundle().appStoreReceiptURL
let receipt: NSData = NSData(contentsOfURL:receiptUrl!)!
let receiptdata: NSString = receipt.base64EncodedStringWithOptions(NSDataBase64EncodingOptions(rawValue: 0))
return receiptdata;
}
func updateWithProducts(products: [SKProduct]) {
var productIdentifiers: Dictionary<String, NSNumber> = [:]
for product in products {
loadedProducts[product.productIdentifier] = product
productIdentifiers[product.productIdentifier] = product.price
print(product.productIdentifier)
}
productsCallbackHolder?([productIdentifiers])
productsCallbackHolder = nil
}
}
extension StoreManager: SKProductsRequestDelegate {
func productsRequest(request: SKProductsRequest, didReceiveResponse response: SKProductsResponse) {
// products retrieved from App store
let appProducts = response.products
if appProducts.count != 0 {
for product in appProducts{
print(product.productIdentifier)
}
print(appProducts)
updateWithProducts(appProducts)
}
else {
print("no products received from store")
}
}
}
extension StoreManager: SKPaymentTransactionObserver {
func paymentQueue(queue: SKPaymentQueue, updatedTransactions transactions: [SKPaymentTransaction]) {
print("Received Payment Transaction Response from Apple");
for transaction:AnyObject in transactions {
// check object is a transaction first
if let trans:SKPaymentTransaction = transaction as? SKPaymentTransaction{
switch trans.transactionState {
case .Purchased:
print("Product Purchased");
// get receipt and back to JS for verification check
let receipt = getReceipt()
purchaseCallbackHolder?([receipt])
purchaseCallbackHolder = nil
SKPaymentQueue.defaultQueue().finishTransaction(transaction as! SKPaymentTransaction)
break;
case .Failed:
print("Purchased Failed");
purchaseCallbackHolder?([])
purchaseCallbackHolder = nil
SKPaymentQueue.defaultQueue().finishTransaction(transaction as! SKPaymentTransaction)
break;
case .Restored:
print("Purchases Restored");
restoreCallbackHolder?([])
restoreCallbackHolder = nil
SKPaymentQueue.defaultQueue().finishTransaction(transaction as! SKPaymentTransaction)
default:
break;
}
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment