This page contains examples of code integration. 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.

OS X Examples

iOS Examples

OS X

Startup receipt validation at startup

This kind of validation is required as per Apple rules so receipt validation occurs immediately after the application is launched.

For example, to perform a startup receipt validation, use the following options for the code generation:

Whether the validation succeeds, nothing happens; if the validation fails the application will exit with a code 173.

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.

For example, to perform a receipt validation check, use the following options for the code generation:

When the validation succeeds, nothing happens; if the validation fails the application will exit with a code 173.

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

// ...

- (void)strategicPlace {
    MyPrefix_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).

For example, to perform a receipt validation check and retrieve the receipt properties, use the following options for the code generation:

Whether the validation succeeds or fails, the given block will be called.

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

...

- (void)strategicPlace {
    MyPrefix_CheckReceipt(^(NSDictionary *receipt_dict, BOOL validationResult) {
        NSLog(@"[%d]", validationResult);
        if (validationResult) {
            NSLog(@"-> %@", [receipt_dict objectForKey:MyPrefix_RECEIPT_ATTRIBUTETYPE_BUNDLE_ID]);
            NSLog(@"-> %@", [receipt_dict objectForKey:MyPrefix_RECEIPT_ATTRIBUTETYPE_BUNDLE_VERSION]);
            NSLog(@"-> %@", [receipt_dict objectForKey:MyPrefix_RECEIPT_ATTRIBUTETYPE_ORIGINAL_APPLICATION_VERSION]);
        }
    });
}

Checking InApp purchases

This kind of validation is used when you need to access the InApp purchase stored in the receipt.

For example, to perform a receipt validation check followed by an InApp purchases check, use the following options for the code generation:

