Skip to content

Commit

Permalink
feat: added paypal tabs flow support for billing details
Browse files Browse the repository at this point in the history
  • Loading branch information
sakksham7 committed Nov 14, 2024
1 parent 324b556 commit adbf394
Show file tree
Hide file tree
Showing 8 changed files with 120 additions and 24 deletions.
28 changes: 28 additions & 0 deletions src/PaymentElement.res
Original file line number Diff line number Diff line change
Expand Up @@ -158,6 +158,19 @@ let make = (~cardProps, ~expiryProps, ~cvcProps, ~paymentType: CardThemeType.mod
googlePayThirdPartySessionObj.sessionsToken,
Gpay,
)
let paypalPaymentMethodExperience = React.useMemo(() => {
PaymentMethodsRecord.getPaymentExperienceTypeFromPML(
~paymentMethodList=paymentMethodListValue,
~paymentMethodName="wallet",
~paymentMethodType="paypal",
)
}, [paymentMethodListValue])
let paypalToken = React.useMemo(
() => SessionsType.getPaymentSessionObj(sessionObj.sessionsToken, Paypal),
[sessionObj],
)
let isPaypalSDKFlow = paypalPaymentMethodExperience->Array.includes(InvokeSDK)
let isPaypalRedirectFlow = paypalPaymentMethodExperience->Array.includes(RedirectToURL)

