diff --git a/InAppUtils/InAppUtils.m b/InAppUtils/InAppUtils.m index d726603..b7be638 100644 --- a/InAppUtils/InAppUtils.m +++ b/InAppUtils/InAppUtils.m @@ -58,7 +58,6 @@ - (void)paymentQueue:(SKPaymentQueue *)queue } else { RCTLogWarn(@"No callback registered for transaction with state purchased."); } - [[SKPaymentQueue defaultQueue] finishTransaction:transaction]; break; } case SKPaymentTransactionStateRestored: @@ -76,6 +75,28 @@ - (void)paymentQueue:(SKPaymentQueue *)queue } } +RCT_EXPORT_METHOD(getPendingPurchases:(RCTResponseSenderBlock)callback) +{ + NSMutableArray *transactionsArrayForJS = [NSMutableArray array]; + for (SKPaymentTransaction *transaction in [SKPaymentQueue defaultQueue].transactions) { + NSMutableDictionary *purchase = [NSMutableDictionary dictionaryWithDictionary: @{ + @"transactionDate": @(transaction.transactionDate.timeIntervalSince1970 * 1000), + @"transactionIdentifier": transaction.transactionIdentifier, + @"productIdentifier": transaction.payment.productIdentifier, + @"transactionReceipt": [[transaction transactionReceipt] base64EncodedStringWithOptions:0], + @"transactionState": StringForTransactionState(transaction.transactionState) + }]; + SKPaymentTransaction *originalTransaction = transaction.originalTransaction; + if (originalTransaction) { + purchase[@"originalTransactionDate"] = @(originalTransaction.transactionDate.timeIntervalSince1970 * 1000); + purchase[@"originalTransactionIdentifier"] = originalTransaction.transactionIdentifier; + } + + [transactionsArrayForJS addObject:purchase]; + } + callback(@[[NSNull null], transactionsArrayForJS]); +} + RCT_EXPORT_METHOD(purchaseProductForUser:(NSString *)productIdentifier username:(NSString *)username callback:(RCTResponseSenderBlock)callback) @@ -114,6 +135,24 @@ - (void) doPurchaseProduct:(NSString *)productIdentifier } } +RCT_EXPORT_METHOD(finishPurchase:(NSString *)transactionIdentifier + callback:(RCTResponseSenderBlock)callback) +{ + for (SKPaymentTransaction *transaction in [SKPaymentQueue defaultQueue].transactions) { + if ([transaction.transactionIdentifier isEqualToString:transactionIdentifier]) { + if (transaction.transactionState == SKPaymentTransactionStatePurchased) { + [[SKPaymentQueue defaultQueue] finishTransaction:transaction]; + callback(@[[NSNull null]]); + } else { + callback(@[@"invalid_purchase"]); + } + return; + } + } + callback(@[@"invalid_purchase"]); +} + + - (void)paymentQueue:(SKPaymentQueue *)queue restoreCompletedTransactionsFailedWithError:(NSError *)error { @@ -270,5 +309,18 @@ - (void)dealloc { return [NSString stringWithFormat:@"%p", instance]; } + +static NSString *StringForTransactionState(SKPaymentTransactionState state) +{ + switch(state) { + case SKPaymentTransactionStatePurchasing: return @"purchasing"; + case SKPaymentTransactionStatePurchased: return @"purchased"; + case SKPaymentTransactionStateFailed: return @"failed"; + case SKPaymentTransactionStateRestored: return @"restored"; + case SKPaymentTransactionStateDeferred: return @"deferred"; + } + + [NSException raise:NSGenericException format:@"Unexpected SKPaymentTransactionState."]; +} @end diff --git a/Readme.md b/Readme.md index 359cba3..da8c876 100644 --- a/Readme.md +++ b/Readme.md @@ -69,7 +69,15 @@ InAppUtils.purchaseProduct(productIdentifier, (error, response) => { // NOTE for v3.0: User can cancel the payment which will be available as error object here. if(response && response.productIdentifier) { Alert.alert('Purchase Successful', 'Your Transaction ID is ' + response.transactionIdentifier); + //unlock store here. + + // After providing the item, we call finishPurchase to finalize the transaction. + InAppUtils.finishPurchase(response.transactionIdentifier, (error) => { + if (!error) { + // Transaction Complete + } + }); } }); ```