Skip to content

Transaction persistence

Hermes Pique edited this page Oct 19, 2013 · 12 revisions

RMStore delegates transaction persistence and provides two optional reference implementations for storing transactions in the Keychain or in NSUserDefaults. You can implement your transaction, use the reference implementations provided by the library or, in the case of non-consumables and auto-renewable subscriptions, get the transactions directly from the receipt.

#Reference implementations

RMStore provides transaction persistence via RMStoreKeychainPersistence (using the Keycahin) and RMStoreUserDefaultsPersistence (using NSUserDefaults).

Neither is intended as a fail-proof solution and, if security is a real concern, you might want to avoid using an open source implementation for transaction persistence. That said, the reference persistors should provide a good starting point for your own implementation.

##RMStoreKeychainPersistence

RMStoreKeychainPersistence is the reference implementation for persisting transactions in the Keychain. Given that the Keychain is not intended for storing complex structures, RMStoreKeychainPersistence only persists product identifiers and their stock.

###Setup

To use RMStoreKeychainPersistence add the following files to your project from RMStore/Optional:

You will also need to link against Security.framework.

###Working with non-consumables

Non-consumables can only be purchased once. To know if a non-consumable has been purchased:

RMStoreKeychainPersistence *persistence = [RMStore defaultStore].transactionPersistor;
BOOL purchased = [persistence isPurchasedProductOfIdentifier:@"fabulousIdol"];

###Working with consumables

Consumables can be purchased more than once and typically will be consumed at most once per purchase. Here is how you would normally operate with a non-consumable:

RMStoreKeychainPersistence *persistence = [RMStore defaultStore].transactionPersistor;
NSInteger purchaseCount = [persistence countProductOfdentifier:@"banana"];
if (purchaseCount > 0)
{
    BOOL success = [persistence consumeProductOfIdentifier:@"banana"];
}

##RMStoreUserDefaultsPersistence

###Setup

To use RMStoreUserDefaultsPersistence add the following files to your project from RMStore/Optional:

###Obfuscation

By default RMStoreUserDefaultsPersistence stores transactions in NSUserDefaults as objects using NSCoding, as a form of weak obfuscation. For better security, you might want to provide your custom obfuscation. You can do this by subclassing RMStoreUserDefaultsPersistence and overriding the methods defined in the Obfuscation category.

- (NSData*)dataWithTransaction:(RMStoreTransaction*)transaction;

- (RMStoreTransaction*)transactionWithData:(NSData*)data;

You will be obfuscating RMStoreTransaction instances, an analogue of SKPaymentTransaction which supports NSCopying, unlike the original. This should make your work a little simpler.

#Custom persistence

#Setting the persistor

No matter if you use a custom or reference persistor, you will need to set it at startup. For example:

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
    _persistor = [[RMStoreKeychainPersistence alloc] init];
    [RMStore defaultStore].transactionPersistor = _persistor;
    // Your code
    return YES;
}

Bear in mind that transactionPersistor is a weak property. In the above example the app delegate is responsible of retaining the persistor.

#Using the receipt

Clone this wiki locally