Belt.Int.toString}px`} id="klarna-payments" className="w-full" />
}
let default = make
diff --git a/src/Payments/KlarnaSDKTypes.res b/src/Payments/KlarnaSDKTypes.res
new file mode 100644
index 000000000..f8db1adf7
--- /dev/null
+++ b/src/Payments/KlarnaSDKTypes.res
@@ -0,0 +1,45 @@
+type token = {client_token: string}
+type collected_shipping_address = {
+ city: string,
+ country: string,
+ email: string,
+ family_name: string,
+ given_name: string,
+ phone: string,
+ postal_code: string,
+ region: string,
+ street_address: string,
+}
+let defaultCollectedShippingAddress = {
+ city: "",
+ country: "",
+ email: "",
+ family_name: "",
+ given_name: "",
+ phone: "",
+ postal_code: "",
+ region: "",
+ street_address: "",
+}
+
+type res = {
+ approved: bool,
+ show_form: bool,
+ authorization_token: string,
+ finalize_required: bool,
+ collected_shipping_address?: collected_shipping_address,
+}
+type authorizeAttributes = {collect_shipping_address: bool}
+type authorize = (authorizeAttributes, JSON.t, res => unit) => unit
+type loadType = {
+ container?: string,
+ color_text?: string,
+ payment_method_category?: string,
+ theme?: string,
+ shape?: string,
+ on_click?: authorize => Promise.t
,
+}
+type some = {
+ init: token => unit,
+ load: (loadType, JSON.t => unit) => unit,
+}
diff --git a/src/Payments/PayPal.res b/src/Payments/PayPal.res
index d82417def..35caa351a 100644
--- a/src/Payments/PayPal.res
+++ b/src/Payments/PayPal.res
@@ -24,7 +24,7 @@ let make = () => {
| Paypal(val) => val->PaypalSDKTypes.getLabel
| _ => Paypal->PaypalSDKTypes.getLabel
}
- let (_, _, heightType) = options.wallets.style.height
+ let (_, _, heightType, _) = options.wallets.style.height
let height = switch heightType {
| Paypal(val) => val
| _ => 48
diff --git a/src/Payments/PaymentRequestButtonElement.res b/src/Payments/PaymentRequestButtonElement.res
index 0c44ede94..aa8ac6b0a 100644
--- a/src/Payments/PaymentRequestButtonElement.res
+++ b/src/Payments/PaymentRequestButtonElement.res
@@ -1,4 +1,4 @@
-type wallet = GPayWallet | PaypalWallet | ApplePayWallet | NONE
+type wallet = GPayWallet | PaypalWallet | ApplePayWallet | KlarnaWallet | NONE
let paymentMode = str => {
switch str {
| "gpay"
@@ -8,6 +8,7 @@ let paymentMode = str => {
| "applepay"
| "apple_pay" =>
ApplePayWallet
+ | "klarna" => KlarnaWallet
| _ => NONE
}
}
@@ -56,6 +57,8 @@ let make = (~sessions, ~walletOptions, ~paymentType) => {
Gpay,
)
+ let klarnaTokenObj = SessionsType.getPaymentSessionObj(sessionObj.sessionsToken, Klarna)
+
let {clientSecret} = Recoil.useRecoilValueFromAtom(RecoilAtoms.keys)
@@ -97,6 +100,17 @@ let make = (~sessions, ~walletOptions, ~paymentType) => {
| ApplePayTokenOptional(optToken) =>
| _ => React.null
}
+ | KlarnaWallet =>
+
+ {switch klarnaTokenObj {
+ | OtherTokenOptional(optToken) =>
+ switch optToken {
+ | Some(token) =>
+ | None => React.null
+ }
+ | _ => React.null
+ }}
+
| NONE => React.null
}
diff --git a/src/Payments/PaypalSDK.res b/src/Payments/PaypalSDK.res
index bb58dd951..c1df5c1ae 100644
--- a/src/Payments/PaypalSDK.res
+++ b/src/Payments/PaypalSDK.res
@@ -22,7 +22,7 @@ let make = (~sessionObj: SessionsType.token, ~paymentType: CardThemeType.mode) =
let options = Recoil.useRecoilValueFromAtom(RecoilAtoms.optionAtom)
let (_, _, buttonType) = options.wallets.style.type_
- let (_, _, heightType) = options.wallets.style.height
+ let (_, _, heightType, _) = options.wallets.style.height
let buttonStyle = {
layout: "vertical",
color: options.wallets.style.theme == Outline
diff --git a/src/RenderPaymentMethods.res b/src/RenderPaymentMethods.res
index 960c0d720..1023c4881 100644
--- a/src/RenderPaymentMethods.res
+++ b/src/RenderPaymentMethods.res
@@ -82,6 +82,7 @@ let make = (
| GooglePayElement
| PayPalElement
| ApplePayElement
+ | KlarnaElement
| ExpressCheckoutElement
| Payment =>
{
| "googlePay" => GooglePayElement
| "payPal" => PayPalElement
| "applePay" => ApplePayElement
+ | "klarna" => KlarnaElement
| "expressCheckout" => ExpressCheckoutElement
| _ => NONE
}
@@ -113,6 +115,7 @@ let getPaymentModeToStrMapper = val => {
| GooglePayElement => "GooglePayElement"
| PayPalElement => "PayPalElement"
| ApplePayElement => "ApplePayElement"
+ | KlarnaElement => "KlarnaElement"
| ExpressCheckoutElement => "ExpressCheckoutElement"
| NONE => "None"
}
diff --git a/src/Types/PaymentModeType.res b/src/Types/PaymentModeType.res
index c95ff75c6..14d29b396 100644
--- a/src/Types/PaymentModeType.res
+++ b/src/Types/PaymentModeType.res
@@ -49,6 +49,9 @@ let paymentMode = str => {
let defaultOrder = [
"card",
+ "apple_pay",
+ "google_pay",
+ "paypal",
"klarna",
"affirm",
"afterpay_clearpay",
@@ -63,9 +66,6 @@ let defaultOrder = [
"giropay",
"ideal",
"eps",
- "apple_pay",
- "google_pay",
- "paypal",
"crypto",
"bancontact_card",
"boleto",
diff --git a/src/Types/PaymentType.res b/src/Types/PaymentType.res
index 2b00dc7c8..4bf8b4ac5 100644
--- a/src/Types/PaymentType.res
+++ b/src/Types/PaymentType.res
@@ -60,7 +60,7 @@ type terms = {
usBankAccount: showTerms,
}
type buttonHeight = Default | Custom
-type heightType = ApplePay(int) | GooglePay(int) | Paypal(int)
+type heightType = ApplePay(int) | GooglePay(int) | Paypal(int) | Klarna(int)
type googlePayStyleType = Default | Buy | Donate | Checkout | Subscribe | Book | Pay | Order
type paypalStyleType = Paypal | Checkout | Buynow | Pay | Installment
type applePayStyleType =
@@ -86,13 +86,14 @@ type theme = Dark | Light | Outline
type style = {
type_: styleTypeArray,
theme: theme,
- height: (heightType, heightType, heightType),
+ height: (heightType, heightType, heightType, heightType),
}
type wallets = {
walletReturnUrl: string,
applePay: showType,
googlePay: showType,
payPal: showType,
+ klarna: showType,
style: style,
}
type business = {name: string}
@@ -253,13 +254,14 @@ let defaultFields = {
let defaultStyle = {
type_: (ApplePay(Default), GooglePay(Default), Paypal(Paypal)),
theme: Light,
- height: (ApplePay(48), GooglePay(48), Paypal(48)),
+ height: (ApplePay(48), GooglePay(48), Paypal(48), Klarna(48)),
}
let defaultWallets = {
walletReturnUrl: "",
applePay: Auto,
googlePay: Auto,
payPal: Auto,
+ klarna: Auto,
style: defaultStyle,
}
let defaultBillingAddress = {
@@ -713,6 +715,31 @@ let getPaypalHeight = (val, logger) => {
: Paypal(val)
val
}
+let getKlarnaHeight = (val, logger) => {
+ let val: heightType =
+ val < 40
+ ? {
+ valueOutRangeWarning(
+ val,
+ "options.style.height",
+ "[40-60] - Klarna. Value set to min",
+ ~logger,
+ )
+ Klarna(40)
+ }
+ : val > 60
+ ? {
+ valueOutRangeWarning(
+ val,
+ "options.style.height",
+ "[40-60] - Paypal. Value set to max",
+ ~logger,
+ )
+ Klarna(60)
+ }
+ : Klarna(val)
+ val
+}
let getTheme = (str, logger) => {
switch str {
| "outline" => Outline
@@ -724,7 +751,12 @@ let getTheme = (str, logger) => {
}
}
let getHeightArray = (val, logger) => {
- (val->getApplePayHeight(logger), val->getGooglePayHeight(logger), val->getPaypalHeight(logger))
+ (
+ val->getApplePayHeight(logger),
+ val->getGooglePayHeight(logger),
+ val->getPaypalHeight(logger),
+ val->getKlarnaHeight(logger),
+ )
}
let getStyle = (dict, str, logger) => {
dict
@@ -747,7 +779,7 @@ let getWallets = (dict, str, logger) => {
->Option.flatMap(JSON.Decode.object)
->Option.map(json => {
unknownKeysWarning(
- ["applePay", "googlePay", "style", "walletReturnUrl", "payPal"],
+ ["applePay", "googlePay", "style", "walletReturnUrl", "payPal", "klarna"],
json,
"options.wallets",
~logger,
@@ -767,6 +799,10 @@ let getWallets = (dict, str, logger) => {
"options.wallets.payPal",
logger,
),
+ klarna: getWarningString(json, "klarna", "auto", ~logger)->getShowType(
+ "options.wallets.klarna",
+ logger,
+ ),
style: getStyle(json, "style", logger),
}
})
diff --git a/src/Utilities/DynamicFieldsUtils.res b/src/Utilities/DynamicFieldsUtils.res
index 207f95b2f..1a0e770fe 100644
--- a/src/Utilities/DynamicFieldsUtils.res
+++ b/src/Utilities/DynamicFieldsUtils.res
@@ -753,6 +753,36 @@ let removeRequiredFieldsDuplicates = (
requiredFields
}
+let getNameFromString = (name, requiredFieldsArr) => {
+ let nameArr = name->String.split(" ")
+ let nameArrLength = nameArr->Array.length
+ switch requiredFieldsArr->Array.get(requiredFieldsArr->Array.length - 1)->Option.getOr("") {
+ | "first_name" => {
+ let end = nameArrLength === 1 ? nameArrLength : nameArrLength - 1
+ nameArr
+ ->Array.slice(~start=0, ~end)
+ ->Array.reduce("", (acc, item) => {
+ acc ++ " " ++ item
+ })
+ }
+ | "last_name" =>
+ if nameArrLength === 1 {
+ ""
+ } else {
+ nameArr->Array.get(nameArrLength - 1)->Option.getOr(name)
+ }
+ | _ => name
+ }->String.trim
+}
+
+let getNameFromFirstAndLastName = (~firstName, ~lastName, ~requiredFieldsArr) => {
+ switch requiredFieldsArr->Array.get(requiredFieldsArr->Array.length - 1)->Option.getOr("") {
+ | "first_name" => firstName
+ | "last_name" => lastName
+ | _ => firstName->String.concatMany([" ", lastName])
+ }->String.trim
+}
+
let getApplePayRequiredFields = (
~billingContact: ApplePayTypes.billingContact,
~shippingContact: ApplePayTypes.shippingContact,
@@ -777,7 +807,11 @@ let getApplePayRequiredFields = (
let fieldVal = switch item.field_type {
| FullName
| BillingName =>
- getName(billingContact.givenName, billingContact.familyName)
+ getNameFromFirstAndLastName(
+ ~firstName=billingContact.givenName,
+ ~lastName=billingContact.familyName,
+ ~requiredFieldsArr,
+ )
| AddressLine1 => billingContact.addressLines->getAddressLine(0)
| AddressLine2 => billingContact.addressLines->getAddressLine(1)
| AddressCity => billingContact.locality
@@ -816,28 +850,6 @@ let getApplePayRequiredFields = (
})
}
-let getNameFromString = (name, requiredFieldsArr) => {
- let nameArr = name->String.split(" ")
- let nameArrLength = nameArr->Array.length
- switch requiredFieldsArr->Array.get(requiredFieldsArr->Array.length - 1)->Option.getOr("") {
- | "first_name" => {
- let end = nameArrLength === 1 ? nameArrLength : nameArrLength - 1
- nameArr
- ->Array.slice(~start=0, ~end)
- ->Array.reduce("", (acc, item) => {
- acc ++ " " ++ item
- })
- }
- | "last_name" =>
- if nameArrLength === 1 {
- ""
- } else {
- nameArr->Array.get(nameArrLength - 1)->Option.getOr(name)
- }
- | _ => name
- }->String.trim
-}
-
let getGooglePayRequiredFields = (
~billingContact: GooglePayType.billingContact,
~shippingContact: GooglePayType.billingContact,
@@ -930,3 +942,40 @@ let getPaypalRequiredFields = (
acc
})
}
+
+let getKlarnaRequiredFields = (
+ ~shippingContact: KlarnaSDKTypes.collected_shipping_address,
+ ~paymentMethodTypes: PaymentMethodsRecord.paymentMethodTypes,
+ ~statesList,
+) => {
+ paymentMethodTypes.required_fields->Array.reduce(Dict.make(), (acc, item) => {
+ let requiredFieldsArr = item.required_field->String.split(".")
+
+ let fieldVal = switch item.field_type {
+ | ShippingName =>
+ getNameFromFirstAndLastName(
+ ~firstName=shippingContact.given_name,
+ ~lastName=shippingContact.family_name,
+ ~requiredFieldsArr,
+ )
+ | ShippingAddressLine1 => shippingContact.street_address
+ | ShippingAddressCity => shippingContact.city
+ | ShippingAddressState => {
+ let administrativeArea = shippingContact.region
+ let countryCode = shippingContact.country
+ Utils.getStateNameFromStateCodeAndCountry(statesList, administrativeArea, countryCode)
+ }
+ | ShippingAddressCountry(_) => shippingContact.country
+ | ShippingAddressPincode => shippingContact.postal_code
+ | Email => shippingContact.email
+ | PhoneNumber => shippingContact.phone
+ | _ => ""
+ }
+
+ if fieldVal !== "" {
+ acc->Dict.set(item.required_field, fieldVal->JSON.Encode.string)
+ }
+
+ acc
+ })
+}
diff --git a/src/Utilities/PaymentUtils.res b/src/Utilities/PaymentUtils.res
index 39d975692..f9b1a654c 100644
--- a/src/Utilities/PaymentUtils.res
+++ b/src/Utilities/PaymentUtils.res
@@ -4,6 +4,8 @@ let paymentListLookupNew = (
list: PaymentMethodsRecord.paymentMethodList,
~order,
~isShowPaypal,
+ ~isShowKlarnaOneClick,
+ ~isKlarnaRedirectFlow,
) => {
let pmList = list->PaymentMethodsRecord.buildFromPaymentList
let walletsList = []
@@ -40,6 +42,12 @@ let paymentListLookupNew = (
otherPaymentList->Array.push("card")->ignore
} else if item.methodType == "reward" {
otherPaymentList->Array.push(item.paymentMethodName)->ignore
+ } else if item.methodType == "pay_later" {
+ if item.paymentMethodName === "klarna" && !isKlarnaRedirectFlow && isShowKlarnaOneClick {
+ walletsList->Array.push(item.paymentMethodName)->ignore
+ } else {
+ otherPaymentList->Array.push(item.paymentMethodName)->ignore
+ }
} else {
otherPaymentList->Array.push(item.paymentMethodName)->ignore
}
@@ -257,7 +265,17 @@ let useAreAllRequiredFieldsPrefilled = (
})
}
-let useGetPaymentMethodList = (~paymentOptions, ~paymentType) => {
+let getIsKlarnaRedirectFlow = sessions => {
+ let dict = sessions->Utils.getDictFromJson
+ let sessionObj = SessionsType.itemToObjMapper(dict, Others)
+ let klarnaTokenObj = SessionsType.getPaymentSessionObj(sessionObj.sessionsToken, Klarna)
+ switch klarnaTokenObj {
+ | OtherTokenOptional(optToken) => optToken->Option.isNone
+ | _ => true
+ }
+}
+
+let useGetPaymentMethodList = (~paymentOptions, ~paymentType, ~sessions) => {
open Utils
let methodslist = Recoil.useRecoilValueFromAtom(RecoilAtoms.paymentMethodList)
@@ -268,6 +286,14 @@ let useGetPaymentMethodList = (~paymentOptions, ~paymentType) => {
let paymentOrder = paymentMethodOrder->getOptionalArr->removeDuplicate
+ let isKlarnaRedirectFlow = getIsKlarnaRedirectFlow(sessions)
+
+ let filterPaymentMethods = (paymentOptionsList: array, ~isKlarnaRedirectFlow) => {
+ paymentOptionsList->Array.filter(paymentOptionsName =>
+ !(paymentOptionsName === "klarna" && !isKlarnaRedirectFlow)
+ )
+ }
+
React.useMemo(() => {
switch methodslist {
| Loaded(paymentlist) =>
@@ -278,10 +304,15 @@ let useGetPaymentMethodList = (~paymentOptions, ~paymentType) => {
plist->paymentListLookupNew(
~order=paymentOrder,
~isShowPaypal=optionAtomValue.wallets.payPal === Auto,
+ ~isShowKlarnaOneClick=optionAtomValue.wallets.klarna === Auto,
+ ~isKlarnaRedirectFlow,
)
(
wallets->removeDuplicate->Utils.getWalletPaymentMethod(paymentType),
- paymentOptions->Array.concat(otherOptions)->removeDuplicate,
+ paymentOptions
+ ->Array.concat(otherOptions)
+ ->removeDuplicate
+ ->filterPaymentMethods(~isKlarnaRedirectFlow),
otherOptions,
)
| SemiLoaded =>
@@ -290,7 +321,14 @@ let useGetPaymentMethodList = (~paymentOptions, ~paymentType) => {
: ([], [], [])
| _ => ([], [], [])
}
- }, (methodslist, paymentMethodOrder, optionAtomValue.wallets.payPal, paymentType))
+ }, (
+ methodslist,
+ paymentMethodOrder,
+ optionAtomValue.wallets.payPal,
+ optionAtomValue.wallets.klarna,
+ paymentType,
+ isKlarnaRedirectFlow,
+ ))
}
let useStatesJson = setStatesJson => {
diff --git a/src/Utilities/RecoilAtoms.res b/src/Utilities/RecoilAtoms.res
index e0014550a..40beb7a88 100644
--- a/src/Utilities/RecoilAtoms.res
+++ b/src/Utilities/RecoilAtoms.res
@@ -62,12 +62,14 @@ type areOneClickWalletsRendered = {
isGooglePay: bool,
isApplePay: bool,
isPaypal: bool,
+ isKlarna: bool,
}
let defaultAreOneClickWalletsRendered = {
isGooglePay: false,
isApplePay: false,
isPaypal: false,
+ isKlarna: false,
}
let areOneClickWalletsRendered = Recoil.atom(
diff --git a/src/Utilities/Utils.res b/src/Utilities/Utils.res
index 7bddcce44..b7714e427 100644
--- a/src/Utilities/Utils.res
+++ b/src/Utilities/Utils.res
@@ -1226,11 +1226,12 @@ let getWalletPaymentMethod = (wallets, paymentType: CardThemeType.mode) => {
| GooglePayElement => wallets->Array.filter(item => item === "google_pay")
| PayPalElement => wallets->Array.filter(item => item === "paypal")
| ApplePayElement => wallets->Array.filter(item => item === "apple_pay")
+ | KlarnaElement => wallets->Array.filter(item => item === "klarna")
| _ => wallets
}
}
-let expressCheckoutComponents = ["googlePay", "payPal", "applePay", "expressCheckout"]
+let expressCheckoutComponents = ["googlePay", "payPal", "applePay", "klarna", "expressCheckout"]
let componentsForPaymentElementCreate = ["payment"]->Array.concat(expressCheckoutComponents)
@@ -1246,6 +1247,7 @@ let walletElementPaymentType: array = [
GooglePayElement,
PayPalElement,
ApplePayElement,
+ KlarnaElement,
ExpressCheckoutElement,
]
diff --git a/src/WalletElement.res b/src/WalletElement.res
index 3e22e8e3e..897286d7e 100644
--- a/src/WalletElement.res
+++ b/src/WalletElement.res
@@ -7,7 +7,11 @@ let make = (~paymentType) => {
let setPaymentMethodListValue = Recoil.useSetRecoilState(PaymentUtils.paymentMethodListValue)
- let (walletList, _, _) = PaymentUtils.useGetPaymentMethodList(~paymentOptions=[], ~paymentType)
+ let (walletList, _, _) = PaymentUtils.useGetPaymentMethodList(
+ ~paymentOptions=[],
+ ~paymentType,
+ ~sessions,
+ )
React.useEffect(() => {
switch methodslist {
diff --git a/src/orca-loader/Elements.res b/src/orca-loader/Elements.res
index 91a528c7c..4142b429b 100644
--- a/src/orca-loader/Elements.res
+++ b/src/orca-loader/Elements.res
@@ -260,6 +260,7 @@ let make = (
| "googlePay"
| "payPal"
| "applePay"
+ | "klarna"
| "expressCheckout"
| "payment" => ()
| str => manageErrorWarning(UNKNOWN_KEY, ~dynamicStr=`${str} type in create`, ~logger, ())
From 6b4fbb75b663ccdb99450a2eabe4ae30fe0f5fa2 Mon Sep 17 00:00:00 2001
From: semantic-release-bot
Date: Wed, 5 Jun 2024 11:41:54 +0000
Subject: [PATCH 2/6] chore(release): 0.60.0 [skip ci]
# [0.60.0](https://github.com/juspay/hyperswitch-web/compare/v0.59.2...v0.60.0) (2024-06-05)
### Features
* added Klarna as a one click widget ([#420](https://github.com/juspay/hyperswitch-web/issues/420)) ([bdd0fa3](https://github.com/juspay/hyperswitch-web/commit/bdd0fa3ffd5b4e0018109541323981c945a1ed4a))
---
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 e81f12cb7..e2cfdf951 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,10 @@
+# [0.60.0](https://github.com/juspay/hyperswitch-web/compare/v0.59.2...v0.60.0) (2024-06-05)
+
+
+### Features
+
+* added Klarna as a one click widget ([#420](https://github.com/juspay/hyperswitch-web/issues/420)) ([bdd0fa3](https://github.com/juspay/hyperswitch-web/commit/bdd0fa3ffd5b4e0018109541323981c945a1ed4a))
+
## [0.59.2](https://github.com/juspay/hyperswitch-web/compare/v0.59.1...v0.59.2) (2024-06-04)
diff --git a/package-lock.json b/package-lock.json
index e3ab7373e..ecf78bded 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -1,12 +1,12 @@
{
"name": "orca-payment-page",
- "version": "0.59.2",
+ "version": "0.60.0",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "orca-payment-page",
- "version": "0.59.2",
+ "version": "0.60.0",
"hasInstallScript": true,
"dependencies": {
"@aws-sdk/client-cloudfront": "^3.414.0",
diff --git a/package.json b/package.json
index 94989df99..95975e01a 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "orca-payment-page",
- "version": "0.59.2",
+ "version": "0.60.0",
"main": "index.js",
"private": true,
"dependencies": {
From 107e914865a0b6a677663746689c6452287fae19 Mon Sep 17 00:00:00 2001
From: Pritish Budhiraja
Date: Fri, 7 Jun 2024 12:29:12 +0530
Subject: [PATCH 3/6] feat: self serve url in env (#425)
---
Hyperswitch-React-Demo-App/.env | 1 +
Hyperswitch-React-Demo-App/src/Payment.js | 8 +++++---
Hyperswitch-React-Demo-App/webpack.common.js | 6 ++----
README.md | 2 ++
4 files changed, 10 insertions(+), 7 deletions(-)
diff --git a/Hyperswitch-React-Demo-App/.env b/Hyperswitch-React-Demo-App/.env
index d2c398adf..22dbd4bfb 100644
--- a/Hyperswitch-React-Demo-App/.env
+++ b/Hyperswitch-React-Demo-App/.env
@@ -3,4 +3,5 @@ HYPERSWITCH_PUBLISHABLE_KEY=
HYPERSWITCH_SECRET_KEY=
HYPERSWITCH_SERVER_URL=
HYPERSWITCH_CLIENT_URL=
+SELF_SERVER_URL=
diff --git a/Hyperswitch-React-Demo-App/src/Payment.js b/Hyperswitch-React-Demo-App/src/Payment.js
index b2b104a2f..03a28b0db 100644
--- a/Hyperswitch-React-Demo-App/src/Payment.js
+++ b/Hyperswitch-React-Demo-App/src/Payment.js
@@ -1,3 +1,4 @@
+/* eslint-disable no-undef */
import { useEffect, useState } from "react";
import React from "react";
import { HyperElements } from "@juspay-tech/react-hyper-js";
@@ -8,10 +9,11 @@ function Payment() {
const [clientSecret, setClientSecret] = useState("");
useEffect(() => {
+ let url = SELF_SERVER_URL === "" ? ENDPOINT : SELF_SERVER_URL;
Promise.all([
- fetch(`${endPoint}/config`),
- fetch(`${endPoint}/urls`),
- fetch(`${endPoint}/create-payment-intent`),
+ fetch(`${url}/config`),
+ fetch(`${url}/urls`),
+ fetch(`${url}/create-payment-intent`),
])
.then((responses) => {
return Promise.all(responses.map((response) => response.json()));
diff --git a/Hyperswitch-React-Demo-App/webpack.common.js b/Hyperswitch-React-Demo-App/webpack.common.js
index 0826c5cfc..f3d25d3ee 100644
--- a/Hyperswitch-React-Demo-App/webpack.common.js
+++ b/Hyperswitch-React-Demo-App/webpack.common.js
@@ -47,11 +47,9 @@ module.exports = (endpoint, publicPath = "auto") => {
template: "./public/playgroundIndex.html",
}),
new webpack.DefinePlugin({
- endPoint:
- typeof endpoint === "string"
- ? JSON.stringify(endpoint)
- : JSON.stringify(process.env.SELF_SERVER_URL),
+ ENDPOINT: JSON.stringify(endpoint),
SCRIPT_SRC: JSON.stringify(process.env.HYPERSWITCH_CLIENT_URL),
+ SELF_SERVER_URL: JSON.stringify(process.env.SELF_SERVER_URL ?? ""),
}),
new BundleAnalyzerPlugin({
analyzerMode: "static",
diff --git a/README.md b/README.md
index 77477bae7..e592c72dd 100644
--- a/README.md
+++ b/README.md
@@ -95,6 +95,8 @@ Before you start the local setup, you will need an understanding of few keys -
- **`HYPERSWITCH_CLIENT_URL`:** The URL of your hosted Hyperswitch SDK. You can also use our Sandbox URL (https://beta.hyperswitch.io/v1) or specify your app running locally (e.g., http://localhost:9050).
+- **`SELF_SERVER_URL`:** The URL of the hosted server file for generating client-secret and for fetching urls & configs. (eg: http://localhost:9060/payments)
+
### About Env Configs for SDK
- **`ENV_BACKEND_URL`:** Sets the endpoint for all the APIs used within the SDK to interact with the backend service. If you are running your own backend service, you can configure and specify its endpoint here for local setups.
From c2cf5c822d4fe5d88f1070d6666b0a3fc0a8f6a7 Mon Sep 17 00:00:00 2001
From: semantic-release-bot
Date: Fri, 7 Jun 2024 07:01:49 +0000
Subject: [PATCH 4/6] chore(release): 0.61.0 [skip ci]
# [0.61.0](https://github.com/juspay/hyperswitch-web/compare/v0.60.0...v0.61.0) (2024-06-07)
### Features
* self serve url in env ([#425](https://github.com/juspay/hyperswitch-web/issues/425)) ([107e914](https://github.com/juspay/hyperswitch-web/commit/107e914865a0b6a677663746689c6452287fae19))
---
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 e2cfdf951..e24054b00 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,10 @@
+# [0.61.0](https://github.com/juspay/hyperswitch-web/compare/v0.60.0...v0.61.0) (2024-06-07)
+
+
+### Features
+
+* self serve url in env ([#425](https://github.com/juspay/hyperswitch-web/issues/425)) ([107e914](https://github.com/juspay/hyperswitch-web/commit/107e914865a0b6a677663746689c6452287fae19))
+
# [0.60.0](https://github.com/juspay/hyperswitch-web/compare/v0.59.2...v0.60.0) (2024-06-05)
diff --git a/package-lock.json b/package-lock.json
index ecf78bded..4c530b195 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -1,12 +1,12 @@
{
"name": "orca-payment-page",
- "version": "0.60.0",
+ "version": "0.61.0",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "orca-payment-page",
- "version": "0.60.0",
+ "version": "0.61.0",
"hasInstallScript": true,
"dependencies": {
"@aws-sdk/client-cloudfront": "^3.414.0",
diff --git a/package.json b/package.json
index 95975e01a..6716a8dc7 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "orca-payment-page",
- "version": "0.60.0",
+ "version": "0.61.0",
"main": "index.js",
"private": true,
"dependencies": {
From 844688be082208db21ebcc2d9e39e17bba71e96c Mon Sep 17 00:00:00 2001
From: Pritish Budhiraja
Date: Fri, 7 Jun 2024 13:24:33 +0530
Subject: [PATCH 5/6] refactor: webpack readability and refactoring (#430)
---
Hyperswitch-React-Demo-App/webpack.common.js | 10 +-
Hyperswitch-React-Demo-App/webpack.dev.js | 13 +-
webpack.common.js | 253 +++++++++----------
webpack.dev.js | 33 ++-
4 files changed, 140 insertions(+), 169 deletions(-)
diff --git a/Hyperswitch-React-Demo-App/webpack.common.js b/Hyperswitch-React-Demo-App/webpack.common.js
index f3d25d3ee..9b0f0039d 100644
--- a/Hyperswitch-React-Demo-App/webpack.common.js
+++ b/Hyperswitch-React-Demo-App/webpack.common.js
@@ -4,14 +4,14 @@ 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");
require("dotenv").config({ path: "./.env" });
module.exports = (endpoint, publicPath = "auto") => {
- let entries = {
+ const entries = {
app: "./src/index.js",
};
+
return {
mode: "development",
devtool: "source-map",
@@ -37,9 +37,7 @@ module.exports = (endpoint, publicPath = "auto") => {
new CopyPlugin({
patterns: [
{ from: "public" },
- {
- from: path.resolve(__dirname, "server.js"),
- },
+ { from: path.resolve(__dirname, "server.js") },
],
}),
new HtmlWebpackPlugin({
diff --git a/Hyperswitch-React-Demo-App/webpack.dev.js b/Hyperswitch-React-Demo-App/webpack.dev.js
index e950ece5b..3ae483540 100644
--- a/Hyperswitch-React-Demo-App/webpack.dev.js
+++ b/Hyperswitch-React-Demo-App/webpack.dev.js
@@ -2,7 +2,7 @@ const path = require("path");
const { merge } = require("webpack-merge");
const common = require("./webpack.common.js");
-let devServer = {
+const devServer = {
contentBase: path.join(__dirname, "dist"),
hot: true,
port: 9060,
@@ -20,10 +20,7 @@ let devServer = {
},
};
-module.exports = merge([
- common("/payments"),
- {
- mode: "development",
- devServer: devServer,
- },
-]);
+module.exports = merge(common("/payments"), {
+ mode: "development",
+ devServer,
+});
diff --git a/webpack.common.js b/webpack.common.js
index ccea631e4..81f350aa7 100644
--- a/webpack.common.js
+++ b/webpack.common.js
@@ -6,158 +6,98 @@ 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 ?? "local";
-const envSdkUrl = process.env.ENV_SDK_URL ?? "";
-const envBackendUrl = process.env.ENV_BACKEND_URL ?? "";
-const envLoggingUrl = process.env.ENV_LOGGING_URL ?? "";
+const getEnvVariable = (variable, defaultValue) =>
+ process.env[variable] ?? defaultValue;
-//git rev-parse --abbrev-ref HEAD
-let repoVersion = require("./package.json").version;
-let majorVersion = "v" + repoVersion.split(".")[0];
+const sdkEnv = getEnvVariable("sdkEnv", "local");
+const envSdkUrl = getEnvVariable("ENV_SDK_URL", "");
+const envBackendUrl = getEnvVariable("ENV_BACKEND_URL", "");
+const envLoggingUrl = getEnvVariable("ENV_LOGGING_URL", "");
-let repoName = require("./package.json").name;
-let repoPublicPath = sdkEnv === "local" ? "" : `/${repoVersion}/${majorVersion}`;
+const repoVersion = require("./package.json").version;
+const majorVersion = "v" + repoVersion.split(".")[0];
+const repoName = require("./package.json").name;
+const repoPublicPath =
+ sdkEnv === "local" ? "" : `/${repoVersion}/${majorVersion}`;
-let sdkUrl;
-
-if (envSdkUrl.length === 0) {
- sdkUrl =
- sdkEnv === "prod"
- ? "https://checkout.hyperswitch.io"
- : sdkEnv === "sandbox"
- ? "https://beta.hyperswitch.io"
- : sdkEnv === "integ"
- ? "https://dev.hyperswitch.io"
- : "http://localhost:9050";
-} else {
- sdkUrl = envSdkUrl;
-}
-
-let backendEndPoint;
-if (envBackendUrl.length === 0) {
- backendEndPoint =
- sdkEnv === "prod"
- ? "https://checkout.hyperswitch.io/api"
- : sdkEnv === "sandbox"
- ? "https://beta.hyperswitch.io/api"
- : sdkEnv === "integ"
- ? "https://integ-api.hyperswitch.io"
- : "https://beta.hyperswitch.io/api";
-} else {
- backendEndPoint = envBackendUrl;
-}
-
-let confirmEndPoint;
-if (envBackendUrl.length === 0) {
- confirmEndPoint =
- sdkEnv === "prod"
- ? "https://api.hyperswitch.io"
- : sdkEnv === "sandbox"
- ? "https://sandbox.hyperswitch.io"
- : sdkEnv === "integ"
- ? "https://integ-api.hyperswitch.io"
- : "https://sandbox.hyperswitch.io";
-} else {
- confirmEndPoint = envBackendUrl;
-}
-
-let logEndpoint;
-if (envLoggingUrl.length === 0) {
- logEndpoint =
- sdkEnv === "prod"
- ? "https://api.hyperswitch.io/logs/sdk"
- : "https://sandbox.hyperswitch.io/logs/sdk";
-} else {
- logEndpoint = envLoggingUrl;
-}
-
-// Set this to true to enable logging
-let enableLogging = true;
+const getSdkUrl = (env, customUrl) => {
+ if (customUrl) return customUrl;
+ const urls = {
+ prod: "https://checkout.hyperswitch.io",
+ sandbox: "https://beta.hyperswitch.io",
+ integ: "https://dev.hyperswitch.io",
+ local: "http://localhost:9050",
+ };
+ return urls[env] || urls.local;
+};
-// Choose from DEBUG, INFO, WARNING, ERROR, SILENT
-let loggingLevel = "DEBUG";
+const sdkUrl = getSdkUrl(sdkEnv, envSdkUrl);
+const backendEndPoint =
+ envBackendUrl ||
+ `https://${sdkEnv === "prod" ? "checkout" : "beta"}.hyperswitch.io/api`;
+const confirmEndPoint =
+ envBackendUrl ||
+ `https://${sdkEnv === "prod" ? "api" : "sandbox"}.hyperswitch.io`;
+const logEndpoint =
+ envLoggingUrl ||
+ `https://${sdkEnv === "prod" ? "api" : "sandbox"}.hyperswitch.io/logs/sdk`;
-// Maximum logs emitted for a particular event, to rate limit logs
-let maxLogsPushedPerEventName = 100;
+const enableLogging = true;
+const loggingLevel = "DEBUG";
+const maxLogsPushedPerEventName = 100;
module.exports = (publicPath = "auto") => {
- let entries = {
+ const entries = {
app: "./index.js",
HyperLoader: "./src/orca-loader/HyperLoader.bs.js",
};
- return {
- mode: "development",
- devtool: "source-map",
- output: {
- path:
- sdkEnv && sdkEnv !== "local"
- ? path.resolve(__dirname, "dist", sdkEnv)
- : path.resolve(__dirname, "dist"),
- clean: true,
- publicPath: `${repoPublicPath}/`,
- },
- // TODO - Can be commented for faster build in local development
- optimization: {
- sideEffects: true,
- minimize: true,
- minimizer: [
- new TerserPlugin({
- terserOptions: {
- compress: {
- drop_console: false,
- },
- },
- }),
- // For webpack@5 you can use the `...` syntax to extend existing minimizers (i.e. `terser-webpack-plugin`), uncomment the next line
- // `...`,
- // new CssMinimizerPlugin(),
- ],
- },
- plugins: [
- new MiniCssExtractPlugin(),
- new CopyPlugin({
- patterns: [{ from: "public" }],
- }),
- new webpack.DefinePlugin({
- repoName: JSON.stringify(repoName),
- repoVersion: JSON.stringify(repoVersion),
- publicPath: JSON.stringify(repoPublicPath),
- sdkUrl: JSON.stringify(sdkUrl),
- backendEndPoint: JSON.stringify(backendEndPoint),
- confirmEndPoint: JSON.stringify(confirmEndPoint),
- logEndpoint: JSON.stringify(logEndpoint),
- sentryDSN: JSON.stringify(process.env.SENTRY_DSN),
- sentryScriptUrl: JSON.stringify(process.env.SENTRY_SCRIPT_URL),
- enableLogging: JSON.stringify(enableLogging),
- loggingLevel: JSON.stringify(loggingLevel),
- maxLogsPushedPerEventName: JSON.stringify(maxLogsPushedPerEventName),
- }),
- new HtmlWebpackPlugin({
- inject: false,
- template: "./public/build.html",
- }),
- new HtmlWebpackPlugin({
- inject: false,
- template: "./public/build.html",
- }),
- new HtmlWebpackPlugin({
- // Also generate a test.html
- inject: false,
- filename: "fullscreenIndex.html",
- template: "./public/fullscreenIndexTemplate.html",
- }),
+ const plugins = [
+ new MiniCssExtractPlugin(),
+ new CopyPlugin({
+ patterns: [{ from: "public" }],
+ }),
+ new webpack.DefinePlugin({
+ repoName: JSON.stringify(repoName),
+ repoVersion: JSON.stringify(repoVersion),
+ publicPath: JSON.stringify(repoPublicPath),
+ sdkUrl: JSON.stringify(sdkUrl),
+ backendEndPoint: JSON.stringify(backendEndPoint),
+ confirmEndPoint: JSON.stringify(confirmEndPoint),
+ logEndpoint: JSON.stringify(logEndpoint),
+ sentryDSN: JSON.stringify(process.env.SENTRY_DSN),
+ sentryScriptUrl: JSON.stringify(process.env.SENTRY_SCRIPT_URL),
+ enableLogging: JSON.stringify(enableLogging),
+ loggingLevel: JSON.stringify(loggingLevel),
+ maxLogsPushedPerEventName: JSON.stringify(maxLogsPushedPerEventName),
+ }),
+ new HtmlWebpackPlugin({
+ inject: false,
+ template: "./public/build.html",
+ }),
+ new HtmlWebpackPlugin({
+ // Also generate a test.html
+ inject: false,
+ filename: "fullscreenIndex.html",
+ template: "./public/fullscreenIndexTemplate.html",
+ }),
+ ];
+
+ if (process.env.NODE_ENV === "production") {
+ plugins.push(
new BundleAnalyzerPlugin({
analyzerMode: "static",
reportFilename: "bundle-report.html",
openAnalyzer: false,
- }),
- // new webpack.HTMLInjectPlugin({
- // publicPath: JSON.stringify(repoVersion),
- // }),
- // TODO - Can be commented if sentry not needed.
+ })
+ );
+ }
+
+ if (process.env.SENTRY_AUTH_TOKEN) {
+ plugins.push(
sentryWebpackPlugin({
org: "sentry",
project: "hyperswitch-react-sdk",
@@ -169,8 +109,38 @@ module.exports = (publicPath = "auto") => {
paths: ["dist"],
},
},
- }),
- ],
+ })
+ );
+ }
+
+ return {
+ mode: sdkEnv === "local" ? "development" : "production",
+ devtool: sdkEnv === "local" ? "eval-source-map" : "source-map",
+ output: {
+ path:
+ sdkEnv && sdkEnv !== "local"
+ ? path.resolve(__dirname, "dist", sdkEnv)
+ : path.resolve(__dirname, "dist"),
+ clean: true,
+ publicPath: `${repoPublicPath}/`,
+ },
+ optimization:
+ sdkEnv === "local"
+ ? {}
+ : {
+ sideEffects: true,
+ minimize: true,
+ minimizer: [
+ new TerserPlugin({
+ terserOptions: {
+ compress: {
+ drop_console: false,
+ },
+ },
+ }),
+ ],
+ },
+ plugins,
module: {
rules: [
{
@@ -188,6 +158,13 @@ module.exports = (publicPath = "auto") => {
},
],
},
+ {
+ test: /\.js$/,
+ exclude: /node_modules/,
+ use: {
+ loader: "babel-loader",
+ },
+ },
],
},
entry: entries,
diff --git a/webpack.dev.js b/webpack.dev.js
index 993c77a9d..2104c3bcf 100644
--- a/webpack.dev.js
+++ b/webpack.dev.js
@@ -1,19 +1,20 @@
const path = require("path");
-const dotenv = require("dotenv").config();
+require("dotenv").config();
const { merge } = require("webpack-merge");
const common = require("./webpack.common.js");
+
const sdkEnv = process.env.sdkEnv ?? "local";
-let backendEndPoint =
- sdkEnv === "prod"
- ? "https://api.hyperswitch.io/payments"
- : sdkEnv === "sandbox"
- ? "https://sandbox.hyperswitch.io/payments"
- : sdkEnv === "integ"
- ? "https://integ-api.hyperswitch.io/payments"
- : "https://sandbox.hyperswitch.io/payments";
+const endpointMap = {
+ prod: "https://api.hyperswitch.io/payments",
+ sandbox: "https://sandbox.hyperswitch.io/payments",
+ integ: "https://integ-api.hyperswitch.io/payments",
+ local: "https://sandbox.hyperswitch.io/payments", // Default or local environment endpoint
+};
+
+const backendEndPoint = endpointMap[sdkEnv] || endpointMap.local;
-let devServer = {
+const devServer = {
contentBase: path.join(__dirname, "dist"),
hot: true,
host: "0.0.0.0",
@@ -26,6 +27,7 @@ let devServer = {
secure: true,
pathRewrite: { "^/payments": "" },
},
+ // * Uncomment the following if needed for 3DS method proxying
// "/3dsmethod": {
// target: "https://acs40.sandbox.3dsecure.io",
// changeOrigin: true,
@@ -37,10 +39,7 @@ let devServer = {
},
};
-module.exports = merge([
- common(),
- {
- mode: "development",
- devServer: devServer,
- },
-]);
+module.exports = merge(common(), {
+ mode: "development",
+ devServer,
+});
From 80f7393346a1cff67949388b3621e3e4017fef05 Mon Sep 17 00:00:00 2001
From: semantic-release-bot
Date: Fri, 7 Jun 2024 07:56:08 +0000
Subject: [PATCH 6/6] chore(release): 0.61.1 [skip ci]
## [0.61.1](https://github.com/juspay/hyperswitch-web/compare/v0.61.0...v0.61.1) (2024-06-07)
---
CHANGELOG.md | 2 ++
package-lock.json | 4 ++--
package.json | 2 +-
3 files changed, 5 insertions(+), 3 deletions(-)
diff --git a/CHANGELOG.md b/CHANGELOG.md
index e24054b00..1e6dc95bf 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,5 @@
+## [0.61.1](https://github.com/juspay/hyperswitch-web/compare/v0.61.0...v0.61.1) (2024-06-07)
+
# [0.61.0](https://github.com/juspay/hyperswitch-web/compare/v0.60.0...v0.61.0) (2024-06-07)
diff --git a/package-lock.json b/package-lock.json
index 4c530b195..475a2c172 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -1,12 +1,12 @@
{
"name": "orca-payment-page",
- "version": "0.61.0",
+ "version": "0.61.1",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "orca-payment-page",
- "version": "0.61.0",
+ "version": "0.61.1",
"hasInstallScript": true,
"dependencies": {
"@aws-sdk/client-cloudfront": "^3.414.0",
diff --git a/package.json b/package.json
index 6716a8dc7..c1c4dc087 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "orca-payment-page",
- "version": "0.61.0",
+ "version": "0.61.1",
"main": "index.js",
"private": true,
"dependencies": {