javascript React-native 在浏览器中打开链接并返回到应用程序
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/51259156/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
React-native open link in browser and return to app
提问by Morteza
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 WebViewand after that I get return's url with onNavigationStateChangeand show success or failure message.
我正在开发一个反应原生应用程序,它应该与支付网关进行通信,在完成支付过程(成功或失败)后,我需要向用户显示警报。为此,我打开一个链接,WebView然后我得到返回的 urlonNavigationStateChange并显示成功或失败的消息。
But, this flow for securityissues 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
任何的想法?
谢谢
回答by blaz
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, e.g. 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, e.g. 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. 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
}
}
回答by jdnichollsc
For authentication purposes, using a deep linking redirection for example, you can use an embedded browser with Chrome Custom Tabsfrom Android and SafariViewControllerfrom iOS, check the InAppBrowsercomponent to support both platforms with the same code (Linkingis already used internally to detect the deep link redirection).
认证的目的,例如使用深层链接重定向,您可以使用带有嵌入式浏览器Chrome的自定义选项卡,从Android和SafariViewController从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):
正如您从示例文件夹中看到的,您可以使用从您的应用程序配置的自定义深层链接(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 :(')
}
}

