React-native-iap: RNIap.getProducts not returning promise on ios

Created on 19 Dec 2018  ·  24Comments  ·  Source: dooboolab/react-native-iap

Version of react-native-iap

"react-native-iap": "^2.3.25"

Version of react-native

"react-native": "0.57.4",

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

IOS

Expected behavior

buyProduct should return promise ( .then() is not call ),

Actual behavior

buyProduct not returning any promise, in android its working fine, .then() call successfully, but in ios its not.

Tested environment (Emulator? Real Device?)

Real Device

Steps to reproduce the behavior

onBuyNowPress() {
    this.setState({ loading: true });
    RNIap.getProducts(['product_id']).then(success => { 
       RNIap.buyProduct('product_id').then(purchase => { 
        console.log("Purchase >>", purchase)
        this.setState({
          loading: false,
          receipt: purchase.transactionReceipt, 
        });
        Alert.alert('Purchase Successful!');
        this.props.getPurchase();
       }).catch(err => { 
         console.log(err.code, err.message);
          this.setState({ loading: false });
          Alert.alert(err.message);
          if(err.message === "You already own this item.") {
            this.props.getPurchase();
          }
        }) 
      }).catch(error => { 
        alert(error); 
        this.setState({ loading: false });
      })
  }

In ios i already buy product, so again when i press buy now, i get popup like you already purchase this product. but .then() or .catch() not getting call.

i also tried getAvailablePurchases() method, its always return []

📱 iOS 🙏 help wanted

Most helpful comment

Could you try 2.4.0-beta4?

All 24 comments

@LinusU I think @JJMoon was right. I've removed all the async and the problem comes up again. What do you think? @ZeroCool00 Would you downgrade to 2.3.24 for now?

@ZeroCool00 Actually, would you please try 2.3.26 for us?

@hyochan i'll test soon.. and let you know, and thank you for the quick reply.

@hyochan i tried with 2.3.26, it not working? any solution?

@ZeroCool00 Then it must be a linking problem. You should try to unlink and re-link again.

@hyochan i tried, even i unlink and than uninstall and than install again, and link again. but it still not working

@ZeroCool00 If you are in window, react-native link script is even more unstable. Did you try manually? Also please try 2.3.24 too. I think you are facing some config problem.

@hyochan i m on mac, and i unlink and than uninstall and then install 2.3.24, and do manual setup, follow each step, it working with android, in ios its still not showing. process is working fine. i m getting popup and product also getting purchase, but no promise return.?

is there any other configuration for ios? i m stuck here, is there any other way to get that i already purchase.

@JJMoon Could you help @ZeroCool00 ?

@ZeroCool00 Also try removing Alert and use console to test instead. Because ios automatically generate native Alert when the purchase is being processed which may interrupt your code.

@hyochan Plz reopen this.. i tried everything.. i also remove Alert. even i stop debugging and check.. its just not working. i wanted to publish my app, but i m stuck here. i even tried this lib https://github.com/chirag04/react-native-in-app-utils

this lib also has a same problem.. purchasing process working fine but not getting any promise.

is there any lifecycle method where i get event callback. i just want event callback where i can call server api.

@ZeroCool00 Could you try to use async and await also? I'm also using this in our app and we are not facing this issue.

@hyochan can you please provide your demo.. how are you using it.. it would be a great help.

async forIOS() {
    let purchase =  await RNIap.buyProduct('product_id');
    console.log("BannerPurchase >>",purchase);  **<--- THIS IS NOT GETTING CALL**
    if(purchase) {
      console.log("Purchase >>", purchase)
      this.props.getPurchase();
      this.setState({
        loading: false,
        receipt: purchase.transactionReceipt, 
      });
      console.log('Purchase succesfully')
    }
  }

@hyochan I follow what you say, it seems this proccess is infinite, not returning anything. i dont even get the log.

Since many others use our modules these days, your case looks quite weird. It'd be hard for us to figure out unless we have a full working code of yours.

@hyochan Having the same issue like @ZeroCool00
Just upgraded from 2.3.26 to 2.4.0-beta3 (made an unlink and link), the same story.
Getting this in logs from device. Using real iPhone, development build via xCode (wire connected).

[IAPInfoManager]: Update operation failed, error: Error Domain=SSErrorDomain Code=109 "Cannot connect to iTunes Store" UserInfo={NSLocalizedDescription=Cannot connect to iTunes Store, SSErrorHTTPStatusCodeKey=401}

