HS Cap
diff --git a/src/BrutalTheme.res b/src/BrutalTheme.res
index bf897d61a..723960679 100644
--- a/src/BrutalTheme.res
+++ b/src/BrutalTheme.res
@@ -38,6 +38,14 @@ let brutal = {
colorIconCardError: "#ff1a1a",
spacingGridColumn: "20px",
spacingGridRow: "20px",
+ buttonBackgroundColor: "#f5fb1f",
+ buttonHeight: "48px",
+ buttonWidth: "thin",
+ buttonBorderRadius: "6px",
+ buttonBorderColor: "#566186",
+ buttonTextColor: "#000000",
+ buttonTextFontSize: "16px",
+ buttonTextFontWeight: "500",
}
let brutalRules = (theme: CardThemeType.themeClass) =>
{
diff --git a/src/CardTheme.res b/src/CardTheme.res
index 28c3d6dab..bc0e74bff 100644
--- a/src/CardTheme.res
+++ b/src/CardTheme.res
@@ -128,6 +128,14 @@ let getVariables = (str, dict, default, logger) => {
"spacingGridColumn",
"spacingGridRow",
"spacingAccordionItem",
+ "buttonBackgroundColor",
+ "buttonHeight",
+ "buttonWidth",
+ "buttonBorderRadius",
+ "buttonBorderColor",
+ "buttonTextColor",
+ "buttonTextFontSize",
+ "buttonTextFontWeight",
]
unknownKeysWarning(validKeys, json, "appearance.variables", ~logger)
{
@@ -244,6 +252,39 @@ let getVariables = (str, dict, default, logger) => {
~logger,
),
spacingGridRow: getWarningString(json, "spacingGridRow", default.spacingGridRow, ~logger),
+ buttonBackgroundColor: getWarningString(
+ json,
+ "buttonBackgroundColor",
+ default.spacingGridRow,
+ ~logger,
+ ),
+ buttonHeight: getWarningString(json, "buttonHeight", default.spacingGridRow, ~logger),
+ buttonWidth: getWarningString(json, "buttonWidth", default.spacingGridRow, ~logger),
+ buttonBorderRadius: getWarningString(
+ json,
+ "buttonBorderRadius",
+ default.spacingGridRow,
+ ~logger,
+ ),
+ buttonBorderColor: getWarningString(
+ json,
+ "buttonBorderColor",
+ default.spacingGridRow,
+ ~logger,
+ ),
+ buttonTextColor: getWarningString(json, "buttonTextColor", default.spacingGridRow, ~logger),
+ buttonTextFontSize: getWarningString(
+ json,
+ "buttonTextFontSize",
+ default.spacingGridRow,
+ ~logger,
+ ),
+ buttonTextFontWeight: getWarningString(
+ json,
+ "buttonTextFontWeight",
+ default.spacingGridRow,
+ ~logger,
+ ),
}
})
->Belt.Option.getWithDefault(default)
diff --git a/src/CharcoalTheme.res b/src/CharcoalTheme.res
index 32a755ed1..d42347b9f 100644
--- a/src/CharcoalTheme.res
+++ b/src/CharcoalTheme.res
@@ -38,6 +38,14 @@ let charcoal = {
colorIconCardError: "#fd1717",
spacingGridColumn: "20px",
spacingGridRow: "20px",
+ buttonBackgroundColor: "#000000",
+ buttonHeight: "48px",
+ buttonWidth: "thin",
+ buttonBorderRadius: "6px",
+ buttonBorderColor: "#000000",
+ buttonTextColor: "#ffffff",
+ buttonTextFontSize: "16px",
+ buttonTextFontWeight: "500",
}
let charcoalRules = theme =>
diff --git a/src/Components/PayNowButton.res b/src/Components/PayNowButton.res
index aa5b8dda6..def4bbdfb 100644
--- a/src/Components/PayNowButton.res
+++ b/src/Components/PayNowButton.res
@@ -1,6 +1,6 @@
-@send external postMessage: (Window.window, Js.Json.t, string) => unit = "postMessage"
+@send external postMessage: (Window.window, JSON.t, string) => unit = "postMessage"
-external eventToJson: ReactEvent.Mouse.t => Js.Json.t = "%identity"
+external eventToJson: ReactEvent.Mouse.t => JSON.t = "%identity"
module Loader = {
@react.component
@@ -14,41 +14,72 @@ module Loader = {
}
}
@react.component
-let make = () => {
- let {themeObj, localeString} = Recoil.useRecoilValueFromAtom(RecoilAtoms.configAtom)
+let make = (
+ ~cvcProps: CardUtils.cvcProps,
+ ~cardProps: CardUtils.cardProps,
+ ~expiryProps: CardUtils.expiryProps,
+ ~selectedOption: PaymentModeType.payment,
+) => {
+ open RecoilAtoms
+ let {themeObj, localeString} = Recoil.useRecoilValueFromAtom(configAtom)
let (isDisabled, setIsDisabled) = React.useState(() => false)
let (showLoader, setShowLoader) = React.useState(() => false)
- let complete = Recoil.useRecoilValueFromAtom(RecoilAtoms.fieldsComplete)
+ let areRequiredFieldsValidValue = Recoil.useRecoilValueFromAtom(areRequiredFieldsValid)
+ let {sdkHandleConfirmPayment} = Recoil.useRecoilValueFromAtom(optionAtom)
- let handleOnClick = _ev => {
+ let (isCVCValid, _, _, _, _, _, _, _, _, _) = cvcProps
+ let (isCardValid, _, _, _, _, _, _, _, _, _) = cardProps
+ let (isExpiryValid, _, _, _, _, _, _, _, _) = expiryProps
+
+ let validFormat =
+ isCVCValid->Option.getOr(false) &&
+ isCardValid->Option.getOr(false) &&
+ isExpiryValid->Option.getOr(false) &&
+ areRequiredFieldsValidValue
+
+ let confirmPayload = sdkHandleConfirmPayment->PaymentBody.confirmPayloadForSDKButton
+
+ let handleOnClick = _ => {
setIsDisabled(_ => true)
setShowLoader(_ => true)
- Utils.handleOnConfirmPostMessage(~targetOrigin="*", ())
+ Utils.handlePostMessage([("handleSdkConfirm", confirmPayload)])
}
- React.useEffect1(() => {
- setIsDisabled(_ => !complete)
+ React.useEffect3(() => {
+ if selectedOption === Card {
+ setIsDisabled(_ => !validFormat)
+ } else {
+ setIsDisabled(_ => !areRequiredFieldsValidValue)
+ }
None
- }, [complete])
+ }, (validFormat, areRequiredFieldsValidValue, selectedOption))
-
+
diff --git a/src/DefaultTheme.res b/src/DefaultTheme.res
index 16f84b73b..9077766f3 100644
--- a/src/DefaultTheme.res
+++ b/src/DefaultTheme.res
@@ -38,6 +38,14 @@ let default = {
colorIconCardError: "#fd1717",
spacingGridColumn: "20px",
spacingGridRow: "20px",
+ buttonBackgroundColor: "#006df9",
+ buttonHeight: "48px",
+ buttonWidth: "thin",
+ buttonBorderRadius: "6px",
+ buttonBorderColor: "#ffffff",
+ buttonTextColor: "#ffffff",
+ buttonTextFontSize: "16px",
+ buttonTextFontWeight: "500",
}
let defaultRules = theme =>
{
diff --git a/src/Hooks/CommonHooks.res b/src/Hooks/CommonHooks.res
index b5fd1f564..228df4b5a 100644
--- a/src/Hooks/CommonHooks.res
+++ b/src/Hooks/CommonHooks.res
@@ -13,7 +13,6 @@ type keys = {
publishableKey: string,
iframeId: string,
parentURL: string,
- sdkHandleConfirmPayment: bool,
sdkHandleOneClickConfirmPayment: bool,
}
@val @scope("document") external querySelector: string => Js.Nullable.t
= "querySelector"
@@ -86,11 +85,6 @@ let updateKeys = (dict, keyPair, setKeys) => {
...prev,
parentURL: dict->Utils.getString(key, valueStr),
})
- | "sdkHandleConfirmPayment" =>
- setKeys(.prev => {
- ...prev,
- sdkHandleConfirmPayment: dict->Utils.getBool(key, valueBool(false)),
- })
| "sdkHandleOneClickConfirmPayment" =>
setKeys(.prev => {
...prev,
@@ -105,6 +99,5 @@ let defaultkeys = {
publishableKey: "",
iframeId: "",
parentURL: "*",
- sdkHandleConfirmPayment: false,
sdkHandleOneClickConfirmPayment: true,
}
diff --git a/src/LoaderController.res b/src/LoaderController.res
index d9e861c83..0ca9ac8e4 100644
--- a/src/LoaderController.res
+++ b/src/LoaderController.res
@@ -137,7 +137,8 @@ let make = (~children, ~paymentMode, ~setIntegrateErrorError, ~logger) => {
setList(._ => updatedState)
logger.setLogInfo(~value="SemiLoaded", ~eventName=LOADER_CHANGED, ())
}
- | LoadError(x) => logger.setLogError(
+ | LoadError(x) =>
+ logger.setLogError(
~value="LoadError: " ++ x->Js.Json.stringify,
~eventName=LOADER_CHANGED,
(),
@@ -269,7 +270,6 @@ let make = (~children, ~paymentMode, ~setIntegrateErrorError, ~logger) => {
("iframeId", "no-element"->Js.Json.string),
("publishableKey", ""->Js.Json.string),
("parentURL", "*"->Js.Json.string),
- ("sdkHandleConfirmPayment", false->Js.Json.boolean),
("sdkHandleOneClickConfirmPayment", true->Js.Json.boolean),
]->Js.Array2.forEach(keyPair => {
dict->CommonHooks.updateKeys(keyPair, setKeys)
diff --git a/src/MidnightTheme.res b/src/MidnightTheme.res
index 29d626d2e..b46337934 100644
--- a/src/MidnightTheme.res
+++ b/src/MidnightTheme.res
@@ -38,6 +38,14 @@ let midnight = {
colorIconCardError: "#fd1717",
spacingGridColumn: "20px",
spacingGridRow: "20px",
+ buttonBackgroundColor: "#85d996",
+ buttonHeight: "48px",
+ buttonWidth: "thin",
+ buttonBorderRadius: "6px",
+ buttonBorderColor: "#85d996",
+ buttonTextColor: "#000000",
+ buttonTextFontSize: "16px",
+ buttonTextFontWeight: "500",
}
let midnightRules = theme =>
diff --git a/src/NoTheme.res b/src/NoTheme.res
index 7cfb74446..9f9df6f50 100644
--- a/src/NoTheme.res
+++ b/src/NoTheme.res
@@ -39,6 +39,14 @@ let nakedValues = {
colorIconCardError: "#fd1717",
spacingGridColumn: "20px",
spacingGridRow: "20px",
+ buttonBackgroundColor: "",
+ buttonHeight: "48px",
+ buttonWidth: "thin",
+ buttonBorderRadius: "6px",
+ buttonBorderColor: "",
+ buttonTextColor: "",
+ buttonTextFontSize: "16px",
+ buttonTextFontWeight: "500",
}
let nakedValuesRules = _ => Js.Dict.empty()->Js.Json.object_
diff --git a/src/PaymentElement.res b/src/PaymentElement.res
index f738c2bac..e373568b3 100644
--- a/src/PaymentElement.res
+++ b/src/PaymentElement.res
@@ -30,7 +30,7 @@ let make = (
let (sessions, setSessions) = React.useState(_ => Js.Dict.empty()->Js.Json.object_)
let (paymentOptions, setPaymentOptions) = React.useState(_ => [])
let (walletOptions, setWalletOptions) = React.useState(_ => [])
- let {sdkHandleConfirmPayment} = Recoil.useRecoilValueFromAtom(keys)
+ let {sdkHandleConfirmPayment} = Recoil.useRecoilValueFromAtom(optionAtom)
let (list, setList) = React.useState(_ => PaymentMethodsRecord.defaultList)
let (cardsContainerWidth, setCardsContainerWidth) = React.useState(_ => 0)
@@ -392,11 +392,16 @@ let make = (
| Accordion =>
}}
-
-
-
+
+
+
+
PaymentModeType.paymentMode}
+ />
+
{switch methodslist {
diff --git a/src/SoftTheme.res b/src/SoftTheme.res
index 9038d8cd8..95d4b028d 100644
--- a/src/SoftTheme.res
+++ b/src/SoftTheme.res
@@ -39,6 +39,14 @@ let soft = {
colorIconCardError: "#fe87a1",
spacingGridColumn: "20px",
spacingGridRow: "20px",
+ buttonBackgroundColor: "#3c3d3e",
+ buttonHeight: "48px",
+ buttonWidth: "thin",
+ buttonBorderRadius: "6px",
+ buttonBorderColor: "#7d8fff",
+ buttonTextColor: "#7d8fff",
+ buttonTextFontSize: "16px",
+ buttonTextFontWeight: "500",
}
let softRules = theme =>
diff --git a/src/Types/CardThemeType.res b/src/Types/CardThemeType.res
index 97505436f..ccaa1c050 100644
--- a/src/Types/CardThemeType.res
+++ b/src/Types/CardThemeType.res
@@ -51,6 +51,14 @@ type themeClass = {
colorIconCardError: string,
spacingGridColumn: string,
spacingGridRow: string,
+ buttonBackgroundColor: string,
+ buttonHeight: string,
+ buttonWidth: string,
+ buttonBorderRadius: string,
+ buttonBorderColor: string,
+ buttonTextColor: string,
+ buttonTextFontSize: string,
+ buttonTextFontWeight: string,
}
type appearance = {
theme: theme,
diff --git a/src/Types/PaymentType.res b/src/Types/PaymentType.res
index a5c2784b4..586c310ae 100644
--- a/src/Types/PaymentType.res
+++ b/src/Types/PaymentType.res
@@ -132,6 +132,11 @@ type billingAddress = {
usePrefilledValues: showType,
}
+type sdkHandleConfirmPayment = {
+ handleConfirm: bool,
+ confirmParams: ConfirmType.confirmParams,
+}
+
type options = {
defaultValues: defaultValues,
layout: layoutType,
@@ -149,6 +154,7 @@ type options = {
payButtonStyle: style,
showCardFormByDefault: bool,
billingAddress: billingAddress,
+ sdkHandleConfirmPayment: sdkHandleConfirmPayment,
}
let defaultCardDetails = {
scheme: None,
@@ -250,6 +256,12 @@ let defaultBillingAddress = {
isUseBillingAddress: false,
usePrefilledValues: Auto,
}
+
+let defaultSdkHandleConfirmPayment = {
+ handleConfirm: false,
+ confirmParams: ConfirmType.defaultConfirm,
+}
+
let defaultOptions = {
defaultValues: defaultDefaultValues,
business: defaultBusiness,
@@ -267,6 +279,7 @@ let defaultOptions = {
customMethodNames: [],
showCardFormByDefault: true,
billingAddress: defaultBillingAddress,
+ sdkHandleConfirmPayment: defaultSdkHandleConfirmPayment,
}
let getLayout = (str, logger) => {
switch str {
@@ -873,6 +886,19 @@ let getBillingAddress = (dict, str, logger) => {
->Belt.Option.getWithDefault(defaultBillingAddress)
}
+let getConfirmParams = dict => {
+ open ConfirmType
+ {
+ return_url: dict->getString("return_url", ""),
+ publishableKey: dict->getString("publishableKey", ""),
+ }
+}
+
+let getSdkHandleConfirmPaymentProps = dict => {
+ handleConfirm: dict->getBool("handleConfirm", false),
+ confirmParams: dict->getDictfromDict("confirmParams")->getConfirmParams,
+}
+
let itemToObjMapper = (dict, logger) => {
unknownKeysWarning(
[
@@ -890,6 +916,7 @@ let itemToObjMapper = (dict, logger) => {
"displaySavedPaymentMethods",
"sdkHandleOneClickConfirmPayment",
"showCardFormByDefault",
+ "sdkHandleConfirmPayment",
],
dict,
"options",
@@ -925,6 +952,9 @@ let itemToObjMapper = (dict, logger) => {
payButtonStyle: getStyle(dict, "payButtonStyle", logger),
showCardFormByDefault: getBool(dict, "showCardFormByDefault", true),
billingAddress: getBillingAddress(dict, "billingAddress", logger),
+ sdkHandleConfirmPayment: dict
+ ->getDictfromDict("sdkHandleConfirmPayment")
+ ->getSdkHandleConfirmPaymentProps,
}
}
diff --git a/src/Utilities/PaymentBody.res b/src/Utilities/PaymentBody.res
index dacfac091..ffc308d62 100644
--- a/src/Utilities/PaymentBody.res
+++ b/src/Utilities/PaymentBody.res
@@ -95,6 +95,19 @@ let mandateBody = paymentType => {
]
}
+let confirmPayloadForSDKButton = (sdkHandleConfirmPayment: PaymentType.sdkHandleConfirmPayment) =>
+ [
+ ("redirect", "always"->JSON.Encode.string),
+ (
+ "confirmParams",
+ [("return_url", sdkHandleConfirmPayment.confirmParams.return_url->JSON.Encode.string)]
+ ->Dict.fromArray
+ ->JSON.Encode.object,
+ ),
+ ]
+ ->Dict.fromArray
+ ->JSON.Encode.object
+
let achBankDebitBody = (
~email,
~bank: ACHTypes.data,
diff --git a/src/Utilities/Utils.res b/src/Utilities/Utils.res
index a5b94ec38..b853d87f1 100644
--- a/src/Utilities/Utils.res
+++ b/src/Utilities/Utils.res
@@ -57,6 +57,26 @@ let getInt = (dict, key, default: int) => {
->Belt.Float.toInt
}
+let getFloatFromString = (str, default) => {
+ let val = str->Js.Float.fromString
+ val->Js.Float.isNaN ? default : val
+}
+
+let getFloatFromJson = (json, default) => {
+ switch json->Js.Json.classify {
+ | JSONString(str) => getFloatFromString(str, default)
+ | JSONNumber(floatValue) => floatValue
+ | _ => default
+ }
+}
+
+let getFloat = (dict, key, default) => {
+ dict
+ ->Js.Dict.get(key)
+ ->Belt.Option.map(json => getFloatFromJson(json, default))
+ ->Belt.Option.getWithDefault(default)
+}
+
let getJsonBoolValue = (dict, key, default) => {
dict->Js.Dict.get(key)->Belt.Option.getWithDefault(default->Js.Json.boolean)
}
@@ -138,6 +158,10 @@ let getDictFromJson = (json: Js.Json.t) => {
json->Js.Json.decodeObject->Belt.Option.getWithDefault(Js.Dict.empty())
}
+let getDictfromDict = (dict, key) => {
+ dict->getJsonObjectFromDict(key)->getDictFromJson
+}
+
let getBool = (dict, key, default) => {
getOptionBool(dict, key)->Belt.Option.getWithDefault(default)
}
diff --git a/src/orca-loader/Elements.res b/src/orca-loader/Elements.res
index 6df044b38..75eff009e 100644
--- a/src/orca-loader/Elements.res
+++ b/src/orca-loader/Elements.res
@@ -218,7 +218,6 @@ let make = (
let mountPostMessage = (
mountedIframeRef,
selectorString,
- sdkHandleConfirmPayment,
sdkHandleOneClickConfirmPayment,
displaySavedPaymentMethods,
) => {
@@ -245,7 +244,6 @@ let make = (
("publishableKey", publishableKey->Js.Json.string),
("endpoint", endpoint->Js.Json.string),
("sdkSessionId", sdkSessionId->Js.Json.string),
- ("sdkHandleConfirmPayment", sdkHandleConfirmPayment->Js.Json.boolean),
("blockConfirm", blockConfirm->Js.Json.boolean),
("switchToCustomPod", switchToCustomPod->Js.Json.boolean),
("endpoint", endpoint->Js.Json.string),
diff --git a/src/orca-loader/Hyper.res b/src/orca-loader/Hyper.res
index bb037fbaf..38472a849 100644
--- a/src/orca-loader/Hyper.res
+++ b/src/orca-loader/Hyper.res
@@ -339,6 +339,17 @@ let make = (publishableKey, options: option
, analyticsInfo: option {
+ let json = event.data->eventToJson
+ let dict = json->getDictFromJson
+ switch dict->Js.Dict.get("handleSdkConfirm") {
+ | Some(payload) => confirmPayment(payload)->ignore
+ | None => ()
+ }
+ }
+
+ addSmartEventListener("message", handleSdkConfirm, "handleSdkConfirm")
+
let elements = elementsOptions => {
open Promise
let clientSecretId =
diff --git a/src/orca-loader/LoaderPaymentElement.res b/src/orca-loader/LoaderPaymentElement.res
index e34242950..b28b2dc96 100644
--- a/src/orca-loader/LoaderPaymentElement.res
+++ b/src/orca-loader/LoaderPaymentElement.res
@@ -19,12 +19,6 @@ let make = (componentType, options, setIframeRef, iframeRef, mountPostMessage) =
setIframeRef(ref)
}
- let sdkHandleConfirmPayment =
- options->getDecodedBoolFromJson(
- callbackFuncForExtractingValFromDict("sdkHandleConfirmPayment"),
- false,
- )
-
let sdkHandleOneClickConfirmPayment =
options->getDecodedBoolFromJson(
callbackFuncForExtractingValFromDict("sdkHandleOneClickConfirmPayment"),
@@ -170,7 +164,8 @@ let make = (componentType, options, setIframeRef, iframeRef, mountPostMessage) =
eventDataObject
->getOptionalJsonFromJson("iframeId")
->getStringfromOptionaljson("no-element")
- iframeHeightRef := iframeHeight->getFloatfromjson(200.0)
+ iframeHeightRef :=
+ iframeHeight->Option.getOr(JSON.Encode.null)->Utils.getFloatFromJson(200.0)
if iframeId === localSelectorString {
let elem = Window.querySelector(
`#orca-payment-element-iframeRef-${localSelectorString}`,
@@ -303,7 +298,6 @@ let make = (componentType, options, setIframeRef, iframeRef, mountPostMessage) =
mountPostMessage(
Window.querySelector(`#orca-payment-element-iframeRef-${localSelectorString}`),
localSelectorString,
- sdkHandleConfirmPayment,
sdkHandleOneClickConfirmPayment,
displaySavedPaymentMethods,
)
diff --git a/src/orca-loader/OrcaUtils.res b/src/orca-loader/OrcaUtils.res
index bbe4aa1c4..d0aba433a 100644
--- a/src/orca-loader/OrcaUtils.res
+++ b/src/orca-loader/OrcaUtils.res
@@ -294,10 +294,6 @@ let getBoolfromjson = (json: option, default: bool) => {
json->Belt.Option.flatMap(Js.Json.decodeBoolean)->Belt.Option.getWithDefault(default)
}
-let getFloatfromjson = (json: option, default: float) => {
- json->Belt.Option.flatMap(Js.Json.decodeNumber)->Belt.Option.getWithDefault(default)
-}
-
let getStringfromjson = (json: Js.Json.t, default: string) => {
json->Js.Json.decodeString->Belt.Option.getWithDefault(default)
}