Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

consumePurchaseAndroid not working #531

Closed
ko-devHong opened this issue Jun 17, 2019 · 6 comments
Closed

consumePurchaseAndroid not working #531

ko-devHong opened this issue Jun 17, 2019 · 6 comments
Labels
🤖 android Related to android 🙏 help wanted Extra attention is needed

Comments

@ko-devHong
Copy link

ko-devHong commented Jun 17, 2019

I bought a test payment ID and wanted to pay again.

So I was looking for that feature, and I found a consumePurchaseAndroid. So I used it, but it didn't work.

I want to use the functions of below.

Note: To make multiple test purchases for the same in-app product, mark the item as consumed after each purchase. To do so, call 'consumeAsync().

componentDidmount {
  try {
    const purchases = await RNIap.getAvailablePurchases();
    purchases.forEach(purchase => {
        await RNIap.consumePurchaseAndroid(purchase.purchaseToken);
      }
    })
  } catch(err) {
    console.warn(err); // standardized err.code and err.message available
    Alert.alert(err.message);
  }
}
@hyochan hyochan added 🤖 android Related to android 🙏 help wanted Extra attention is needed labels Jun 17, 2019
@hyochan
Copy link
Member

hyochan commented Jun 17, 2019

@StudyTae Could you test the example project? I've already tested that it was working.

@ko-devHong
Copy link
Author

ko-devHong commented Jun 18, 2019

@hyochan Project behavior: Start the app => pay for it => turn it off and restart it => And try to pay again. => But there is no reaction.

Version of react-native-iap
^2.5.3

My product ID: android.test.purchased

Is the example you are saying is this example?

getPurchases = async() => {
  try {
    const purchases = await RNIap.getAvailablePurchases();
    let restoredTitles = '';
    let coins = CoinStore.getCount();
    purchases.forEach(purchase => {
      if (purchase.productId == 'com.example.premium') {
        this.setState({ premium: true });
        restoredTitles += 'Premium Version';
      } else if (purchase.productId == 'com.example.no_ads') {
        this.setState({ ads: false });
        restoredTitles += restoredTitles.length > 0 ? 'No Ads' : ', No Ads';
      } else if (purchase.productId == 'com.example.coins100') {
        CoinStore.addCoins(100);
        await RNIap.consumePurchaseAndroid(purchase.purchaseToken);
      }
    })
    Alert.alert('Restore Successful', 'You successfully restored the following purchases: ' + restoredTitles);
  } catch(err) {
    console.warn(err); // standardized err.code and err.message available
    Alert.alert(err.message);
  }
}

I saw this example and used the necessary parts. Where is the problem?

The simple code I'm using:

async componentDidMount() {
    try {
      const result = await RNIap.initConnection();
      await RNIap.consumeAllItems();
      const purchases = await RNIap.getAvailablePurchases();
      console.log(purchases);        //This array value is empty.
 purchases.forEach(purchase => {
        await RNIap.consumePurchaseAndroid(purchase.purchaseToken);
    });
      this.setState({
        loading: true,
      });
    } catch (error) {
      Alert.alert(
        "Info",
        "Network Error",
        [
          {
            text: "ok",
            onPress: () => {
              errorCodeSend("webviewlogin", JSON.stringify(error));
            }
          }
        ],
        { cancelable: false }
      );
    }
  }
...

  getItems = async itemSkus => {
    try {
      const products = await RNIap.getProducts(itemSkus);
      this.setState({ productlist: products });
    } catch (err) {
      errorCodeSend("webViewGetItemsFuc", err);
    }
  };


  buyItem = async sku => {
    try {
      const purchase = await RNIap.buyProduct(sku);
      this.setState({ receipt: purchase.transactionReceipt }, () =>
        this.webview.postMessage(JSON.stringify(code));
      );
    } catch (err) {
      if (err.code === "E_USER_CANCELLED") {
        this.webview.postMessage(JSON.stringify(code));
      }
      const subscription = RNIap.addAdditionalSuccessPurchaseListenerIOS(
        async purchase => {
          this.setState({ receipt: purchase.transactionReceipt }, () =>
            console.log("ios sucess")
          );
          subscription.remove();
        }
      );
    }
  };
...
async handleMessage(e) {
  const data = e.nativeEvent.data;
    pasedata = JSON.parse(data);
if (pasedata.apiType === "in_app") {
      array = [pasedata.productid];
      await this.getItems(array);
      await this.buyItem(this.state.productlist[0].productId);
    }
...
    <WebView
          ref={webview => (this.webview = webview)}
          source={{ uri: this.state.uri }}
          mixedContentMode="compatibility"
          allowFileAccess={true}
          onMessage={mssage => this.handleMessage(mssage)}
          onNavigationStateChange={this.onNavigationStateChange}
        />
}

@ko-devHong
Copy link
Author

ko-devHong commented Jun 18, 2019

@hyochan
related issue #126
The solution to this issue is that RNIap.consumeAllItems(), when used, is the solution that makes products that have already been purchased available again.

