hyochan / react-native-iap

In App Purchase module for React Native!
https://react-native-iap.hyo.dev
MIT License
2.84k stars 647 forks source link

purchaseUpdatedListener being called multiple, sometimes 20+ times #1104

Closed Pauly24 closed 3 years ago

Pauly24 commented 4 years ago

Version of react-native-iap

"react-native-iap": "^4.5.3"

Version of react-native

"react-native": "0.62.0"

Platforms you faced the error (IOS or Android or both?)

iOS (havent tested on android yet)

Expected behavior

purchaseUpdatedListener should only be as called as many times as the component has mounted

Actual behavior

purchaseUpdatedListener was called 20 times in a couple of seconds, every so often when I open the app it get's called multiple times

Tested environment (Emulator? Real Device?)

Real device, sandbox env

Steps to reproduce the behavior

Follow instructions as per main page

I currently have purchaseUpdatedListener being attached to a listener in componentDidMount(), sometimes when I open up my app it will fire multiple times. This is happening on txns that I have called finishTransaction on. Is anyone seeing something like this?

indapublic commented 4 years ago

Same for me, but I call purchase flow in action

const { productId } = args
purchaseUpdatedListener(async (purchase) => {
    if (!purchase.transactionReceipt) {
        Alert("Error")
    }
    ...
})
purchaseErrorListener(error => {
    ...
})
await requestPurchase(productId, false)
indapublic commented 4 years ago

I have 4 test products and I receive purchaseUpdatedListener 4 times, but the purchase was requested only for one of them

indapublic commented 4 years ago

Tried finish those transactions but still multiple calls

Pauly24 commented 4 years ago

Is the item an auto-renew? I think what is happening is because it's in the sandbox the renew period is only 5 mins for my monthly subscription. So apple will send an event on each renew, so if the app was closed for 10 mins, that's 2 notifications I'll get when the app opens.

Can anyone confirm this is the expected behavior to get notifications on an auto-renew and not just on the purchase?

indapublic commented 4 years ago

My purchase is one time consumable

EightPool commented 4 years ago

Same here. At every auto-renew event, I receive the actual auto-renewable subscription and a few seconds later I receive a big chunk of 135 purchase objects from the purchaseUpdatedListener. I feel this is my entire purchase history. I tried to call both finishTransaction and finishTransactionIOS to consume the transactions but it doesn't change anything.

At the next auto-renew event, that big chunk of transactions is increasing (136, 137,...). The transactions are only my auto-renew subs. None of my consumable/non-consumable products appear on the list.

manuel-grondona commented 4 years ago

Same here, I confirm it calls the listener the same amount of times as the number of purchases in the purchase history.

VictorKolb commented 4 years ago

I have some problem. It is happening only when subscription is enabled.

tecshogo commented 4 years ago

I had a similar experience with iOS 14.

My app sells an auto-renewal subscription. I think this issue has occurred since I purchased the same subscription again.

The following link may be relevant to this issue. https://developer.apple.com/forums/thread/659529

hieutran24 commented 4 years ago

