FinishTransactionIOS is called but purchaseUpdatedListener is still invoke
See original GitHub issueVersion of react-native-iap
5.0.1
Version of react-native
0.63.2
Platforms you faced the error (IOS or Android or both?)
IOS
Expected behavior
After calling FinishTrasacionIOS with transactionId , purchaseUpdatedListener cannot invoke
Actual behavior
Tested environment (Emulator? Real Device?)
Real device
Steps to reproduce the behavior
I have 2 screen : HomeScreen
and PaymentScreen
. PaymentScreen
is the screen I place purchaseUpdatedListener
into it. Here is my code
PaymentScreen.js
purchaseUpdateSubscription = purchaseUpdatedListener(
async (purchase) => {
const receipt = purchase.transactionReceipt;
if (receipt) {
const signature = Platform.OS == 'android' ? purchase.signatureAndroid : '';
const device = Platform.OS == 'android' ? 'ANDROID' : 'IOS';
const id = uniqueID(stateTree.user.pupil_account.id)
console.log(JSON.stringify(purchase));
//call api
Purchase.valiadateGoogleApple(stateTree.user.token_key, receipt, signature, device, id).then(res => {
setServer("");
setLog(JSON.stringify(res.data));
//Alert.alert("Purchase error", JSON.stringify(res.data));
const transInfo = res.data.data;
let paymentInfo = {
orderId: id,
amount: moneyRef.current.toString(),
time: moment().locale('vi-VN').format('LT') + ' ' + moment().locale('vi-VN').format('L'),
}
if (transInfo.purchase_state == 'PURCHASED') {
paymentInfo.isSuccess = true;
} else {
paymentInfo.isSuccess = false;
}
setProcess(false);
if (Platform.OS == "ios") {
finishTransactionIOS(purchase.transactionId).then(() => {
setInfo(paymentInfo);
});
}
else finishTransaction(purchase, true).then(() => {
setInfo(paymentInfo);
});
}).catch(e => {
const purchaseInfo = {
id, device, purchase, signature,
};
AsyncStorage.setItem("IAPurchase", JSON.stringify(purchaseInfo));
setError(true);
setProcess(false);
});
} else {
setError(true);
setProcess(false);
}
}
);
This code is set up for scenario when my server is malfunctioning, cannot validate the purchase to add money for user. In this case I save the purchase into AsyncStorage
. Every time the app launch, it checks whether purchase is saved in local storage. If there is a purchase left, it calls to the server again.
HomeScreen.js
useEffect(() => {
AsyncStorage.getItem("IAPurchase").then(purchase => {
if (purchase) {
console.log("failed purchase : " + purchase);
const info = JSON.parse(purchase);
Purchase.valiadateGoogleApple(stateTree.user.token_key, info.purchase.transactionReceipt, info.signature, info.device, info.id).then(res => {
AsyncStorage.removeItem("IAPurchase");
if (Platform.OS == "ios") {
finishTransactionIOS(info.transactionId);
console.log("finished");
}
else finishTransaction(purchase, true);
})
}
else console.log("Nothing");
})
}, []);
The problem is even finishTransactionIOS
is called from HomeScreen
, when I navigate to PaymentScreen
, purchaseUpdatedListener
is still invoke, therefore user will get double the money . I already log the purchase
from both screen, they have the same transactionId
but have different transactionReceipt
and I still don’t know why. Can you guy help me to solve this problem ?
Issue Analytics
- State:
- Created 3 years ago
- Reactions:1
- Comments:6
same problem
Can you please help us check if this is still an issue on 8.x.x for iOS?
I have found the following as something that is expected from the native SDK: https://stackoverflow.com/a/3633571/570612 If it still happens on 8.x.x and the above doesn’t fix. We’ll reopen. Thank you
Note: I’m not trying to minimize the issue. I see there are multiple posts about it in various forms and I’m trying to make sense of it but with no help and it being reported on such an old version of the library is close to impossible. Thank you for understanding