@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,378 @@
1
+ import type { HandlerResponse } from '@api-types';
2
+ import type { Logger } from '@logger-types';
3
+ import {
4
+ PaymentComponentsHandler,
5
+ type PaymentComponentsIncomingHttpHeaders,
6
+ type PaymentComponentsOutgoingHttpHeaders,
7
+ type PaymentComponentsRequest,
8
+ type PaymentComponentsResponse,
9
+ } from '@/api/handlers/payment-components.handler.js';
10
+
11
+ // Concrete implementation for testing the abstract class
12
+ class TestPaymentComponentsHandler extends PaymentComponentsHandler {
13
+ public handlePaymentComponents = vi.fn();
14
+ }
15
+
16
+ describe('PaymentComponentsHandler', () => {
17
+ let handler: TestPaymentComponentsHandler;
18
+ let mockLogger: Logger;
19
+
20
+ const mockHeaders: PaymentComponentsIncomingHttpHeaders = {
21
+ authorization: 'Bearer test-token',
22
+ 'content-type': 'application/json',
23
+ accept: 'application/json',
24
+ 'x-request-id': '123',
25
+ 'x-correlation-id': '456',
26
+ };
27
+
28
+ const mockSuccessResponse: HandlerResponse<
29
+ PaymentComponentsResponse,
30
+ PaymentComponentsOutgoingHttpHeaders
31
+ > = {
32
+ status: 200,
33
+ body: {
34
+ dropins: [
35
+ {
36
+ type: 'embedded',
37
+ },
38
+ ],
39
+ components: [
40
+ {
41
+ type: 'card',
42
+ subtypes: ['visa', 'mastercard', 'amex'],
43
+ },
44
+ {
45
+ type: 'paypal',
46
+ },
47
+ ],
48
+ express: [],
49
+ },
50
+ };
51
+
52
+ beforeEach(() => {
53
+ mockLogger = {
54
+ error: vi.fn(),
55
+ info: vi.fn(),
56
+ debug: vi.fn(),
57
+ warn: vi.fn(),
58
+ } as unknown as Logger;
59
+
60
+ handler = new TestPaymentComponentsHandler({ logger: mockLogger });
61
+
62
+ // Set default success behavior
63
+ handler.handlePaymentComponents.mockResolvedValue(mockSuccessResponse);
64
+ });
65
+
66
+ afterEach(() => {
67
+ vi.clearAllMocks();
68
+ });
69
+
70
+ describe('Public methods', () => {
71
+ test('should return GET as HTTP method', () => {
72
+ expect(handler.method()).toBe('GET');
73
+ });
74
+
75
+ test('should return correct endpoint', () => {
76
+ expect(handler.endpoint()).toBe('/operations/payment-components');
77
+ });
78
+
79
+ test('should return correct auth configuration', () => {
80
+ const auth = handler.auth();
81
+ expect(auth).toEqual([
82
+ {
83
+ type: 'jwt',
84
+ },
85
+ ]);
86
+ });
87
+ });
88
+
89
+ describe('Handler method', () => {
90
+ describe('successful scenarios', () => {
91
+ test('should handle payment components request successfully with embedded dropin', async () => {
92
+ const request: PaymentComponentsRequest = undefined;
93
+
94
+ const result = await handler.handler({
95
+ request,
96
+ headers: mockHeaders,
97
+ });
98
+
99
+ expect(handler.handlePaymentComponents).toHaveBeenCalledWith({
100
+ headers: mockHeaders,
101
+ });
102
+ expect(result).toEqual(mockSuccessResponse);
103
+ expect(result.body.dropins).toHaveLength(1);
104
+ expect(result.body.dropins[0].type).toBe('embedded');
105
+ expect(result.body.components).toHaveLength(2);
106
+ });
107
+
108
+ test('should handle payment components request successfully with hpp dropin', async () => {
109
+ const request: PaymentComponentsRequest = undefined;
110
+ const hppResponse: HandlerResponse<
111
+ PaymentComponentsResponse,
112
+ PaymentComponentsOutgoingHttpHeaders
113
+ > = {
114
+ status: 200,
115
+ body: {
116
+ dropins: [
117
+ {
118
+ type: 'hpp',
119
+ },
120
+ ],
121
+ components: [],
122
+ express: [],
123
+ },
124
+ };
125
+
126
+ handler.handlePaymentComponents.mockResolvedValue(hppResponse);
127
+
128
+ const result = await handler.handler({
129
+ request,
130
+ headers: mockHeaders,
131
+ });
132
+
133
+ expect(handler.handlePaymentComponents).toHaveBeenCalledWith({
134
+ headers: mockHeaders,
135
+ });
136
+ expect(result.body.dropins[0].type).toBe('hpp');
137
+ });
138
+
139
+ test('should handle payment components request with multiple dropins', async () => {
140
+ const request: PaymentComponentsRequest = undefined;
141
+ const multipleDropinsResponse: HandlerResponse<
142
+ PaymentComponentsResponse,
143
+ PaymentComponentsOutgoingHttpHeaders
144
+ > = {
145
+ status: 200,
146
+ body: {
147
+ dropins: [
148
+ {
149
+ type: 'embedded',
150
+ },
151
+ {
152
+ type: 'hpp',
153
+ },
154
+ ],
155
+ components: [
156
+ {
157
+ type: 'card',
158
+ subtypes: ['visa', 'mastercard'],
159
+ },
160
+ ],
161
+ express: [],
162
+ },
163
+ };
164
+
165
+ handler.handlePaymentComponents.mockResolvedValue(
166
+ multipleDropinsResponse,
167
+ );
168
+
169
+ const result = await handler.handler({
170
+ request,
171
+ headers: mockHeaders,
172
+ });
173
+
174
+ expect(result.body.dropins).toHaveLength(2);
175
+ expect(result.body.dropins[0].type).toBe('embedded');
176
+ expect(result.body.dropins[1].type).toBe('hpp');
177
+ });
178
+
179
+ test('should handle payment components with components that have subtypes', async () => {
180
+ const request: PaymentComponentsRequest = undefined;
181
+
182
+ const result = await handler.handler({
183
+ request,
184
+ headers: mockHeaders,
185
+ });
186
+
187
+ expect(result.body.components[0].type).toBe('card');
188
+ expect(result.body.components[0].subtypes).toEqual([
189
+ 'visa',
190
+ 'mastercard',
191
+ 'amex',
192
+ ]);
193
+ });
194
+
195
+ test('should handle payment components with components without subtypes', async () => {
196
+ const request: PaymentComponentsRequest = undefined;
197
+ const noSubtypesResponse: HandlerResponse<
198
+ PaymentComponentsResponse,
199
+ PaymentComponentsOutgoingHttpHeaders
200
+ > = {
201
+ status: 200,
202
+ body: {
203
+ dropins: [],
204
+ components: [
205
+ {
206
+ type: 'paypal',
207
+ },
208
+ {
209
+ type: 'googlepay',
210
+ },
211
+ ],
212
+ express: [],
213
+ },
214
+ };
215
+
216
+ handler.handlePaymentComponents.mockResolvedValue(noSubtypesResponse);
217
+
218
+ const result = await handler.handler({
219
+ request,
220
+ headers: mockHeaders,
221
+ });
222
+
223
+ expect(result.body.components).toHaveLength(2);
224
+ expect(result.body.components[0].subtypes).toBeUndefined();
225
+ expect(result.body.components[1].subtypes).toBeUndefined();
226
+ });
227
+
228
+ test('should handle empty dropins and components arrays', async () => {
229
+ const request: PaymentComponentsRequest = undefined;
230
+ const emptyResponse: HandlerResponse<
231
+ PaymentComponentsResponse,
232
+ PaymentComponentsOutgoingHttpHeaders
233
+ > = {
234
+ status: 200,
235
+ body: {
236
+ dropins: [],
237
+ components: [],
238
+ express: [],
239
+ },
240
+ };
241
+
242
+ handler.handlePaymentComponents.mockResolvedValue(emptyResponse);
243
+
244
+ const result = await handler.handler({
245
+ request,
246
+ headers: mockHeaders,
247
+ });
248
+
249
+ expect(result.body.dropins).toHaveLength(0);
250
+ expect(result.body.components).toHaveLength(0);
251
+ });
252
+ });
253
+
254
+ describe('error scenarios', () => {
255
+ test('should handle errors thrown by handlePaymentComponents', async () => {
256
+ const request: PaymentComponentsRequest = undefined;
257
+ const error = new Error('Failed to fetch payment components');
258
+
259
+ handler.handlePaymentComponents.mockRejectedValue(error);
260
+
261
+ await expect(
262
+ handler.handler({
263
+ request,
264
+ headers: mockHeaders,
265
+ }),
266
+ ).rejects.toThrow('Failed to fetch payment components');
267
+
268
+ expect(handler.handlePaymentComponents).toHaveBeenCalledWith({
269
+ headers: mockHeaders,
270
+ });
271
+ });
272
+
273
+ test('should propagate custom error from handlePaymentComponents', async () => {
274
+ const request: PaymentComponentsRequest = undefined;
275
+ class CustomError extends Error {
276
+ constructor(
277
+ message: string,
278
+ public statusCode: number,
279
+ ) {
280
+ super(message);
281
+ }
282
+ }
283
+ const customError = new CustomError('Custom error', 503);
284
+
285
+ handler.handlePaymentComponents.mockRejectedValue(customError);
286
+
287
+ await expect(
288
+ handler.handler({
289
+ request,
290
+ headers: mockHeaders,
291
+ }),
292
+ ).rejects.toThrow(customError);
293
+ });
294
+ });
295
+
296
+ describe('headers handling', () => {
297
+ test('should pass headers correctly to handlePaymentComponents', async () => {
298
+ const request: PaymentComponentsRequest = undefined;
299
+ const customHeaders: PaymentComponentsIncomingHttpHeaders = {
300
+ authorization: 'Bearer custom-token',
301
+ 'content-type': 'application/json',
302
+ accept: 'application/json',
303
+ 'x-request-id': 'custom-request-id',
304
+ 'x-correlation-id': 'custom-correlation-id',
305
+ };
306
+
307
+ await handler.handler({
308
+ request,
309
+ headers: customHeaders,
310
+ });
311
+
312
+ expect(handler.handlePaymentComponents).toHaveBeenCalledWith({
313
+ headers: customHeaders,
314
+ });
315
+ });
316
+ });
317
+
318
+ describe('response structure validation', () => {
319
+ test('should return valid response structure with all required fields', async () => {
320
+ const request: PaymentComponentsRequest = undefined;
321
+
322
+ const result = await handler.handler({
323
+ request,
324
+ headers: mockHeaders,
325
+ });
326
+
327
+ expect(result).toHaveProperty('status');
328
+ expect(result).toHaveProperty('body');
329
+ expect(result.body).toHaveProperty('dropins');
330
+ expect(result.body).toHaveProperty('components');
331
+ expect(Array.isArray(result.body.dropins)).toBe(true);
332
+ expect(Array.isArray(result.body.components)).toBe(true);
333
+ });
334
+
335
+ test('should validate dropin type is either embedded or hpp', async () => {
336
+ const request: PaymentComponentsRequest = undefined;
337
+
338
+ const result = await handler.handler({
339
+ request,
340
+ headers: mockHeaders,
341
+ });
342
+
343
+ result.body.dropins.forEach((dropin) => {
344
+ expect(['embedded', 'hpp']).toContain(dropin.type);
345
+ });
346
+ });
347
+
348
+ test('should validate components have required type field', async () => {
349
+ const request: PaymentComponentsRequest = undefined;
350
+
351
+ const result = await handler.handler({
352
+ request,
353
+ headers: mockHeaders,
354
+ });
355
+
356
+ result.body.components.forEach((component) => {
357
+ expect(component).toHaveProperty('type');
358
+ expect(typeof component.type).toBe('string');
359
+ });
360
+ });
361
+
362
+ test('should validate subtypes is optional and array when present', async () => {
363
+ const request: PaymentComponentsRequest = undefined;
364
+
365
+ const result = await handler.handler({
366
+ request,
367
+ headers: mockHeaders,
368
+ });
369
+
370
+ result.body.components.forEach((component) => {
371
+ if (component.subtypes !== undefined) {
372
+ expect(Array.isArray(component.subtypes)).toBe(true);
373
+ }
374
+ });
375
+ });
376
+ });
377
+ });
378
+ });
@@ -0,0 +1,80 @@
1
+ import type {
2
+ AuthType,
3
+ BaseIncomingHttpHeaders,
4
+ BaseOutgoingHttpHeaders,
5
+ HandlerResponse,
6
+ RouteHandler,
7
+ } from '@api-types';
8
+ import type { PaymentMethodType } from '@commercetools/checkout-payments-core';
9
+ import type { Logger } from '@/logger/types.js';
10
+
11
+ export type PaymentComponentsRequest = undefined;
12
+
13
+ export type PaymentComponentsResponse = {
14
+ dropins: {
15
+ type: 'embedded' | 'hpp';
16
+ }[];
17
+ components: {
18
+ subtypes?: string[] | undefined;
19
+ type: PaymentMethodType;
20
+ }[];
21
+ express: {
22
+ type: string;
23
+ }[];
24
+ };
25
+
26
+ export type PaymentComponentsIncomingHttpHeaders = BaseIncomingHttpHeaders & {};
27
+
28
+ export type PaymentComponentsOutgoingHttpHeaders = BaseOutgoingHttpHeaders & {};
29
+
30
+ export abstract class PaymentComponentsHandler
31
+ implements
32
+ RouteHandler<
33
+ PaymentComponentsRequest,
34
+ PaymentComponentsResponse,
35
+ PaymentComponentsIncomingHttpHeaders,
36
+ PaymentComponentsOutgoingHttpHeaders
37
+ >
38
+ {
39
+ public readonly logger: Logger;
40
+ public constructor(opts: { logger: Logger }) {
41
+ this.logger = opts.logger;
42
+ }
43
+
44
+ public method() {
45
+ return 'GET';
46
+ }
47
+
48
+ public endpoint() {
49
+ return '/operations/payment-components';
50
+ }
51
+
52
+ public auth(): AuthType[] {
53
+ return [
54
+ {
55
+ type: 'jwt',
56
+ },
57
+ ];
58
+ }
59
+
60
+ public async handler(opts: {
61
+ request: PaymentComponentsRequest;
62
+ headers: PaymentComponentsIncomingHttpHeaders;
63
+ }): Promise<
64
+ HandlerResponse<
65
+ PaymentComponentsResponse,
66
+ PaymentComponentsOutgoingHttpHeaders
67
+ >
68
+ > {
69
+ return await this.handlePaymentComponents({ headers: opts.headers });
70
+ }
71
+
72
+ public abstract handlePaymentComponents(opts: {
73
+ headers: PaymentComponentsIncomingHttpHeaders;
74
+ }): Promise<
75
+ HandlerResponse<
76
+ PaymentComponentsResponse,
77
+ PaymentComponentsOutgoingHttpHeaders
78
+ >
79
+ >;
80
+ }