Skip to content

Commit

Permalink
Merge pull request #61 from vuestorefront/feat-#56/payment-provider
Browse files Browse the repository at this point in the history
feat: #56/payment provider
  • Loading branch information
Baroshem committed Aug 25, 2021
2 parents 59ccdf3 + 11df77a commit 5e620ff
Show file tree
Hide file tree
Showing 32 changed files with 910 additions and 32 deletions.
26 changes: 26 additions & 0 deletions packages/api-client/__tests__/api/getPaymentMethods.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import getPaymentMethods from '../../src/api/getPaymentMethods';
import eligiblePaymentMethodsQuery from '../../src/api/getPaymentMethods/eligiblePaymentMethodsQuery';
import { Context } from '../../src/types';

describe('[vendure-api-client] getPaymentMethods', () => {
it('returns shipping methods', async () => {
const givenVariables = {};

const context = {
config: {},
client: {
query: ({ variables, query }) => {
expect(variables).toEqual(givenVariables);
expect(query).toEqual(eligiblePaymentMethodsQuery);

return { data: 'get payment methods response' };
}
},
extendQuery: (customQuery, args) => args
} as unknown as Context;

const { data } = await getPaymentMethods(context);

expect(data).toBe('get payment methods response');
});
});
26 changes: 26 additions & 0 deletions packages/api-client/__tests__/api/setCustomerForOrder.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import setCustomerForOrder from '../../src/api/setCustomerForOrder';
import setCustomerForOrderMutation from '../../src/api/setCustomerForOrder/setCustomerForOrderMutation';
import { Context } from '../../src/types';

describe('[vendure-api-client] setCustomerForOrder', () => {
it('sets customer for certain order', async () => {
const givenVariables = { firstName: 'test', lastName: 'test', emailAddress: 'test@test.com' };

const context = {
config: {},
client: {
mutate: ({ variables, mutation }) => {
expect(variables).toEqual({ input: givenVariables });
expect(mutation).toEqual(setCustomerForOrderMutation);

return { data: 'set customer for order response' };
}
},
extendQuery: (customQuery, args) => args
} as unknown as Context;

const { data } = await setCustomerForOrder(context, givenVariables);

expect(data).toBe('set customer for order response');
});
});
28 changes: 28 additions & 0 deletions packages/api-client/__tests__/api/setPaymentMethod.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import setPaymentMethod from '../../src/api/setPaymentMethod';
import addPaymentToOrderMutation from '../../src/api/setPaymentMethod/addPaymentToOrderMutation';
import { Context } from '../../src/types';

describe('[vendure-api-client] setPaymentMethod', () => {
it('sets payment method for certain order', async () => {
const givenVariables = { metadata: {}, method: 'test' };

const context = {
config: {},
client: {
mutate: ({ variables, mutation }) => {
expect(variables).toEqual({ input: givenVariables });
expect(mutation).toEqual(addPaymentToOrderMutation);

return { data: 'set payment method response' };
}
},
extendQuery: (customQuery, args) => args
} as unknown as Context;

const { data } = await setPaymentMethod(context, { method: 'test' });

const expectedSetPaymentResponse = 'set payment method response';

expect(data).toBe(expectedSetPaymentResponse);
});
});
26 changes: 26 additions & 0 deletions packages/api-client/__tests__/api/transitionOrderToState.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import transitionOrderToState from '../../src/api/transitionOrderToState';
import transitionOrderToStateMutation from '../../src/api/transitionOrderToState/transitionOrderToStateMutation';
import { Context } from '../../src/types';

