From b61bc3cdd049a8b66bbfe38879367ecb22ec0659 Mon Sep 17 00:00:00 2001 From: Praful Koppalkar <126236898+prafulkoppalkar@users.noreply.github.com> Date: Fri, 26 Apr 2024 21:46:50 +0530 Subject: [PATCH 01/16] feat: three_ds polling part2 (#334) --- src/Utilities/PaymentHelpers.res | 17 ++++++++---- src/orca-loader/Elements.res | 45 +++++++++++++++++++++++--------- 2 files changed, 44 insertions(+), 18 deletions(-) diff --git a/src/Utilities/PaymentHelpers.res b/src/Utilities/PaymentHelpers.res index ccdcf56aa..884017dfe 100644 --- a/src/Utilities/PaymentHelpers.res +++ b/src/Utilities/PaymentHelpers.res @@ -245,7 +245,7 @@ let retrieveStatus = (~headers, ~switchToCustomPod, pollID) => { }) } -let rec pollStatus = (~headers, ~switchToCustomPod, ~pollId, ~interval, ~count) => { +let rec pollStatus = (~headers, ~switchToCustomPod, ~pollId, ~interval, ~count, ~returnUrl) => { open Promise retrieveStatus(~headers, ~switchToCustomPod, pollId) ->then(json => { @@ -254,14 +254,21 @@ let rec pollStatus = (~headers, ~switchToCustomPod, ~pollId, ~interval, ~count) Promise.make((resolve, _) => { if status === "completed" { resolve(json) - } else if !(count > 0) { + } else if count === 0 { handlePostMessage([("fullscreen", false->JSON.Encode.bool)]) - postFailedSubmitResponse(~errortype="server_error", ~message="Something went wrong") // redirect to return url + openUrl(returnUrl) } else { delay(interval) ->then( _ => { - pollStatus(~headers, ~switchToCustomPod, ~pollId, ~interval, ~count=count - 1) + pollStatus( + ~headers, + ~switchToCustomPod, + ~pollId, + ~interval, + ~count=count - 1, + ~returnUrl, + ) }, ) ->ignore @@ -270,7 +277,7 @@ let rec pollStatus = (~headers, ~switchToCustomPod, ~pollId, ~interval, ~count) }) ->catch(e => { Console.log2("Unable to retrieve payment due to following error", e) - pollStatus(~headers, ~switchToCustomPod, ~pollId, ~interval, ~count=count - 1) + pollStatus(~headers, ~switchToCustomPod, ~pollId, ~interval, ~count=count - 1, ~returnUrl) }) } diff --git a/src/orca-loader/Elements.res b/src/orca-loader/Elements.res index 37716fc43..287e70c44 100644 --- a/src/orca-loader/Elements.res +++ b/src/orca-loader/Elements.res @@ -439,20 +439,39 @@ let make = ( 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 + PaymentHelpers.pollStatus( + ~headers, + ~switchToCustomPod, + ~pollId, + ~interval, + ~count, + ~returnUrl=url, ) + ->then(_ => { + PaymentHelpers.retrievePaymentIntent( + clientSecret, + headers, + ~optLogger=Some(logger), + ~switchToCustomPod, + ~isForceSync=true, + ) + ->then(json => { + let dict = json->JSON.Decode.object->Option.getOr(Dict.make()) + let status = dict->getString("status", "") + let returnUrl = dict->getString("return_url", "") + Window.Location.replace( + `${returnUrl}?payment_intent_client_secret=${clientSecret}&status=${status}`, + ) + resolve() + }) + ->catch(_ => { + Window.Location.replace(url) + resolve() + }) + ->ignore + ->resolve + }) + ->catch(e => Console.log2("POLL_STATUS ERROR -", e)->resolve) ->ignore } | None => () From 95451bd676c0dfe357d0a7252f32ebbcab4c22e4 Mon Sep 17 00:00:00 2001 From: semantic-release-bot Date: Fri, 26 Apr 2024 16:18:58 +0000 Subject: [PATCH 02/16] chore(release): 0.46.0 [skip ci] # [0.46.0](https://github.com/juspay/hyperswitch-web/compare/v0.45.1...v0.46.0) (2024-04-26) ### Features * three_ds polling part2 ([#334](https://github.com/juspay/hyperswitch-web/issues/334)) ([b61bc3c](https://github.com/juspay/hyperswitch-web/commit/b61bc3cdd049a8b66bbfe38879367ecb22ec0659)) --- CHANGELOG.md | 7 +++++++ package-lock.json | 4 ++-- package.json | 2 +- 3 files changed, 10 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 78c01f3b2..a3a0e49a2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,10 @@ +# [0.46.0](https://github.com/juspay/hyperswitch-web/compare/v0.45.1...v0.46.0) (2024-04-26) + + +### Features + +* three_ds polling part2 ([#334](https://github.com/juspay/hyperswitch-web/issues/334)) ([b61bc3c](https://github.com/juspay/hyperswitch-web/commit/b61bc3cdd049a8b66bbfe38879367ecb22ec0659)) + ## [0.45.1](https://github.com/juspay/hyperswitch-web/compare/v0.45.0...v0.45.1) (2024-04-24) diff --git a/package-lock.json b/package-lock.json index 198b7af94..369f843b6 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "orca-payment-page", - "version": "0.45.1", + "version": "0.46.0", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "orca-payment-page", - "version": "0.45.1", + "version": "0.46.0", "hasInstallScript": true, "dependencies": { "@aws-sdk/client-cloudfront": "^3.414.0", diff --git a/package.json b/package.json index 88b168e81..97e0a0b45 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "orca-payment-page", - "version": "0.45.1", + "version": "0.46.0", "main": "index.js", "private": true, "dependencies": { From c08ec25e1211e3efdbe7af5c6db44d6a0b7cc03b Mon Sep 17 00:00:00 2001 From: Vrishab Srivatsa <136090360+vsrivatsa-juspay@users.noreply.github.com> Date: Mon, 29 Apr 2024 16:43:43 +0530 Subject: [PATCH 03/16] fix: move applepay thirdparty event listeners outside (#336) --- src/Payments/ApplePay.res | 7 - src/Payments/GPay.res | 7 - src/orca-loader/Elements.res | 449 ++++++++++++++++++++--------------- 3 files changed, 251 insertions(+), 212 deletions(-) diff --git a/src/Payments/ApplePay.res b/src/Payments/ApplePay.res index a3a985a23..17b17518b 100644 --- a/src/Payments/ApplePay.res +++ b/src/Payments/ApplePay.res @@ -273,13 +273,6 @@ let make = ( let bodyDict = PaymentBody.applePayRedirectBody(~connectors) processPayment(bodyDict) } - let value = "Payment Data Filled: New Payment Method" - loggerState.setLogInfo( - ~value, - ~eventName=PAYMENT_DATA_FILLED, - ~paymentMethod="APPLE_PAY", - (), - ) } else { setApplePayClicked(_ => false) } diff --git a/src/Payments/GPay.res b/src/Payments/GPay.res index 400a078af..950563161 100644 --- a/src/Payments/GPay.res +++ b/src/Payments/GPay.res @@ -149,13 +149,6 @@ let make = ( makeOneClickHandlerPromise(sdkHandleOneClickConfirmPayment)->then(result => { let result = result->JSON.Decode.bool->Option.getOr(false) if result { - let value = "Payment Data Filled: New Payment Method" - loggerState.setLogInfo( - ~value, - ~eventName=PAYMENT_DATA_FILLED, - ~paymentMethod="GOOGLE_PAY", - (), - ) if isInvokeSDKFlow { if isDelayedSessionToken { handlePostMessage([ diff --git a/src/orca-loader/Elements.res b/src/orca-loader/Elements.res index 287e70c44..5ea77b0d5 100644 --- a/src/orca-loader/Elements.res +++ b/src/orca-loader/Elements.res @@ -20,7 +20,6 @@ let make = ( ~logger: option, ~analyticsMetadata, ) => { - let handleApplePayMessages = ref(_ => ()) let applePaySessionRef = ref(Nullable.null) try { @@ -144,12 +143,15 @@ let make = ( ? "https://tpgw.trustpay.eu/js/v1.js" : "https://test-tpgw.trustpay.eu/js/v1.js" let trustPayScript = Window.createElement("script") + logger.setLogInfo(~value="TrustPay Script Loading", ~eventName=TRUSTPAY_SCRIPT, ()) trustPayScript->Window.elementSrc(trustPayScriptURL) trustPayScript->Window.elementOnerror(err => { Utils.logInfo(Console.log2("ERROR DURING LOADING TRUSTPAY APPLE PAY", err)) }) + trustPayScript->Window.elementOnload(_ => { + logger.setLogInfo(~value="TrustPay Script Loaded", ~eventName=TRUSTPAY_SCRIPT, ()) + }) Window.body->Window.appendChild(trustPayScript) - logger.setLogInfo(~value="TrustPay Script Loaded", ~eventName=TRUSTPAY_SCRIPT, ()) } } let msg = [("paymentMethodList", json)]->Dict.fromArray @@ -289,19 +291,33 @@ let make = ( if dict->Dict.get("applePayMounted")->Option.isSome { switch sessionForApplePay->Nullable.toOption { | Some(session) => - if session.canMakePayments() { - let msg = [("applePayCanMakePayments", true->JSON.Encode.bool)]->Dict.fromArray - mountedIframeRef->Window.iframePostMessage(msg) - } else { - logger.setLogInfo( - ~value="CANNOT MAKE PAYMENT USING APPLE PAY", - ~eventName=APPLE_PAY_FLOW, - ~paymentMethod="APPLE_PAY", - ~logType=ERROR, - (), - ) + try { + if session.canMakePayments() { + let msg = [("applePayCanMakePayments", true->JSON.Encode.bool)]->Dict.fromArray + mountedIframeRef->Window.iframePostMessage(msg) + } else { + Console.log("CANNOT MAKE PAYMENT USING APPLE PAY") + logger.setLogInfo( + ~value="CANNOT MAKE PAYMENT USING APPLE PAY", + ~eventName=APPLE_PAY_FLOW, + ~paymentMethod="APPLE_PAY", + ~logType=ERROR, + (), + ) + } + } catch { + | exn => { + let exnString = exn->anyTypeToJson->JSON.stringify + Console.log("CANNOT MAKE PAYMENT USING APPLE PAY: " ++ exnString) + logger.setLogInfo( + ~value=exnString, + ~eventName=APPLE_PAY_FLOW, + ~paymentMethod="APPLE_PAY", + ~logType=ERROR, + (), + ) + } } - | None => () } } @@ -381,6 +397,13 @@ let make = ( ~paymentMethod="GOOGLE_PAY", (), ) + let value = "Payment Data Filled: New Payment Method" + logger.setLogInfo( + ~value, + ~eventName=PAYMENT_DATA_FILLED, + ~paymentMethod="GOOGLE_PAY", + (), + ) let msg = [("googlePaySyncPayment", true->JSON.Encode.bool)]->Dict.fromArray mountedIframeRef->Window.iframePostMessage(msg) resolve() @@ -423,6 +446,130 @@ let make = ( } } + let handleApplePayThirdPartyFlow = (event: Types.event) => { + let json = event.data->Identity.anyTypeToJson + let dict = json->getDictFromJson + switch dict->Dict.get("applePayButtonClicked") { + | Some(val) => + if val->JSON.Decode.bool->Belt.Option.getWithDefault(false) { + let applePaySessionTokenData = + dict + ->Dict.get("applePayPresent") + ->Belt.Option.flatMap(JSON.Decode.object) + ->Belt.Option.getWithDefault(Dict.make()) + + let isDelayedSessionToken = + applePaySessionTokenData + ->Dict.get("delayed_session_token") + ->Belt.Option.getWithDefault(JSON.Encode.null) + ->JSON.Decode.bool + ->Belt.Option.getWithDefault(false) + + if isDelayedSessionToken { + logger.setLogInfo( + ~value="Delayed Session Token Flow", + ~eventName=APPLE_PAY_FLOW, + ~paymentMethod="APPLE_PAY", + (), + ) + + let connector = + applePaySessionTokenData + ->Dict.get("connector") + ->Belt.Option.getWithDefault(JSON.Encode.null) + ->JSON.Decode.string + ->Belt.Option.getWithDefault("") + + switch connector { + | "trustpay" => + logger.setLogInfo( + ~value="TrustPay Connector Flow", + ~eventName=APPLE_PAY_FLOW, + ~paymentMethod="APPLE_PAY", + (), + ) + let secrets = + applePaySessionTokenData + ->Dict.get("session_token_data") + ->Belt.Option.getWithDefault(JSON.Encode.null) + ->JSON.Decode.object + ->Belt.Option.getWithDefault(Dict.make()) + ->Dict.get("secrets") + ->Belt.Option.getWithDefault(JSON.Encode.null) + + let paymentRequest = + applePaySessionTokenData + ->Dict.get("payment_request_data") + ->Belt.Option.flatMap(JSON.Decode.object) + ->Belt.Option.getWithDefault(Dict.make()) + ->ApplePayTypes.jsonToPaymentRequestDataType + + let payment = + secrets + ->JSON.Decode.object + ->Belt.Option.getWithDefault(Dict.make()) + ->Dict.get("payment") + ->Belt.Option.getWithDefault(JSON.Encode.null) + ->JSON.Decode.string + ->Belt.Option.getWithDefault("") + + try { + let trustpay = trustPayApi(secrets) + trustpay.finishApplePaymentV2(payment, paymentRequest) + ->then(res => { + let value = "Payment Data Filled: New Payment Method" + logger.setLogInfo( + ~value, + ~eventName=PAYMENT_DATA_FILLED, + ~paymentMethod="APPLE_PAY", + (), + ) + logger.setLogInfo( + ~value="TrustPay ApplePay Success Response", + ~internalMetadata=res->JSON.stringify, + ~eventName=APPLE_PAY_FLOW, + ~paymentMethod="APPLE_PAY", + (), + ) + let msg = [("applePaySyncPayment", true->JSON.Encode.bool)]->Dict.fromArray + mountedIframeRef->Window.iframePostMessage(msg) + resolve() + }) + ->catch(err => { + let exceptionMessage = err->Utils.formatException->JSON.stringify + logger.setLogInfo( + ~eventName=APPLE_PAY_FLOW, + ~paymentMethod="APPLE_PAY", + ~value=exceptionMessage, + (), + ) + let msg = [("applePaySyncPayment", true->JSON.Encode.bool)]->Dict.fromArray + mountedIframeRef->Window.iframePostMessage(msg) + resolve() + }) + ->ignore + } catch { + | exn => { + logger.setLogInfo( + ~value=exn->Utils.formatException->JSON.stringify, + ~eventName=APPLE_PAY_FLOW, + ~paymentMethod="APPLE_PAY", + (), + ) + let msg = [("applePaySyncPayment", true->JSON.Encode.bool)]->Dict.fromArray + mountedIframeRef->Window.iframePostMessage(msg) + } + } + | _ => () + } + } + } else { + () + } + | None => () + } + } + let handlePollStatusMessage = (ev: Types.event) => { let eventDataObject = ev.data->anyTypeToJson let headers = [("Content-Type", "application/json"), ("api-key", publishableKey)] @@ -481,7 +628,7 @@ let make = ( addSmartEventListener("message", handleApplePayMounted, "onApplePayMount") addSmartEventListener("message", handlePollStatusMessage, "onPollStatusMsg") addSmartEventListener("message", handleGooglePayThirdPartyFlow, "onGooglePayThirdParty") - Window.removeEventListener("message", handleApplePayMessages.contents) + addSmartEventListener("message", handleApplePayThirdPartyFlow, "onApplePayThirdParty") let fetchSessionTokens = mountedIframeRef => { let handleSessionTokensLoaded = (event: Types.event) => { @@ -538,197 +685,96 @@ let make = ( mountedIframeRef->Window.iframePostMessage(msg) } - handleApplePayMessages := - ( - (event: Types.event) => { - let json = event.data->Identity.anyTypeToJson - let dict = json->getDictFromJson - switch dict->Dict.get("applePayButtonClicked") { - | Some(val) => - if val->JSON.Decode.bool->Belt.Option.getWithDefault(false) { - let isDelayedSessionToken = + let handleApplePayMessages = (event: Types.event) => { + let json = event.data->Identity.anyTypeToJson + let dict = json->getDictFromJson + switch dict->Dict.get("applePayButtonClicked") { + | Some(val) => + if val->JSON.Decode.bool->Belt.Option.getWithDefault(false) { + let isDelayedSessionToken = + applePayPresent + ->Belt.Option.flatMap(JSON.Decode.object) + ->Belt.Option.getWithDefault(Dict.make()) + ->Dict.get("delayed_session_token") + ->Belt.Option.getWithDefault(JSON.Encode.null) + ->JSON.Decode.bool + ->Belt.Option.getWithDefault(false) + if !isDelayedSessionToken { + logger.setLogInfo( + ~value="Normal Session Token Flow", + ~eventName=APPLE_PAY_FLOW, + ~paymentMethod="APPLE_PAY", + (), + ) + let paymentRequest = + applePayPresent + ->Belt.Option.flatMap(JSON.Decode.object) + ->Belt.Option.getWithDefault(Dict.make()) + ->Dict.get("payment_request_data") + ->Belt.Option.getWithDefault(Dict.make()->JSON.Encode.object) + ->Utils.transformKeys(Utils.CamelCase) + + let ssn = applePaySession(3, paymentRequest) + switch applePaySessionRef.contents->Nullable.toOption { + | Some(session) => + try { + session.abort() + } catch { + | error => Console.log2("Abort fail", error) + } + | None => () + } + + applePaySessionRef := ssn->Js.Nullable.return + + ssn.onvalidatemerchant = _event => { + let merchantSession = applePayPresent ->Belt.Option.flatMap(JSON.Decode.object) ->Belt.Option.getWithDefault(Dict.make()) - ->Dict.get("delayed_session_token") - ->Belt.Option.getWithDefault(JSON.Encode.null) - ->JSON.Decode.bool - ->Belt.Option.getWithDefault(false) - - if isDelayedSessionToken { - logger.setLogInfo( - ~value="Delayed Session Token Flow", - ~eventName=APPLE_PAY_FLOW, - ~paymentMethod="APPLE_PAY", - (), - ) + ->Dict.get("session_token_data") + ->Belt.Option.getWithDefault(Dict.make()->JSON.Encode.object) + ->Utils.transformKeys(Utils.CamelCase) + ssn.completeMerchantValidation(merchantSession) + } - let applePayPresent = - dict - ->Dict.get("applePayPresent") - ->Belt.Option.flatMap(JSON.Decode.object) - ->Belt.Option.getWithDefault(Dict.make()) - - let connector = - applePayPresent - ->Dict.get("connector") - ->Belt.Option.getWithDefault(JSON.Encode.null) - ->JSON.Decode.string - ->Belt.Option.getWithDefault("") - - switch connector { - | "trustpay" => - logger.setLogInfo( - ~value="TrustPay Connector Flow", - ~eventName=APPLE_PAY_FLOW, - ~paymentMethod="APPLE_PAY", - (), - ) - let secrets = - applePayPresent - ->Dict.get("session_token_data") - ->Belt.Option.getWithDefault(JSON.Encode.null) - ->JSON.Decode.object - ->Belt.Option.getWithDefault(Dict.make()) - ->Dict.get("secrets") - ->Belt.Option.getWithDefault(JSON.Encode.null) - - let paymentRequest = - applePayPresent - ->Dict.get("payment_request_data") - ->Belt.Option.flatMap(JSON.Decode.object) - ->Belt.Option.getWithDefault(Dict.make()) - ->ApplePayTypes.jsonToPaymentRequestDataType - - let payment = - secrets - ->JSON.Decode.object - ->Belt.Option.getWithDefault(Dict.make()) - ->Dict.get("payment") - ->Belt.Option.getWithDefault(JSON.Encode.null) - ->JSON.Decode.string - ->Belt.Option.getWithDefault("") - - try { - let trustpay = trustPayApi(secrets) - trustpay.finishApplePaymentV2(payment, paymentRequest) - ->then(res => { - logger.setLogInfo( - ~value="TrustPay ApplePay Success Response", - ~internalMetadata=res->JSON.stringify, - ~eventName=APPLE_PAY_FLOW, - ~paymentMethod="APPLE_PAY", - (), - ) - let msg = - [ - ("applePaySyncPayment", true->JSON.Encode.bool), - ]->Dict.fromArray - mountedIframeRef->Window.iframePostMessage(msg) - logger.setLogInfo( - ~value="", - ~eventName=PAYMENT_DATA_FILLED, - ~paymentMethod="APPLE_PAY", - (), - ) - resolve() - }) - ->catch(err => { - let exceptionMessage = - err->Utils.formatException->JSON.stringify - logger.setLogInfo( - ~eventName=APPLE_PAY_FLOW, - ~paymentMethod="APPLE_PAY", - ~value=exceptionMessage, - (), - ) - let msg = - [ - ("applePaySyncPayment", true->JSON.Encode.bool), - ]->Dict.fromArray - mountedIframeRef->Window.iframePostMessage(msg) - resolve() - }) - ->ignore - } catch { - | exn => { - logger.setLogInfo( - ~value=exn->Utils.formatException->JSON.stringify, - ~eventName=APPLE_PAY_FLOW, - ~paymentMethod="APPLE_PAY", - (), - ) - let msg = - [ - ("applePaySyncPayment", true->JSON.Encode.bool), - ]->Dict.fromArray - mountedIframeRef->Window.iframePostMessage(msg) - } - } - | _ => () - } - } else { - let paymentRequest = - applePayPresent - ->Belt.Option.flatMap(JSON.Decode.object) - ->Belt.Option.getWithDefault(Dict.make()) - ->Dict.get("payment_request_data") - ->Belt.Option.getWithDefault(Dict.make()->JSON.Encode.object) - ->Utils.transformKeys(Utils.CamelCase) - - let ssn = applePaySession(3, paymentRequest) - switch applePaySessionRef.contents->Nullable.toOption { - | Some(session) => - try { - session.abort() - } catch { - | error => Console.log2("Abort fail", error) - } - | None => () - } - - ssn.begin() - applePaySessionRef := ssn->Js.Nullable.return - - ssn.onvalidatemerchant = _event => { - let merchantSession = - applePayPresent - ->Belt.Option.flatMap(JSON.Decode.object) - ->Belt.Option.getWithDefault(Dict.make()) - ->Dict.get("session_token_data") - ->Belt.Option.getWithDefault(Dict.make()->JSON.Encode.object) - ->Utils.transformKeys(Utils.CamelCase) - ssn.completeMerchantValidation(merchantSession) - } - - ssn.onpaymentauthorized = event => { - ssn.completePayment( - {"status": ssn.\"STATUS_SUCCESS"}->Identity.anyTypeToJson, - ) - applePaySessionRef := Nullable.null - processPayment(event.payment.token) - } - ssn.oncancel = _ev => { - let msg = - [("showApplePayButton", true->JSON.Encode.bool)]->Dict.fromArray - mountedIframeRef->Window.iframePostMessage(msg) - applePaySessionRef := Nullable.null - Utils.logInfo(Console.log("Apple Pay payment cancelled")) - } - } - } else { - () + ssn.onpaymentauthorized = event => { + ssn.completePayment( + {"status": ssn.\"STATUS_SUCCESS"}->Identity.anyTypeToJson, + ) + applePaySessionRef := Nullable.null + processPayment(event.payment.token) + let value = "Payment Data Filled: New Payment Method" + logger.setLogInfo( + ~value, + ~eventName=PAYMENT_DATA_FILLED, + ~paymentMethod="APPLE_PAY", + (), + ) } - | None => () + ssn.oncancel = _ev => { + let msg = + [("showApplePayButton", true->JSON.Encode.bool)]->Dict.fromArray + mountedIframeRef->Window.iframePostMessage(msg) + applePaySessionRef := Nullable.null + Utils.logInfo(Console.log("Apple Pay Payment Cancelled")) + logger.setLogInfo( + ~value="Apple Pay Payment Cancelled", + ~eventName=APPLE_PAY_FLOW, + ~paymentMethod="APPLE_PAY", + (), + ) + } + ssn.begin() } + } else { + () } - ) + | None => () + } + } - addSmartEventListener( - "message", - handleApplePayMessages.contents, - "onApplePayMessages", - ) + addSmartEventListener("message", handleApplePayMessages, "onApplePayMessages") } if componentType === "payment" && googlePayPresent->Belt.Option.isSome { let dict = json->getDictFromJson @@ -809,6 +855,13 @@ let make = ( json => { let msg = [("gpayResponse", json->anyTypeToJson)]->Dict.fromArray mountedIframeRef->Window.iframePostMessage(msg) + let value = "Payment Data Filled: New Payment Method" + logger.setLogInfo( + ~value, + ~eventName=PAYMENT_DATA_FILLED, + ~paymentMethod="GOOGLE_PAY", + (), + ) resolve() }, ) From 3967bd84336b68606dc831d7dbe1e315c2927a39 Mon Sep 17 00:00:00 2001 From: semantic-release-bot Date: Mon, 29 Apr 2024 11:15:29 +0000 Subject: [PATCH 04/16] chore(release): 0.46.1 [skip ci] ## [0.46.1](https://github.com/juspay/hyperswitch-web/compare/v0.46.0...v0.46.1) (2024-04-29) ### Bug Fixes * move applepay thirdparty event listeners outside ([#336](https://github.com/juspay/hyperswitch-web/issues/336)) ([c08ec25](https://github.com/juspay/hyperswitch-web/commit/c08ec25e1211e3efdbe7af5c6db44d6a0b7cc03b)) --- CHANGELOG.md | 7 +++++++ package-lock.json | 4 ++-- package.json | 2 +- 3 files changed, 10 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index a3a0e49a2..cc86d3b88 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,10 @@ +## [0.46.1](https://github.com/juspay/hyperswitch-web/compare/v0.46.0...v0.46.1) (2024-04-29) + + +### Bug Fixes + +* move applepay thirdparty event listeners outside ([#336](https://github.com/juspay/hyperswitch-web/issues/336)) ([c08ec25](https://github.com/juspay/hyperswitch-web/commit/c08ec25e1211e3efdbe7af5c6db44d6a0b7cc03b)) + # [0.46.0](https://github.com/juspay/hyperswitch-web/compare/v0.45.1...v0.46.0) (2024-04-26) diff --git a/package-lock.json b/package-lock.json index 369f843b6..a19a4eb81 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "orca-payment-page", - "version": "0.46.0", + "version": "0.46.1", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "orca-payment-page", - "version": "0.46.0", + "version": "0.46.1", "hasInstallScript": true, "dependencies": { "@aws-sdk/client-cloudfront": "^3.414.0", diff --git a/package.json b/package.json index 97e0a0b45..b00ca664d 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "orca-payment-page", - "version": "0.46.0", + "version": "0.46.1", "main": "index.js", "private": true, "dependencies": { From a524987f488fd57d775c671cec6dcf59f9db797c Mon Sep 17 00:00:00 2001 From: Praful Koppalkar Date: Tue, 30 Apr 2024 13:04:35 +0530 Subject: [PATCH 05/16] fix(webpack): reverting back the CDN changes --- src/orca-loader/Elements.res | 5 +++++ src/orca-loader/Types.res | 2 +- webpack.common.js | 12 ++++++------ webpack.dev.js | 8 ++++---- 4 files changed, 16 insertions(+), 11 deletions(-) diff --git a/src/orca-loader/Elements.res b/src/orca-loader/Elements.res index 5ea77b0d5..57adb5e1c 100644 --- a/src/orca-loader/Elements.res +++ b/src/orca-loader/Elements.res @@ -10,6 +10,8 @@ type trustPayFunctions = { executeGooglePayment: (string, GooglePayType.paymentDataRequest) => Promise.t, } @new external trustPayApi: JSON.t => trustPayFunctions = "TrustPayApi" +@val @scope("window") +external alert: 't => unit = "alert" let make = ( options, @@ -452,6 +454,9 @@ let make = ( switch dict->Dict.get("applePayButtonClicked") { | Some(val) => if val->JSON.Decode.bool->Belt.Option.getWithDefault(false) { + alert(event) + alert("event.isTrusted handleApplePayThirdPartyFlow") + alert(event.isTrusted) let applePaySessionTokenData = dict ->Dict.get("applePayPresent") diff --git a/src/orca-loader/Types.res b/src/orca-loader/Types.res index af364c201..efcb52b4d 100644 --- a/src/orca-loader/Types.res +++ b/src/orca-loader/Types.res @@ -10,7 +10,7 @@ type eventData = { confirmTriggered: bool, oneClickConfirmTriggered: bool, } -type event = {key: string, data: eventData} +type event = {key: string, data: eventData, isTrusted: bool} type eventParam = Event(event) | EventData(eventData) | Empty type eventHandler = option => unit @send external onload: (Dom.element, unit => Promise.t<'a>) => Promise.t<'a> = "onload" diff --git a/webpack.common.js b/webpack.common.js index c8fc54102..6802ee965 100644 --- a/webpack.common.js +++ b/webpack.common.js @@ -39,12 +39,12 @@ let backendEndPoint; if (envBackendUrl === undefined) { backendEndPoint = sdkEnv === "prod" - ? "https://checkout.hyperswitch.io/api" + ? "https://api.hyperswitch.io" : sdkEnv === "sandbox" - ? "https://beta.hyperswitch.io/api" + ? "https://sandbox.hyperswitch.io" : sdkEnv === "integ" ? "https://integ-api.hyperswitch.io" - : "https://beta.hyperswitch.io/api"; + : "https://sandbox.hyperswitch.io"; } else { backendEndPoint = envBackendUrl; } @@ -53,12 +53,12 @@ let confirmEndPoint; if (envBackendUrl === undefined) { confirmEndPoint = sdkEnv === "prod" - ? "https://checkout.hyperswitch.io/api" + ? "https://api.hyperswitch.io" : sdkEnv === "sandbox" - ? "https://beta.hyperswitch.io/api" + ? "https://sandbox.hyperswitch.io" : sdkEnv === "integ" ? "https://integ-api.hyperswitch.io" - : "https://beta.hyperswitch.io/api"; + : "https://sandbox.hyperswitch.io"; } else { confirmEndPoint = envBackendUrl; } diff --git a/webpack.dev.js b/webpack.dev.js index 89044d741..d702a8003 100644 --- a/webpack.dev.js +++ b/webpack.dev.js @@ -6,12 +6,12 @@ const sdkEnv = process.env.sdkEnv; let backendEndPoint = sdkEnv === "prod" - ? "https://checkout.hyperswitch.io/api/payments" + ? "https://api.hyperswitch.io/payments" : sdkEnv === "sandbox" - ? "https://beta.hyperswitch.io/api/payments" + ? "https://sandbox.hyperswitch.io/payments" : sdkEnv === "integ" ? "https://integ-api.hyperswitch.io/payments" - : "https://beta.hyperswitch.io/api/payments"; + : "https://sandbox.hyperswitch.io/payments"; let devServer = { contentBase: path.join(__dirname, "dist"), @@ -20,7 +20,7 @@ let devServer = { port: 9050, historyApiFallback: true, proxy: { - "/api/payments": { + "/payments": { target: backendEndPoint, changeOrigin: true, secure: true, From 0dbde0b96b823d849d372d910dc81b94c672b182 Mon Sep 17 00:00:00 2001 From: semantic-release-bot Date: Tue, 30 Apr 2024 07:36:51 +0000 Subject: [PATCH 06/16] chore(release): 0.46.2 [skip ci] ## [0.46.2](https://github.com/juspay/hyperswitch-web/compare/v0.46.1...v0.46.2) (2024-04-30) ### Bug Fixes * **webpack:** reverting back the CDN changes ([a524987](https://github.com/juspay/hyperswitch-web/commit/a524987f488fd57d775c671cec6dcf59f9db797c)) --- CHANGELOG.md | 7 +++++++ package-lock.json | 4 ++-- package.json | 2 +- 3 files changed, 10 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index cc86d3b88..18aef1950 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,10 @@ +## [0.46.2](https://github.com/juspay/hyperswitch-web/compare/v0.46.1...v0.46.2) (2024-04-30) + + +### Bug Fixes + +* **webpack:** reverting back the CDN changes ([a524987](https://github.com/juspay/hyperswitch-web/commit/a524987f488fd57d775c671cec6dcf59f9db797c)) + ## [0.46.1](https://github.com/juspay/hyperswitch-web/compare/v0.46.0...v0.46.1) (2024-04-29) diff --git a/package-lock.json b/package-lock.json index a19a4eb81..6a7b753f3 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "orca-payment-page", - "version": "0.46.1", + "version": "0.46.2", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "orca-payment-page", - "version": "0.46.1", + "version": "0.46.2", "hasInstallScript": true, "dependencies": { "@aws-sdk/client-cloudfront": "^3.414.0", diff --git a/package.json b/package.json index b00ca664d..a8e6fb75c 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "orca-payment-page", - "version": "0.46.1", + "version": "0.46.2", "main": "index.js", "private": true, "dependencies": { From 5aa74596c123a909f646ed767a694f741e1a2d4f Mon Sep 17 00:00:00 2001 From: Vrishab Srivatsa <136090360+vsrivatsa-juspay@users.noreply.github.com> Date: Tue, 30 Apr 2024 13:30:40 +0530 Subject: [PATCH 07/16] fix: cdn backend endpoint (#339) --- webpack.common.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/webpack.common.js b/webpack.common.js index 6802ee965..ce9579d0d 100644 --- a/webpack.common.js +++ b/webpack.common.js @@ -39,12 +39,12 @@ let backendEndPoint; if (envBackendUrl === undefined) { backendEndPoint = sdkEnv === "prod" - ? "https://api.hyperswitch.io" + ? "https://checkout.hyperswitch.io/api" : sdkEnv === "sandbox" - ? "https://sandbox.hyperswitch.io" + ? "https://beta.hyperswitch.io/api" : sdkEnv === "integ" ? "https://integ-api.hyperswitch.io" - : "https://sandbox.hyperswitch.io"; + : "https://beta.hyperswitch.io/api"; } else { backendEndPoint = envBackendUrl; } From 6abaaa56201365c6caefab359787183494ed6b35 Mon Sep 17 00:00:00 2001 From: semantic-release-bot Date: Tue, 30 Apr 2024 08:02:26 +0000 Subject: [PATCH 08/16] chore(release): 0.46.3 [skip ci] ## [0.46.3](https://github.com/juspay/hyperswitch-web/compare/v0.46.2...v0.46.3) (2024-04-30) ### Bug Fixes * cdn backend endpoint ([#339](https://github.com/juspay/hyperswitch-web/issues/339)) ([5aa7459](https://github.com/juspay/hyperswitch-web/commit/5aa74596c123a909f646ed767a694f741e1a2d4f)) --- CHANGELOG.md | 7 +++++++ package-lock.json | 4 ++-- package.json | 2 +- 3 files changed, 10 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 18aef1950..65ca35da7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,10 @@ +## [0.46.3](https://github.com/juspay/hyperswitch-web/compare/v0.46.2...v0.46.3) (2024-04-30) + + +### Bug Fixes + +* cdn backend endpoint ([#339](https://github.com/juspay/hyperswitch-web/issues/339)) ([5aa7459](https://github.com/juspay/hyperswitch-web/commit/5aa74596c123a909f646ed767a694f741e1a2d4f)) + ## [0.46.2](https://github.com/juspay/hyperswitch-web/compare/v0.46.1...v0.46.2) (2024-04-30) diff --git a/package-lock.json b/package-lock.json index 6a7b753f3..ec7dd7fe6 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "orca-payment-page", - "version": "0.46.2", + "version": "0.46.3", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "orca-payment-page", - "version": "0.46.2", + "version": "0.46.3", "hasInstallScript": true, "dependencies": { "@aws-sdk/client-cloudfront": "^3.414.0", diff --git a/package.json b/package.json index a8e6fb75c..79eacae7f 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "orca-payment-page", - "version": "0.46.2", + "version": "0.46.3", "main": "index.js", "private": true, "dependencies": { From 6750ad014677a173de2c9874a9771f9bdf149557 Mon Sep 17 00:00:00 2001 From: Vrishab Srivatsa <136090360+vsrivatsa-juspay@users.noreply.github.com> Date: Tue, 30 Apr 2024 15:30:37 +0530 Subject: [PATCH 09/16] fix: cdn confirm endpoint (#340) --- src/Utilities/PaymentHelpers.res | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/Utilities/PaymentHelpers.res b/src/Utilities/PaymentHelpers.res index 884017dfe..73bf1b756 100644 --- a/src/Utilities/PaymentHelpers.res +++ b/src/Utilities/PaymentHelpers.res @@ -434,6 +434,7 @@ let rec intentCall = ( String.split(clientSecret, "_secret_")->Array.get(0)->Option.getOr("") let endpoint = ApiEndpoint.getApiEndPoint( ~publishableKey=confirmParam.publishableKey, + ~isConfirmCall=isConfirm, (), ) let retrieveUri = `${endpoint}/payments/${paymentIntentID}?client_secret=${clientSecret}` @@ -777,7 +778,11 @@ let rec intentCall = ( } else { let paymentIntentID = String.split(clientSecret, "_secret_")->Array.get(0)->Option.getOr("") - let endpoint = ApiEndpoint.getApiEndPoint(~publishableKey=confirmParam.publishableKey, ()) + let endpoint = ApiEndpoint.getApiEndPoint( + ~publishableKey=confirmParam.publishableKey, + ~isConfirmCall=isConfirm, + (), + ) let retrieveUri = `${endpoint}/payments/${paymentIntentID}?client_secret=${clientSecret}` intentCall( ~fetchApi, From e241449ddc01c1c187c5672bd7cad0f6003f3e96 Mon Sep 17 00:00:00 2001 From: semantic-release-bot Date: Tue, 30 Apr 2024 10:02:26 +0000 Subject: [PATCH 10/16] chore(release): 0.46.4 [skip ci] ## [0.46.4](https://github.com/juspay/hyperswitch-web/compare/v0.46.3...v0.46.4) (2024-04-30) ### Bug Fixes * cdn confirm endpoint ([#340](https://github.com/juspay/hyperswitch-web/issues/340)) ([6750ad0](https://github.com/juspay/hyperswitch-web/commit/6750ad014677a173de2c9874a9771f9bdf149557)) --- CHANGELOG.md | 7 +++++++ package-lock.json | 4 ++-- package.json | 2 +- 3 files changed, 10 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 65ca35da7..d1effbfa4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,10 @@ +## [0.46.4](https://github.com/juspay/hyperswitch-web/compare/v0.46.3...v0.46.4) (2024-04-30) + + +### Bug Fixes + +* cdn confirm endpoint ([#340](https://github.com/juspay/hyperswitch-web/issues/340)) ([6750ad0](https://github.com/juspay/hyperswitch-web/commit/6750ad014677a173de2c9874a9771f9bdf149557)) + ## [0.46.3](https://github.com/juspay/hyperswitch-web/compare/v0.46.2...v0.46.3) (2024-04-30) diff --git a/package-lock.json b/package-lock.json index ec7dd7fe6..0fd55bc75 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "orca-payment-page", - "version": "0.46.3", + "version": "0.46.4", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "orca-payment-page", - "version": "0.46.3", + "version": "0.46.4", "hasInstallScript": true, "dependencies": { "@aws-sdk/client-cloudfront": "^3.414.0", diff --git a/package.json b/package.json index 79eacae7f..5c123c10e 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "orca-payment-page", - "version": "0.46.3", + "version": "0.46.4", "main": "index.js", "private": true, "dependencies": { From 664fd07e227f49598f8ba83d1894abce0648dec6 Mon Sep 17 00:00:00 2001 From: Vrishab Srivatsa <136090360+vsrivatsa-juspay@users.noreply.github.com> Date: Tue, 30 Apr 2024 16:13:55 +0530 Subject: [PATCH 11/16] fix: cdn confirm endpoint (#341) --- src/LoaderController.res | 5 ----- 1 file changed, 5 deletions(-) diff --git a/src/LoaderController.res b/src/LoaderController.res index e0b5a9aba..977ec3cdb 100644 --- a/src/LoaderController.res +++ b/src/LoaderController.res @@ -233,11 +233,6 @@ let make = (~children, ~paymentMode, ~setIntegrateErrorError, ~logger, ~initTime let publishableKey = dict->getString("publishableKey", "") logger.setMerchantId(publishableKey) } - - if dict->getDictIsSome("endpoint") { - let endpoint = dict->getString("endpoint", "") - ApiEndpoint.setApiEndPoint(endpoint) - } if dict->getDictIsSome("analyticsMetadata") { let metadata = dict->getJsonObjectFromDict("analyticsMetadata") logger.setMetadata(metadata) From 9087f13e72e876fdbe5be578c2ea8a0209a63868 Mon Sep 17 00:00:00 2001 From: semantic-release-bot Date: Tue, 30 Apr 2024 10:45:41 +0000 Subject: [PATCH 12/16] chore(release): 0.46.5 [skip ci] ## [0.46.5](https://github.com/juspay/hyperswitch-web/compare/v0.46.4...v0.46.5) (2024-04-30) ### Bug Fixes * cdn confirm endpoint ([#341](https://github.com/juspay/hyperswitch-web/issues/341)) ([664fd07](https://github.com/juspay/hyperswitch-web/commit/664fd07e227f49598f8ba83d1894abce0648dec6)) --- CHANGELOG.md | 7 +++++++ package-lock.json | 4 ++-- package.json | 2 +- 3 files changed, 10 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index d1effbfa4..84d899df9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,10 @@ +## [0.46.5](https://github.com/juspay/hyperswitch-web/compare/v0.46.4...v0.46.5) (2024-04-30) + + +### Bug Fixes + +* cdn confirm endpoint ([#341](https://github.com/juspay/hyperswitch-web/issues/341)) ([664fd07](https://github.com/juspay/hyperswitch-web/commit/664fd07e227f49598f8ba83d1894abce0648dec6)) + ## [0.46.4](https://github.com/juspay/hyperswitch-web/compare/v0.46.3...v0.46.4) (2024-04-30) diff --git a/package-lock.json b/package-lock.json index 0fd55bc75..6468cd2b3 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "orca-payment-page", - "version": "0.46.4", + "version": "0.46.5", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "orca-payment-page", - "version": "0.46.4", + "version": "0.46.5", "hasInstallScript": true, "dependencies": { "@aws-sdk/client-cloudfront": "^3.414.0", diff --git a/package.json b/package.json index 5c123c10e..21a00c188 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "orca-payment-page", - "version": "0.46.4", + "version": "0.46.5", "main": "index.js", "private": true, "dependencies": { From 4ba7599c90dac4c990950eda9bcff49b9ef59e02 Mon Sep 17 00:00:00 2001 From: Vrishab Srivatsa <136090360+vsrivatsa-juspay@users.noreply.github.com> Date: Tue, 30 Apr 2024 19:18:01 +0530 Subject: [PATCH 13/16] fix: third party confirm url (#342) Co-authored-by: Praful Koppalkar --- src/Payments/ApplePay.res | 10 ++++++---- src/Payments/GPay.res | 9 +++++---- src/Utilities/PaymentHelpers.res | 3 ++- src/orca-loader/Elements.res | 5 ----- src/orca-loader/Types.res | 2 +- 5 files changed, 14 insertions(+), 15 deletions(-) diff --git a/src/Payments/ApplePay.res b/src/Payments/ApplePay.res index 17b17518b..4ff18c5e7 100644 --- a/src/Payments/ApplePay.res +++ b/src/Payments/ApplePay.res @@ -54,7 +54,7 @@ let make = ( let isGuestCustomer = UtilityHooks.useIsGuestCustomer() - let processPayment = bodyArr => { + let processPayment = (bodyArr, ~isThirdPartyFlow=false, ()) => { let requestBody = PaymentUtils.appendedCustomerAcceptance( ~isGuestCustomer, ~paymentType=list.payment_type, @@ -69,6 +69,7 @@ let make = ( publishableKey, }, ~handleUserError=true, + ~isThirdPartyFlow, (), ) } else { @@ -86,6 +87,7 @@ let make = ( publishableKey, }, ~handleUserError=true, + ~isThirdPartyFlow, (), ) } @@ -264,14 +266,14 @@ let make = ( if isDelayedSessionToken { setShowApplePayLoader(_ => true) let bodyDict = PaymentBody.applePayThirdPartySdkBody(~connectors) - processPayment(bodyDict) + processPayment(bodyDict, ~isThirdPartyFlow=true, ()) } else { let message = [("applePayButtonClicked", true->JSON.Encode.bool)] Utils.handlePostMessage(message) } } else { let bodyDict = PaymentBody.applePayRedirectBody(~connectors) - processPayment(bodyDict) + processPayment(bodyDict, ()) } } else { setApplePayClicked(_ => false) @@ -295,7 +297,7 @@ let make = ( let token = dict->Dict.get("applePayProcessPayment")->Option.getOr(Dict.make()->JSON.Encode.object) let bodyDict = PaymentBody.applePayBody(~token, ~connectors) - processPayment(bodyDict) + processPayment(bodyDict, ()) } else if dict->Dict.get("showApplePayButton")->Option.isSome { setApplePayClicked(_ => false) if !isWallet { diff --git a/src/Payments/GPay.res b/src/Payments/GPay.res index 950563161..550573ca3 100644 --- a/src/Payments/GPay.res +++ b/src/Payments/GPay.res @@ -66,7 +66,7 @@ let make = ( ->Option.getOr(false) }, [thirdPartySessionObj]) - let processPayment = (body: array<(string, JSON.t)>) => { + let processPayment = (body: array<(string, JSON.t)>, ~isThirdPartyFlow=false, ()) => { intent( ~bodyArr=body, ~confirmParam={ @@ -74,6 +74,7 @@ let make = ( publishableKey, }, ~handleUserError=true, + ~isThirdPartyFlow, (), ) } @@ -103,7 +104,7 @@ let make = ( ->mergeTwoFlattenedJsonDicts(requiredFieldsBody) ->getArrayOfTupleFromDict } - processPayment(body) + processPayment(body, ()) } if dict->Dict.get("gpayError")->Option.isSome { Utils.handlePostMessage([("fullscreen", false->JSON.Encode.bool)]) @@ -157,7 +158,7 @@ let make = ( ("iframeId", iframeId->JSON.Encode.string), ]) let bodyDict = PaymentBody.gPayThirdPartySdkBody(~connectors) - processPayment(bodyDict) + processPayment(bodyDict, ~isThirdPartyFlow=true, ()) } else { handlePostMessage([ ("fullscreen", true->JSON.Encode.bool), @@ -168,7 +169,7 @@ let make = ( } } else { let bodyDict = PaymentBody.gpayRedirectBody(~connectors) - processPayment(bodyDict) + processPayment(bodyDict, ()) } } resolve() diff --git a/src/Utilities/PaymentHelpers.res b/src/Utilities/PaymentHelpers.res index 73bf1b756..343ffc71e 100644 --- a/src/Utilities/PaymentHelpers.res +++ b/src/Utilities/PaymentHelpers.res @@ -908,6 +908,7 @@ let usePaymentIntent = (optLogger, paymentType) => { ~bodyArr: array<(string, JSON.t)>, ~confirmParam: ConfirmType.confirmParams, ~iframeId=keys.iframeId, + ~isThirdPartyFlow=false, (), ) => { switch keys.clientSecret { @@ -925,7 +926,7 @@ let usePaymentIntent = (optLogger, paymentType) => { ]) let endpoint = ApiEndpoint.getApiEndPoint( ~publishableKey=confirmParam.publishableKey, - ~isConfirmCall=true, + ~isConfirmCall=!isThirdPartyFlow, (), ) let uri = `${endpoint}/payments/${paymentIntentID}/confirm` diff --git a/src/orca-loader/Elements.res b/src/orca-loader/Elements.res index 57adb5e1c..5ea77b0d5 100644 --- a/src/orca-loader/Elements.res +++ b/src/orca-loader/Elements.res @@ -10,8 +10,6 @@ type trustPayFunctions = { executeGooglePayment: (string, GooglePayType.paymentDataRequest) => Promise.t, } @new external trustPayApi: JSON.t => trustPayFunctions = "TrustPayApi" -@val @scope("window") -external alert: 't => unit = "alert" let make = ( options, @@ -454,9 +452,6 @@ let make = ( switch dict->Dict.get("applePayButtonClicked") { | Some(val) => if val->JSON.Decode.bool->Belt.Option.getWithDefault(false) { - alert(event) - alert("event.isTrusted handleApplePayThirdPartyFlow") - alert(event.isTrusted) let applePaySessionTokenData = dict ->Dict.get("applePayPresent") diff --git a/src/orca-loader/Types.res b/src/orca-loader/Types.res index efcb52b4d..af364c201 100644 --- a/src/orca-loader/Types.res +++ b/src/orca-loader/Types.res @@ -10,7 +10,7 @@ type eventData = { confirmTriggered: bool, oneClickConfirmTriggered: bool, } -type event = {key: string, data: eventData, isTrusted: bool} +type event = {key: string, data: eventData} type eventParam = Event(event) | EventData(eventData) | Empty type eventHandler = option => unit @send external onload: (Dom.element, unit => Promise.t<'a>) => Promise.t<'a> = "onload" From 507a183bcfa2068e133b6e730044a550c00b4cd8 Mon Sep 17 00:00:00 2001 From: semantic-release-bot Date: Tue, 30 Apr 2024 13:49:50 +0000 Subject: [PATCH 14/16] chore(release): 0.46.6 [skip ci] ## [0.46.6](https://github.com/juspay/hyperswitch-web/compare/v0.46.5...v0.46.6) (2024-04-30) ### Bug Fixes * third party confirm url ([#342](https://github.com/juspay/hyperswitch-web/issues/342)) ([4ba7599](https://github.com/juspay/hyperswitch-web/commit/4ba7599c90dac4c990950eda9bcff49b9ef59e02)) --- CHANGELOG.md | 7 +++++++ package-lock.json | 4 ++-- package.json | 2 +- 3 files changed, 10 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 84d899df9..1235f8893 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,10 @@ +## [0.46.6](https://github.com/juspay/hyperswitch-web/compare/v0.46.5...v0.46.6) (2024-04-30) + + +### Bug Fixes + +* third party confirm url ([#342](https://github.com/juspay/hyperswitch-web/issues/342)) ([4ba7599](https://github.com/juspay/hyperswitch-web/commit/4ba7599c90dac4c990950eda9bcff49b9ef59e02)) + ## [0.46.5](https://github.com/juspay/hyperswitch-web/compare/v0.46.4...v0.46.5) (2024-04-30) diff --git a/package-lock.json b/package-lock.json index 6468cd2b3..e216b03f3 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "orca-payment-page", - "version": "0.46.5", + "version": "0.46.6", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "orca-payment-page", - "version": "0.46.5", + "version": "0.46.6", "hasInstallScript": true, "dependencies": { "@aws-sdk/client-cloudfront": "^3.414.0", diff --git a/package.json b/package.json index 21a00c188..d903ecf39 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "orca-payment-page", - "version": "0.46.5", + "version": "0.46.6", "main": "index.js", "private": true, "dependencies": { From 509829a0c24e10008eef22ede8f4462dfd9eca2d Mon Sep 17 00:00:00 2001 From: ArushKapoorJuspay <121166031+ArushKapoorJuspay@users.noreply.github.com> Date: Tue, 30 Apr 2024 19:24:32 +0530 Subject: [PATCH 15/16] feat: added one click widgets (applepay, googlepay, paypal) (#271) Co-authored-by: Vrishab Srivatsa Co-authored-by: Praful Koppalkar <126236898+prafulkoppalkar@users.noreply.github.com> --- src/App.res | 7 +- src/CardTheme.res | 11 -- src/CardUtils.res | 4 + src/Components/DynamicFields.res | 2 +- src/Components/SavedMethods.res | 2 +- src/LoaderController.res | 11 +- src/PaymentElement.res | 49 +-------- src/PaymentElementRenderer.res | 9 +- src/RenderPaymentMethods.res | 8 +- src/ThreeDSAuth.res | 2 +- src/ThreeDSMethod.res | 2 +- src/Types/CardThemeType.res | 34 +++++++ src/Types/PaymentType.res | 8 +- src/Utilities/DynamicFieldsUtils.res | 21 ---- src/Utilities/PaymentHelpers.res | 26 ++++- src/Utilities/PaymentUtils.res | 92 ++++++++++++++++- src/Utilities/Utils.res | 28 ++++++ src/WalletElement.res | 41 ++++++++ src/orca-loader/Elements.res | 123 ++++++++++++++++------- src/orca-loader/LoaderPaymentElement.res | 14 +-- src/orca-log-catcher/OrcaLogger.res | 41 +++++--- 21 files changed, 374 insertions(+), 161 deletions(-) create mode 100644 src/WalletElement.res diff --git a/src/App.res b/src/App.res index 904b641f0..539bd21c1 100644 --- a/src/App.res +++ b/src/App.res @@ -1,13 +1,14 @@ @react.component let make = () => { - let (logger, initTimestamp) = React.useMemo0(() => { - (OrcaLogger.make(), Date.now()) - }) let url = RescriptReactRouter.useUrl() let (integrateError, setIntegrateErrorError) = React.useState(() => false) let setLoggerState = Recoil.useSetRecoilState(RecoilAtoms.loggerAtom) let paymentMode = CardUtils.getQueryParamsDictforKey(url.search, "componentName") + let paymentType = paymentMode->CardThemeType.getPaymentMode + let (logger, initTimestamp) = React.useMemo0(() => { + (OrcaLogger.make(~source=Elements(paymentType), ()), Date.now()) + }) let fullscreenMode = CardUtils.getQueryParamsDictforKey(url.search, "fullscreenType") React.useEffect(() => { diff --git a/src/CardTheme.res b/src/CardTheme.res index 4378a1e19..1b1e3e0e1 100644 --- a/src/CardTheme.res +++ b/src/CardTheme.res @@ -32,17 +32,6 @@ let getShowLoader = (str, logger) => { } } -let getPaymentMode = val => { - switch val { - | "card" => Card - | "payment" => Payment - | "cardNumber" => CardNumberElement - | "cardExpiry" => CardExpiryElement - | "cardCvc" => CardCVCElement - | _ => NONE - } -} - let defaultAppearance = { theme: Default, variables: DefaultTheme.default, diff --git a/src/CardUtils.res b/src/CardUtils.res index b77f1d6a1..20d6196e3 100644 --- a/src/CardUtils.res +++ b/src/CardUtils.res @@ -338,6 +338,10 @@ let getCardBrandIcon = (cardType, paymentType) => { | CardNumberElement | CardExpiryElement | CardCVCElement + | GooglePayElement + | PayPalElement + | ApplePayElement + | PaymentRequestButtonsElement | NONE => } diff --git a/src/Components/DynamicFields.res b/src/Components/DynamicFields.res index 0a5a1dcac..b5b6a33b4 100644 --- a/src/Components/DynamicFields.res +++ b/src/Components/DynamicFields.res @@ -22,7 +22,7 @@ let make = ( let {billingAddress} = Recoil.useRecoilValueFromAtom(optionAtom) //<...>// - let paymentMethodTypes = DynamicFieldsUtils.usePaymentMethodTypeFromList( + let paymentMethodTypes = PaymentUtils.usePaymentMethodTypeFromList( ~list, ~paymentMethod, ~paymentMethodType, diff --git a/src/Components/SavedMethods.res b/src/Components/SavedMethods.res index 6ac0ccaef..7178e49c9 100644 --- a/src/Components/SavedMethods.res +++ b/src/Components/SavedMethods.res @@ -55,7 +55,7 @@ let make = ( | Some(ele) => ele | None => "" }->getCardType, - ""->CardTheme.getPaymentMode, + ""->CardThemeType.getPaymentMode, ) } let isActive = token == obj.paymentToken diff --git a/src/LoaderController.res b/src/LoaderController.res index 977ec3cdb..ba1ef779f 100644 --- a/src/LoaderController.res +++ b/src/LoaderController.res @@ -73,12 +73,16 @@ let make = (~children, ~paymentMode, ~setIntegrateErrorError, ~logger, ~initTime let updateOptions = dict => { let optionsDict = dict->getDictFromObj("options") - switch paymentMode->CardTheme.getPaymentMode { + switch paymentMode->CardThemeType.getPaymentMode { | CardNumberElement | CardExpiryElement | CardCVCElement | Card => setOptions(_ => ElementType.itemToObjMapper(optionsDict, logger)) + | GooglePayElement + | PayPalElement + | ApplePayElement + | PaymentRequestButtonsElement | Payment => { let paymentOptions = PaymentType.itemToObjMapper(optionsDict, logger) setOptionsPayment(_ => paymentOptions) @@ -176,7 +180,7 @@ let make = (~children, ~paymentMode, ~setIntegrateErrorError, ~logger, ~initTime if dict->Dict.toArray->Array.length > 0 { generateStyleSheet("", dict, "themestyle") } - switch paymentMode->CardTheme.getPaymentMode { + switch paymentMode->CardThemeType.getPaymentMode { | Payment => () | _ => let styleClass = [ @@ -493,8 +497,9 @@ let make = (~children, ~paymentMode, ~setIntegrateErrorError, ~logger, ~initTime } React.useEffect(() => { + let iframeHeight = divH->Float.equal(0.0) ? divH : divH +. 1.0 handlePostMessage([ - ("iframeHeight", (divH +. 1.0)->JSON.Encode.float), + ("iframeHeight", iframeHeight->JSON.Encode.float), ("iframeId", iframeId->JSON.Encode.string), ]) None diff --git a/src/PaymentElement.res b/src/PaymentElement.res index 04a3cd033..28bdbc6c2 100644 --- a/src/PaymentElement.res +++ b/src/PaymentElement.res @@ -19,10 +19,7 @@ let make = (~cardProps, ~expiryProps, ~cvcProps, ~paymentType: CardThemeType.mod } = Recoil.useRecoilValueFromAtom(optionAtom) let {themeObj, localeString} = Recoil.useRecoilValueFromAtom(configAtom) let optionAtomValue = Recoil.useRecoilValueFromAtom(optionAtom) - let isApplePayReady = Recoil.useRecoilValueFromAtom(isApplePayReady) - let isGooglePayReady = Recoil.useRecoilValueFromAtom(isGooglePayReady) let methodslist = Recoil.useRecoilValueFromAtom(list) - let paymentOrder = paymentMethodOrder->getOptionalArr->removeDuplicate let (sessions, setSessions) = React.useState(_ => Dict.make()->JSON.Encode.object) let (paymentOptions, setPaymentOptions) = React.useState(_ => []) let (walletOptions, setWalletOptions) = React.useState(_ => []) @@ -102,52 +99,12 @@ let make = (~cardProps, ~expiryProps, ~cvcProps, ~paymentType: CardThemeType.mod None }, [savedMethods]) - let areAllGooglePayRequiredFieldsPrefilled = DynamicFieldsUtils.useAreAllRequiredFieldsPrefilled( + let (walletList, paymentOptionsList, actualList) = PaymentUtils.useGetPaymentMethodList( ~list, - ~paymentMethod="wallet", - ~paymentMethodType="google_pay", + ~paymentOptions, + ~paymentType, ) - let areAllApplePayRequiredFieldsPrefilled = DynamicFieldsUtils.useAreAllRequiredFieldsPrefilled( - ~list, - ~paymentMethod="wallet", - ~paymentMethodType="apple_pay", - ) - - let (walletList, paymentOptionsList, actualList) = React.useMemo(() => { - switch methodslist { - | Loaded(paymentlist) => - let paymentOrder = - paymentOrder->Array.length > 0 ? paymentOrder : PaymentModeType.defaultOrder - let plist = paymentlist->getDictFromJson->PaymentMethodsRecord.itemToObjMapper - let (wallets, otherOptions) = - plist->PaymentUtils.paymentListLookupNew( - ~order=paymentOrder, - ~showApplePay=isApplePayReady, - ~showGooglePay=isGooglePayReady, - ~areAllGooglePayRequiredFieldsPrefilled, - ~areAllApplePayRequiredFieldsPrefilled, - ) - ( - wallets->removeDuplicate, - paymentOptions->Array.concat(otherOptions)->removeDuplicate, - otherOptions, - ) - | SemiLoaded => - showCardFormByDefault && checkPriorityList(paymentMethodOrder) - ? ([], ["card"], []) - : ([], [], []) - | _ => ([], [], []) - } - }, ( - methodslist, - paymentMethodOrder, - isApplePayReady, - isGooglePayReady, - areAllGooglePayRequiredFieldsPrefilled, - areAllApplePayRequiredFieldsPrefilled, - )) - React.useEffect(() => { switch methodslist { | Loaded(paymentlist) => diff --git a/src/PaymentElementRenderer.res b/src/PaymentElementRenderer.res index ed3bbfbd9..da2d15a0b 100644 --- a/src/PaymentElementRenderer.res +++ b/src/PaymentElementRenderer.res @@ -15,9 +15,14 @@ let make = ( switch (sessions, list) { | (_, Loading) => - + {paymentType->Utils.isWalletElementPaymentType + ? + : } - | _ => + | _ => + paymentType->Utils.isWalletElementPaymentType + ? + : } } diff --git a/src/RenderPaymentMethods.res b/src/RenderPaymentMethods.res index 9e72ab009..94c282c6d 100644 --- a/src/RenderPaymentMethods.res +++ b/src/RenderPaymentMethods.res @@ -79,10 +79,16 @@ let make = ( paymentType cardProps expiryProps cvcProps zipProps handleElementFocus isFocus /> + | GooglePayElement + | PayPalElement + | ApplePayElement + | PaymentRequestButtonsElement | Payment => - + {paymentType->Utils.isWalletElementPaymentType + ? + : } }> diff --git a/src/ThreeDSAuth.res b/src/ThreeDSAuth.res index f9495e84a..a763a8a4d 100644 --- a/src/ThreeDSAuth.res +++ b/src/ThreeDSAuth.res @@ -5,7 +5,7 @@ let make = () => { let (openModal, setOpenModal) = React.useState(_ => false) let (loader, setloader) = React.useState(_ => true) - let logger = OrcaLogger.make() + let logger = OrcaLogger.make(~source=Elements(Payment), ()) React.useEffect0(() => { handlePostMessage([("iframeMountedCallback", true->JSON.Encode.bool)]) diff --git a/src/ThreeDSMethod.res b/src/ThreeDSMethod.res index e024fd7a9..a46696e26 100644 --- a/src/ThreeDSMethod.res +++ b/src/ThreeDSMethod.res @@ -1,7 +1,7 @@ open Utils @react.component let make = () => { - let logger = OrcaLogger.make() + let logger = OrcaLogger.make(~source=Elements(Payment), ()) let (stateMetadata, setStateMetadata) = React.useState(_ => Dict.make()->JSON.Encode.object) diff --git a/src/Types/CardThemeType.res b/src/Types/CardThemeType.res index 7001fcba4..3290cfde1 100644 --- a/src/Types/CardThemeType.res +++ b/src/Types/CardThemeType.res @@ -9,6 +9,10 @@ type mode = | CardNumberElement | CardExpiryElement | CardCVCElement + | GooglePayElement + | PayPalElement + | ApplePayElement + | PaymentRequestButtonsElement | NONE type label = Above | Floating | Never type themeClass = { @@ -80,3 +84,33 @@ type configClass = { fonts: array, loader: showLoader, } + +let getPaymentMode = val => { + switch val { + | "card" => Card + | "payment" => Payment + | "cardNumber" => CardNumberElement + | "cardExpiry" => CardExpiryElement + | "cardCvc" => CardCVCElement + | "googlePay" => GooglePayElement + | "payPal" => PayPalElement + | "applePay" => ApplePayElement + | "paymentRequestButtons" => PaymentRequestButtonsElement + | _ => NONE + } +} + +let getPaymentModeToStrMapper = val => { + switch val { + | Card => "Card" + | Payment => "Payment" + | CardNumberElement => "CardNumberElement" + | CardExpiryElement => "CardExpiryElement" + | CardCVCElement => "CardCVCElement" + | GooglePayElement => "GooglePayElement" + | PayPalElement => "PayPalElement" + | ApplePayElement => "ApplePayElement" + | PaymentRequestButtonsElement => "PaymentRequestButtonsElement" + | NONE => "None" + } +} diff --git a/src/Types/PaymentType.res b/src/Types/PaymentType.res index b17ca0f09..7c7a5d5cc 100644 --- a/src/Types/PaymentType.res +++ b/src/Types/PaymentType.res @@ -92,6 +92,7 @@ type wallets = { walletReturnUrl: string, applePay: showType, googlePay: showType, + payPal: showType, style: style, } type business = {name: string} @@ -257,6 +258,7 @@ let defaultWallets = { walletReturnUrl: "", applePay: Auto, googlePay: Auto, + payPal: Auto, style: defaultStyle, } let defaultBillingAddress = { @@ -743,7 +745,7 @@ let getWallets = (dict, str, logger) => { ->Option.flatMap(JSON.Decode.object) ->Option.map(json => { unknownKeysWarning( - ["applePay", "googlePay", "style", "walletReturnUrl"], + ["applePay", "googlePay", "style", "walletReturnUrl", "payPal"], json, "options.wallets", ~logger, @@ -759,6 +761,10 @@ let getWallets = (dict, str, logger) => { "options.wallets.googlePay", logger, ), + payPal: getWarningString(json, "payPal", "auto", ~logger)->getShowType( + "options.wallets.payPal", + logger, + ), style: getStyle(json, "style", logger), } }) diff --git a/src/Utilities/DynamicFieldsUtils.res b/src/Utilities/DynamicFieldsUtils.res index 34c9b7dff..f4a77f9d9 100644 --- a/src/Utilities/DynamicFieldsUtils.res +++ b/src/Utilities/DynamicFieldsUtils.res @@ -685,24 +685,3 @@ let useSubmitCallback = () => { } }, (line1, line2, state, city, postalCode)) } - -let usePaymentMethodTypeFromList = (~list, ~paymentMethod, ~paymentMethodType) => { - React.useMemo(() => { - PaymentMethodsRecord.getPaymentMethodTypeFromList( - ~list, - ~paymentMethod, - ~paymentMethodType=PaymentUtils.getPaymentMethodName( - ~paymentMethodType=paymentMethod, - ~paymentMethodName=paymentMethodType, - ), - )->Option.getOr(PaymentMethodsRecord.defaultPaymentMethodType) - }, (list, paymentMethod, paymentMethodType)) -} - -let useAreAllRequiredFieldsPrefilled = (~list, ~paymentMethod, ~paymentMethodType) => { - let paymentMethodTypes = usePaymentMethodTypeFromList(~list, ~paymentMethod, ~paymentMethodType) - - paymentMethodTypes.required_fields->Array.reduce(true, (acc, requiredField) => { - acc && requiredField.value != "" - }) -} diff --git a/src/Utilities/PaymentHelpers.res b/src/Utilities/PaymentHelpers.res index 343ffc71e..8e6fda559 100644 --- a/src/Utilities/PaymentHelpers.res +++ b/src/Utilities/PaymentHelpers.res @@ -186,11 +186,10 @@ let rec pollRetrievePaymentIntent = ( }) } -let retrieveStatus = (~headers, ~switchToCustomPod, pollID) => { +let retrieveStatus = (~headers, ~switchToCustomPod, pollID, logger) => { open Promise let endpoint = ApiEndpoint.getApiEndPoint() let uri = `${endpoint}/poll/status/${pollID}` - let logger = OrcaLogger.make() logApi( ~optLogger=Some(logger), ~url=uri, @@ -245,9 +244,17 @@ let retrieveStatus = (~headers, ~switchToCustomPod, pollID) => { }) } -let rec pollStatus = (~headers, ~switchToCustomPod, ~pollId, ~interval, ~count, ~returnUrl) => { +let rec pollStatus = ( + ~headers, + ~switchToCustomPod, + ~pollId, + ~interval, + ~count, + ~returnUrl, + ~logger, +) => { open Promise - retrieveStatus(~headers, ~switchToCustomPod, pollId) + retrieveStatus(~headers, ~switchToCustomPod, pollId, logger) ->then(json => { let dict = json->JSON.Decode.object->Option.getOr(Dict.make()) let status = dict->getString("status", "") @@ -268,6 +275,7 @@ let rec pollStatus = (~headers, ~switchToCustomPod, ~pollId, ~interval, ~count, ~interval, ~count=count - 1, ~returnUrl, + ~logger, ) }, ) @@ -277,7 +285,15 @@ let rec pollStatus = (~headers, ~switchToCustomPod, ~pollId, ~interval, ~count, }) ->catch(e => { Console.log2("Unable to retrieve payment due to following error", e) - pollStatus(~headers, ~switchToCustomPod, ~pollId, ~interval, ~count=count - 1, ~returnUrl) + pollStatus( + ~headers, + ~switchToCustomPod, + ~pollId, + ~interval, + ~count=count - 1, + ~returnUrl, + ~logger, + ) }) } diff --git a/src/Utilities/PaymentUtils.res b/src/Utilities/PaymentUtils.res index c99bd8398..05fdad0d3 100644 --- a/src/Utilities/PaymentUtils.res +++ b/src/Utilities/PaymentUtils.res @@ -5,6 +5,7 @@ let paymentListLookupNew = ( ~showGooglePay, ~areAllGooglePayRequiredFieldsPrefilled, ~areAllApplePayRequiredFieldsPrefilled, + ~isShowPaypal, ) => { let pmList = list->PaymentMethodsRecord.buildFromPaymentList let walletsList = [] @@ -45,7 +46,9 @@ let paymentListLookupNew = ( if walletToBeDisplayedInTabs->Array.includes(item.paymentMethodName) { otherPaymentList->Array.push(item.paymentMethodName)->ignore } else if item.methodType == "wallet" { - walletsList->Array.push(item.paymentMethodName)->ignore + if item.paymentMethodName !== "paypal" || isShowPaypal { + walletsList->Array.push(item.paymentMethodName)->ignore + } } else if item.methodType == "bank_debit" { otherPaymentList->Array.push(item.paymentMethodName ++ "_debit")->ignore } else if item.methodType == "bank_transfer" { @@ -237,3 +240,90 @@ let appendedCustomerAcceptance = (~isGuestCustomer, ~paymentType, ~body) => { ? body->Array.concat([("customer_acceptance", PaymentBody.customerAcceptanceBody)]) : body } + +let usePaymentMethodTypeFromList = (~list, ~paymentMethod, ~paymentMethodType) => { + React.useMemo(() => { + PaymentMethodsRecord.getPaymentMethodTypeFromList( + ~list, + ~paymentMethod, + ~paymentMethodType=getPaymentMethodName( + ~paymentMethodType=paymentMethod, + ~paymentMethodName=paymentMethodType, + ), + )->Option.getOr(PaymentMethodsRecord.defaultPaymentMethodType) + }, (list, paymentMethod, paymentMethodType)) +} + +let useAreAllRequiredFieldsPrefilled = (~list, ~paymentMethod, ~paymentMethodType) => { + let paymentMethodTypes = usePaymentMethodTypeFromList(~list, ~paymentMethod, ~paymentMethodType) + + paymentMethodTypes.required_fields->Array.reduce(true, (acc, requiredField) => { + acc && requiredField.value != "" + }) +} + +let useGetPaymentMethodList = (~list, ~paymentOptions, ~paymentType) => { + open Utils + let methodslist = Recoil.useRecoilValueFromAtom(RecoilAtoms.list) + + let {showCardFormByDefault, paymentMethodOrder} = Recoil.useRecoilValueFromAtom( + RecoilAtoms.optionAtom, + ) + + let isApplePayReady = Recoil.useRecoilValueFromAtom(RecoilAtoms.isApplePayReady) + let isGooglePayReady = Recoil.useRecoilValueFromAtom(RecoilAtoms.isGooglePayReady) + let optionAtomValue = Recoil.useRecoilValueFromAtom(RecoilAtoms.optionAtom) + + let paymentOrder = paymentMethodOrder->getOptionalArr->removeDuplicate + + let areAllGooglePayRequiredFieldsPrefilled = useAreAllRequiredFieldsPrefilled( + ~list, + ~paymentMethod="wallet", + ~paymentMethodType="google_pay", + ) + + let areAllApplePayRequiredFieldsPrefilled = useAreAllRequiredFieldsPrefilled( + ~list, + ~paymentMethod="wallet", + ~paymentMethodType="apple_pay", + ) + + React.useMemo(() => { + switch methodslist { + | Loaded(paymentlist) => + let paymentOrder = + paymentOrder->Array.length > 0 ? paymentOrder : PaymentModeType.defaultOrder + let plist = paymentlist->getDictFromJson->PaymentMethodsRecord.itemToObjMapper + let (wallets, otherOptions) = + plist->paymentListLookupNew( + ~order=paymentOrder, + ~showApplePay=isApplePayReady, + ~showGooglePay=isGooglePayReady, + ~areAllGooglePayRequiredFieldsPrefilled, + ~areAllApplePayRequiredFieldsPrefilled, + ~isShowPaypal=optionAtomValue.wallets.payPal === Auto, + ) + ( + wallets->removeDuplicate->Utils.getWalletPaymentMethod(paymentType), + paymentOptions->Array.concat(otherOptions)->removeDuplicate, + otherOptions, + ) + | SemiLoaded => + showCardFormByDefault && checkPriorityList(paymentMethodOrder) + ? ([], ["card"], []) + : ([], [], []) + | _ => ([], [], []) + } + }, ( + methodslist, + paymentMethodOrder, + isApplePayReady, + isGooglePayReady, + areAllGooglePayRequiredFieldsPrefilled, + areAllApplePayRequiredFieldsPrefilled, + optionAtomValue.wallets.payPal, + paymentType, + paymentOrder, + paymentOptions, + )) +} diff --git a/src/Utilities/Utils.res b/src/Utilities/Utils.res index c3b8a2d00..7376519f2 100644 --- a/src/Utilities/Utils.res +++ b/src/Utilities/Utils.res @@ -1214,3 +1214,31 @@ let generateRandomString = length => { }) result.contents } + +let getWalletPaymentMethod = (wallets, paymentType: CardThemeType.mode) => { + switch paymentType { + | GooglePayElement => wallets->Array.filter(item => item === "google_pay") + | PayPalElement => wallets->Array.filter(item => item === "paypal") + | ApplePayElement => wallets->Array.filter(item => item === "apple_pay") + | _ => wallets + } +} + +let expressCheckoutComponents = ["googlePay", "payPal", "applePay", "paymentRequestButtons"] + +let componentsForPaymentElementCreate = ["payment"]->Array.concat(expressCheckoutComponents) + +let isComponentTypeForPaymentElementCreate = componentType => { + componentsForPaymentElementCreate->Array.includes(componentType) +} + +let walletElementPaymentType: array = [ + GooglePayElement, + PayPalElement, + ApplePayElement, + PaymentRequestButtonsElement, +] + +let isWalletElementPaymentType = (paymentType: CardThemeType.mode) => { + walletElementPaymentType->Array.includes(paymentType) +} diff --git a/src/WalletElement.res b/src/WalletElement.res new file mode 100644 index 000000000..1395cc89c --- /dev/null +++ b/src/WalletElement.res @@ -0,0 +1,41 @@ +@react.component +let make = (~paymentType) => { + let sessionsObj = Recoil.useRecoilValueFromAtom(RecoilAtoms.sessions) + let methodslist = Recoil.useRecoilValueFromAtom(RecoilAtoms.list) + let (sessions, setSessions) = React.useState(_ => Dict.make()->JSON.Encode.object) + let (walletOptions, setWalletOptions) = React.useState(_ => []) + + let (list, setList) = React.useState(_ => PaymentMethodsRecord.defaultList) + + let (walletList, _, _) = PaymentUtils.useGetPaymentMethodList( + ~list, + ~paymentOptions=[], + ~paymentType, + ) + + React.useEffect(() => { + switch methodslist { + | Loaded(paymentlist) => + let plist = paymentlist->Utils.getDictFromJson->PaymentMethodsRecord.itemToObjMapper + setWalletOptions(_ => walletList) + setList(_ => plist) + | _ => () + } + None + }, (methodslist, walletList)) + React.useEffect(() => { + switch sessionsObj { + | Loaded(ssn) => setSessions(_ => ssn) + | _ => () + } + None + }, [sessionsObj]) + + Array.length > 0}> +
+ + + +
+
+} diff --git a/src/orca-loader/Elements.res b/src/orca-loader/Elements.res index 5ea77b0d5..5a6d6e23f 100644 --- a/src/orca-loader/Elements.res +++ b/src/orca-loader/Elements.res @@ -112,7 +112,7 @@ let make = ( ) }) - let fetchPaymentsList = mountedIframeRef => { + let fetchPaymentsList = (mountedIframeRef, componentType) => { let handlePaymentMethodsLoaded = (event: Types.event) => { let json = event.data->Identity.anyTypeToJson let dict = json->getDictFromJson @@ -159,10 +159,15 @@ let make = ( } } let msg = [("sendPaymentMethodsResponse", true->JSON.Encode.bool)]->Dict.fromArray - addSmartEventListener("message", handlePaymentMethodsLoaded, "onPaymentMethodsLoaded") + addSmartEventListener( + "message", + handlePaymentMethodsLoaded, + `onPaymentMethodsLoaded-${componentType}`, + ) preMountLoaderIframeDiv->Window.iframePostMessage(msg) } - let fetchCustomerPaymentMethods = (mountedIframeRef, disableSaveCards) => { + + let fetchCustomerPaymentMethods = (mountedIframeRef, disableSaveCards, componentType) => { if !disableSaveCards { let handleCustomerPaymentMethodsLoaded = (event: Types.event) => { let json = event.data->Identity.anyTypeToJson @@ -178,7 +183,7 @@ let make = ( addSmartEventListener( "message", handleCustomerPaymentMethodsLoaded, - "onCustomerPaymentMethodsLoaded", + `onCustomerPaymentMethodsLoaded-${componentType}`, ) } let msg = @@ -244,6 +249,10 @@ let make = ( | "cardNumber" | "cardExpiry" | "cardCvc" + | "googlePay" + | "payPal" + | "applePay" + | "paymentRequestButtons" | "payment" => () | str => manageErrorWarning(UNKNOWN_KEY, ~dynamicStr=`${str} type in create`, ~logger, ()) } @@ -267,7 +276,10 @@ let make = ( ->JSON.Encode.object let message = [ - ("paymentElementCreate", (componentType == "payment")->JSON.Encode.bool), + ( + "paymentElementCreate", + componentType->Utils.isComponentTypeForPaymentElementCreate->JSON.Encode.bool, + ), ("otherElements", otherElements->JSON.Encode.bool), ("options", newOptions), ("componentType", componentType->JSON.Encode.string), @@ -284,41 +296,53 @@ let make = ( ("launchTime", launchTime->JSON.Encode.float), ]->Dict.fromArray + let wallets = PaymentType.getWallets(newOptions->getDictFromJson, "wallets", logger) + let handleApplePayMounted = (event: Types.event) => { let json = event.data->anyTypeToJson let dict = json->getDictFromJson if dict->Dict.get("applePayMounted")->Option.isSome { - switch sessionForApplePay->Nullable.toOption { - | Some(session) => - try { - if session.canMakePayments() { - let msg = [("applePayCanMakePayments", true->JSON.Encode.bool)]->Dict.fromArray - mountedIframeRef->Window.iframePostMessage(msg) - } else { - Console.log("CANNOT MAKE PAYMENT USING APPLE PAY") - logger.setLogInfo( - ~value="CANNOT MAKE PAYMENT USING APPLE PAY", - ~eventName=APPLE_PAY_FLOW, - ~paymentMethod="APPLE_PAY", - ~logType=ERROR, - (), - ) - } - } catch { - | exn => { - let exnString = exn->anyTypeToJson->JSON.stringify - Console.log("CANNOT MAKE PAYMENT USING APPLE PAY: " ++ exnString) - logger.setLogInfo( - ~value=exnString, - ~eventName=APPLE_PAY_FLOW, - ~paymentMethod="APPLE_PAY", - ~logType=ERROR, - (), - ) + if wallets.applePay === Auto { + switch sessionForApplePay->Nullable.toOption { + | Some(session) => + try { + if session.canMakePayments() { + let msg = [("applePayCanMakePayments", true->JSON.Encode.bool)]->Dict.fromArray + mountedIframeRef->Window.iframePostMessage(msg) + } else { + Console.log("CANNOT MAKE PAYMENT USING APPLE PAY") + logger.setLogInfo( + ~value="CANNOT MAKE PAYMENT USING APPLE PAY", + ~eventName=APPLE_PAY_FLOW, + ~paymentMethod="APPLE_PAY", + ~logType=ERROR, + (), + ) + } + } catch { + | exn => { + let exnString = exn->anyTypeToJson->JSON.stringify + Console.log("CANNOT MAKE PAYMENT USING APPLE PAY: " ++ exnString) + logger.setLogInfo( + ~value=exnString, + ~eventName=APPLE_PAY_FLOW, + ~paymentMethod="APPLE_PAY", + ~logType=ERROR, + (), + ) + } } + | None => () } - | None => () + } else { + logger.setLogInfo( + ~value="ApplePay is set as 'never' by merchant", + ~eventName=APPLE_PAY_FLOW, + ~paymentMethod="APPLE_PAY", + ~logType=INFO, + (), + ) } } } @@ -593,6 +617,7 @@ let make = ( ~interval, ~count, ~returnUrl=url, + ~logger, ) ->then(_ => { PaymentHelpers.retrievePaymentIntent( @@ -677,7 +702,10 @@ let make = ( } ->then(res => { let (json, applePayPresent, googlePayPresent) = res - if componentType === "payment" && applePayPresent->Belt.Option.isSome { + if ( + componentType->Utils.isComponentTypeForPaymentElementCreate && + applePayPresent->Belt.Option.isSome + ) { //do operations here let processPayment = (token: JSON.t) => { //let body = PaymentBody.applePayBody(~token) @@ -776,7 +804,11 @@ let make = ( addSmartEventListener("message", handleApplePayMessages, "onApplePayMessages") } - if componentType === "payment" && googlePayPresent->Belt.Option.isSome { + if ( + componentType->Utils.isComponentTypeForPaymentElementCreate && + googlePayPresent->Belt.Option.isSome && + wallets.googlePay === Auto + ) { let dict = json->getDictFromJson let sessionObj = SessionsType.itemToObjMapper(dict, Others) let gPayToken = SessionsType.getPaymentSessionObj(sessionObj.sessionsToken, Gpay) @@ -888,6 +920,14 @@ let make = ( } catch { | _ => Console.log("Error loading Gpay") } + } else if wallets.googlePay === Never { + logger.setLogInfo( + ~value="GooglePay is set as never by merchant", + ~eventName=GOOGLE_PAY_FLOW, + ~paymentMethod="GOOGLE_PAY", + ~logType=INFO, + (), + ) } json->resolve @@ -901,18 +941,23 @@ let make = ( } } let msg = [("sendSessionTokensResponse", true->JSON.Encode.bool)]->Dict.fromArray - addSmartEventListener("message", handleSessionTokensLoaded, "onSessionTokensLoaded") + addSmartEventListener( + "message", + handleSessionTokensLoaded, + `onSessionTokensLoaded-${componentType}`, + ) preMountLoaderIframeDiv->Window.iframePostMessage(msg) } preMountLoaderMountedPromise ->then(_ => { - fetchPaymentsList(mountedIframeRef) + fetchPaymentsList(mountedIframeRef, componentType) if ( newOptions ->getDictFromJson - ->getBool("displaySavedPaymentMethods", true) + ->getBool("displaySavedPaymentMethods", true) && + !(Utils.expressCheckoutComponents->Array.includes(componentType)) ) { - fetchCustomerPaymentMethods(mountedIframeRef, false) + fetchCustomerPaymentMethods(mountedIframeRef, false, componentType) } fetchSessionTokens(mountedIframeRef) mountedIframeRef->Window.iframePostMessage(message) diff --git a/src/orca-loader/LoaderPaymentElement.res b/src/orca-loader/LoaderPaymentElement.res index 0e3e2cd9e..5acfaec8f 100644 --- a/src/orca-loader/LoaderPaymentElement.res +++ b/src/orca-loader/LoaderPaymentElement.res @@ -158,14 +158,9 @@ let make = (componentType, options, setIframeRef, iframeRef, mountPostMessage) = `#orca-payment-element-iframeRef-${localSelectorString}`, ) switch elem->Nullable.toOption { - | Some(ele) => - ele + | Some(ele) => ele ->Window.style - ->Window.setHeight( - `${iframeHeightRef.contents !== 0.0 - ? iframeHeightRef.contents->Belt.Float.toString - : "200"}px`, - ) + ->Window.setHeight(`${iframeHeightRef.contents->Float.toString}px`) | None => () } } @@ -293,10 +288,11 @@ let make = (componentType, options, setIframeRef, iframeRef, mountPostMessage) = let oElement = Window.querySelector(selector) let classesBase = optionsDict->getClasses("base") - let additionalIframeStyle = componentType->Utils.isOtherElements ? "height: 2rem;" : "" + let additionalIframeStyle = + componentType->Utils.isOtherElements ? "height: 2rem;" : "height: 0;" switch oElement->Nullable.toOption { | Some(elem) => { - let iframeDiv = `
+ let iframeDiv = `