But I already use that function, as you can see from the comments above. But it didn't work properly. So I tried to use getAvailablePurchases and consumePurchaseAndroid but this doesn't work right either. Is this the function difference based on the version? My version is 2.5.3.

So I read the readme again and looked for the functions of RNIap. And I found RNIap.consumePurchase, and I tried to apply it. The function worked successfully on me.

 buyItem = async sku => {
    try {
      const purchase = await RNIap.buyProduct(sku);
      this.setState({ receipt: purchase.transactionReceipt });
      let parsedata = JSON.parse(this.state.receipt);
      let comsume = await RNIap.consumePurchase(parsedata.purchaseToken);
      if (comsume === true) {
         this.webview.postMessage(JSON.stringify(code));
      }
    } catch (err) {
      if (err.code === "E_USER_CANCELLED") {
        this.webview.postMessage(JSON.stringify(code));
      }
      const subscription = RNIap.addAdditionalSuccessPurchaseListenerIOS(
        async purchase => {
          this.setState({ receipt: purchase.transactionReceipt }, () =>
            console.log("ios sucess")
          );
          subscription.remove();
        }
      );
    }
  };

Is my method the right way?

Is there the right way to recommend me? Why doesn't the other solution work on me?

@hyochan
Copy link
Member

hyochan commented Jun 18, 2019

@StudyTae This is resolved in 3.0.0-rc.+. Please try using our 3.0.0 for now on. Currently 3.0.0-rc.12.

@ashutosh-s
Copy link

ashutosh-s commented Jul 20, 2019

I am using similar code and getting following error

 const availablePurchases = await RNIap.getAvailablePurchases();
availablePurchases.forEach((purchase)=>{
 RNIap.consumePurchaseAndroid(purchase.purchaseToken);
});

if there are 3 packeges i get bellow error thrice and packages are still available in getAvailablePurchase

I am using version 3.3.5

"react-native-iap": "^3.3.5"

Error: Google is indicating that we have some issue connecting to payment.
Error: Google is indicating that we have some issue connecting to payment.
at createErrorFromErrorData (blob:file:///5763777c-30bd-4220-b6d5-6644ff59a553:15917:17)
at blob:file:///5763777c-30bd-4220-b6d5-6644ff59a553:15869:27
at MessageQueue.__invokeCallback (blob:file:///5763777c-30bd-4220-b6d5-6644ff59a553:16746:18)
at blob:file:///5763777c-30bd-4220-b6d5-6644ff59a553:16477:18
at MessageQueue.__guard (blob:file:///5763777c-30bd-4220-b6d5-6644ff59a553:16650:13)
at MessageQueue.invokeCallbackAndReturnFlushedQueue (blob:file:///5763777c-30bd-4220-b6d5-6644ff59a553:16476:14)
at e (file:///usr/lib/react-native-debugger/resources/app.asar/js/RNDebuggerWorker.js:1:136705)

@khorark
Copy link
Contributor

khorark commented Aug 10, 2019

@hyochan
related issue #126
The solution to this issue is that RNIap.consumeAllItems(), when used, is the solution that makes products that have already been purchased available again.

But I already use that function, as you can see from the comments above. But it didn't work properly. So I tried to use getAvailablePurchases and consumePurchaseAndroid but this doesn't work right either. Is this the function difference based on the version? My version is 2.5.3.

So I read the readme again and looked for the functions of RNIap. And I found RNIap.consumePurchase, and I tried to apply it. The function worked successfully on me.

 buyItem = async sku => {
    try {
      const purchase = await RNIap.buyProduct(sku);
      this.setState({ receipt: purchase.transactionReceipt });
      let parsedata = JSON.parse(this.state.receipt);
      let comsume = await RNIap.consumePurchase(parsedata.purchaseToken);
      if (comsume === true) {
         this.webview.postMessage(JSON.stringify(code));
      }
    } catch (err) {
      if (err.code === "E_USER_CANCELLED") {
        this.webview.postMessage(JSON.stringify(code));
      }
      const subscription = RNIap.addAdditionalSuccessPurchaseListenerIOS(
        async purchase => {
          this.setState({ receipt: purchase.transactionReceipt }, () =>
            console.log("ios sucess")
          );
          subscription.remove();
        }
      );
    }
  };

Is my method the right way?

Is there the right way to recommend me? Why doesn't the other solution work on me?

I have this problem and my solution be that I'm reverted call function consumePurchaseAndroid and acknowledgePurchaseAndroid.

export const acceptPurchase = async (purchase: Purchase) => {
    try {
        if (isAndroid) {
            // If not consumable
            purchase.purchaseToken && (await acknowledgePurchaseAndroid(purchase.purchaseToken));
            // If consumable (can be purchased again)
            purchase.purchaseToken && (await consumePurchaseAndroid(purchase.purchaseToken));
        } else if (isIos) {
            purchase.transactionId && (await finishTransactionIOS(purchase.transactionId));
        }
        return true;
    } catch (e) {
        console.warn('confirmPurchase error =>', e);
        return false;
    }
};

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
🤖 android Related to android 🙏 help wanted Extra attention is needed
Projects
None yet
Development

No branches or pull requests

4 participants