Skip to content

Commit

Permalink
Merge pull request #35 from mollie/feature/MOL-186/PICT-225
Browse files Browse the repository at this point in the history
Feature/mol 186/pict 225
  • Loading branch information
Tung-Huynh-Shopmacher authored Aug 9, 2024
2 parents 6f5e3f4 + 6827459 commit 88bd48e
Show file tree
Hide file tree
Showing 28 changed files with 641 additions and 196 deletions.
11 changes: 9 additions & 2 deletions connect.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -15,13 +15,20 @@ deployAs:
description: Enable Mollie cart component (0 or 1)
required: false
default: "0"
- key: CONNECTOR_MODE
description: Either test or live
required: true
default: "test"
- key: DEBUG
description: Debug mode (0 or 1)
required: false
default: "0"
securedConfiguration:
- key: MOLLIE_API_KEY
description: Mollie PSP API key
- key: MOLLIE_API_TEST_KEY
description: Mollie PSP test API key
required: true
- key: MOLLIE_API_LIVE_KEY
description: Mollie PSP live API key
required: true
- key: MOLLIE_PROFILE_ID
description: Mollie PSP profile ID
Expand Down
4 changes: 3 additions & 1 deletion processor/.env.example
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,9 @@ CTP_API_URL=https://api.<YOUR_CTP_REGION>.commercetools.com

## Mollie PSP credentials
DEBUG=<INTEGER_VALUE> ## Either 1 for enable or 0 for disable
MOLLIE_API_KEY=<YOUR_MOLLIE_API_KEY>
CONNECTOR_MODE=<YOUR_CONNECTOR_MODE> ## Either test or live
MOLLIE_API_TEST_KEY=<YOUR_MOLLIE_API_TEST_KEY>
MOLLIE_API_LIVE_KEY=<YOUR_MOLLIE_API_LIVE_KEY>
MOLLIE_PROFILE_ID=<YOUR_MOLLIE_PROFILE_ID>
MOLLIE_CARD_COMPONENT=0 ## Either 1 for enable or 0 for disable

Expand Down
4 changes: 3 additions & 1 deletion processor/.env.jest
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,11 @@ CTP_PROJECT_KEY=TEST
CTP_SCOPE=TEST
CTP_REGION=europe-west1.gcp
## MOLLIE vars
MOLLIE_API_KEY=12345678901234567890123456789012
MOLLIE_PROFILE_ID=pfl_12345
DEBUG=0
MOLLIE_CARD_COMPONENT=0
CONNECTOR_MODE=test ## Either test or live
MOLLIE_API_TEST_KEY=test_12345
MOLLIE_API_LIVE_KEY=live_12345

CONNECT_SERVICE_URL=http://localhost:3000/processor
4 changes: 2 additions & 2 deletions processor/package-lock.json

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

16 changes: 11 additions & 5 deletions processor/src/client/mollie.client.ts
Original file line number Diff line number Diff line change
@@ -1,16 +1,22 @@
import createMollieClient, { MollieClient } from '@mollie/api-client';
import { readConfiguration } from '../utils/config.utils';
import { LIBRARY_NAME, LIBRARY_VERSION } from '../utils/constant.utils';
import { getApiKey, readConfiguration } from '../utils/config.utils';
import { VERSION_STRING } from '../utils/constant.utils';

/**
* Initializes the Mollie client using the API key from the configuration.
*
* @return {MollieClient} Returns the initialized Mollie client.
*/
export const initMollieClient = (): MollieClient => {
const { mollie } = readConfiguration();
return createMollieClient({
apiKey: mollie.apiKey,
versionStrings: `${LIBRARY_NAME}/${LIBRARY_VERSION}`,
apiKey: getApiKey(),
versionStrings: `${VERSION_STRING}`,
});
};

