Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Rearrange validation flow #8

Merged
merged 4 commits into from
Jul 19, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 9 additions & 5 deletions connect.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,13 @@ deployAs:
configuration:
standardConfiguration:
- key: CTP_REGION
description: commercetools Composable Commerce API region
description: Commercetools Composable Commerce API region
required: true
default: "europe-west1.gcp"
- key: DEBUG
description: Debug mode (0 or 1)
required: false
default: "0"
securedConfiguration:
- key: MOLLIE_API_KEY
description: Mollie PSP API key
Expand All @@ -19,14 +23,14 @@ deployAs:
description: Mollie PSP profile ID
required: true
- key: CTP_PROJECT_KEY
description: commercetools Composable Commerce project key
description: Commercetools Composable Commerce project key
required: true
- key: CTP_CLIENT_ID
description: commercetools Composable Commerce client ID
description: Commercetools Composable Commerce client ID
required: true
- key: CTP_CLIENT_SECRET
description: commercetools Composable Commerce client secret
description: Commercetools Composable Commerce client secret
required: true
- key: CTP_SCOPE
description: commercetools Composable Commerce client scope
description: Commercetools Composable Commerce client scope
required: true
2 changes: 1 addition & 1 deletion processor/.env.example
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ CTP_AUTH_URL=https://auth.<YOUR_CTP_REGION>.commercetools.com
CTP_API_URL=https://api.<YOUR_CTP_REGION>.commercetools.com

## Mollie PSP credentials
MOLLIE_DEBUG=<INTEGER_VALUE> ## Either 1 for enable or 0 for disable
DEBUG=<INTEGER_VALUE> ## Either 1 for enable or 0 for disable
MOLLIE_API_KEY=<YOUR_MOLLIE_API_KEY>
MOLLIE_PROFILE_ID=<YOUR_MOLLIE_PROFILE_ID>

Expand Down
2 changes: 1 addition & 1 deletion processor/.env.jest
Original file line number Diff line number Diff line change
Expand Up @@ -8,4 +8,4 @@ CTP_REGION=europe-west1.gcp
## MOLLIE vars
MOLLIE_API_KEY=12345678901234567890123456789012
MOLLIE_PROFILE_ID=pfl_12345
MOLLIE_DEBUG=1
DEBUG=0
2 changes: 1 addition & 1 deletion processor/.nvmrc
Original file line number Diff line number Diff line change
@@ -1 +1 @@
16.16.0
18.12.0
27 changes: 20 additions & 7 deletions processor/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 3 additions & 2 deletions processor/package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "shopmacher-mollie-processor",
"description": "Integration between commercetools and mollie payment service provider",
"version": "0.0.8",
"version": "0.0.11",
"main": "index.js",
"private": true,
"scripts": {
Expand Down Expand Up @@ -30,7 +30,7 @@
"payment provider"
],
"engines": {
"node": ">=18.0.0"
"node": ">=18.0.0 <=20.9.0"
},
"resolutions": {
"axios": "1.6.8"
Expand Down Expand Up @@ -70,6 +70,7 @@
"dotenv": "^16.4.5",
"express": "^4.19.2",
"proxy-from-env": "^1.1.0",
"uuid": "^10.0.0",
"validator": "^13.12.0"
}
}
23 changes: 16 additions & 7 deletions processor/src/controllers/payment.controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { PaymentReference, Payment } from '@commercetools/platform-sdk';
import { ConnectorActions } from '../utils/constant.utils';
import { validateCommerceToolsPaymentPayload } from '../validators/payment.validators';
import CustomError from '../errors/custom.error';
import SkipError from '../errors/skip.error';

