Skip to content

Commit

Permalink
Refactoring.
Browse files Browse the repository at this point in the history
 - Extract part of `isTransactionAndItsReceiptValid:error:` logic into CBPurchaseInfoFromTransactionReceipt().
  • Loading branch information
lxcid committed Dec 9, 2012
1 parent 83df886 commit 9d7ea95
Showing 1 changed file with 30 additions and 23 deletions.
53 changes: 30 additions & 23 deletions CargoBay/CargoBay.m
Expand Up @@ -527,6 +527,33 @@ calculating SHA1(version|purchaseinfo)
#endif
}

static NSDictionary *CBPurchaseInfoFromTransactionReceipt(NSData *theTransactionReceiptData, NSError * __autoreleasing *theError) {
NSDictionary *theTransactionReceiptDictionary = [NSPropertyListSerialization propertyListWithData:theTransactionReceiptData options:NSPropertyListImmutable format:nil error:theError];
if (!theTransactionReceiptDictionary) {
return nil;
}
NSString *thePurchaseInfo = [theTransactionReceiptDictionary objectForKey:@"purchase-info"];
NSDictionary *thePurchaseInfoDictionary = [NSPropertyListSerialization propertyListWithData:CBDataFromBase64EncodedString(thePurchaseInfo) options:NSPropertyListImmutable format:nil error:theError];
if (!thePurchaseInfoDictionary) {
return nil;
}
NSString *thePurchaseDateString = [thePurchaseInfoDictionary objectForKey:@"purchase-date"];
NSString *theSignature = [theTransactionReceiptDictionary objectForKey:@"signature"];

// Converts the string into a date
NSDateFormatter *theDateFormatter = [[NSDateFormatter alloc] init];
theDateFormatter.dateFormat = @"yyyy-MM-dd HH:mm:ss z";

NSDate *thePurchaseDate = [theDateFormatter dateFromString:[thePurchaseDateString stringByReplacingOccurrencesOfString:@"Etc/" withString:@""]];

// Check the authenticity of the receipt response/signature etc.
if (!CBCheckReceiptSecurity(thePurchaseInfo, theSignature, (__bridge CFDateRef)thePurchaseDate)) {
return nil;
}

return thePurchaseInfoDictionary;
}

#pragma mark

@interface CargoBayProductRequestDelegate : NSObject <SKRequestDelegate, SKProductsRequestDelegate> {
Expand Down Expand Up @@ -798,26 +825,10 @@ - (BOOL)isTransactionAndItsReceiptValid:(SKPaymentTransaction *)theTransaction e
return NO;
}

// Pull the purchase-info out of the transaction receipt, decode it, and save it for later so
// it can be cross checked with the verifyReceipt.
NSDictionary *theReceiptDictionary = [NSPropertyListSerialization propertyListWithData:theTransaction.transactionReceipt options:NSPropertyListImmutable format:nil error:theError];
if (!theReceiptDictionary) {
return NO;
}
NSString *theTransactionPurchaseInfo = [theReceiptDictionary objectForKey:@"purchase-info"];
NSDictionary *thePurchaseInfoDictionary = [NSPropertyListSerialization propertyListWithData:CBDataFromBase64EncodedString(theTransactionPurchaseInfo) options:NSPropertyListImmutable format:nil error:theError];
NSDictionary *thePurchaseInfoDictionary = CBPurchaseInfoFromTransactionReceipt(theTransaction.transactionReceipt, theError);
if (!thePurchaseInfoDictionary) {
return NO;
}
__unused NSString *theTransactionID = [thePurchaseInfoDictionary objectForKey:@"transaction-id"];
NSString *thePurchaseDateString = [thePurchaseInfoDictionary objectForKey:@"purchase-date"];
NSString *theSignature = [theReceiptDictionary objectForKey:@"signature"];

// Converts the string into a date
NSDateFormatter *theDateFormatter = [[NSDateFormatter alloc] init];
theDateFormatter.dateFormat = @"yyyy-MM-dd HH:mm:ss z";

NSDate *thePurchaseDate = [theDateFormatter dateFromString:[thePurchaseDateString stringByReplacingOccurrencesOfString:@"Etc/" withString:@""]];

// In Apple's implementation, it stores the transaction ID together with its receipt.
// Apple chooses the `NSUserDefaults` for storage. I'm not sure about whether we should
Expand All @@ -826,19 +837,15 @@ - (BOOL)isTransactionAndItsReceiptValid:(SKPaymentTransaction *)theTransaction e
// The TODOs below is written as a reminder that this portion of the code is still in review.

// // TODO: Checks to see if the transaction ID is unique.
// //NSString *theTransactionID = theTransaction.transactionIdentifier;
// NSString *theTransactionID = [thePurchaseInfoDictionary objectForKey:@"transaction-id"];
// if (![self isTransactionIDUnique:theTransactionID]) {
// // We've seen this transaction before.
// // Had [self.transactionsReceiptStorageDictionary objectForKey:theTransactionID];
// // Got thePurchaseInfoDictionary
// return NO;
// }

// Check the authenticity of the receipt response/signature etc.

if (!CBCheckReceiptSecurity(theTransactionPurchaseInfo, theSignature, (__bridge CFDateRef)thePurchaseDate)) {
return NO;
}

// Ensure the transaction itself is legit
if (!CBValidateTransactionMatchesPurchaseInfo(theTransaction, thePurchaseInfoDictionary)) {
return NO;
Expand Down

0 comments on commit 9d7ea95

Please sign in to comment.