【问题标题】:React-native open link in browser and return to appReact-native 在浏览器中打开链接并返回应用程序
【发布时间】:2018-12-17 22:35:03
【问题描述】:

我正在开发一个 react-native 应用程序,它应该与支付网关通信,在完成支付过程(成功或失败)后,我需要向用户显示警报。为此,我在 WebView 中打开一个链接,然后我得到返回的 url 为 onNavigationStateChange 并显示成功或失败消息。

但是,此安全问题流程必须在默认设备浏览器中完成。

当前代码:

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

有什么想法吗?
谢谢

【问题讨论】:

  • 我很不明白您在 webviews 安全问题背后的原因和含义是什么?有没有与此相关的文章? Webview 在移动设备上使用与 Chrome 相同的引擎,我看不出 Webview 在安全方面会受到怎样的影响。
  • @JimiPajala 我们本地商店只接受这种方式用于包含在线支付的应用程序。

标签: javascript reactjs react-native


【解决方案1】:

出于身份验证目的,例如使用深度链接重定向,您可以使用带有 Android 的 Chrome 自定义选项卡 和 iOS 的 SafariViewController 的嵌入式浏览器,请查看@987654321 @ 组件以使用相同的代码支持两个平台(Linking 已在内部用于检测深层链接重定向)。

从示例文件夹中可以看出,您可以使用从您的应用配置的自定义深层链接(AndroidManifest for Android 和 Info.plist for 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 :(')
    }
  }

【讨论】:

    【解决方案2】:

    如果您可以从网关网站进行回调,那么我建议使用深度链接来处理应用程序和浏览器之间的流量。基本上,您的应用会打开网关网站进行支付,根据支付结果,网站会使用其深层链接回调应用。然后应用程序将监听该链接,取出必要的信息并继续进行。

    你需要做的是:

    在您的应用中设置深层链接。您应该按照官方网站(here)的指南来启用它。让我们在这里选择一个随机 URL 进行链接,例如gatewaylistener

    设置从网关到您的应用的必要回调。在您的情况下,由于您需要处理成功付款和付款失败,您可以添加2个回调,例如gatewaylistener://success?id={paymentId}gatewaylistener://error?id={paymentId}

    最后,您需要从应用程序中收听网络浏览器。一种方法是在打开网关的组件内添加侦听器。

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

    【讨论】:

    • 感谢您的帮助,您说设置深层链接我们需要一个 URL 对吗?这个 url 可以在 Intent-filter 和 data 属性中指定吗?像这样? &lt;data android:scheme="http" android:host="www.example.com" android:pathPrefix="/gizmos" /&gt; 并将 gatewaylistener://success?id={paymentId} 放入此数据中?
    • 应该是&lt;data android:scheme="gatewaylistener" /&gt;,因为你要使用的方案不是http,而是gatewaylistener。我建议您查看一些很好的示例,例如 medium.com/react-native-training/… 以了解如何调用和设置深度链接。
    • 为什么我的方案不是http?我需要从浏览器监听 URL,如果用户重定向到该 URL,我的应用程序应该打开该屏幕并显示成功/失败消息。是对的还是我弄错了?现在,我将用户发送到浏览器进行付款,但完成付款后我的应用程序没有响应。
    • Scheme 的价值是让 Android 系统知道当一个 Web URI Intent 被调用时它可以做什么。您的应用不会监听来自浏览器的 URL,而是监听来自网关网站的回调。如果你操作正确,那么即使是像&lt;a href="gatewaylistener://success"&gt;Open app&lt;/a&gt; 这样的链接标签也可以毫无问题地打开你的应用程序。
    • 当然,scheme 可以是 http 或任何你想要的,但你必须先在你的应用程序中正确设置它,以确保系统知道在浏览器中调用 URI 时要做什么。使用非http scheme是区分app scheme和普通web scheme的常用方法。
    猜你喜欢
    • 2016-06-02
    • 1970-01-01
    • 1970-01-01
    • 2018-08-10
    • 2019-04-05
    • 2021-11-03
    • 1970-01-01
    • 2014-01-07
    • 1970-01-01
    相关资源
    最近更新 更多