Skip to content

Commit

Permalink
feat(payments-plugin): Check for eligibility of Mollie method (#3200)
Browse files Browse the repository at this point in the history
  • Loading branch information
martijnvdbrug authored Nov 15, 2024
1 parent 2ed3211 commit a12dedc
Show file tree
Hide file tree
Showing 3 changed files with 93 additions and 14 deletions.
46 changes: 45 additions & 1 deletion packages/payments-plugin/e2e/mollie-payment.e2e-spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,12 +42,15 @@ import {
import {
AddItemToOrderMutation,
AddItemToOrderMutationVariables,
AdjustOrderLineMutation,
AdjustOrderLineMutationVariables,
GetOrderByCodeQuery,
GetOrderByCodeQueryVariables,
TestOrderFragmentFragment,
} from './graphql/generated-shop-types';
import {
ADD_ITEM_TO_ORDER,
ADJUST_ORDER_LINE,
APPLY_COUPON_CODE,
GET_ACTIVE_ORDER,
GET_ORDER_BY_CODE,
Expand All @@ -60,6 +63,7 @@ import {
GET_MOLLIE_PAYMENT_METHODS,
refundOrderLine,
setShipping,
testPaymentEligibilityChecker,
} from './payment-helpers';

const mockData = {
Expand Down Expand Up @@ -181,6 +185,9 @@ describe('Mollie payments', () => {
beforeAll(async () => {
const devConfig = mergeConfig(testConfig(), {
plugins: [MolliePlugin.init({ vendureHost: mockData.host })],
paymentOptions: {
paymentMethodEligibilityCheckers: [testPaymentEligibilityChecker],
},
});
const env = createTestEnvironment(devConfig);
serverPort = devConfig.apiOptions.port;
Expand Down Expand Up @@ -224,6 +231,10 @@ describe('Mollie payments', () => {
input: {
code: mockData.methodCode,
enabled: true,
checker: {
code: testPaymentEligibilityChecker.code,
arguments: [],
},
handler: {
code: molliePaymentHandler.code,
arguments: [
Expand Down Expand Up @@ -390,7 +401,41 @@ describe('Mollie payments', () => {
});
});

it('Should not allow creating intent if payment method is not eligible', async () => {
// Set quantity to 9, which is not allowe by our test eligibility checker
await shopClient.query<AdjustOrderLineMutation, AdjustOrderLineMutationVariables>(
ADJUST_ORDER_LINE,
{
orderLineId: order.lines[0].id,
quantity: 9,
},
);
let mollieRequest: any | undefined;
nock('https://api.mollie.com/')
.post('/v2/orders', body => {
mollieRequest = body;
return true;
})
.reply(200, mockData.mollieOrderResponse);
const { createMolliePaymentIntent } = await shopClient.query(CREATE_MOLLIE_PAYMENT_INTENT, {
input: {
paymentMethodCode: mockData.methodCode,
redirectUrl: 'given-storefront-redirect-url',
},
});
expect(createMolliePaymentIntent.errorCode).toBe('INELIGIBLE_PAYMENT_METHOD_ERROR');
expect(createMolliePaymentIntent.message).toContain('is not eligible for order');
});

it('Should get payment url with deducted amount if a payment is already made', async () => {
// Change quantity back to 10
await shopClient.query<AdjustOrderLineMutation, AdjustOrderLineMutationVariables>(
ADJUST_ORDER_LINE,
{
orderLineId: order.lines[0].id,
quantity: 10,
},
);
let mollieRequest: any | undefined;
nock('https://api.mollie.com/')
.post('/v2/orders', body => {
Expand Down Expand Up @@ -702,7 +747,6 @@ describe('Mollie payments', () => {
>(CREATE_PAYMENT_METHOD, {
input: {
code: mockData.methodCodeBroken,

enabled: true,
handler: {
code: molliePaymentHandler.code,
Expand Down
20 changes: 20 additions & 0 deletions packages/payments-plugin/e2e/payment-helpers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,9 @@ import { ID } from '@vendure/common/lib/shared-types';
import {
ChannelService,
ErrorResult,
LanguageCode,
OrderService,
PaymentMethodEligibilityChecker,
PaymentService,
RequestContext,
assertFound,
Expand Down Expand Up @@ -189,6 +191,24 @@ export async function createFreeShippingCoupon(
}
}

/**
* Test payment eligibility checker that doesn't allow orders with quantity 9 on an order line,
* just so that we can easily mock non-eligibility
*/
export const testPaymentEligibilityChecker = new PaymentMethodEligibilityChecker({
code: 'test-payment-eligibility-checker',
description: [{ languageCode: LanguageCode.en, value: 'Do not allow 9 items' }],
args: {},
check: (ctx, order, args) => {
const hasLineWithQuantity9 = order.lines.find(line => line.quantity === 9);
if (hasLineWithQuantity9) {
return false;
} else {
return true;
}
},
});

export const CREATE_MOLLIE_PAYMENT_INTENT = gql`
mutation createMolliePaymentIntent($input: MolliePaymentIntentInput!) {
createMolliePaymentIntent(input: $input) {
Expand Down
41 changes: 28 additions & 13 deletions packages/payments-plugin/src/mollie/mollie.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import {
EntityHydrator,
ErrorResult,
ID,
idsAreEqual,
Injector,
LanguageCode,
Logger,
Expand Down Expand Up @@ -94,16 +95,33 @@ export class MollieService {
if (order instanceof PaymentIntentError) {
return order;
}
await this.entityHydrator.hydrate(ctx, order, {
relations: [
'customer',
'surcharges',
'lines.productVariant',
'lines.productVariant.translations',
'shippingLines.shippingMethod',
'payments',
],
});
if (!paymentMethod) {
return new PaymentIntentError(`No paymentMethod found with code ${String(paymentMethodCode)}`);
}
const [eligiblePaymentMethods] = await Promise.all([
this.orderService.getEligiblePaymentMethods(ctx, order.id),
await this.entityHydrator.hydrate(ctx, order, {
relations: [
'customer',
'surcharges',
'lines.productVariant',
'lines.productVariant.translations',
'shippingLines.shippingMethod',
'payments',
],
}),
]);
if (
!eligiblePaymentMethods.find(
eligibleMethod =>
idsAreEqual(eligibleMethod.id, paymentMethod?.id) && eligibleMethod.isEligible,
)
) {
// Given payment method code is not eligible for this order
return new InvalidInputError(
`Payment method ${paymentMethod?.code} is not eligible for order ${order.code}`,
);
}
if (order.state !== 'ArrangingPayment' && order.state !== 'ArrangingAdditionalPayment') {
// Pre-check if order is transitionable to ArrangingPayment, because that will happen after Mollie payment
try {
Expand All @@ -125,9 +143,6 @@ export class MollieService {
'Cannot create payment intent for order with customer that has no lastName set',
);
}
if (!paymentMethod) {
return new PaymentIntentError(`No paymentMethod found with code ${String(paymentMethodCode)}`);
}
let redirectUrl = input.redirectUrl;
if (!redirectUrl) {
// Use fallback redirect if no redirectUrl is given
Expand Down

0 comments on commit a12dedc

Please sign in to comment.