question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

FinishTransactionIOS is called but purchaseUpdatedListener is still invoke

See original GitHub issue

Version 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:closed
  • Created 3 years ago
  • Reactions:1
  • Comments:6

github_iconTop GitHub Comments

5reactions
burak4ydincommented, Mar 28, 2021

same problem

0reactions
andresesfmcommented, Jul 26, 2022

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

Read more comments on GitHub >

github_iconTop Results From Across the Web

Developers - FinishTransactionIOS is called but ... - Bountysource
FinishTransactionIOS is called but purchaseUpdatedListener is still invoke.
Read more >
react-native-iap - npm
This react-native module will help you access the In-app purchases capabilities of your phone on the Android , iOS platforms and the Amazon ......
Read more >
Issuehunt
purchaseUpdatedListener being called multiple, sometimes 20+ times #1104 ... the problem is finishTransaction and finishTransactionIOS not work for iOS now, ...
Read more >
Changing renewable subscription in iOS In-app purchase ...
purchaseUpdatedListener handler correctly fires, and I finish the transaction using RNIap.finishTransactionIOS(purchase.transactionId) .
Read more >
React Native : Subscriptions, In-App Purchases & Service ...
In-app purchasing refers to the buying of goods and services from an application on ... by simply calling finishTransactionIOS() on non-consumables as well....
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found