diff --git a/aws/hyperswitch_web_aws_production_deployment.sh b/aws/hyperswitch_web_aws_production_deployment.sh index 62c9ed923..7d8e96b84 100755 --- a/aws/hyperswitch_web_aws_production_deployment.sh +++ b/aws/hyperswitch_web_aws_production_deployment.sh @@ -76,12 +76,12 @@ echo $( (aws s3api put-bucket-policy --bucket $MY_AWS_S3_BUCKET_NAME --policy "$ echo "Bucket configuration updated" -echo "Enter the backend endpoint your Hyperswitch Client will hit (hosted Hyperswitch Backend, https://beta.hyperswitch.io/api is taken by default):" +echo "Enter the backend endpoint your Hyperswitch Client will hit (hosted Hyperswitch Backend, https://beta.hyperswitch.io/api/payments is taken by default):" read AWS_BACKEND_URL { let clientSecret = CardUtils.getQueryParamsDictforKey(url.search, "clientSecret") let sessionId = CardUtils.getQueryParamsDictforKey(url.search, "sessionId") let publishableKey = CardUtils.getQueryParamsDictforKey(url.search, "publishableKey") - let endpoint = - CardUtils.getQueryParamsDictforKey(url.search, "endpoint")->decodeURIComponent - + } | "achBankTransfer" | "bacsBankTransfer" diff --git a/src/Payments/PreMountLoader.res b/src/Payments/PreMountLoader.res index 36736e506..19bf389ec 100644 --- a/src/Payments/PreMountLoader.res +++ b/src/Payments/PreMountLoader.res @@ -1,5 +1,5 @@ @react.component -let make = (~sessionId, ~publishableKey, ~clientSecret, ~endpoint) => { +let make = (~sessionId, ~publishableKey, ~clientSecret) => { open Utils let (paymentMethodsResponseSent, setPaymentMethodsResponseSent) = React.useState(_ => false) let ( @@ -15,36 +15,32 @@ let make = (~sessionId, ~publishableKey, ~clientSecret, ~endpoint) => { (), ) - let ( - paymentMethodsResponse, - customerPaymentMethodsResponse, - sessionTokensResponse, - ) = React.useMemo0(() => { - ( - PaymentHelpers.fetchPaymentMethodList( - ~clientSecret, - ~publishableKey, - ~logger, - ~switchToCustomPod=false, - ~endpoint, - ), - PaymentHelpers.fetchCustomerDetails( - ~clientSecret, - ~publishableKey, - ~optLogger=Some(logger), - ~switchToCustomPod=false, - ~endpoint, - ), - PaymentHelpers.fetchSessions( - ~clientSecret, - ~publishableKey, - ~optLogger=Some(logger), - ~switchToCustomPod=false, - ~endpoint, - (), - ), - ) - }) + let endpoint = ApiEndpoint.getApiEndPoint(~publishableKey, ()) + + let (paymentMethodsResponse, customerPaymentMethodsResponse, sessionTokensResponse) = ( + PaymentHelpers.fetchPaymentMethodList( + ~clientSecret, + ~publishableKey, + ~logger, + ~switchToCustomPod=false, + ~endpoint, + ), + PaymentHelpers.fetchCustomerPaymentMethodList( + ~clientSecret, + ~publishableKey, + ~optLogger=Some(logger), + ~switchToCustomPod=false, + ~endpoint, + ), + PaymentHelpers.fetchSessions( + ~clientSecret, + ~publishableKey, + ~optLogger=Some(logger), + ~switchToCustomPod=false, + ~endpoint, + (), + ), + ) let sendPromiseData = (promise, key) => { open Promise diff --git a/src/Utilities/ApiEndpoint.res b/src/Utilities/ApiEndpoint.res index d3ede5855..4ee8ec0fc 100644 --- a/src/Utilities/ApiEndpoint.res +++ b/src/Utilities/ApiEndpoint.res @@ -14,7 +14,7 @@ let getApiEndPoint = (~publishableKey="", ~isConfirmCall=false, ()) => { | Some(str) => str | None => let backendEndPoint = isConfirmCall ? GlobalVars.confirmEndPoint : GlobalVars.backendEndPoint - GlobalVars.isProd && testMode ? "https://beta.hyperswitch.io/api" : backendEndPoint + GlobalVars.isProd && testMode ? "https://beta.hyperswitch.io/api/payments" : backendEndPoint } } diff --git a/src/Utilities/PaymentHelpers.res b/src/Utilities/PaymentHelpers.res index 06a0c310b..43b80648b 100644 --- a/src/Utilities/PaymentHelpers.res +++ b/src/Utilities/PaymentHelpers.res @@ -1004,82 +1004,86 @@ let fetchSessions = ( ~endpoint, (), ) => { - open Promise - let headers = [("Content-Type", "application/json"), ("api-key", publishableKey)] - let paymentIntentID = String.split(clientSecret, "_secret_")->Array.get(0)->Option.getOr("") - let body = - [ - ("payment_id", paymentIntentID->JSON.Encode.string), - ("client_secret", clientSecret->JSON.Encode.string), - ("wallets", wallets->JSON.Encode.array), - ("delayed_session_token", isDelayedSessionToken->JSON.Encode.bool), - ] - ->Dict.fromArray - ->JSON.Encode.object - let uri = `${endpoint}/payments/session_tokens` - logApi( - ~optLogger, - ~url=uri, - ~apiLogType=Request, - ~eventName=SESSIONS_CALL_INIT, - ~logType=INFO, - ~logCategory=API, - (), - ) - fetchApi( - uri, - ~method=#POST, - ~bodyStr=body->JSON.stringify, - ~headers=headers->ApiEndpoint.addCustomPodHeader(~switchToCustomPod, ()), - (), - ) - ->then(resp => { - let statusCode = resp->Fetch.Response.status->Int.toString - if statusCode->String.charAt(0) !== "2" { - resp - ->Fetch.Response.json - ->then(data => { + React.useMemo(() => { + open Promise + let headers = [("Content-Type", "application/json"), ("api-key", publishableKey)] + let paymentIntentID = String.split(clientSecret, "_secret_")->Array.get(0)->Option.getOr("") + let body = + [ + ("payment_id", paymentIntentID->JSON.Encode.string), + ("client_secret", clientSecret->JSON.Encode.string), + ("wallets", wallets->JSON.Encode.array), + ("delayed_session_token", isDelayedSessionToken->JSON.Encode.bool), + ] + ->Dict.fromArray + ->JSON.Encode.object + let uri = `${endpoint}/payments/session_tokens` + logApi( + ~optLogger, + ~url=uri, + ~apiLogType=Request, + ~eventName=SESSIONS_CALL_INIT, + ~logType=INFO, + ~logCategory=API, + (), + ) + fetchApi( + uri, + ~method=#POST, + ~bodyStr=body->JSON.stringify, + ~headers=headers->ApiEndpoint.addCustomPodHeader(~switchToCustomPod, ()), + (), + ) + ->then(resp => { + let statusCode = resp->Fetch.Response.status->Int.toString + if statusCode->String.charAt(0) !== "2" { + resp + ->Fetch.Response.json + ->then( + data => { + logApi( + ~optLogger, + ~url=uri, + ~data, + ~statusCode, + ~apiLogType=Err, + ~eventName=SESSIONS_CALL, + ~logType=ERROR, + ~logCategory=API, + (), + ) + JSON.Encode.null->resolve + }, + ) + } else { logApi( ~optLogger, ~url=uri, - ~data, ~statusCode, - ~apiLogType=Err, + ~apiLogType=Response, ~eventName=SESSIONS_CALL, - ~logType=ERROR, + ~logType=INFO, ~logCategory=API, (), ) - JSON.Encode.null->resolve - }) - } else { + Fetch.Response.json(resp) + } + }) + ->catch(err => { + let exceptionMessage = err->formatException logApi( ~optLogger, ~url=uri, - ~statusCode, - ~apiLogType=Response, + ~apiLogType=NoResponse, ~eventName=SESSIONS_CALL, - ~logType=INFO, + ~logType=ERROR, ~logCategory=API, + ~data=exceptionMessage, (), ) - Fetch.Response.json(resp) - } - }) - ->catch(err => { - let exceptionMessage = err->formatException - logApi( - ~optLogger, - ~url=uri, - ~apiLogType=NoResponse, - ~eventName=SESSIONS_CALL, - ~logType=ERROR, - ~logCategory=API, - ~data=exceptionMessage, - (), - ) - JSON.Encode.null->resolve - }) + JSON.Encode.null->resolve + }) + }, [clientSecret]) } let fetchPaymentMethodList = ( @@ -1089,143 +1093,151 @@ let fetchPaymentMethodList = ( ~switchToCustomPod, ~endpoint, ) => { - open Promise - let headers = [("Content-Type", "application/json"), ("api-key", publishableKey)] - let uri = `${endpoint}/account/payment_methods?client_secret=${clientSecret}` - logApi( - ~optLogger=Some(logger), - ~url=uri, - ~apiLogType=Request, - ~eventName=PAYMENT_METHODS_CALL_INIT, - ~logType=INFO, - ~logCategory=API, - (), - ) - fetchApi( - uri, - ~method=#GET, - ~headers=headers->ApiEndpoint.addCustomPodHeader(~switchToCustomPod, ()), - (), - ) - ->then(resp => { - let statusCode = resp->Fetch.Response.status->Int.toString - if statusCode->String.charAt(0) !== "2" { - resp - ->Fetch.Response.json - ->then(data => { + React.useMemo(() => { + open Promise + let headers = [("Content-Type", "application/json"), ("api-key", publishableKey)] + let uri = `${endpoint}/account/payment_methods?client_secret=${clientSecret}` + logApi( + ~optLogger=Some(logger), + ~url=uri, + ~apiLogType=Request, + ~eventName=PAYMENT_METHODS_CALL_INIT, + ~logType=INFO, + ~logCategory=API, + (), + ) + fetchApi( + uri, + ~method=#GET, + ~headers=headers->ApiEndpoint.addCustomPodHeader(~switchToCustomPod, ()), + (), + ) + ->then(resp => { + let statusCode = resp->Fetch.Response.status->Int.toString + if statusCode->String.charAt(0) !== "2" { + resp + ->Fetch.Response.json + ->then( + data => { + logApi( + ~optLogger=Some(logger), + ~url=uri, + ~data, + ~statusCode, + ~apiLogType=Err, + ~eventName=PAYMENT_METHODS_CALL, + ~logType=ERROR, + ~logCategory=API, + (), + ) + JSON.Encode.null->resolve + }, + ) + } else { logApi( ~optLogger=Some(logger), ~url=uri, - ~data, ~statusCode, - ~apiLogType=Err, + ~apiLogType=Response, ~eventName=PAYMENT_METHODS_CALL, - ~logType=ERROR, + ~logType=INFO, ~logCategory=API, (), ) - JSON.Encode.null->resolve - }) - } else { + Fetch.Response.json(resp) + } + }) + ->catch(err => { + let exceptionMessage = err->formatException logApi( ~optLogger=Some(logger), ~url=uri, - ~statusCode, - ~apiLogType=Response, + ~apiLogType=NoResponse, ~eventName=PAYMENT_METHODS_CALL, - ~logType=INFO, + ~logType=ERROR, ~logCategory=API, + ~data=exceptionMessage, (), ) - Fetch.Response.json(resp) - } - }) - ->catch(err => { - let exceptionMessage = err->formatException - logApi( - ~optLogger=Some(logger), - ~url=uri, - ~apiLogType=NoResponse, - ~eventName=PAYMENT_METHODS_CALL, - ~logType=ERROR, - ~logCategory=API, - ~data=exceptionMessage, - (), - ) - JSON.Encode.null->resolve - }) + JSON.Encode.null->resolve + }) + }, [clientSecret]) } -let fetchCustomerDetails = ( +let fetchCustomerPaymentMethodList = ( ~clientSecret, ~publishableKey, ~endpoint, ~optLogger, ~switchToCustomPod, ) => { - open Promise - let headers = [("Content-Type", "application/json"), ("api-key", publishableKey)] - let uri = `${endpoint}/customers/payment_methods?client_secret=${clientSecret}` - logApi( - ~optLogger, - ~url=uri, - ~apiLogType=Request, - ~eventName=CUSTOMER_PAYMENT_METHODS_CALL_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 => { + React.useMemo(() => { + open Promise + let headers = [("Content-Type", "application/json"), ("api-key", publishableKey)] + let uri = `${endpoint}/customers/payment_methods?client_secret=${clientSecret}` + logApi( + ~optLogger, + ~url=uri, + ~apiLogType=Request, + ~eventName=CUSTOMER_PAYMENT_METHODS_CALL_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, + ~url=uri, + ~data, + ~statusCode, + ~apiLogType=Err, + ~eventName=CUSTOMER_PAYMENT_METHODS_CALL, + ~logType=ERROR, + ~logCategory=API, + (), + ) + JSON.Encode.null->resolve + }, + ) + } else { logApi( ~optLogger, ~url=uri, - ~data, ~statusCode, - ~apiLogType=Err, + ~apiLogType=Response, ~eventName=CUSTOMER_PAYMENT_METHODS_CALL, - ~logType=ERROR, + ~logType=INFO, ~logCategory=API, (), ) - JSON.Encode.null->resolve - }) - } else { + res->Fetch.Response.json + } + }) + ->catch(err => { + let exceptionMessage = err->formatException logApi( ~optLogger, ~url=uri, - ~statusCode, - ~apiLogType=Response, + ~apiLogType=NoResponse, ~eventName=CUSTOMER_PAYMENT_METHODS_CALL, - ~logType=INFO, + ~logType=ERROR, ~logCategory=API, + ~data=exceptionMessage, (), ) - res->Fetch.Response.json - } - }) - ->catch(err => { - let exceptionMessage = err->formatException - logApi( - ~optLogger, - ~url=uri, - ~apiLogType=NoResponse, - ~eventName=CUSTOMER_PAYMENT_METHODS_CALL, - ~logType=ERROR, - ~logCategory=API, - ~data=exceptionMessage, - (), - ) - JSON.Encode.null->resolve - }) + JSON.Encode.null->resolve + }) + }, [clientSecret]) } diff --git a/src/Utilities/Utils.res b/src/Utilities/Utils.res index af84cfe38..da69a2211 100644 --- a/src/Utilities/Utils.res +++ b/src/Utilities/Utils.res @@ -1234,3 +1234,14 @@ let makeOneClickHandlerPromise = sdkHandleOneClickConfirmPayment => { } }) } + +let generateRandomString = length => { + let characters = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789" + let result = ref("") + let charactersLength = characters->String.length + Int.range(0, length)->Array.forEach(_ => { + let charIndex = mod((Math.random() *. 100.0)->Float.toInt, charactersLength) + result := result.contents ++ characters->String.charAt(charIndex) + }) + result.contents +} diff --git a/src/orca-loader/Elements.res b/src/orca-loader/Elements.res index c4e3fb292..20fa12940 100644 --- a/src/orca-loader/Elements.res +++ b/src/orca-loader/Elements.res @@ -276,7 +276,6 @@ let make = ( ("sdkSessionId", sdkSessionId->JSON.Encode.string), ("blockConfirm", blockConfirm->JSON.Encode.bool), ("switchToCustomPod", switchToCustomPod->JSON.Encode.bool), - ("endpoint", endpoint->JSON.Encode.string), ("sdkHandleOneClickConfirmPayment", sdkHandleOneClickConfirmPayment->JSON.Encode.bool), ("parentURL", "*"->JSON.Encode.string), ("analyticsMetadata", analyticsMetadata), diff --git a/src/orca-loader/Hyper.res b/src/orca-loader/Hyper.res index 372e194ec..91c060db0 100644 --- a/src/orca-loader/Hyper.res +++ b/src/orca-loader/Hyper.res @@ -85,7 +85,8 @@ let make = (publishableKey, options: option, analyticsInfo: optionOption.flatMap(JSON.Decode.object)->Option.getOr(Dict.make()) - let sessionID = analyticsInfoDict->getString("sessionID", "") + let sessionID = + analyticsInfoDict->getString("sessionID", "hyp_" ++ Utils.generateRandomString(8)) let sdkTimestamp = analyticsInfoDict->getString("timeStamp", Date.now()->Belt.Float.toString) let logger = OrcaLogger.make( ~sessionId=sessionID, diff --git a/src/orca-loader/PaymentSessionMethods.res b/src/orca-loader/PaymentSessionMethods.res index 78512e758..da598d074 100644 --- a/src/orca-loader/PaymentSessionMethods.res +++ b/src/orca-loader/PaymentSessionMethods.res @@ -8,7 +8,7 @@ let getCustomerSavedPaymentMethods = ( ~switchToCustomPod, ) => { open Promise - PaymentHelpers.fetchCustomerDetails( + PaymentHelpers.fetchCustomerPaymentMethodList( ~clientSecret, ~publishableKey, ~endpoint, diff --git a/webpack.common.js b/webpack.common.js index f4b8920aa..bf1531072 100644 --- a/webpack.common.js +++ b/webpack.common.js @@ -5,8 +5,7 @@ const MiniCssExtractPlugin = require("mini-css-extract-plugin"); const CopyPlugin = require("copy-webpack-plugin"); const HtmlWebpackPlugin = require("html-webpack-plugin"); const TerserPlugin = require("terser-webpack-plugin"); -const BundleAnalyzerPlugin = - require("webpack-bundle-analyzer").BundleAnalyzerPlugin; +const BundleAnalyzerPlugin = require("webpack-bundle-analyzer").BundleAnalyzerPlugin; const { sentryWebpackPlugin } = require("@sentry/webpack-plugin"); const sdkEnv = process.env.sdkEnv; @@ -18,8 +17,7 @@ let repoVersion = require("./package.json").version; let majorVersion = "v" + repoVersion.split(".")[0]; let repoName = require("./package.json").name; -let repoPublicPath = - sdkEnv === "local" ? "" : `/${repoVersion}/${majorVersion}`; +let repoPublicPath = sdkEnv === "local" ? "" : `/${repoVersion}/${majorVersion}`; let sdkUrl; @@ -54,12 +52,12 @@ let confirmEndPoint; if (envBackendUrl === undefined) { confirmEndPoint = sdkEnv === "prod" - ? "https://checkout.hyperswitch.io/api" + ? "https://checkout.hyperswitch.io/api/payments" : sdkEnv === "sandbox" - ? "https://beta.hyperswitch.io/api" + ? "https://beta.hyperswitch.io/api/payments" : sdkEnv === "integ" ? "https://integ-api.hyperswitch.io" - : "https://beta.hyperswitch.io/api"; + : "https://beta.hyperswitch.io/api/payments"; } else { confirmEndPoint = envBackendUrl; } @@ -151,18 +149,18 @@ module.exports = (publicPath = "auto") => { // new webpack.HTMLInjectPlugin({ // publicPath: JSON.stringify(repoVersion), // }), - // sentryWebpackPlugin({ - // org: "sentry", - // project: "hyperswitch-react-sdk", - // authToken: process.env.SENTRY_AUTH_TOKEN, - // url: process.env.SENTRY_URL, - // release: { - // name: "0.2", - // uploadLegacySourcemaps: { - // paths: ["dist"], - // }, - // }, - // }), + sentryWebpackPlugin({ + org: "sentry", + project: "hyperswitch-react-sdk", + authToken: process.env.SENTRY_AUTH_TOKEN, + url: process.env.SENTRY_URL, + release: { + name: "0.2", + uploadLegacySourcemaps: { + paths: ["dist"], + }, + }, + }), ], module: { rules: [ diff --git a/webpack.dev.js b/webpack.dev.js index da6d81baa..4a8fb11d1 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" + ? "https://checkout.hyperswitch.io/api/payments" : sdkEnv === "sandbox" - ? "https://beta.hyperswitch.io/api" + ? "https://beta.hyperswitch.io/api/payments" : sdkEnv === "integ" ? "https://integ-api.hyperswitch.io" - : "https://beta.hyperswitch.io/api"; + : "https://beta.hyperswitch.io/api/payments"; let devServer = { contentBase: path.join(__dirname, "dist"), @@ -19,8 +19,8 @@ let devServer = { port: 9050, historyApiFallback: true, proxy: { - "/payments": { - target: backendEndPoint + "/payments", + "/api/payments": { + target: backendEndPoint, changeOrigin: true, secure: true, pathRewrite: { "^/payments": "" }, @@ -30,18 +30,18 @@ let devServer = { // changeOrigin: true, // secure: false, // }, - "/customers": { - target: backendEndPoint + "/customers", - changeOrigin: true, - secure: true, - pathRewrite: { "^/customers": "" }, - }, - "/account": { - target: backendEndPoint + "/account", - changeOrigin: true, - secure: true, - pathRewrite: { "^/account": "" }, - }, + // "/customers": { + // target: backendEndPoint + "/customers", + // changeOrigin: true, + // secure: true, + // pathRewrite: { "^/customers": "" }, + // }, + // "/account": { + // target: backendEndPoint + "/account", + // changeOrigin: true, + // secure: true, + // pathRewrite: { "^/account": "" }, + // }, }, headers: { "Cache-Control": "max-age=31536000,must-revalidate",