How To Add In-App Purchase on Exported hyperPad Games
Adding In-App Purchase on Exported hyperPad Projects
Hey there, hyperPad creators! This tutorial shows you how to add In-App Purchases (IAP) to your exported hyperPad project.
We'll walk you through every step. Once IAP is in place, you can earn money from your game by selling items, levels, or upgrades inside it.
PS: Please check all the requirements below before you start.
Requirements
- You need a Mac to work with your exported project and add in-app purchases to it.
- You need CocoaPods installed on your Mac. If you don't have it yet, read the section below.
- You need the Terminal app on your Mac.
- You need a text editor app on your Mac.
CocoaPods
CocoaPods manages library dependencies in your Xcode projects. You list the dependencies in a text file called a Podfile. CocoaPods resolves the dependencies between libraries, fetches their source code, and links everything in an Xcode workspace so your project compiles.
Its goal is to make third-party open-source libraries easier to find and use, by keeping them in one central place.
Learn more here.
Terminal App
The Terminal app on macOS is a command-line interface. You type text commands to control your Mac, run tasks, move around files and folders, and more.
From Terminal you can run tools and scripts and change system settings. It gives you more control than the graphical interface, which is why developers and system administrators use it.
Procedure
- Using a text editor, add
pod 'SwiftyStoreKit'to the list of pods in the Podfile of your exported project. - In Terminal, run pod install. This might take a while, so hang on!
Replace the contents of HPSwift.swift with the following file:
//
// HPSwift.swift
// hyperPad-Project
//
// Created by Hamed Saadat on 2019-08-07.
//
import Foundation
import SwiftyStoreKit
@objc class HPSwift: NSObject {
fileprivate var _behaviours: HPBehaviours? = nil
@objc var behaviours: HPBehaviours? {
get { return _behaviours }
set(behaviours) {
_behaviours = behaviours
SwiftyStoreKit.completeTransactions(atomically: true) { purchases in
for purchase in purchases {
switch purchase.transaction.transactionState {
case .purchased, .restored:
if purchase.needsFinishTransaction {
// Deliver content from server, then:
SwiftyStoreKit.finishTransaction(purchase.transaction)
}
// Unlock content
behaviours?.broadcastValue(purchase.productId as NSString, withKey: "purchaseComplete")
case .failed, .purchasing, .deferred:
behaviours?.broadcastValue(purchase.productId as NSString, withKey: "purchaseError")
break // do nothing
@unknown default:
break
}
}
}
behaviours?.addReceiveKey("restorePurchases", onReceive: { (receiveValue) in
SwiftyStoreKit.restorePurchases(atomically: true) { results in
if results.restoreFailedPurchases.count > 0 {
behaviours?.broadcastValue("Restore Failed: \(results.restoreFailedPurchases)" as NSString, withKey: "purchaseError")
}
else if results.restoredPurchases.count > 0 {
results.restoredPurchases.forEach { (purchase) in
behaviours?.broadcastValue(purchase.productId as NSString, withKey: "purchaseComplete")
}
}
else {
print("Nothing to Restore")
}
}
})
/*
Add Behaviour functionality here
*/
behaviours?.addReceiveKey("purchase", onReceive: { (recieveValue) in
// handle in app purchase logic! //
SwiftyStoreKit.purchaseProduct("INSERT_PURCHASE_IDENTIFIER_HERE_OR_USE_recieveValue", quantity: 1, atomically: true) { result in
switch result {
case .success(let purchase):
behaviours?.broadcastValue(purchase.productId as NSString, withKey: "purchaseComplete")
case .error(let error):
var message = ""
switch error.code {
case .unknown: message = "Unknown error. Please contact support"
case .clientInvalid: message = "Not allowed to make the payment"
case .paymentCancelled: break
case .paymentInvalid: message = "The purchase identifier was invalid"
case .paymentNotAllowed: message = "The device is not allowed to make the payment"
case .storeProductNotAvailable: message = "The product is not available in the current storefront"
case .cloudServicePermissionDenied: message = "Access to cloud service information is not allowed"
case .cloudServiceNetworkConnectionFailed: message = "Could not connect to the network"
case .cloudServiceRevoked: message = "User has revoked permission to use this cloud service"
default: message = ((error as NSError).localizedDescription)
}
behaviours?.broadcastValue(message as NSString, withKey: "purchaseFailed")
}
}
})
}
}
}
Things to Note
behaviours?.addReceiveKey("restorePurchases", onReceive: { (receiveValue) in
// add your code here
})
This runs when a broadcast Behavior sends the restorePurchases key.
behaviours?.broadcastValue(purchase.productId as NSString, withKey: "purchaseComplete")
When the purchase completes, this triggers any Receive Message Behaviors listening for the purchaseComplete key.
You can replace INSERT_PURCHASE_IDENTIFIER_HERE_OR_USE_recieveValue with either your purchase's identifier from App Store Connect or the recieveValue parameter (spelled that way in the code). If you use the parameter, make sure your broadcast Behavior sends the identifier from App Store Connect.
Share your games!
And you're done! Follow our socials and tag us in your posts. Let us know you're using hyperPad, so we can reshare your creations with the community.

