React-native-iap: RNIap.getProducts no devuelve la promesa en ios

Creado en 19 dic. 2018  ·  24Comentarios  ·  Fuente: dooboolab/react-native-iap

Versión de react-native-iap

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

Versión de react-native

"react-native": "0.57.4",

Plataformas a las que se enfrentó el error (¿IOS o Android o ambos?)

IOS

Comportamiento esperado

buyProduct debe devolver la promesa (.then () no es una llamada),

Comportamiento real

buyProduct no devuelve ninguna promesa, en android funciona bien, .then () llama correctamente, pero en ios no.

Entorno probado (¿Emulador? ¿Dispositivo real?)

Dispositivo real

Pasos para reproducir el comportamiento

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 });
      })
  }

En ios ya compro el producto, así que de nuevo cuando presiono comprar ahora, aparece una ventana emergente como si ya hubiera comprado este producto. pero .then () o .catch () no reciben la llamada.

También probé el método getAvailablePurchases (), siempre devuelve []

📱 iOS 🙏 help wanted

Comentario más útil

¿Podrías probar 2.4.0-beta4 ?

Todos 24 comentarios

@LinusU Creo que @JJMoon tenía razón. He eliminado todos los async y el problema vuelve a aparecer. ¿Qué piensas? @ ZeroCool00 ¿ 2.3.24 por ahora?

@ ZeroCool00 En realidad, ¿podría probar 2.3.26 por nosotros?

@hyochan lo probaré pronto ... y te lo haré saber, y gracias por la rápida respuesta.

@hyochan probé con 2.3.26, ¿no funciona? ¿alguna solución?

@ ZeroCool00 Entonces debe ser un problema de vinculación. Debería intentar unlink y volver a link .

@hyochan lo intenté, incluso desvincular y luego desinstalar y luego instalar de nuevo, y vincular de nuevo. pero aun no funciona

@ ZeroCool00 Si está en la ventana, el script de enlace nativo de reacción es aún más inestable. ¿Lo intentaste manualmente? También intente 2.3.24 también. Creo que estás enfrentando algún problema de configuración.

@hyochan estoy en mac, y me desvinculo y luego desinstalo y luego instalo 2.3.24, y hago la configuración manual, siga cada paso, funciona con Android, en iOS todavía no se muestra. el proceso está funcionando bien. Recibo una ventana emergente y el producto también se compra, pero no hay promesa de devolución.

¿Existe alguna otra configuración para ios? Estoy atrapado aquí, ¿hay alguna otra forma de obtener que ya compré?

@JJMoon ¿Podrías ayudar a @ ZeroCool00 ?

@ ZeroCool00 También intente eliminar Alert y use console para probar en su lugar. Porque ios genera automáticamente Alert nativo cuando se procesa la compra, lo que puede interrumpir su código.

@hyochan Plz reabrir esto ... lo intenté todo ... también elimino Alert. incluso dejo de depurar y comprobar ... simplemente no funciona. Quería publicar mi aplicación, pero estoy atrapado aquí. Incluso probé esta lib https://github.com/chirag04/react-native-in-app-utils

esta lib también tiene el mismo problema ... el proceso de compra funciona bien pero no obtiene ninguna promesa.

¿Existe algún método de ciclo de vida donde obtengo una devolución de llamada de evento? Solo quiero devolución de llamada de evento donde pueda llamar a la API del servidor.

@ ZeroCool00 ¿Podría intentar usar async y await también? También estoy usando esto en nuestra aplicación y no enfrentamos este problema.

@hyochan , ¿puede proporcionarnos su demostración? ¿Cómo la está utilizando? Sería de gran ayuda.

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 sigo lo que dices, parece que este proceso es infinito, no devuelve nada. Ni siquiera recibo el registro.

Dado que muchos otros usan nuestros módulos en estos días, su caso parece bastante extraño. Sería difícil para nosotros averiguarlo a menos que tengamos un código de trabajo completo suyo.

@hyochan Tiene el mismo problema que @ ZeroCool00
Acabo de actualizar de 2.3.26 a 2.4.0-beta3 (hizo una desvinculación y enlace), la misma historia.
Obteniendo esto en los registros del dispositivo. Usando iPhone real, desarrollo de compilación a través de xCode (conectado por cable).

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

Pero aparecen ventanas emergentes con compra, con historia de éxito. Pero ninguna reacción en el hilo de Javascript :(
La promesa no se resuelve o rechaza en el módulo de iOS.

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
Ni siquiera aparece. La misma historia sin async / await, con la resolución .then promise.

¿Alguna idea de qué podría causar este problema?

¿Podrías probar 2.4.0-beta4 ?

@hyochan Muchas gracias 👍
Problema resuelto por mi parte.

@IsaevTimur ¿cómo lo

@hyochan Aquí está el código completo de mi módulo de compra inapp

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

Asegúrese de que está utilizando - 2.4.0-beta4.

Además, asegúrese de que está utilizando el usuario de SANDBOX (en desarrollo). Que se puede configurar en iTunes Connect. Estos usuarios se crearon aquí: https://appstoreconnect.apple.com/access/users , en la sección Sandbox.

Espero eso ayude :)

@IsaevTimur
pero el proceso de compra de mi tienda de aplicaciones funciona bien, lo que significa que todo está configurado, y sí, estoy usando 2.4.0-beta4.

aquí está mi entrada en el archivo package.json

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

@hyochan finalmente resolví el problema ... el problema es que cuando await RNIap.finishTransaction(); en el método .then (). lo agregué después. ese era el problema, la solución es que necesito borrar la transacción ( await RNIap.clearTransaction(); ), y funciona.

Gracias de nuevo por su apoyo para esta gran biblioteca.

@ ZeroCool00 ¡¡ Felicitaciones por el éxito !! Sí, ese tipo de problemas deberían resolverse mejor de tu lado porque necesitamos algo de tracción sobre lo que has hecho mal. Gracias por regresar de nuevo para aquellos que podrían estar sufriendo lo mismo.

¿Fue útil esta página
0 / 5 - 0 calificaciones

Temas relacionados

safciplak picture safciplak  ·  3Comentarios

jvandenaardweg picture jvandenaardweg  ·  4Comentarios

bakedbean picture bakedbean  ·  5Comentarios

coldfins picture coldfins  ·  3Comentarios

ramondelmondo picture ramondelmondo  ·  4Comentarios