/**
* Handle the cart controller according to the action
Expand All @@ -19,20 +20,28 @@ export const paymentController = async (
): Promise<ControllerResponseType> => {
const ctPayment: Payment = JSON.parse(JSON.stringify(resource)).obj;

validateCommerceToolsPaymentPayload(action, ctPayment);

const controllerAction = determinePaymentAction(ctPayment);

if (controllerAction.errorMessage !== '') {
throw new CustomError(400, controllerAction.errorMessage as string);
}

if (controllerAction.action === ConnectorActions.NoAction) {
throw new SkipError('SCTM - No payment actions matched');
}

validateCommerceToolsPaymentPayload(action, controllerAction.action, ctPayment);

switch (controllerAction.action) {
case ConnectorActions.GetPaymentMethods:
return await handleListPaymentMethodsByPayment(ctPayment);
case ConnectorActions.CreatePayment:
return await handleCreatePayment(ctPayment);
case ConnectorActions.NoAction:
return {
statusCode: 200,
};
default:
throw new CustomError(400, controllerAction.errorMessage ?? '');
if (controllerAction.errorMessage === '') {
throw new SkipError('SCTM - No payment actions matched');
}

throw new CustomError(400, controllerAction.errorMessage as string);
}
};
5 changes: 3 additions & 2 deletions processor/src/controllers/processor.controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
import CustomError from '../errors/custom.error';
import SkipError from '../errors/skip.error';
import { apiError } from '../api/error.api';
import { formatErrorResponse } from '../errors/mollie.error';

/**
* Exposed service endpoint.
Expand All @@ -18,7 +19,7 @@
* @param {NextFunction} next
* @returns
*/
export const post = async (request: Request, response: Response, next: NextFunction) => {

Check warning on line 22 in processor/src/controllers/processor.controller.ts

View workflow job for this annotation

GitHub Actions / build-processor

'next' is defined but never used. Allowed unused args must match /^_/u

Check warning on line 22 in processor/src/controllers/processor.controller.ts

View workflow job for this annotation

GitHub Actions / build-processor

'next' is defined but never used
try {
const { action, resource }: ExtensionInput = request.body;

Expand All @@ -44,8 +45,8 @@
}
if (error instanceof CustomError) {
return apiError(response, error.errors);
} else {
next(error);
}

return apiError(response, formatErrorResponse(error).errors);
}
};
3 changes: 1 addition & 2 deletions processor/src/service/payment.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,15 +42,14 @@ export const handleListPaymentMethodsByPayment = async (ctPayment: Payment): Pro
try {
const mollieOptions = await mapCommercetoolsPaymentCustomFieldsToMollieListParams(ctPayment);
const methods: List<Method> = await listPaymentMethods(mollieOptions);

const availableMethods = JSON.stringify({
count: methods.length,
methods: methods.length ? methods : [],
});

const ctUpdateActions: UpdateAction[] = [setCustomFields(CustomFields.payment.response, availableMethods)];

const hasCardPayment = methods.findIndex((method: Method) => method.id === PaymentMethod.creditcard);
const hasCardPayment = methods.find((method: Method) => method.id === PaymentMethod.creditcard);

if (hasCardPayment) {
ctUpdateActions.push(setCustomFields(CustomFields.payment.profileId, readConfiguration().mollie.profileId));
Expand Down
2 changes: 1 addition & 1 deletion processor/src/utils/config.utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ export const readConfiguration = () => {
},
mollie: {
apiKey: process.env.MOLLIE_API_KEY as string,
debug: process.env.MOLLIE_DEBUG as string,
debug: process.env.DEBUG as string,
profileId: process.env.MOLLIE_PROFILE_ID as string,
},
};
Expand Down
6 changes: 3 additions & 3 deletions processor/src/utils/paymentAction.utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ export const determinePaymentAction = (ctPayment?: Payment): DeterminePaymentAct
};
}

const { key, transactions } = ctPayment;
const { id, key, transactions } = ctPayment;

const initialChargeTransactions: CTTransaction[] = [];
const pendingChargeTransactions: CTTransaction[] = [];
Expand Down Expand Up @@ -70,15 +70,15 @@ export const determinePaymentAction = (ctPayment?: Payment): DeterminePaymentAct
break;

// Create Payment
case !!key &&
case (!!key || !!id) &&
initialChargeTransactions.length === 1 &&
!successChargeTransactions.length &&
!pendingChargeTransactions.length:
action = ConnectorActions.CreatePayment;
break;
default:
action = ConnectorActions.NoAction;
errorMessage = 'SCTM - No payment actions matched';
logger.warn('SCTM - No payment actions matched');
}