take a look this post the problem is finishTransaction and finishTransactionIOS not work for iOS now, these alway return undefined , so that u can't finish transaction and they stuck in pending transaction. When u open your app, ALL pending transactions will be handled in purchaseUpdatedListener ... so that's why u got 20+ times. :((( someone fix this plsssssss

hyochan commented 4 years ago

take a look this post the problem is finishTransaction and finishTransactionIOS not work for iOS now, these alway return undefined , so that u can't finish transaction and they stuck in pending transaction. When u open your app, ALL pending transactions will be handled in purchaseUpdatedListener ... so that's why u got 20+ times. :((( someone fix this plsssssss

https://github.com/dooboolab/react-native-iap/issues/1160#issuecomment-716525603 I've posted a reply here and actually it is expected that finishTransaction does not resolve promise. We need to verify that it actually finishes transaction by putting log in iOS side and check if it enters an if statement.

edo1493 commented 3 years ago

I am seeing the same as mentioned here: https://github.com/dooboolab/react-native-iap/issues/1172#issuecomment-721676878.

laurpantelimon commented 3 years ago

On android, after a requestPurchase, the purchaseUpdatedListener is called exactly 3 times with the same payload and I therefore make 3 circles of "give rewards in backend -> finish transaction". The first time it is all good but the second and third time they fail because the transaction is finished the first time. On IOS it's all good, only one time the purchaseUpdatedListener is called.The purchase history in empty. Any ideas?

andresesfm commented 3 years ago

Can somebody please validate this is the case in 6.1.0 or newer? The IapExample app is back in working order and I can't replicate this issue

marcpechaitis commented 3 years ago

@andresesfm I am encountering this issue on 6.2.1.

My code (note, I'm testing Android right now so I'm only using consumePurchaseAndroid() because finishTransaction() is a hot mess):

  useEffect(() => {
    const checkCurrentPurchase = async (purchase?: Purchase): Promise<void> => {
      console.log('🔳🔲🔳🔲🔳🔲', 'checkCurrentPurchase');
      if (purchase) {
        const receipt = purchase.transactionReceipt;
        console.log('🔳🔳🔳', receipt);
        if (receipt) {
          try {
            // const ackResult = await finishTransaction(purchase);
            await RNIap.consumePurchaseAndroid(purchase.purchaseToken);
            console.log('🔲🔲🔲 ackResult', ackResult);
          } catch (ackErr) {
            setProcessingPurchase(false);
            console.warn('🔷🔷🔷 ackErr', ackErr);
          }
        }
      }
    };
    checkCurrentPurchase(currentPurchase);
  }, [currentPurchase, finishTransaction]);

result:

[Wed Jun 23 2021 08:55:22.820]  LOG      🔳🔲🔳🔲🔳🔲 checkCurrentPurchase
[Wed Jun 23 2021 08:55:22.875]  LOG      🔳🔳🔳 {"orderId":"GPA.3344-3869-5501-90751","packageName":"com.sugarloafappcompany.bingo","productId":"bingo.consumable.dollar","purchaseTime":1624460117834,"purchaseState":0,"purchaseToken":"adhfehbkneedajpdbpaocmhk.AO-J1OyoT5Od2NpKrOG2AJ81z0VfIWakGQW-10Y3grx9J3XlHWXJS-hlZ5PMyDx8duq8_y-PlAnhWMlC6xtPE_4kXZJXbTtjbN8DZOJ_ppZPdfJKPkiTvZJmDD7NeQWnDOgzCeZqwRU8","acknowledged":false}
[Wed Jun 23 2021 08:55:24.392]  LOG      🔳🔲🔳🔲🔳🔲 checkCurrentPurchase
[Wed Jun 23 2021 08:55:24.454]  LOG      🔳🔳🔳 {"orderId":"GPA.3344-3869-5501-90751","packageName":"com.sugarloafappcompany.bingo","productId":"bingo.consumable.dollar","purchaseTime":1624460117834,"purchaseState":0,"purchaseToken":"adhfehbkneedajpdbpaocmhk.AO-J1OyoT5Od2NpKrOG2AJ81z0VfIWakGQW-10Y3grx9J3XlHWXJS-hlZ5PMyDx8duq8_y-PlAnhWMlC6xtPE_4kXZJXbTtjbN8DZOJ_ppZPdfJKPkiTvZJmDD7NeQWnDOgzCeZqwRU8","acknowledged":false}
[Wed Jun 23 2021 08:55:25.920]  LOG      🔳🔲🔳🔲🔳🔲 checkCurrentPurchase
[Wed Jun 23 2021 08:55:25.979]  LOG      🔳🔳🔳 {"orderId":"GPA.3344-3869-5501-90751","packageName":"com.sugarloafappcompany.bingo","productId":"bingo.consumable.dollar","purchaseTime":1624460117834,"purchaseState":0,"purchaseToken":"adhfehbkneedajpdbpaocmhk.AO-J1OyoT5Od2NpKrOG2AJ81z0VfIWakGQW-10Y3grx9J3XlHWXJS-hlZ5PMyDx8duq8_y-PlAnhWMlC6xtPE_4kXZJXbTtjbN8DZOJ_ppZPdfJKPkiTvZJmDD7NeQWnDOgzCeZqwRU8","acknowledged":false}
[Wed Jun 23 2021 08:55:27.552]  LOG      🔳🔲🔳🔲🔳🔲 checkCurrentPurchase
[Wed Jun 23 2021 08:55:27.609]  LOG      🔳🔳🔳 {"orderId":"GPA.3344-3869-5501-90751","packageName":"com.sugarloafappcompany.bingo","productId":"bingo.consumable.dollar","purchaseTime":1624460117834,"purchaseState":0,"purchaseToken":"adhfehbkneedajpdbpaocmhk.AO-J1OyoT5Od2NpKrOG2AJ81z0VfIWakGQW-10Y3grx9J3XlHWXJS-hlZ5PMyDx8duq8_y-PlAnhWMlC6xtPE_4kXZJXbTtjbN8DZOJ_ppZPdfJKPkiTvZJmDD7NeQWnDOgzCeZqwRU8","acknowledged":false}
[Wed Jun 23 2021 08:55:29.830]  LOG      🔳🔲🔳🔲🔳🔲 checkCurrentPurchase
[Wed Jun 23 2021 08:55:29.880]  LOG      🔳🔳🔳 {"orderId":"GPA.3344-3869-5501-90751","packageName":"com.sugarloafappcompany.bingo","productId":"bingo.consumable.dollar","purchaseTime":1624460117834,"purchaseState":0,"purchaseToken":"adhfehbkneedajpdbpaocmhk.AO-J1OyoT5Od2NpKrOG2AJ81z0VfIWakGQW-10Y3grx9J3XlHWXJS-hlZ5PMyDx8duq8_y-PlAnhWMlC6xtPE_4kXZJXbTtjbN8DZOJ_ppZPdfJKPkiTvZJmDD7NeQWnDOgzCeZqwRU8","acknowledged":false}
[Wed Jun 23 2021 08:55:30.683]  LOG      🔳🔲🔳🔲🔳🔲 checkCurrentPurchase
[Wed Jun 23 2021 08:55:30.743]  LOG      🔳🔳🔳 {"orderId":"GPA.3344-3869-5501-90751","packageName":"com.sugarloafappcompany.bingo","productId":"bingo.consumable.dollar","purchaseTime":1624460117834,"purchaseState":0,"purchaseToken":"adhfehbkneedajpdbpaocmhk.AO-J1OyoT5Od2NpKrOG2AJ81z0VfIWakGQW-10Y3grx9J3XlHWXJS-hlZ5PMyDx8duq8_y-PlAnhWMlC6xtPE_4kXZJXbTtjbN8DZOJ_ppZPdfJKPkiTvZJmDD7NeQWnDOgzCeZqwRU8","acknowledged":false}
[Wed Jun 23 2021 08:55:32.271]  LOG      🔳🔲🔳🔲🔳🔲 checkCurrentPurchase
[Wed Jun 23 2021 08:55:32.327]  LOG      🔳🔳🔳 {"orderId":"GPA.3344-3869-5501-90751","packageName":"com.sugarloafappcompany.bingo","productId":"bingo.consumable.dollar","purchaseTime":1624460117834,"purchaseState":0,"purchaseToken":"adhfehbkneedajpdbpaocmhk.AO-J1OyoT5Od2NpKrOG2AJ81z0VfIWakGQW-10Y3grx9J3XlHWXJS-hlZ5PMyDx8duq8_y-PlAnhWMlC6xtPE_4kXZJXbTtjbN8DZOJ_ppZPdfJKPkiTvZJmDD7NeQWnDOgzCeZqwRU8","acknowledged":false}
[Wed Jun 23 2021 08:55:34.340]  LOG      🔳🔲🔳🔲🔳🔲 checkCurrentPurchase
[Wed Jun 23 2021 08:55:34.410]  LOG      🔳🔳🔳 {"orderId":"GPA.3344-3869-5501-90751","packageName":"com.sugarloafappcompany.bingo","productId":"bingo.consumable.dollar","purchaseTime":1624460117834,"purchaseState":0,"purchaseToken":"adhfehbkneedajpdbpaocmhk.AO-J1OyoT5Od2NpKrOG2AJ81z0VfIWakGQW-10Y3grx9J3XlHWXJS-hlZ5PMyDx8duq8_y-PlAnhWMlC6xtPE_4kXZJXbTtjbN8DZOJ_ppZPdfJKPkiTvZJmDD7NeQWnDOgzCeZqwRU8","acknowledged":false}
[Wed Jun 23 2021 08:55:35.988]  LOG      🔳🔲🔳🔲🔳🔲 checkCurrentPurchase
[Wed Jun 23 2021 08:55:36.480]  LOG      🔳🔳🔳 {"orderId":"GPA.3344-3869-5501-90751","packageName":"com.sugarloafappcompany.bingo","productId":"bingo.consumable.dollar","purchaseTime":1624460117834,"purchaseState":0,"purchaseToken":"adhfehbkneedajpdbpaocmhk.AO-J1OyoT5Od2NpKrOG2AJ81z0VfIWakGQW-10Y3grx9J3XlHWXJS-hlZ5PMyDx8duq8_y-PlAnhWMlC6xtPE_4kXZJXbTtjbN8DZOJ_ppZPdfJKPkiTvZJmDD7NeQWnDOgzCeZqwRU8","acknowledged":false}
[Wed Jun 23 2021 08:55:37.639]  LOG      🔳🔲🔳🔲🔳🔲 checkCurrentPurchase
[Wed Jun 23 2021 08:55:37.691]  LOG      🔳🔳🔳 {"orderId":"GPA.3344-3869-5501-90751","packageName":"com.sugarloafappcompany.bingo","productId":"bingo.consumable.dollar","purchaseTime":1624460117834,"purchaseState":0,"purchaseToken":"adhfehbkneedajpdbpaocmhk.AO-J1OyoT5Od2NpKrOG2AJ81z0VfIWakGQW-10Y3grx9J3XlHWXJS-hlZ5PMyDx8duq8_y-PlAnhWMlC6xtPE_4kXZJXbTtjbN8DZOJ_ppZPdfJKPkiTvZJmDD7NeQWnDOgzCeZqwRU8","acknowledged":false}
[Wed Jun 23 2021 08:55:39.210]  LOG      🔳🔲🔳🔲🔳🔲 checkCurrentPurchase
[Wed Jun 23 2021 08:55:39.269]  LOG      🔳🔳🔳 {"orderId":"GPA.3344-3869-5501-90751","packageName":"com.sugarloafappcompany.bingo","productId":"bingo.consumable.dollar","purchaseTime":1624460117834,"purchaseState":0,"purchaseToken":"adhfehbkneedajpdbpaocmhk.AO-J1OyoT5Od2NpKrOG2AJ81z0VfIWakGQW-10Y3grx9J3XlHWXJS-hlZ5PMyDx8duq8_y-PlAnhWMlC6xtPE_4kXZJXbTtjbN8DZOJ_ppZPdfJKPkiTvZJmDD7NeQWnDOgzCeZqwRU8","acknowledged":false}
[Wed Jun 23 2021 08:55:40.811]  LOG      🔳🔲🔳🔲🔳🔲 checkCurrentPurchase
[Wed Jun 23 2021 08:55:40.875]  LOG      🔳🔳🔳 {"orderId":"GPA.3344-3869-5501-90751","packageName":"com.sugarloafappcompany.bingo","productId":"bingo.consumable.dollar","purchaseTime":1624460117834,"purchaseState":0,"purchaseToken":"adhfehbkneedajpdbpaocmhk.AO-J1OyoT5Od2NpKrOG2AJ81z0VfIWakGQW-10Y3grx9J3XlHWXJS-hlZ5PMyDx8duq8_y-PlAnhWMlC6xtPE_4kXZJXbTtjbN8DZOJ_ppZPdfJKPkiTvZJmDD7NeQWnDOgzCeZqwRU8","acknowledged":false}
[Wed Jun 23 2021 08:55:42.346]  LOG      🔳🔲🔳🔲🔳🔲 checkCurrentPurchase
[Wed Jun 23 2021 08:55:42.405]  LOG      🔳🔳🔳 {"orderId":"GPA.3344-3869-5501-90751","packageName":"com.sugarloafappcompany.bingo","productId":"bingo.consumable.dollar","purchaseTime":1624460117834,"purchaseState":0,"purchaseToken":"adhfehbkneedajpdbpaocmhk.AO-J1OyoT5Od2NpKrOG2AJ81z0VfIWakGQW-10Y3grx9J3XlHWXJS-hlZ5PMyDx8duq8_y-PlAnhWMlC6xtPE_4kXZJXbTtjbN8DZOJ_ppZPdfJKPkiTvZJmDD7NeQWnDOgzCeZqwRU8","acknowledged":false}
[Wed Jun 23 2021 08:55:43.916]  LOG      🔳🔲🔳🔲🔳🔲 checkCurrentPurchase
[Wed Jun 23 2021 08:55:43.983]  LOG      🔳🔳🔳 {"orderId":"GPA.3344-3869-5501-90751","packageName":"com.sugarloafappcompany.bingo","productId":"bingo.consumable.dollar","purchaseTime":1624460117834,"purchaseState":0,"purchaseToken":"adhfehbkneedajpdbpaocmhk.AO-J1OyoT5Od2NpKrOG2AJ81z0VfIWakGQW-10Y3grx9J3XlHWXJS-hlZ5PMyDx8duq8_y-PlAnhWMlC6xtPE_4kXZJXbTtjbN8DZOJ_ppZPdfJKPkiTvZJmDD7NeQWnDOgzCeZqwRU8","acknowledged":false}
[Wed Jun 23 2021 08:55:45.443]  LOG      🔳🔲🔳🔲🔳🔲 checkCurrentPurchase
[Wed Jun 23 2021 08:55:45.502]  LOG      🔳🔳🔳 {"orderId":"GPA.3344-3869-5501-90751","packageName":"com.sugarloafappcompany.bingo","productId":"bingo.consumable.dollar","purchaseTime":1624460117834,"purchaseState":0,"purchaseToken":"adhfehbkneedajpdbpaocmhk.AO-J1OyoT5Od2NpKrOG2AJ81z0VfIWakGQW-10Y3grx9J3XlHWXJS-hlZ5PMyDx8duq8_y-PlAnhWMlC6xtPE_4kXZJXbTtjbN8DZOJ_ppZPdfJKPkiTvZJmDD7NeQWnDOgzCeZqwRU8","acknowledged":false}
[Wed Jun 23 2021 08:55:47.200]  LOG      🔳🔲🔳🔲🔳🔲 checkCurrentPurchase
[Wed Jun 23 2021 08:55:47.610]  LOG      🔳🔳🔳 {"orderId":"GPA.3344-3869-5501-90751","packageName":"com.sugarloafappcompany.bingo","productId":"bingo.consumable.dollar","purchaseTime":1624460117834,"purchaseState":0,"purchaseToken":"adhfehbkneedajpdbpaocmhk.AO-J1OyoT5Od2NpKrOG2AJ81z0VfIWakGQW-10Y3grx9J3XlHWXJS-hlZ5PMyDx8duq8_y-PlAnhWMlC6xtPE_4kXZJXbTtjbN8DZOJ_ppZPdfJKPkiTvZJmDD7NeQWnDOgzCeZqwRU8","acknowledged":false}
[Wed Jun 23 2021 08:55:48.506]  LOG      🔳🔲🔳🔲🔳🔲 checkCurrentPurchase
[Wed Jun 23 2021 08:55:48.558]  LOG      🔳🔳🔳 {"orderId":"GPA.3344-3869-5501-90751","packageName":"com.sugarloafappcompany.bingo","productId":"bingo.consumable.dollar","purchaseTime":1624460117834,"purchaseState":0,"purchaseToken":"adhfehbkneedajpdbpaocmhk.AO-J1OyoT5Od2NpKrOG2AJ81z0VfIWakGQW-10Y3grx9J3XlHWXJS-hlZ5PMyDx8duq8_y-PlAnhWMlC6xtPE_4kXZJXbTtjbN8DZOJ_ppZPdfJKPkiTvZJmDD7NeQWnDOgzCeZqwRU8","acknowledged":false}
[Wed Jun 23 2021 08:55:50.550]  LOG      🔳🔲🔳🔲🔳🔲 checkCurrentPurchase
[Wed Jun 23 2021 08:55:50.118]  LOG      🔳🔳🔳 {"orderId":"GPA.3344-3869-5501-90751","packageName":"com.sugarloafappcompany.bingo","productId":"bingo.consumable.dollar","purchaseTime":1624460117834,"purchaseState":0,"purchaseToken":"adhfehbkneedajpdbpaocmhk.AO-J1OyoT5Od2NpKrOG2AJ81z0VfIWakGQW-10Y3grx9J3XlHWXJS-hlZ5PMyDx8duq8_y-PlAnhWMlC6xtPE_4kXZJXbTtjbN8DZOJ_ppZPdfJKPkiTvZJmDD7NeQWnDOgzCeZqwRU8","acknowledged":false}
[Wed Jun 23 2021 08:55:51.591]  LOG      🔳🔲🔳🔲🔳🔲 checkCurrentPurchase
[Wed Jun 23 2021 08:55:51.654]  LOG      🔳🔳🔳 {"orderId":"GPA.3344-3869-5501-90751","packageName":"com.sugarloafappcompany.bingo","productId":"bingo.consumable.dollar","purchaseTime":1624460117834,"purchaseState":0,"purchaseToken":"adhfehbkneedajpdbpaocmhk.AO-J1OyoT5Od2NpKrOG2AJ81z0VfIWakGQW-10Y3grx9J3XlHWXJS-hlZ5PMyDx8duq8_y-PlAnhWMlC6xtPE_4kXZJXbTtjbN8DZOJ_ppZPdfJKPkiTvZJmDD7NeQWnDOgzCeZqwRU8","acknowledged":false}
[Wed Jun 23 2021 08:55:53.134]  LOG      🔳🔲🔳🔲🔳🔲 checkCurrentPurchase
[Wed Jun 23 2021 08:55:53.191]  LOG      🔳🔳🔳 {"orderId":"GPA.3344-3869-5501-90751","packageName":"com.sugarloafappcompany.bingo","productId":"bingo.consumable.dollar","purchaseTime":1624460117834,"purchaseState":0,"purchaseToken":"adhfehbkneedajpdbpaocmhk.AO-J1OyoT5Od2NpKrOG2AJ81z0VfIWakGQW-10Y3grx9J3XlHWXJS-hlZ5PMyDx8duq8_y-PlAnhWMlC6xtPE_4kXZJXbTtjbN8DZOJ_ppZPdfJKPkiTvZJmDD7NeQWnDOgzCeZqwRU8","acknowledged":false}
[Wed Jun 23 2021 08:55:54.674]  LOG      🔳🔲🔳🔲🔳🔲 checkCurrentPurchase
[Wed Jun 23 2021 08:55:54.735]  LOG      🔳🔳🔳 {"orderId":"GPA.3344-3869-5501-90751","packageName":"com.sugarloafappcompany.bingo","productId":"bingo.consumable.dollar","purchaseTime":1624460117834,"purchaseState":0,"purchaseToken":"adhfehbkneedajpdbpaocmhk.AO-J1OyoT5Od2NpKrOG2AJ81z0VfIWakGQW-10Y3grx9J3XlHWXJS-hlZ5PMyDx8duq8_y-PlAnhWMlC6xtPE_4kXZJXbTtjbN8DZOJ_ppZPdfJKPkiTvZJmDD7NeQWnDOgzCeZqwRU8","acknowledged":false}
[Wed Jun 23 2021 08:55:56.170]  LOG      🔳🔲🔳🔲🔳🔲 checkCurrentPurchase
[Wed Jun 23 2021 08:55:56.226]  LOG      🔳🔳🔳 {"orderId":"GPA.3344-3869-5501-90751","packageName":"com.sugarloafappcompany.bingo","productId":"bingo.consumable.dollar","purchaseTime":1624460117834,"purchaseState":0,"purchaseToken":"adhfehbkneedajpdbpaocmhk.AO-J1OyoT5Od2NpKrOG2AJ81z0VfIWakGQW-10Y3grx9J3XlHWXJS-hlZ5PMyDx8duq8_y-PlAnhWMlC6xtPE_4kXZJXbTtjbN8DZOJ_ppZPdfJKPkiTvZJmDD7NeQWnDOgzCeZqwRU8","acknowledged":false}
[Wed Jun 23 2021 08:55:57.774]  LOG      🔳🔲🔳🔲🔳🔲 checkCurrentPurchase
[Wed Jun 23 2021 08:55:57.838]  LOG      🔳🔳🔳 {"orderId":"GPA.3344-3869-5501-90751","packageName":"com.sugarloafappcompany.bingo","productId":"bingo.consumable.dollar","purchaseTime":1624460117834,"purchaseState":0,"purchaseToken":"adhfehbkneedajpdbpaocmhk.AO-J1OyoT5Od2NpKrOG2AJ81z0VfIWakGQW-10Y3grx9J3XlHWXJS-hlZ5PMyDx8duq8_y-PlAnhWMlC6xtPE_4kXZJXbTtjbN8DZOJ_ppZPdfJKPkiTvZJmDD7NeQWnDOgzCeZqwRU8","acknowledged":false}
[Wed Jun 23 2021 08:55:59.281]  LOG      🔳🔲🔳🔲🔳🔲 checkCurrentPurchase
[Wed Jun 23 2021 08:55:59.342]  LOG      🔳🔳🔳 {"orderId":"GPA.3344-3869-5501-90751","packageName":"com.sugarloafappcompany.bingo","productId":"bingo.consumable.dollar","purchaseTime":1624460117834,"purchaseState":0,"purchaseToken":"adhfehbkneedajpdbpaocmhk.AO-J1OyoT5Od2NpKrOG2AJ81z0VfIWakGQW-10Y3grx9J3XlHWXJS-hlZ5PMyDx8duq8_y-PlAnhWMlC6xtPE_4kXZJXbTtjbN8DZOJ_ppZPdfJKPkiTvZJmDD7NeQWnDOgzCeZqwRU8","acknowledged":false}
[Wed Jun 23 2021 08:56:00.845]  LOG      🔳🔲🔳🔲🔳🔲 checkCurrentPurchase
[Wed Jun 23 2021 08:56:00.910]  LOG      🔳🔳🔳 {"orderId":"GPA.3344-3869-5501-90751","packageName":"com.sugarloafappcompany.bingo","productId":"bingo.consumable.dollar","purchaseTime":1624460117834,"purchaseState":0,"purchaseToken":"adhfehbkneedajpdbpaocmhk.AO-J1OyoT5Od2NpKrOG2AJ81z0VfIWakGQW-10Y3grx9J3XlHWXJS-hlZ5PMyDx8duq8_y-PlAnhWMlC6xtPE_4kXZJXbTtjbN8DZOJ_ppZPdfJKPkiTvZJmDD7NeQWnDOgzCeZqwRU8","acknowledged":false}
[Wed Jun 23 2021 08:56:02.357]  LOG      🔳🔲🔳🔲🔳🔲 checkCurrentPurchase
[Wed Jun 23 2021 08:56:02.409]  LOG      🔳🔳🔳 {"orderId":"GPA.3344-3869-5501-90751","packageName":"com.sugarloafappcompany.bingo","productId":"bingo.consumable.dollar","purchaseTime":1624460117834,"purchaseState":0,"purchaseToken":"adhfehbkneedajpdbpaocmhk.AO-J1OyoT5Od2NpKrOG2AJ81z0VfIWakGQW-10Y3grx9J3XlHWXJS-hlZ5PMyDx8duq8_y-PlAnhWMlC6xtPE_4kXZJXbTtjbN8DZOJ_ppZPdfJKPkiTvZJmDD7NeQWnDOgzCeZqwRU8","acknowledged":false}
[Wed Jun 23 2021 08:56:04.312]  LOG      🔳🔲🔳🔲🔳🔲 checkCurrentPurchase
[Wed Jun 23 2021 08:56:04.387]  LOG      🔳🔳🔳 {"orderId":"GPA.3344-3869-5501-90751","packageName":"com.sugarloafappcompany.bingo","productId":"bingo.consumable.dollar","purchaseTime":1624460117834,"purchaseState":0,"purchaseToken":"adhfehbkneedajpdbpaocmhk.AO-J1OyoT5Od2NpKrOG2AJ81z0VfIWakGQW-10Y3grx9J3XlHWXJS-hlZ5PMyDx8duq8_y-PlAnhWMlC6xtPE_4kXZJXbTtjbN8DZOJ_ppZPdfJKPkiTvZJmDD7NeQWnDOgzCeZqwRU8","acknowledged":false}
[Wed Jun 23 2021 08:56:05.932]  LOG      🔳🔲🔳🔲🔳🔲 checkCurrentPurchase
[Wed Jun 23 2021 08:56:05.997]  LOG      🔳🔳🔳 {"orderId":"GPA.3344-3869-5501-90751","packageName":"com.sugarloafappcompany.bingo","productId":"bingo.consumable.dollar","purchaseTime":1624460117834,"purchaseState":0,"purchaseToken":"adhfehbkneedajpdbpaocmhk.AO-J1OyoT5Od2NpKrOG2AJ81z0VfIWakGQW-10Y3grx9J3XlHWXJS-hlZ5PMyDx8duq8_y-PlAnhWMlC6xtPE_4kXZJXbTtjbN8DZOJ_ppZPdfJKPkiTvZJmDD7NeQWnDOgzCeZqwRU8","acknowledged":false}
[Wed Jun 23 2021 08:56:07.721]  LOG      🔳🔲🔳🔲🔳🔲 checkCurrentPurchase
[Wed Jun 23 2021 08:56:07.746]  LOG      🔳🔳🔳 {"orderId":"GPA.3344-3869-5501-90751","packageName":"com.sugarloafappcompany.bingo","productId":"bingo.consumable.dollar","purchaseTime":1624460117834,"purchaseState":0,"purchaseToken":"adhfehbkneedajpdbpaocmhk.AO-J1OyoT5Od2NpKrOG2AJ81z0VfIWakGQW-10Y3grx9J3XlHWXJS-hlZ5PMyDx8duq8_y-PlAnhWMlC6xtPE_4kXZJXbTtjbN8DZOJ_ppZPdfJKPkiTvZJmDD7NeQWnDOgzCeZqwRU8","acknowledged":false}
[Wed Jun 23 2021 08:56:07.746]  LOG      [CodePush] Sync already in progress.
[Wed Jun 23 2021 08:56:07.746]  LOG      [CodePush] Sync already in progress.
[Wed Jun 23 2021 08:56:07.747]  LOG      [CodePush] Sync already in progress.
[Wed Jun 23 2021 08:56:07.747]  LOG      [CodePush] Sync already in progress.
[Wed Jun 23 2021 08:56:07.748]  LOG      [CodePush] Sync already in progress.
[Wed Jun 23 2021 08:56:07.749]  LOG      [CodePush] Sync already in progress.
[Wed Jun 23 2021 08:56:07.749]  LOG      [CodePush] Sync already in progress.
[Wed Jun 23 2021 08:56:07.749]  LOG      [CodePush] Sync already in progress.
[Wed Jun 23 2021 08:56:07.752]  LOG      [CodePush] Sync already in progress.
[Wed Jun 23 2021 08:56:07.753]  LOG      [CodePush] Sync already in progress.
[Wed Jun 23 2021 08:56:07.754]  LOG      [CodePush] Sync already in progress.
[Wed Jun 23 2021 08:56:07.754]  LOG      [CodePush] Sync already in progress.
[Wed Jun 23 2021 08:56:07.754]  LOG      [CodePush] Sync already in progress.
[Wed Jun 23 2021 08:56:07.764]  LOG      [CodePush] Sync already in progress.
[Wed Jun 23 2021 08:56:07.767]  LOG      App has come to the foreground!
[Wed Jun 23 2021 08:56:09.433]  LOG      [CodePush] Checking for update.
[Wed Jun 23 2021 08:56:09.566]  WARN     🔷🔷🔷 ackErr [ReferenceError: Can't find variable: ackResult]
[Wed Jun 23 2021 08:56:09.617]  WARN     🔷🔷🔷 ackErr [Error: Purchase failed with code: 8]
[Wed Jun 23 2021 08:56:09.758]  WARN     🔷🔷🔷 ackErr [Error: Purchase failed with code: 8]
[Wed Jun 23 2021 08:56:09.759]  WARN     🔷🔷🔷 ackErr [Error: Purchase failed with code: 8]
[Wed Jun 23 2021 08:56:09.771]  WARN     🔷🔷🔷 ackErr [Error: Purchase failed with code: 8]
[Wed Jun 23 2021 08:56:09.837]  WARN     🔷🔷🔷 ackErr [Error: Purchase failed with code: 8]
[Wed Jun 23 2021 08:56:09.859]  WARN     🔷🔷🔷 ackErr [Error: Purchase failed with code: 8]
[Wed Jun 23 2021 08:56:09.926]  WARN     🔷🔷🔷 ackErr [Error: Purchase failed with code: 8]
[Wed Jun 23 2021 08:56:09.963]  WARN     🔷🔷🔷 ackErr [Error: Purchase failed with code: 8]
[Wed Jun 23 2021 08:56:09.999]  WARN     🔷🔷🔷 ackErr [Error: Purchase failed with code: 8]
[Wed Jun 23 2021 08:56:10.580]  WARN     🔷🔷🔷 ackErr [Error: Purchase failed with code: 8]
[Wed Jun 23 2021 08:56:10.920]  WARN     🔷🔷🔷 ackErr [Error: Purchase failed with code: 8]
[Wed Jun 23 2021 08:56:10.128]  WARN     🔷🔷🔷 ackErr [Error: Purchase failed with code: 8]
[Wed Jun 23 2021 08:56:10.165]  WARN     🔷🔷🔷 ackErr [Error: Purchase failed with code: 8]
[Wed Jun 23 2021 08:56:10.199]  WARN     🔷🔷🔷 ackErr [Error: Purchase failed with code: 8]
[Wed Jun 23 2021 08:56:10.236]  WARN     🔷🔷🔷 ackErr [Error: Purchase failed with code: 8]
[Wed Jun 23 2021 08:56:10.270]  WARN     🔷🔷🔷 ackErr [Error: Purchase failed with code: 8]
[Wed Jun 23 2021 08:56:10.303]  WARN     🔷🔷🔷 ackErr [Error: Purchase failed with code: 8]
[Wed Jun 23 2021 08:56:10.339]  WARN     🔷🔷🔷 ackErr [Error: Purchase failed with code: 8]
[Wed Jun 23 2021 08:56:10.392]  WARN     🔷🔷🔷 ackErr [Error: Purchase failed with code: 8]
[Wed Jun 23 2021 08:56:10.435]  WARN     🔷🔷🔷 ackErr [Error: Purchase failed with code: 8]
[Wed Jun 23 2021 08:56:10.456]  WARN     🔷🔷🔷 ackErr [Error: Purchase failed with code: 8]
[Wed Jun 23 2021 08:56:10.506]  WARN     🔷🔷🔷 ackErr [Error: Purchase failed with code: 8]
[Wed Jun 23 2021 08:56:10.540]  WARN     🔷🔷🔷 ackErr [Error: Purchase failed with code: 8]
[Wed Jun 23 2021 08:56:10.572]  WARN     🔷🔷🔷 ackErr [Error: Purchase failed with code: 8]
[Wed Jun 23 2021 08:56:10.606]  WARN     🔷🔷🔷 ackErr [Error: Purchase failed with code: 8]
[Wed Jun 23 2021 08:56:10.642]  WARN     🔷🔷🔷 ackErr [Error: Purchase failed with code: 8]
[Wed Jun 23 2021 08:56:10.678]  WARN     🔷🔷🔷 ackErr [Error: Purchase failed with code: 8]
[Wed Jun 23 2021 08:56:10.970]  LOG      [CodePush] Reporting binary update (8.0.2)
[Wed Jun 23 2021 08:56:10.987]  WARN     🔷🔷🔷 ackErr [Error: Purchase failed with code: 8]
[Wed Jun 23 2021 08:56:12.967]  LOG      [CodePush] Report status failed: {"appVersion":"8.0.2"}
[Wed Jun 23 2021 08:56:13.250]  LOG      [CodePush] App is up to date.

note 1 - I have attempted purchases many many times this morning, and after each attempt the number of these loops increases note 2 - I'm not sure why I'm getting "Error: Purchase failed with code 8"? The purchase is getting consumed, but according to this error code 8 = "Failure to consume item since it is not owned"?

On the surface it does seems possible the purchaseUpdatedListener is not getting removed properly, and maybe this is happening because I have been hot reloading the app?

Thanks for looking into this!

andresesfm commented 3 years ago

@marcpechaitis thank you for the details. I have created a PR with fixes to multiple billing clients being created: https://github.com/dooboolab/react-native-iap/pull/1388 this could be the solution to your problems. Any help testing it would be appreciated.

marcpechaitis commented 3 years ago

@andresesfm awesome thanks for the hard work on this! I've been out of town and am just now able to get back at this. I have a question about your PR (#1338) -- I reviewed your changes and I see the recommendation related to the connection lifecycle and, essentially, "connect/init as soon as you can, not right before you need it" which makes sense... but does the useIAP hook honor that? I have written my code around useIAP() and will have to do some refactoring away from that in order to properly test your PR, right? Another way to put it, does invoking useIAP() throughout the app mean multiple attempts to init are made?

High-level: I have 2 screens where I'm using useIAP(one for consumables, the other for a non-consumable). When I invoke useIAP on either screen doesn't that kick off another init? And on top of that, I'm loading the currentPurchase & currentPurchaseError listeners in my main App.tsx file -- which results in another init happening?

marcpechaitis commented 3 years ago

@andresesfm I'm having issues trying to get your fork to work in my project:

error: Error: While trying to resolve module `react-native-iap` from file `/Users/marcpechaitis/Dropbox/Develop/rn/sandbox/iTour/helpers/router.tsx`, the package `/Users/marcpechaitis/Dropbox/Develop/rn/sandbox/iTour/node_modules/react-native-iap/package.json` was successfully found. However, this package itself specifies a `main` module field that could not be resolved (`/Users/marcpechaitis/Dropbox/Develop/rn/sandbox/iTour/node_modules/react-native-iap/index.js`. Indeed, none of these files exist:

  * /Users/marcpechaitis/Dropbox/Develop/rn/sandbox/iTour/node_modules/react-native-iap/index.js(.native|.ios.js|.native.js|.js|.ios.json|.native.json|.json|.ios.ts|.native.ts|.ts|.ios.tsx|.native.tsx|.tsx|.ios.svg|.native.svg|.svg)
  * /Users/marcpechaitis/Dropbox/Develop/rn/sandbox/iTour/node_modules/react-native-iap/index.js/index(.native|.ios.js|.native.js|.js|.ios.json|.native.json|.json|.ios.ts|.native.ts|.ts|.ios.tsx|.native.tsx|.tsx|.ios.svg|.native.svg|.svg)
    at ResolutionRequest.resolveDependency (/Users/marcpechaitis/Dropbox/Develop/rn/sandbox/iTour/node_modules/metro/src/node-haste/DependencyGraph/ResolutionRequest.js:65:15)
    at DependencyGraph.resolveDependency (/Users/marcpechaitis/Dropbox/Develop/rn/sandbox/iTour/node_modules/metro/src/node-haste/DependencyGraph.js:287:16)
    at Object.resolve (/Users/marcpechaitis/Dropbox/Develop/rn/sandbox/iTour/node_modules/metro/src/lib/transformHelpers.js:267:42)
    at /Users/marcpechaitis/Dropbox/Develop/rn/sandbox/iTour/node_modules/metro/src/DeltaBundler/traverseDependencies.js:434:31
    at Array.map (<anonymous>)
    at resolveDependencies (/Users/marcpechaitis/Dropbox/Develop/rn/sandbox/iTour/node_modules/metro/src/DeltaBundler/traverseDependencies.js:431:18)
    at /Users/marcpechaitis/Dropbox/Develop/rn/sandbox/iTour/node_modules/metro/src/DeltaBundler/traverseDependencies.js:275:33
    at Generator.next (<anonymous>)
    at asyncGeneratorStep (/Users/marcpechaitis/Dropbox/Develop/rn/sandbox/iTour/node_modules/metro/src/DeltaBundler/traverseDependencies.js:87:24)
    at _next (/Users/marcpechaitis/Dropbox/Develop/rn/sandbox/iTour/node_modules/metro/src/DeltaBundler/traverseDependencies.js:107:9)

(I'm don't have tons of experience with git, so I appreciate any advice you can give to help me proceed?)

Here is how I tried to use your fork:

// 1st remove old version
> yarn remove react-native-iap
// use forked version
> yarn add https://github.com/andresesfm/react-native-iap.git 
// clean & run
> cd android &&./gradlew clean && cd .
> react-native run-android
marcpechaitis commented 3 years ago

@andresesfm I just wanted to report back that I made some changes and have stopped seeing the "purchaseUpdatedListener being called multiple times" issue on my end (despite not using your fork).

I took the advice in the documentation of your fork and removed a couple extraneous calls I was making to initConnection() at various spots throughout my code. Now I am letting that happening solely via the call to the useIAP() hook in a useEffect() where I set the currentPurchase and currentPurchaseError in my main App.tsx file.

StefanNedelchev commented 3 years ago

Probably the best solution is - on iOS call a chain of clearProductsIOS() and clearTransactionIOS() before initializing your transaction listeners. Additionally - don't use getAvailablePurchases() on iOS if you want to restore purchases. The better solution is to restore the receipt (getReceiptIOS()) and pass it to validateReceiptIos(). If you are using auto-renewable subscriptions you can look for the pending_renewal_info array returned by validateReceiptIos() as it contains info for currently ongoing (or canceled) subscriptions. You can check if a subscription is still active by verifying that the property auto_renew_status is '1' and the property expiration_intent is not present.

andresesfm commented 3 years ago

Thank you all for the info. I'm closing it, but feel free to reopen if needed

Haseeba393 commented 1 year ago

I'm using latest version 12.10.2 and still getting this problem. Can you please help me out?

VictoriaStudios commented 1 year ago

Getting the same problem here... .Will probably need to code a workaround.... Maybe have a timeout that prevents a second trigger of the assigned side effect. Edit: I'm on Android, it happens on a physical device.

Haseeba393 commented 1 year ago

In getting the same issue on latest version ios

VictoriaStudios commented 1 year ago

So here's my solution with comments:

let checkCount = 0
// this was the only way of stopping react native from generating an unpredictable amount of subscriptions
const [subscriptionsBound, setSubscriptionsBound] = useState(false)

useEffect(() => {
    if (!subscriptionsBound) {
        const purchaseUpdateSubscription = IAP.purchaseUpdatedListener((purchase) => {
            checkCount++
            // insert your number of repeated subscription calls below
            if (checkCount >= 2) {
                console.log ('checkCount reached two, checking purchase')
                checkPurchase(purchase)
                checkCount = 0
            }
        })

        //... other effects
        setSubscriptionsBound(true)
       //just to make sure react doesn't call multile useEffects
        console.log('useEffect called')
        return () => {
            purchaseUpdateSubscription.remove()
            purchaseErrorSubscription.remove()
        }
    }
}, [])
VictoriaStudios commented 1 year ago

Another update: I noticed that the multiple binding only happens at the very start of the App. If I bind the purchaseUpdate to data that is later fetched, the error does not happen. So I basically accidentally fixed it by having an if-statement and a dependency on data that were later fetched:

   useEffect(() => {
        if (uData) {
            console.log('Binding purchase Subscriptions, uData:')
            console.log(uData)
            const purchaseUpdateSubscription = IAP.purchaseUpdatedListener((purchase) => {
                console.log('update Subscription called')
                checkPurchase(purchase, uData)
            })

            return () => {
                purchaseUpdateSubscription.remove()
            }
        }
    }, [uData])
Anupamchap commented 1 year ago

Issue still exist in the latest version of react-native-iap, purchaseUpdatedListener is getting called multiple times. Please share if someone has resolution for this issue.

carlosmellado commented 11 months ago

Having the same problem. All works as expected on Android but I'm having issues with this on iOS. clearTransactionIOS() is not solving the issue.

SufianBabri commented 9 months ago

It seems to happen on Android if you have multiple open connections (which can happen pretty easily when running with Metro, i.e. initConnection got called more times than endConnection). Also, see this answer which is related to native Android code

In my testing, the function passed to purchaseUpdatedListener gets called twice unless I call endConnection before calling initConnection. This seems weird, maybe it is specific to debug builds?

mrtawil commented 8 months ago

+1

RouberR commented 1 month ago

Same problem, test users have too many requests which eventually causes the application to freeze

useEffect(() => {
    if (currentPurchase && connected) {
      const handlePurchase = async () => {
        const receipt = currentPurchase.transactionReceipt;
        if (receipt) {
          if (
            Platform.OS === 'android' &&
            !currentPurchase.isAcknowledgedAndroid
          ) {
            await acknowledgePurchaseAndroid({
              token: currentPurchase.purchaseToken,
            });
          }

          try {

            const data =
              Platform.OS === 'ios'
                ? {
                    password: 'password',
                    'receipt-data': receipt,
                  }
                : {
                    subscriptionType:
                      currentPurchase.productId === '7trial_monthly_7.99'
                        ? 'SEVEN_TRIAL_MONTHLY'
                        : 'SEVEN_TRIAL_ANNUAL',
                    token: currentPurchase.purchaseToken,
                  };
            const response =
              Platform.OS === 'ios'
                ? await submitIOSSubscription(data) //api server
                : await submitAndroidSubscription(data); //api server

            await finishTransaction({
              purchase: currentPurchase,
              isConsumable: false,
            });

            if (response.success) {
              dispatch(setIsSubscriptionPurchased(true));
            }

          } catch (error) {
            AmplitudeService.logEvent('Purchase Error', { error });
            console.error(
              'An error occurred while completing the transaction:',
              error,
            );
          } 
        }
      };

      handlePurchase();
    }
  }, [currentPurchase, finishTransaction, connected]);
Karthik-V26 commented 4 weeks ago

Hi, Is there any work around for this issue ? I also facing the same issue.