Skip to content

Commit

Permalink
feat(payment): add EPS payment method support (#156)
Browse files Browse the repository at this point in the history
* feat(payment): add EPS payment method support

* fix(enabler): get the eps and klarna methods to work again in dev-tools

* fix(processor): add mocks for to fix unit-testing

* chore(enabler): fix klarna keys
  • Loading branch information
joey-koster-ct authored Jul 17, 2024
1 parent 67f88f3 commit 45308a5
Show file tree
Hide file tree
Showing 9 changed files with 74 additions and 3 deletions.
1 change: 1 addition & 0 deletions enabler/dev-utils/session.js
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ const getSessionId = async (cartId) => {
"paypal",
"applepay",
"googlepay",
"eps"
], // add here your allowed methods for development purposes
};

Expand Down
3 changes: 2 additions & 1 deletion enabler/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -169,7 +169,8 @@ <h1 class="h3 mb-3 font-weight-normal">Dev Site</h1>
});

if (builder.componentHasSubmit) {
if (selectedValue === 'card') {
const methodsRequireMounting = ['eps', 'card', 'klarna_pay_now', 'klarna_pay_later', 'klarna_pay_overtime'];
if (methodsRequireMounting.includes(selectedValue)) {
component.mount("#container--external");
}

Expand Down
52 changes: 52 additions & 0 deletions enabler/src/components/payment-methods/eps.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
import Core from "@adyen/adyen-web/dist/types/core/core";
import {
ComponentOptions,
PaymentComponent,
PaymentMethod
} from "../../payment-enabler/payment-enabler";
import {
AdyenBaseComponentBuilder,
DefaultAdyenComponent,
BaseOptions,
} from "../base";

/**
* EPS component
*
* Configuration options:
* https://docs.adyen.com/payment-methods/eps/web-component/
*/
export class EPSBuilder extends AdyenBaseComponentBuilder {

constructor(baseOptions: BaseOptions) {
super(PaymentMethod.eps, baseOptions);
}

build(config: ComponentOptions): PaymentComponent {
const epsComponent = new EPSComponent({
paymentMethod: this.paymentMethod,
adyenCheckout: this.adyenCheckout,
componentOptions: config,
sessionId: this.sessionId,
processorUrl: this.processorUrl,
});
epsComponent.init();
return epsComponent;
}
}

export class EPSComponent extends DefaultAdyenComponent {
constructor(opts: {
paymentMethod: PaymentMethod;
adyenCheckout: typeof Core;
componentOptions: ComponentOptions;
sessionId: string;
processorUrl: string;
}) {
super(opts);
}

init() {
this.component = this.adyenCheckout.create(this.paymentMethod, {});
}
}
2 changes: 2 additions & 0 deletions enabler/src/payment-enabler/adyen-payment-enabler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import { PaypalBuilder } from "../components/payment-methods/paypal";
import { KlarnaPayNowBuilder } from "../components/payment-methods/klarna-pay-now";
import { KlarnaPayLaterBuilder } from "../components/payment-methods/klarna-pay-later";
import { KlarnaPayOverTimeBuilder } from "../components/payment-methods/klarna-pay-over-time";
import { EPSBuilder } from "../components/payment-methods/eps";

class AdyenInitError extends Error {
sessionId: string;
Expand Down Expand Up @@ -187,6 +188,7 @@ export class AdyenPaymentEnabler implements PaymentEnabler {
klarna_pay_now: KlarnaPayNowBuilder,
klarna_pay_later: KlarnaPayLaterBuilder,
klarna_pay_overtime: KlarnaPayOverTimeBuilder,
eps: EPSBuilder
};
if (!Object.keys(supportedMethods).includes(type)) {
throw new Error(
Expand Down
1 change: 1 addition & 0 deletions enabler/src/payment-enabler/payment-enabler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ export enum PaymentMethod {
klarna_pay_now = "klarna_paynow", // Pay now
klarna_pay_later = "klarna", // Pay later
klarna_pay_overtime = "klarna_account", // Pay over time
eps = "eps"
}

export type PaymentResult = {
Expand Down
3 changes: 3 additions & 0 deletions processor/src/config/payment-method.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,4 +16,7 @@ export const paymentMethodConfig: PaymentMethodConfig = {
ideal: {
supportSeparateCapture: false,
},
eps: {
supportSeparateCapture: false,
},
};
6 changes: 5 additions & 1 deletion processor/src/services/adyen-payment.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -517,7 +517,11 @@ export class AdyenPaymentService extends AbstractPaymentService {
private convertAdyenResultCode(resultCode: PaymentResponse.ResultCodeEnum, isActionRequired: boolean): string {
if (resultCode === PaymentResponse.ResultCodeEnum.Authorised) {
return 'Success';
} else if (resultCode === PaymentResponse.ResultCodeEnum.Pending && !isActionRequired) {
} else if (
(resultCode === PaymentResponse.ResultCodeEnum.Pending ||
resultCode === PaymentResponse.ResultCodeEnum.Received) &&
!isActionRequired
) {
return 'Pending';
} else if (
resultCode === PaymentResponse.ResultCodeEnum.Refused ||
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,9 @@ export class PaymentComponentsConverter {
{
type: 'klarna_pay_overtime', // klarna_account
},
{
type: 'eps',
},
],
};
}
Expand Down
6 changes: 5 additions & 1 deletion processor/test/services/adyen-payment.service.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@ describe('adyen-payment.service', () => {

test('getSupportedPaymentComponents', async () => {
const result: SupportedPaymentComponentsSchemaDTO = await paymentService.getSupportedPaymentComponents();
expect(result?.components).toHaveLength(8);
expect(result?.components).toHaveLength(9);
expect(result?.components[0]?.type).toStrictEqual('card');
expect(result?.components[1]?.type).toStrictEqual('ideal');
expect(result?.components[2]?.type).toStrictEqual('paypal');
Expand All @@ -107,6 +107,7 @@ describe('adyen-payment.service', () => {
expect(result?.components[5]?.type).toStrictEqual('klarna_pay_now');
expect(result?.components[6]?.type).toStrictEqual('klarna_pay_later');
expect(result?.components[7]?.type).toStrictEqual('klarna_pay_overtime');
expect(result?.components[8]?.type).toStrictEqual('eps');
});

test('getStatus', async () => {
Expand Down Expand Up @@ -411,6 +412,7 @@ describe('adyen-payment.service', () => {
jest.spyOn(DefaultPaymentService.prototype, 'createPayment').mockResolvedValue(mockGetPaymentResult);
jest.spyOn(DefaultCartService.prototype, 'addPayment').mockResolvedValue(mockGetCartResult());
jest.spyOn(FastifyContext, 'getProcessorUrlFromContext').mockReturnValue('http://127.0.0.1');
jest.spyOn(FastifyContext, 'getMerchantReturnUrlFromContext').mockReturnValue('http://127.0.0.1/checkout/result');
jest.spyOn(PaymentsApi.prototype, 'payments').mockResolvedValue(mockAdyenCreatePaymentResponse);

jest.spyOn(DefaultPaymentService.prototype, 'updatePayment').mockResolvedValue(mockGetPaymentResult);
Expand All @@ -437,6 +439,7 @@ describe('adyen-payment.service', () => {
jest.spyOn(DefaultPaymentService.prototype, 'createPayment').mockResolvedValue(mockGetPaymentResult);
jest.spyOn(DefaultCartService.prototype, 'addPayment').mockResolvedValue(mockGetCartResult());
jest.spyOn(FastifyContext, 'getProcessorUrlFromContext').mockReturnValue('http://127.0.0.1');
jest.spyOn(FastifyContext, 'getMerchantReturnUrlFromContext').mockReturnValue('http://127.0.0.1/checkout/result');
jest.spyOn(PaymentsApi.prototype, 'payments').mockResolvedValue(mockAdyenCreatePaymentResponse);

jest.spyOn(DefaultPaymentService.prototype, 'updatePayment').mockResolvedValue(mockGetPaymentResult);
Expand All @@ -463,6 +466,7 @@ describe('adyen-payment.service', () => {
jest.spyOn(DefaultPaymentService.prototype, 'createPayment').mockResolvedValue(mockGetPaymentResult);
jest.spyOn(DefaultCartService.prototype, 'addPayment').mockResolvedValue(mockGetCartResult());
jest.spyOn(FastifyContext, 'getProcessorUrlFromContext').mockReturnValue('http://127.0.0.1');
jest.spyOn(FastifyContext, 'getMerchantReturnUrlFromContext').mockReturnValue('http://127.0.0.1/checkout/result');
jest.spyOn(PaymentsApi.prototype, 'payments').mockResolvedValue(mockAdyenCreatePaymentResponse);

jest.spyOn(DefaultPaymentService.prototype, 'updatePayment').mockResolvedValue(mockGetPaymentResult);
Expand Down

0 comments on commit 45308a5

Please sign in to comment.