Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Orphan purchases #182

Open
wants to merge 9 commits into
base: master
Choose a base branch
from
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
2 changes: 2 additions & 0 deletions RMStore/RMStore.h
Original file line number Diff line number Diff line change
Expand Up @@ -261,6 +261,8 @@ extern NSInteger const RMStoreErrorCodeUnableToCompleteVerification;
- (void)storeRefreshReceiptFinished:(NSNotification*)notification __attribute__((availability(ios,introduced=7.0)));
- (void)storeRestoreTransactionsFailed:(NSNotification*)notification;
- (void)storeRestoreTransactionsFinished:(NSNotification*)notification;
- (void)storeTransactionsOrphanFinished:(NSNotification*)notification;
- (void)storeTransactionsOrphanFailed:(NSNotification*)notification;

@end

Expand Down
26 changes: 23 additions & 3 deletions RMStore/RMStore.m
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,8 @@
NSString* const RMSKRefreshReceiptFinished = @"RMSKRefreshReceiptFinished";
NSString* const RMSKRestoreTransactionsFailed = @"RMSKRestoreTransactionsFailed";
NSString* const RMSKRestoreTransactionsFinished = @"RMSKRestoreTransactionsFinished";
NSString* const RMSKPaymentTransactionOrphanFinished = @"RMSKPaymentTransactionOrphanFinished";
NSString* const RMSKPaymentTransactionOrphanFailed = @"RMSKPaymentTransactionOrphanFailed";

NSString* const RMStoreNotificationInvalidProductIdentifiers = @"invalidProductIdentifiers";
NSString* const RMStoreNotificationDownloadProgress = @"downloadProgress";
Expand Down Expand Up @@ -129,7 +131,8 @@ @interface RMStore() <SKRequestDelegate>

@end

@implementation RMStore {
@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;
Expand Down Expand Up @@ -293,7 +296,7 @@ - (void)refreshReceiptOnSuccess:(RMStoreSuccessBlock)successBlock
{
_refreshReceiptFailureBlock = failureBlock;
_refreshReceiptSuccessBlock = successBlock;
_refreshReceiptRequest = [[SKReceiptRefreshRequest alloc] initWithReceiptProperties:@{}];
_refreshReceiptRequest = [[SKReceiptRefreshRequest alloc] initWithReceiptProperties:@{}];
_refreshReceiptRequest.delegate = self;
[_refreshReceiptRequest start];
}
Expand Down Expand Up @@ -332,6 +335,9 @@ - (void)addStoreObserver:(id<RMStoreObserver>)observer
[self addStoreObserver:observer selector:@selector(storeRefreshReceiptFinished:) notificationName:RMSKRefreshReceiptFinished];
[self addStoreObserver:observer selector:@selector(storeRestoreTransactionsFailed:) notificationName:RMSKRestoreTransactionsFailed];
[self addStoreObserver:observer selector:@selector(storeRestoreTransactionsFinished:) notificationName:RMSKRestoreTransactionsFinished];
[self addStoreObserver:observer selector:@selector(storeTransactionsOrphanFinished:) notificationName:RMSKPaymentTransactionOrphanFinished];
[self addStoreObserver:observer selector:@selector(storeTransactionsOrphanFailed:) notificationName:RMSKPaymentTransactionOrphanFailed];

}

- (void)removeStoreObserver:(id<RMStoreObserver>)observer
Expand All @@ -350,6 +356,8 @@ - (void)removeStoreObserver:(id<RMStoreObserver>)observer
[[NSNotificationCenter defaultCenter] removeObserver:observer name:RMSKRefreshReceiptFinished object:self];
[[NSNotificationCenter defaultCenter] removeObserver:observer name:RMSKRestoreTransactionsFailed object:self];
[[NSNotificationCenter defaultCenter] removeObserver:observer name:RMSKRestoreTransactionsFinished object:self];
[[NSNotificationCenter defaultCenter] removeObserver:observer name:RMSKPaymentTransactionOrphanFinished object:self];
[[NSNotificationCenter defaultCenter] removeObserver:observer name:RMSKPaymentTransactionOrphanFailed object:self];
}

// Private
Expand Down Expand Up @@ -557,6 +565,10 @@ - (void)didFailTransaction:(SKPaymentTransaction *)transaction queue:(SKPaymentQ
{
parameters.failureBlock(transaction, error);
}
else
{
[self postNotificationWithName:RMSKPaymentTransactionOrphanFailed transaction:transaction userInfoExtras:nil];
}

NSDictionary *extras = error ? @{RMStoreNotificationStoreError : error} : nil;
[self postNotificationWithName:RMSKPaymentTransactionFailed transaction:transaction userInfoExtras:extras];
Expand Down Expand Up @@ -640,6 +652,14 @@ - (void)finishTransaction:(SKPaymentTransaction *)transaction queue:(SKPaymentQu
{
wrapper.successBlock(transaction);
}
else
{
/*
Nobody has requested this transaction, which would indicate that the app has died after purchase (or at least sometime after beeing added) but before finishTransaction was called.
This regularly happens on older devices if credit cards are denied or old, then the user needs to update their card info and switch away from the app. When coming back the app might have been killed and the success-block is gone (since it was living in RAM).
*/
[self postNotificationWithName:RMSKPaymentTransactionOrphanFinished transaction:transaction userInfoExtras:nil];
}

[self postNotificationWithName:RMSKPaymentTransactionFinished transaction:transaction userInfoExtras:nil];

Expand Down Expand Up @@ -751,7 +771,7 @@ - (void)productsRequest:(SKProductsRequest *)request didReceiveResponse:(SKProdu

for (SKProduct *product in products)
{
RMStoreLog(@"received product with id %@", product.productIdentifier);
//RMStoreLog(@"received product with id %@", product.productIdentifier);
[self.store addProduct:product];
}

Expand Down