react-native-iap: [8.0.4][iOS] finishTransaction promise never finishes
Version of react-native-iap
8.0.4
Version of react-native
0.67.2
Platforms you faced the error (IOS or Android or both?)
iOS
Expected behavior
calling finishTransaction marks the transaction as finished
Actual behavior
Any code after the await RNIap.finishTransaction is not executed, and the transaction is reattempted after each relaunch of the app.
Tested environment (Emulator? Real Device?)
Real device
Steps to reproduce the behavior
Purchase a product in sandbox, call finishTransaction, check if some code after the promise is executed.
Here is my listener:
purchaseUpdatedListener = RNIap.purchaseUpdatedListener(
async (purchase: RNIap.InAppPurchase | RNIap.SubscriptionPurchase) => {
const receipt = purchase.transactionReceipt;
try {
if (receipt) {
const decodedReceipt = await decodeAppleReceipt(receipt);
const isValid = await isSubValid(decodedReceipt);
if (isValid) {
const { latest_receipt_info: latestReceipts }: any = decodedReceipt;
const sortedReceiptInfo = latestReceipts.sort(
(
a: { original_purchase_date_ms: number },
b: { original_purchase_date_ms: number },
) => b.original_purchase_date_ms - a.original_purchase_date_ms,
);
let latestReceiptInfo = sortedReceiptInfo[sortedReceiptInfo.length - 1];
console.log(latestReceiptInfo);
const subPrice = await getSubPrice(latestReceiptInfo.product_id);
const subDuration = getSubDuration(latestReceiptInfo.product_id);
latestReceiptInfo = {
...latestReceiptInfo,
subscription_price: subPrice,
};
// Persist the purchase on backend API
const persistedPurchase = await persistSubscriptionIOS(latestReceiptInfo, sessionId);
const persistedPurchaseId: string = persistedPurchase.persistPurchase.id;
latestReceiptInfo = {
...latestReceiptInfo,
persisted_purchase_id: persistedPurchaseId,
source: 'ios',
subscription_duration: subDuration,
};
// Activate the subscription on backend API
const deliveryResult = await activateSubscription(latestReceiptInfo, sessionId);
if (isSuccess(deliveryResult)) {
console.log('deliveryResult is true');
await RNIap.finishTransaction(purchase, false);
console.log('finish transaction done');
onSuccess?.();
}
}
}
} catch (error) {
console.error(error);
}
},
);
The console.log of finish transaction done is never executed, neither my onSuccess callback. However the console.log before finishTransaction is logged.
About this issue
- Original URL
- State: closed
- Created 2 years ago
- Reactions: 7
- Comments: 41
This seems to be fixed for me in 8.0.5
I ended up just rewriting that function entirely
@objc public func finishTransaction( _ transactionIdentifier: String, resolve: @escaping RCTPromiseResolveBlock = { _ in }, reject: @escaping RCTPromiseRejectBlock = { _, _, _ in } ) { let queue = SKPaymentQueue.default() for transaction in queue.transactions { if transaction.transactionIdentifier == transactionIdentifier { if transaction.transactionState == .purchasing { print("transaction is purchasing still") } else { SKPaymentQueue.default().finishTransaction(transaction) resolve(nil) } } } }Following the history of the file, it looks like this was broken trying to fix https://github.com/dooboolab/react-native-iap/issues/1637 , by adding the promise methods in the header but not calling resolve/reject. I have fixed both methods (
finishTransactionandclearTransaction) here: https://github.com/dooboolab/react-native-iap/pull/1665 Thank you all for helping with the research@mikeportanova have you tried receipt validation with subscriptions? I’m getting 21199 error response.
I still have the same issue in v8.0.5. @aijcoa Can you please provide more info on how you managed to solve it?
This problem definitely persists in 8.0.5. How are you implementing it., @aijcoa?