getPurchaseHistory trigger lots of restored, clearTransactionIOS takes long time to clear it, subscription request no response during this
See original GitHub issueVersion of react-native-iap
5.2.14 & 6.02
Version of react-native
0.63.4
Platforms you faced the error (IOS or Android or both?)
IOS
Expected behavior
no Restored action & purchase show fast
Actual behavior
getPurchaseHistory() trigger Restored and the subscription button work only after cleaning all the restored,
Tested environment (Emulator? Real Device?)
Real Device
Steps to reproduce the behavior
useEffect(() => {
IAP.initConnection().catch(() => {
console.log("error connect to store")
})
.then(async () => {
if (Platform.OS === 'ios') {
await IAP.clearTransactionIOS();
}
console.log("connected to store...")
await IAP.getSubscriptions(items).catch((e) => {
console.log(e);
}).then((res) => {
setProducts(res);
})
})
// getPurchaseHistory block
.then(async () => {
await IAP.getPurchaseHistory().catch(() => {
setChecking(false);
setPurchased(false);
}).then(async (res: any) => {
if (res != null) {
const receiptInfo = res[res.length - 1];
if (receiptInfo != null) {
const receipt = receiptInfo.transactionReceipt;
console.log(res.length); // it equal to the number of restored on xcode
await IAP.clearTransactionIOS();
if (receipt) {
await validate(receipt);
}
}
}
});
})
// declare listener block
.then(async () => {
setChecking(false); // without checking history
console.log("declare purchaseUpdatedListener");
purchaseUpdatedListener = IAP.purchaseUpdatedListener(async (purchase: InAppPurchase | SubscriptionPurchase) => {
try {
console.log("update listener")
const receipt = purchase.transactionReceipt;
if (receipt) {
console.log(receipt);
if (validateFlag) { // flag prevent listener run suddenly
await validate(receipt);
} else {
console.log("block validate")
}
await IAP.finishTransaction(purchase);
await IAP.clearTransactionIOS();
}
} catch (error) {
}
})
})
return () => {
if (purchaseUpdatedListener) {
purchaseUpdatedListener.remove();
purchaseUpdatedListener = null;
}
if (purchaseErrorListener) {
purchaseErrorListener.remove();
purchaseErrorListener = null;
}
}
}, [])
I found that when i use getPurchaseHistory(), the subscription button is broken When i look at the debug log of Xcode, I see lots of Restored action occurs after getPurchaseHistory
2021-04-04 17:10:03.761129+0800 MyApp[7767:3203077] Restored
2021-04-04 17:10:03.761269+0800 MyApp[7767:3203077] Restored
2021-04-04 17:10:03.761373+0800 MyApp[7767:3203077] Restored
...
2021-04-04 17:10:03.781085+0800 MyApp[7767:3203077] Restored
2021-04-04 17:10:03.781211+0800 MyApp[7767:3203077] Restored
2021-04-04 17:10:03.781295+0800 MyApp[7767:3203077] Restored
total 151 Restored within 1 second, this number is the length of respond of getPurchaseHistory() so I add await IAP.clearTransactionIOS() after using getPurchaseHistory(), but it takes long time to kill all the Restored, 151 is the length of respond of getPurchaseHistory() during this process, nothing happen in clicking subscription button
2021-04-04 17:10:03.918169+0800 MyApp[7767:3203371] [javascript] 151
*** clear remaining Transactions. Call this before make a new transaction
2021-04-04 17:10:05.282095+0800 MyApp[7767:3203077] removedTransactions
2021-04-04 17:10:06.709204+0800 MyApp[7767:3203077] removedTransactions
2021-04-04 17:10:08.161100+0800 MyApp[7767:3203077] removedTransactions
...
2021-04-04 17:16:13.535573+0800 MyApp[7767:3203077] removedTransactions
2021-04-04 17:16:14.756614+0800 MyApp[7767:3203077] removedTransactions
2021-04-04 17:16:15.816927+0800 MyApp[7767:3203077] removedTransactions
total 151 removedTransactions in 6 minutes, even i close the app and rebuild it, next time i open the app, it’s still there needed to be killed, so I also add await IAP.clearTransactionIOS() at the beginning just after the initConnection. sometimes after killing all the Restored, the purchase dialog show… i believe it’s the last time i press the purchase button but nothing happen, now it show after killing all the Restored
if I change the order of getPurchaseHistory block and declare listener block, the restored will trigger the listener, listener will runs 151 times, so you may see I’ve added the flag there to prevent my backend from explosion, but now this order is okay . just need to wait, one time i close the app before it kill all the restore, 4 hours later the purchase dialog show
and I am not sure if this bug makes purchase so slow, sometimes after the killing, purchase button work perfectly, very fast. but sometimes i need to wait, or click couple times
without getPurchaseHistory block, everything works perfectly, the subscription reaction is fast every time, but i need to get the receipt to know the expiry and change the UI logic
Issue Analytics
- State:
- Created 2 years ago
- Comments:7
After decoding the receipt at backend, the object shows all the item you’ve bought on object[‘receipt’][‘in_app’] source: responseBody.Receipt.In_app | Apple Developer Documentation
if you want to know the latest subscriptions, you can look at Object[‘data’][‘latest_reciept_into’] then you can do the logic if the item(s) not expire
I am facing the same issue, it takes long time on real IOS device, I have 44 purchases takes a lot of time to trigger
I don’t know if this is the same as your case also
After many trails I figured out that when we call
RNIap.getPurchaseHistory()
then call other methods likerequestSubscription()
takes alot of time. I don’t know what is the issue withRNIap.getPurchaseHistory()
but there is a real issue in it.Issue: After digging on it for days I found there is a bug in SDK or IOS 14 when we use
RNIap.getPurchaseHistory()
After calling it the other methods takes very long timeSolution: I changed the method with this workaround
If you want to know more you can find the source of Receipt here Verify Receipt