When the validation succeeds, the InApp purchases will be checked; if the validation fails the application will exit with a code 173.

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
    MyPrefix_CheckInAppPurchases(identifiers, ^(NSString *identifier, BOOL isPresent, NSDictionary *purchaseInfo) {
        if (isPresent) {
            NSLog(@">>> %@ x %d", identifier, [[purchaseInfo objectForKey:MyPrefix_INAPP_ATTRIBUTETYPE_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.

For example, to perform a receipt validation check followed by an InApp purchases check, use the following options for the code generation:

When the validation succeeds, the InApp purchases will be checked; if the validation fails the application will exit with a code 173.

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
    MyPrefix_CheckInAppPurchasesAndReceipt(identifiers, ^(NSDictionary *receipt_dict, NSString *identifier, BOOL isPresent, NSDictionary *purchaseInfo) {
        NSLog(@"-> %@", [receipt_dict objectForKey:MyPrefix_RECEIPT_ATTRIBUTETYPE_ORIGINAL_APPLICATION_VERSION]);
        if (isPresent) {
            NSLog(@">>> %@ x %d", identifier, [[purchaseInfo objectForKey:MyPrefix_INAPP_ATTRIBUTETYPE_QUANTITY] intValue]);
        } else {
            NSLog(@">>> %@ missing", identifier);
        }
    });
}

iOS

Basic receipt validation

This kind of validation should be executed in the early stage of the application's lifetime.

For example, to perform a receipt validation check, use the following options for the code generation:

When the validation succeeds, nothing happens; if the validation fails a receipt refresh request will be created and started.

You need to implement a request delegate in order to receive notifications of the receipt refresh request:

//
// MyClass.h
//
#import <UIKit/UIKit.h>
#import <StoreKit/StoreKit.h>

@interface MyClass : NSObject &lt;SKRequestDelegate>

...

@end

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. So you have to trigger another receipt validation in this method or later to be sure that the user has confirmed his credentials.

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

...

- (void)strategicPlace {
    MyPrefix_CheckReceipt(self);
}

- (void)request:(SKRequest *)request didFailWithError:(NSError *)error {
    // There was an error during refresh request
}

- (void)requestDidFinish:(SKRequest *)request {
    // The refresh request has finished

    // While debugging, use the following code to check that the receipt has been correctly retrieved
    NSURL *url = [[NSBundle mainBundle] appStoreReceiptURL];
    NSLog(@"Found %d", [[NSFileManager defaultManager] fileExistsAtPath:[url path]]);    

    // Perform another receipt validation to be sure if the user presses cancel
    // To avoid an infinite loop, you may implement a counter
    // You may also use dispatch_after to postpone the retry
    dispatch_async(dispatch_get_main_queue(), ^{
        MyPrefix_CheckReceipt(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).

For example, to perform a receipt validation check and retrieve the receipt properties, use the following options for the code generation:

Whether the validation succeeds or fails, the given block will be called.

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

...

- (void)strategicPlace {
    MyPrefix_CheckReceipt(^(NSDictionary *receipt_dict, BOOL validationResult) {
        NSLog(@"[%d]", validationResult);
        if (validationResult) {
            NSLog(@"-> %@", [receipt_dict objectForKey:MyPrefix_RECEIPT_ATTRIBUTETYPE_BUNDLE_ID]);
            NSLog(@"-> %@", [receipt_dict objectForKey:MyPrefix_RECEIPT_ATTRIBUTETYPE_BUNDLE_VERSION]);
            NSLog(@"-> %@", [receipt_dict objectForKey:MyPrefix_RECEIPT_ATTRIBUTETYPE_ORIGINAL_APPLICATION_VERSION]);
        }
    });
}

Checking InApp purchases

This kind of validation is used when you need to access the InApp purchase stored in the receipt.

For example, to perform a receipt validation check followed by an InApp purchases check, use the following options for the code generation for the InApp check:

and use the following options for the code generation for the standard check:

When the validation succeeds, the InApp purchases will be checked; if the validation fails a receipt refresh request will be created and started.

You need to implement a request delegate in order to receive notifications of the receipt refresh request:

//
// MyClass.h
//
#import <UIKit/UIKit.h>
#import <StoreKit/StoreKit.h>

@interface MyClass : NSObject &lt;SKRequestDelegate>

...

@end

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
    MyPrefix_CheckInAppPurchases(identifiers, ^(NSString *identifier, BOOL isPresent, NSDictionary *purchaseInfo) {
        if (isPresent) {
            NSLog(@">>> %@ x %d", identifier, [[purchaseInfo objectForKey:MyPrefix_INAPP_ATTRIBUTETYPE_QUANTITY] intValue]);
        } else {
            NSLog(@">>> %@ missing", identifier);
        }
    }, self);
}

- (void)request:(SKRequest *)request didFailWithError:(NSError *)error {
    // There was an error during refresh request
}

- (void)requestDidFinish:(SKRequest *)request {
    // The refresh request has finished

    // While debugging, use the following code to check that the receipt has been correctly retrieved
    NSURL *url = [[NSBundle mainBundle] appStoreReceiptURL];
    NSLog(@"Found %d", [[NSFileManager defaultManager] fileExistsAtPath:[url path]]);    

    // Perform another receipt validation to be sure if the user presses cancel
    // To avoid an infinite loop, you may implement a counter
    // You may also use dispatch_after to postpone the retry
    dispatch_async(dispatch_get_main_queue(), ^{
        AnotherPrefix_CheckReceipt(self);
    });
}

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.

For example, to perform a receipt validation check followed by an InApp purchases check, use the following options for the code generation for the InApp check:

and use the following options for the code generation for the standard check:

When the validation succeeds, the InApp purchases will be checked; if the validation fails a receipt refresh request will be created and started.

You need to implement a request delegate in order to receive notifications of the receipt refresh request:

//
// MyClass.h
//
#import <UIKit/UIKit.h>
#import <StoreKit/StoreKit.h>

@interface MyClass : NSObject &lt;SKRequestDelegate>

...

@end

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
    MyPrefix_CheckInAppPurchasesAndReceipt(identifiers, ^(NSDictionary *receipt_dict, NSString *identifier, BOOL isPresent, NSDictionary *purchaseInfo) {
        NSLog(@"-> %@", [receipt_dict objectForKey:MyPrefix_RECEIPT_ATTRIBUTETYPE_ORIGINAL_APPLICATION_VERSION]);
        if (isPresent) {
            NSLog(@">>> %@ x %d", identifier, [[purchaseInfo objectForKey:MyPrefix_INAPP_ATTRIBUTETYPE_QUANTITY] intValue]);
        } else {
            NSLog(@">>> %@ missing", identifier);
        }
    }, self);
}

- (void)request:(SKRequest *)request didFailWithError:(NSError *)error {
    // There was an error during refresh request
}

- (void)requestDidFinish:(SKRequest *)request {
    // The refresh request has finished

    // While debugging, use the following code to check that the receipt has been correctly retrieved
    NSURL *url = [[NSBundle mainBundle] appStoreReceiptURL];
    NSLog(@"Found %d", [[NSFileManager defaultManager] fileExistsAtPath:[url path]]);    

    // Perform another receipt validation to be sure if the user presses cancel
    // To avoid an infinite loop, you may implement a counter
    // You may also use dispatch_after to postpone the retry
    dispatch_async(dispatch_get_main_queue(), ^{
        AnotherPrefix_CheckReceipt(self);
    });
}