Skip to content

Commit

Permalink
feat: open banking PIS integration (#541)
Browse files Browse the repository at this point in the history
  • Loading branch information
PritishBudhiraja authored Aug 7, 2024
1 parent 812cd74 commit 25e24b6
Show file tree
Hide file tree
Showing 6 changed files with 99 additions and 33 deletions.
23 changes: 7 additions & 16 deletions src/Payments/PaymentMethodsRecord.res
Original file line number Diff line number Diff line change
Expand Up @@ -499,6 +499,13 @@ let paymentMethodsFields = [
fields: [InfoElement],
miniIcon: Some(icon("bank", ~size=19)),
},
{
paymentMethodName: "open_banking_pis",
icon: Some(icon("bank", ~size=19)),
displayName: "Open Banking",
fields: [InfoElement],
miniIcon: Some(icon("bank", ~size=19)),
},
{
paymentMethodName: "evoucher",
icon: Some(icon("cashtocode", ~size=50)),
Expand Down Expand Up @@ -739,9 +746,6 @@ let getPaymentDetails = (arr: array<string>) => {
finalArr
}

type paymentMethod =
Cards | Wallets | PayLater | BankRedirect | BankTransfer | BankDebit | Crypto | Voucher | NONE

type cardType = Credit | Debit

type paymentExperience = {
Expand Down Expand Up @@ -825,19 +829,6 @@ let defaultList = {
merchant_name: "",
collect_billing_details_from_wallets: true,
}
let getMethod = str => {
switch str {
| "card" => Cards
| "wallet" => Wallets
| "pay_later" => PayLater
| "bank_redirect" => BankRedirect
| "bank_transfer" => BankTransfer
| "bank_debit" => BankDebit
| "crypto" => Crypto
| "voucher" => Voucher
| _ => NONE
}
}

let getPaymentExperienceType = str => {
switch str {
Expand Down
75 changes: 64 additions & 11 deletions src/Payments/PlaidSDKIframe.res
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,11 @@ let make = () => {
let (isReady, setIsReady) = React.useState(_ => false)
let (pmAuthConnectorsArr, setPmAuthConnectorsArr) = React.useState(_ => [])
let (publishableKey, setPublishableKey) = React.useState(_ => "")
let (paymentId, setPaymentId) = React.useState(_ => "")
let (clientSecret, setClientSecret) = React.useState(_ => "")
let (isForceSync, setIsForceSync) = React.useState(_ => false)
let logger = React.useMemo(() => {
OrcaLogger.make(~source=Elements(Payment), ~clientSecret=paymentId, ~merchantId=publishableKey)
}, (publishableKey, paymentId))
OrcaLogger.make(~source=Elements(Payment), ~clientSecret, ~merchantId=publishableKey)
}, (publishableKey, clientSecret))

React.useEffect0(() => {
let handle = (ev: Window.event) => {
Expand All @@ -24,8 +25,9 @@ let make = () => {

setLinkToken(_ => linkToken)
setPmAuthConnectorsArr(_ => pmAuthConnectorArray)
setPublishableKey(_ => metaData->getString("payment_id", ""))
setPaymentId(_ => metaData->getString("publishableKey", ""))
setPublishableKey(_ => metaData->getString("publishableKey", ""))
setClientSecret(_ => metaData->getString("clientSecret", ""))
setIsForceSync(_ => metaData->getBool("isForceSync", false))
}
}
Window.addEventListener("message", handle)
Expand All @@ -47,6 +49,50 @@ let make = () => {
None
}, [pmAuthConnectorsArr])

let callbackOnSuccessOfPlaidPaymentsFlow = () => {
open Promise
let headers = [("Content-Type", "application/json"), ("api-key", publishableKey)]

PaymentHelpers.retrievePaymentIntent(
clientSecret,
headers,
~optLogger=Some(logger),
~switchToCustomPod=false,
~isForceSync=true,
)
->then(json => {
let dict = json->getDictFromJson
let status = dict->getString("status", "")
let return_url = dict->getString("return_url", "")

if (
status === "succeeded" || status === "requires_customer_action" || status === "processing"
) {
postSubmitResponse(~jsonData=json, ~url=return_url)
} else if status === "failed" {
postFailedSubmitResponse(
~errortype="confirm_payment_failed",
~message="Payment failed. Try again!",
)
} else {
postFailedSubmitResponse(
~errortype="sync_payment_failed",
~message="Payment is processing. Try again later!",
)
}
handlePostMessage([("fullscreen", false->JSON.Encode.bool)])
resolve(json)
})
->then(_ => {
resolve(Nullable.null)
})
->catch(e => {
logInfo(Console.log2("Retrieve Failed", e))
resolve(Nullable.null)
})
->ignore
}

React.useEffect(() => {
if isReady && linkToken->String.length > 0 {
let handler = Plaid.create({
Expand All @@ -59,14 +105,21 @@ let make = () => {
("isPlaid", true->JSON.Encode.bool),
("publicToken", publicToken->JSON.Encode.string),
])
if isForceSync {
callbackOnSuccessOfPlaidPaymentsFlow()
}
},
onExit: _ => {
handlePostMessage([
("fullscreen", false->JSON.Encode.bool),
("isPlaid", true->JSON.Encode.bool),
("isExited", true->JSON.Encode.bool),
("publicToken", ""->JSON.Encode.string),
])
if isForceSync {
callbackOnSuccessOfPlaidPaymentsFlow()
} else {
handlePostMessage([
("fullscreen", false->JSON.Encode.bool),
("isPlaid", true->JSON.Encode.bool),
("isExited", true->JSON.Encode.bool),
("publicToken", ""->JSON.Encode.string),
])
}
},
})

Expand Down
2 changes: 1 addition & 1 deletion src/Payments/QRCodeDisplay.res
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@ let make = () => {
~switchToCustomPod,
)
->then(json => {
let dict = json->JSON.Decode.object->Option.getOr(Dict.make())
let dict = json->getDictFromJson
let status = dict->getString("status", "")

if (
Expand Down
2 changes: 1 addition & 1 deletion src/ThreeDSAuth.res
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ let make = () => {
~headers,
)
->then(json => {
let dict = json->JSON.Decode.object->Option.getOr(Dict.make())
let dict = json->getDictFromJson
if dict->Dict.get("error")->Option.isSome {
let errorObj = PaymentError.itemToObjMapper(dict)
handlePostMessage([("fullscreen", false->JSON.Encode.bool)])
Expand Down
28 changes: 25 additions & 3 deletions src/Utilities/PaymentHelpers.res
Original file line number Diff line number Diff line change
Expand Up @@ -176,7 +176,7 @@ let rec pollRetrievePaymentIntent = (
open Promise
retrievePaymentIntent(clientSecret, headers, ~optLogger, ~switchToCustomPod, ~isForceSync)
->then(json => {
let dict = json->JSON.Decode.object->Option.getOr(Dict.make())
let dict = json->getDictFromJson
let status = dict->getString("status", "")

if status === "succeeded" || status === "failed" {
Expand Down Expand Up @@ -261,7 +261,7 @@ let rec pollStatus = (
open Promise
retrieveStatus(~headers, ~switchToCustomPod, pollId, logger)
->then(json => {
let dict = json->JSON.Decode.object->Option.getOr(Dict.make())
let dict = json->getDictFromJson
let status = dict->getString("status", "")
Promise.make((resolve, _) => {
if status === "completed" {
Expand Down Expand Up @@ -693,12 +693,33 @@ let rec intentCall = (
| None => Dict.make()
}
let walletName = session_token->getString("wallet_name", "")

let message = switch walletName {
| "apple_pay" => [
("applePayButtonClicked", true->JSON.Encode.bool),
("applePayPresent", session_token->anyTypeToJson),
]
| "google_pay" => [("googlePayThirdPartyFlow", session_token->anyTypeToJson)]
| "open_banking" => {
let metaData = [
(
"linkToken",
session_token
->getString("open_banking_session_token", "")
->JSON.Encode.string,
),
("pmAuthConnectorArray", ["plaid"]->Identity.anyTypeToJson),
("publishableKey", confirmParam.publishableKey->JSON.Encode.string),
("clientSecret", clientSecret->JSON.Encode.string),
("isForceSync", true->JSON.Encode.bool),
]->getJsonFromArrayOfJson
[
("fullscreen", true->JSON.Encode.bool),
("param", "plaidSDK"->JSON.Encode.string),
("iframeId", iframeId->JSON.Encode.string),
("metadata", metaData),
]
}
| _ => []
}

Expand Down Expand Up @@ -1687,8 +1708,9 @@ let callAuthLink = (
[
("linkToken", data->getDictFromJson->getString("link_token", "")->JSON.Encode.string),
("pmAuthConnectorArray", pmAuthConnectorsArr->Identity.anyTypeToJson),
("payment_id", clientSecret->Option.getOr("")->getPaymentId->JSON.Encode.string),
("publishableKey", publishableKey->JSON.Encode.string),
("clientSecret", clientSecret->Option.getOr("")->JSON.Encode.string),
("isForceSync", false->JSON.Encode.bool),
]->getJsonFromArrayOfJson

handlePostMessage([
Expand Down
2 changes: 1 addition & 1 deletion src/orca-loader/Elements.res
Original file line number Diff line number Diff line change
Expand Up @@ -643,7 +643,7 @@ let make = (
)
->then(json => {
if redirect.contents === "always" {
let dict = json->JSON.Decode.object->Option.getOr(Dict.make())
let dict = json->getDictFromJson
let status = dict->getString("status", "")
let returnUrl = dict->getString("return_url", "")
Window.Location.replace(
Expand Down

0 comments on commit 25e24b6

Please sign in to comment.