But pop-ups with purchase show up, with success story. But none reaction in Javascript Thread on it :(
Promise is not resolved or rejected in iOS module.

try {
      let purchase = false;

      console.log('BEFORE BUY');
      if (Platform.OS === 'ios') {
        purchase = await RNIap.buyProduct(selected);
      } else {
        purchase = await RNIap.buySubscription(selected);
      }
      console.log('AFTER BUY');

      await RNIap.finishTransaction();
      console.info('purchase >', purchase);
      setSubscription({type: selected, purchaseData: purchase});
    } catch (err) {
      console.log(err); // TODO add something went wrong
    }

AFTER BUY
Don't even shows up. The same story without async/await, with resolving .then promise.

Any ideas what might cause this problem?

Could you try 2.4.0-beta4?

@hyochan Thanks a lot 👍
Issue resolved on my side.

@IsaevTimur how did you solve it? its still not working.

@hyochan Here is the Full code of my inapp purchase module

import React, { Component } from 'react';
import { View, ImageBackground, TouchableOpacity, Image, Alert, 
  ActivityIndicator, Platform } from 'react-native';
import {inapp, btnBuy, purple} from '../helper/constants';
import ImageResizeMode from 'react-native/Libraries/Image/ImageResizeMode'
import { connect } from 'react-redux';
import { Icon } from 'native-base';
import { Actions } from 'react-native-router-flux';
import * as RNIap from 'react-native-iap';
import { getItems, getPurchase, fetchCategory } from '../action';

const itemSkus = Platform.select({
  ios: [
    'max_asl_unlimited_access'
  ],
  android: [
    'max_asl_unlimited_access'
  ]
});

class Banner extends Component {

  constructor(props){
    super(props);
    this.onBuyNowPress = this.onBuyNowPress.bind(this);
    this.forAndroid = this.forAndroid.bind(this);
    this.forIOS = this.forIOS.bind(this);
  }

  state = {
    loading: false,
  }

  async componentDidMount() {
    try {
      const result = await RNIap.initConnection();
      console.log('result', result);
      this.props.getItems();
    } catch (err) {
      console.warn(err.code, err.message);
    }
}

  componentDidUpdate(prevProps) {
    if(prevProps.purchase !== this.props.purchase) {
      this.props.fetchCategory();
    } 
  }

  onBuyNowPress() {
    this.setState({ loading: true });
    RNIap.getProducts(itemSkus).then(success => { 
      if(Platform.OS == "ios") {
        this.forIOS()
      } else {
        this.forAndroid()
      }
    }).catch(error => { 
      alert(error); 
      this.setState({ loading: false });
    })
  }

  async forIOS() {
    console.log('BannerCall');
    try {
      const purchase = await RNIap.buyProduct('max_asl_unlimited_access');
      console.log("BannerPurchase >>",purchase);
      if(purchase) {
        this.props.getPurchase();
        this.setState({
          loading: false,
        });
        console.log('Purchase succesfully')
      }
    } catch (err) {
      console.log("BannerError >> ", err);
    }
  }

  forAndroid() {
    RNIap.buyProduct('max_asl_unlimited_access').then(purchase => { 
      this.props.getPurchase();
      this.setState({
        loading: false,
        receipt: purchase.transactionReceipt, 
      });
      console.log('Purchase succesfully')
      Alert.alert("Purchase succesfully")
     }).catch(err => { 
       console.log(err.code, err.message);
        this.setState({ loading: false });
        if(err.message === "You already own this item.") {
          this.props.getPurchase();
          Alert.alert("You already own this product, we are restoring your purchase.")
        }
      }) 
  }

  componentWillUnmount() {
    RNIap.endConnection();
  }

  renderSpinner() {
    if(this.state.loading) {
      return (
        <ActivityIndicator size="large" color="#F7CD52" />
      )
    }
    return null
}

  render() {
    const { container, bannerStyle, btnContainer, iconClose } = styles;
    return (
      <View style={container}>
          <ImageBackground source={inapp} style={bannerStyle} resizeMode={ImageResizeMode.contain}>
              <Icon name="close" style={iconClose} type="FontAwesome" onPress={() => {Actions.pop()}}/>
              <View style={btnContainer}>
                {this.renderSpinner()}
                <TouchableOpacity onPress={() => this.onBuyNowPress()}>
                    <Image source={btnBuy}  />
                </TouchableOpacity>
              </View>
          </ImageBackground>
      </View>
    );
  }
}


const styles = {
  container: {
    flex: 1,  
  },
  iconClose: {
    color: '#FFF',
    fontSize: 30,
    alignSelf: 'flex-end',
    margin: 20,
    fontWeight: 'bold',
  },
  bannerStyle: {
    flex: 1,
    width: '100%',
    height: '100%',
    backgroundColor: purple
  }, 
  btnBuy: {
    marginRight: 20,
    marginTop: 160,
    height: 85,
    width: 215,
  },
  btnContainer: {
    flex: 1,
    marginTop: 50,
    justifyContent: 'center',
    alignItems: 'center'
  }
};

function mapStateToProps({ purchase }) {
    return { purchase };
}

export default connect(mapStateToProps, { getItems, getPurchase, fetchCategory })(Banner);

@ZeroCool00

Make sure that you are using - 2.4.0-beta4.

Also, make sure that you are using SANDBOX user (under development). Which can be configured in iTunes connect. These users created here - https://appstoreconnect.apple.com/access/users, under Sandbox section.

Hope it helps :)

@IsaevTimur
but my app store purchase process is working fine that meant everything is configured, and yes i m using 2.4.0-beta4.

here is my entry on package.json file

"react-native-iap": "^2.4.0-beta4",

@hyochan i finally solved the issue.. problem is when i first test i didnt write this line await RNIap.finishTransaction(); in .then() method. i added it afterward. that was the problem, solution is i need to clear transaction(await RNIap.clearTransaction();), and it work.

Thanks again for your support n for this great library.

@ZeroCool00 Congrat for success!! Yeah, those kinds of the problem should be solved better on your side because we need some traction on what've you've done wrong. Thanks for coming back again for those who might be suffering on the same thing.

Was this page helpful?
0 / 5 - 0 ratings