简体   繁体   English

浏览器中的React-native打开链接并返回应用程序

[英]React-native open link in browser and return to app

I've developing an app in react-native that should communicate with a gateway for payments, after finishing the payment process (success or failure) I need to show an alert to user. 我正在开发一个应用本地的应用程序,应该与网关进行通信以进行付款,在完成付款流程(成功或失败)后,我需要向用户显示警报。 For this purpose, I open a link in WebView and after that I get return's url with onNavigationStateChange and show success or failure message. 为此,我在WebView打开一个链接,之后我通过onNavigationStateChange获取返回的url并显示成功或失败消息。

But, this flow for security issues must be done in a default device browser . 但是,此安全问题的流程必须在默认设备浏览器中完成

Current Code: 现行代码:

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

Any idea? 任何想法?
Thanks 谢谢

If you can make callbacks from the gateway website, then I recommend to use deep linking to handle flow between app and browser. 如果您可以从网关网站进行回调,那么我建议使用深层链接来处理应用和浏览器之间的流量。 Basically, your app will open the gateway website for payment, and depending on payment result, the website will make a callback to the app using its deep link. 基本上,您的应用程序将打开网关网站进行付款,根据付款结果,网站将使用其深层链接回复该应用程序。 App then will listen to the link, take out necessary information and continue to proceed. 应用程序然后将收听链接,取出必要的信息并继续进行。

What you need to do is: 你需要做的是:

Set up deep linking in your app. 在您的应用中设置深层链接。 You should follow the guide from official website ( here ) to enable it. 您应该按照官方网站( 此处 )的指南进行操作。 Let pick a random URL here for linking, eg gatewaylistener 我们在这里选择一个随机URL进行链接,例如gatewaylistener

Set the necessary callbacks from gateway to your app. 设置从网关到您的应用程序的必要回调。 In your case, since you need to handle successful payment and failed payment, you can add 2 callbacks, eg gatewaylistener://success?id={paymentId} and gatewaylistener://error?id={paymentId} 在您的情况下,由于您需要处理成功付款和付款失败,您可以添加2个回调,例如gatewaylistener://success?id={paymentId}gatewaylistener://error?id={paymentId}

Finally, you need to listen to web browser from the app. 最后,您需要从应用程序中收听Web浏览器。 One way to do that is add listener right inside the component opening the gateway. 一种方法是在打开网关的组件内添加侦听器。

// 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
  }
}

For authentication purposes, using a deep linking redirection for example, you can use an embedded browser with Chrome Custom Tabs from Android and SafariViewController from iOS, check the InAppBrowser component to support both platforms with the same code ( Linking is already used internally to detect the deep link redirection). 认证的目的,例如使用深层链接重定向,您可以使用来自Android和SafariViewController Chrome的自定义选项卡从iOS的嵌入式浏览器,检查InAppBrowser组件支持代码相同的两个平台( 链接已在内部用于检测深层链接重定向)。

As you can see from the example folder, you can use a custom deep link configured from your app (AndroidManifest for Android and Info.plist for iOS) : 从示例文件夹中可以看出,您可以使用从应用程序配置的自定义深层链接(适用于Android的AndroidManifest和适用于iOS的Info.plist)

  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 :(')
    }
  }

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM