From 9d7ea9511af2072dbb832c1c9a835266ef6513e4 Mon Sep 17 00:00:00 2001 From: Stan Chang Khin Boon Date: Sun, 9 Dec 2012 17:30:07 +0800 Subject: [PATCH] Refactoring. - Extract part of `isTransactionAndItsReceiptValid:error:` logic into CBPurchaseInfoFromTransactionReceipt(). --- CargoBay/CargoBay.m | 53 +++++++++++++++++++++++++-------------------- 1 file changed, 30 insertions(+), 23 deletions(-) diff --git a/CargoBay/CargoBay.m b/CargoBay/CargoBay.m index 351632f..6eeefe6 100644 --- a/CargoBay/CargoBay.m +++ b/CargoBay/CargoBay.m @@ -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 { @@ -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 @@ -826,6 +837,8 @@ - (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]; @@ -833,12 +846,6 @@ - (BOOL)isTransactionAndItsReceiptValid:(SKPaymentTransaction *)theTransaction e // 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;