@commercetools/connect-payments-sdk 0.26.0 → 0.27.1

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.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,17 @@
1
1
  # @commercetools/connect-payments-sdk
2
2
 
3
+ ## 0.27.1
4
+
5
+ ### Patch Changes
6
+
7
+ - 7bfd391: Fix issue calling the recurring payment jobs API
8
+
9
+ ## 0.27.0
10
+
11
+ ### Minor Changes
12
+
13
+ - 9fe494b: feat(recurring-orders): added new recurring payment job service that allows connectors to create a recurring payment job instance in Checkout
14
+
3
15
  ## 0.26.0
4
16
 
5
17
  ### Minor Changes
@@ -5,6 +5,7 @@ export { AuthorizationService as CommercetoolsAuthorizationService } from './typ
5
5
  export { OrderService as CommercetoolsOrderService } from './types/order.type';
6
6
  export { PaymentMethodService as CommercetoolsPaymentMethodService } from './types/payment-method.type';
7
7
  export { CustomTypeService as CommercetoolsCustomTypeService } from './types/custom-type.type';
8
+ export { RecurringPaymentJobService as CommercetoolsRecurringPaymentJobService, RecurringPaymentJobDraft, } from './types/recurring-payment-job.type';
8
9
  export * as CommercetoolsPaymentMethodTypes from './types/payment-method.type';
9
10
  export { CommercetoolsClient } from './types/api.type';
10
11
  export { CustomFields, CustomFieldsDraft, Cart, Order, OrderPagedQueryResponse, Payment, PaymentDraft, PaymentMethodInfoDraft, Money, LineItem, CustomLineItem, Address, Transaction, TransactionType, TransactionState, ShippingInfo, PaymentMethod, PaymentMethodPagedQueryResponse, PaymentMethodToken, PaymentMethodStatus, Type, TypeDraft, TypeUpdateAction, ProductTypeDraft, TypeAddFieldDefinitionAction, TypeRemoveFieldDefinitionAction, CustomerSetCustomFieldAction, CustomerSetCustomTypeAction, CustomerUpdateAction, TypePagedQueryResponse, LocalizedString, Customer, } from '@commercetools/platform-sdk';