export const initMollieClientForApplePaySession = (): MollieClient => {
return createMollieClient({
apiKey: readConfiguration().mollie.liveApiKey,
versionStrings: `${VERSION_STRING}`,
});
};
24 changes: 24 additions & 0 deletions processor/src/commercetools/customFields.commercetools.ts
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,30 @@ export async function createCustomPaymentType(): Promise<void> {
},
inputHint: 'MultiLine',
},
{
name: CustomFields.applePay.session.request,
label: {
en: 'The request object for inquiring the Apple Pay payment session',
de: 'Das Anfrageobjekt für die Abfrage der Apple Pay-Zahlungssitzung',
},
required: false,
type: {
name: 'String',
},
inputHint: 'MultiLine',
},
{
name: CustomFields.applePay.session.response,
label: {
en: 'The response object holding the Apple Pay payment session',
de: 'Das Antwortobjekt zur Speicherung der Apple Pay-Zahlungssitzung',
},
required: false,
type: {
name: 'String',
},
inputHint: 'MultiLine',
},
],
},
})
Expand Down
4 changes: 4 additions & 0 deletions processor/src/controllers/payment.controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import {
handleCancelPayment,
handleCreatePayment,
handleCreateRefund,
handleGetApplePaySession,
handleListPaymentMethodsByPayment,
handlePaymentCancelRefund,
} from '../service/payment.service';
Expand Down Expand Up @@ -56,6 +57,9 @@ export const paymentController = async (
case ConnectorActions.CancelRefund:
logger.debug('SCTM - payment processing - paymentController - handlePaymentCancelRefund');
return await handlePaymentCancelRefund(ctPayment);
case ConnectorActions.GetApplePaySession:
logger.debug('SCTM - payment processing - paymentController - getApplePaySession');
return await handleGetApplePaySession(ctPayment);
default:
logger.debug('SCTM - payment processing - paymentController - No payment actions matched');
throw new SkipError('No payment actions matched');
Expand Down
33 changes: 25 additions & 8 deletions processor/src/mollie/payment.mollie.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,13 @@ import {
PaymentCreateParams,
PaymentEmbed,
} from '@mollie/api-client';
import { initMollieClient } from '../client/mollie.client';
import { initMollieClient, initMollieClientForApplePaySession } from '../client/mollie.client';
import CustomError from '../errors/custom.error';
import { logger } from '../utils/logger.utils';
import { readConfiguration } from '../utils/config.utils';
import { LIBRARY_NAME, LIBRARY_VERSION } from '../utils/constant.utils';
import { CustomPayment } from '../types/mollie.types';
import { ApplePaySessionRequest, CustomPayment } from '../types/mollie.types';
import ApplePaySession from '@mollie/api-client/dist/types/src/data/applePaySession/ApplePaySession';
import { getApiKey } from '../utils/config.utils';
import { VERSION_STRING } from '../utils/constant.utils';
import fetch from 'node-fetch';

/**
Expand Down Expand Up @@ -107,12 +108,10 @@ export const createPaymentWithCustomMethod = async (paymentParams: PaymentCreate
let errorMessage;

try {
const { mollie } = readConfiguration();

const headers = {
'Content-Type': 'application/json',
Authorization: `Bearer ${mollie.apiKey}`,
versionStrings: `${LIBRARY_NAME}/${LIBRARY_VERSION}`,
Authorization: `Bearer ${getApiKey()}`,
versionStrings: `${VERSION_STRING}`,
};

const response = await fetch('https://api.mollie.com/v2/payments', {
Expand Down Expand Up @@ -149,3 +148,21 @@ export const createPaymentWithCustomMethod = async (paymentParams: PaymentCreate
throw new CustomError(400, errorMessage);
}
};

export const getApplePaySession = async (options: ApplePaySessionRequest): Promise<ApplePaySession> => {
try {
return await initMollieClientForApplePaySession().applePay.requestPaymentSession(options);
} catch (error: unknown) {
let errorMessage;
if (error instanceof MollieApiError) {
errorMessage = `SCTM - getApplePaySession - error: ${error.message}, field: ${error.field}`;
} else {
errorMessage = `SCTM - getApplePaySession - Failed to get ApplePay session with unknown errors`;
}

logger.error(errorMessage, {
error,
});
throw new CustomError(400, errorMessage);
}
};
23 changes: 22 additions & 1 deletion processor/src/service/payment.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import {
cancelPayment,
createMolliePayment,
createPaymentWithCustomMethod,
getApplePaySession,
getPaymentById,
listPaymentMethods,
} from '../mollie/payment.mollie';
Expand Down Expand Up @@ -54,7 +55,9 @@ import {
import { getPaymentExtension } from '../commercetools/extensions.commercetools';
import { HttpDestination } from '@commercetools/platform-sdk/dist/declarations/src/generated/models/extension';
import { cancelPaymentRefund, createPaymentRefund, getPaymentRefund } from '../mollie/refund.mollie';
import { CustomPayment } from '../types/mollie.types';
import { ApplePaySessionRequest, CustomPayment } from '../types/mollie.types';
import { parseStringToJsonObject } from '../utils/app.utils';
import ApplePaySession from '@mollie/api-client/dist/types/src/data/applePaySession/ApplePaySession';

/**
* Handles listing payment methods by payment.
Expand Down Expand Up @@ -527,3 +530,21 @@ export const handleCancelPayment = async (ctPayment: Payment): Promise<Controlle
actions: [],
};
};

export const handleGetApplePaySession = async (ctPayment: Payment): Promise<ControllerResponseType> => {
const requestOptions: ApplePaySessionRequest = parseStringToJsonObject(
ctPayment.custom?.fields[CustomFields.applePay.session.request],
CustomFields.applePay.session.request,
'SCTM - handleGetApplePaySession',
ctPayment.id,
);

const session: ApplePaySession = await getApplePaySession(requestOptions);

const ctActions: UpdateAction[] = [setCustomFields(CustomFields.applePay.session.response, JSON.stringify(session))];

return {
statusCode: 200,
actions: ctActions,
};
};
3 changes: 2 additions & 1 deletion processor/src/types/controller.types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,4 +11,5 @@ export type DeterminePaymentActionType =
| 'cancelPayment'
| 'createRefund'
| 'cancelRefund'
| 'noAction';
| 'noAction'
| 'getApplePaySession';
4 changes: 3 additions & 1 deletion processor/src/types/index.types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,9 @@ export type ConnectorEnvVars = {
region: string;
};
mollie: {
apiKey: string;
testApiKey: string;
liveApiKey: string;
mode: string;
profileId: string;
debug: string;
cardComponent: string;
Expand Down
4 changes: 4 additions & 0 deletions processor/src/types/mollie.types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,10 @@ export type ParsedMethodsRequestType = {
sequenceType?: string;
};

export type ApplePaySessionRequest = {
domain: string;
validationUrl: string;
};
export enum CustomPaymentMethod {
blik = 'blik',
}
Expand Down
11 changes: 10 additions & 1 deletion processor/src/utils/config.utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,9 @@ export const readConfiguration = () => {
region: process.env.CTP_REGION as string,
},
mollie: {
apiKey: process.env.MOLLIE_API_KEY as string,
testApiKey: process.env.MOLLIE_API_TEST_KEY as string,
liveApiKey: process.env.MOLLIE_API_LIVE_KEY as string,
mode: process.env.CONNECTOR_MODE as string,
debug: process.env.DEBUG as string,
profileId: process.env.MOLLIE_PROFILE_ID as string,
cardComponent: process.env.MOLLIE_CARD_COMPONENT as string,
Expand All @@ -36,3 +38,10 @@ export const readConfiguration = () => {

return envVars;
};

export const getApiKey = (): string => {
if (process.env.CONNECTOR_MODE === 'test') {
return process.env.MOLLIE_API_TEST_KEY as string;
}
return process.env.MOLLIE_API_LIVE_KEY as string;
};
7 changes: 7 additions & 0 deletions processor/src/utils/constant.utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,12 @@ export const CustomFields = {
interfaceInteraction: 'sctm_interface_interaction_type',
},
paymentCancelReason: 'sctm_payment_cancel_reason',
applePay: {
session: {
request: 'sctm_apple_pay_session_request',
response: 'sctm_apple_pay_session_response',
},
},
};

export enum ConnectorActions {
Expand All @@ -28,6 +34,7 @@ export enum ConnectorActions {
CreateRefund = 'createRefund',
CancelRefund = 'cancelRefund',
NoAction = 'noAction',
GetApplePaySession = 'getApplePaySession',
}

export const ErrorMessages = {
Expand Down
8 changes: 8 additions & 0 deletions processor/src/utils/paymentAction.utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,14 @@ export const determinePaymentAction = (ctPayment?: Payment): DeterminePaymentAct
return ConnectorActions.GetPaymentMethods;
}

const shouldGetAppleSession =
ctPayment.custom?.fields?.[CustomFields.applePay.session.request] &&
ctPayment.custom?.fields?.[CustomFields.applePay.session.request].length > 0;

if (shouldGetAppleSession) {
return ConnectorActions.GetApplePaySession;
}

const { transactions } = ctPayment;
const groups = getTransactionGroups(transactions);

Expand Down
25 changes: 22 additions & 3 deletions processor/src/validators/env.validators.ts
Original file line number Diff line number Diff line change
Expand Up @@ -46,9 +46,15 @@ const envValidators = [
referencedBy: 'environmentVariables',
}),

standardKey(['mollie', 'apiKey'], {
code: 'InvalidMollieApiKey',
message: 'Mollie API key should be a valid string.',
standardKey(['mollie', 'testApiKey'], {
code: 'InvalidMollieTestApiKey',
message: 'Mollie test API key should be a valid string.',
referencedBy: 'environmentVariables',
}),

standardKey(['mollie', 'liveApiKey'], {
code: 'InvalidMollieLiveApiKey',
message: 'Mollie live API key should be a valid string.',
referencedBy: 'environmentVariables',
}),

Expand Down Expand Up @@ -83,6 +89,19 @@ const envValidators = [
max: 1,
},
),

standardString(
['mollie', 'mode'],
{
code: 'InvalidMode',
message: 'Mode should be a valid string of either "test" or "live".',
referencedBy: 'environmentVariables',
},
{
min: 1,
max: 4,
},
),
];

export default envValidators;
Loading

0 comments on commit 88bd48e

Please sign in to comment.