From d3239699edf7668f60822154a54d60eb856567ee Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Pfannemu=CC=88ller?= Date: Sun, 16 Oct 2016 18:44:01 +0200 Subject: [PATCH 1/5] Add canMakePayment method --- IAPHelper/IAPHelper.h | 2 ++ IAPHelper/IAPHelper.m | 6 +++++- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/IAPHelper/IAPHelper.h b/IAPHelper/IAPHelper.h index 9840a93..2e88626 100755 --- a/IAPHelper/IAPHelper.h +++ b/IAPHelper/IAPHelper.h @@ -26,6 +26,8 @@ typedef void (^resoreProductsCompleteResponseBlock) (SKPaymentQueue* payment,NSE @property (nonatomic,strong) SKProductsRequest *request; @property (nonatomic) BOOL production; +- (BOOL)canMakePayment; + - (void)requestProductsWithCompletion:(IAPProductsResponseBlock)completion; - (id)initWithProductIdentifiers:(NSSet *)productIdentifiers; diff --git a/IAPHelper/IAPHelper.m b/IAPHelper/IAPHelper.m index d668d4f..5203d5c 100755 --- a/IAPHelper/IAPHelper.m +++ b/IAPHelper/IAPHelper.m @@ -66,7 +66,11 @@ - (void)dealloc } } --(BOOL)isPurchasedProductsIdentifier:(NSString*)productID +- (BOOL)canMakePayment{ + return [SKPaymentQueue canMakePayments]; +} + +- (BOOL)isPurchasedProductsIdentifier:(NSString*)productID { BOOL productPurchased = NO; From fb0695e2ecd632165305e35907cb47c5de0d9316 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Pfannemu=CC=88ller?= Date: Mon, 17 Oct 2016 17:24:02 +0200 Subject: [PATCH 2/5] Delete .DS_Store --- .DS_Store | Bin 6148 -> 0 bytes 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 .DS_Store diff --git a/.DS_Store b/.DS_Store deleted file mode 100644 index 2a623d37275b5ea10743b3b05316874ceb08543e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6148 zcmeHK-D=w~6h3Ox)Q)dlwn3pczU&~BEM41MCr!oz>j?E|8SBXG+AIRs3bxZQLcn*0 zJ;wguV{Ff`J<6`Kqo0;#$u4#?M$mzy??^hI6n#XJ1puTu4DSKh0AQeVELE^rV7#CE zoUN#qG9nRUL=eLOB1k*&T()k|3TOrXHwF0KHK79y=)yzXxi|Zlod+=su$LbV574*K z%hM^A3mL&E8z{z)U=Y(RuhqVjmDSQ(dEGE8mSt5ed!zE)>$8!U`}r_y`sp)KqhS=N zxa;Tr>-Y&{@lEUpCo~%M?AwPd$$gqc=`Yl?Q<{Wq)MUdX%+5SH-YE_9e$T$sO`}Vs zcKswep&1QmO!HTUX_|)Fvp2`%`rdBUsn_=>RcCx~P^&ukclRd~`^qr3?(Q{?o(?9j z-@JYI{=>&lpTCI31Hr>i*e!+E@D+mvVqSV_60_tb_HyRNyxg#Z$0maiGI4yKcj6iO z`Mh=XH6{N#Ji;*!p$(70gZ6ATImXQGsW6QAFFMA|2DIP^aR)9S{EhLAGth||pR=?r zy#nfQY*tS z6;V=&dSVbs$96~Mxe5!3k`6>YK8Tu`s22(mv*Y-VNC)Cd)TLHHD=@3Ts;t`l{%`;J z{Xa|6HLZYFV5t-!rIy!f;*!+eI=47}*E;Ag(7ExvLZYBxp{`>Q@T+(eT^RN`JV106 U780=qO@9ao8FZl)_@@f|1emsuumAu6 From 1b197df6c19d36319d14976f64830c551d2885af Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Pfannemu=CC=88ller?= Date: Mon, 17 Oct 2016 17:24:30 +0200 Subject: [PATCH 3/5] Update gitignore --- .gitignore | 42 ++++++++++++++++++++++++++++-------------- 1 file changed, 28 insertions(+), 14 deletions(-) diff --git a/.gitignore b/.gitignore index 70965dc..efec5dd 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,5 @@ -# Created by https://www.gitignore.io/api/xcode,objective-c +# Created by https://www.gitignore.io/api/xcode,objective-c,osx ### Xcode ### # Xcode @@ -33,22 +33,10 @@ xcuserdata/ # gitignore contributors: remember to update Global/Xcode.gitignore, Objective-C.gitignore & Swift.gitignore ## Build generated -build/ -DerivedData/ ## Various settings -*.pbxuser -!default.pbxuser -*.mode1v3 -!default.mode1v3 -*.mode2v3 -!default.mode2v3 -*.perspectivev3 -!default.perspectivev3 -xcuserdata/ ## Other -*.moved-aside *.xcuserstate ## Obj-C/Swift specific @@ -80,7 +68,9 @@ Carthage/Build # https://github.com/fastlane/fastlane/blob/master/fastlane/docs/Gitignore.md fastlane/report.xml +fastlane/Preview.html fastlane/screenshots +fastlane/test_output # Code Injection # @@ -90,4 +80,28 @@ fastlane/screenshots iOSInjectionProject/ ### Objective-C Patch ### -*.xcscmblueprint \ No newline at end of file + + +### OSX ### +*.DS_Store +.AppleDouble +.LSOverride + +# Icon must end with two \r +Icon +# Thumbnails +._* +# Files that might appear in the root of a volume +.DocumentRevisions-V100 +.fseventsd +.Spotlight-V100 +.TemporaryItems +.Trashes +.VolumeIcon.icns +.com.apple.timemachine.donotpresent +# Directories potentially created on remote AFP share +.AppleDB +.AppleDesktop +Network Trash Folder +Temporary Items +.apdisk From f5be05fd5143c0bf5d301d82143f6cf0e3ddd726 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Pfannemu=CC=88ller?= Date: Mon, 17 Oct 2016 17:37:31 +0200 Subject: [PATCH 4/5] Add IAPHelperDelegate for transaction recording --- IAPHelper/IAPHelper.h | 8 ++++++++ IAPHelper/IAPHelper.m | 32 ++++++++++++++++++++------------ 2 files changed, 28 insertions(+), 12 deletions(-) diff --git a/IAPHelper/IAPHelper.h b/IAPHelper/IAPHelper.h index 2e88626..52c22b5 100755 --- a/IAPHelper/IAPHelper.h +++ b/IAPHelper/IAPHelper.h @@ -9,6 +9,7 @@ #import #import "StoreKit/StoreKit.h" +@protocol IAPHelperDelegate; typedef void (^IAPProductsResponseBlock)(SKProductsRequest* request , SKProductsResponse* response); @@ -25,6 +26,7 @@ typedef void (^resoreProductsCompleteResponseBlock) (SKPaymentQueue* payment,NSE @property (nonatomic,strong) NSMutableSet *purchasedProducts; @property (nonatomic,strong) SKProductsRequest *request; @property (nonatomic) BOOL production; +@property (nonatomic, weak) id delegate; - (BOOL)canMakePayment; @@ -48,3 +50,9 @@ typedef void (^resoreProductsCompleteResponseBlock) (SKPaymentQueue* payment,NSE - (void)clearSavedPurchasedProducts; - (void)clearSavedPurchasedProductByID:(NSString*)productIdentifier; @end + +@protocol IAPHelperDelegate + +- (bool)recordTransaction:(SKPaymentTransaction*)transaction; + +@end diff --git a/IAPHelper/IAPHelper.m b/IAPHelper/IAPHelper.m index 5203d5c..b89fa31 100755 --- a/IAPHelper/IAPHelper.m +++ b/IAPHelper/IAPHelper.m @@ -105,8 +105,16 @@ - (void)productsRequest:(SKProductsRequest *)request didReceiveResponse:(SKProdu } -- (void)recordTransaction:(SKPaymentTransaction *)transaction { - // TODO: Record the transaction on the server side... +- (bool)recordTransaction:(SKPaymentTransaction *)transaction { + + bool success = false; + if(_delegate != nil){ + success = [_delegate recordTransaction:transaction]; + }else{ + success = true; + } + + return success; } @@ -152,17 +160,17 @@ - (void)clearSavedPurchasedProductByID:(NSString*)productIdentifier { - (void)completeTransaction:(SKPaymentTransaction *)transaction { - - - [self recordTransaction: transaction]; - - if ([SKPaymentQueue defaultQueue]) { - [[SKPaymentQueue defaultQueue] finishTransaction: transaction]; - } + bool success = [self recordTransaction: transaction]; - if(_buyProductCompleteBlock) - { - _buyProductCompleteBlock(transaction); + if(success){ + if ([SKPaymentQueue defaultQueue]) { + [[SKPaymentQueue defaultQueue] finishTransaction: transaction]; + } + + if(_buyProductCompleteBlock) + { + _buyProductCompleteBlock(transaction); + } } } From cddd0005840f4601fa158fe2957983291c3ccdd3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Pfannemu=CC=88ller?= Date: Mon, 17 Oct 2016 18:10:29 +0200 Subject: [PATCH 5/5] Use completion-based delegate method instead --- IAPHelper/IAPHelper.h | 2 +- IAPHelper/IAPHelper.m | 121 ++++++++++++++++++++++-------------------- 2 files changed, 64 insertions(+), 59 deletions(-) diff --git a/IAPHelper/IAPHelper.h b/IAPHelper/IAPHelper.h index 52c22b5..07aeb39 100755 --- a/IAPHelper/IAPHelper.h +++ b/IAPHelper/IAPHelper.h @@ -53,6 +53,6 @@ typedef void (^resoreProductsCompleteResponseBlock) (SKPaymentQueue* payment,NSE @protocol IAPHelperDelegate -- (bool)recordTransaction:(SKPaymentTransaction*)transaction; +- (void)recordTransaction:(SKPaymentTransaction*)transaction completion:(nonnull void(^)(bool result))completion; @end diff --git a/IAPHelper/IAPHelper.m b/IAPHelper/IAPHelper.m index b89fa31..d150d99 100755 --- a/IAPHelper/IAPHelper.m +++ b/IAPHelper/IAPHelper.m @@ -22,6 +22,8 @@ @interface IAPHelper() @property (nonatomic,copy) checkReceiptCompleteResponseBlock checkReceiptCompleteBlock; @property (nonatomic,strong) NSMutableData* receiptRequestData; + +- (void)recordTransaction:(SKPaymentTransaction *)transaction completion:(nonnull void(^)(bool result))completion; @end @implementation IAPHelper @@ -51,7 +53,7 @@ - (id)initWithProductIdentifiers:(NSSet *)productIdentifiers { } if ([SKPaymentQueue defaultQueue]) { [[SKPaymentQueue defaultQueue] addTransactionObserver:self]; - + self.purchasedProducts = purchasedProducts; } @@ -72,7 +74,7 @@ - (BOOL)canMakePayment{ - (BOOL)isPurchasedProductsIdentifier:(NSString*)productID { - + BOOL productPurchased = NO; NSString* password = [SFHFKeychainUtils getPasswordForUsername:productID andServiceName:@"IAPHelper" error:nil]; @@ -80,7 +82,7 @@ - (BOOL)isPurchasedProductsIdentifier:(NSString*)productID { productPurchased = YES; } - + return productPurchased; } @@ -98,26 +100,26 @@ - (void)productsRequest:(SKProductsRequest *)request didReceiveResponse:(SKProdu self.products = response.products; self.request = nil; - + if(_requestProductsBlock) { _requestProductsBlock (request,response); } - + } -- (bool)recordTransaction:(SKPaymentTransaction *)transaction { +- (void)recordTransaction:(SKPaymentTransaction *)transaction completion:(nonnull void(^)(bool result))completion{ bool success = false; if(_delegate != nil){ - success = [_delegate recordTransaction:transaction]; + [_delegate recordTransaction:transaction completion:^(bool result) { + completion(result); + }]; }else{ - success = true; + completion(true); } - - return success; + } - - (void)provideContentWithTransaction:(SKPaymentTransaction *)transaction { NSString* productIdentifier = @""; @@ -140,7 +142,7 @@ - (void)provideContent:(NSString *)productIdentifier { [_purchasedProducts addObject:productIdentifier]; - + } - (void)clearSavedPurchasedProducts { @@ -160,36 +162,38 @@ - (void)clearSavedPurchasedProductByID:(NSString*)productIdentifier { - (void)completeTransaction:(SKPaymentTransaction *)transaction { - bool success = [self recordTransaction: transaction]; - - if(success){ - if ([SKPaymentQueue defaultQueue]) { - [[SKPaymentQueue defaultQueue] finishTransaction: transaction]; - } - - if(_buyProductCompleteBlock) - { - _buyProductCompleteBlock(transaction); + [self recordTransaction:transaction completion:^(bool success) { + if(success){ + if ([SKPaymentQueue defaultQueue]) { + [[SKPaymentQueue defaultQueue] finishTransaction: transaction]; + } + + if(_buyProductCompleteBlock) + { + _buyProductCompleteBlock(transaction); + } } - } + }]; } - (void)restoreTransaction:(SKPaymentTransaction *)transaction { - - [self recordTransaction: transaction]; - [self provideContentWithTransaction:transaction]; - - if ([SKPaymentQueue defaultQueue]) { - [[SKPaymentQueue defaultQueue] finishTransaction: transaction]; + [self recordTransaction:transaction completion:^(bool result) { + if(result){ + [self provideContentWithTransaction:transaction]; - - if(_buyProductCompleteBlock!=nil) - { - _buyProductCompleteBlock(transaction); + if ([SKPaymentQueue defaultQueue]) { + [[SKPaymentQueue defaultQueue] finishTransaction: transaction]; + + + if(_buyProductCompleteBlock!=nil) + { + _buyProductCompleteBlock(transaction); + } + } } - } + }]; } @@ -199,7 +203,7 @@ - (void)failedTransaction:(SKPaymentTransaction *)transaction { { NSLog(@"Transaction error: %@ %ld", transaction.error.localizedDescription,(long)transaction.error.code); } - + if ([SKPaymentQueue defaultQueue]) { [[SKPaymentQueue defaultQueue] finishTransaction: transaction]; if(_buyProductCompleteBlock) { @@ -211,8 +215,6 @@ - (void)failedTransaction:(SKPaymentTransaction *)transaction { - (void)paymentQueue:(SKPaymentQueue *)queue updatedTransactions:(NSArray *)transactions { - - for (SKPaymentTransaction *transaction in transactions) { switch (transaction.transactionState) @@ -237,15 +239,15 @@ - (void)buyProduct:(SKProduct *)productIdentifier onCompletion:(IAPbuyProductCom self.restoreCompletedBlock = nil; SKPayment *payment = [SKPayment paymentWithProduct:productIdentifier]; - + if ([SKPaymentQueue defaultQueue]) { [[SKPaymentQueue defaultQueue] addPayment:payment]; } - + } -(void)restoreProductsWithCompletion:(resoreProductsCompleteResponseBlock)completion { - + //clear it self.buyProductCompleteBlock = nil; @@ -276,8 +278,11 @@ - (void)paymentQueueRestoreCompletedTransactionsFinished:(SKPaymentQueue *)queue { case SKPaymentTransactionStateRestored: { - [self recordTransaction: transaction]; - [self provideContentWithTransaction:transaction]; + [self recordTransaction:transaction completion:^(bool result) { + if(result){ + [self provideContentWithTransaction:transaction]; + } + }]; } default: @@ -288,7 +293,7 @@ - (void)paymentQueueRestoreCompletedTransactionsFinished:(SKPaymentQueue *)queue if(_restoreCompletedBlock) { _restoreCompletedBlock(queue,nil); } - + } - (void)checkReceipt:(NSData*)receiptData onCompletion:(checkReceiptCompleteResponseBlock)completion @@ -299,13 +304,13 @@ - (void)checkReceipt:(NSData*)receiptData AndSharedSecret:(NSString*)secretKey o { self.checkReceiptCompleteBlock = completion; - + NSError *jsonError = nil; NSString *receiptBase64 = [NSString base64StringFromData:receiptData length:[receiptData length]]; - - + + NSData *jsonData = nil; - + if(secretKey !=nil && ![secretKey isEqualToString:@""]) { jsonData = [NSJSONSerialization dataWithJSONObject:[NSDictionary dictionaryWithObjectsAndKeys:receiptBase64,@"receipt-data", @@ -317,16 +322,16 @@ - (void)checkReceipt:(NSData*)receiptData AndSharedSecret:(NSString*)secretKey o } else { jsonData = [NSJSONSerialization dataWithJSONObject:[NSDictionary dictionaryWithObjectsAndKeys: - receiptBase64,@"receipt-data", - nil] - options:NSJSONWritingPrettyPrinted - error:&jsonError - ]; + receiptBase64,@"receipt-data", + nil] + options:NSJSONWritingPrettyPrinted + error:&jsonError + ]; } - - -// NSString* jsonStr = [[NSString alloc] initWithData:jsonData encoding:NSUTF8StringEncoding]; - + + + // NSString* jsonStr = [[NSString alloc] initWithData:jsonData encoding:NSUTF8StringEncoding]; + NSURL *requestURL = nil; if(_production) { @@ -335,11 +340,11 @@ - (void)checkReceipt:(NSData*)receiptData AndSharedSecret:(NSString*)secretKey o else { requestURL = [NSURL URLWithString:@"https://sandbox.itunes.apple.com/verifyReceipt"]; } - + NSMutableURLRequest *req = [[NSMutableURLRequest alloc] initWithURL:requestURL]; [req setHTTPMethod:@"POST"]; [req setHTTPBody:jsonData]; - + NSURLConnection *conn = [[NSURLConnection alloc] initWithRequest:req delegate:self]; if(conn) { self.receiptRequestData = [[NSMutableData alloc] init];