Skip to content

Commit

Permalink
fix(payments-plugin): Allow mollie orders with $0 (#2855)
Browse files Browse the repository at this point in the history
  • Loading branch information
martijnvdbrug authored May 24, 2024
1 parent 0b1dcb7 commit b54c210
Show file tree
Hide file tree
Showing 7 changed files with 252 additions and 91 deletions.
11 changes: 11 additions & 0 deletions packages/payments-plugin/e2e/graphql/admin-queries.ts
Original file line number Diff line number Diff line change
Expand Up @@ -114,3 +114,14 @@ export const CREATE_CHANNEL = gql`
}
}
`;

export const CREATE_COUPON = gql`
mutation CreatePromotion($input: CreatePromotionInput!) {
createPromotion(input: $input) {
... on ErrorResult {
errorCode
}
__typename
}
}
`;
37 changes: 26 additions & 11 deletions packages/payments-plugin/e2e/graphql/shop-queries.ts
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,17 @@ export const TEST_ORDER_FRAGMENT = gql`
type
}
}
shippingAddress {
fullName
company
streetLine1
streetLine2
city
province
postalCode
country
phoneNumber
}
shippingLines {
shippingMethod {
id
Expand Down Expand Up @@ -104,24 +115,15 @@ export const SET_SHIPPING_ADDRESS = gql`
mutation SetShippingAddress($input: CreateAddressInput!) {
setOrderShippingAddress(input: $input) {
... on Order {
shippingAddress {
fullName
company
streetLine1
streetLine2
city
province
postalCode
country
phoneNumber
}
...TestOrderFragment
}
... on ErrorResult {
errorCode
message
}
}
}
${TEST_ORDER_FRAGMENT}
`;

export const GET_ELIGIBLE_SHIPPING_METHODS = gql`
Expand Down Expand Up @@ -221,3 +223,16 @@ export const GET_ACTIVE_ORDER = gql`
}
${TEST_ORDER_FRAGMENT}
`;

export const APPLY_COUPON_CODE = gql`
mutation ApplyCouponCode($couponCode: String!) {
applyCouponCode(couponCode: $couponCode) {
...TestOrderFragment
... on ErrorResult {
errorCode
message
}
}
}
${TEST_ORDER_FRAGMENT}
`;
69 changes: 19 additions & 50 deletions packages/payments-plugin/e2e/mollie-dev-server.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,6 @@
import { AdminUiPlugin } from '@vendure/admin-ui-plugin';
import {
ChannelService,
DefaultLogger,
DefaultSearchPlugin,
LogLevel,
mergeConfig,
RequestContext,
} from '@vendure/core';
import { DefaultLogger, DefaultSearchPlugin, LogLevel, mergeConfig } from '@vendure/core';
import { createTestEnvironment, registerInitializer, SqljsInitializer, testConfig } from '@vendure/testing';
import { compileUiExtensions } from '@vendure/ui-devkit/compiler';
import gql from 'graphql-tag';
import localtunnel from 'localtunnel';
import path from 'path';
Expand All @@ -23,9 +15,13 @@ import {
CreatePaymentMethodMutationVariables,
LanguageCode,
} from './graphql/generated-admin-types';
import { AddItemToOrderMutation, AddItemToOrderMutationVariables } from './graphql/generated-shop-types';
import { ADD_ITEM_TO_ORDER, ADJUST_ORDER_LINE } from './graphql/shop-queries';
import { CREATE_MOLLIE_PAYMENT_INTENT, setShipping } from './payment-helpers';
import { ADD_ITEM_TO_ORDER, APPLY_COUPON_CODE } from './graphql/shop-queries';
import {
CREATE_MOLLIE_PAYMENT_INTENT,
createFixedDiscountCoupon,
createFreeShippingCoupon,
setShipping,
} from './payment-helpers';

/**
* This should only be used to locally test the Mollie payment plugin
Expand Down Expand Up @@ -99,50 +95,23 @@ async function runMollieDevServer() {
},
},
);
// Prepare order with 2 items
// Prepare a test order where the total is 0
await shopClient.asUserWithCredentials('hayden.zieme12@hotmail.com', 'test');
// Add another item to the order
await shopClient.query<AddItemToOrderMutation, AddItemToOrderMutationVariables>(ADD_ITEM_TO_ORDER, {
productVariantId: 'T_4',
quantity: 1,
});
await shopClient.query<AddItemToOrderMutation, AddItemToOrderMutationVariables>(ADD_ITEM_TO_ORDER, {
productVariantId: 'T_5',
await shopClient.query(ADD_ITEM_TO_ORDER, {
productVariantId: 'T_1',
quantity: 1,
});
await setShipping(shopClient);
// Create payment intent
// Create payment intent
const { createMolliePaymentIntent } = await shopClient.query(CREATE_MOLLIE_PAYMENT_INTENT, {
input: {
redirectUrl: `${tunnel.url}/admin/orders?filter=open&page=1`,
paymentMethodCode: 'mollie',
// molliePaymentMethodCode: 'klarnapaylater'
},
});
if (createMolliePaymentIntent.errorCode) {
throw createMolliePaymentIntent;
}
// eslint-disable-next-line no-console
console.log('\x1b[41m', `Mollie payment link: ${createMolliePaymentIntent.url as string}`, '\x1b[0m');

// Remove first orderLine
await shopClient.query(ADJUST_ORDER_LINE, {
orderLineId: 'T_1',
quantity: 0,
});
await setShipping(shopClient);
// Comment out these lines if you want to test the payment flow via Mollie
await createFixedDiscountCoupon(adminClient, 156880, 'DISCOUNT_ORDER');
await createFreeShippingCoupon(adminClient, 'FREE_SHIPPING');
await shopClient.query(APPLY_COUPON_CODE, { couponCode: 'DISCOUNT_ORDER' });
await shopClient.query(APPLY_COUPON_CODE, { couponCode: 'FREE_SHIPPING' });

// Create another intent after Xs, should update the mollie order
await new Promise(resolve => setTimeout(resolve, 5000));
const { createMolliePaymentIntent: secondIntent } = await shopClient.query(CREATE_MOLLIE_PAYMENT_INTENT, {
input: {
redirectUrl: `${tunnel.url}/admin/orders?filter=open&page=1&dynamicRedirectUrl=true`,
paymentMethodCode: 'mollie',
},
});
// Create Payment Intent
const result = await shopClient.query(CREATE_MOLLIE_PAYMENT_INTENT, { input: {} });
// eslint-disable-next-line no-console
console.log('\x1b[41m', `Second payment link: ${secondIntent.url as string}`, '\x1b[0m');
console.log('Payment intent result', result);
}

(async () => {
Expand Down
41 changes: 39 additions & 2 deletions packages/payments-plugin/e2e/mollie-payment.e2e-spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import {
EventBus,
LanguageCode,
mergeConfig,
Order,
OrderPlacedEvent,
OrderService,
RequestContext,
Expand Down Expand Up @@ -44,10 +45,17 @@ import {
GetOrderByCodeQueryVariables,
TestOrderFragmentFragment,
} from './graphql/generated-shop-types';
import { ADD_ITEM_TO_ORDER, GET_ORDER_BY_CODE } from './graphql/shop-queries';
import {
ADD_ITEM_TO_ORDER,
APPLY_COUPON_CODE,
GET_ACTIVE_ORDER,
GET_ORDER_BY_CODE,
} from './graphql/shop-queries';
import {
addManualPayment,
CREATE_MOLLIE_PAYMENT_INTENT,
createFixedDiscountCoupon,
createFreeShippingCoupon,
GET_MOLLIE_PAYMENT_METHODS,
refundOrderLine,
setShipping,
Expand Down Expand Up @@ -196,7 +204,7 @@ describe('Mollie payments', () => {
authorizedAsOwnerOnly: false,
channel: await server.app.get(ChannelService).getDefaultChannel(),
});
await server.app.get(OrderService).addSurchargeToOrder(ctx, 1, {
await server.app.get(OrderService).addSurchargeToOrder(ctx, order.id.replace('T_', ''), {
description: 'Negative test surcharge',
listPrice: SURCHARGE_AMOUNT,
});
Expand Down Expand Up @@ -441,6 +449,34 @@ describe('Mollie payments', () => {
expect(method.maximumAmount).toBeDefined();
expect(method.image).toBeDefined();
});

it('Transitions to PaymentSettled for orders with a total of $0', async () => {
await shopClient.asUserWithCredentials(customers[1].emailAddress, 'test');
const { addItemToOrder } = await shopClient.query(ADD_ITEM_TO_ORDER, {
productVariantId: 'T_1',
quantity: 1,
});
await setShipping(shopClient);
// Discount the order so it has a total of $0
await createFixedDiscountCoupon(adminClient, 156880, 'DISCOUNT_ORDER');
await createFreeShippingCoupon(adminClient, 'FREE_SHIPPING');
await shopClient.query(APPLY_COUPON_CODE, { couponCode: 'DISCOUNT_ORDER' });
await shopClient.query(APPLY_COUPON_CODE, { couponCode: 'FREE_SHIPPING' });
// Create payment intent
const { createMolliePaymentIntent: intent } = await shopClient.query(
CREATE_MOLLIE_PAYMENT_INTENT,
{
input: {
paymentMethodCode: mockData.methodCode,
redirectUrl: 'https://my-storefront.io/order-confirmation',
},
},
);
const { orderByCode } = await shopClient.query(GET_ORDER_BY_CODE, { code: addItemToOrder.code });
expect(intent.url).toBe('https://my-storefront.io/order-confirmation');
expect(orderByCode.totalWithTax).toBe(0);
expect(orderByCode.state).toBe('PaymentSettled');
});
});

describe('Handle standard payment methods', () => {
Expand Down Expand Up @@ -486,6 +522,7 @@ describe('Mollie payments', () => {
body: JSON.stringify({ id: mockData.mollieOrderResponse.id }),
headers: { 'Content-Type': 'application/json' },
});
await shopClient.asUserWithCredentials(customers[0].emailAddress, 'test');
const { orderByCode } = await shopClient.query<GetOrderByCodeQuery, GetOrderByCodeQueryVariables>(
GET_ORDER_BY_CODE,
{
Expand Down
Loading

0 comments on commit b54c210

Please sign in to comment.