@@ -0,0 +1,63 @@
1
+ import { Logger } from '../..';
2
+ import { AuthorizationService } from '../types/authorization.type';
3
+ import { RecurringPaymentJob, RecurringPaymentJobDraft, RecurringPaymentJobService } from '../types/recurring-payment-job.type';
4
+ import { DefaultCartService } from './ct-cart.service';
5
+ /**
6
+ * Default implementation of the RecurringPaymentJobService interface.
7
+ */
8
+ export declare class DefaultRecurringPaymentJobService implements RecurringPaymentJobService {
9
+ private authorizationService;
10
+ private ctCartService;
11
+ private checkoutUrl;
12
+ private projectKey;
13
+ private logger;
14
+ private token;
15
+ constructor(opts: {
16
+ authorizationService: AuthorizationService;
17
+ ctCartService: DefaultCartService;
18
+ checkoutUrl: string;
19
+ projectKey: string;
20
+ logger: Logger;
21
+ });
22
+ /**
23
+ * Creates a recurring payment job only if applicable (i.e., when the cart is configured for recurring payments).
24
+ *
25
+ * This method abstracts the business logic of determining whether a recurring payment job should be created.
26
+ * The caller doesn't need to validate the cart - the method handles it internally.
27
+ *
28
+ * The method performs the following operations:
29
+ * 1. Retrieves the cart associated with the origin payment
30
+ * 2. Checks if the cart is configured for recurring payments
31
+ * 3. If yes, creates the recurring payment job via the checkout API
32
+ * 4. If no, returns null without creating anything
33
+ *
34
+ * @param draft - The draft object containing the origin payment and payment method references
35
+ * @returns The created recurring payment job if the cart supports recurring payments,
36
+ * or null if it doesn't or if an error occurs
37
+ *
38
+ * @example
39
+ * ```typescript
40
+ * // Caller doesn't need to check if cart is recurring - method handles it
41
+ * const job = await service.createRecurringPaymentJobIfApplicable({
42
+ * originPayment: { id: 'payment-123', typeId: 'payment' },
43
+ * paymentMethod: { id: 'method-456', typeId: 'payment-method' }
44
+ * });
45
+ *
46
+ * if (job) {
47
+ * // Job was created because cart is recurring
48
+ * } else {
49
+ * // Cart is not recurring or an error occurred
50
+ * }
51
+ * ```
52
+ */
53
+ createRecurringPaymentJobIfApplicable(draft: RecurringPaymentJobDraft): Promise<RecurringPaymentJob | null>;
54
+ /**
55
+ * Internal method that performs the HTTP request to create a recurring payment job.
56
+ */
57
+ private internalCreateRecurringPaymentJob;
58
+ /**
59
+ * Performs a fetch request with automatic token refresh on 401/403 errors.
60
+ */
61
+ private fetchWithTokenRetry;
62
+ private safeParseErrorResponse;
63
+ }
@@ -0,0 +1,135 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.DefaultRecurringPaymentJobService = void 0;
4
+ const errorx_1 = require("../../errorx/errorx");
5
+ /**
6
+ * Default implementation of the RecurringPaymentJobService interface.
7
+ */
8
+ class DefaultRecurringPaymentJobService {
9
+ authorizationService;
10
+ ctCartService;
11
+ checkoutUrl;
12
+ projectKey;
13
+ logger;
14
+ token;
15
+ constructor(opts) {
16
+ this.authorizationService = opts.authorizationService;
17
+ this.ctCartService = opts.ctCartService;
18
+ this.checkoutUrl = opts.checkoutUrl;
19
+ this.projectKey = opts.projectKey;
20
+ this.logger = opts.logger;
21
+ }
22
+ /**
23
+ * Creates a recurring payment job only if applicable (i.e., when the cart is configured for recurring payments).
24
+ *
25
+ * This method abstracts the business logic of determining whether a recurring payment job should be created.
26
+ * The caller doesn't need to validate the cart - the method handles it internally.
27
+ *
28
+ * The method performs the following operations:
29
+ * 1. Retrieves the cart associated with the origin payment
30
+ * 2. Checks if the cart is configured for recurring payments
31
+ * 3. If yes, creates the recurring payment job via the checkout API
32
+ * 4. If no, returns null without creating anything
33
+ *
34
+ * @param draft - The draft object containing the origin payment and payment method references
35
+ * @returns The created recurring payment job if the cart supports recurring payments,
36
+ * or null if it doesn't or if an error occurs
37
+ *
38
+ * @example
39
+ * ```typescript
40
+ * // Caller doesn't need to check if cart is recurring - method handles it
41
+ * const job = await service.createRecurringPaymentJobIfApplicable({
42
+ * originPayment: { id: 'payment-123', typeId: 'payment' },
43
+ * paymentMethod: { id: 'method-456', typeId: 'payment-method' }
44
+ * });
45
+ *
46
+ * if (job) {
47
+ * // Job was created because cart is recurring
48
+ * } else {
49
+ * // Cart is not recurring or an error occurred
50
+ * }
51
+ * ```
52
+ */
53
+ async createRecurringPaymentJobIfApplicable(draft) {
54
+ try {
55
+ const cart = await this.ctCartService.getCartByPaymentId({ paymentId: draft.originPayment.id });
56
+ if (!this.ctCartService.isRecurringCart(cart)) {
57
+ this.logger.info({ originPaymentId: draft.originPayment.id }, 'Cart is not recurring. Skipping recurring payment job creation');
58
+ return null;
59
+ }
60
+ this.logger.info({ draft }, 'Creating new recurring payment job');
61
+ const recurringPaymentJob = await this.internalCreateRecurringPaymentJob(draft);
62
+ this.logger.info({ recurringPaymentJobId: recurringPaymentJob.id }, 'Created new recurring payment job');
63
+ return recurringPaymentJob;
64
+ }
65
+ catch (error) {
66
+ this.logger.error({ error, draft }, 'Error creating recurring payment job');
67
+ return null;
68
+ }
69
+ }
70
+ /**
71
+ * Internal method that performs the HTTP request to create a recurring payment job.
72
+ */
73
+ async internalCreateRecurringPaymentJob(draft) {
74
+ const url = `${this.checkoutUrl}/${this.projectKey}/recurring-payment-jobs`;
75
+ const payload = {
76
+ ...draft,
77
+ status: {
78
+ state: 'Initial',
79
+ },
80
+ };
81
+ const response = await this.fetchWithTokenRetry(url, {
82
+ method: 'POST',
83
+ body: JSON.stringify(payload),
84
+ });
85
+ if (!response.ok) {
86
+ const errorBody = await this.safeParseErrorResponse(response);
87
+ throw new errorx_1.ErrorGeneral('Could not create recurring payment job', {
88
+ privateFields: {
89
+ status: response.status,
90
+ statusText: response.statusText,
91
+ errorBody,
92
+ },
93
+ });
94
+ }
95
+ return (await response.json());
96
+ }
97
+ /**
98
+ * Performs a fetch request with automatic token refresh on 401/403 errors.
99
+ */
100
+ async fetchWithTokenRetry(url, options) {
101
+ if (!this.token) {
102
+ this.token = await this.authorizationService.getAccessToken();
103
+ }
104
+ let response = await fetch(url, {
105
+ ...options,
106
+ headers: {
107
+ 'Content-Type': 'application/json',
108
+ Authorization: `Bearer ${this.token.access_token}`,
109
+ ...options.headers,
110
+ },
111
+ });
112
+ // If commercetools oauth token is expired, get a new one and retry once
113
+ if (response.status === 401 || response.status === 403) {
114
+ this.token = await this.authorizationService.getAccessToken();
115
+ response = await fetch(url, {
116
+ ...options,
117
+ headers: {
118
+ 'Content-Type': 'application/json',
119
+ Authorization: `Bearer ${this.token.access_token}`,
120
+ ...options.headers,
121
+ },
122
+ });
123
+ }
124
+ return response;
125
+ }
126
+ async safeParseErrorResponse(response) {
127
+ try {
128
+ return await response.json();
129
+ }
130
+ catch {
131
+ return response.statusText;
132
+ }
133
+ }
134
+ }
135
+ exports.DefaultRecurringPaymentJobService = DefaultRecurringPaymentJobService;
@@ -0,0 +1,34 @@
1
+ export type RecurringPaymentJobDraft = {
2
+ originPayment: {
3
+ id: string;
4
+ typeId: string;
5
+ };
6
+ paymentMethod: {
7
+ id: string;
8
+ typeId: string;
9
+ };
10
+ };
11
+ export type RecurringPaymentJob = {
12
+ id: string;
13
+ version: number;
14
+ createdAt: string;
15
+ lastModifiedAt: string;
16
+ originPayment?: {
17
+ id: string;
18
+ typeId: string;
19
+ };
20
+ paymentMethod?: {
21
+ id: string;
22
+ typeId: string;
23
+ };
24
+ status: {
25
+ state: string;
26
+ };
27
+ };
28
+ export interface RecurringPaymentJobService {
29
+ /**
30
+ * Ensures a recurring payment job is created if the payment's cart is configured for recurring payments.
31
+ * Returns null if the cart is not configured for recurring payments or if an error occurs.
32
+ */
33
+ createRecurringPaymentJobIfApplicable(draft: RecurringPaymentJobDraft): Promise<RecurringPaymentJob | null>;
34
+ }
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
package/dist/index.d.ts CHANGED
@@ -5,6 +5,7 @@ import { DefaultCartService } from './commercetools/services/ct-cart.service';
5
5
  import { DefaultOrderService } from './commercetools/services/ct-order.service';