describe('[vendure-api-client] transitionOrderToState', () => {
it('sets payment method for certain order', async () => {
const givenVariables = { state: 'test' };

const context = {
config: {},
client: {
mutate: ({ variables, mutation }) => {
expect(variables).toEqual(givenVariables);
expect(mutation).toEqual(transitionOrderToStateMutation);

return { data: 'transition order to state response' };
}
},
extendQuery: (customQuery, args) => args
} as unknown as Context;

const { data } = await transitionOrderToState(context, { state: 'test' });

expect(data).toBe('transition order to state response');
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import gql from 'graphql-tag';

export default gql`
query eligiblePaymentMethods {
eligiblePaymentMethods {
id
code
name
description
isEligible
eligibilityMessage
}
}
`;
23 changes: 23 additions & 0 deletions packages/api-client/src/api/getPaymentMethods/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import gql from 'graphql-tag';
import eligiblePaymentMethodsQuery from './eligiblePaymentMethodsQuery';
import { CustomQuery } from '@vue-storefront/core';
import { Context, RequestDataStructure, PaymentMethodQuote, GetPaymentMethodsResponse } from '../../types';
import { NO_CACHE_FETCH_POLICY } from '../../helpers';

const getPaymentMethods = async (context: Context, customQuery?: CustomQuery): Promise<GetPaymentMethodsResponse> => {
const getPaymentMethodsVariables = {};

const { eligiblePaymentMethods } = context.extendQuery(
customQuery, { eligiblePaymentMethods: { query: eligiblePaymentMethodsQuery, variables: getPaymentMethodsVariables } }
);

const request = await context.client.query<RequestDataStructure<'eligiblePaymentMethods', PaymentMethodQuote[]>>({
query: gql`${eligiblePaymentMethods.query}`,
variables: eligiblePaymentMethods.variables,
fetchPolicy: NO_CACHE_FETCH_POLICY
});
return request;

};

export default getPaymentMethods;
4 changes: 4 additions & 0 deletions packages/api-client/src/api/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,4 +10,8 @@ export { default as removeCartCoupon } from './removeCartCoupon';
export { default as getMe } from './getMe';
export { default as updateAddressDetails } from './updateAddressDetails';
export { default as getShippingMethods } from './getShippingMethods';
export { default as getPaymentMethods } from './getPaymentMethods';
export { default as setShippingMethod } from './setShippingMethod';
export { default as setPaymentMethod } from './setPaymentMethod';
export { default as transitionOrderToState } from './transitionOrderToState';
export { default as setCustomerForOrder } from './setCustomerForOrder';
25 changes: 25 additions & 0 deletions packages/api-client/src/api/setCustomerForOrder/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import setCustomerForOrderMutation from './setCustomerForOrderMutation';
import { CustomQuery } from '@vue-storefront/core';
import gql from 'graphql-tag';
import { Context, CreateCustomerInput, SetCustomerForOrderResponse } from '../../types';
import { NO_CACHE_FETCH_POLICY } from '../../helpers';

const setCustomerForOrder = async (context: Context, params: CreateCustomerInput, customQuery?: CustomQuery): Promise<SetCustomerForOrderResponse> => {
const setCustomerForOrderVariables = {
input: params
};

const { setCustomerForOrder } = context.extendQuery(
customQuery, { setCustomerForOrder: { query: setCustomerForOrderMutation, variables: setCustomerForOrderVariables } }
);

const request = await context.client.mutate({
mutation: gql`${setCustomerForOrder.query}`,
variables: setCustomerForOrder.variables,
fetchPolicy: NO_CACHE_FETCH_POLICY
}) as SetCustomerForOrderResponse;

return request;
};

export default setCustomerForOrder;
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import gql from 'graphql-tag';
import { CartFragment, ErrorResultFragment } from '../../fragments';

export default gql`
${CartFragment}
${ErrorResultFragment}
mutation setCustomerForOrder($input: CreateCustomerInput!) {
setCustomerForOrder(input: $input) {
...Cart
...ErrorResult
}
}
`;
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import gql from 'graphql-tag';
import { CartFragment, ErrorResultFragment } from '../../fragments';

export default gql`
${CartFragment}
${ErrorResultFragment}
mutation addPaymentToOrder($input: PaymentInput!) {
addPaymentToOrder(input: $input) {
...Cart
...ErrorResult
}
}
`;
30 changes: 30 additions & 0 deletions packages/api-client/src/api/setPaymentMethod/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import addPaymentToOrderMutation from './addPaymentToOrderMutation';
import { CustomQuery } from '@vue-storefront/core';
import gql from 'graphql-tag';
import { AddPaymentToOrderParams, Context, PaymentInput, SetShippingMethodResponse } from '../../types';
import { NO_CACHE_FETCH_POLICY } from '../../helpers';

const setPaymentMethod = async (context: Context, params: AddPaymentToOrderParams, customQuery?: CustomQuery): Promise<SetShippingMethodResponse> => {
const setPaymentMethodVariables = {
input: {
method: params.method,
metadata: {
// Here you would pass data from an external Payment Provided after successful payment process like payment id.
}
} as PaymentInput
};

const { addPaymentToOrder } = context.extendQuery(
customQuery, { addPaymentToOrder: { query: addPaymentToOrderMutation, variables: setPaymentMethodVariables } }
);

const request = await context.client.mutate({
mutation: gql`${addPaymentToOrder.query}`,
variables: addPaymentToOrder.variables,
fetchPolicy: NO_CACHE_FETCH_POLICY
}) as SetShippingMethodResponse;

return request;
};

export default setPaymentMethod;
25 changes: 25 additions & 0 deletions packages/api-client/src/api/transitionOrderToState/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import transitionOrderToStateMutation from './transitionOrderToStateMutation';
import { CustomQuery } from '@vue-storefront/core';
import gql from 'graphql-tag';
import { Context, TransitionOrderToState, TransitionOrderToStateParams } from '../../types';
import { NO_CACHE_FETCH_POLICY } from '../../helpers';

const transitionOrderToState = async (context: Context, params: TransitionOrderToStateParams, customQuery?: CustomQuery): Promise<TransitionOrderToState> => {
const transitionOrderToStateVariables = {
...params
};

const { transitionOrderToState } = context.extendQuery(
customQuery, { transitionOrderToState: { query: transitionOrderToStateMutation, variables: transitionOrderToStateVariables } }
);

const request = await context.client.mutate({
mutation: gql`${transitionOrderToState.query}`,
variables: transitionOrderToState.variables,
fetchPolicy: NO_CACHE_FETCH_POLICY
}) as TransitionOrderToState;

return request;
};

export default transitionOrderToState;
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import gql from 'graphql-tag';
import { CartFragment, ErrorResultFragment } from '../../fragments';

export default gql`
${CartFragment}
${ErrorResultFragment}
mutation transitionOrderToState($state: String!) {
transitionOrderToState(state: $state) {
...Cart
...ErrorResult
}
}
`;
12 changes: 9 additions & 3 deletions packages/api-client/src/api/updateAddressDetails/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,16 @@ import setOrderBillingAddressMutation from './setOrderBillingAddressMutation';
import setOrderShippingAddressMutation from './setOrderShippingAddressMutation';
import { CustomQuery } from '@vue-storefront/core';
import gql from 'graphql-tag';
import { Context, UpdateAddressDetailsParams, UpdateAddressDetailsResponse } from '../../types';
import { BILLING_TYPE, NO_CACHE_FETCH_POLICY } from '../../helpers/constants';
import { Context, Order, UpdateAddressDetailsParams, UpdateAddressDetailsResponse } from '../../types';
import { ARRANGING_PAYMENT_STATE, BILLING_TYPE, NO_CACHE_FETCH_POLICY, isCustomerDataFilled } from '../../helpers';
import transitionOrderToState from '../transitionOrderToState';

const updateAddressDetails = async (context: Context, params: UpdateAddressDetailsParams, customQuery?: CustomQuery): Promise<UpdateAddressDetailsResponse> => {
const { type, input } = params;
const updateAddressDetailsVariables = { input };
const isBilling = type === BILLING_TYPE;

const updateAddressDetailsQuery = type === BILLING_TYPE ? setOrderBillingAddressMutation : setOrderShippingAddressMutation;
const updateAddressDetailsQuery = isBilling ? setOrderBillingAddressMutation : setOrderShippingAddressMutation;

const { updateAddressDetails } = context.extendQuery(
customQuery, { updateAddressDetails: { query: updateAddressDetailsQuery, variables: updateAddressDetailsVariables } }
Expand All @@ -21,6 +23,10 @@ const updateAddressDetails = async (context: Context, params: UpdateAddressDetai
fetchPolicy: NO_CACHE_FETCH_POLICY
}) as UpdateAddressDetailsResponse;

if (isBilling && isCustomerDataFilled(request?.data?.setOrderBillingAddress as Order)) {
await transitionOrderToState(context, { state: ARRANGING_PAYMENT_STATE });
}

return request;
};

Expand Down
5 changes: 5 additions & 0 deletions packages/api-client/src/fragments/cart.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,11 @@ export const CartFragment = `
code
state
active
customer {
firstName
lastName
emailAddress
}
lines {
id
featuredAsset {
Expand Down
6 changes: 6 additions & 0 deletions packages/api-client/src/helpers/checkout.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import { Order } from '../types';

export const isCustomerDataFilled = (order: Order): boolean => {
if (!order) return;
return Boolean(order?.customer?.emailAddress && order?.billingAddress?.streetLine1 && order?.shippingAddress?.streetLine1);
};
1 change: 1 addition & 0 deletions packages/api-client/src/helpers/constants.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
export const VENDURE_AUTH_TOKEN_NAME = 'vendure-auth-token';
export const BILLING_TYPE = 'billing';
export const ARRANGING_PAYMENT_STATE = 'ArrangingPayment';
export const NO_CACHE_FETCH_POLICY = 'no-cache';
2 changes: 2 additions & 0 deletions packages/api-client/src/helpers/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
export * from './constants';
export * from './checkout';
12 changes: 10 additions & 2 deletions packages/api-client/src/types/API.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import { CustomQuery } from '@vue-storefront/core';
import { ApolloQueryResult } from 'apollo-client';
import { FetchResult } from 'apollo-link';
import { ActiveOrderResult, ApplyCouponCodeResult, CollectionList, Customer, Order, Product, RemoveOrderItemsResult, SearchResponse, ShippingMethodQuote, UpdateOrderItemsResult } from './GraphQL';
import { AddToCartParams, CartCouponParams, CollectionParams, ProductParams, RemoveFromCartParams, SearchParams, SetShippingMethodParams, UpdateAddressDetailsParams, UpdateCartParams } from './types';
import { ActiveOrderResult, ApplyCouponCodeResult, CollectionList, CreateCustomerInput, Customer, Order, PaymentMethodQuote, Product, RemoveOrderItemsResult, SearchResponse, SetCustomerForOrderResult, ShippingMethodQuote, UpdateOrderItemsResult } from './GraphQL';
import { AddPaymentToOrderParams, AddToCartParams, CartCouponParams, CollectionParams, ProductParams, RemoveFromCartParams, SearchParams, SetShippingMethodParams, TransitionOrderToStateParams, UpdateAddressDetailsParams, UpdateCartParams } from './types';

export type QueryResponse<K extends string, V> = ApolloQueryResult<Record<K, V>>;
export type MutationResponse<K extends string, V> = FetchResult<Record<K, V>>;
Expand All @@ -14,13 +14,17 @@ export type GetFacetResponse = QueryResponse<'search', SearchResponse>;
export type GetCartResponse = QueryResponse<'activeOrder', Order>;
export type GetMeResponse = QueryResponse<'activeCustomer', Customer>;
export type GetShippingMethodsResponse = QueryResponse<'eligibleShippingMethods', ShippingMethodQuote[]>;
export type GetPaymentMethodsResponse = QueryResponse<'eligiblePaymentMethods', PaymentMethodQuote[]>;
export type AddToCartResponse = MutationResponse<'addItemToOrder', UpdateOrderItemsResult>;
export type RemoveFromCartResponse = MutationResponse<'removeOrderLine', RemoveOrderItemsResult>;
export type UpdateCartQuantityResponse = MutationResponse<'adjustOrderLine', UpdateOrderItemsResult>;
export type ApplyCouponCodeResponse = MutationResponse<'applyCouponCode', ApplyCouponCodeResult>;
export type RemoveCouponCodeResponse = MutationResponse<'removeCouponCode', Order>;
export type UpdateAddressDetailsResponse = MutationResponse<'setOrderShippingAddress' | 'setOrderBillingAddress', ActiveOrderResult>;
export type SetShippingMethodResponse = MutationResponse<'setOrderShippingMethod', Order>;
export type SetPaymentMethodResponse = MutationResponse<'setPaymentShippingMethod', Order>;
export type TransitionOrderToState = MutationResponse<'transitionOrderToState', Order>;
export type SetCustomerForOrderResponse = MutationResponse<'setCustomerForOrder', SetCustomerForOrderResult>;

export interface VendureApiMethods {
getProduct(params: ProductParams, customQuery?: CustomQuery): Promise<GetProductResponse>;
Expand All @@ -29,11 +33,15 @@ export interface VendureApiMethods {
getCart(customQuery?: CustomQuery): Promise<GetCartResponse>;
getsMe(customQuery?: CustomQuery): Promise<GetMeResponse>;
getShippingMethods(customQuery?: CustomQuery): Promise<GetShippingMethodsResponse>;
getPaymentMethods(customQuery?: CustomQuery): Promise<GetPaymentMethodsResponse>;
addToCart(params: AddToCartParams, customQuery?: CustomQuery): Promise<AddToCartResponse>;
removeFromCart(params: RemoveFromCartParams, customQuery?: CustomQuery): Promise<RemoveFromCartResponse>;
updateCartQuantity(params: UpdateCartParams, customQuery?: CustomQuery): Promise<UpdateCartQuantityResponse>;
applyCouponCode(params: CartCouponParams, customQuery?: CustomQuery): Promise<ApplyCouponCodeResponse>;
removeCouponCode(params: CartCouponParams, customQuery?: CustomQuery): Promise<RemoveCouponCodeResponse>;
updateAddressDetails(params: UpdateAddressDetailsParams, customQuery?: CustomQuery): Promise<UpdateAddressDetailsResponse>;
setShippingMethod(params: SetShippingMethodParams, customQuery?: CustomQuery): Promise<SetShippingMethodResponse>;
setPaymentMethod(params: AddPaymentToOrderParams, customQuery?: CustomQuery): Promise<SetPaymentMethodResponse>;
transitionOrderToState(params: TransitionOrderToStateParams, customQuery?: CustomQuery): Promise<TransitionOrderToState>;
setCustomerForOrder(params: CreateCustomerInput, customQuery?: CustomQuery): Promise<SetCustomerForOrderResponse>;
}
Loading

0 comments on commit 5e620ff

Please sign in to comment.