This page contains samples of code integration in Objective-C for OS X.

NOTE 1: On OS X, the version that is checked during validation is the one stored in the CFBundleShortVersionString field of the Info.plist file. Never put the version in the CFBundleVersion 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.

Startup receipt validation

This validation is required as per Apple rules so receipt validation occurs immediately after the application is launched. When the validation succeeds the application is run; when the validation fails the application will exit with a code 173.

Use the following options for the code generation (replace with your own values):

In the main.m file, replace the NSApplicationMain by the CheckReceiptAndRun.

//
// main.m
//
#import <Cocoa/Cocoa.h>
#import "receipt.h"

int main(int argc, const char * argv[]) {
        return CheckReceiptAndRun(argc, argv);
}

Receipt validation during application’s lifecycle

This kind of validation should be executed during the application’s lifetime to ensure that the initial check has not been by-passed. When the validation succeeds nothing happens; when the validation fails the application will exit with a code 173.

Use the following options for the code generation (replace with your own values):

In a strategic place (in a class for example), call the validation function.

//
// main.m
//
#import "MyClass.h"
#import "receipt.h"

// ...

- (void)strategicPlace {
        <Your Code Prefix>_CheckReceipt();
}

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):

In a strategic place (in a class for example), call the validation function.

//
// MyClass.m
//
#import "MyClass.h"
#import "receipt.h"

// ...

- (void)strategicPlace {
    <Your Code Prefix>_CheckReceipt(^(NSDictionary *receipt_dict, BOOL validationResult) {
        NSLog(@"[%d]", validationResult);
        if (validationResult) {
            NSLog(@"-> %@", [receipt_dict objectForKey:<Your Code Prefix>_RECEIPT_BUNDLE_ID]);
            NSLog(@"-> %@", [receipt_dict objectForKey:<Your Code Prefix>_RECEIPT_BUNDLE_VERSION]);
            NSLog(@"-> %@", [receipt_dict objectForKey:<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 the application will exit with a code 173.

Use the following options for the code generation (replace with your own values):

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.m
//
#import "MyClass.h"
#import "receipt.h"

// ...

- (void)strategicPlace {
    // An array of the product identifiers to query in the receipt
    NSArray *identifiers = [NSArray arrayWithObjects:@"RECEIGEN_CONSUMABLE", @"RECEIGEN_NON_CONSUMABLE", @"OTHER", nil];

    // The validation code that enumerates the InApp purchases
    <Your Code Prefix>_CheckInAppPurchases(identifiers, ^(NSString *identifier, BOOL isPresent, NSDictionary *purchaseInfo) {
        if (isPresent) {
            NSLog(@">>> %@ x %d", identifier, [[purchaseInfo objectForKey:<Your Code Prefix>INAPP_QUANTITY] intValue]);
        } else {
            NSLog(@">>> %@ missing", identifier);
        }
    });
}

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 the application will exit with a code 173.

Use the following options for the code generation (replace with your own values):

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.m
//
#import "MyClass.h"
#import "receipt.h"

// ...

- (void)strategicPlace {
    // An array of the product identifiers to query in the receipt
    NSArray *identifiers = [NSArray arrayWithObjects:@"RECEIGEN_CONSUMABLE", @"RECEIGEN_NON_CONSUMABLE", @"OTHER", nil];

    // The validation code that enumerates the InApp purchases
    <Your Code Prefix>_CheckInAppPurchasesAndReceipt(identifiers, ^(NSDictionary *receipt_dict, NSString *identifier, BOOL isPresent, NSDictionary *purchaseInfo) {
        NSLog(@"-> %@", [receipt_dict objectForKey:<Your Code Prefix>_RECEIPT_ORIGINAL_APPLICATION_VERSION]);
        if (isPresent) {
            NSLog(@">>> %@ x %d", identifier, [[purchaseInfo objectForKey:<Your Code Prefix>INAPP_QUANTITY] intValue]);
        } else {
            NSLog(@">>> %@ missing", identifier);
        }
    });
}