@commercetools/checkout-payments-processor-sdk 0.0.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (105) hide show
  1. package/CHANGELOG.md +15 -0
  2. package/README.md +42 -0
  3. package/biome.json +38 -0
  4. package/package.json +48 -0
  5. package/src/api/context/request-context.helper.test.ts +98 -0
  6. package/src/api/context/request-context.helper.ts +89 -0
  7. package/src/api/context/request-context.provider.ts +27 -0
  8. package/src/api/context/types/request-context.type.ts +18 -0
  9. package/src/api/handlers/payment-components.handler.test.ts +378 -0
  10. package/src/api/handlers/payment-components.handler.ts +80 -0
  11. package/src/api/handlers/payment-intents.handler.test.ts +475 -0
  12. package/src/api/handlers/payment-intents.handler.ts +169 -0
  13. package/src/api/handlers/status.handler.test.ts +551 -0
  14. package/src/api/handlers/status.handler.ts +216 -0
  15. package/src/api/handlers/transaction.handler.ts +86 -0
  16. package/src/api/handlers/types/handler.type.ts +49 -0
  17. package/src/api/hooks/authorize.hook.test.ts +62 -0
  18. package/src/api/hooks/authorize.hook.ts +51 -0
  19. package/src/api/hooks/jwt-auth.hook.test.ts +54 -0
  20. package/src/api/hooks/jwt-auth.hook.ts +56 -0
  21. package/src/api/hooks/oauth2-auth.hook.test.ts +173 -0
  22. package/src/api/hooks/oauth2-auth.hook.ts +46 -0
  23. package/src/api/hooks/session-header-auth.hook.ts +47 -0
  24. package/src/api/hooks/session-query-param-auth.hook.ts +46 -0
  25. package/src/api/hooks/types/hook.type.ts +12 -0
  26. package/src/api/index.ts +11 -0
  27. package/src/api/types.ts +3 -0
  28. package/src/commercetools/api/base-api.ts +28 -0
  29. package/src/commercetools/api/cart-api.test.ts +95 -0
  30. package/src/commercetools/api/cart-api.ts +55 -0
  31. package/src/commercetools/api/custom-type-api.ts +39 -0
  32. package/src/commercetools/api/order-api.ts +22 -0
  33. package/src/commercetools/api/payment-api.ts +64 -0
  34. package/src/commercetools/api/payment-method-api.ts +118 -0
  35. package/src/commercetools/api/root-api.ts +109 -0
  36. package/src/commercetools/errors/ct-api.error.ts +27 -0
  37. package/src/commercetools/helpers/currency.converter.test.ts +121 -0
  38. package/src/commercetools/helpers/currency.converter.test_data.json +2379 -0
  39. package/src/commercetools/helpers/currency.converter.ts +102 -0
  40. package/src/commercetools/helpers/taxrate.converter.test.ts +48 -0
  41. package/src/commercetools/helpers/taxrate.converter.ts +39 -0
  42. package/src/commercetools/index.ts +22 -0
  43. package/src/commercetools/services/ct-cart.service.test.ts +1616 -0
  44. package/src/commercetools/services/ct-cart.service.ts +316 -0
  45. package/src/commercetools/services/ct-custom-type.service.ts +62 -0
  46. package/src/commercetools/services/ct-order.service.test.ts +136 -0
  47. package/src/commercetools/services/ct-order.service.ts +47 -0
  48. package/src/commercetools/services/ct-payment-method.service.test.ts +878 -0
  49. package/src/commercetools/services/ct-payment-method.service.ts +223 -0
  50. package/src/commercetools/services/ct-payment.service.test.ts +1123 -0
  51. package/src/commercetools/services/ct-payment.service.ts +574 -0
  52. package/src/commercetools/types/api.type.ts +162 -0
  53. package/src/commercetools/types/cart.type.ts +83 -0
  54. package/src/commercetools/types/custom-type.type.ts +21 -0
  55. package/src/commercetools/types/order.type.ts +19 -0
  56. package/src/commercetools/types/payment-method.type.ts +130 -0
  57. package/src/commercetools/types/payment.type.ts +74 -0
  58. package/src/commercetools/types/predefined-custom-types.type.ts +240 -0
  59. package/src/commercetools/types.ts +7 -0
  60. package/src/errorx/errorx.ts +625 -0
  61. package/src/errorx/index.ts +1 -0
  62. package/src/errorx/types.ts +5 -0
  63. package/src/fetch/decorators/base.decorator.ts +13 -0
  64. package/src/fetch/decorators/monitoring.decorator.ts +41 -0
  65. package/src/fetch/fetch.test.ts +57 -0
  66. package/src/fetch/index.ts +3 -0
  67. package/src/fetch/types/fetch.type.ts +11 -0
  68. package/src/fetch/types.ts +1 -0
  69. package/src/index.ts +15 -0
  70. package/src/logger/commercetools-logger.ts +69 -0
  71. package/src/logger/index.ts +1 -0
  72. package/src/logger/types/logger.type.ts +6 -0
  73. package/src/logger/types.ts +1 -0
  74. package/src/mocks/auth.mock.ts +6 -0
  75. package/src/mocks/cart.mock.ts +239 -0
  76. package/src/mocks/ct-api-error.mock.ts +23 -0
  77. package/src/mocks/index.ts +4 -0
  78. package/src/mocks/payment.mock.ts +35 -0
  79. package/src/payment-processor.ts +317 -0
  80. package/src/security/authn/authns.ts +219 -0
  81. package/src/security/authn/bearer-utils.test.ts +35 -0
  82. package/src/security/authn/bearer-utils.ts +28 -0
  83. package/src/security/authn/jwt-authn-manager.ts +69 -0
  84. package/src/security/authn/oauth2-authn-manager.ts +105 -0
  85. package/src/security/authn/session-header-authn-manager.ts +58 -0
  86. package/src/security/authn/session-query-param-authn-manager.ts +53 -0
  87. package/src/security/authn/types/authn.type.ts +50 -0
  88. package/src/security/authz/authorization-manager.ts +39 -0
  89. package/src/security/authz/types/authz.type.ts +13 -0
  90. package/src/security/index.ts +13 -0
  91. package/src/security/services/authorization.service.ts +54 -0
  92. package/src/security/services/jwt.service.test.ts +27 -0
  93. package/src/security/services/jwt.service.ts +45 -0
  94. package/src/security/services/oauth2.service.ts +60 -0
  95. package/src/security/services/session.service.ts +141 -0
  96. package/src/security/services/types/authorization.type.ts +10 -0
  97. package/src/security/services/types/jwt.type.ts +3 -0
  98. package/src/security/services/types/oauth2.type.ts +15 -0
  99. package/src/security/services/types/session.type.ts +38 -0
  100. package/src/security/types.ts +6 -0
  101. package/tsconfig.json +28 -0
  102. package/tsconfig.prod.json +9 -0
  103. package/typedoc.json +6 -0
  104. package/vitest.config.ts +15 -0
  105. package/wiki/getting-started.md +13 -0
