Skip to content

Commit e42a5a3

Browse files
ArushKapoorJuspayprafulkoppalkarVrishab Srivatsa
authored
fix(threedsmethod): changed Three DS method API call to hidden Form Post (#302)
Co-authored-by: Praful Koppalkar <[email protected]> Co-authored-by: Vrishab Srivatsa <[email protected]>
1 parent b13a369 commit e42a5a3

File tree

5 files changed

+67
-163
lines changed

5 files changed

+67
-163
lines changed

src/ThreeDSMethod.res

Lines changed: 62 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -3,15 +3,25 @@ open Utils
33
let make = () => {
44
let logger = OrcaLogger.make()
55

6-
let mountToInnerHTML = innerHTML => {
7-
let ele = Window.querySelector("#threeDsInvisibleIframe")
8-
switch ele->Nullable.toOption {
9-
| Some(elem) => elem->Window.innerHTML(innerHTML)
10-
| None =>
11-
Console.warn(
12-
"INTEGRATION ERROR: Div does not seem to exist on which threeDSMethod is to be mounted",
13-
)
14-
}
6+
let (stateMetadata, setStateMetadata) = React.useState(_ => Dict.make()->JSON.Encode.object)
7+
8+
let handleLoaded = _ev => {
9+
stateMetadata->Utils.getDictFromJson->Dict.set("3dsMethodComp", "Y"->JSON.Encode.string)
10+
let metadataDict = stateMetadata->JSON.Decode.object->Option.getOr(Dict.make())
11+
let iframeId = metadataDict->getString("iframeId", "")
12+
LoggerUtils.handleLogging(
13+
~optLogger=Some(logger),
14+
~eventName=THREE_DS_METHOD_RESULT,
15+
~value="Y",
16+
~paymentMethod="CARD",
17+
(),
18+
)
19+
handlePostMessage([
20+
("fullscreen", true->JSON.Encode.bool),
21+
("param", `3dsAuth`->JSON.Encode.string),
22+
("iframeId", iframeId->JSON.Encode.string),
23+
("metadata", stateMetadata),
24+
])
1525
}
1626

1727
React.useEffect0(() => {
@@ -21,6 +31,7 @@ let make = () => {
2131
let dict = json->Utils.getDictFromJson
2232
if dict->Dict.get("fullScreenIframeMounted")->Option.isSome {
2333
let metadata = dict->getJsonObjectFromDict("metadata")
34+
setStateMetadata(_ => metadata)
2435
let metaDataDict = metadata->JSON.Decode.object->Option.getOr(Dict.make())
2536
let threeDsDataDict =
2637
metaDataDict
@@ -42,74 +53,65 @@ let make = () => {
4253
->Option.getOr(Dict.make()->JSON.Encode.object)
4354
let paymentIntentId = metaDataDict->Utils.getString("paymentIntentId", "")
4455
let publishableKey = metaDataDict->Utils.getString("publishableKey", "")
45-
let iframeId = metaDataDict->getString("iframeId", "")
4656

4757
logger.setClientSecret(paymentIntentId)
4858
logger.setMerchantId(publishableKey)
4959

50-
open Promise
51-
PaymentHelpers.threeDsMethod(threeDsUrl, threeDsMethodData, ~optLogger=Some(logger))
52-
->then(res => {
53-
if res == "" {
54-
Exn.raiseError("Empty response from threeDsMethod")->reject
55-
} else {
56-
LoggerUtils.handleLogging(
57-
~optLogger=Some(logger),
58-
~eventName=THREE_DS_METHOD_RESULT,
59-
~value="Y",
60-
~paymentMethod="CARD",
61-
(),
62-
)
63-
mountToInnerHTML(res)
64-
metadata->Utils.getDictFromJson->Dict.set("3dsMethodComp", "Y"->JSON.Encode.string)
65-
handlePostMessage([
66-
("fullscreen", true->JSON.Encode.bool),
67-
("param", `3dsAuth`->JSON.Encode.string),
68-
("iframeId", iframeId->JSON.Encode.string),
69-
("metadata", metadata),
70-
])
71-
resolve(res)
72-
}
73-
})
74-
->catch(err => {
75-
let exceptionMessage = err->Utils.formatException
76-
metadata->Utils.getDictFromJson->Dict.set("3dsMethodComp", "N"->JSON.Encode.string)
77-
handlePostMessage([
78-
("fullscreen", true->JSON.Encode.bool),
79-
("param", `3dsAuth`->JSON.Encode.string),
80-
("iframeId", iframeId->JSON.Encode.string),
81-
("metadata", metadata),
82-
])
60+
let iframeId = metaDataDict->getString("iframeId", "")
61+
62+
let handleFailureScenarios = value => {
8363
LoggerUtils.handleLogging(
8464
~optLogger=Some(logger),
8565
~eventName=THREE_DS_METHOD_RESULT,
86-
~value=exceptionMessage->JSON.stringify,
66+
~value,
8767
~paymentMethod="CARD",
8868
~logType=ERROR,
8969
(),
9070
)
91-
reject(err)
92-
})
93-
->ignore
71+
metadata->Utils.getDictFromJson->Dict.set("3dsMethodComp", "N"->JSON.Encode.string)
72+
handlePostMessage([
73+
("fullscreen", true->JSON.Encode.bool),
74+
("param", `3dsAuth`->JSON.Encode.string),
75+
("iframeId", iframeId->JSON.Encode.string),
76+
("metadata", stateMetadata),
77+
])
78+
}
9479

95-
let headersDict =
96-
metaDataDict
97-
->getJsonObjectFromDict("headers")
98-
->JSON.Decode.object
99-
->Option.getOr(Dict.make())
100-
let headers = Dict.make()
80+
let ele = Window.querySelector("#threeDsInvisibleDiv")
10181

102-
headersDict
103-
->Dict.toArray
104-
->Array.forEach(entries => {
105-
let (x, val) = entries
106-
Dict.set(headers, x, val->JSON.Decode.string->Option.getOr(""))
107-
})
82+
switch ele->Nullable.toOption {
83+
| Some(elem) => {
84+
let form = elem->makeForm(threeDsUrl, "threeDsHiddenPostMethod")
85+
let input = Types.createElement("input")
86+
input.name = encodeURIComponent("threeDSMethodData")
87+
let threeDsMethodStr = threeDsMethodData->JSON.Decode.string->Option.getOr("")
88+
input.value = encodeURIComponent(threeDsMethodStr)
89+
form.target = "threeDsInvisibleIframe"
90+
form.appendChild(input)
91+
try {
92+
form.submit()
93+
} catch {
94+
| err => {
95+
let exceptionMessage = err->Utils.formatException->JSON.stringify
96+
handleFailureScenarios(exceptionMessage)
97+
}
98+
}
99+
}
100+
| None => handleFailureScenarios("Unable to Locate threeDsInvisibleDiv")
101+
}
108102
}
109103
}
110104
Window.addEventListener("message", handle)
111105
Some(() => {Window.removeEventListener("message", handle)})
112106
})
113107

114-
<div id="threeDsInvisibleIframe" className="bg-black-100 h-96" />
108+
<>
109+
<div id="threeDsInvisibleDiv" className="hidden" />
110+
<iframe
111+
id="threeDsInvisibleIframe"
112+
name="threeDsInvisibleIframe"
113+
className="h-96 invisible"
114+
onLoad=handleLoaded
115+
/>
116+
</>
115117
}

src/Utilities/PaymentHelpers.res

Lines changed: 0 additions & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -79,69 +79,6 @@ let retrievePaymentIntent = (
7979
})
8080
}
8181

82-
let threeDsMethod = (url, threeDsMethodData, ~optLogger) => {
83-
open Promise
84-
logApi(
85-
~optLogger,
86-
~url,
87-
~apiLogType=Request,
88-
~eventName=THREE_DS_METHOD_CALL_INIT,
89-
~logType=INFO,
90-
~logCategory=API,
91-
(),
92-
)
93-
let threeDsMethodStr = threeDsMethodData->JSON.Decode.string->Option.getOr("")
94-
let body = `${encodeURIComponent("threeDSMethodData")}=${encodeURIComponent(threeDsMethodStr)}`
95-
96-
fetchApiWithNoCors(url, ~method=#POST, ~bodyStr=body, ())
97-
->then(res => {
98-
let statusCode = res->Fetch.Response.status->Int.toString
99-
if statusCode->String.charAt(0) !== "2" {
100-
res
101-
->Fetch.Response.text
102-
->then(text => {
103-
logApi(
104-
~optLogger,
105-
~url,
106-
~data=text->JSON.Encode.string,
107-
~statusCode,
108-
~apiLogType=Err,
109-
~eventName=THREE_DS_METHOD_CALL,
110-
~logType=ERROR,
111-
~logCategory=API,
112-
(),
113-
)
114-
""->resolve
115-
})
116-
} else {
117-
logApi(
118-
~optLogger,
119-
~url,
120-
~statusCode,
121-
~apiLogType=Response,
122-
~eventName=THREE_DS_METHOD_CALL,
123-
(),
124-
)
125-
res->Fetch.Response.text
126-
}
127-
})
128-
->catch(err => {
129-
let exceptionMessage = err->formatException
130-
Console.log2("Unable to call 3ds method ", exceptionMessage)
131-
logApi(
132-
~optLogger,
133-
~url,
134-
~eventName=THREE_DS_METHOD_CALL,
135-
~apiLogType=NoResponse,
136-
~data=exceptionMessage,
137-
~logType=ERROR,
138-
~logCategory=API,
139-
(),
140-
)
141-
reject(err)
142-
})
143-
}
144-
14582
let threeDsAuth = (~clientSecret, ~optLogger, ~threeDsMethodComp, ~headers) => {
14683
let endpoint = ApiEndpoint.getApiEndPoint()
14784
let paymentIntentID = String.split(clientSecret, "_secret_")[0]->Option.getOr("")

src/Utilities/Utils.res

Lines changed: 1 addition & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -835,37 +835,6 @@ let fetchApi = (uri, ~bodyStr: string="", ~headers=Dict.make(), ~method: Fetch.m
835835
})
836836
}
837837

838-
let fetchApiWithNoCors = (
839-
uri,
840-
~bodyStr: string="",
841-
~headers=Dict.make(),
842-
~method: Fetch.method,
843-
(),
844-
) => {
845-
open Promise
846-
let body = switch method {
847-
| #GET => resolve(None)
848-
| _ => resolve(Some(Fetch.Body.string(bodyStr)))
849-
}
850-
body->then(body => {
851-
Fetch.fetch(
852-
uri,
853-
{
854-
method,
855-
mode: #"no-cors",
856-
?body,
857-
headers: getHeaders(~headers, ~uri, ()),
858-
},
859-
)
860-
->catch(err => {
861-
reject(err)
862-
})
863-
->then(resp => {
864-
resolve(resp)
865-
})
866-
})
867-
}
868-
869838
let arrayJsonToCamelCase = arr => {
870839
arr->Array.map(item => {
871840
item->transformKeys(CamelCase)
@@ -1192,7 +1161,7 @@ let makeForm = (element, url, id) => {
11921161
form.action = url
11931162
form.method = "POST"
11941163
form.enctype = "application/x-www-form-urlencoded;charset=UTF-8"
1195-
form.style = "display: hidden; "
1164+
form.style = "display: hidden;"
11961165
element->appendChild(form)
11971166
form
11981167
}

src/orca-loader/Types.res

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -177,8 +177,8 @@ type rec ele = {
177177
mutable target: string,
178178
mutable enctype: string,
179179
mutable value: string,
180-
submit: (. unit) => unit,
181-
appendChild: (. ele) => unit,
180+
submit: unit => unit,
181+
appendChild: ele => unit,
182182
}
183183
@scope("document") @val external createElement: string => ele = "createElement"
184184

src/orca-log-catcher/OrcaLogger.res

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,6 @@ type eventName =
1414
| RETRIEVE_CALL
1515
| AUTHENTICATION_CALL_INIT
1616
| AUTHENTICATION_CALL
17-
| THREE_DS_METHOD_CALL_INIT
18-
| THREE_DS_METHOD_CALL
1917
| CONFIRM_CALL_INIT
2018
| CONFIRM_CALL
2119
| SESSIONS_CALL_INIT
@@ -79,8 +77,6 @@ let eventNameToStrMapper = eventName => {
7977
| RETRIEVE_CALL => "RETRIEVE_CALL"
8078
| AUTHENTICATION_CALL_INIT => "AUTHENTICATION_CALL_INIT"
8179
| AUTHENTICATION_CALL => "AUTHENTICATION_CALL"
82-
| THREE_DS_METHOD_CALL_INIT => "THREE_DS_METHOD_CALL_INIT"
83-
| THREE_DS_METHOD_CALL => "THREE_DS_METHOD_CALL"
8480
| CONFIRM_CALL_INIT => "CONFIRM_CALL_INIT"
8581
| CONFIRM_CALL => "CONFIRM_CALL"
8682
| SESSIONS_CALL_INIT => "SESSIONS_CALL_INIT"
@@ -499,7 +495,7 @@ let make = (
499495
PAYMENT_ATTEMPT,
500496
CONFIRM_CALL,
501497
AUTHENTICATION_CALL,
502-
THREE_DS_METHOD_CALL,
498+
THREE_DS_METHOD_RESULT,
503499
SDK_CRASH,
504500
REDIRECTING_USER,
505501
DISPLAY_BANK_TRANSFER_INFO_PAGE,
@@ -508,6 +504,7 @@ let make = (
508504
LOADER_CHANGED,
509505
SESSIONS_CALL,
510506
RETRIEVE_CALL,
507+
DISPLAY_THREE_DS_SDK,
511508
]
512509
arrayOfLogs
513510
->Array.find(log => {
@@ -542,7 +539,6 @@ let make = (
542539
}
543540
}
544541
| AUTHENTICATION_CALL
545-
| THREE_DS_METHOD_CALL
546542
| RETRIEVE_CALL
547543
| CONFIRM_CALL
548544
| SESSIONS_CALL

0 commit comments

Comments
 (0)