diff --git a/src/libs/actions/IOU.js b/src/libs/actions/IOU.js index 3422e54e76dd..9056210024bc 100644 --- a/src/libs/actions/IOU.js +++ b/src/libs/actions/IOU.js @@ -1,5 +1,4 @@ import Onyx from 'react-native-onyx'; -import {Linking} from 'react-native'; import _ from 'underscore'; import CONST from '../../CONST'; import ONYXKEYS from '../../ONYXKEYS'; @@ -7,6 +6,7 @@ import ROUTES from '../../ROUTES'; import * as API from '../API'; import {getSimplifiedIOUReport, fetchChatReportsByIDs, fetchIOUReportByIDAndUpdateChatReport} from './Report'; import Navigation from '../Navigation/Navigation'; +import asyncOpenURL from '../asyncOpenURL'; /** * @param {Object[]} requestParams @@ -196,7 +196,18 @@ function payIOUReport({ const payIOUPromise = paymentMethodType === CONST.IOU.PAYMENT_TYPE.EXPENSIFY ? API.PayWithWallet({reportID}) : API.PayIOU({reportID, paymentMethodType}); - payIOUPromise + + // Build the url for the user's platform of choice if they have + // selected something other than a manual settlement or Expensify Wallet e.g. Venmo or PayPal.me + let url; + if (paymentMethodType === CONST.IOU.PAYMENT_TYPE.PAYPAL_ME) { + url = buildPayPalPaymentUrl(amount, submitterPayPalMeAddress, currency); + } + if (paymentMethodType === CONST.IOU.PAYMENT_TYPE.VENMO) { + url = buildVenmoPaymentURL(amount, submitterPhoneNumber); + } + + asyncOpenURL(payIOUPromise .then((response) => { if (response.jsonCode !== 200) { throw new Error(response.message); @@ -209,20 +220,13 @@ function payIOUReport({ // iouReport being fetched here must be open, because only an open iouReoport can be paid. // Therefore, we should also sync the chatReport after fetching the iouReport. fetchIOUReportByIDAndUpdateChatReport(reportID, chatReportID); - - // Once we have successfully paid the IOU we will transfer the user to their platform of choice if they have - // selected something other than a manual settlement or Expensify Wallet e.g. Venmo or PayPal.me - if (paymentMethodType === CONST.IOU.PAYMENT_TYPE.PAYPAL_ME) { - Linking.openURL(buildPayPalPaymentUrl(amount, submitterPayPalMeAddress, currency)); - } else if (paymentMethodType === CONST.IOU.PAYMENT_TYPE.VENMO) { - Linking.openURL(buildVenmoPaymentURL(amount, submitterPhoneNumber)); - } }) .catch((error) => { console.error(`Error Paying iouReport: ${error}`); Onyx.merge(ONYXKEYS.IOU, {error: true}); }) - .finally(() => Onyx.merge(ONYXKEYS.IOU, {loading: false})); + .finally(() => Onyx.merge(ONYXKEYS.IOU, {loading: false})), + url); } export { diff --git a/src/libs/asyncOpenURL/index.js b/src/libs/asyncOpenURL/index.js new file mode 100644 index 000000000000..192a9c3cba07 --- /dev/null +++ b/src/libs/asyncOpenURL/index.js @@ -0,0 +1,11 @@ +import {Linking} from 'react-native'; + +export default function asyncOpenURL(promise, url) { + if (!url) { + return; + } + + promise.then(() => { + Linking.openURL(url); + }); +} diff --git a/src/libs/asyncOpenURL/index.website.js b/src/libs/asyncOpenURL/index.website.js new file mode 100644 index 000000000000..2ea074c8c5a2 --- /dev/null +++ b/src/libs/asyncOpenURL/index.website.js @@ -0,0 +1,28 @@ +import {Linking} from 'react-native'; + +/** + * Prevents Safari from blocking pop-up window when opened within async call. + * + * @param {Promise} promise + * @param {string} url + */ +export default function asyncOpenURL(promise, url) { + if (!url) { + return; + } + + const isSafari = /^((?!chrome|android).)*safari/i.test(navigator.userAgent); + + if (!isSafari) { + promise.then(() => { + Linking.openURL(url); + }); + } else { + const windowRef = window.open(); + promise + .then(() => { + windowRef.location = url; + }) + .catch(() => windowRef.close()); + } +}