@@ -0,0 +1,118 @@
1
+ import type {
2
+ PaymentMethod,
3
+ PaymentMethodDraft,
4
+ PaymentMethodPagedQueryResponse,
5
+ } from '@commercetools/platform-sdk';
6
+ import { CommercetoolsBaseAPI } from '@/commercetools/api/base-api.js';
7
+ import { CommercetoolsAPIError } from '@/commercetools/errors/ct-api.error.js';
8
+ import type {
9
+ APIOpts,
10
+ CheckIfExistsByPredicate,
11
+ DeletePaymentMethod,
12
+ FindPaymentMethods,
13
+ GetPaymentMethod,
14
+ PaymentMethodAPI,
15
+ UpdatePaymentMethod,
16
+ } from '@/commercetools/types/api.type.js';
17
+
18
+ export class CommercetoolsPaymentMethodAPI
19
+ extends CommercetoolsBaseAPI
20
+ implements PaymentMethodAPI
21
+ {
22
+ constructor(opts: APIOpts) {
23
+ super(opts);
24
+ Object.setPrototypeOf(this, CommercetoolsPaymentMethodAPI.prototype);
25
+ }
26
+
27
+ get(opts: GetPaymentMethod): Promise<PaymentMethod> {
28
+ return this.executeCall(
29
+ this.client.paymentMethods().withId({ ID: opts.id }).get().execute(),
30
+ );
31
+ }
32
+
33
+ async checkIfExistsByPredicate(
34
+ opts: CheckIfExistsByPredicate,
35
+ ): Promise<boolean> {
36
+ try {
37
+ const result = await this.executeCall(
38
+ this.client
39
+ .paymentMethods()
40
+ .get({
41
+ queryArgs: {
42
+ where: opts.queryString,
43
+ },
44
+ })
45
+ .execute(),
46
+ );
47
+
48
+ if (result.total === 0) {
49
+ return false;
50
+ }
51
+
52
+ return true;
53
+ } catch (error) {
54
+ // The HEAD call returns a 404 if the paymentMethod does not exist
55
+ if (
56
+ error instanceof CommercetoolsAPIError &&
57
+ error.httpErrorStatus === 404
58
+ ) {
59
+ return false;
60
+ } else {
61
+ throw error;
62
+ }
63
+ }
64
+ }
65
+
66
+ find(opts: FindPaymentMethods): Promise<PaymentMethodPagedQueryResponse> {
67
+ return this.executeCall(
68
+ this.client
69
+ .paymentMethods()
70
+ .get({
71
+ queryArgs: {
72
+ where: opts.queryString,
73
+ },
74
+ })
75
+ .execute(),
76
+ );
77
+ }
78
+
79
+ create(draft: PaymentMethodDraft): Promise<PaymentMethod> {
80
+ return this.executeCall(
81
+ this.client
82
+ .paymentMethods()
83
+ .post({
84
+ body: draft,
85
+ })
86
+ .execute(),
87
+ );
88
+ }
89
+
90
+ update(opts: UpdatePaymentMethod): Promise<PaymentMethod> {
91
+ return this.executeCall(
92
+ this.client
93
+ .paymentMethods()
94
+ .withId({ ID: opts.resource.id })
95
+ .post({
96
+ body: {
97
+ version: opts.resource.version,
98
+ actions: opts.actions,
99
+ },
100
+ })
101
+ .execute(),
102
+ );
103
+ }
104
+
105
+ delete(opts: DeletePaymentMethod): Promise<PaymentMethod> {
106
+ return this.executeCall(
107
+ this.client
108
+ .paymentMethods()
109
+ .withId({ ID: opts.id })
110
+ .delete({
111
+ queryArgs: {
112
+ version: opts.version,
113
+ },
114
+ })
115
+ .execute(),
116
+ );
117
+ }
118
+ }
@@ -0,0 +1,109 @@
1
+ import { randomUUID } from 'node:crypto';
2
+ import { createApiBuilderFromCtpClient } from '@commercetools/platform-sdk';
3
+ import {
4
+ type AuthMiddlewareOptions,
5
+ ClientBuilder,
6
+ type CorrelationIdMiddlewareOptions,
7
+ type HttpMiddlewareOptions,
8
+ } from '@commercetools/ts-client';
9
+ import type { Logger } from '@logger-types';
10
+ import type {
11
+ ContextProvider,
12
+ RequestContextData,
13
+ } from '@/api/context/types/request-context.type.js';
14
+ import { CommercetoolsCartAPI } from '@/commercetools/api/cart-api.js';
15
+ import { CommercetoolsOrderAPI } from '@/commercetools/api/order-api.js';
16
+ import { CommercetoolsPaymentAPI } from '@/commercetools/api/payment-api.js';
17
+ import { CommercetoolsPaymentMethodAPI } from '@/commercetools/api/payment-method-api.js';
18
+ import type {
19
+ CartAPI,
20
+ CommercetoolsAPI,
21
+ CommercetoolsClient,
22
+ CustomTypeAPI,
23
+ OrderAPI,
24
+ PaymentAPI,
25
+ PaymentMethodAPI,
26
+ } from '@/commercetools/types/api.type.js';
27
+ import { CommercetoolsCustomTypeAPI } from './custom-type-api.js';
28
+
29
+ export class DefaultCommercetoolsAPI implements CommercetoolsAPI {
30
+ public client: CommercetoolsClient;
31
+ public cart: CartAPI;
32
+ public payment: PaymentAPI;
33
+ public order: OrderAPI;
34
+ public paymentMethod: PaymentMethodAPI;
35
+ public customType: CustomTypeAPI;
36
+ private logger: Logger;
37
+
38
+ constructor(opts: {
39
+ clientId: string;
40
+ clientSecret: string;
41
+ authUrl: string;
42
+ apiUrl: string;
43
+ projectKey: string;
44
+ contextProvider: ContextProvider<RequestContextData>;
45
+ logger: Logger;
46
+ // biome-ignore lint/complexity/noBannedTypes: Accept any function
47
+ httpClient?: Function;
48
+ }) {
49
+ this.client = createClient(opts);
50
+ this.cart = new CommercetoolsCartAPI({ client: this.client });
51
+ this.payment = new CommercetoolsPaymentAPI({ client: this.client });
52
+ this.order = new CommercetoolsOrderAPI({ client: this.client });
53
+ this.paymentMethod = new CommercetoolsPaymentMethodAPI({
54
+ client: this.client,
55
+ });
56
+ this.customType = new CommercetoolsCustomTypeAPI({ client: this.client });
57
+ this.logger = opts.logger;
58
+ }
59
+ }
60
+
61
+ const createClient = (opts: {
62
+ clientId: string;
63
+ clientSecret: string;
64
+ authUrl: string;
65
+ apiUrl: string;
66
+ projectKey: string;
67
+ contextProvider: ContextProvider<RequestContextData>;
68
+ // biome-ignore lint/complexity/noBannedTypes: Accept any function
69
+ httpClient?: Function;
70
+ }): CommercetoolsClient => {
71
+ const authMiddlewareOptions: AuthMiddlewareOptions = {
72
+ host: opts.authUrl,
73
+ projectKey: opts.projectKey,
74
+ credentials: {
75
+ clientId: opts.clientId,
76
+ clientSecret: opts.clientSecret,
77
+ },
78
+ ...(opts.httpClient ? { httpClient: opts.httpClient } : {}),
79
+ };
80
+
81
+ const httpMiddlewareOptions: HttpMiddlewareOptions = {
82
+ host: opts.apiUrl,
83
+ //Enables SDK retries when CoCo returns a 503 error. It retries up to 10 times with an 200ms backoff.
84
+ enableRetry: true,
85
+ ...(opts.httpClient ? { httpClient: opts.httpClient } : {}),
86
+ maskSensitiveHeaderData: true,
87
+ };
88
+
89
+ const correlationIdMiddlewareOptions: CorrelationIdMiddlewareOptions = {
90
+ generate: () => {
91
+ const contextData = opts.contextProvider.getContextData();
92
+ const correlationID =
93
+ contextData.correlationId && contextData.correlationId.length > 0
94
+ ? contextData.correlationId
95
+ : randomUUID();
96
+ return correlationID;
97
+ },
98
+ };
99
+
100
+ const ctpClient = new ClientBuilder()
101
+ .withClientCredentialsFlow(authMiddlewareOptions)
102
+ .withCorrelationIdMiddleware(correlationIdMiddlewareOptions)
103
+ .withHttpMiddleware(httpMiddlewareOptions)
104
+ .build();
105
+
106
+ return createApiBuilderFromCtpClient(ctpClient).withProjectKey({
107
+ projectKey: opts.projectKey,
108
+ });
109
+ };
@@ -0,0 +1,27 @@
1
+ import { Errorx } from '@errorx';
2
+
3
+ export type CocoErrorType = {
4
+ body?: {
5
+ message?: string;
6
+ errors?: {
7
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
8
+ [key: string]: unknown;
9
+ }[];
10
+ };
11
+ statusCode: number;
12
+ message?: string;
13
+ };
14
+
15
+ export class CommercetoolsAPIError extends Errorx {
16
+ constructor(err: CocoErrorType) {
17
+ super({
18
+ code: (err.body?.errors?.[0]?.code as string) ?? 'CommercetoolsAPIError',
19
+ message: err?.body?.message ?? err?.message ?? '',
20
+ httpErrorStatus: err.statusCode,
21
+ //TODO: make sure this type is handled better. Remove the `as unknown as Error`
22
+ cause: err as unknown as Error,
23
+ fields: err.body?.errors,
24
+ });
25
+ this.name = 'CommercetoolsAPIError';
26
+ }
27
+ }
@@ -0,0 +1,121 @@
1
+ import {
2
+ type ConvertWithMappingOptions,
3
+ convert,
4
+ convertWithMapping,
5
+ } from '@/commercetools/helpers/currency.converter.js';
6
+ import CurrencyConverterTestData from '@/commercetools/helpers/currency.converter.test_data.json' with {
7
+ type: 'json',
8
+ };
9
+
10
+ describe('currency.converter.ts', () => {
11
+ describe('convert', () => {
12
+ test('should pass all types of conversions', () => {
13
+ const failedTests: Record<string, unknown>[] = [];
14
+
15
+ for (const testInput of CurrencyConverterTestData) {
16
+ const got = convert(testInput.inputvalue, testInput.fractionDigits);
17
+
18
+ const areEqual = got === testInput.expectedValue;
19
+ if (!areEqual) {
20
+ failedTests.push({ ...testInput, got });
21
+ }
22
+ }
23
+
24
+ expect(failedTests).toStrictEqual([]);
25
+ });
26
+
27
+ test('should throw an error if the given fractionDigit is not a integer', () => {
28
+ const input = 10.99;
29
+
30
+ expect(() => convert(100, input)).toThrow(
31
+ `The given fraction digit of "${input}" is not a integer. Fraction digit must be an integer value.`,
32
+ );
33
+ });
34
+
35
+ test('should throw an error if the given amount is not a safe integer', () => {
36
+ const input = Number.MAX_SAFE_INTEGER + 1;
37
+
38
+ expect(() => convert(input, 0)).toThrow(
39
+ `The given value of ${input} is not a safe integer number`,
40
+ );
41
+ });
42
+ });
43
+
44
+ describe('convertWithMapping', () => {
45
+ test('it should use return the original value if no mapping matches and no fractionDigits are given', () => {
46
+ const input: ConvertWithMappingOptions = {
47
+ amount: 100,
48
+ currencyCode: 'EUR',
49
+ mapping: new Map<string, number>(),
50
+ };
51
+
52
+ const result = convertWithMapping(input);
53
+
54
+ expect(result).toEqual(100);
55
+ });
56
+
57
+ test('it should use apply the overruling fractionDigit from the map when the currencyCode matches with the one in the mapping', () => {
58
+ const input: ConvertWithMappingOptions = {
59
+ amount: 100,
60
+ currencyCode: 'EUR',
61
+ mapping: new Map<string, number>([['EUR', 4]]),
62
+ };
63
+
64
+ const result = convertWithMapping(input);
65
+
66
+ expect(result).toEqual(1000000);
67
+ });
68
+
69
+ test('it should use apply the overruling fractionDigit from the map even if the fractionDigit is provided', () => {
70
+ const input: ConvertWithMappingOptions = {
71
+ amount: 100,
72
+ currencyCode: 'EUR',
73
+ mapping: new Map<string, number>([['EUR', 4]]),
74
+ fractionDigit: 2,
75
+ };
76
+
77
+ const result = convertWithMapping(input);
78
+
79
+ expect(result).toEqual(1000000);
80
+ });
81
+
82
+ test('it should apply the given fractionDigit if no mapping could be found', () => {
83
+ const input: ConvertWithMappingOptions = {
84
+ amount: 100,
85
+ currencyCode: 'USD',
86
+ mapping: new Map<string, number>([['EUR', 4]]),
87
+ fractionDigit: 2,
88
+ };
89
+
90
+ const result = convertWithMapping(input);
91
+
92
+ expect(result).toEqual(10000);
93
+ });
94
+
95
+ test('it should throw an error if the given fractionDigit is not a integer', () => {
96
+ const input: ConvertWithMappingOptions = {
97
+ amount: 100,
98
+ currencyCode: 'USD',
99
+ mapping: new Map<string, number>([['EUR', 4]]),
100
+ fractionDigit: 2.288,
101
+ };
102
+
103
+ expect(() => convertWithMapping(input)).toThrow(
104
+ `The given fraction digit of "${input.fractionDigit}" is not a integer. Fraction digit must be an integer value.`,
105
+ );
106
+ });
107
+
108
+ test('it should throw an error if the fractionDigit from the mapping is not a integer', () => {
109
+ const input: ConvertWithMappingOptions = {
110
+ amount: 100,
111
+ currencyCode: 'EUR',
112
+ mapping: new Map<string, number>([['EUR', 4.123]]),
113
+ fractionDigit: 2,
114
+ };
115
+
116
+ expect(() => convertWithMapping(input)).toThrow(
117
+ `The given fraction digit of "4.123" is not a integer. Fraction digit must be an integer value.`,
118
+ );
119
+ });
120
+ });
121
+ });