React.useEffect(() => {
switch paymentMethodList {
Expand Down Expand Up @@ -355,6 +368,21 @@ let make = (~cardProps, ~expiryProps, ~cvcProps, ~paymentType: CardThemeType.mod
| _ => React.null
}}
</SessionPaymentWrapper>
| PayPal =>
<SessionPaymentWrapper type_={Wallet}>
{switch paypalToken {
| OtherTokenOptional(optToken) =>
switch (optToken, isPaypalSDKFlow, isPaypalRedirectFlow) {
| (Some(token), true, _) => <PaypalSDKLazy sessionObj=token paymentType />
| (_, _, true) => <PayPalLazy paymentType walletOptions />
| _ => React.null
}
| _ =>
<RenderIf condition={isPaypalRedirectFlow}>
<PayPalLazy paymentType walletOptions />
</RenderIf>
}}
</SessionPaymentWrapper>
| _ =>
<ReusableReactSuspense loaderComponent={loader()} componentName="PaymentMethodsWrapperLazy">
<PaymentMethodsWrapperLazy paymentType paymentMethodName=selectedOption />
Expand Down
85 changes: 64 additions & 21 deletions src/Payments/PayPal.res
Original file line number Diff line number Diff line change
Expand Up @@ -11,14 +11,16 @@ module Loader = {
let payPalIcon = <Icon size=35 width=90 name="paypal" />

@react.component
let make = () => {
let make = (~paymentType, ~walletOptions) => {
let loggerState = Recoil.useRecoilValueFromAtom(loggerAtom)
let (paypalClicked, setPaypalClicked) = React.useState(_ => false)
let sdkHandleIsThere = Recoil.useRecoilValueFromAtom(isPaymentButtonHandlerProvidedAtom)
let {publishableKey} = Recoil.useRecoilValueFromAtom(keys)
let options = Recoil.useRecoilValueFromAtom(optionAtom)
let areOneClickWalletsRendered = Recoil.useSetRecoilState(areOneClickWalletsRendered)
let paymentMethodListValue = Recoil.useRecoilValueFromAtom(PaymentUtils.paymentMethodListValue)
let isWallet = walletOptions->Array.includes("paypal")
let (requiredFieldsBody, setRequiredFieldsBody) = React.useState(_ => Dict.make())

let (_, _, labelType) = options.wallets.style.type_
let _label = switch labelType {
Expand Down Expand Up @@ -56,12 +58,16 @@ let make = () => {
let (connectors, _) =
paymentMethodListValue->PaymentUtils.getConnectors(Wallets(Paypal(Redirect)))
let body = PaymentBody.paypalRedirectionBody(~connectors)

let modifiedPaymentBody = PaymentUtils.appendedCustomerAcceptance(
let basePaymentBody = PaymentUtils.appendedCustomerAcceptance(
~isGuestCustomer,
~paymentType=paymentMethodListValue.payment_type,
~body,
)
let modifiedPaymentBody = if isWallet {
basePaymentBody
} else {
basePaymentBody->Utils.mergeAndFlattenToTuples(requiredFieldsBody)
}

intent(
~bodyArr=modifiedPaymentBody,
Expand All @@ -88,24 +94,61 @@ let make = () => {
None
})

<button
style={
display: "inline-block",
color: textColor,
height: `${height->Int.toString}px`,
borderRadius: `${options.wallets.style.buttonRadius->Int.toString}px`,
width: "100%",
backgroundColor: buttonColor,
}
onClick={_ => options.readOnly ? () : onPaypalClick()}>
<div className="justify-center" style={display: "flex", flexDirection: "row", color: textColor}>
{if !paypalClicked {
payPalIcon
} else {
<Loader />
}}
</div>
</button>
let useSubmitCallback = (~isWallet) => {
let areRequiredFieldsValid = Recoil.useRecoilValueFromAtom(RecoilAtoms.areRequiredFieldsValid)
let areRequiredFieldsEmpty = Recoil.useRecoilValueFromAtom(RecoilAtoms.areRequiredFieldsEmpty)
let {localeString} = Recoil.useRecoilValueFromAtom(RecoilAtoms.configAtom)
let {iframeId} = Recoil.useRecoilValueFromAtom(RecoilAtoms.keys)

React.useCallback((ev: Window.event) => {
if !isWallet {
let json = ev.data->Utils.safeParse
let confirm = json->Utils.getDictFromJson->ConfirmType.itemToObjMapper
if confirm.doSubmit && areRequiredFieldsValid && !areRequiredFieldsEmpty {
onPaypalClick(ev)
} else if areRequiredFieldsEmpty {
Utils.postFailedSubmitResponse(
~errortype="validation_error",
~message=localeString.enterFieldsText,
)
} else if !areRequiredFieldsValid {
Utils.postFailedSubmitResponse(
~errortype="validation_error",
~message=localeString.enterValidDetailsText,
)
}
}
}, (areRequiredFieldsValid, areRequiredFieldsEmpty, isWallet, iframeId))
}

let submitCallback = useSubmitCallback(~isWallet)
Utils.useSubmitPaymentData(submitCallback)

if isWallet {
<button
style={
display: "inline-block",
color: textColor,
height: `${height->Int.toString}px`,
borderRadius: `${options.wallets.style.buttonRadius->Int.toString}px`,
width: "100%",
backgroundColor: buttonColor,
}
onClick={_ => options.readOnly ? () : onPaypalClick()}>
<div
className="justify-center" style={display: "flex", flexDirection: "row", color: textColor}>
{if !paypalClicked {
payPalIcon
} else {
<Loader />
}}
</div>
</button>
} else {
<DynamicFields
paymentType paymentMethod="wallet" paymentMethodType="paypal" setRequiredFieldsBody
/>
}
}

let default = make
2 changes: 1 addition & 1 deletion src/Payments/PayPal.resi
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
@react.component
let default: unit => React.element
let default: (~paymentType: CardThemeType.mode, ~walletOptions: array<string>) => React.element
7 changes: 7 additions & 0 deletions src/Payments/PaymentMethodsRecord.res
Original file line number Diff line number Diff line change
Expand Up @@ -534,6 +534,13 @@ let paymentMethodsFields = [
fields: [InfoElement],
miniIcon: None,
},
{
paymentMethodName: "paypal",
icon: Some(icon("paypal", ~size=21, ~width=25)),
displayName: "Paypal",
fields: [],
miniIcon: None,
},
{
paymentMethodName: "local_bank_transfer_transfer",
fields: [InfoElement],
Expand Down
4 changes: 2 additions & 2 deletions src/Payments/PaymentRequestButtonElement.res
Original file line number Diff line number Diff line change
Expand Up @@ -113,12 +113,12 @@ let make = (~sessions, ~walletOptions, ~paymentType) => {
| OtherTokenOptional(optToken) =>
switch (optToken, isPaypalSDKFlow, isPaypalRedirectFlow) {
| (Some(token), true, _) => <PaypalSDKLazy sessionObj=token paymentType />
| (_, _, true) => <PayPalLazy />
| (_, _, true) => <PayPalLazy paymentType walletOptions />
| _ => React.null
}
| _ =>
<RenderIf condition={isPaypalRedirectFlow}>
<PayPalLazy />
<PayPalLazy paymentType walletOptions />
</RenderIf>
}}
</SessionPaymentWrapper>
Expand Down
2 changes: 2 additions & 0 deletions src/Types/PaymentModeType.res
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ type payment =
| GooglePay
| ApplePay
| Boleto
| PayPal
| NONE

let paymentMode = str => {
Expand All @@ -43,6 +44,7 @@ let paymentMode = str => {
| "google_pay" => GooglePay
| "apple_pay" => ApplePay
| "boleto" => Boleto
| "paypal" => PayPal
| _ => NONE
}
}
Expand Down
1 change: 1 addition & 0 deletions src/Utilities/DynamicFieldsUtils.res
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ let dynamicFieldsEnabledPaymentMethods = [
"bacs",
"pay_bright",
"multibanco_transfer",
"paypal",
]

let getName = (item: PaymentMethodsRecord.required_fields, field: RecoilAtomTypes.field) => {
Expand Down
15 changes: 15 additions & 0 deletions src/Utilities/PaymentUtils.res
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ let paymentListLookupNew = (
~isKlarnaSDKFlow,
~paymentMethodListValue: PaymentMethodsRecord.paymentMethodList,
~areAllGooglePayRequiredFieldsPrefilled,
~areAllPaypalRequiredFieldsPreFilled,
~isGooglePayReady,
~shouldDisplayApplePayInTabs,
) => {
Expand Down Expand Up @@ -36,6 +37,13 @@ let paymentListLookupNew = (
walletToBeDisplayedInTabs->Array.push("apple_pay")
}

if (
!paymentMethodListValue.collect_billing_details_from_wallets &&
!areAllPaypalRequiredFieldsPreFilled
) {
walletToBeDisplayedInTabs->Array.push("paypal")
}

if (
!paymentMethodListValue.collect_billing_details_from_wallets &&
!areAllGooglePayRequiredFieldsPrefilled &&
Expand Down Expand Up @@ -332,6 +340,12 @@ let useGetPaymentMethodList = (~paymentOptions, ~paymentType, ~sessions) => {
~paymentMethodType="google_pay",
)

let areAllPaypalRequiredFieldsPreFilled = useAreAllRequiredFieldsPrefilled(
~paymentMethodListValue,
~paymentMethod="wallet",
~paymentMethodType="paypal",
)

let isApplePayReady = Recoil.useRecoilValueFromAtom(RecoilAtoms.isApplePayReady)
let isGooglePayReady = Recoil.useRecoilValueFromAtom(RecoilAtoms.isGooglePayReady)

Expand All @@ -355,6 +369,7 @@ let useGetPaymentMethodList = (~paymentOptions, ~paymentType, ~sessions) => {
~isKlarnaSDKFlow,
~paymentMethodListValue=plist,
~areAllGooglePayRequiredFieldsPrefilled,
~areAllPaypalRequiredFieldsPreFilled,
~isGooglePayReady,
~shouldDisplayApplePayInTabs,
)
Expand Down

0 comments on commit adbf394

Please sign in to comment.