Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add samsung pay payment method support for cybersource #1650

Open
wants to merge 26 commits into from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
70079f1
Merge branch 'main' of github.com:juspay/hyperswitch-control-center
JeevaRamu0104 Sep 18, 2024
780a799
Merge branch 'main' of github.com:juspay/hyperswitch-control-center
JeevaRamu0104 Sep 19, 2024
24ac760
Merge branch 'main' of github.com:juspay/hyperswitch-control-center
JeevaRamu0104 Sep 24, 2024
2883deb
Merge branch 'main' of github.com:juspay/hyperswitch-control-center
JeevaRamu0104 Sep 25, 2024
047c6c5
Merge branch 'main' of github.com:juspay/hyperswitch-control-center
JeevaRamu0104 Sep 25, 2024
0365e91
Merge branch 'main' of github.com:juspay/hyperswitch-control-center
JeevaRamu0104 Sep 25, 2024
5eeb7af
Merge branch 'main' of github.com:juspay/hyperswitch-control-center
JeevaRamu0104 Sep 26, 2024
7ff97cf
Merge branch 'main' of github.com:juspay/hyperswitch-control-center
JeevaRamu0104 Sep 27, 2024
b594e3f
Merge branch 'main' of github.com:juspay/hyperswitch-control-center
JeevaRamu0104 Oct 1, 2024
639886c
Merge branch 'main' of github.com:juspay/hyperswitch-control-center
JeevaRamu0104 Oct 1, 2024
8c4fb4e
Merge branch 'main' of github.com:juspay/hyperswitch-control-center
JeevaRamu0104 Oct 1, 2024
789553d
Merge branch 'main' of github.com:juspay/hyperswitch-control-center
JeevaRamu0104 Oct 2, 2024
451a667
Merge branch 'main' of github.com:juspay/hyperswitch-control-center
JeevaRamu0104 Oct 3, 2024
6bff9ac
Merge branch 'main' of github.com:juspay/hyperswitch-control-center
JeevaRamu0104 Oct 4, 2024
cecb863
Merge branch 'main' of github.com:juspay/hyperswitch-control-center
JeevaRamu0104 Oct 9, 2024
5d9f00f
Merge branch 'main' of github.com:juspay/hyperswitch-control-center
JeevaRamu0104 Oct 10, 2024
6909aca
Merge branch 'main' of github.com:juspay/hyperswitch-control-center
JeevaRamu0104 Oct 11, 2024
dc16caf
Merge branch 'main' of github.com:juspay/hyperswitch-control-center
JeevaRamu0104 Oct 16, 2024
ee3b5ae
Merge branch 'main' of github.com:juspay/hyperswitch-control-center
JeevaRamu0104 Oct 22, 2024
bfe5183
Merge branch 'main' of github.com:juspay/hyperswitch-control-center
JeevaRamu0104 Oct 23, 2024
933a405
chore: wasm changes for samsung pay
JeevaRamu0104 Oct 24, 2024
c0759f8
chore: resolve comments
JeevaRamu0104 Oct 24, 2024
c5c9ed2
Merge branch 'main' into add-samsung-pay-payment-method-support-for-c…
JeevaRamu0104 Oct 24, 2024
907cc12
chore: resolve comments
JeevaRamu0104 Oct 24, 2024
6bb3b5b
chore: address comments
JeevaRamu0104 Oct 28, 2024
61a793e
Merge branch 'add-samsung-pay-payment-method-support-for-cybersource'…
JeevaRamu0104 Oct 28, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions src/screens/Connectors/Common/CommonConnectorUtils.res
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ let inputTypeMapperr = ipType => {
| "Toggle" => Toggle
| "Select" => Select
| "MultiSelect" => MultiSelect
| "Radio" => Radio
| _ => Text
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,142 @@
@react.component
let make = (~connector, ~setShowWalletConfigurationModal, ~update, ~onCloseClickCustomFun) => {
open APIUtils
open LogicUtils
open SamsungPayIntegrationUtils
let getURL = useGetURL()
let fetchDetails = useGetMethod()
let (merchantBusinessCountry, setMerchantBusinessCountry) = React.useState(_ => [])
let (screenState, setScreenState) = React.useState(_ => PageLoaderWrapper.Success)
let formState: ReactFinalForm.formState = ReactFinalForm.useFormState(
ReactFinalForm.useFormSubscription(["values"])->Nullable.make,
)
let form = ReactFinalForm.useForm()
let {globalUIConfig: {font: {textColor}}} = React.useContext(ThemeProvider.themeContext)
let samsungPayFields = React.useMemo(() => {
try {
if connector->isNonEmptyString {
let samsungPayInputFields =
Window.getConnectorConfig(connector)
->getDictFromJsonObject
->getDictfromDict("connector_wallets_details")
->getArrayFromDict("samsung_pay", [])

samsungPayInputFields
} else {
[]
}
} catch {
| Exn.Error(e) => {
Js.log2("FAILED TO LOAD CONNECTOR CONFIG", e)
[]
}
}
}, [connector])

let setSamsungFormData = () => {
let initalFormValue =
formState.values
->getDictFromJsonObject
->getDictfromDict("connector_wallets_details")
->getDictfromDict("samsung_pay")
->getDictfromDict("merchant_credentials")

form.change(
"connector_wallets_details.samsung_pay.merchant_credentials",
initalFormValue->samsungPayRequest->Identity.genericTypeToJson,
)
}

let getProcessorDetails = async () => {
try {
setScreenState(_ => Loading)
let paymentMethoConfigUrl = getURL(~entityName=PAYMENT_METHOD_CONFIG, ~methodType=Get)
let res = await fetchDetails(
`${paymentMethoConfigUrl}?connector=${connector}&paymentMethodType=samsung_pay`,
)
let countries =
res
->getDictFromJsonObject
->getArrayFromDict("countries", [])
->Array.map(item => {
let dict = item->getDictFromJsonObject
let countryList: SelectBox.dropdownOption = {
label: dict->getString("name", ""),
value: dict->getString("code", ""),
}
countryList
})

setMerchantBusinessCountry(_ => countries)
setSamsungFormData()
setScreenState(_ => Success)
} catch {
| _ => setScreenState(_ => Success)
}
}

React.useEffect(() => {
if connector->LogicUtils.isNonEmptyString {
getProcessorDetails()->ignore
}
None
}, [connector])
let onSubmit = () => {
update()
setShowWalletConfigurationModal(_ => false)
}

let onCancel = () => {
onCloseClickCustomFun()
setShowWalletConfigurationModal(_ => false)
}
let samsungPayFields =
samsungPayFields
->Array.mapWithIndex((field, index) => {
let samsungPayField = field->convertMapObjectToDict->CommonConnectorUtils.inputFieldMapper
let {name} = samsungPayField
<div key={index->Int.toString}>
{switch name {
| "merchant_business_country" =>
<FormRenderer.FieldRenderer
labelClass="font-semibold !text-hyperswitch_black"
field={CommonConnectorHelper.selectInput(
~field={samsungPayField},
~opt={Some(merchantBusinessCountry)},
~formName={
samsungPayNameMapper(~name="merchant_business_country")
},
)}
/>
| _ =>
<FormRenderer.FieldRenderer
labelClass="font-semibold !text-hyperswitch_black"
field={samsungPayValueInput(~samsungPayField, ~fill=textColor.primaryNormal)}
/>
}}
</div>
})
->React.array
<PageLoaderWrapper
screenState={screenState}
customLoader={<div className="mt-60 w-scrren flex flex-col justify-center items-center">
<div className={`animate-spin mb-1`}>
<Icon name="spinner" size=20 />
</div>
</div>}
sectionHeight="!h-screen">
<div className="p-2">
{samsungPayFields}
<div className={`flex gap-2 justify-end m-2 p-6`}>
<Button text="Cancel" buttonType={Secondary} onClick={_ => onCancel()} />
<Button
onClick={_ => onSubmit()}
text="Continue"
buttonType={Primary}
buttonState={formState.values->SamsungPayIntegrationUtils.validateSamsungPay}
/>
</div>
</div>
<FormValuesSpy />
</PageLoaderWrapper>
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
type samsungPay = {
merchant_business_country: string,
merchant_display_name: string,
service_id: string,
allowed_brands: array<string>,
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
open SamsungPayIntegrationTypes
open LogicUtils

let samsungPayRequest = dict => {
merchant_business_country: dict->getString("merchant_business_country", ""),
merchant_display_name: dict->getString("merchant_display_name", ""),
service_id: dict->getString("service_id", ""),
allowed_brands: dict->getStrArrayFromDict(
"allowed_brands",
["visa", "masterCard", "amex", "discover"],
),
}

let samsungPayNameMapper = (~name) => {
`connector_wallets_details.samsung_pay.merchant_credentials.${name}`
}

let samsungPayValueInput = (~samsungPayField: CommonConnectorTypes.inputField, ~fill) => {
open CommonConnectorHelper
let {\"type", name} = samsungPayField
let formName = samsungPayNameMapper(~name)

{
switch \"type" {
| Text => textInput(~field={samsungPayField}, ~formName)
| Select => selectInput(~field={samsungPayField}, ~formName)
| MultiSelect => multiSelectInput(~field={samsungPayField}, ~formName)
| Radio => radioInput(~field={samsungPayField}, ~formName, ~fill, ())
| _ => textInput(~field={samsungPayField}, ~formName)
}
}
}

let validateSamsungPay = (json: JSON.t) => {
let {merchant_business_country, merchant_display_name, service_id, allowed_brands} =
getDictFromJsonObject(json)
->getDictfromDict("connector_wallets_details")
->getDictfromDict("samsung_pay")
->getDictfromDict("merchant_credentials")
->samsungPayRequest
merchant_business_country->isNonEmptyString &&
merchant_display_name->isNonEmptyString &&
service_id->isNonEmptyString &&
allowed_brands->Array.length > 0
? Button.Normal
: Button.Disabled
}
9 changes: 5 additions & 4 deletions src/screens/Connectors/ConnectorPaymentMethod.res
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ let make = (

let mixpanelEventName = isUpdateFlow ? "processor_step2_onUpdate" : "processor_step2"

let onSubmit = async () => {
let onSubmit = async (values, _form: ReactFinalForm.formApi) => {
mixpanelEvent(~eventName=mixpanelEventName)
try {
setScreenState(_ => Loading)
Expand All @@ -66,7 +66,7 @@ let make = (
metadata: metaData,
}
let body =
constructConnectorRequestBody(obj, initialValues)->ignoreFields(
constructConnectorRequestBody(obj, values)->ignoreFields(
connectorID->Option.getOr(""),
connectorIgnoredField,
)
Expand Down Expand Up @@ -98,10 +98,11 @@ let make = (
}
}
}
Nullable.null
}

<PageLoaderWrapper screenState>
<Form initialValues={initialValues}>
<Form onSubmit initialValues={initialValues}>
<div className="flex flex-col">
<div className="flex justify-between border-b p-2 md:px-10 md:py-6">
<div className="flex gap-2 items-center">
Expand All @@ -111,7 +112,7 @@ let make = (
</h2>
</div>
<div className="self-center">
<Button text="Proceed" buttonType={Primary} onClick={_ => onSubmit()->ignore} />
<FormRenderer.SubmitButton text="Proceed" />
</div>
</div>
<div className="grid grid-cols-4 flex-1 p-2 md:p-10">
Expand Down
1 change: 1 addition & 0 deletions src/screens/Connectors/ConnectorTypes.res
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,7 @@ type paymentMethodTypes =
| Debit
| GooglePay
| ApplePay
| SamsungPay
| PayPal
| BankDebit
| OpenBankingPIS
Expand Down
20 changes: 16 additions & 4 deletions src/screens/Connectors/ConnectorUIUtils/PaymentMethod.res
Original file line number Diff line number Diff line change
Expand Up @@ -36,8 +36,12 @@ module CardRenderer = {
ReactFinalForm.useFormSubscription(["values"])->Nullable.make,
)
let form = ReactFinalForm.useForm()
let initalFormValue = React.useMemo(() => {
formState.values->getDictFromJsonObject->getDictfromDict("metadata")
let (meteDataInitialValues, connectorWalletsInitialValues) = React.useMemo(() => {
let formValues = formState.values->getDictFromJsonObject
(
formValues->getDictfromDict("metadata"),
formValues->getDictfromDict("connector_wallets_details"),
)
}, [])
let featureFlagDetails = HyperswitchAtom.featureFlagAtom->Recoil.useRecoilValueFromAtom
let {globalUIConfig: {font: {textColor}}} = React.useContext(ThemeProvider.themeContext)
Expand Down Expand Up @@ -87,7 +91,9 @@ module CardRenderer = {
}

let showSideModal = methodVariant => {
((methodVariant === GooglePay || methodVariant === ApplePay) &&
((methodVariant === GooglePay ||
methodVariant === ApplePay ||
methodVariant === SamsungPay) &&
{
switch connector->getConnectorNameTypeFromString {
| Processors(TRUSTPAY)
Expand Down Expand Up @@ -177,7 +183,12 @@ module CardRenderer = {
let p2RegularTextStyle = `${HSwitchUtils.getTextClass((P2, Medium))} text-grey-700 opacity-50`

let removeSelectedWallet = () => {
form.change("metadata", initalFormValue->Identity.genericTypeToJson)
form.change("metadata", meteDataInitialValues->Identity.genericTypeToJson)
form.change(
"connector_wallets_details",
connectorWalletsInitialValues->Identity.genericTypeToJson,
)

setSelectedWallet(_ => Dict.make()->itemProviderMapper)
}

Expand Down Expand Up @@ -286,6 +297,7 @@ module CardRenderer = {
condition={selectedWallet.payment_method_type->getPaymentMethodTypeFromString ===
ApplePay ||
selectedWallet.payment_method_type->getPaymentMethodTypeFromString === GooglePay ||
selectedWallet.payment_method_type->getPaymentMethodTypeFromString === SamsungPay ||
(paymentMethod->getPaymentMethodFromString === BankDebit && shouldShowPMAuthSidebar)}>
<Modal
modalHeading
Expand Down
8 changes: 8 additions & 0 deletions src/screens/Connectors/ConnectorUtils.res
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,7 @@ let getPaymentMethodTypeFromString = paymentMethodType => {
| "apple_pay" => ApplePay
| "paypal" => PayPal
| "open_banking_pis" => OpenBankingPIS
| "samsung_pay" => SamsungPay
| _ => UnknownPaymentMethodType(paymentMethodType)
}
}
Expand Down Expand Up @@ -920,6 +921,7 @@ let configKeysToIgnore = [
"metadata",
"connector_webhook_details",
"additional_merchant_data",
"connector_wallets_details",
]

let verifyConnectorIgnoreField = [
Expand Down Expand Up @@ -1435,6 +1437,12 @@ let constructConnectorRequestBody = (wasmRequest: wasmRequest, payload: JSON.t)
? JSON.Encode.null
: dict->getDictfromDict("pm_auth_config")->JSON.Encode.object,
),
(
"connector_wallets_details",
dict->getDictfromDict("connector_wallets_details")->isEmptyDict
? JSON.Encode.null
: dict->getDictfromDict("connector_wallets_details")->JSON.Encode.object,
),
])

values
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,13 @@ module AdditionalDetailsSidebarComp = {
<GooglePayIntegration
connector setShowWalletConfigurationModal update=updateMetadata onCloseClickCustomFun
/>
| SamsungPay =>
<SamsungPayIntegration
connector
setShowWalletConfigurationModal
update=updatePaymentMethods
onCloseClickCustomFun
/>
| _ => React.null
}}
</RenderIf>
Expand Down
Loading