From d448533aba9cc88e70365fcfca6a1434cdac1252 Mon Sep 17 00:00:00 2001 From: Sean Blahovici Date: Wed, 19 Aug 2015 15:06:07 -0400 Subject: [PATCH 01/19] Added MutableSet instead of regular counter to insure that callback is always called in the case of duplicate updatedTransaction callbacks --- RMStore/RMStore.m | 100 +++++++++++++++++++++++----------------------- 1 file changed, 51 insertions(+), 49 deletions(-) diff --git a/RMStore/RMStore.m b/RMStore/RMStore.m index 06a88ee8..ce76a107 100755 --- a/RMStore/RMStore.m +++ b/RMStore/RMStore.m @@ -133,16 +133,16 @@ @implementation RMStore { NSMutableDictionary *_addPaymentParameters; // HACK: We use a dictionary of product identifiers because the returned SKPayment is different from the one we add to the queue. Bad Apple. NSMutableDictionary *_products; NSMutableSet *_productsRequestDelegates; - + NSMutableArray *_restoredTransactions; - - NSInteger _pendingRestoredTransactionsCount; + + NSMutableSet *_pendingRestoredTransactionsCount; BOOL _restoredCompletedTransactionsFinished; - + SKReceiptRefreshRequest *_refreshReceiptRequest; void (^_refreshReceiptFailureBlock)(NSError* error); void (^_refreshReceiptSuccessBlock)(); - + void (^_restoreTransactionsFailureBlock)(NSError* error); void (^_restoreTransactionsSuccessBlock)(NSArray* transactions); } @@ -155,6 +155,7 @@ - (id) init _products = [NSMutableDictionary dictionary]; _productsRequestDelegates = [NSMutableSet set]; _restoredTransactions = [NSMutableArray array]; + _pendingRestoredTransactionsCount = [NSMutableSet set]; [[SKPaymentQueue defaultQueue] addTransactionObserver:self]; } return self; @@ -188,16 +189,16 @@ - (void)addPayment:(NSString*)productIdentifier } - (void)addPayment:(NSString*)productIdentifier - success:(void (^)(SKPaymentTransaction *transaction))successBlock - failure:(void (^)(SKPaymentTransaction *transaction, NSError *error))failureBlock + success:(void (^)(SKPaymentTransaction *transaction))successBlock + failure:(void (^)(SKPaymentTransaction *transaction, NSError *error))failureBlock { [self addPayment:productIdentifier user:nil success:successBlock failure:failureBlock]; } - (void)addPayment:(NSString*)productIdentifier - user:(NSString*)userIdentifier - success:(void (^)(SKPaymentTransaction *transaction))successBlock - failure:(void (^)(SKPaymentTransaction *transaction, NSError *error))failureBlock + user:(NSString*)userIdentifier + success:(void (^)(SKPaymentTransaction *transaction))successBlock + failure:(void (^)(SKPaymentTransaction *transaction, NSError *error))failureBlock { SKProduct *product = [self productForIdentifier:productIdentifier]; if (product == nil) @@ -215,12 +216,12 @@ - (void)addPayment:(NSString*)productIdentifier { payment.applicationUsername = userIdentifier; } - + RMAddPaymentParameters *parameters = [[RMAddPaymentParameters alloc] init]; parameters.successBlock = successBlock; parameters.failureBlock = failureBlock; _addPaymentParameters[productIdentifier] = parameters; - + [[SKPaymentQueue defaultQueue] addPayment:payment]; } @@ -230,18 +231,18 @@ - (void)requestProducts:(NSSet*)identifiers } - (void)requestProducts:(NSSet*)identifiers - success:(RMSKProductsRequestSuccessBlock)successBlock - failure:(RMSKProductsRequestFailureBlock)failureBlock + success:(RMSKProductsRequestSuccessBlock)successBlock + failure:(RMSKProductsRequestFailureBlock)failureBlock { RMProductsRequestDelegate *delegate = [[RMProductsRequestDelegate alloc] init]; delegate.store = self; delegate.successBlock = successBlock; delegate.failureBlock = failureBlock; [_productsRequestDelegates addObject:delegate]; - + SKProductsRequest *productsRequest = [[SKProductsRequest alloc] initWithProductIdentifiers:identifiers]; - productsRequest.delegate = delegate; - + productsRequest.delegate = delegate; + [productsRequest start]; } @@ -251,10 +252,10 @@ - (void)restoreTransactions } - (void)restoreTransactionsOnSuccess:(void (^)(NSArray *transactions))successBlock - failure:(void (^)(NSError *error))failureBlock + failure:(void (^)(NSError *error))failureBlock { _restoredCompletedTransactionsFinished = NO; - _pendingRestoredTransactionsCount = 0; + [_pendingRestoredTransactionsCount removeAllObjects]; _restoredTransactions = [NSMutableArray array]; _restoreTransactionsSuccessBlock = successBlock; _restoreTransactionsFailureBlock = failureBlock; @@ -262,12 +263,12 @@ - (void)restoreTransactionsOnSuccess:(void (^)(NSArray *transactions))successBlo } - (void)restoreTransactionsOfUser:(NSString*)userIdentifier - onSuccess:(void (^)(NSArray *transactions))successBlock - failure:(void (^)(NSError *error))failureBlock + onSuccess:(void (^)(NSArray *transactions))successBlock + failure:(void (^)(NSError *error))failureBlock { NSAssert([[SKPaymentQueue defaultQueue] respondsToSelector:@selector(restoreCompletedTransactionsWithApplicationUsername:)], @"restoreCompletedTransactionsWithApplicationUsername: not supported in this iOS version. Use restoreTransactionsOnSuccess:failure: instead."); _restoredCompletedTransactionsFinished = NO; - _pendingRestoredTransactionsCount = 0; + [_pendingRestoredTransactionsCount removeAllObjects]; _restoreTransactionsSuccessBlock = successBlock; _restoreTransactionsFailureBlock = failureBlock; [[SKPaymentQueue defaultQueue] restoreCompletedTransactionsWithApplicationUsername:userIdentifier]; @@ -289,7 +290,7 @@ - (void)refreshReceipt } - (void)refreshReceiptOnSuccess:(RMStoreSuccessBlock)successBlock - failure:(RMStoreFailureBlock)failureBlock + failure:(RMStoreFailureBlock)failureBlock { _refreshReceiptFailureBlock = failureBlock; _refreshReceiptSuccessBlock = successBlock; @@ -307,11 +308,11 @@ - (SKProduct*)productForIdentifier:(NSString*)productIdentifier + (NSString*)localizedPriceOfProduct:(SKProduct*)product { - NSNumberFormatter *numberFormatter = [[NSNumberFormatter alloc] init]; - numberFormatter.numberStyle = NSNumberFormatterCurrencyStyle; - numberFormatter.locale = product.priceLocale; - NSString *formattedString = [numberFormatter stringFromNumber:product.price]; - return formattedString; + NSNumberFormatter *numberFormatter = [[NSNumberFormatter alloc] init]; + numberFormatter.numberStyle = NSNumberFormatterCurrencyStyle; + numberFormatter.locale = product.priceLocale; + NSString *formattedString = [numberFormatter stringFromNumber:product.price]; + return formattedString; } #pragma mark Observers @@ -392,7 +393,7 @@ - (void)paymentQueueRestoreCompletedTransactionsFinished:(SKPaymentQueue *)queue { RMStoreLog(@"restore transactions finished"); _restoredCompletedTransactionsFinished = YES; - + [self notifyRestoreTransactionFinishedIfApplicableAfterTransaction:nil]; } @@ -478,7 +479,7 @@ - (void)didFinishDownload:(SKDownload*)download queue:(SKPaymentQueue*)queue { SKPaymentTransaction *transaction = download.transaction; RMStoreLog(@"download %@ for product %@ finished", download.contentIdentifier, transaction.payment.productIdentifier); - + [self postNotificationWithName:RMSKDownloadFinished download:download userInfoExtras:nil]; const BOOL hasPendingDownloads = [self.class hasPendingDownloadsInTransaction:transaction]; @@ -525,7 +526,7 @@ + (BOOL)hasPendingDownloadsInTransaction:(SKPaymentTransaction*)transaction - (void)didPurchaseTransaction:(SKPaymentTransaction *)transaction queue:(SKPaymentQueue*)queue { RMStoreLog(@"transaction purchased with product %@", transaction.payment.productIdentifier); - + if (self.receiptVerificator != nil) { [self.receiptVerificator verifyTransaction:transaction success:^{ @@ -544,23 +545,23 @@ - (void)didPurchaseTransaction:(SKPaymentTransaction *)transaction queue:(SKPaym - (void)didFailTransaction:(SKPaymentTransaction *)transaction queue:(SKPaymentQueue*)queue error:(NSError*)error { SKPayment *payment = transaction.payment; - NSString* productIdentifier = payment.productIdentifier; + NSString* productIdentifier = payment.productIdentifier; RMStoreLog(@"transaction failed with product %@ and error %@", productIdentifier, error.debugDescription); - + if (error.code != RMStoreErrorCodeUnableToCompleteVerification) { // If we were unable to complete the verification we want StoreKit to keep reminding us of the transaction [queue finishTransaction:transaction]; } - + RMAddPaymentParameters *parameters = [self popAddPaymentParametersForIdentifier:productIdentifier]; if (parameters.failureBlock != nil) { parameters.failureBlock(transaction, error); } - + NSDictionary *extras = error ? @{RMStoreNotificationStoreError : error} : nil; [self postNotificationWithName:RMSKPaymentTransactionFailed transaction:transaction userInfoExtras:extras]; - + if (transaction.transactionState == SKPaymentTransactionStateRestored) { [self notifyRestoreTransactionFinishedIfApplicableAfterTransaction:transaction]; @@ -569,9 +570,10 @@ - (void)didFailTransaction:(SKPaymentTransaction *)transaction queue:(SKPaymentQ - (void)didRestoreTransaction:(SKPaymentTransaction *)transaction queue:(SKPaymentQueue*)queue { - RMStoreLog(@"transaction restored with product %@", transaction.originalTransaction.payment.productIdentifier); - - _pendingRestoredTransactionsCount++; + NSString *productIdentifier = transaction.originalTransaction.payment.productIdentifier; + RMStoreLog(@"transaction restored with product %@", productIdentifier); + + [_pendingRestoredTransactionsCount addObject:productIdentifier]; if (self.receiptVerificator != nil) { [self.receiptVerificator verifyTransaction:transaction success:^{ @@ -631,18 +633,18 @@ - (void)didDownloadSelfHostedContentForTransaction:(SKPaymentTransaction *)trans - (void)finishTransaction:(SKPaymentTransaction *)transaction queue:(SKPaymentQueue*)queue { SKPayment *payment = transaction.payment; - NSString* productIdentifier = payment.productIdentifier; + NSString* productIdentifier = payment.productIdentifier; [queue finishTransaction:transaction]; [self.transactionPersistor persistTransaction:transaction]; - + RMAddPaymentParameters *wrapper = [self popAddPaymentParametersForIdentifier:productIdentifier]; if (wrapper.successBlock != nil) { wrapper.successBlock(transaction); } - + [self postNotificationWithName:RMSKPaymentTransactionFinished transaction:transaction userInfoExtras:nil]; - + if (transaction.transactionState == SKPaymentTransactionStateRestored) { [self notifyRestoreTransactionFinishedIfApplicableAfterTransaction:transaction]; @@ -654,9 +656,9 @@ - (void)notifyRestoreTransactionFinishedIfApplicableAfterTransaction:(SKPaymentT if (transaction != nil) { [_restoredTransactions addObject:transaction]; - _pendingRestoredTransactionsCount--; + [_pendingRestoredTransactionsCount removeObject:transaction.payment.productIdentifier]; } - if (_restoredCompletedTransactionsFinished && _pendingRestoredTransactionsCount == 0) + if (_restoredCompletedTransactionsFinished && _pendingRestoredTransactionsCount.count == 0) { // Wait until all restored transations have been verified NSArray *restoredTransactions = [_restoredTransactions copy]; if (_restoreTransactionsSuccessBlock != nil) @@ -711,7 +713,7 @@ - (void)request:(SKRequest *)request didFailWithError:(NSError *)error - (void)addProduct:(SKProduct*)product { - _products[product.productIdentifier] = product; + _products[product.productIdentifier] = product; } - (void)postNotificationWithName:(NSString*)notificationName download:(SKDownload*)download userInfoExtras:(NSDictionary*)extras @@ -748,17 +750,17 @@ - (void)productsRequest:(SKProductsRequest *)request didReceiveResponse:(SKProdu RMStoreLog(@"products request received response"); NSArray *products = [NSArray arrayWithArray:response.products]; NSArray *invalidProductIdentifiers = [NSArray arrayWithArray:response.invalidProductIdentifiers]; - + for (SKProduct *product in products) { RMStoreLog(@"received product with id %@", product.productIdentifier); [self.store addProduct:product]; } - + [invalidProductIdentifiers enumerateObjectsUsingBlock:^(NSString *invalid, NSUInteger idx, BOOL *stop) { RMStoreLog(@"invalid product with id %@", invalid); }]; - + if (self.successBlock) { self.successBlock(products, invalidProductIdentifiers); From 67bf17b01cc00ba081a6e5d1bf97b77c71765179 Mon Sep 17 00:00:00 2001 From: Sean Blahovici Date: Wed, 19 Aug 2015 15:11:29 -0400 Subject: [PATCH 02/19] Updating version podspec --- RMStore.podspec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/RMStore.podspec b/RMStore.podspec index d557348d..6d590cba 100644 --- a/RMStore.podspec +++ b/RMStore.podspec @@ -1,6 +1,6 @@ Pod::Spec.new do |s| s.name = 'RMStore' - s.version = '0.7.1' + s.version = '0.7.2' s.license = 'Apache 2.0' s.summary = 'A lightweight iOS library for In-App Purchases that adds blocks and notifications to StoreKit, plus verification, persistence and downloads.' s.homepage = 'https://github.com/robotmedia/RMStore' From b3f88229ca4dc9573ccbe72146c51a0d75ec9b4c Mon Sep 17 00:00:00 2001 From: Sean Blahovici Date: Wed, 19 Aug 2015 15:19:03 -0400 Subject: [PATCH 03/19] Updating podspec source --- RMStore.podspec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/RMStore.podspec b/RMStore.podspec index 6d590cba..736624af 100644 --- a/RMStore.podspec +++ b/RMStore.podspec @@ -6,7 +6,7 @@ Pod::Spec.new do |s| s.homepage = 'https://github.com/robotmedia/RMStore' s.author = 'Hermes Pique' s.social_media_url = 'https://twitter.com/hpique' - s.source = { :git => 'https://github.com/robotmedia/RMStore.git', :tag => "v#{s.version}" } + s.source = { :git => 'https://bitbucket.org/ipnossoft/pod-rm-store.git', :tag => "v#{s.version}" } s.platform = :ios, '7.0' s.frameworks = 'StoreKit' s.requires_arc = true From 1396cbbc4fc86d0990568332120493d586d09be4 Mon Sep 17 00:00:00 2001 From: Sean Blahovici Date: Wed, 19 Aug 2015 15:46:20 -0400 Subject: [PATCH 04/19] Forgot nil check on producit Id for the set --- RMStore/RMStore.m | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/RMStore/RMStore.m b/RMStore/RMStore.m index ce76a107..67c4ee8a 100755 --- a/RMStore/RMStore.m +++ b/RMStore/RMStore.m @@ -136,7 +136,7 @@ @implementation RMStore { NSMutableArray *_restoredTransactions; - NSMutableSet *_pendingRestoredTransactionsCount; + NSMutableSet *_pendingRestoredTransactionIds; BOOL _restoredCompletedTransactionsFinished; SKReceiptRefreshRequest *_refreshReceiptRequest; @@ -155,7 +155,7 @@ - (id) init _products = [NSMutableDictionary dictionary]; _productsRequestDelegates = [NSMutableSet set]; _restoredTransactions = [NSMutableArray array]; - _pendingRestoredTransactionsCount = [NSMutableSet set]; + _pendingRestoredTransactionIds = [NSMutableSet set]; [[SKPaymentQueue defaultQueue] addTransactionObserver:self]; } return self; @@ -255,7 +255,7 @@ - (void)restoreTransactionsOnSuccess:(void (^)(NSArray *transactions))successBlo failure:(void (^)(NSError *error))failureBlock { _restoredCompletedTransactionsFinished = NO; - [_pendingRestoredTransactionsCount removeAllObjects]; + [_pendingRestoredTransactionIds removeAllObjects]; _restoredTransactions = [NSMutableArray array]; _restoreTransactionsSuccessBlock = successBlock; _restoreTransactionsFailureBlock = failureBlock; @@ -268,7 +268,7 @@ - (void)restoreTransactionsOfUser:(NSString*)userIdentifier { NSAssert([[SKPaymentQueue defaultQueue] respondsToSelector:@selector(restoreCompletedTransactionsWithApplicationUsername:)], @"restoreCompletedTransactionsWithApplicationUsername: not supported in this iOS version. Use restoreTransactionsOnSuccess:failure: instead."); _restoredCompletedTransactionsFinished = NO; - [_pendingRestoredTransactionsCount removeAllObjects]; + [_pendingRestoredTransactionIds removeAllObjects]; _restoreTransactionsSuccessBlock = successBlock; _restoreTransactionsFailureBlock = failureBlock; [[SKPaymentQueue defaultQueue] restoreCompletedTransactionsWithApplicationUsername:userIdentifier]; @@ -573,7 +573,9 @@ - (void)didRestoreTransaction:(SKPaymentTransaction *)transaction queue:(SKPayme NSString *productIdentifier = transaction.originalTransaction.payment.productIdentifier; RMStoreLog(@"transaction restored with product %@", productIdentifier); - [_pendingRestoredTransactionsCount addObject:productIdentifier]; + if(productIdentifier) { + [_pendingRestoredTransactionIds addObject:productIdentifier]; + } if (self.receiptVerificator != nil) { [self.receiptVerificator verifyTransaction:transaction success:^{ @@ -656,9 +658,9 @@ - (void)notifyRestoreTransactionFinishedIfApplicableAfterTransaction:(SKPaymentT if (transaction != nil) { [_restoredTransactions addObject:transaction]; - [_pendingRestoredTransactionsCount removeObject:transaction.payment.productIdentifier]; + [_pendingRestoredTransactionIds removeObject:transaction.payment.productIdentifier]; } - if (_restoredCompletedTransactionsFinished && _pendingRestoredTransactionsCount.count == 0) + if (_restoredCompletedTransactionsFinished && _pendingRestoredTransactionIds.count == 0) { // Wait until all restored transations have been verified NSArray *restoredTransactions = [_restoredTransactions copy]; if (_restoreTransactionsSuccessBlock != nil) From 858fb439a583554d3b0a778193752d21eb69bc51 Mon Sep 17 00:00:00 2001 From: Sean Blahovici Date: Wed, 19 Aug 2015 16:46:58 -0400 Subject: [PATCH 05/19] Reverting to origin podspec for pull request --- RMStore.podspec | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/RMStore.podspec b/RMStore.podspec index 736624af..27372a78 100644 --- a/RMStore.podspec +++ b/RMStore.podspec @@ -1,12 +1,12 @@ Pod::Spec.new do |s| s.name = 'RMStore' - s.version = '0.7.2' + s.version = '0.7.1' s.license = 'Apache 2.0' - s.summary = 'A lightweight iOS library for In-App Purchases that adds blocks and notifications to StoreKit, plus verification, persistence and downloads.' + s.summary = 'A lightweight iOS library for In-App Purchases. RMStore add blocks and notifications to StoreKit, plus receipt verification, content downloads and transaction persistence.' s.homepage = 'https://github.com/robotmedia/RMStore' s.author = 'Hermes Pique' s.social_media_url = 'https://twitter.com/hpique' - s.source = { :git => 'https://bitbucket.org/ipnossoft/pod-rm-store.git', :tag => "v#{s.version}" } + s.source = { :git => 'https://github.com/robotmedia/RMStore.git', :tag => "v#{s.version}" } s.platform = :ios, '7.0' s.frameworks = 'StoreKit' s.requires_arc = true From 303b1e9625a80b21e195e7a58034f33a63edbeb1 Mon Sep 17 00:00:00 2001 From: Hermes Pique Date: Sun, 3 Jan 2016 14:15:32 +0100 Subject: [PATCH 06/19] Update README.md --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 4c2a0ae6..62fa551d 100644 --- a/README.md +++ b/README.md @@ -1,8 +1,8 @@ #RMStore -[![Join the chat at https://gitter.im/robotmedia/RMStore](https://badges.gitter.im/robotmedia/RMStore.svg)](https://gitter.im/robotmedia/RMStore?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) -[![Version](https://cocoapod-badges.herokuapp.com/v/RMStore/badge.png)](http://cocoadocs.org/docsets/RMStore) [![Platform](https://cocoapod-badges.herokuapp.com/p/RMStore/badge.png)](http://cocoadocs.org/docsets/RMStore) +[![CocoaPods Version](https://cocoapod-badges.herokuapp.com/v/RMStore/badge.png)](http://cocoadocs.org/docsets/RMStore) [![Platform](https://cocoapod-badges.herokuapp.com/p/RMStore/badge.png)](http://cocoadocs.org/docsets/RMStore) [![Build Status](https://travis-ci.org/robotmedia/RMStore.png)](https://travis-ci.org/robotmedia/RMStore) +[![Join the chat at https://gitter.im/robotmedia/RMStore](https://badges.gitter.im/robotmedia/RMStore.svg)](https://gitter.im/robotmedia/RMStore?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) A lightweight iOS library for In-App Purchases. From 3153a69b451b1bf347e852e4dd1b8614fa02e25b Mon Sep 17 00:00:00 2001 From: Sean Blahovici Date: Mon, 4 Jan 2016 10:42:38 -0500 Subject: [PATCH 07/19] Fixed wrong formatting and changed description in podspec --- RMStore.podspec | 2 +- RMStore/RMStore.m | 20 -------------------- 2 files changed, 1 insertion(+), 21 deletions(-) diff --git a/RMStore.podspec b/RMStore.podspec index 27372a78..d557348d 100644 --- a/RMStore.podspec +++ b/RMStore.podspec @@ -2,7 +2,7 @@ Pod::Spec.new do |s| s.name = 'RMStore' s.version = '0.7.1' s.license = 'Apache 2.0' - s.summary = 'A lightweight iOS library for In-App Purchases. RMStore add blocks and notifications to StoreKit, plus receipt verification, content downloads and transaction persistence.' + s.summary = 'A lightweight iOS library for In-App Purchases that adds blocks and notifications to StoreKit, plus verification, persistence and downloads.' s.homepage = 'https://github.com/robotmedia/RMStore' s.author = 'Hermes Pique' s.social_media_url = 'https://twitter.com/hpique' diff --git a/RMStore/RMStore.m b/RMStore/RMStore.m index 67c4ee8a..84fb2f8c 100755 --- a/RMStore/RMStore.m +++ b/RMStore/RMStore.m @@ -133,16 +133,12 @@ @implementation RMStore { NSMutableDictionary *_addPaymentParameters; // HACK: We use a dictionary of product identifiers because the returned SKPayment is different from the one we add to the queue. Bad Apple. NSMutableDictionary *_products; NSMutableSet *_productsRequestDelegates; - NSMutableArray *_restoredTransactions; - NSMutableSet *_pendingRestoredTransactionIds; BOOL _restoredCompletedTransactionsFinished; - SKReceiptRefreshRequest *_refreshReceiptRequest; void (^_refreshReceiptFailureBlock)(NSError* error); void (^_refreshReceiptSuccessBlock)(); - void (^_restoreTransactionsFailureBlock)(NSError* error); void (^_restoreTransactionsSuccessBlock)(NSArray* transactions); } @@ -216,12 +212,10 @@ - (void)addPayment:(NSString*)productIdentifier { payment.applicationUsername = userIdentifier; } - RMAddPaymentParameters *parameters = [[RMAddPaymentParameters alloc] init]; parameters.successBlock = successBlock; parameters.failureBlock = failureBlock; _addPaymentParameters[productIdentifier] = parameters; - [[SKPaymentQueue defaultQueue] addPayment:payment]; } @@ -239,10 +233,8 @@ - (void)requestProducts:(NSSet*)identifiers delegate.successBlock = successBlock; delegate.failureBlock = failureBlock; [_productsRequestDelegates addObject:delegate]; - SKProductsRequest *productsRequest = [[SKProductsRequest alloc] initWithProductIdentifiers:identifiers]; productsRequest.delegate = delegate; - [productsRequest start]; } @@ -393,7 +385,6 @@ - (void)paymentQueueRestoreCompletedTransactionsFinished:(SKPaymentQueue *)queue { RMStoreLog(@"restore transactions finished"); _restoredCompletedTransactionsFinished = YES; - [self notifyRestoreTransactionFinishedIfApplicableAfterTransaction:nil]; } @@ -479,7 +470,6 @@ - (void)didFinishDownload:(SKDownload*)download queue:(SKPaymentQueue*)queue { SKPaymentTransaction *transaction = download.transaction; RMStoreLog(@"download %@ for product %@ finished", download.contentIdentifier, transaction.payment.productIdentifier); - [self postNotificationWithName:RMSKDownloadFinished download:download userInfoExtras:nil]; const BOOL hasPendingDownloads = [self.class hasPendingDownloadsInTransaction:transaction]; @@ -526,7 +516,6 @@ + (BOOL)hasPendingDownloadsInTransaction:(SKPaymentTransaction*)transaction - (void)didPurchaseTransaction:(SKPaymentTransaction *)transaction queue:(SKPaymentQueue*)queue { RMStoreLog(@"transaction purchased with product %@", transaction.payment.productIdentifier); - if (self.receiptVerificator != nil) { [self.receiptVerificator verifyTransaction:transaction success:^{ @@ -547,18 +536,15 @@ - (void)didFailTransaction:(SKPaymentTransaction *)transaction queue:(SKPaymentQ SKPayment *payment = transaction.payment; NSString* productIdentifier = payment.productIdentifier; RMStoreLog(@"transaction failed with product %@ and error %@", productIdentifier, error.debugDescription); - if (error.code != RMStoreErrorCodeUnableToCompleteVerification) { // If we were unable to complete the verification we want StoreKit to keep reminding us of the transaction [queue finishTransaction:transaction]; } - RMAddPaymentParameters *parameters = [self popAddPaymentParametersForIdentifier:productIdentifier]; if (parameters.failureBlock != nil) { parameters.failureBlock(transaction, error); } - NSDictionary *extras = error ? @{RMStoreNotificationStoreError : error} : nil; [self postNotificationWithName:RMSKPaymentTransactionFailed transaction:transaction userInfoExtras:extras]; @@ -572,7 +558,6 @@ - (void)didRestoreTransaction:(SKPaymentTransaction *)transaction queue:(SKPayme { NSString *productIdentifier = transaction.originalTransaction.payment.productIdentifier; RMStoreLog(@"transaction restored with product %@", productIdentifier); - if(productIdentifier) { [_pendingRestoredTransactionIds addObject:productIdentifier]; } @@ -638,15 +623,12 @@ - (void)finishTransaction:(SKPaymentTransaction *)transaction queue:(SKPaymentQu NSString* productIdentifier = payment.productIdentifier; [queue finishTransaction:transaction]; [self.transactionPersistor persistTransaction:transaction]; - RMAddPaymentParameters *wrapper = [self popAddPaymentParametersForIdentifier:productIdentifier]; if (wrapper.successBlock != nil) { wrapper.successBlock(transaction); } - [self postNotificationWithName:RMSKPaymentTransactionFinished transaction:transaction userInfoExtras:nil]; - if (transaction.transactionState == SKPaymentTransactionStateRestored) { [self notifyRestoreTransactionFinishedIfApplicableAfterTransaction:transaction]; @@ -752,13 +734,11 @@ - (void)productsRequest:(SKProductsRequest *)request didReceiveResponse:(SKProdu RMStoreLog(@"products request received response"); NSArray *products = [NSArray arrayWithArray:response.products]; NSArray *invalidProductIdentifiers = [NSArray arrayWithArray:response.invalidProductIdentifiers]; - for (SKProduct *product in products) { RMStoreLog(@"received product with id %@", product.productIdentifier); [self.store addProduct:product]; } - [invalidProductIdentifiers enumerateObjectsUsingBlock:^(NSString *invalid, NSUInteger idx, BOOL *stop) { RMStoreLog(@"invalid product with id %@", invalid); }]; From d1737ca844cae17c6af3114c879ef57be0818e9f Mon Sep 17 00:00:00 2001 From: Sean Blahovici Date: Mon, 4 Jan 2016 10:47:05 -0500 Subject: [PATCH 08/19] Fixed another auto format problem --- RMStore/RMStore.m | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/RMStore/RMStore.m b/RMStore/RMStore.m index 84fb2f8c..ce9b79df 100755 --- a/RMStore/RMStore.m +++ b/RMStore/RMStore.m @@ -185,16 +185,16 @@ - (void)addPayment:(NSString*)productIdentifier } - (void)addPayment:(NSString*)productIdentifier - success:(void (^)(SKPaymentTransaction *transaction))successBlock - failure:(void (^)(SKPaymentTransaction *transaction, NSError *error))failureBlock + success:(void (^)(SKPaymentTransaction *transaction))successBlock + failure:(void (^)(SKPaymentTransaction *transaction, NSError *error))failureBlock { [self addPayment:productIdentifier user:nil success:successBlock failure:failureBlock]; } - (void)addPayment:(NSString*)productIdentifier - user:(NSString*)userIdentifier - success:(void (^)(SKPaymentTransaction *transaction))successBlock - failure:(void (^)(SKPaymentTransaction *transaction, NSError *error))failureBlock + user:(NSString*)userIdentifier + success:(void (^)(SKPaymentTransaction *transaction))successBlock + failure:(void (^)(SKPaymentTransaction *transaction, NSError *error))failureBlock { SKProduct *product = [self productForIdentifier:productIdentifier]; if (product == nil) @@ -225,8 +225,8 @@ - (void)requestProducts:(NSSet*)identifiers } - (void)requestProducts:(NSSet*)identifiers - success:(RMSKProductsRequestSuccessBlock)successBlock - failure:(RMSKProductsRequestFailureBlock)failureBlock + success:(RMSKProductsRequestSuccessBlock)successBlock + failure:(RMSKProductsRequestFailureBlock)failureBlock { RMProductsRequestDelegate *delegate = [[RMProductsRequestDelegate alloc] init]; delegate.store = self; @@ -244,7 +244,7 @@ - (void)restoreTransactions } - (void)restoreTransactionsOnSuccess:(void (^)(NSArray *transactions))successBlock - failure:(void (^)(NSError *error))failureBlock + failure:(void (^)(NSError *error))failureBlock { _restoredCompletedTransactionsFinished = NO; [_pendingRestoredTransactionIds removeAllObjects]; @@ -255,8 +255,8 @@ - (void)restoreTransactionsOnSuccess:(void (^)(NSArray *transactions))successBlo } - (void)restoreTransactionsOfUser:(NSString*)userIdentifier - onSuccess:(void (^)(NSArray *transactions))successBlock - failure:(void (^)(NSError *error))failureBlock + onSuccess:(void (^)(NSArray *transactions))successBlock + failure:(void (^)(NSError *error))failureBlock { NSAssert([[SKPaymentQueue defaultQueue] respondsToSelector:@selector(restoreCompletedTransactionsWithApplicationUsername:)], @"restoreCompletedTransactionsWithApplicationUsername: not supported in this iOS version. Use restoreTransactionsOnSuccess:failure: instead."); _restoredCompletedTransactionsFinished = NO; @@ -282,7 +282,7 @@ - (void)refreshReceipt } - (void)refreshReceiptOnSuccess:(RMStoreSuccessBlock)successBlock - failure:(RMStoreFailureBlock)failureBlock + failure:(RMStoreFailureBlock)failureBlock { _refreshReceiptFailureBlock = failureBlock; _refreshReceiptSuccessBlock = successBlock; From 811d820825b369849a6d91a298195135c086138a Mon Sep 17 00:00:00 2001 From: Sean Blahovici Date: Mon, 4 Jan 2016 10:50:17 -0500 Subject: [PATCH 09/19] Removing remaining new lines --- RMStore/RMStore.m | 2 -- 1 file changed, 2 deletions(-) diff --git a/RMStore/RMStore.m b/RMStore/RMStore.m index ce9b79df..fbd681b4 100755 --- a/RMStore/RMStore.m +++ b/RMStore/RMStore.m @@ -547,7 +547,6 @@ - (void)didFailTransaction:(SKPaymentTransaction *)transaction queue:(SKPaymentQ } NSDictionary *extras = error ? @{RMStoreNotificationStoreError : error} : nil; [self postNotificationWithName:RMSKPaymentTransactionFailed transaction:transaction userInfoExtras:extras]; - if (transaction.transactionState == SKPaymentTransactionStateRestored) { [self notifyRestoreTransactionFinishedIfApplicableAfterTransaction:transaction]; @@ -742,7 +741,6 @@ - (void)productsRequest:(SKProductsRequest *)request didReceiveResponse:(SKProdu [invalidProductIdentifiers enumerateObjectsUsingBlock:^(NSString *invalid, NSUInteger idx, BOOL *stop) { RMStoreLog(@"invalid product with id %@", invalid); }]; - if (self.successBlock) { self.successBlock(products, invalidProductIdentifiers); From 2d493eeeaa12b326a4da0aaf2536ffe59c31e369 Mon Sep 17 00:00:00 2001 From: Sean Blahovici Date: Mon, 4 Jan 2016 10:57:24 -0500 Subject: [PATCH 10/19] Did a proper compare to the latest version of RMStore. Reset all formatting and added new lines where necessary. --- RMStore/RMStore.m | 35 ++++++++++++++++++++++++++++------- 1 file changed, 28 insertions(+), 7 deletions(-) diff --git a/RMStore/RMStore.m b/RMStore/RMStore.m index fbd681b4..2500e8bd 100755 --- a/RMStore/RMStore.m +++ b/RMStore/RMStore.m @@ -133,12 +133,15 @@ @implementation RMStore { NSMutableDictionary *_addPaymentParameters; // HACK: We use a dictionary of product identifiers because the returned SKPayment is different from the one we add to the queue. Bad Apple. NSMutableDictionary *_products; NSMutableSet *_productsRequestDelegates; + NSMutableArray *_restoredTransactions; NSMutableSet *_pendingRestoredTransactionIds; BOOL _restoredCompletedTransactionsFinished; + SKReceiptRefreshRequest *_refreshReceiptRequest; void (^_refreshReceiptFailureBlock)(NSError* error); void (^_refreshReceiptSuccessBlock)(); + void (^_restoreTransactionsFailureBlock)(NSError* error); void (^_restoreTransactionsSuccessBlock)(NSArray* transactions); } @@ -212,10 +215,12 @@ - (void)addPayment:(NSString*)productIdentifier { payment.applicationUsername = userIdentifier; } + RMAddPaymentParameters *parameters = [[RMAddPaymentParameters alloc] init]; parameters.successBlock = successBlock; parameters.failureBlock = failureBlock; _addPaymentParameters[productIdentifier] = parameters; + [[SKPaymentQueue defaultQueue] addPayment:payment]; } @@ -233,8 +238,10 @@ - (void)requestProducts:(NSSet*)identifiers delegate.successBlock = successBlock; delegate.failureBlock = failureBlock; [_productsRequestDelegates addObject:delegate]; + SKProductsRequest *productsRequest = [[SKProductsRequest alloc] initWithProductIdentifiers:identifiers]; - productsRequest.delegate = delegate; + productsRequest.delegate = delegate; + [productsRequest start]; } @@ -300,11 +307,11 @@ - (SKProduct*)productForIdentifier:(NSString*)productIdentifier + (NSString*)localizedPriceOfProduct:(SKProduct*)product { - NSNumberFormatter *numberFormatter = [[NSNumberFormatter alloc] init]; - numberFormatter.numberStyle = NSNumberFormatterCurrencyStyle; - numberFormatter.locale = product.priceLocale; - NSString *formattedString = [numberFormatter stringFromNumber:product.price]; - return formattedString; + NSNumberFormatter *numberFormatter = [[NSNumberFormatter alloc] init]; + numberFormatter.numberStyle = NSNumberFormatterCurrencyStyle; + numberFormatter.locale = product.priceLocale; + NSString *formattedString = [numberFormatter stringFromNumber:product.price]; + return formattedString; } #pragma mark Observers @@ -385,6 +392,7 @@ - (void)paymentQueueRestoreCompletedTransactionsFinished:(SKPaymentQueue *)queue { RMStoreLog(@"restore transactions finished"); _restoredCompletedTransactionsFinished = YES; + [self notifyRestoreTransactionFinishedIfApplicableAfterTransaction:nil]; } @@ -470,6 +478,7 @@ - (void)didFinishDownload:(SKDownload*)download queue:(SKPaymentQueue*)queue { SKPaymentTransaction *transaction = download.transaction; RMStoreLog(@"download %@ for product %@ finished", download.contentIdentifier, transaction.payment.productIdentifier); + [self postNotificationWithName:RMSKDownloadFinished download:download userInfoExtras:nil]; const BOOL hasPendingDownloads = [self.class hasPendingDownloadsInTransaction:transaction]; @@ -516,6 +525,7 @@ + (BOOL)hasPendingDownloadsInTransaction:(SKPaymentTransaction*)transaction - (void)didPurchaseTransaction:(SKPaymentTransaction *)transaction queue:(SKPaymentQueue*)queue { RMStoreLog(@"transaction purchased with product %@", transaction.payment.productIdentifier); + if (self.receiptVerificator != nil) { [self.receiptVerificator verifyTransaction:transaction success:^{ @@ -536,17 +546,21 @@ - (void)didFailTransaction:(SKPaymentTransaction *)transaction queue:(SKPaymentQ SKPayment *payment = transaction.payment; NSString* productIdentifier = payment.productIdentifier; RMStoreLog(@"transaction failed with product %@ and error %@", productIdentifier, error.debugDescription); + if (error.code != RMStoreErrorCodeUnableToCompleteVerification) { // If we were unable to complete the verification we want StoreKit to keep reminding us of the transaction [queue finishTransaction:transaction]; } + RMAddPaymentParameters *parameters = [self popAddPaymentParametersForIdentifier:productIdentifier]; if (parameters.failureBlock != nil) { parameters.failureBlock(transaction, error); } + NSDictionary *extras = error ? @{RMStoreNotificationStoreError : error} : nil; [self postNotificationWithName:RMSKPaymentTransactionFailed transaction:transaction userInfoExtras:extras]; + if (transaction.transactionState == SKPaymentTransactionStateRestored) { [self notifyRestoreTransactionFinishedIfApplicableAfterTransaction:transaction]; @@ -557,6 +571,7 @@ - (void)didRestoreTransaction:(SKPaymentTransaction *)transaction queue:(SKPayme { NSString *productIdentifier = transaction.originalTransaction.payment.productIdentifier; RMStoreLog(@"transaction restored with product %@", productIdentifier); + if(productIdentifier) { [_pendingRestoredTransactionIds addObject:productIdentifier]; } @@ -619,15 +634,18 @@ - (void)didDownloadSelfHostedContentForTransaction:(SKPaymentTransaction *)trans - (void)finishTransaction:(SKPaymentTransaction *)transaction queue:(SKPaymentQueue*)queue { SKPayment *payment = transaction.payment; - NSString* productIdentifier = payment.productIdentifier; + NSString* productIdentifier = payment.productIdentifier; [queue finishTransaction:transaction]; [self.transactionPersistor persistTransaction:transaction]; + RMAddPaymentParameters *wrapper = [self popAddPaymentParametersForIdentifier:productIdentifier]; if (wrapper.successBlock != nil) { wrapper.successBlock(transaction); } + [self postNotificationWithName:RMSKPaymentTransactionFinished transaction:transaction userInfoExtras:nil]; + if (transaction.transactionState == SKPaymentTransactionStateRestored) { [self notifyRestoreTransactionFinishedIfApplicableAfterTransaction:transaction]; @@ -733,14 +751,17 @@ - (void)productsRequest:(SKProductsRequest *)request didReceiveResponse:(SKProdu RMStoreLog(@"products request received response"); NSArray *products = [NSArray arrayWithArray:response.products]; NSArray *invalidProductIdentifiers = [NSArray arrayWithArray:response.invalidProductIdentifiers]; + for (SKProduct *product in products) { RMStoreLog(@"received product with id %@", product.productIdentifier); [self.store addProduct:product]; } + [invalidProductIdentifiers enumerateObjectsUsingBlock:^(NSString *invalid, NSUInteger idx, BOOL *stop) { RMStoreLog(@"invalid product with id %@", invalid); }]; + if (self.successBlock) { self.successBlock(products, invalidProductIdentifiers); From 344a5d7183701947f0a1c724331b44b032e30b78 Mon Sep 17 00:00:00 2001 From: Sean Blahovici Date: Wed, 19 Aug 2015 15:06:07 -0400 Subject: [PATCH 11/19] Added MutableSet instead of regular counter to insure that callback is always called in the case of duplicate updatedTransaction callbacks --- RMStore/RMStore.m | 25 +++++++++++++------------ 1 file changed, 13 insertions(+), 12 deletions(-) diff --git a/RMStore/RMStore.m b/RMStore/RMStore.m index ece43bd9..3f4993f4 100755 --- a/RMStore/RMStore.m +++ b/RMStore/RMStore.m @@ -135,8 +135,8 @@ @implementation RMStore { NSMutableSet *_productsRequestDelegates; NSMutableArray *_restoredTransactions; - - NSInteger _pendingRestoredTransactionsCount; + + NSMutableSet *_pendingRestoredTransactionsCount; BOOL _restoredCompletedTransactionsFinished; SKReceiptRefreshRequest *_refreshReceiptRequest; @@ -155,6 +155,7 @@ - (instancetype) init _products = [NSMutableDictionary dictionary]; _productsRequestDelegates = [NSMutableSet set]; _restoredTransactions = [NSMutableArray array]; + _pendingRestoredTransactionsCount = [NSMutableSet set]; [[SKPaymentQueue defaultQueue] addTransactionObserver:self]; } return self; @@ -254,7 +255,7 @@ - (void)restoreTransactionsOnSuccess:(void (^)(NSArray *transactions))successBlo failure:(void (^)(NSError *error))failureBlock { _restoredCompletedTransactionsFinished = NO; - _pendingRestoredTransactionsCount = 0; + [_pendingRestoredTransactionsCount removeAllObjects]; _restoredTransactions = [NSMutableArray array]; _restoreTransactionsSuccessBlock = successBlock; _restoreTransactionsFailureBlock = failureBlock; @@ -267,7 +268,7 @@ - (void)restoreTransactionsOfUser:(NSString*)userIdentifier { NSAssert([[SKPaymentQueue defaultQueue] respondsToSelector:@selector(restoreCompletedTransactionsWithApplicationUsername:)], @"restoreCompletedTransactionsWithApplicationUsername: not supported in this iOS version. Use restoreTransactionsOnSuccess:failure: instead."); _restoredCompletedTransactionsFinished = NO; - _pendingRestoredTransactionsCount = 0; + [_pendingRestoredTransactionsCount removeAllObjects]; _restoreTransactionsSuccessBlock = successBlock; _restoreTransactionsFailureBlock = failureBlock; [[SKPaymentQueue defaultQueue] restoreCompletedTransactionsWithApplicationUsername:userIdentifier]; @@ -525,8 +526,8 @@ + (BOOL)hasPendingDownloadsInTransaction:(SKPaymentTransaction*)transaction - (void)didPurchaseTransaction:(SKPaymentTransaction *)transaction queue:(SKPaymentQueue*)queue { RMStoreLog(@"transaction purchased with product %@", transaction.payment.productIdentifier); - - if (self.receiptVerifier != nil) + + if (self.receiptVerificator != nil) { [self.receiptVerifier verifyTransaction:transaction success:^{ [self didVerifyTransaction:transaction queue:queue]; @@ -570,9 +571,9 @@ - (void)didFailTransaction:(SKPaymentTransaction *)transaction queue:(SKPaymentQ - (void)didRestoreTransaction:(SKPaymentTransaction *)transaction queue:(SKPaymentQueue*)queue { RMStoreLog(@"transaction restored with product %@", transaction.originalTransaction.payment.productIdentifier); - - _pendingRestoredTransactionsCount++; - if (self.receiptVerifier != nil) + + [_pendingRestoredTransactionsCount addObject:productIdentifier]; + if (self.receiptVerificator != nil) { [self.receiptVerifier verifyTransaction:transaction success:^{ [self didVerifyTransaction:transaction queue:queue]; @@ -631,7 +632,7 @@ - (void)didDownloadSelfHostedContentForTransaction:(SKPaymentTransaction *)trans - (void)finishTransaction:(SKPaymentTransaction *)transaction queue:(SKPaymentQueue*)queue { SKPayment *payment = transaction.payment; - NSString* productIdentifier = payment.productIdentifier; + NSString* productIdentifier = payment.productIdentifier; [queue finishTransaction:transaction]; [self.transactionPersistor persistTransaction:transaction]; @@ -654,9 +655,9 @@ - (void)notifyRestoreTransactionFinishedIfApplicableAfterTransaction:(SKPaymentT if (transaction != nil) { [_restoredTransactions addObject:transaction]; - _pendingRestoredTransactionsCount--; + [_pendingRestoredTransactionsCount removeObject:transaction.payment.productIdentifier]; } - if (_restoredCompletedTransactionsFinished && _pendingRestoredTransactionsCount == 0) + if (_restoredCompletedTransactionsFinished && _pendingRestoredTransactionsCount.count == 0) { // Wait until all restored transations have been verified NSArray *restoredTransactions = [_restoredTransactions copy]; if (_restoreTransactionsSuccessBlock != nil) From 58c63e4871f794f3383a14ff7cf604198900837d Mon Sep 17 00:00:00 2001 From: Sean Blahovici Date: Wed, 19 Aug 2015 15:11:29 -0400 Subject: [PATCH 12/19] Updating version podspec --- RMStore.podspec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/RMStore.podspec b/RMStore.podspec index 3e89f892..a3e99e98 100644 --- a/RMStore.podspec +++ b/RMStore.podspec @@ -1,6 +1,6 @@ Pod::Spec.new do |s| s.name = 'RMStore' - s.version = '0.7.1' + s.version = '0.7.2' s.license = 'Apache 2.0' s.summary = 'A lightweight iOS library for In-App Purchases that adds blocks and notifications to StoreKit, plus verification, persistence and downloads.' s.homepage = 'https://github.com/robotmedia/RMStore' From 86bc310d5cd1226aeb27cece2116ce29264ddb07 Mon Sep 17 00:00:00 2001 From: Sean Blahovici Date: Wed, 19 Aug 2015 15:19:03 -0400 Subject: [PATCH 13/19] Updating podspec source --- RMStore.podspec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/RMStore.podspec b/RMStore.podspec index a3e99e98..1c88a0ca 100644 --- a/RMStore.podspec +++ b/RMStore.podspec @@ -6,7 +6,7 @@ Pod::Spec.new do |s| s.homepage = 'https://github.com/robotmedia/RMStore' s.author = 'Hermes Pique' s.social_media_url = 'https://twitter.com/hpique' - s.source = { :git => 'https://github.com/robotmedia/RMStore.git', :tag => "v#{s.version}" } + s.source = { :git => 'https://bitbucket.org/ipnossoft/pod-rm-store.git', :tag => "v#{s.version}" } s.platform = :ios, '7.0' s.frameworks = 'StoreKit' s.requires_arc = true From 576560fba4415c0912133cf24f49a12ab1b76209 Mon Sep 17 00:00:00 2001 From: Sean Blahovici Date: Wed, 19 Aug 2015 15:46:20 -0400 Subject: [PATCH 14/19] Forgot nil check on producit Id for the set --- RMStore/RMStore.m | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/RMStore/RMStore.m b/RMStore/RMStore.m index 3f4993f4..75d8e233 100755 --- a/RMStore/RMStore.m +++ b/RMStore/RMStore.m @@ -136,7 +136,7 @@ @implementation RMStore { NSMutableArray *_restoredTransactions; - NSMutableSet *_pendingRestoredTransactionsCount; + NSMutableSet *_pendingRestoredTransactionIds; BOOL _restoredCompletedTransactionsFinished; SKReceiptRefreshRequest *_refreshReceiptRequest; @@ -155,7 +155,7 @@ - (instancetype) init _products = [NSMutableDictionary dictionary]; _productsRequestDelegates = [NSMutableSet set]; _restoredTransactions = [NSMutableArray array]; - _pendingRestoredTransactionsCount = [NSMutableSet set]; + _pendingRestoredTransactionIds = [NSMutableSet set]; [[SKPaymentQueue defaultQueue] addTransactionObserver:self]; } return self; @@ -255,7 +255,7 @@ - (void)restoreTransactionsOnSuccess:(void (^)(NSArray *transactions))successBlo failure:(void (^)(NSError *error))failureBlock { _restoredCompletedTransactionsFinished = NO; - [_pendingRestoredTransactionsCount removeAllObjects]; + [_pendingRestoredTransactionIds removeAllObjects]; _restoredTransactions = [NSMutableArray array]; _restoreTransactionsSuccessBlock = successBlock; _restoreTransactionsFailureBlock = failureBlock; @@ -268,7 +268,7 @@ - (void)restoreTransactionsOfUser:(NSString*)userIdentifier { NSAssert([[SKPaymentQueue defaultQueue] respondsToSelector:@selector(restoreCompletedTransactionsWithApplicationUsername:)], @"restoreCompletedTransactionsWithApplicationUsername: not supported in this iOS version. Use restoreTransactionsOnSuccess:failure: instead."); _restoredCompletedTransactionsFinished = NO; - [_pendingRestoredTransactionsCount removeAllObjects]; + [_pendingRestoredTransactionIds removeAllObjects]; _restoreTransactionsSuccessBlock = successBlock; _restoreTransactionsFailureBlock = failureBlock; [[SKPaymentQueue defaultQueue] restoreCompletedTransactionsWithApplicationUsername:userIdentifier]; @@ -572,7 +572,9 @@ - (void)didRestoreTransaction:(SKPaymentTransaction *)transaction queue:(SKPayme { RMStoreLog(@"transaction restored with product %@", transaction.originalTransaction.payment.productIdentifier); - [_pendingRestoredTransactionsCount addObject:productIdentifier]; + if(productIdentifier) { + [_pendingRestoredTransactionIds addObject:productIdentifier]; + } if (self.receiptVerificator != nil) { [self.receiptVerifier verifyTransaction:transaction success:^{ @@ -655,9 +657,9 @@ - (void)notifyRestoreTransactionFinishedIfApplicableAfterTransaction:(SKPaymentT if (transaction != nil) { [_restoredTransactions addObject:transaction]; - [_pendingRestoredTransactionsCount removeObject:transaction.payment.productIdentifier]; + [_pendingRestoredTransactionIds removeObject:transaction.payment.productIdentifier]; } - if (_restoredCompletedTransactionsFinished && _pendingRestoredTransactionsCount.count == 0) + if (_restoredCompletedTransactionsFinished && _pendingRestoredTransactionIds.count == 0) { // Wait until all restored transations have been verified NSArray *restoredTransactions = [_restoredTransactions copy]; if (_restoreTransactionsSuccessBlock != nil) From 551a7e2497075ffff85d80744d865d70940434a3 Mon Sep 17 00:00:00 2001 From: Sean Blahovici Date: Wed, 19 Aug 2015 16:46:58 -0400 Subject: [PATCH 15/19] Reverting to origin podspec for pull request --- RMStore.podspec | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/RMStore.podspec b/RMStore.podspec index 1c88a0ca..065979ff 100644 --- a/RMStore.podspec +++ b/RMStore.podspec @@ -1,12 +1,12 @@ Pod::Spec.new do |s| s.name = 'RMStore' - s.version = '0.7.2' + s.version = '0.7.1' s.license = 'Apache 2.0' - s.summary = 'A lightweight iOS library for In-App Purchases that adds blocks and notifications to StoreKit, plus verification, persistence and downloads.' + s.summary = 'A lightweight iOS library for In-App Purchases. RMStore add blocks and notifications to StoreKit, plus receipt verification, content downloads and transaction persistence.' s.homepage = 'https://github.com/robotmedia/RMStore' s.author = 'Hermes Pique' s.social_media_url = 'https://twitter.com/hpique' - s.source = { :git => 'https://bitbucket.org/ipnossoft/pod-rm-store.git', :tag => "v#{s.version}" } + s.source = { :git => 'https://github.com/robotmedia/RMStore.git', :tag => "v#{s.version}" } s.platform = :ios, '7.0' s.frameworks = 'StoreKit' s.requires_arc = true From 968349bed183bf4606b9a2a31a6a0c210bab130a Mon Sep 17 00:00:00 2001 From: Sean Blahovici Date: Mon, 4 Jan 2016 10:42:38 -0500 Subject: [PATCH 16/19] Fixed wrong formatting and changed description in podspec --- RMStore.podspec | 2 +- RMStore/RMStore.m | 42 ++++++++++++++++++++---------------------- 2 files changed, 21 insertions(+), 23 deletions(-) diff --git a/RMStore.podspec b/RMStore.podspec index 065979ff..3e89f892 100644 --- a/RMStore.podspec +++ b/RMStore.podspec @@ -2,7 +2,7 @@ Pod::Spec.new do |s| s.name = 'RMStore' s.version = '0.7.1' s.license = 'Apache 2.0' - s.summary = 'A lightweight iOS library for In-App Purchases. RMStore add blocks and notifications to StoreKit, plus receipt verification, content downloads and transaction persistence.' + s.summary = 'A lightweight iOS library for In-App Purchases that adds blocks and notifications to StoreKit, plus verification, persistence and downloads.' s.homepage = 'https://github.com/robotmedia/RMStore' s.author = 'Hermes Pique' s.social_media_url = 'https://twitter.com/hpique' diff --git a/RMStore/RMStore.m b/RMStore/RMStore.m index 75d8e233..2e3c5b66 100755 --- a/RMStore/RMStore.m +++ b/RMStore/RMStore.m @@ -133,16 +133,15 @@ @implementation RMStore { NSMutableDictionary *_addPaymentParameters; // HACK: We use a dictionary of product identifiers because the returned SKPayment is different from the one we add to the queue. Bad Apple. NSMutableDictionary *_products; NSMutableSet *_productsRequestDelegates; - - NSMutableArray *_restoredTransactions; + NSMutableArray *_restoredTransactions; NSMutableSet *_pendingRestoredTransactionIds; BOOL _restoredCompletedTransactionsFinished; - + SKReceiptRefreshRequest *_refreshReceiptRequest; void (^_refreshReceiptFailureBlock)(NSError* error); void (^_refreshReceiptSuccessBlock)(); - + void (^_restoreTransactionsFailureBlock)(NSError* error); void (^_restoreTransactionsSuccessBlock)(NSArray* transactions); } @@ -216,12 +215,12 @@ - (void)addPayment:(NSString*)productIdentifier { payment.applicationUsername = userIdentifier; } - + RMAddPaymentParameters *parameters = [[RMAddPaymentParameters alloc] init]; parameters.successBlock = successBlock; parameters.failureBlock = failureBlock; _addPaymentParameters[productIdentifier] = parameters; - + [[SKPaymentQueue defaultQueue] addPayment:payment]; } @@ -239,10 +238,10 @@ - (void)requestProducts:(NSSet*)identifiers delegate.successBlock = successBlock; delegate.failureBlock = failureBlock; [_productsRequestDelegates addObject:delegate]; - + SKProductsRequest *productsRequest = [[SKProductsRequest alloc] initWithProductIdentifiers:identifiers]; productsRequest.delegate = delegate; - + [productsRequest start]; } @@ -393,7 +392,7 @@ - (void)paymentQueueRestoreCompletedTransactionsFinished:(SKPaymentQueue *)queue { RMStoreLog(@"restore transactions finished"); _restoredCompletedTransactionsFinished = YES; - + [self notifyRestoreTransactionFinishedIfApplicableAfterTransaction:nil]; } @@ -479,7 +478,7 @@ - (void)didFinishDownload:(SKDownload*)download queue:(SKPaymentQueue*)queue { SKPaymentTransaction *transaction = download.transaction; RMStoreLog(@"download %@ for product %@ finished", download.contentIdentifier, transaction.payment.productIdentifier); - + [self postNotificationWithName:RMSKDownloadFinished download:download userInfoExtras:nil]; const BOOL hasPendingDownloads = [self.class hasPendingDownloadsInTransaction:transaction]; @@ -526,7 +525,6 @@ + (BOOL)hasPendingDownloadsInTransaction:(SKPaymentTransaction*)transaction - (void)didPurchaseTransaction:(SKPaymentTransaction *)transaction queue:(SKPaymentQueue*)queue { RMStoreLog(@"transaction purchased with product %@", transaction.payment.productIdentifier); - if (self.receiptVerificator != nil) { [self.receiptVerifier verifyTransaction:transaction success:^{ @@ -547,21 +545,21 @@ - (void)didFailTransaction:(SKPaymentTransaction *)transaction queue:(SKPaymentQ SKPayment *payment = transaction.payment; NSString* productIdentifier = payment.productIdentifier; RMStoreLog(@"transaction failed with product %@ and error %@", productIdentifier, error.debugDescription); - + if (error.code != RMStoreErrorCodeUnableToCompleteVerification) { // If we were unable to complete the verification we want StoreKit to keep reminding us of the transaction [queue finishTransaction:transaction]; } - + RMAddPaymentParameters *parameters = [self popAddPaymentParametersForIdentifier:productIdentifier]; if (parameters.failureBlock != nil) { parameters.failureBlock(transaction, error); } - + NSDictionary *extras = error ? @{RMStoreNotificationStoreError : error} : nil; [self postNotificationWithName:RMSKPaymentTransactionFailed transaction:transaction userInfoExtras:extras]; - + if (transaction.transactionState == SKPaymentTransactionStateRestored) { [self notifyRestoreTransactionFinishedIfApplicableAfterTransaction:transaction]; @@ -637,15 +635,15 @@ - (void)finishTransaction:(SKPaymentTransaction *)transaction queue:(SKPaymentQu NSString* productIdentifier = payment.productIdentifier; [queue finishTransaction:transaction]; [self.transactionPersistor persistTransaction:transaction]; - + RMAddPaymentParameters *wrapper = [self popAddPaymentParametersForIdentifier:productIdentifier]; if (wrapper.successBlock != nil) { wrapper.successBlock(transaction); } - + [self postNotificationWithName:RMSKPaymentTransactionFinished transaction:transaction userInfoExtras:nil]; - + if (transaction.transactionState == SKPaymentTransactionStateRestored) { [self notifyRestoreTransactionFinishedIfApplicableAfterTransaction:transaction]; @@ -714,7 +712,7 @@ - (void)request:(SKRequest *)request didFailWithError:(NSError *)error - (void)addProduct:(SKProduct*)product { - _products[product.productIdentifier] = product; + _products[product.productIdentifier] = product; } - (void)postNotificationWithName:(NSString*)notificationName download:(SKDownload*)download userInfoExtras:(NSDictionary*)extras @@ -751,17 +749,17 @@ - (void)productsRequest:(SKProductsRequest *)request didReceiveResponse:(SKProdu RMStoreLog(@"products request received response"); NSArray *products = [NSArray arrayWithArray:response.products]; NSArray *invalidProductIdentifiers = [NSArray arrayWithArray:response.invalidProductIdentifiers]; - + for (SKProduct *product in products) { RMStoreLog(@"received product with id %@", product.productIdentifier); [self.store addProduct:product]; } - + [invalidProductIdentifiers enumerateObjectsUsingBlock:^(NSString *invalid, NSUInteger idx, BOOL *stop) { RMStoreLog(@"invalid product with id %@", invalid); }]; - + if (self.successBlock) { self.successBlock(products, invalidProductIdentifiers); From a7e52f059d4dfecef1023b9f2f73043681223a10 Mon Sep 17 00:00:00 2001 From: Sean Blahovici Date: Mon, 4 Jan 2016 10:50:17 -0500 Subject: [PATCH 17/19] Removing remaining new lines --- RMStore/RMStore.m | 2 -- 1 file changed, 2 deletions(-) diff --git a/RMStore/RMStore.m b/RMStore/RMStore.m index 2e3c5b66..e46b860e 100755 --- a/RMStore/RMStore.m +++ b/RMStore/RMStore.m @@ -559,7 +559,6 @@ - (void)didFailTransaction:(SKPaymentTransaction *)transaction queue:(SKPaymentQ NSDictionary *extras = error ? @{RMStoreNotificationStoreError : error} : nil; [self postNotificationWithName:RMSKPaymentTransactionFailed transaction:transaction userInfoExtras:extras]; - if (transaction.transactionState == SKPaymentTransactionStateRestored) { [self notifyRestoreTransactionFinishedIfApplicableAfterTransaction:transaction]; @@ -759,7 +758,6 @@ - (void)productsRequest:(SKProductsRequest *)request didReceiveResponse:(SKProdu [invalidProductIdentifiers enumerateObjectsUsingBlock:^(NSString *invalid, NSUInteger idx, BOOL *stop) { RMStoreLog(@"invalid product with id %@", invalid); }]; - if (self.successBlock) { self.successBlock(products, invalidProductIdentifiers); From 6a35cf8ae0d08947b990f8b4b65fe5908a719782 Mon Sep 17 00:00:00 2001 From: Sean Blahovici Date: Mon, 4 Jan 2016 10:57:24 -0500 Subject: [PATCH 18/19] Did a proper compare to the latest version of RMStore. Reset all formatting and added new lines where necessary. --- RMStore/RMStore.m | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/RMStore/RMStore.m b/RMStore/RMStore.m index e46b860e..ee532e7f 100755 --- a/RMStore/RMStore.m +++ b/RMStore/RMStore.m @@ -525,6 +525,7 @@ + (BOOL)hasPendingDownloadsInTransaction:(SKPaymentTransaction*)transaction - (void)didPurchaseTransaction:(SKPaymentTransaction *)transaction queue:(SKPaymentQueue*)queue { RMStoreLog(@"transaction purchased with product %@", transaction.payment.productIdentifier); + if (self.receiptVerificator != nil) { [self.receiptVerifier verifyTransaction:transaction success:^{ @@ -559,6 +560,7 @@ - (void)didFailTransaction:(SKPaymentTransaction *)transaction queue:(SKPaymentQ NSDictionary *extras = error ? @{RMStoreNotificationStoreError : error} : nil; [self postNotificationWithName:RMSKPaymentTransactionFailed transaction:transaction userInfoExtras:extras]; + if (transaction.transactionState == SKPaymentTransactionStateRestored) { [self notifyRestoreTransactionFinishedIfApplicableAfterTransaction:transaction]; @@ -631,7 +633,7 @@ - (void)didDownloadSelfHostedContentForTransaction:(SKPaymentTransaction *)trans - (void)finishTransaction:(SKPaymentTransaction *)transaction queue:(SKPaymentQueue*)queue { SKPayment *payment = transaction.payment; - NSString* productIdentifier = payment.productIdentifier; + NSString* productIdentifier = payment.productIdentifier; [queue finishTransaction:transaction]; [self.transactionPersistor persistTransaction:transaction]; @@ -758,6 +760,7 @@ - (void)productsRequest:(SKProductsRequest *)request didReceiveResponse:(SKProdu [invalidProductIdentifiers enumerateObjectsUsingBlock:^(NSString *invalid, NSUInteger idx, BOOL *stop) { RMStoreLog(@"invalid product with id %@", invalid); }]; + if (self.successBlock) { self.successBlock(products, invalidProductIdentifiers); From fc805bd71f1173a7beea420309cf5dffcce074f4 Mon Sep 17 00:00:00 2001 From: Sean Blahovici Date: Mon, 18 Jan 2016 16:45:18 -0500 Subject: [PATCH 19/19] Merged Master into fork. Hopefully this will allow the Pull Request to be merged. --- RMStore/RMStore.m | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/RMStore/RMStore.m b/RMStore/RMStore.m index ee532e7f..478ee0c7 100755 --- a/RMStore/RMStore.m +++ b/RMStore/RMStore.m @@ -526,7 +526,7 @@ - (void)didPurchaseTransaction:(SKPaymentTransaction *)transaction queue:(SKPaym { RMStoreLog(@"transaction purchased with product %@", transaction.payment.productIdentifier); - if (self.receiptVerificator != nil) + if (self.receiptVerifier != nil) { [self.receiptVerifier verifyTransaction:transaction success:^{ [self didVerifyTransaction:transaction queue:queue]; @@ -569,12 +569,13 @@ - (void)didFailTransaction:(SKPaymentTransaction *)transaction queue:(SKPaymentQ - (void)didRestoreTransaction:(SKPaymentTransaction *)transaction queue:(SKPaymentQueue*)queue { - RMStoreLog(@"transaction restored with product %@", transaction.originalTransaction.payment.productIdentifier); + NSString *productIdentifier = transaction.originalTransaction.payment.productIdentifier; + RMStoreLog(@"transaction restored with product %@", productIdentifier); if(productIdentifier) { [_pendingRestoredTransactionIds addObject:productIdentifier]; } - if (self.receiptVerificator != nil) + if (self.receiptVerifier != nil) { [self.receiptVerifier verifyTransaction:transaction success:^{ [self didVerifyTransaction:transaction queue:queue];