From 54847fe7268842951c47b9e6d3bcbae3ef273661 Mon Sep 17 00:00:00 2001 From: Praful Koppalkar Date: Wed, 24 Apr 2024 14:59:45 +0530 Subject: [PATCH] feat: polling status for 3ds flow --- src/Utilities/PaymentHelpers.res | 88 +++++++++++++++++++++++++++++ src/orca-loader/Elements.res | 37 ++++++++++++ src/orca-log-catcher/OrcaLogger.res | 4 ++ 3 files changed, 129 insertions(+) diff --git a/src/Utilities/PaymentHelpers.res b/src/Utilities/PaymentHelpers.res index d7746678..ccdcf56a 100644 --- a/src/Utilities/PaymentHelpers.res +++ b/src/Utilities/PaymentHelpers.res @@ -186,6 +186,94 @@ let rec pollRetrievePaymentIntent = ( }) } +let retrieveStatus = (~headers, ~switchToCustomPod, pollID) => { + open Promise + let endpoint = ApiEndpoint.getApiEndPoint() + let uri = `${endpoint}/poll/status/${pollID}` + let logger = OrcaLogger.make() + logApi( + ~optLogger=Some(logger), + ~url=uri, + ~apiLogType=Request, + ~eventName=POLL_STATUS_INIT, + ~logType=INFO, + ~logCategory=API, + (), + ) + fetchApi( + uri, + ~method=#GET, + ~headers=headers->ApiEndpoint.addCustomPodHeader(~switchToCustomPod, ()), + (), + ) + ->then(res => { + let statusCode = res->Fetch.Response.status->Int.toString + if statusCode->String.charAt(0) !== "2" { + res + ->Fetch.Response.json + ->then(data => { + logApi( + ~optLogger=Some(logger), + ~url=uri, + ~data, + ~statusCode, + ~apiLogType=Err, + ~eventName=POLL_STATUS_CALL, + ~logType=ERROR, + ~logCategory=API, + (), + ) + JSON.Encode.null->resolve + }) + } else { + logApi( + ~optLogger=Some(logger), + ~url=uri, + ~statusCode, + ~apiLogType=Response, + ~eventName=POLL_STATUS_CALL, + ~logType=INFO, + ~logCategory=API, + (), + ) + res->Fetch.Response.json + } + }) + ->catch(e => { + Console.log2("Unable to Poll status details because of ", e) + JSON.Encode.null->resolve + }) +} + +let rec pollStatus = (~headers, ~switchToCustomPod, ~pollId, ~interval, ~count) => { + open Promise + retrieveStatus(~headers, ~switchToCustomPod, pollId) + ->then(json => { + let dict = json->JSON.Decode.object->Option.getOr(Dict.make()) + let status = dict->getString("status", "") + Promise.make((resolve, _) => { + if status === "completed" { + resolve(json) + } else if !(count > 0) { + handlePostMessage([("fullscreen", false->JSON.Encode.bool)]) + postFailedSubmitResponse(~errortype="server_error", ~message="Something went wrong") // redirect to return url + } else { + delay(interval) + ->then( + _ => { + pollStatus(~headers, ~switchToCustomPod, ~pollId, ~interval, ~count=count - 1) + }, + ) + ->ignore + } + }) + }) + ->catch(e => { + Console.log2("Unable to retrieve payment due to following error", e) + pollStatus(~headers, ~switchToCustomPod, ~pollId, ~interval, ~count=count - 1) + }) +} + let rec intentCall = ( ~fetchApi: ( string, diff --git a/src/orca-loader/Elements.res b/src/orca-loader/Elements.res index 35d57fe0..37716fc4 100644 --- a/src/orca-loader/Elements.res +++ b/src/orca-loader/Elements.res @@ -423,7 +423,44 @@ let make = ( } } + let handlePollStatusMessage = (ev: Types.event) => { + let eventDataObject = ev.data->anyTypeToJson + let headers = [("Content-Type", "application/json"), ("api-key", publishableKey)] + switch eventDataObject->getOptionalJsonFromJson("poll_status") { + | Some(val) => { + handlePostMessage([ + ("fullscreen", true->JSON.Encode.bool), + ("param", "paymentloader"->JSON.Encode.string), + ("iframeId", selectorString->JSON.Encode.string), + ]) + let dict = val->getDictFromJson + let pollId = dict->getString("poll_id", "") + let interval = + dict->getString("delay_in_secs", "")->Int.fromString->Option.getOr(1) * 1000 + let count = dict->getString("frequency", "")->Int.fromString->Option.getOr(5) + let url = dict->getString("return_url_with_query_params", "") + PaymentHelpers.pollStatus(~headers, ~switchToCustomPod, ~pollId, ~interval, ~count) + ->then(res => { + let dict = res->JSON.Decode.object->Option.getOr(Dict.make()) + let status = dict->getString("status", "") + if status === "completed" { + Window.Location.replace(url)->ignore // retrive status + }->resolve + }) + ->catch(_e => + postFailedSubmitResponse( + ~errortype="Server_error", + ~message="Something went Wrong", + )->resolve + ) + ->ignore + } + | None => () + } + } + addSmartEventListener("message", handleApplePayMounted, "onApplePayMount") + addSmartEventListener("message", handlePollStatusMessage, "onPollStatusMsg") addSmartEventListener("message", handleGooglePayThirdPartyFlow, "onGooglePayThirdParty") Window.removeEventListener("message", handleApplePayMessages.contents) diff --git a/src/orca-log-catcher/OrcaLogger.res b/src/orca-log-catcher/OrcaLogger.res index c42ca30c..8ec06c2f 100644 --- a/src/orca-log-catcher/OrcaLogger.res +++ b/src/orca-log-catcher/OrcaLogger.res @@ -63,6 +63,8 @@ type eventName = | PAYMENT_METHODS_RESPONSE | LOADER_CHANGED | PAYMENT_SESSION_INITIATED + | POLL_STATUS_INIT + | POLL_STATUS_CALL let eventNameToStrMapper = eventName => { switch eventName { @@ -126,6 +128,8 @@ let eventNameToStrMapper = eventName => { | PAYMENT_METHODS_RESPONSE => "PAYMENT_METHODS_RESPONSE" | LOADER_CHANGED => "LOADER_CHANGED" | PAYMENT_SESSION_INITIATED => "PAYMENT_SESSION_INITIATED" + | POLL_STATUS_INIT => "POLL_STATUS_INIT" + | POLL_STATUS_CALL => "POLL_STATUS_CALL" } }