diff --git a/src/Payments/QRCodeDisplay.res b/src/Payments/QRCodeDisplay.res index 453f3cb27..faf769cf8 100644 --- a/src/Payments/QRCodeDisplay.res +++ b/src/Payments/QRCodeDisplay.res @@ -15,6 +15,7 @@ let make = () => { let (return_url, setReturnUrl) = React.useState(_ => "") let (clientSecret, setClientSecret) = React.useState(_ => "") let (headers, setHeaders) = React.useState(_ => []) + let logger = Recoil.useRecoilValueFromAtom(RecoilAtoms.loggerAtom) React.useEffect0(() => { handlePostMessage([("iframeMountedCallback", true->Js.Json.boolean)]) @@ -49,7 +50,7 @@ let make = () => { // } open Promise setHeaders(_ => headers->Js.Dict.entries) - PaymentHelpers.pollRetrievePaymentIntent(paymentIntentId, headers->Js.Dict.entries) + PaymentHelpers.pollRetrievePaymentIntent(paymentIntentId, headers->Js.Dict.entries, ~optLogger=Some(logger)) ->then(res => { Modal.close(setOpenModal) postSubmitResponse(~jsonData=res, ~url=return_url) @@ -77,7 +78,7 @@ let make = () => { let closeModal = () => { open Promise - PaymentHelpers.retrievePaymentIntent(clientSecret, headers) + PaymentHelpers.retrievePaymentIntent(clientSecret, headers, ~optLogger=Some(logger)) ->then(json => { let dict = json->Js.Json.decodeObject->Belt.Option.getWithDefault(Js.Dict.empty()) let status = dict->getString("status", "") diff --git a/src/Utilities/LoggerUtils.res b/src/Utilities/LoggerUtils.res index 6999e97a0..9dc4bb925 100644 --- a/src/Utilities/LoggerUtils.res +++ b/src/Utilities/LoggerUtils.res @@ -30,13 +30,13 @@ let logApi = ( ] | NoResponse => [ ("url", url->Js.Json.string), - ("statusCode", "\"500\""->Js.Json.string), - ("response", "{\"error\": \"No Response from Server\"}"->Js.Json.string), + ("statusCode", "504"->Js.Json.string), + ("response", `{"error": "No Response from Server"}`->Js.Json.string), ] | Err => [ ("url", url->Js.Json.string), ("statusCode", statusCode->Js.Json.string), - ("response", "{\"error\": \"No Response from Server\"}"->Js.Json.string), + ("response", `{"error": "No Response from Server"}`->Js.Json.string), ] | Method => [("method", paymentMethod->Js.Json.string), ("result", result)] } diff --git a/src/Utilities/PaymentHelpers.res b/src/Utilities/PaymentHelpers.res index 0bdbaae78..4c48acc1a 100644 --- a/src/Utilities/PaymentHelpers.res +++ b/src/Utilities/PaymentHelpers.res @@ -13,7 +13,7 @@ type payment = Card | BankTransfer | BankDebits | KlarnaRedirect | Gpay | Applep let closePaymentLoaderIfAny = () => Utils.handlePostMessage([("fullscreen", false->Js.Json.boolean)]) -let retrievePaymentIntent = (clientSecret, headers) => { +let retrievePaymentIntent = (clientSecret, headers, ~optLogger) => { open Promise let fetchApi = CommonHooks.useApiFetcher() let paymentIntentID = Js.String2.split(clientSecret, "_secret_")[0] @@ -22,6 +22,37 @@ let retrievePaymentIntent = (clientSecret, headers) => { //let headers = [("Accept", "application/json"), ("api-key", publishableKey)] fetchApi(uri, ~method_=Fetch.Get, ~headers=headers->addCustomPodHeader, ()) ->then(res => { + let statusCode = res->Fetch.Response.status->string_of_int + if statusCode->Js.String2.charAt(0) !== "2" { + res + ->Fetch.Response.json + ->then(data => { + logApi( + ~optLogger, + ~url=uri, + ~data, + ~statusCode, + ~type_="err", + ~eventName=RETRIEVE_CALL, + ~logType=ERROR, + ~logCategory=API, + (), + ) + resolve() + }) + ->ignore + } else { + logApi( + ~optLogger, + ~url=uri, + ~statusCode, + ~type_="response", + ~eventName=RETRIEVE_CALL, + ~logType=INFO, + ~logCategory=API, + (), + ) + } res->Fetch.Response.json }) ->then(res => resolve(res)) @@ -31,9 +62,9 @@ let retrievePaymentIntent = (clientSecret, headers) => { }) } -let rec pollRetrievePaymentIntent = (clientSecret, headers) => { +let rec pollRetrievePaymentIntent = (clientSecret, headers, ~optLogger) => { open Promise - retrievePaymentIntent(clientSecret, headers) + retrievePaymentIntent(clientSecret, headers, ~optLogger) ->then(json => { let dict = json->Js.Json.decodeObject->Belt.Option.getWithDefault(Js.Dict.empty()) let status = dict->getString("status", "") @@ -42,13 +73,13 @@ let rec pollRetrievePaymentIntent = (clientSecret, headers) => { resolve(json) } else { delay(2000)->then(_val => { - pollRetrievePaymentIntent(clientSecret, headers) + pollRetrievePaymentIntent(clientSecret, headers, ~optLogger) }) } }) ->catch(e => { Js.log2("Unable to retrieve payment due to following error", e) - pollRetrievePaymentIntent(clientSecret, headers) + pollRetrievePaymentIntent(clientSecret, headers, ~optLogger) }) } @@ -73,6 +104,8 @@ let intentCall = ( ~setIsManualRetryEnabled, ) => { open Promise + let isConfirm = uri->Js.String.includes("/confirm") + let eventName: OrcaLogger.eventName = isConfirm ? CONFIRM_CALL : RETRIEVE_CALL fetchApi(uri, ~method_=fetchMethod, ~headers=headers->addCustomPodHeader, ~bodyStr, ()) ->then(res => { let statusCode = res->Fetch.Response.status->string_of_int @@ -84,7 +117,7 @@ let intentCall = ( res ->Fetch.Response.json ->then(data => { - if uri->Js.String.includes("/confirm") { + if isConfirm { let paymentMethod = switch paymentType { | Card => "CARD" | _ => @@ -100,18 +133,18 @@ let intentCall = ( ~paymentMethod, ) } - logApi( ~optLogger, ~url=uri, ~data, ~statusCode, - ~type_="response", - ~eventName=API_CALL_FAILED, + ~type_="err", + ~eventName, ~logType=ERROR, ~logCategory=API, (), ) + let dict = data->getDictFromJson let errorObj = PaymentError.itemToObjMapper(dict) closePaymentLoaderIfAny() @@ -126,8 +159,8 @@ let intentCall = ( ~optLogger, ~url=uri, ~statusCode, - ~type_="err", - ~eventName=API_CALL_FAILED_WITHOUT_STATUS_CODE, + ~type_="no_response", + ~eventName, ~logType=ERROR, ~logCategory=API, (), @@ -144,15 +177,7 @@ let intentCall = ( res ->Fetch.Response.json ->then(data => { - logApi( - ~optLogger, - ~url=uri, - ~data, - ~statusCode, - ~type_="response", - ~eventName=PAYMENT_RESPONSE, - (), - ) + logApi(~optLogger, ~url=uri, ~statusCode, ~type_="response", ~eventName, ()) let intent = PaymentConfirmTypes.itemToObjMapper(data->getDictFromJson) let url = urlSearch(confirmParam.return_url) @@ -271,7 +296,7 @@ let intentCall = ( logApi( ~optLogger, ~url=uri, - ~eventName=API_CALL_FAILED_WITHOUT_STATUS_CODE, + ~eventName, ~type_="no_response", ~logType=ERROR, ~logCategory=API, @@ -456,6 +481,7 @@ let useSessions = ( ~publishableKey, ~wallets=[], ~isDelayedSessionToken=false, + ~optLogger, (), ) => { let fetchApi = CommonHooks.useApiFetcher() @@ -473,20 +499,61 @@ let useSessions = ( ] ->Js.Dict.fromArray ->Js.Json.object_ + let uri = `${endpoint}/payments/session_tokens` fetchApi( - `${endpoint}/payments/session_tokens`, + uri, ~method_=Fetch.Post, ~bodyStr=body->Js.Json.stringify, ~headers=headers->addCustomPodHeader, (), ) ->then(resp => { + let statusCode = resp->Fetch.Response.status->string_of_int + if statusCode->Js.String2.charAt(0) !== "2" { + resp + ->Fetch.Response.json + ->then(data => { + logApi( + ~optLogger, + ~url=uri, + ~data, + ~statusCode, + ~type_="err", + ~eventName=SESSIONS_CALL, + ~logType=ERROR, + ~logCategory=API, + (), + ) + resolve() + }) + ->ignore + } else { + logApi( + ~optLogger, + ~url=uri, + ~statusCode, + ~type_="response", + ~eventName=SESSIONS_CALL, + ~logType=INFO, + ~logCategory=API, + (), + ) + } Fetch.Response.json(resp) }) ->then(json => { json->resolve }) ->catch(_e => { + logApi( + ~optLogger, + ~url=uri, + ~type_="no_response", + ~eventName=SESSIONS_CALL, + ~logType=ERROR, + ~logCategory=API, + (), + ) Js.Dict.empty()->Js.Json.object_->resolve }) } @@ -496,16 +563,39 @@ let usePaymentMethodList = (~clientSecret, ~publishableKey, ~logger) => { open Promise let headers = [("Content-Type", "application/json"), ("api-key", publishableKey)] - fetchApi( - `${endpoint}/account/payment_methods?client_secret=${clientSecret}`, - ~method_=Fetch.Get, - ~headers=headers->addCustomPodHeader, - (), - ) + let uri = `${endpoint}/account/payment_methods?client_secret=${clientSecret}` + fetchApi(uri, ~method_=Fetch.Get, ~headers=headers->addCustomPodHeader, ()) ->then(resp => { let statusCode = resp->Fetch.Response.status->string_of_int if statusCode->Js.String2.charAt(0) !== "2" { - ErrorUtils.manageErrorWarning(INTERNAL_API_DOWN, ~logger, ()) + resp + ->Fetch.Response.json + ->then(data => { + logApi( + ~optLogger=Some(logger), + ~url=uri, + ~data, + ~statusCode, + ~type_="err", + ~eventName=PAYMENT_METHODS_CALL, + ~logType=ERROR, + ~logCategory=API, + (), + ) + resolve() + }) + ->ignore + } else { + logApi( + ~optLogger=Some(logger), + ~url=uri, + ~statusCode, + ~type_="response", + ~eventName=PAYMENT_METHODS_CALL, + ~logType=INFO, + ~logCategory=API, + (), + ) } Fetch.Response.json(resp) }) @@ -513,11 +603,20 @@ let usePaymentMethodList = (~clientSecret, ~publishableKey, ~logger) => { json->resolve }) ->catch(_e => { + logApi( + ~optLogger=Some(logger), + ~url=uri, + ~type_="no_response", + ~eventName=PAYMENT_METHODS_CALL, + ~logType=ERROR, + ~logCategory=API, + (), + ) Js.Dict.empty()->Js.Json.object_->resolve }) } -let useCustomerDetails = (~clientSecret, ~publishableKey) => { +let useCustomerDetails = (~clientSecret, ~publishableKey, ~optLogger) => { open Promise let fetchApi = CommonHooks.useApiFetcher() let headers = [("Content-Type", "application/json"), ("api-key", publishableKey)] @@ -525,11 +624,41 @@ let useCustomerDetails = (~clientSecret, ~publishableKey) => { fetchApi(uri, ~method_=Fetch.Get, ~headers=headers->ApiEndpoint.addCustomPodHeader, ()) ->then(res => { + let statusCode = res->Fetch.Response.status->string_of_int + if statusCode->Js.String2.charAt(0) !== "2" { + res + ->Fetch.Response.json + ->then(data => { + logApi( + ~optLogger, + ~url=uri, + ~data, + ~statusCode, + ~type_="err", + ~eventName=CUSTOMER_PAYMENT_METHODS_CALL, + ~logType=ERROR, + ~logCategory=API, + (), + ) + resolve() + }) + ->ignore + } else { + logApi( + ~optLogger, + ~url=uri, + ~statusCode, + ~type_="response", + ~eventName=CUSTOMER_PAYMENT_METHODS_CALL, + ~logType=INFO, + ~logCategory=API, + (), + ) + } res->Fetch.Response.json }) ->then(res => resolve(res)) ->catch(e => { - Js.log2("Unable to retrieve customer details because of ", e) Js.Dict.empty()->Js.Json.object_->resolve }) } diff --git a/src/orca-loader/Elements.res b/src/orca-loader/Elements.res index e96442cc0..e1a8b7e0d 100644 --- a/src/orca-loader/Elements.res +++ b/src/orca-loader/Elements.res @@ -45,6 +45,7 @@ let make = ( let sessionsPromise = PaymentHelpers.useSessions( ~clientSecret=clientSecretId, ~publishableKey, + ~optLogger=Some(logger), (), ) let paymentMethodListPromise = PaymentHelpers.usePaymentMethodList( @@ -125,6 +126,7 @@ let make = ( let customerDetailsPromise = PaymentHelpers.useCustomerDetails( ~clientSecret=clientSecretId, ~publishableKey, + ~optLogger=Some(logger), ) open Promise customerDetailsPromise diff --git a/src/orca-loader/Hyper.res b/src/orca-loader/Hyper.res index 20e2b7554..3845af66a 100644 --- a/src/orca-loader/Hyper.res +++ b/src/orca-loader/Hyper.res @@ -120,12 +120,46 @@ let make = (publishableKey, _options: option, analyticsInfo: optionthen(Fetch.Response.json) + ->then(resp => { + let statusCode = resp->Fetch.Response.status->string_of_int + if statusCode->Js.String2.charAt(0) !== "2" { + resp + ->Fetch.Response.json + ->then(data => { + logApi( + ~optLogger=Some(logger), + ~url=retrievePaymentUrl, + ~data, + ~statusCode, + ~type_="err", + ~eventName=RETRIEVE_CALL, + ~logType=ERROR, + ~logCategory=API, + (), + ) + resolve() + }) + ->ignore + } else { + logApi( + ~optLogger=Some(logger), + ~url=retrievePaymentUrl, + ~statusCode, + ~type_="response", + ~eventName=RETRIEVE_CALL, + ~logType=INFO, + ~logCategory=API, + (), + ) + } + Fetch.Response.json(resp) + }) ->then(data => { [("paymentIntent", data)]->Js.Dict.fromArray->Js.Json.object_->Promise.resolve }) diff --git a/src/orca-log-catcher/OrcaLogger.res b/src/orca-log-catcher/OrcaLogger.res index 66ce942b4..5734d5de5 100644 --- a/src/orca-log-catcher/OrcaLogger.res +++ b/src/orca-log-catcher/OrcaLogger.res @@ -28,8 +28,11 @@ type eventName = | COUNTRY_CHANGED | LOG_INITIATED | INPUT_FIELD_CHANGED - | API_CALL_FAILED - | API_CALL_FAILED_WITHOUT_STATUS_CODE + | RETRIEVE_CALL + | CONFIRM_CALL + | SESSIONS_CALL + | PAYMENT_METHODS_CALL + | CUSTOMER_PAYMENT_METHODS_CALL | TRUSTPAY_SCRIPT | GOOGLE_PAY_SCRIPT | APPLE_PAY_FLOW @@ -76,8 +79,11 @@ let eventNameToStrMapper = eventName => { | COUNTRY_CHANGED => "COUNTRY_CHANGED" | LOG_INITIATED => "LOG_INITIATED" | INPUT_FIELD_CHANGED => "INPUT_FIELD_CHANGED" - | API_CALL_FAILED => "API_CALL_FAILED" - | API_CALL_FAILED_WITHOUT_STATUS_CODE => "API_CALL_FAILED_WITHOUT_STATUS_CODE" + | RETRIEVE_CALL => "RETRIEVE_CALL" + | CONFIRM_CALL => "CONFIRM_CALL" + | SESSIONS_CALL => "SESSIONS_CALL" + | PAYMENT_METHODS_CALL => "PAYMENT_METHODS_CALL" + | CUSTOMER_PAYMENT_METHODS_CALL => "CUSTOMER_PAYMENT_METHODS_CALL" | TRUSTPAY_SCRIPT => "TRUSTPAY_SCRIPT" | GOOGLE_PAY_SCRIPT => "GOOGLE_PAY_SCRIPT" | APPLE_PAY_FLOW => "APPLE_PAY_FLOW" @@ -473,7 +479,7 @@ let make = ( | None => timeOut := Some(Js.Global.setTimeout(() => sendLogs(), 20000)) } let len = mainLogFile->Js.Array2.length - if len > 5 { + if len > 0 { sendLogs() } }