Skip to content

Commit

Permalink
Merge pull request #50 from juspay/unify-env
Browse files Browse the repository at this point in the history
Unify Deployment Environment
  • Loading branch information
mrudulvajpayee4935 authored Sep 10, 2024
2 parents b45c61c + 1623676 commit a7e0d35
Show file tree
Hide file tree
Showing 14 changed files with 143 additions and 82 deletions.
4 changes: 0 additions & 4 deletions src/modules/api-utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,6 @@ import { normalizeValue } from "./payment-app-configuration/utils";
import { env } from "@/lib/env.mjs";
import { randomBytes } from "crypto";

export const getEnvironmentFromKey = (): string => {
return env.NEXT_PUBLIC_ENV;
};

export function generate16DigitId(): string {
return randomBytes(8).toString("hex");
}
Expand Down
40 changes: 15 additions & 25 deletions src/modules/hyperswitch/hyperswitch-api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,9 @@ import { HyperswitchFullyConfiguredEntry } from "../payment-app-configuration/hy
import { env } from "@/lib/env.mjs";
import { invariant } from "@/lib/invariant";
import { ConfigObject } from "@/backend-lib/api-route-utils";
import { getEnvironmentFromKey } from "@/modules/api-utils";

const getHyperswitchBaseUrl = () => {
if (getEnvironmentFromKey() == "production") {
const getHyperswitchBaseUrl = (config_env: string) => {
if (config_env == "live") {
invariant(env.HYPERSWITCH_PROD_BASE_URL, "ENV variable HYPERSWITCH_PROD_BASE_URL not set");
return env.HYPERSWITCH_PROD_BASE_URL;
} else {
Expand All @@ -35,37 +34,28 @@ const getHyperswitchBaseUrl = () => {
}
};

const fetchHyperswitchConfiguration = async (
const fetchSavedConfiguration = async (
configData: ConfigObject,
): Promise<HyperswitchFullyConfiguredEntry> => {
): Promise<PaymentAppConfigEntryFullyConfigured> => {
const appConfig = await configData.configurator.getConfig();

const appChannelConfig = getConfigurationForChannel(appConfig, configData.channelId);
if (appChannelConfig == null) {
throw new ChannelNotConfigured("Please assign a channel for your configuration");
}

return getHyperswitchConfig(paymentAppFullyConfiguredEntrySchema.parse(appChannelConfig));
return paymentAppFullyConfiguredEntrySchema.parse(appChannelConfig);
};

export const fetchHyperswitchProfileID = async (configData: ConfigObject): Promise<string> => {
const appConfig = await configData.configurator.getConfig();
const appChannelConfig = getConfigurationForChannel(appConfig, configData.channelId);
if (appChannelConfig == null) {
throw new ChannelNotConfigured("Please assign a channel for your configuration");
}
let appChannelConfig = await fetchSavedConfiguration(configData);
const HyperswitchConfig = getHyperswitchConfig(
paymentAppFullyConfiguredEntrySchema.parse(appChannelConfig),
);
return HyperswitchConfig.profileId;
};

export const fetchHyperswitchPublishableKey = async (configData: ConfigObject): Promise<string> => {
const appConfig = await configData.configurator.getConfig();
const appChannelConfig = getConfigurationForChannel(appConfig, configData.channelId);
if (appChannelConfig == null) {
throw new ChannelNotConfigured("Please assign a channel for your configuration");
}
let appChannelConfig = await fetchSavedConfiguration(configData);
const HyperswitchConfig = getHyperswitchConfig(
paymentAppFullyConfiguredEntrySchema.parse(appChannelConfig),
);
Expand All @@ -75,22 +65,22 @@ export const fetchHyperswitchPublishableKey = async (configData: ConfigObject):
export const fetchHyperswitchPaymentResponseHashKey = async (
configData: ConfigObject,
): Promise<string> => {
const appConfig = await configData.configurator.getConfig();
const appChannelConfig = getConfigurationForChannel(appConfig, configData.channelId);
if (appChannelConfig == null) {
throw new ChannelNotConfigured("Please assign a channel for your configuration");
}
let appChannelConfig = await fetchSavedConfiguration(configData);
const HyperswitchConfig = getHyperswitchConfig(
paymentAppFullyConfiguredEntrySchema.parse(appChannelConfig),
);
return HyperswitchConfig.paymentResponseHashKey;
};

export const createHyperswitchClient = async ({ configData }: { configData: ConfigObject }) => {
const HyperswitchConfig = await fetchHyperswitchConfiguration(configData);
const SavedConfiguration = await fetchSavedConfiguration(configData);
const HyperswitchConfig = getHyperswitchConfig(
paymentAppFullyConfiguredEntrySchema.parse(SavedConfiguration),
);

const fetcher = Fetcher.for<HyperswitchPaymentPaths>();
fetcher.configure({
baseUrl: getHyperswitchBaseUrl(),
baseUrl: getHyperswitchBaseUrl(SavedConfiguration.environment),
init: {
headers: {
"api-key": HyperswitchConfig.apiKey,
Expand Down Expand Up @@ -121,6 +111,6 @@ export function getHyperswitchConfig(
if (config.hyperswitchConfiguration) {
return config.hyperswitchConfiguration;
} else {
throw new ConfigurationNotFound("Please add Hyperswitch configuration");
throw new ConfigurationNotFound("Please add a Hyperswitch configuration");
}
}
34 changes: 11 additions & 23 deletions src/modules/juspay/juspay-api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,9 @@ import { JuspayFullyConfiguredEntry } from "../payment-app-configuration/juspay-
import { getConfigurationForChannel } from "../payment-app-configuration/payment-app-configuration";
import { intoErrorResponse } from "./juspay-api-response";
import { invariant } from "@/lib/invariant";
import { getEnvironmentFromKey } from "@/modules/api-utils";

const getJuspayBaseUrl = () => {
if (getEnvironmentFromKey() == "production") {
const getJuspayBaseUrl = (config_env: string) => {
if (config_env == "live") {
invariant(env.JUSPAY_PROD_BASE_URL, "ENV variable HYPERSWITCH_PROD_BASE_URL not set");
return env.JUSPAY_PROD_BASE_URL;
} else {
Expand All @@ -23,60 +22,49 @@ const getJuspayBaseUrl = () => {
}
};

const fetchJuspayConfiguration = async (
const fetchSavedConfiguration = async (
configData: ConfigObject,
): Promise<JuspayFullyConfiguredEntry> => {
): Promise<PaymentAppConfigEntryFullyConfigured> => {
const appConfig = await configData.configurator.getConfig();
const appChannelConfig = getConfigurationForChannel(appConfig, configData.channelId);
if (appChannelConfig == null) {
throw new ChannelNotConfigured("Please assign a channel for your configuration");
}

return getJuspayConfig(paymentAppFullyConfiguredEntrySchema.parse(appChannelConfig));
return paymentAppFullyConfiguredEntrySchema.parse(appChannelConfig);
};

export const fetchJuspayCleintId = async (configData: ConfigObject): Promise<string> => {
const appConfig = await configData.configurator.getConfig();
const appChannelConfig = getConfigurationForChannel(appConfig, configData.channelId);
if (appChannelConfig == null) {
throw new ChannelNotConfigured("Please assign a channel for your configuration");
}
const appChannelConfig = await fetchSavedConfiguration(configData);
const JuspayConfig = getJuspayConfig(
paymentAppFullyConfiguredEntrySchema.parse(appChannelConfig),
);
return JuspayConfig.clientId;
};

export const fetchJuspayUsername = async (configData: ConfigObject): Promise<string> => {
const appConfig = await configData.configurator.getConfig();
const appChannelConfig = getConfigurationForChannel(appConfig, configData.channelId);
if (appChannelConfig == null) {
throw new ChannelNotConfigured("Please assign a channel for your configuration");
}
const appChannelConfig = await fetchSavedConfiguration(configData);
const JuspayConfig = getJuspayConfig(
paymentAppFullyConfiguredEntrySchema.parse(appChannelConfig),
);
return JuspayConfig.username;
};

export const fetchJuspayPassword = async (configData: ConfigObject): Promise<string> => {
const appConfig = await configData.configurator.getConfig();
const appChannelConfig = getConfigurationForChannel(appConfig, configData.channelId);
if (appChannelConfig == null) {
throw new ChannelNotConfigured("Please assign a channel for your configuration");
}
const appChannelConfig = await fetchSavedConfiguration(configData);
const JuspayConfig = getJuspayConfig(
paymentAppFullyConfiguredEntrySchema.parse(appChannelConfig),
);
return JuspayConfig.password;
};

export const createJuspayClient = async ({ configData }: { configData: ConfigObject }) => {
const JuspayConfig = await fetchJuspayConfiguration(configData);
const SavedConfiguration = await fetchSavedConfiguration(configData);
const JuspayConfig = getJuspayConfig(SavedConfiguration);
const fetcher = Fetcher.for<JuspayPaymentPaths>();
const apiKey = Buffer.from(JuspayConfig.apiKey).toString("base64");
fetcher.configure({
baseUrl: getJuspayBaseUrl(),
baseUrl: getJuspayBaseUrl(SavedConfiguration.environment),
init: {
headers: {
authorization: `Basic ${apiKey}`,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,12 @@ import {
hyperswitchUserVisibleConfigEntrySchema,
} from "../hyperswitch-app-configuration/config-entry";

const Environment = z.enum(["test", "live"]);

export const paymentAppConfigEntryInternalSchema = z.object({
configurationId: z.string().min(1),
configurationName: z.string().min(1),
environment: Environment,
});

export const paymentAppConfigEntryEncryptedSchema = z.object({
Expand Down Expand Up @@ -58,6 +61,7 @@ export const paymentAppFormConfigEntrySchema = z
hyperswitchConfiguration: hyperswitchFormConfigEntrySchema.nullable().optional(),
juspayConfiguration: juspayFormConfigEntrySchema.nullable().optional(),
configurationName: paymentAppConfigEntryInternalSchema.shape.configurationName,
environment: paymentAppConfigEntryInternalSchema.shape.environment,
})
.strict();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,7 @@ export const addConfigEntry = async (
juspayConfiguration: undefined,
configurationName: newConfigEntry.configurationName,
configurationId: uuid,
environment: newConfigEntry.environment,
} satisfies PaymentAppConfigEntryFullyConfigured;
await configurator.setConfigEntry(config);
const result = obfuscateConfigEntry(config);
Expand All @@ -112,6 +113,7 @@ export const addConfigEntry = async (
},
configurationName: newConfigEntry.configurationName,
configurationId: uuid,
environment: newConfigEntry.environment,
} satisfies PaymentAppConfigEntryFullyConfigured;
await configurator.setConfigEntry(config);
return obfuscateConfigEntry(config);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,8 @@ export const paymentAppConfigurationRouter = router({
add: protectedClientProcedure
.input(paymentAppFormConfigEntrySchema)
.mutation(async ({ input, ctx }) => {
const { hyperswitchConfiguration, juspayConfiguration, configurationName } = input;
const { hyperswitchConfiguration, juspayConfiguration, configurationName, environment } =
input;
if (juspayConfiguration) {
const { apiKey, username, clientId, password, merchantId } = juspayConfiguration;
ctx.logger.info("appConfigurationRouter.paymentConfig.add called");
Expand All @@ -76,6 +77,7 @@ export const paymentAppConfigurationRouter = router({
merchantId: redactLogValue(merchantId),
password: redactLogValue(password),
clientId: redactLogValue(clientId),
environment: redactLogValue(environment),
},
"appConfigurationRouter.paymentConfig.add input",
);
Expand Down
11 changes: 9 additions & 2 deletions src/modules/payment-app-configuration/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,13 @@ import {
export const obfuscateConfigEntry = (
entry: PaymentAppConfigEntry | PaymentAppUserVisibleConfigEntry,
): PaymentAppUserVisibleConfigEntry => {
const { configurationName, configurationId, hyperswitchConfiguration, juspayConfiguration } =
entry;
const {
configurationName,
configurationId,
hyperswitchConfiguration,
juspayConfiguration,
environment,
} = entry;

if (juspayConfiguration) {
const { apiKey, username, merchantId, password, clientId } = juspayConfiguration;
Expand All @@ -32,6 +37,7 @@ export const obfuscateConfigEntry = (
},
configurationName,
configurationId,
environment,
} satisfies PaymentAppUserVisibleConfigEntry);
} else {
invariant(hyperswitchConfiguration, "Missing Configuration Entry");
Expand All @@ -54,6 +60,7 @@ export const obfuscateConfigEntry = (
},
configurationName,
configurationId,
environment,
} satisfies PaymentAppUserVisibleConfigEntry);

return result;
Expand Down
41 changes: 40 additions & 1 deletion src/modules/ui/atoms/macaw-ui/FormInput.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,9 @@
import { Input as $Input, type InputProps as $InputProps } from "@saleor/macaw-ui";
import {
Input as $Input,
Select as $Select,
type InputProps as $InputProps,
type SelectProps as $SelectProps,
} from "@saleor/macaw-ui";
import {
type UseControllerProps,
type FieldPath,
Expand Down Expand Up @@ -37,3 +42,37 @@ export function FormInput<
/>
);
}

export type SelectProps<
TFieldValues extends FieldValues,
TName extends FieldPath<TFieldValues> = FieldPath<TFieldValues>,
TOption = any,
TValue = any,
> = UseControllerProps<TFieldValues, TName> & $SelectProps<TOption, TValue>;

export function SelectInput<
TFieldValues extends FieldValues,
TName extends FieldPath<TFieldValues> = FieldPath<TFieldValues>,
>(props: SelectProps<TFieldValues, TName>) {
const { field, fieldState } = useController<TFieldValues, TName>(props);

return (
<$Select
error={!!fieldState.error?.message}
{...props}
{...field}
helperText={fieldState.error?.message || props.helperText}
onChange={(e) => {
field.onChange(e.value);
props.onChange?.(e.value);
}}
onFocus={(e) => {
props.onFocus?.(e);
}}
onBlur={(e) => {
field.onBlur();
props.onBlur?.(e);
}}
/>
);
}
Original file line number Diff line number Diff line change
@@ -1,15 +1,16 @@
import { Box } from "@saleor/macaw-ui";
import { ChipSuccess, ChipHyperswitchOrange, ChipInfo } from "@/modules/ui/atoms/Chip/Chip";
import { getEnvironmentFromKey } from "@/modules/api-utils";

import { appBridgeInstance } from "@/app-bridge-instance";
import { HyperswitchUserVisibleConfigEntry } from "@/modules/payment-app-configuration/hyperswitch-app-configuration/config-entry";
import { JuspayUserVisibleConfigEntry } from "@/modules/payment-app-configuration/juspay-app-configuration/config-entry";
import { env } from "@/lib/env.mjs";

export const HyperswitchConfigurationSummary = ({
config,
environment,
}: {
config: HyperswitchUserVisibleConfigEntry;
environment: string;
}) => {
return (
<Box
Expand All @@ -25,7 +26,7 @@ export const HyperswitchConfigurationSummary = ({
Environment
</Box>
<Box as="dd" marginX={4} textAlign="right">
{getEnvironmentFromKey() === "production" ? (
{environment === "live" ? (
<ChipSuccess>LIVE</ChipSuccess>
) : (
<ChipHyperswitchOrange>TESTING</ChipHyperswitchOrange>
Expand All @@ -49,8 +50,10 @@ export const HyperswitchConfigurationSummary = ({

export const JuspayConfigurationSummary = ({
config,
environment,
}: {
config: JuspayUserVisibleConfigEntry;
environment: String;
}) => {
return (
<Box
Expand All @@ -66,7 +69,7 @@ export const JuspayConfigurationSummary = ({
Environment
</Box>
<Box as="dd" marginX={4} textAlign="right">
{getEnvironmentFromKey() === "production" ? (
{environment === "live" ? (
<ChipSuccess>LIVE</ChipSuccess>
) : (
<ChipHyperswitchOrange>TESTING</ChipHyperswitchOrange>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@ import {
type ChannelMapping,
} from "@/modules/payment-app-configuration/common-app-configuration/app-config";
import { type PaymentAppConfigEntry } from "@/modules/payment-app-configuration/common-app-configuration/config-entry";
import { getEnvironmentFromKey } from "@/modules/api-utils";

const ChannelToConfigurationTableRow = ({
channel,
Expand Down Expand Up @@ -94,7 +93,7 @@ const ChannelToConfigurationTableRow = ({
<Td className={classNames(tableStyles.td, tableStyles.statusColumnTd)}>
{!selectedConfiguration ? (
<ChipNeutral>Disabled</ChipNeutral>
) : getEnvironmentFromKey() === "live" ? (
) : selectedConfiguration.environment === "live" ? (
<ChipSuccess>LIVE</ChipSuccess>
) : (
<ChipHyperswitchOrange>TESTING</ChipHyperswitchOrange>
Expand Down
Loading

0 comments on commit a7e0d35

Please sign in to comment.