6
6
  import { DefaultPaymentService } from './commercetools/services/ct-payment.service';
7
7
  import { DefaultPaymentMethodService } from './commercetools/services/ct-payment-method.service';
8
+ import { DefaultRecurringPaymentJobService } from './commercetools/services/ct-recurring-payment-job.service';
8
9
  import { DefaultCustomTypeService } from './commercetools/services/ct-custom-type.service';
9
10
  import { Logger } from './logger';
10
11
  export * from './api';
@@ -17,6 +18,7 @@ export declare const setupPaymentSDK: (opts: {
17
18
  authUrl: string;
18
19
  apiUrl: string;
19
20
  sessionUrl: string;
21
+ checkoutUrl: string;
20
22
  jwksUrl: string;
21
23
  clientId: string;
22
24
  clientSecret: string;
@@ -33,6 +35,7 @@ export declare const setupPaymentSDK: (opts: {
33
35
  ctPaymentMethodService: DefaultPaymentMethodService;
34
36
  ctCustomTypeService: DefaultCustomTypeService;
35
37
  ctAuthorizationService: DefaultAuthorizationService;
38
+ ctRecurringPaymentJobService: DefaultRecurringPaymentJobService;
36
39
  contextProvider: RequestContextProvider;
37
40
  sessionHeaderAuthHookFn: SessionHeaderAuthenticationHook;
38
41
  sessionQueryParamAuthHookFn: SessionQueryParamAuthenticationHook;
package/dist/index.js CHANGED
@@ -23,6 +23,7 @@ const ct_order_service_1 = require("./commercetools/services/ct-order.service");
23
23
  const ct_payment_service_1 = require("./commercetools/services/ct-payment.service");
24
24
  const ct_payment_method_service_1 = require("./commercetools/services/ct-payment-method.service");
25
25
  const ct_session_service_1 = require("./commercetools/services/ct-session.service");
26
+ const ct_recurring_payment_job_service_1 = require("./commercetools/services/ct-recurring-payment-job.service");
26
27
  const ct_custom_type_service_1 = require("./commercetools/services/ct-custom-type.service");
27
28
  const base_decorator_1 = require("./fetch/decorators/base.decorator");
28
29
  const monitoring_decorator_1 = require("./fetch/decorators/monitoring.decorator");
@@ -69,6 +70,13 @@ const setupPaymentSDK = (opts) => {
69
70
  const ctPaymentService = new ct_payment_service_1.DefaultPaymentService({ ctAPI, logger });
70
71
  const ctPaymentMethodService = new ct_payment_method_service_1.DefaultPaymentMethodService({ ctAPI, logger });
71
72
  const ctCustomTypeService = new ct_custom_type_service_1.DefaultCustomTypeService({ ctAPI, logger });
73
+ const ctRecurringPaymentJobService = new ct_recurring_payment_job_service_1.DefaultRecurringPaymentJobService({
74
+ authorizationService: ctAuthorizationService,
75
+ ctCartService,
76
+ checkoutUrl: opts.checkoutUrl,
77
+ projectKey: opts.projectKey,
78
+ logger,
79
+ });
72
80
  const oauth2Service = new security_1.DefaultOauth2Service({ logger });
73
81
  const jwtService = new security_1.DefaultJWTService({
74
82
  jwksUrl: opts.jwksUrl,
@@ -128,6 +136,7 @@ const setupPaymentSDK = (opts) => {
128
136
  apiUrl: opts.apiUrl,
129
137
  authUrl: opts.authUrl,
130
138
  sessionUrl: opts.sessionUrl,
139
+ checkoutUrl: opts.checkoutUrl,
131
140
  jwksUrl: opts.jwksUrl,
132
141
  jwtIssuer: opts.jwtIssuer,
133
142
  clientId: opts.clientId,
@@ -140,6 +149,7 @@ const setupPaymentSDK = (opts) => {
140
149
  ctPaymentMethodService,
141
150
  ctCustomTypeService,
142
151
  ctAuthorizationService,
152
+ ctRecurringPaymentJobService,
143
153
  contextProvider,
144
154
  sessionHeaderAuthHookFn,
145
155
  sessionQueryParamAuthHookFn,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@commercetools/connect-payments-sdk",
3
- "version": "0.26.0",
3
+ "version": "0.27.1",
4
4
  "description": "Payment SDK for commercetools payment connectors",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",