return {
Expand Down
23 changes: 15 additions & 8 deletions processor/src/validators/payment.validators.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { PaymentMethod as MolliePaymentMethods } from '@mollie/api-client';
import SkipError from '../errors/skip.error';
import CustomError from '../errors/custom.error';
import { logger } from '../utils/logger.utils';
import { CustomFields } from '../utils/constant.utils';
import { ConnectorActions, CustomFields } from '../utils/constant.utils';

/**
* Checks if the given action is either 'Create' or 'Update'.
Expand Down Expand Up @@ -51,12 +51,12 @@ export const hasValidPaymentMethod: (method: string | undefined) => boolean = (m
/**
* Checks the payment method input of a Commercetools Payment object.
*
* @param {CTPayment} CTPayment - The Commercetools Payment object to check.
* @return {true | CustomError} An object containing the validation result.
* The `isInvalid` property indicates if the payment method input is invalid.
* The `errorMessage` property contains the error message if the input is invalid.
* @param ctPayment
*/
export const checkPaymentMethodInput = (ctPayment: CTPayment): true | CustomError => {
export const checkPaymentMethodInput = (connectorAction: string, ctPayment: CTPayment): true | CustomError => {
const CTPaymentMethod = ctPayment.paymentMethodInfo?.method ?? '';
const [method] = CTPaymentMethod.split(',');

Expand Down Expand Up @@ -128,16 +128,23 @@ export const checkAmountPlanned = (ctPayment: CTPayment): true | CustomError =>
/**
* Validates the payload of a CommerceTools payment based on the provided action and payment object.
*
* @param {string} action - The action to perform on the payment.
* @param {CTPayment} CTPayment - The CommerceTools payment object to validate.
* @param {string} extensionAction - The action to perform on the payment.
* @param {string} controllerAction - The determined action that need to be done with the payment.
* @param {CTPayment} ctPayment - The CommerceTools payment object to validate.
* @return {void} - An object containing the validated action and an error message if validation fails.
*/
export const validateCommerceToolsPaymentPayload = (action: string, ctPayment: CTPayment): void => {
checkExtensionAction(action);
export const validateCommerceToolsPaymentPayload = (
extensionAction: string,
connectorAction: string,
ctPayment: CTPayment,
): void => {
checkExtensionAction(extensionAction);

checkPaymentInterface(ctPayment);

checkPaymentMethodInput(ctPayment);
if (connectorAction === ConnectorActions.CreatePayment) {
checkPaymentMethodInput(connectorAction, ctPayment);
}

checkAmountPlanned(ctPayment);
};
8 changes: 7 additions & 1 deletion processor/tests/controllers/payment.controller.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,11 @@ describe('Test payment.controller.ts', () => {
} as unknown as Payment,
} as PaymentReference;

(determinePaymentAction as jest.Mock).mockReturnValue({
action: ConnectorActions.GetPaymentMethods,
errorMessage: '',
});

(validateCommerceToolsPaymentPayload as jest.Mock).mockImplementationOnce(() => {
throw new CustomError(400, 'dummy message');
});
Expand All @@ -61,7 +66,8 @@ describe('Test payment.controller.ts', () => {
expect(error).toBeInstanceOf(CustomError);
expect(error.statusCode).toBe(400);
expect(error.message).toBe('dummy message');
expect(determinePaymentAction).toBeCalledTimes(0);
expect(determinePaymentAction).toBeCalledTimes(1);
expect(validateCommerceToolsPaymentPayload).toBeCalledTimes(1);
expect(handleListPaymentMethodsByPayment).toBeCalledTimes(0);
expect(handleCreatePayment).toBeCalledTimes(0);
});
Expand Down
6 changes: 3 additions & 3 deletions processor/tests/utils/config.utils.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ describe('Test src/utils/config.utils.ts', () => {
},
mollie: {
apiKey: process.env.MOLLIE_API_KEY,
debug: process.env.MOLLIE_DEBUG,
debug: process.env.DEBUG,
profileId: process.env.MOLLIE_PROFILE_ID,
},
});
Expand Down Expand Up @@ -51,8 +51,8 @@ describe('Test src/utils/config.utils.ts', () => {
expect(() => readConfiguration()).toThrow(CustomError);
});

test('should throw an error when MOLLIE_DEBUG is not defined', () => {
delete process.env.MOLLIE_DEBUG;
test('should throw an error when DEBUG is not defined', () => {
delete process.env.DEBUG;
expect(() => readConfiguration()).toThrow(CustomError);
});
});
4 changes: 2 additions & 2 deletions processor/tests/validators/helpers.validators.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -234,7 +234,7 @@ describe('Test helpers.validators.ts', () => {
},
mollie: {
apiKey: process.env.MOLLIE_API_KEY as string,
debug: (process.env.MOLLIE_DEBUG ?? '0') as string,
debug: (process.env.DEBUG ?? '0') as string,
profileId: process.env.MOLLIE_PROFILE_ID as string,
},
};
Expand All @@ -254,7 +254,7 @@ describe('Test helpers.validators.ts', () => {
},
mollie: {
apiKey: process.env.MOLLIE_API_KEY as string,
debug: (process.env.MOLLIE_DEBUG ?? '0') as string,
debug: (process.env.DEBUG ?? '0') as string,
profileId: process.env.MOLLIE_PROFILE_ID as string,
},
};
Expand Down
Loading