diff --git a/public/icons/orca.svg b/public/icons/orca.svg
index 5cb955e11..e57670093 100644
--- a/public/icons/orca.svg
+++ b/public/icons/orca.svg
@@ -2543,4 +2543,8 @@ License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL
+
+
+
+
diff --git a/src/Components/DynamicFields.res b/src/Components/DynamicFields.res
index 60471082b..0d01e58d8 100644
--- a/src/Components/DynamicFields.res
+++ b/src/Components/DynamicFields.res
@@ -458,6 +458,7 @@ let make = (
>
| CryptoCurrencyNetworks =>
| DateOfBirth =>
+ | VpaId =>
| Email
| InfoElement
| Country
@@ -765,6 +766,7 @@ let make = (
| CryptoCurrencyNetworks
| DateOfBirth
| PhoneCountryCode
+ | VpaId
| None => React.null
}}
diff --git a/src/Components/VpaIdPaymentInput.res b/src/Components/VpaIdPaymentInput.res
new file mode 100644
index 000000000..275ed7dc5
--- /dev/null
+++ b/src/Components/VpaIdPaymentInput.res
@@ -0,0 +1,61 @@
+open RecoilAtoms
+open Utils
+
+@react.component
+let make = (~paymentType) => {
+ let {localeString} = Recoil.useRecoilValueFromAtom(configAtom)
+ let loggerState = Recoil.useRecoilValueFromAtom(loggerAtom)
+ let (vpaId, setVpaId) = Recoil.useLoggedRecoilState(userVpaId, "vpaId", loggerState)
+
+ let vpaIdRef = React.useRef(Nullable.null)
+
+ let changeVpaId = ev => {
+ let val: string = ReactEvent.Form.target(ev)["value"]
+ setVpaId(prev => {
+ value: val,
+ isValid: val->isVpaIdValid,
+ errorString: val->isVpaIdValid->Option.getOr(false) ? "" : prev.errorString,
+ })
+ }
+ let onBlur = ev => {
+ let val = ReactEvent.Focus.target(ev)["value"]
+ let isValid = val->isVpaIdValid
+ let errorString = switch isValid {
+ | Some(val) => val ? "" : localeString.vpaIdInvalidText
+ | None => ""
+ }
+
+ setVpaId(prev => {
+ ...prev,
+ isValid,
+ errorString,
+ })
+ }
+
+ let submitCallback = React.useCallback((ev: Window.event) => {
+ let json = ev.data->JSON.parseExn
+ let confirm = json->getDictFromJson->ConfirmType.itemToObjMapper
+ if confirm.doSubmit {
+ if vpaId.value == "" {
+ setVpaId(prev => {
+ ...prev,
+ errorString: localeString.vpaIdEmptyText,
+ })
+ }
+ }
+ }, [vpaId])
+ useSubmitPaymentData(submitCallback)
+
+
+}
diff --git a/src/LocaleStrings/ArabicLocale.res b/src/LocaleStrings/ArabicLocale.res
index 9700c718d..e86f2914f 100644
--- a/src/LocaleStrings/ArabicLocale.res
+++ b/src/LocaleStrings/ArabicLocale.res
@@ -85,4 +85,7 @@ let localeStrings: LocaleStringTypes.localeStrings = {
currencyNetwork: `شبكات العملات`,
expiryPlaceholder: `MM / YY`,
dateOfBirth: `تاريخ الميلاد`,
+ vpaIdLabel: `معرف VPA`,
+ vpaIdEmptyText: `لا يمكن أن يكون معرف Vpa فارغًا`,
+ vpaIdInvalidText: `معرف Vpa غير صالح`,
}
diff --git a/src/LocaleStrings/CatalanLocale.res b/src/LocaleStrings/CatalanLocale.res
index a5ff0d1c3..d5e3e21b1 100644
--- a/src/LocaleStrings/CatalanLocale.res
+++ b/src/LocaleStrings/CatalanLocale.res
@@ -85,4 +85,7 @@ let localeStrings: LocaleStringTypes.localeStrings = {
currencyNetwork: `Xarxes de Monedes`,
expiryPlaceholder: `MM / AA`,
dateOfBirth: `Data de naixement`,
+ vpaIdLabel: `Vpa Id`,
+ vpaIdEmptyText: `L'identificador de Vpa no pot estar buit`,
+ vpaIdInvalidText: `Identificador de VPA no vàlid`,
}
diff --git a/src/LocaleStrings/DeutschLocale.res b/src/LocaleStrings/DeutschLocale.res
index b3dbf8d85..aa3bf7b45 100644
--- a/src/LocaleStrings/DeutschLocale.res
+++ b/src/LocaleStrings/DeutschLocale.res
@@ -85,4 +85,7 @@ let localeStrings: LocaleStringTypes.localeStrings = {
currencyNetwork: `Währungsnetzwerke`,
expiryPlaceholder: `MM / JJ`,
dateOfBirth: `Geburtsdatum`,
+ vpaIdLabel: `Vpa-ID`,
+ vpaIdEmptyText: `Die VPA-ID darf nicht leer sein`,
+ vpaIdInvalidText: `Ungültige VPA-ID`,
}
diff --git a/src/LocaleStrings/DutchLocale.res b/src/LocaleStrings/DutchLocale.res
index 2021c3bca..44b55ea73 100644
--- a/src/LocaleStrings/DutchLocale.res
+++ b/src/LocaleStrings/DutchLocale.res
@@ -85,4 +85,7 @@ let localeStrings: LocaleStringTypes.localeStrings = {
currencyNetwork: `Valutanetwerken`,
expiryPlaceholder: `MM / JJ`,
dateOfBirth: `Geboortedatum`,
+ vpaIdLabel: `Vpa-id`,
+ vpaIdEmptyText: `Vpa-ID mag niet leeg zijn`,
+ vpaIdInvalidText: `Ongeldige Vpa-ID`,
}
diff --git a/src/LocaleStrings/EnglishGBLocale.res b/src/LocaleStrings/EnglishGBLocale.res
index fc7dae731..38f9b0d91 100644
--- a/src/LocaleStrings/EnglishGBLocale.res
+++ b/src/LocaleStrings/EnglishGBLocale.res
@@ -85,4 +85,7 @@ let localeStrings: LocaleStringTypes.localeStrings = {
currencyNetwork: `Currency Networks`,
expiryPlaceholder: `MM / YY`,
dateOfBirth: `Date of Birth`,
+ vpaIdLabel: `Vpa Id`,
+ vpaIdEmptyText: `Vpa Id cannot be empty`,
+ vpaIdInvalidText: `Invalid Vpa Id address`,
}
diff --git a/src/LocaleStrings/EnglishLocale.res b/src/LocaleStrings/EnglishLocale.res
index 71bd100a7..2ada38ccb 100644
--- a/src/LocaleStrings/EnglishLocale.res
+++ b/src/LocaleStrings/EnglishLocale.res
@@ -85,4 +85,7 @@ let localeStrings: LocaleStringTypes.localeStrings = {
currencyNetwork: `Currency Networks`,
expiryPlaceholder: `MM / YY`,
dateOfBirth: `Date of Birth`,
+ vpaIdLabel: "Vpa Id",
+ vpaIdEmptyText: "Vpa Id cannot be empty",
+ vpaIdInvalidText: "Invalid Vpa Id address",
}
diff --git a/src/LocaleStrings/FrenchBelgiumLocale.res b/src/LocaleStrings/FrenchBelgiumLocale.res
index 1d84d2d1b..50a979872 100644
--- a/src/LocaleStrings/FrenchBelgiumLocale.res
+++ b/src/LocaleStrings/FrenchBelgiumLocale.res
@@ -85,4 +85,7 @@ let localeStrings: LocaleStringTypes.localeStrings = {
currencyNetwork: `Réseaux Monétaires`,
expiryPlaceholder: `MM / AA`,
dateOfBirth: `Date de naissance`,
+ vpaIdLabel: `Identifiant Vpa`,
+ vpaIdEmptyText: `L'identifiant Vpa ne peut pas être vide`,
+ vpaIdInvalidText: `Identifiant Vpa invalide`,
}
diff --git a/src/LocaleStrings/FrenchLocale.res b/src/LocaleStrings/FrenchLocale.res
index cacfe3a13..6f477a411 100644
--- a/src/LocaleStrings/FrenchLocale.res
+++ b/src/LocaleStrings/FrenchLocale.res
@@ -85,4 +85,7 @@ let localeStrings: LocaleStringTypes.localeStrings = {
currencyNetwork: `Réseaux Monétaires`,
expiryPlaceholder: `MM / AA`,
dateOfBirth: `Date de naissance`,
+ vpaIdLabel: `Identifiant Vpa`,
+ vpaIdEmptyText: `L'identifiant Vpa ne peut pas être vide`,
+ vpaIdInvalidText: `Identifiant Vpa invalide`,
}
diff --git a/src/LocaleStrings/HebrewLocale.res b/src/LocaleStrings/HebrewLocale.res
index e6f2c94ac..a47571807 100644
--- a/src/LocaleStrings/HebrewLocale.res
+++ b/src/LocaleStrings/HebrewLocale.res
@@ -85,4 +85,7 @@ let localeStrings: LocaleStringTypes.localeStrings = {
currencyNetwork: `רשתות מטבעות`,
expiryPlaceholder: `MM / YY`,
dateOfBirth: `תאריך לידה`,
+ vpaIdLabel: `מזהה VPA`,
+ vpaIdEmptyText: `מזהה VPA לא יכול להיות ריק`,
+ vpaIdInvalidText: `מזהה VPA לא חוקי`,
}
diff --git a/src/LocaleStrings/ItalianLocale.res b/src/LocaleStrings/ItalianLocale.res
index 7f71fcd15..b0cd1a52a 100644
--- a/src/LocaleStrings/ItalianLocale.res
+++ b/src/LocaleStrings/ItalianLocale.res
@@ -85,4 +85,7 @@ let localeStrings: LocaleStringTypes.localeStrings = {
currencyNetwork: `Reti Valutarie`,
expiryPlaceholder: `MM / AA`,
dateOfBirth: `Data di nascita`,
+ vpaIdLabel: `Codice Vpa`,
+ vpaIdEmptyText: `L'ID Vpa non può essere vuoto`,
+ vpaIdInvalidText: `ID Vpa non valido`,
}
diff --git a/src/LocaleStrings/JapaneseLocale.res b/src/LocaleStrings/JapaneseLocale.res
index 6c6bb2c97..e6ef52df8 100644
--- a/src/LocaleStrings/JapaneseLocale.res
+++ b/src/LocaleStrings/JapaneseLocale.res
@@ -85,4 +85,7 @@ let localeStrings: LocaleStringTypes.localeStrings = {
currencyNetwork: `通貨ネットワーク`,
expiryPlaceholder: `MM / YY`,
dateOfBirth: `生年月日`,
+ vpaIdLabel: `VPA ID`,
+ vpaIdEmptyText: `VPA ID を空にすることはできません`,
+ vpaIdInvalidText: `無効な VPA ID`,
}
diff --git a/src/LocaleStrings/LocaleStringTypes.res b/src/LocaleStrings/LocaleStringTypes.res
index 7a9b90a2f..02959934b 100644
--- a/src/LocaleStrings/LocaleStringTypes.res
+++ b/src/LocaleStrings/LocaleStringTypes.res
@@ -76,4 +76,7 @@ type localeStrings = {
currencyNetwork: string,
expiryPlaceholder: string,
dateOfBirth: string,
+ vpaIdLabel: string,
+ vpaIdEmptyText: string,
+ vpaIdInvalidText: string,
}
diff --git a/src/LocaleStrings/PolishLocale.res b/src/LocaleStrings/PolishLocale.res
index 48d549f89..39265917d 100644
--- a/src/LocaleStrings/PolishLocale.res
+++ b/src/LocaleStrings/PolishLocale.res
@@ -85,4 +85,7 @@ let localeStrings: LocaleStringTypes.localeStrings = {
currencyNetwork: `Sieci Walutowe`,
expiryPlaceholder: `MM / RR`,
dateOfBirth: `Data urodzenia`,
+ vpaIdLabel: `Identyfikator Vpa`,
+ vpaIdEmptyText: `Identyfikator Vpa nie może być pusty`,
+ vpaIdInvalidText: `Nieprawidłowy identyfikator Vpa`,
}
diff --git a/src/LocaleStrings/PortugueseLocale.res b/src/LocaleStrings/PortugueseLocale.res
index dea76434f..24f343b89 100644
--- a/src/LocaleStrings/PortugueseLocale.res
+++ b/src/LocaleStrings/PortugueseLocale.res
@@ -85,4 +85,7 @@ let localeStrings: LocaleStringTypes.localeStrings = {
currencyNetwork: `Redes de Moeda`,
expiryPlaceholder: `MM / AA`,
dateOfBirth: `Data de nascimento`,
+ vpaIdLabel: `ID VPA`,
+ vpaIdEmptyText: `O ID Vpa não pode ficar vazio`,
+ vpaIdInvalidText: `ID Vpa inválido`,
}
diff --git a/src/LocaleStrings/RussianLocale.res b/src/LocaleStrings/RussianLocale.res
index dd1d77c1d..5969a7ad4 100644
--- a/src/LocaleStrings/RussianLocale.res
+++ b/src/LocaleStrings/RussianLocale.res
@@ -89,4 +89,7 @@ let localeStrings: LocaleStringTypes.localeStrings = {
currencyNetwork: `Валютные сети`,
expiryPlaceholder: `MM / ГГ`,
dateOfBirth: `Дата рождения`,
+ vpaIdLabel: `Идентификатор ВПА`,
+ vpaIdEmptyText: `Идентификатор VPA не может быть пустым.`,
+ vpaIdInvalidText: `Неверный идентификатор VPA`,
}
diff --git a/src/LocaleStrings/SpanishLocale.res b/src/LocaleStrings/SpanishLocale.res
index b94079bc0..8fd11f1be 100644
--- a/src/LocaleStrings/SpanishLocale.res
+++ b/src/LocaleStrings/SpanishLocale.res
@@ -85,4 +85,7 @@ let localeStrings: LocaleStringTypes.localeStrings = {
currencyNetwork: `Redes de Divisas`,
expiryPlaceholder: `MM / AA`,
dateOfBirth: `Fecha de nacimiento`,
+ vpaIdLabel: `Identificación de Vpa`,
+ vpaIdEmptyText: `El ID de Vpa no puede estar vacío`,
+ vpaIdInvalidText: `ID de Vpa no válido`,
}
diff --git a/src/LocaleStrings/SwedishLocale.res b/src/LocaleStrings/SwedishLocale.res
index 50f07e395..0cad17fc2 100644
--- a/src/LocaleStrings/SwedishLocale.res
+++ b/src/LocaleStrings/SwedishLocale.res
@@ -85,4 +85,7 @@ let localeStrings: LocaleStringTypes.localeStrings = {
currencyNetwork: `Valutanätverk`,
expiryPlaceholder: `MM / ÅÅ`,
dateOfBirth: `Födelsedatum`,
+ vpaIdLabel: `Vpa-id`,
+ vpaIdEmptyText: `Vpa-id får inte vara tomt`,
+ vpaIdInvalidText: `Ogiltigt Vpa-ID`,
}
diff --git a/src/Payments/PaymentMethodsRecord.res b/src/Payments/PaymentMethodsRecord.res
index 175032769..38aba1c0a 100644
--- a/src/Payments/PaymentMethodsRecord.res
+++ b/src/Payments/PaymentMethodsRecord.res
@@ -37,6 +37,7 @@ type paymentMethodsFields =
| ShippingAddressCountry(array)
| CryptoCurrencyNetworks
| DateOfBirth
+ | VpaId
let getPaymentMethodsFieldsOrder = paymentMethodField => {
switch paymentMethodField {
@@ -524,6 +525,13 @@ let paymentMethodsFields = [
displayName: "Mifinity",
miniIcon: None,
},
+ {
+ paymentMethodName: "upi_collect",
+ fields: [InfoElement],
+ icon: Some(icon("bhim_upi", ~size=19)),
+ displayName: "UPI Collect",
+ miniIcon: None,
+ },
]
type required_fields = {
@@ -560,6 +568,7 @@ let getPaymentMethodsFieldTypeFromString = (str, isBancontact) => {
| ("user_crypto_currency_network", _) => CryptoCurrencyNetworks
| ("user_date_of_birth", _) => DateOfBirth
| ("user_phone_number_country_code", _) => PhoneCountryCode
+ | ("user_vpa_id", _) => VpaId
| _ => None
}
}
@@ -637,6 +646,7 @@ let dynamicFieldsEnabledPaymentMethods = [
"local_bank_transfer_transfer",
"afterpay_clearpay",
"mifinity",
+ "upi_collect",
]
let getIsBillingField = requiredFieldType => {
diff --git a/src/Utilities/DynamicFieldsUtils.res b/src/Utilities/DynamicFieldsUtils.res
index ffeb3a9d6..16f5fe252 100644
--- a/src/Utilities/DynamicFieldsUtils.res
+++ b/src/Utilities/DynamicFieldsUtils.res
@@ -110,6 +110,7 @@ let useRequiredFieldsEmptyAndValid = (
~cvcNumber,
) => {
let email = Recoil.useRecoilValueFromAtom(userEmailAddress)
+ let vpaId = Recoil.useRecoilValueFromAtom(userVpaId)
let fullName = Recoil.useRecoilValueFromAtom(userFullName)
let billingName = Recoil.useRecoilValueFromAtom(userBillingName)
let line1 = Recoil.useRecoilValueFromAtom(userAddressline1)
@@ -165,6 +166,7 @@ let useRequiredFieldsEmptyAndValid = (
| Some(val) => val->Utils.checkIs18OrAbove
| None => false
}
+ | VpaId => vpaId.isValid->Option.getOr(false)
| _ => true
}
})
@@ -225,6 +227,7 @@ let useRequiredFieldsEmptyAndValid = (
dateOfBirth,
(
email,
+ vpaId,
line2.value,
selectedBank,
phone.value,
@@ -412,6 +415,7 @@ let useSetInitialRequiredFields = (
| ShippingAddressPincode
| ShippingAddressState
| ShippingAddressCountry(_)
+ | VpaId
| None => ()
}
})
@@ -430,6 +434,7 @@ let useRequiredFieldsBody = (
~setRequiredFieldsBody,
) => {
let email = Recoil.useRecoilValueFromAtom(userEmailAddress)
+ let vpaId = Recoil.useRecoilValueFromAtom(userVpaId)
let fullName = Recoil.useRecoilValueFromAtom(userFullName)
let billingName = Recoil.useRecoilValueFromAtom(userBillingName)
let line1 = Recoil.useRecoilValueFromAtom(userAddressline1)
@@ -488,6 +493,7 @@ let useRequiredFieldsBody = (
| None => ""
}
| CardCvc => cvcNumber
+ | VpaId => vpaId.value
| StateAndCity
| CountryAndPincode(_)
| SpecialField(_)
@@ -565,6 +571,7 @@ let useRequiredFieldsBody = (
}, (
fullName.value,
email.value,
+ vpaId.value,
line1.value,
line2.value,
city.value,
@@ -596,7 +603,8 @@ let isFieldTypeToRenderOutsideBilling = (fieldType: PaymentMethodsRecord.payment
| CardExpiryAndCvc
| CryptoCurrencyNetworks
| DateOfBirth
- | Currency(_) => true
+ | Currency(_)
+ | VpaId => true
| _ => false
}
}
diff --git a/src/Utilities/RecoilAtoms.res b/src/Utilities/RecoilAtoms.res
index 1e3dd1c7a..fbb1f79e9 100644
--- a/src/Utilities/RecoilAtoms.res
+++ b/src/Utilities/RecoilAtoms.res
@@ -63,6 +63,7 @@ let areRequiredFieldsValid = Recoil.atom("areRequiredFieldsValid", true)
let areRequiredFieldsEmpty = Recoil.atom("areRequiredFieldsEmpty", false)
let dateOfBirth = Recoil.atom("dateOfBirth", Nullable.null)
let userBillingName = Recoil.atom("userBillingName", defaultFieldValues)
+let userVpaId = Recoil.atom("userVpaId", defaultFieldValues)
type areOneClickWalletsRendered = {
isGooglePay: bool,
diff --git a/src/Utilities/Utils.res b/src/Utilities/Utils.res
index ecaafd04f..318e7a6bd 100644
--- a/src/Utilities/Utils.res
+++ b/src/Utilities/Utils.res
@@ -393,6 +393,15 @@ let isEmailValid = email => {
}
}
+let isVpaIdValid = vpaId => {
+ switch vpaId->String.match(
+ %re("/^[a-zA-Z0-9]([a-zA-Z0-9.-]{1,50})[a-zA-Z0-9]@[a-zA-Z0-9]{2,}$/"),
+ ) {
+ | Some(_match) => Some(true)
+ | None => vpaId->String.length > 0 ? Some(false) : None
+ }
+}
+
let checkEmailValid = (
email: RecoilAtomTypes.field,
fn: (RecoilAtomTypes.field => RecoilAtomTypes.field) => unit,