web-dev-qa-db-fra.com

Lien ouvert natif React dans le navigateur et retour à l'application

J'ai développé une application en natif réactif qui devrait communiquer avec une passerelle pour les paiements, après avoir terminé le processus de paiement (succès ou échec), je dois montrer une alerte à l'utilisateur. À cet effet, j'ouvre un lien dans WebView et après cela, j'obtiens l'URL de retour avec onNavigationStateChange et affiche un message de réussite ou d'échec.

Mais, ce flux pour les problèmes de sécurité doit être effectué dans un navigateur de périphérique par défaut.

Code actuel:

const BASEURL = 'https://gatewayURL/?ID=';
let Token = null;
let paymentAccepted = null;
let paymentFactorId = null;

class Gateway extends PureComponent {
  static propTypes = {
    dispatch: PropTypes.func,
    navigation: PropTypes.any,
  }

  componentWillMount() {
    this.props.dispatch(getPaymentStatus());
  }


  _onLoad(webViewState) {
    let url = webViewState.url.toString();
    let isResponseValid = url.includes('backFromGateway');
    if(isResponseValid){
      if(this.props.checkedPaymentStatus != 'checked' ){
        setTimeout(() => {
          this.props.dispatch(setPaymentStatus('checked'));

          let splitedURL = url.split("/");
          paymentFactorId = splitedURL[splitedURL.length -2];
          if(splitedURL[splitedURL.length - 1] === '0'){
            paymentAccepted = true;
            this.props.dispatch(setGatewayResponse('done', paymentFactorId));
          }
          else {
            paymentAccepted = false;
            this.props.dispatch(setGatewayResponse('rejected', paymentFactorId));
          }


          this.props.navigation.navigate('BackFromGateway', { title: '' })
        }, 1000);
      }
    }
  }


  render() {
    const { addNewOrderGatewayToken, checkedPaymentStatus } = this.props;
    token = addNewOrderGatewayToken;
    let view = null;
    if(checkedPaymentStatus !== 'checked'){
      view =  <WebView onNavigationStateChange={this._onLoad.bind(this)} style={styles.container} source={{ uri: `${BASEURL}${token}`  }}/>
    }
    else{
      view = <View></View>
    }

    return (
      <View style={styles.container}>
        {view}
      </View>      
    );
  }
}

Une idée?
Merci

7
Morteza

Si vous pouvez effectuer des rappels à partir du site Web de la passerelle, je recommande d'utiliser un lien profond pour gérer le flux entre l'application et le navigateur. Fondamentalement, votre application ouvrira le site Web de la passerelle pour le paiement et, selon le résultat du paiement, le site Web rappellera l'application en utilisant son lien profond. L'application écoutera ensuite le lien, retirera les informations nécessaires et continuera à poursuivre.

Ce que vous devez faire, c'est:

Configurez un lien profond dans votre application. Vous devez suivre le guide du site officiel ( ici ) pour l'activer. Choisissez une URL aléatoire ici pour le lien, par exemple gatewaylistener

Définissez les rappels nécessaires de la passerelle vers votre application. Dans votre cas, puisque vous devez gérer un paiement réussi et un échec de paiement, vous pouvez ajouter 2 rappels, par ex. gatewaylistener://success?id={paymentId} et gatewaylistener://error?id={paymentId}

Enfin, vous devez écouter le navigateur Web depuis l'application. Une façon de le faire consiste à ajouter un écouteur directement à l'intérieur du composant ouvrant la passerelle.

// setup
componentDidMount() {
  Linking.getInitialURL().then((url) => {
    if (url) {
      this.handleOpenURL(url)
    }
  }).catch(err => {})
  Linking.addEventListener('url', this.handleOpenURL)
}

componentWillUnmount() {
  Linking.removeEventListener('url', this.handleOpenURL)
}

// open your gateway
async openGateWay = () => {
  const { addNewOrderGatewayToken } = this.props
  const url = `${BASEURL}${addNewOrderGatewayToken}`
  const canOpen = await Linking.canOpenURL(url)
  if (canOpen) {
    this.props.dispatch(setPaymentStatus('checked'))
    Linking.openURL(url)
  }
}

// handle gateway callbacks
handleOpenURL = (url) => {
  if (isSucceedPayment(url)) { // your condition
    // handle success payment
  } else {
    // handle failure
  }
}
10
blaz

À des fins d'authentification, en utilisant une redirection de liens profonds par exemple, vous pouvez utiliser un navigateur intégré avec onglets personnalisés Chrome de Android = et SafariViewController depuis iOS, vérifiez le composant InAppBrowser pour prendre en charge les deux plates-formes avec le même code ( La liaison est déjà utilisée en interne pour détecter la redirection de lien profond).

Comme vous pouvez le voir dans l'exemple de dossier, vous pouvez utiliser un lien profond personnalisé configuré à partir de votre application (AndroidManifest pour Android et Info.plist pour iOS) :

  getDeepLink (path = '') {
    const scheme = 'my-demo'
    const prefix = Platform.OS === 'Android' ? `${scheme}://demo/` : `${scheme}://`
    return prefix + path
  }

  async tryDeepLinking () {
    const redirectToURL = `https://proyecto26.github.io/react-native-inappbrowser/`
    const redirectUrl = this.getDeepLink('home')
    const url = `${redirectToURL}?redirect_url=${encodeURIComponent(redirectUrl)}`
    try {
      if (await InAppBrowser.isAvailable()) {
        const result = await InAppBrowser.openAuth(url, redirectUrl)
        await this.sleep(800)
        Alert.alert('Response', JSON.stringify(result))
      } else {
        // You can use Linking directly for iOS < 9
      }
    } catch (error) {
      Alert.alert('Something’s wrong with the app :(')
    }
  }
0
jdnichollsc