Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Binary file removed .DS_Store
Binary file not shown.
42 changes: 28 additions & 14 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -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
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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
#
Expand All @@ -90,4 +80,28 @@ fastlane/screenshots
iOSInjectionProject/

### Objective-C Patch ###
*.xcscmblueprint


### 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
10 changes: 10 additions & 0 deletions IAPHelper/IAPHelper.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
#import <Foundation/Foundation.h>
#import "StoreKit/StoreKit.h"

@protocol IAPHelperDelegate;

typedef void (^IAPProductsResponseBlock)(SKProductsRequest* request , SKProductsResponse* response);

Expand All @@ -25,6 +26,9 @@ typedef void (^resoreProductsCompleteResponseBlock) (SKPaymentQueue* payment,NSE
@property (nonatomic,strong) NSMutableSet *purchasedProducts;
@property (nonatomic,strong) SKProductsRequest *request;
@property (nonatomic) BOOL production;
@property (nonatomic, weak) id<IAPHelperDelegate> delegate;

- (BOOL)canMakePayment;

- (void)requestProductsWithCompletion:(IAPProductsResponseBlock)completion;
- (id)initWithProductIdentifiers:(NSSet *)productIdentifiers;
Expand All @@ -46,3 +50,9 @@ typedef void (^resoreProductsCompleteResponseBlock) (SKPaymentQueue* payment,NSE
- (void)clearSavedPurchasedProducts;
- (void)clearSavedPurchasedProductByID:(NSString*)productIdentifier;
@end

@protocol IAPHelperDelegate <NSObject>

- (void)recordTransaction:(SKPaymentTransaction*)transaction completion:(nonnull void(^)(bool result))completion;

@end
131 changes: 74 additions & 57 deletions IAPHelper/IAPHelper.m
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -51,7 +53,7 @@ - (id)initWithProductIdentifiers:(NSSet *)productIdentifiers {
}
if ([SKPaymentQueue defaultQueue]) {
[[SKPaymentQueue defaultQueue] addTransactionObserver:self];

self.purchasedProducts = purchasedProducts;
}

Expand All @@ -66,17 +68,21 @@ - (void)dealloc
}
}

-(BOOL)isPurchasedProductsIdentifier:(NSString*)productID
{
- (BOOL)canMakePayment{
return [SKPaymentQueue canMakePayments];
}

- (BOOL)isPurchasedProductsIdentifier:(NSString*)productID
{

BOOL productPurchased = NO;

NSString* password = [SFHFKeychainUtils getPasswordForUsername:productID andServiceName:@"IAPHelper" error:nil];
if([password isEqualToString:@"YES"])
{
productPurchased = YES;
}

return productPurchased;
}

Expand All @@ -94,18 +100,26 @@ - (void)productsRequest:(SKProductsRequest *)request didReceiveResponse:(SKProdu

self.products = response.products;
self.request = nil;

if(_requestProductsBlock) {
_requestProductsBlock (request,response);
}

}

- (void)recordTransaction:(SKPaymentTransaction *)transaction {
// TODO: Record the transaction on the server side...
- (void)recordTransaction:(SKPaymentTransaction *)transaction completion:(nonnull void(^)(bool result))completion{

bool success = false;
if(_delegate != nil){
[_delegate recordTransaction:transaction completion:^(bool result) {
completion(result);
}];
}else{
completion(true);
}

}


- (void)provideContentWithTransaction:(SKPaymentTransaction *)transaction {

NSString* productIdentifier = @"";
Expand All @@ -128,7 +142,7 @@ - (void)provideContent:(NSString *)productIdentifier {

[_purchasedProducts addObject:productIdentifier];


}

- (void)clearSavedPurchasedProducts {
Expand All @@ -148,36 +162,38 @@ - (void)clearSavedPurchasedProductByID:(NSString*)productIdentifier {

- (void)completeTransaction:(SKPaymentTransaction *)transaction {



[self recordTransaction: transaction];

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);
}
}
}
}
}];

}

Expand All @@ -187,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) {
Expand All @@ -199,8 +215,6 @@ - (void)failedTransaction:(SKPaymentTransaction *)transaction {

- (void)paymentQueue:(SKPaymentQueue *)queue updatedTransactions:(NSArray *)transactions
{


for (SKPaymentTransaction *transaction in transactions)
{
switch (transaction.transactionState)
Expand All @@ -225,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;

Expand Down Expand Up @@ -264,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:
Expand All @@ -276,7 +293,7 @@ - (void)paymentQueueRestoreCompletedTransactionsFinished:(SKPaymentQueue *)queue
if(_restoreCompletedBlock) {
_restoreCompletedBlock(queue,nil);
}

}

- (void)checkReceipt:(NSData*)receiptData onCompletion:(checkReceiptCompleteResponseBlock)completion
Expand All @@ -287,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",
Expand All @@ -305,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)
{
Expand All @@ -323,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];
Expand Down