This page contains samples of code integration in Swift for iOS.
NOTE 1: On iOS, the version that is checked during validation is the one stored in the CFBundleVersion
field of the Info.plist
file.
Never put the version in the CFBundleShortVersionString
field.
NOTE 2: These examples only covers a small subset of the possible behaviors. Carefully check the signature of the receipt validation function to learn about the required arguments.
NOTE 3: These examples serve as a basis to show you how to integrate the code and call it. Remember that you have to be creative in the way you integration validation code.
- Basic receipt validation
- Retrieving receipt properties
- Checking InApp purchases
- Checking InApp purchases and access receipt properties
Basic receipt validation
This kind of validation should be executed in the early stage of the application's lifetime. When the validation succeeds, nothing happens; if the validation fails a receipt refresh request will be created and started.
Use the following options for the code generation (replace with your own values):
- Platform: iOS
- Language: Swift
- Bundle Identifier: <Your Bundle Identifier>
- Bundle Version: <Your Bundle Version>
- Code Prefix: <Your Code Prefix>
- Success behavior: DoNothing
- Failure behavior: RefreshReceipt
You need to implement the SKRequestDelegate
protocol in order to receive notifications of the receipt refresh request. Then, call the validation code by passing the request delegate instance. Note that the requestDidFinish:
method is called even when the user has cancelled the request; you may have to trigger another receipt validation in this method or later to be sure that the user has confirmed his credentials.
//
// MyClass.swift
//
import Foundation
import StoreKit
public class MyClass: SKRequestDelegate {
// ...
func strategicPlace() {
<Your Code Prefix>_CheckReceipt(request_delegate: self)
}
// ...
func request(_ request: SKRequest, didFailWithError error: Error) {
// There was an error during refresh request
}
func requestDidFinish(_ request: SKRequest) {
// The refresh request has finished
let url = Bundle.main.appStoreReceiptURL
if FileManager.default.fileExists(atPath: url!.path) {
// Receipt has been retrieved
} else {
// Trigger a new validation
DispatchQueue.main.async {
<Your Code Prefix>_CheckReceipt(request_delegate: self)
}
}
}
// ...
}
Retrieving receipt properties
This kind of validation is useful when you want to access to some receipt properties like the original bundle version (i.e. the version that was originally purchased). Whether the validation succeeds or fails, the given block will be called.
Use the following options for the code generation (replace with your own values):
- Platform: iOS
- Language: Swift
- Bundle Identifier: <Your Bundle Identifier>
- Bundle Version: <Your Bundle Version>
- Code Prefix: <Your Code Prefix>
- Success behavior: CallBlock
- Failure behavior: CallBlock
In a strategic place (in a class for example), call the validation function.
//
// MyClass.swift
//
import Foundation
public class MyClass {
// ...
func strategicPlace() {
<Your Code Prefix>_CheckReceipt(callback_block: { (receiptDictionary, validationResult) in
print(validationResult)
if validationResult, let dictionary = receiptDictionary {
print("-> \(dictionary[<Your Code Prefix>_RECEIPT_BUNDLE_ID] ?? "-")")
print("-> \(dictionary[<Your Code Prefix>_RECEIPT_BUNDLE_VERSION] ?? "-")")
print("-> \(dictionary[<Your Code Prefix>_RECEIPT_ORIGINAL_APPLICATION_VERSION] ?? "-")")
}
})
}
// ...
}
Checking InApp purchases
This kind of validation is used when you need to access the InApp purchase stored in the receipt. When the validation succeeds, the InApp purchases will be checked; if the validation fails nothing will be done.
Use the following options for the code generation (replace with your own values):
- Platform: iOS
- Language: Swift
- Bundle Identifier: <Your Bundle Identifier>
- Bundle Version: <Your Bundle Version>
- Code Prefix: <Your Code Prefix>
- Success behavior: CheckInApp
- Failure behavior: DoNothing
The code validates the receipt and call-back the given block for each given product identifiers. If the product identifier is found in the receipt, the block will be called back with the purchase information. Otherwise, no information will be provided.
//
// MyClass.swift
//
import Foundation
public class MyClass {
// ...
func strategicPlace() {
// An array of the product identifiers to query in the receipt
let identifiers = ["RECEIGEN_CONSUMABLE", "RECEIGEN_NON_CONSUMABLE", "OTHER"]
<Your Code Prefix>_CheckReceipt(inapp_identifiers: identifiers, { (identifier, isPresent, purchaseInfo) in
if isPresent,
let info = purchaseInfo,
let quantity = info[<Your Code Prefix>INAPP_QUANTITY] {
print(">>> \(identifier) x \(quantity)")
} else {
print(">>> \(identifier) not found")
}
})
}
// ...
}
Checking InApp purchases and access receipt properties
This kind of validation is used when you need to access the InApp purchase stored in the receipt, while also accessing to the receipt properties. When the validation succeeds, the InApp purchases will be checked; if the validation fails nothing will be done.
Use the following options for the code generation (replace with your own values):
- Platform: iOS
- Language: Swift
- Bundle Identifier: <Your Bundle Identifier>
- Bundle Version: <Your Bundle Version>
- Code Prefix: <Your Code Prefix>
- Success behavior: CheckInAppAndReceipt
- Failure behavior: DoNothing
The code validates the receipt and call-back the given block for each given product identifiers. If the product identifier is found in the receipt, the block will be called back with the purchase information. Otherwise, no information will be provided.
//
// MyClass.swift
//
import Foundation
public class MyClass {
// ...
func strategicPlace() {
// An array of the product identifiers to query in the receipt
let identifiers = ["RECEIGEN_CONSUMABLE", "RECEIGEN_NON_CONSUMABLE", "OTHER"]
<Your Code Prefix>_CheckInAppPurchasesAndReceipt(inapp_identifiers: identifiers, { (receiptDictionary, identifier, isPresent, purchaseInfo) in
if let dictionary = receiptDictionary {
print("-> \(dictionary[<Your Code Prefix>_RECEIPT_ORIGINAL_APPLICATION_VERSION] ?? "-")")
}
if isPresent,
let info = purchaseInfo,
let quantity = info[<Your Code Prefix>INAPP_QUANTITY] {
print(">>> \(identifier) x \(quantity)")
} else {
print(">>> \(identifier) not found")
}
})
}
// ...
}