{availablePaymentMethods
->Array.mapWithIndex((pm, i) => {
})
->React.array}
let renderPMTOptions = () => {
- let commonClasses = "text-start border border-solid border-jp-gray-200 px-[20px] py-[10px] rounded mt-[10px] hover:bg-jp-gray-50"
+ let commonClasses = "flex flex-row items-center border border-solid border-jp-gray-200 px-5 py-2.5 rounded mt-2.5 hover:bg-jp-gray-50"
+ let buttonTextClasses = "text-start ml-2.5"
{switch selectedPaymentMethod {
| Some(Card) => React.null
| Some(BankTransfer) =>
- availablePaymentMethodTypes.bankTransfer
+ availablePaymentMethodTypes
+ ->Array.filterMap(pmt =>
+ switch pmt {
+ | BankTransfer(bank) => Some(bank)
+ | _ => None
+ }
+ )
->Array.mapWithIndex((pmt, i) =>
)
->React.array
| Some(Wallet) =>
- availablePaymentMethodTypes.wallet
+ availablePaymentMethodTypes
+ ->Array.filterMap(pmt =>
+ switch pmt {
+ | Wallet(wallet) => Some(wallet)
+ | _ => None
+ }
+ )
->Array.mapWithIndex((pmt, i) =>
)
->React.array
@@ -314,22 +459,142 @@ let make = (
-
-
{renderBackButton()}
-
{renderContentHeader()}
+ let renderJourneyScreen = () => {
+
+
+
{renderBackButton()}
+
{renderContentHeader()}
+
+
{renderContentSubHeader()}
+
+ {switch savedPMD {
+ | Some(pmd) => renderFinalizeScreen(pmd)
+ | None =>
+ switch selectedPaymentMethodType {
+ | Some(pmt) => renderInputs(pmt)
+ | None => renderPMTOptions()
+ }
+ }}
+
-
{renderContentSubHeader()}
-
- {switch savedPMD {
- | Some(pmd) => renderFinalizeScreen(pmd)
- | None =>
- switch selectedPaymentMethodType {
- | Some(pmt) => renderInputs(pmt)
- | None => renderPMTOptions()
+ }
+
+ let handleTabSelection = selectedPMT => {
+ if availablePaymentMethodTypes->Array.indexOf(selectedPMT) >= defaultOptionsLimitInTabLayout {
+ // Move the selected payment method at the last tab position
+ let ordList = availablePaymentMethodTypes->Array.reduceWithIndex([], (acc, pmt, i) => {
+ if i === defaultOptionsLimitInTabLayout - 1 {
+ acc->Array.push(selectedPMT)
+ } else if pmt !== selectedPMT {
+ acc->Array.push(pmt)
}
- }}
+ acc
+ })
+ setAvailablePaymentMethodTypesOrdered(_ => ordList)
+ }
+ setSelectedPaymentMethodType(_ => Some(selectedPMT))
+ }
+
+ let renderTabScreen = (~limit=defaultOptionsLimitInTabLayout) => {
+ let activeStyles: JsxDOM.style = {
+ borderColor: primaryTheme,
+ borderWidth: "2px",
+ color: primaryTheme,
+ }
+ let defaultStyles: JsxDOM.style = {
+ borderColor: "#9A9FA8",
+ borderWidth: "1px",
+ color: primaryTheme,
+ }
+ // tabs
+
+
+ {
+ let hiddenTabs = availablePaymentMethodTypesOrdered->Array.reduceWithIndex([], (
+ options,
+ pmt,
+ i,
+ ) => {
+ if i >= limit {
+ options->Array.push(
+
,
+ )
+ }
+ options
+ })
+ let visibleTabs = availablePaymentMethodTypesOrdered->Array.reduceWithIndex([], (
+ items,
+ pmt,
+ i,
+ ) => {
+ if i < limit {
+ items->Array.push(
+
Int.toString}
+ onClick={_ => setSelectedPaymentMethodType(_ => Some(pmt))}
+ className="flex w-full items-center rounded border border-solid border-jp-gray-700 px-2.5 py-1.5 mr-2.5 cursor-pointer hover:bg-jp-gray-50"
+ style={selectedPaymentMethodType === Some(pmt) ? activeStyles : defaultStyles}>
+ {pmt->getPaymentMethodTypeIcon}
+
{React.string(pmt->getPaymentMethodTypeLabel)}
+
,
+ )
+ }
+ items
+ })
+ switch savedPMD {
+ | Some(pmd) => renderFinalizeScreen(pmd)
+ | None =>
+
+
+ {visibleTabs->React.array}
+ {
Array.length > limit}>
+
+
+
+
+ }
+
+
+ {switch selectedPaymentMethodType {
+ | Some(pmt) => renderInputs(pmt)
+ | None => React.null
+ }}
+
+
+ }
+ }
+
+ }
+
+
+ {switch formLayout {
+ | Journey => renderJourneyScreen()
+ | Tabs => renderTabScreen()
+ }}
}
let default = make
diff --git a/src/Components/InputField.res b/src/Components/InputField.res
index fc741d969..22da6e237 100644
--- a/src/Components/InputField.res
+++ b/src/Components/InputField.res
@@ -11,6 +11,7 @@ let make = (
~onFocus=?,
~rightIcon=React.null,
~errorString=?,
+ ~errorStringClasses=?,
~fieldName="",
~type_="text",
~paymentType: CardThemeType.mode,
@@ -142,12 +143,15 @@ let make = (
/>
{rightIcon}
- {switch errorString {
- | Some(val) =>
-
String.length > 0}>
- {React.string(val)}
-
- | None => React.null
- }}
+ {
+ let errorClases = errorStringClasses->Option.getOr("")
+ switch errorString {
+ | Some(val) =>
+
String.length > 0}>
+ {React.string(val)}
+
+ | None => React.null
+ }
+ }
}
diff --git a/src/PaymentMethodCollectElement.res b/src/PaymentMethodCollectElement.res
index ef114178e..b2037de00 100644
--- a/src/PaymentMethodCollectElement.res
+++ b/src/PaymentMethodCollectElement.res
@@ -4,6 +4,7 @@ open RecoilAtoms
@react.component
let make = (~integrateError, ~logger) => {
+ let {themeObj} = Recoil.useRecoilValueFromAtom(configAtom)
let keys = Recoil.useRecoilValueFromAtom(keys)
let options = Recoil.useRecoilValueFromAtom(paymentMethodCollectOptionAtom)
@@ -14,118 +15,48 @@ let make = (~integrateError, ~logger) => {
let (availablePaymentMethodTypes, setAvailablePaymentMethodTypes) = React.useState(_ =>
defaultAvailablePaymentMethodTypes
)
- let (amount, setAmount) = React.useState(_ => options.amount)
- let (currency, setCurrency) = React.useState(_ => options.currency)
- let (flow, setFlow) = React.useState(_ => options.flow)
let (loader, setLoader) = React.useState(_ => false)
- let (returnUrl, setReturnUrl) = React.useState(_ => options.returnUrl)
let (secondsUntilRedirect, setSecondsUntilRedirect) = React.useState(_ => None)
- let (sessionExpiry, setSessionExpiry) = React.useState(_ => options.sessionExpiry)
let (showStatus, setShowStatus) = React.useState(_ => false)
let (statusInfo, setStatusInfo) = React.useState(_ => defaultStatusInfo)
- let (payoutId, setPayoutId) = React.useState(_ => options.payoutId)
- let (merchantLogo, setMerchantLogo) = React.useState(_ => options.logo)
- let (merchantName, setMerchantName) = React.useState(_ => options.collectorName)
- let (merchantTheme, setMerchantTheme) = React.useState(_ => options.theme)
// Form a list of available payment methods
React.useEffect(() => {
- let availablePMT = {
- card: [],
- bankTransfer: [],
- wallet: [],
- }
+ let availablePM: array
= []
+ let availablePMT: array = []
let _ = options.enabledPaymentMethods->Array.map(pm => {
switch pm {
- | Card(cardType) =>
- if !(availablePMT.card->Array.includes(cardType)) {
- availablePMT.card->Array.push(cardType)
+ | Card(_) =>
+ if !(availablePM->Array.includes(Card)) {
+ availablePMT->Array.push(Card(Debit))
+ availablePM->Array.push(Card)
+ }
+ | BankTransfer(_) =>
+ if !(availablePM->Array.includes(BankTransfer)) {
+ availablePM->Array.push(BankTransfer)
+ }
+ if !(availablePMT->Array.includes(pm)) {
+ availablePMT->Array.push(pm)
}
- | BankTransfer(bankTransferType) =>
- if !(availablePMT.bankTransfer->Array.includes(bankTransferType)) {
- availablePMT.bankTransfer->Array.push(bankTransferType)
+ | Wallet(_) =>
+ if !(availablePM->Array.includes(Wallet)) {
+ availablePM->Array.push(Wallet)
}
- | Wallet(walletType) =>
- if !(availablePMT.wallet->Array.includes(walletType)) {
- availablePMT.wallet->Array.push(walletType)
+ if !(availablePMT->Array.includes(pm)) {
+ availablePMT->Array.push(pm)
}
}
})
- let availablePM: array = []
- if !(availablePM->Array.includes(BankTransfer)) && availablePMT.bankTransfer->Array.length > 0 {
- availablePM->Array.push(BankTransfer)
- }
- if !(availablePM->Array.includes(Card)) && availablePMT.card->Array.length > 0 {
- availablePM->Array.push(Card)
- }
- if !(availablePM->Array.includes(Wallet)) && availablePMT.wallet->Array.length > 0 {
- availablePM->Array.push(Wallet)
- }
-
setAvailablePaymentMethods(_ => availablePM)
setAvailablePaymentMethodTypes(_ => availablePMT)
None
}, [options.enabledPaymentMethods])
- // Update amount
- React.useEffect(() => {
- setAmount(_ => options.amount)
- None
- }, [options.amount])
-
- // Update currency
- React.useEffect(() => {
- setCurrency(_ => options.currency)
- None
- }, [options.currency])
-
- // Update flow
- React.useEffect(() => {
- setFlow(_ => options.flow)
- None
- }, [options.flow])
-
- // Update payoutId
- React.useEffect(() => {
- setPayoutId(_ => options.payoutId)
- None
- }, [options.payoutId])
-
- // Update merchant's name
- React.useEffect(() => {
- setMerchantName(_ => options.collectorName)
- None
- }, [options.collectorName])
-
- // Update merchant's logo
- React.useEffect(() => {
- setMerchantLogo(_ => options.logo)
- None
- }, [options.logo])
-
- // Update merchant's primary theme
- React.useEffect(() => {
- setMerchantTheme(_ => options.theme)
- None
- }, [options.theme])
-
- // Update returnUrl
- React.useEffect(() => {
- setReturnUrl(_ => options.returnUrl)
- None
- }, [options.returnUrl])
-
- // Update sessionExpiry
- React.useEffect(() => {
- setSessionExpiry(_ => options.sessionExpiry)
- None
- }, [options.sessionExpiry])
-
// Start a timer for redirecting to return_url
React.useEffect(() => {
- switch (returnUrl, showStatus) {
+ switch (options.returnUrl, showStatus) {
| (Some(returnUrl), true) => {
setSecondsUntilRedirect(_ => Some(5))
// Start a interval to update redirect text every second
@@ -143,7 +74,7 @@ let make = (~integrateError, ~logger) => {
clearInterval(interval)
// Append query params and redirect
let url = PaymentHelpers.urlSearch(returnUrl)
- url.searchParams.set("payout_id", payoutId)
+ url.searchParams.set("payout_id", options.payoutId)
url.searchParams.set("status", statusInfo.status->getPayoutStatusString)
Utils.openUrl(url.href)
}, 5010)->ignore
@@ -155,12 +86,13 @@ let make = (~integrateError, ~logger) => {
let handleSubmit = pmd => {
setLoader(_ => true)
+ let flow = options.flow
let pmdBody = flow->formBody(pmd)
switch flow {
| PayoutLinkInitiate => {
let endpoint = ApiEndpoint.getApiEndPoint()
- let uri = `${endpoint}/payouts/${payoutId}/confirm`
+ let uri = `${endpoint}/payouts/${options.payoutId}/confirm`
// Create payment method
open Promise
PaymentHelpers.confirmPayout(
@@ -187,7 +119,7 @@ let make = (~integrateError, ~logger) => {
}
| Some(ErrorResponse(err)) => {
let updatedStatusInfo = {
- payoutId,
+ payoutId: options.payoutId,
status: Failed,
message: "Failed to process your payout. Please check with your provider for more details.",
code: Some(err.code),
@@ -198,7 +130,7 @@ let make = (~integrateError, ~logger) => {
}
| None => {
let updatedStatusInfo = {
- payoutId,
+ payoutId: options.payoutId,
status: Failed,
message: "Failed to process your payout. Please check with your provider for more details.",
code: None,
@@ -213,7 +145,7 @@ let make = (~integrateError, ~logger) => {
->catch(err => {
Console.error2("CRITICAL - Payouts confirm failed with unknown error", err)
let updatedStatusInfo = {
- payoutId,
+ payoutId: options.payoutId,
status: Failed,
message: "Failed to process your payout. Please check with your provider for more details.",
code: None,
@@ -258,16 +190,17 @@ let make = (~integrateError, ~logger) => {
}
let renderCollectWidget = () =>
-
-
+
+
{loader
?
: {React.null}}
@@ -276,7 +209,7 @@ let make = (~integrateError, ~logger) => {
let status = statusInfo.status
let imageSource = getPayoutImageSource(status)
let readableStatus = getPayoutReadableStatus(status)
- let statusInfoFields: array
= [{key: "Ref Id", value: payoutId}]
+ let statusInfoFields: array = [{key: "Ref Id", value: options.payoutId}]
statusInfo.code
->Option.flatMap(code => {
@@ -297,28 +230,41 @@ let make = (~integrateError, ~logger) => {
})
->ignore
-
+
+ className="flex flex-col items-center rounded-lg max-w-[500px]
+ xs:shadow-lg">
-
{React.string(merchantName)}
-
+ className="flex flex-row justify-between items-center w-full px-10 py-5 border-b border-jp-gray-300">
+
{React.string(options.collectorName)}
+
-
-
{React.string(readableStatus)}
-
+
+
{React.string(readableStatus)}
+
{React.string(statusInfo.message)}
-
-
+
+
{statusInfoFields
->Array.mapWithIndex((info, i) => {
-
Int.toString} className={`flex flex-row items-center`}>
-
+
Int.toString} className={`flex flex-row items-center mb-0.5`}>
+
{React.string(info.key)}
-
+
{React.string(info.value)}
@@ -327,76 +273,88 @@ let make = (~integrateError, ~logger) => {
-
- {switch secondsUntilRedirect {
- | Some(seconds) =>
- React.string("Redirecting in " ++ seconds->Int.toString ++ " seconds ...")
- | None => React.null
- }}
-
+ {switch secondsUntilRedirect {
+ | Some(seconds) =>
+
+ {React.string("Redirecting in " ++ seconds->Int.toString ++ " seconds ...")}
+
+ | None => React.null
+ }}
}
if integrateError {
} else {
-
- {switch flow {
- | PayoutLinkInitiate =>
- if showStatus {
- renderPayoutStatus()
- } else {
-
- // Merchant's info
-
+
+ {
+ let merchantLogo = options.logo
+ let merchantName = options.collectorName
+ let merchantTheme = options.theme
+ switch options.flow {
+ | PayoutLinkInitiate =>
+ if showStatus {
+ renderPayoutStatus()
+ } else {
+ <>
+ // Merchant's info
-
-
- {React.string(`${currency} ${amount}`)}
-
-
-
-
-
- {React.string("Payout from ")}
- {React.string(merchantName)}
+ className="flex flex-col w-full h-max items-center p-6
+ lg:w-4/10 lg:px-12 lg:py-20 lg:h-screen lg:items-end"
+ style={backgroundColor: merchantTheme}>
+
+
+
+ {React.string(`${options.currency} ${options.amount}`)}
+
+
+
+
-
-
{React.string("Ref Id")}
-
- {React.string(payoutId)}
+
+
+ {React.string("Payout from ")}
+ {React.string(merchantName)}
+
+
{React.string("Ref Id")}
+
{React.string(options.payoutId)}
+
+
+
+ {React.string(`Link expires on: ${options.sessionExpiry}`)}
-
- {React.string(`Link expires on: ${sessionExpiry}`)}
+
+ // Collect widget
+ {renderCollectWidget()}
+ >
+ }
+
+ | PayoutMethodCollect =>
+ <>
+ // Merchant's info
+
+
+
+
+ {React.string(merchantName)}
// Collect widget
{renderCollectWidget()}
-
+ >
}
-
- | PayoutMethodCollect =>
-
- // Merchant's info
-
-
-
-
- {React.string(merchantName)}
-
-
-
- // Collect widget
- {renderCollectWidget()}
-
- }}
+ }
}
}
diff --git a/src/PaymentMethodCollectElementLazy.res b/src/PaymentMethodCollectElementLazy.res
deleted file mode 100644
index fe013f6ca..000000000
--- a/src/PaymentMethodCollectElementLazy.res
+++ /dev/null
@@ -1 +0,0 @@
-let make = React.lazy_(() => Js.import(PaymentMethodCollectElement.default))
diff --git a/src/Types/PaymentMethodCollectTypes.res b/src/Types/PaymentMethodCollectTypes.res
index fc10fcd7d..5f860e697 100644
--- a/src/Types/PaymentMethodCollectTypes.res
+++ b/src/Types/PaymentMethodCollectTypes.res
@@ -11,17 +11,13 @@ type paymentMethodType =
| BankTransfer(bankTransfer)
| Wallet(wallet)
-type paymentMethodTypes = {
- card: array
,
- bankTransfer: array,
- wallet: array,
-}
-
type paymentMethodDataField =
// Cards
| CardNumber
| CardExpDate
| CardHolderName
+ // Card meta
+ | CardBrand
// Banks
| ACHRoutingNumber
| ACHAccountNumber
@@ -46,6 +42,8 @@ type paymentMethodDataField =
type paymentMethodData = (paymentMethod, paymentMethodType, array<(paymentMethodDataField, string)>)
+type formLayout = Journey | Tabs
+
type paymentMethodCollectFlow = PayoutLinkInitiate | PayoutMethodCollect
type paymentMethodCollectOptions = {
@@ -61,6 +59,7 @@ type paymentMethodCollectOptions = {
currency: string,
flow: paymentMethodCollectFlow,
sessionExpiry: string,
+ formLayout: formLayout,
}
// API TYPES
@@ -139,6 +138,17 @@ let decodeFlow = (dict, defaultPaymentMethodCollectFlow) =>
| None => defaultPaymentMethodCollectFlow
}
+let decodeFormLayout = (dict, decodeFormLayout) =>
+ switch dict->Dict.get("formLayout") {
+ | Some(formLayout) =>
+ switch formLayout->JSON.Decode.string {
+ | Some("journey") => Journey
+ | Some("tabs") => Tabs
+ | _ => decodeFormLayout
+ }
+ | None => decodeFormLayout
+ }
+
let decodeCard = (cardType: string): option =>
switch cardType {
| "credit" => Some(Credit)
diff --git a/src/Utilities/PaymentMethodCollectUtils.res b/src/Utilities/PaymentMethodCollectUtils.res
index 2ab0df77e..734e00552 100644
--- a/src/Utilities/PaymentMethodCollectUtils.res
+++ b/src/Utilities/PaymentMethodCollectUtils.res
@@ -126,8 +126,8 @@ let getPaymentMethodTypeLabel = (paymentMethodType: paymentMethodType): string =
switch paymentMethodType {
| Card(cardType) =>
switch cardType {
- | Credit => "Credit"
- | Debit => "Debit"
+ | Credit
+ | Debit => "Card"
}
| BankTransfer(bankTransferType) =>
switch bankTransferType {
@@ -149,6 +149,7 @@ let getPaymentMethodDataFieldKey = (key: paymentMethodDataField): string =>
| CardNumber => "card.cardNumber"
| CardExpDate => "card.cardExp"
| CardHolderName => "card.cardHolder"
+ | CardBrand => "card.brand"
| ACHRoutingNumber => "ach.routing"
| ACHAccountNumber => "ach.account"
| ACHBankName => "ach.bankName"
@@ -182,20 +183,17 @@ let getPaymentMethodDataFieldLabel = (key: paymentMethodDataField): string =>
| SepaBic => "Bank Identifier Code (BIC)"
| PixId => "Pix ID"
| PixBankAccountNumber => "Bank Account Number"
-
| PaypalMail => "Email"
| PaypalMobNumber | VenmoMobNumber => "Phone Number"
-
| SepaCountryCode => "Country Code (Optional)"
-
| ACHBankName
| BacsBankName
| PixBankName
| SepaBankName => "Bank Name (Optional)"
-
| ACHBankCity
| BacsBankCity
| SepaBankCity => "Bank City (Optional)"
+ | CardBrand => "Misc."
}
let getPaymentMethodDataFieldPlaceholder = (key: paymentMethodDataField): string =>
@@ -212,33 +210,60 @@ let getPaymentMethodDataFieldPlaceholder = (key: paymentMethodDataField): string
| SepaCountryCode => "Country"
| PixId => "**** 3251"
| PixBankAccountNumber => "**** 1232"
-
| ACHBankName
| BacsBankName
| PixBankName
| SepaBankName => "Bank Name"
-
| ACHBankCity
| BacsBankCity
| SepaBankCity => "Bank City"
-
| PaypalMail => "Your Email"
| PaypalMobNumber | VenmoMobNumber => "Your Phone"
+ | CardBrand => "Misc."
}
let getPaymentMethodDataFieldMaxLength = (key: paymentMethodDataField): int =>
switch key {
- | CardNumber => 18
+ | CardNumber => 23
| CardExpDate => 7
| ACHRoutingNumber => 9
| ACHAccountNumber => 12
| BacsSortCode => 6
| BacsAccountNumber => 18
- | SepaIban => 34
| SepaBic => 8
+ | SepaIban => 34
| _ => 32
}
+let getPaymentMethodDataFieldCharacterPattern = (key: paymentMethodDataField): option =>
+ switch key {
+ | ACHAccountNumber => Some(%re("/^\d{1,17}$/"))
+ | ACHRoutingNumber => Some(%re("/^\d{1,9}$/"))
+ | BacsAccountNumber => Some(%re("/^\d{1,18}$/"))
+ | BacsSortCode => Some(%re("/^\d{1,6}$/"))
+ | CardHolderName => Some(%re("/^([a-zA-Z]| ){1,32}$/"))
+ | CardNumber => Some(%re("/^\d{1,18}$/"))
+ | PaypalMail => Some(%re("/^[a-zA-Z0-9._%+-]*[a-zA-Z0-9._%+-]*@[a-zA-Z0-9.-]*$/"))
+ | PaypalMobNumber => Some(%re("/^[0-9]{1,12}$/"))
+ | SepaBic => Some(%re("/^([A-Z0-9]| ){1,8}$/"))
+ | SepaIban => Some(%re("/^([A-Z0-9]| ){1,34}$/"))
+ | _ => None
+ }
+
+let getPaymentMethodDataFieldInputType = (key: paymentMethodDataField): string =>
+ switch key {
+ | ACHAccountNumber => "tel"
+ | ACHRoutingNumber => "tel"
+ | BacsAccountNumber => "tel"
+ | BacsSortCode => "tel"
+ | CardExpDate => "tel"
+ | CardNumber => "tel"
+ | PaypalMail => "email"
+ | PaypalMobNumber => "tel"
+ | VenmoMobNumber => "tel"
+ | _ => "text"
+ }
+
let getPayoutImageSource = (payoutStatus: payoutStatus): string => {
switch payoutStatus {
| Success => "https://live.hyperswitch.io/payment-link-assets/success.png"
@@ -308,7 +333,48 @@ let getPayoutStatusMessage = (payoutStatus: payoutStatus): string =>
| RequiresVendorAccountCreation => "Failed to process your payout. Please check with your provider for more details."
}
+let getPaymentMethodDataErrorString = (key: paymentMethodDataField, value): string => {
+ let len = value->String.length
+ let notEmptyAndComplete = len <= 0 || len === key->getPaymentMethodDataFieldMaxLength
+ switch (key, notEmptyAndComplete) {
+ | (CardNumber, _) => "Card number is invalid."
+ | (CardExpDate, false) => "Your card's expiration date is incomplete."
+ | (CardExpDate, true) => "Your card's expiration year is in the past."
+ | (ACHRoutingNumber, false) => "Routing number is invalid."
+ | _ => ""
+ }
+}
+
+let getPaymentMethodIcon = (paymentMethod: paymentMethod) =>
+ switch paymentMethod {
+ | Card =>
+ | BankTransfer =>
+ | Wallet =>
+ }
+
+let getBankTransferIcon = (bankTransfer: bankTransfer) =>
+ switch bankTransfer {
+ | ACH =>
+ | Bacs =>
+ | Sepa =>
+ }
+
+let getWalletIcon = (wallet: wallet) =>
+ switch wallet {
+ | Paypal =>
+ | Pix =>
+ | Venmo =>
+ }
+
+let getPaymentMethodTypeIcon = (paymentMethodType: paymentMethodType) =>
+ switch paymentMethodType {
+ | Card(_) => Card->getPaymentMethodIcon
+ | BankTransfer(b) => b->getBankTransferIcon
+ | Wallet(w) => w->getWalletIcon
+ }
+
// Defaults
+let defaultFormLayout: formLayout = Tabs
let defaultPaymentMethodCollectFlow: paymentMethodCollectFlow = PayoutLinkInitiate
let defaultAmount = "0.01"
let defaultCurrency = "EUR"
@@ -333,13 +399,11 @@ let defaultPaymentMethodCollectOptions = {
currency: defaultCurrency,
flow: defaultPaymentMethodCollectFlow,
sessionExpiry: "",
+ formLayout: defaultFormLayout,
}
+let defaultOptionsLimitInTabLayout = 2
let defaultAvailablePaymentMethods: array = []
-let defaultAvailablePaymentMethodTypes = {
- card: [],
- bankTransfer: [],
- wallet: [],
-}
+let defaultAvailablePaymentMethodTypes: array = []
let defaultSelectedPaymentMethod: option = None
let defaultSelectedPaymentMethodType: option = None
let defaultStatusInfo = {
@@ -366,6 +430,7 @@ let itemToObjMapper = (dict, logger) => {
"currency",
"flow",
"sessionExpiry",
+ "formLayout",
],
dict,
"options",
@@ -387,6 +452,7 @@ let itemToObjMapper = (dict, logger) => {
currency: getString(dict, "currency", defaultCurrency),
flow: dict->decodeFlow(defaultPaymentMethodCollectFlow),
sessionExpiry: getString(dict, "sessionExpiry", ""),
+ formLayout: dict->decodeFormLayout(defaultFormLayout),
}
}
@@ -599,8 +665,8 @@ let formBody = (flow: paymentMethodCollectFlow, paymentMethodData: paymentMethod
let split = value->String.split("/")
switch (split->Array.get(0), split->Array.get(1)) {
| (Some(month), Some(year)) => {
- pmdApiFields->Array.push(("card_exp_month", month))
- pmdApiFields->Array.push(("card_exp_year", year))
+ pmdApiFields->Array.push(("expiry_month", month))
+ pmdApiFields->Array.push(("expiry_year", `20${year}`))
}
| _ => ()
}
@@ -622,6 +688,9 @@ let formBody = (flow: paymentMethodCollectFlow, paymentMethodData: paymentMethod
// Wallets
| PaypalMail => pmdApiFields->Array.push(("email", value))
| PaypalMobNumber | VenmoMobNumber => pmdApiFields->Array.push(("telephone_number", value))
+
+ // Misc.
+ | CardBrand => pmdApiFields->Array.push(("card_brand", value))
}
})