@qelos/sdk 4.1.1 → 4.2.0
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/dist/administrator/integration-sources.d.ts +3 -1
- package/dist/administrator/integration-sources.js +14 -0
- package/dist/administrator/integration-sources.js.map +1 -1
- package/dist/administrator/payments.d.ts +11 -1
- package/dist/administrator/payments.js +12 -0
- package/dist/administrator/payments.js.map +1 -1
- package/dist/administrator/tests/integration-sources-status.test.d.ts +1 -0
- package/dist/administrator/tests/integration-sources-status.test.js +105 -0
- package/dist/administrator/tests/integration-sources-status.test.js.map +1 -0
- package/dist/payments.d.ts +5 -0
- package/dist/payments.js.map +1 -1
- package/docs/payments.md +54 -0
- package/package.json +2 -2
- package/src/administrator/integration-sources.ts +30 -1
- package/src/administrator/payments.ts +22 -0
- package/src/administrator/tests/integration-sources-status.test.ts +121 -0
- package/src/payments.ts +5 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { QelosSDKOptions, RequestExtra } from '../types';
|
|
2
2
|
import BaseSDK from '../base-sdk';
|
|
3
|
-
import { IIntegrationSource } from '@qelos/global-types';
|
|
3
|
+
import { IIntegrationSource, IIntegrationSourceStatusRequest, IIntegrationSourceStatusResult } from '@qelos/global-types';
|
|
4
4
|
export default class QlIntegrationSources extends BaseSDK {
|
|
5
5
|
private options;
|
|
6
6
|
private relativePath;
|
|
@@ -12,4 +12,6 @@ export default class QlIntegrationSources extends BaseSDK {
|
|
|
12
12
|
remove(sourceId: string): Promise<any>;
|
|
13
13
|
update(sourceId: string, changes: Partial<Pick<IIntegrationSource, 'name' | 'labels' | 'metadata' | 'authentication'>>): Promise<IIntegrationSource>;
|
|
14
14
|
create(source: Pick<IIntegrationSource, 'name' | 'labels' | 'metadata' | 'authentication'>): Promise<IIntegrationSource>;
|
|
15
|
+
checkStatus(sourceId: string, overrides?: Partial<Pick<IIntegrationSource, 'metadata' | 'authentication'>>): Promise<IIntegrationSourceStatusResult>;
|
|
16
|
+
checkDraftStatus(source: IIntegrationSourceStatusRequest): Promise<IIntegrationSourceStatusResult>;
|
|
15
17
|
}
|
|
@@ -29,5 +29,19 @@ export default class QlIntegrationSources extends BaseSDK {
|
|
|
29
29
|
body: JSON.stringify(source)
|
|
30
30
|
});
|
|
31
31
|
}
|
|
32
|
+
checkStatus(sourceId, overrides) {
|
|
33
|
+
return this.callJsonApi(`${this.relativePath}/${sourceId}/status`, {
|
|
34
|
+
method: 'post',
|
|
35
|
+
headers: { 'content-type': 'application/json' },
|
|
36
|
+
body: JSON.stringify(overrides ?? {}),
|
|
37
|
+
});
|
|
38
|
+
}
|
|
39
|
+
checkDraftStatus(source) {
|
|
40
|
+
return this.callJsonApi(`${this.relativePath}/status`, {
|
|
41
|
+
method: 'post',
|
|
42
|
+
headers: { 'content-type': 'application/json' },
|
|
43
|
+
body: JSON.stringify(source),
|
|
44
|
+
});
|
|
45
|
+
}
|
|
32
46
|
}
|
|
33
47
|
//# sourceMappingURL=integration-sources.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"integration-sources.js","sourceRoot":"","sources":["../../src/administrator/integration-sources.ts"],"names":[],"mappings":"AACA,OAAO,OAAO,MAAM,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"integration-sources.js","sourceRoot":"","sources":["../../src/administrator/integration-sources.ts"],"names":[],"mappings":"AACA,OAAO,OAAO,MAAM,aAAa,CAAC;AAOlC,MAAM,CAAC,OAAO,OAAO,oBAAqB,SAAQ,OAAO;IAGnC;IAFZ,YAAY,GAAG,0BAA0B,CAAC;IAElD,YAAoB,OAAwB;QAC1C,KAAK,CAAC,OAAO,CAAC,CAAA;QADI,YAAO,GAAP,OAAO,CAAiB;IAE5C,CAAC;IAED,oBAAoB,CAAC,QAAgB,EAAE,KAAoB;QACzD,OAAO,IAAI,CAAC,WAAW,CAAqB,GAAG,IAAI,CAAC,YAAY,IAAI,QAAQ,EAAE,EAAE,KAAK,CAAC,CAAC;IACzF,CAAC;IAED,OAAO,CAAC,KAAyB,EAAE,KAAoB;QACrD,OAAO,IAAI,CAAC,WAAW,CAAuB,IAAI,CAAC,YAAY,GAAG,IAAI,CAAC,cAAc,CAAC,KAAK,CAAC,EAAE,KAAK,CAAC,CAAC;IACvG,CAAC;IAED,MAAM,CAAC,QAAgB;QACrB,OAAO,IAAI,CAAC,OAAO,CAAC,GAAG,IAAI,CAAC,YAAY,IAAI,QAAQ,EAAE,EAAE,EAAE,MAAM,EAAE,QAAQ,EAAE,CAAC,CAAC;IAChF,CAAC;IAED,MAAM,CAAC,QAAgB,EAAE,OAA6F;QACpH,OAAO,IAAI,CAAC,WAAW,CACrB,GAAG,IAAI,CAAC,YAAY,IAAI,QAAQ,EAAE,EAClC;YACE,MAAM,EAAE,KAAK;YACb,OAAO,EAAE,EAAE,cAAc,EAAE,kBAAkB,EAAE;YAC/C,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC;SAC9B,CACF,CAAA;IACH,CAAC;IAED,MAAM,CAAC,MAAmF;QACxF,OAAO,IAAI,CAAC,WAAW,CAAqB,IAAI,CAAC,YAAY,EAAE;YAC7D,MAAM,EAAE,MAAM;YACd,OAAO,EAAE,EAAE,cAAc,EAAE,kBAAkB,EAAE;YAC/C,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC;SAC7B,CAAC,CAAA;IACJ,CAAC;IAED,WAAW,CACT,QAAgB,EAChB,SAA4E;QAE5E,OAAO,IAAI,CAAC,WAAW,CACrB,GAAG,IAAI,CAAC,YAAY,IAAI,QAAQ,SAAS,EACzC;YACE,MAAM,EAAE,MAAM;YACd,OAAO,EAAE,EAAE,cAAc,EAAE,kBAAkB,EAAE;YAC/C,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,SAAS,IAAI,EAAE,CAAC;SACtC,CACF,CAAC;IACJ,CAAC;IAED,gBAAgB,CAAC,MAAuC;QACtD,OAAO,IAAI,CAAC,WAAW,CACrB,GAAG,IAAI,CAAC,YAAY,SAAS,EAC7B;YACE,MAAM,EAAE,MAAM;YACd,OAAO,EAAE,EAAE,cAAc,EAAE,kBAAkB,EAAE;YAC/C,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC;SAC7B,CACF,CAAC;IACJ,CAAC;CAEF"}
|
|
@@ -1,6 +1,10 @@
|
|
|
1
1
|
import { QelosSDKOptions } from '../types';
|
|
2
2
|
import BaseSDK from '../base-sdk';
|
|
3
|
-
import { IPlan, ISubscription, IInvoice, ICoupon, BillableEntityType, SubscriptionStatus, InvoiceStatus, BillingCycle } from '@qelos/global-types';
|
|
3
|
+
import { IPlan, ISubscription, IInvoice, ICoupon, BillableEntityType, SubscriptionStatus, InvoiceStatus, BillingCycle, IPaymentsConfigurationMetadata } from '@qelos/global-types';
|
|
4
|
+
export interface PaymentsConfigurationRecord {
|
|
5
|
+
key: string;
|
|
6
|
+
metadata: IPaymentsConfigurationMetadata;
|
|
7
|
+
}
|
|
4
8
|
export interface AdminCheckoutRequest {
|
|
5
9
|
planId: string;
|
|
6
10
|
billingCycle: BillingCycle;
|
|
@@ -10,6 +14,8 @@ export interface AdminCheckoutRequest {
|
|
|
10
14
|
couponCode?: string;
|
|
11
15
|
successUrl?: string;
|
|
12
16
|
cancelUrl?: string;
|
|
17
|
+
/** When true, cancels any existing active/trialing subscription before checkout. */
|
|
18
|
+
reset?: boolean;
|
|
13
19
|
/**
|
|
14
20
|
* Admin-only. For plans with `dynamic: true`, sets the `dynamicAmount` on the
|
|
15
21
|
* pending subscription before initiating checkout. Regular users cannot set this;
|
|
@@ -77,4 +83,8 @@ export default class QlPaymentsAdmin extends BaseSDK {
|
|
|
77
83
|
createCoupon(data: Omit<ICoupon, '_id' | 'tenant' | 'created' | 'currentRedemptions'>): Promise<ICoupon>;
|
|
78
84
|
updateCoupon(couponId: string, data: Partial<ICoupon>): Promise<ICoupon>;
|
|
79
85
|
deleteCoupon(couponId: string): Promise<ICoupon>;
|
|
86
|
+
/** Load tenant payments settings (`payments-configuration`). */
|
|
87
|
+
getPaymentsConfiguration(): Promise<PaymentsConfigurationRecord>;
|
|
88
|
+
/** Update tenant payments settings. Partial metadata is merged with the existing record. */
|
|
89
|
+
updatePaymentsConfiguration(metadata: Partial<IPaymentsConfigurationMetadata>): Promise<PaymentsConfigurationRecord>;
|
|
80
90
|
}
|
|
@@ -108,5 +108,17 @@ export default class QlPaymentsAdmin extends BaseSDK {
|
|
|
108
108
|
deleteCoupon(couponId) {
|
|
109
109
|
return this.callJsonApi(`/api/coupons/${couponId}`, { method: 'delete' });
|
|
110
110
|
}
|
|
111
|
+
/** Load tenant payments settings (`payments-configuration`). */
|
|
112
|
+
getPaymentsConfiguration() {
|
|
113
|
+
return this.callJsonApi('/api/payments/configuration');
|
|
114
|
+
}
|
|
115
|
+
/** Update tenant payments settings. Partial metadata is merged with the existing record. */
|
|
116
|
+
updatePaymentsConfiguration(metadata) {
|
|
117
|
+
return this.callJsonApi('/api/payments/configuration', {
|
|
118
|
+
method: 'put',
|
|
119
|
+
headers: { 'content-type': 'application/json' },
|
|
120
|
+
body: JSON.stringify({ metadata }),
|
|
121
|
+
});
|
|
122
|
+
}
|
|
111
123
|
}
|
|
112
124
|
//# sourceMappingURL=payments.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"payments.js","sourceRoot":"","sources":["../../src/administrator/payments.ts"],"names":[],"mappings":"AACA,OAAO,OAAO,MAAM,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"payments.js","sourceRoot":"","sources":["../../src/administrator/payments.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
import * as assert from 'node:assert/strict';
|
|
2
|
+
import { test } from 'node:test';
|
|
3
|
+
import { IntegrationSourceKind } from '@qelos/global-types';
|
|
4
|
+
import QlIntegrationSources from '../integration-sources';
|
|
5
|
+
function jsonResponse(body) {
|
|
6
|
+
const res = new Response(JSON.stringify(body));
|
|
7
|
+
res.headers.set('Content-Type', 'application/json');
|
|
8
|
+
return res;
|
|
9
|
+
}
|
|
10
|
+
const connectedResult = {
|
|
11
|
+
status: 'connected',
|
|
12
|
+
message: 'Connection verified',
|
|
13
|
+
kind: IntegrationSourceKind.Sumit,
|
|
14
|
+
checkedAt: '2026-07-23T05:00:00.000Z',
|
|
15
|
+
};
|
|
16
|
+
test('QlIntegrationSources status methods', async (t) => {
|
|
17
|
+
await t.test('checkStatus sends POST to saved source status path', async () => {
|
|
18
|
+
let url = '';
|
|
19
|
+
let init;
|
|
20
|
+
const options = {
|
|
21
|
+
appUrl: 'http://localhost:3000',
|
|
22
|
+
fetch: async (requestUrl, requestInit) => {
|
|
23
|
+
url = requestUrl.toString();
|
|
24
|
+
init = requestInit;
|
|
25
|
+
return jsonResponse(connectedResult);
|
|
26
|
+
},
|
|
27
|
+
};
|
|
28
|
+
const sdk = new QlIntegrationSources(options);
|
|
29
|
+
const result = await sdk.checkStatus('src-123');
|
|
30
|
+
assert.equal(url, 'http://localhost:3000/api/integration-sources/src-123/status');
|
|
31
|
+
assert.equal(init?.method, 'post');
|
|
32
|
+
assert.equal((init?.headers)['content-type'], 'application/json');
|
|
33
|
+
assert.deepEqual(JSON.parse(init?.body), {});
|
|
34
|
+
assert.deepEqual(result, connectedResult);
|
|
35
|
+
});
|
|
36
|
+
await t.test('checkStatus sends metadata and authentication overrides', async () => {
|
|
37
|
+
let init;
|
|
38
|
+
const options = {
|
|
39
|
+
appUrl: 'http://localhost:3000',
|
|
40
|
+
fetch: async (_url, requestInit) => {
|
|
41
|
+
init = requestInit;
|
|
42
|
+
return jsonResponse(connectedResult);
|
|
43
|
+
},
|
|
44
|
+
};
|
|
45
|
+
const sdk = new QlIntegrationSources(options);
|
|
46
|
+
await sdk.checkStatus('src-123', {
|
|
47
|
+
metadata: { companyId: '42' },
|
|
48
|
+
authentication: { apiKey: 'secret' },
|
|
49
|
+
});
|
|
50
|
+
assert.deepEqual(JSON.parse(init?.body), {
|
|
51
|
+
metadata: { companyId: '42' },
|
|
52
|
+
authentication: { apiKey: 'secret' },
|
|
53
|
+
});
|
|
54
|
+
});
|
|
55
|
+
await t.test('checkDraftStatus sends POST to draft status path', async () => {
|
|
56
|
+
let url = '';
|
|
57
|
+
let init;
|
|
58
|
+
const options = {
|
|
59
|
+
appUrl: 'http://localhost:3000',
|
|
60
|
+
fetch: async (requestUrl, requestInit) => {
|
|
61
|
+
url = requestUrl.toString();
|
|
62
|
+
init = requestInit;
|
|
63
|
+
return jsonResponse(connectedResult);
|
|
64
|
+
},
|
|
65
|
+
};
|
|
66
|
+
const draft = {
|
|
67
|
+
kind: IntegrationSourceKind.PayPal,
|
|
68
|
+
metadata: { environment: 'sandbox' },
|
|
69
|
+
authentication: { clientId: 'id', clientSecret: 'secret' },
|
|
70
|
+
};
|
|
71
|
+
const sdk = new QlIntegrationSources(options);
|
|
72
|
+
const result = await sdk.checkDraftStatus(draft);
|
|
73
|
+
assert.equal(url, 'http://localhost:3000/api/integration-sources/status');
|
|
74
|
+
assert.equal(init?.method, 'post');
|
|
75
|
+
assert.equal((init?.headers)['content-type'], 'application/json');
|
|
76
|
+
assert.deepEqual(JSON.parse(init?.body), draft);
|
|
77
|
+
assert.deepEqual(result, connectedResult);
|
|
78
|
+
});
|
|
79
|
+
await t.test('checkDraftStatus is kind-agnostic and works for non-payment sources too', async () => {
|
|
80
|
+
let init;
|
|
81
|
+
const emailConnectedResult = {
|
|
82
|
+
status: 'connected',
|
|
83
|
+
message: 'SMTP connection verified',
|
|
84
|
+
kind: IntegrationSourceKind.Email,
|
|
85
|
+
checkedAt: '2026-07-23T05:00:00.000Z',
|
|
86
|
+
};
|
|
87
|
+
const options = {
|
|
88
|
+
appUrl: 'http://localhost:3000',
|
|
89
|
+
fetch: async (_url, requestInit) => {
|
|
90
|
+
init = requestInit;
|
|
91
|
+
return jsonResponse(emailConnectedResult);
|
|
92
|
+
},
|
|
93
|
+
};
|
|
94
|
+
const draft = {
|
|
95
|
+
kind: IntegrationSourceKind.Email,
|
|
96
|
+
metadata: { smtp: 'smtp.example.com', username: 'bot@example.com', email: 'bot@example.com', pop3: 'pop3.example.com', senderName: 'Bot' },
|
|
97
|
+
authentication: { password: 'secret' },
|
|
98
|
+
};
|
|
99
|
+
const sdk = new QlIntegrationSources(options);
|
|
100
|
+
const result = await sdk.checkDraftStatus(draft);
|
|
101
|
+
assert.deepEqual(JSON.parse(init?.body), draft);
|
|
102
|
+
assert.deepEqual(result, emailConnectedResult);
|
|
103
|
+
});
|
|
104
|
+
});
|
|
105
|
+
//# sourceMappingURL=integration-sources-status.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"integration-sources-status.test.js","sourceRoot":"","sources":["../../../src/administrator/tests/integration-sources-status.test.ts"],"names":[],"mappings":"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"}
|
package/dist/payments.d.ts
CHANGED
|
@@ -9,6 +9,11 @@ export interface CheckoutRequest {
|
|
|
9
9
|
couponCode?: string;
|
|
10
10
|
successUrl?: string;
|
|
11
11
|
cancelUrl?: string;
|
|
12
|
+
/**
|
|
13
|
+
* When true, cancels any existing active or trialing subscription for the
|
|
14
|
+
* authenticated billable entity before starting checkout (e.g. plan change).
|
|
15
|
+
*/
|
|
16
|
+
reset?: boolean;
|
|
12
17
|
/**
|
|
13
18
|
* Pre-created subscription ID. Required for dynamic plans — the admin must set
|
|
14
19
|
* `dynamicAmount` on the subscription before this checkout call will succeed.
|
package/dist/payments.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"payments.js","sourceRoot":"","sources":["../src/payments.ts"],"names":[],"mappings":"AACA,OAAO,OAAO,MAAM,YAAY,CAAC;
|
|
1
|
+
{"version":3,"file":"payments.js","sourceRoot":"","sources":["../src/payments.ts"],"names":[],"mappings":"AACA,OAAO,OAAO,MAAM,YAAY,CAAC;AAgCjC,MAAM,CAAC,OAAO,OAAO,UAAW,SAAQ,OAAO;IACrC,YAAY,GAAG,MAAM,CAAC;IAE9B,YAAY,OAAwB;QAClC,KAAK,CAAC,OAAO,CAAC,CAAC;IACjB,CAAC;IAED,QAAQ,CAAC,KAA8B;QACrC,MAAM,EAAE,GAAG,KAAK,CAAC,CAAC,CAAC,IAAI,IAAI,eAAe,CAAC,KAAY,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QAChE,OAAO,IAAI,CAAC,WAAW,CAAU,GAAG,IAAI,CAAC,YAAY,gBAAgB,EAAE,EAAE,CAAC,CAAC;IAC7E,CAAC;IAED,OAAO,CAAC,MAAc;QACpB,OAAO,IAAI,CAAC,WAAW,CAAQ,GAAG,IAAI,CAAC,YAAY,UAAU,MAAM,EAAE,CAAC,CAAC;IACzE,CAAC;IAED;;;;;OAKG;IACH,eAAe,CAAC,MAAc,EAAE,YAA0B,EAAE,UAAmB;QAC7E,OAAO,IAAI,CAAC,WAAW,CACrB,GAAG,IAAI,CAAC,YAAY,gBAAgB,EACpC;YACE,MAAM,EAAE,MAAM;YACd,OAAO,EAAE,EAAE,cAAc,EAAE,kBAAkB,EAAE;YAC/C,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,EAAE,MAAM,EAAE,YAAY,EAAE,UAAU,EAAE,CAAC;SAC3D,CACF,CAAC;IACJ,CAAC;IAED;;;;;;;;;;OAUG;IACH,QAAQ,CAAC,MAAuB;QAC9B,OAAO,IAAI,CAAC,WAAW,CACrB,GAAG,IAAI,CAAC,YAAY,WAAW,EAC/B;YACE,MAAM,EAAE,MAAM;YACd,OAAO,EAAE,EAAE,cAAc,EAAE,kBAAkB,EAAE;YAC/C,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC;SAC7B,CACF,CAAC;IACJ,CAAC;IAED,iBAAiB;QACf,OAAO,IAAI,CAAC,WAAW,CAAgB,GAAG,IAAI,CAAC,YAAY,mBAAmB,CAAC,CAAC;IAClF,CAAC;IAED,kBAAkB,CAAC,cAAsB;QACvC,OAAO,IAAI,CAAC,WAAW,CACrB,GAAG,IAAI,CAAC,YAAY,kBAAkB,cAAc,SAAS,EAC7D,EAAE,MAAM,EAAE,KAAK,EAAE,CAClB,CAAC;IACJ,CAAC;IAED,WAAW,CAAC,KAA2B;QACrC,MAAM,EAAE,GAAG,KAAK,CAAC,CAAC,CAAC,IAAI,IAAI,eAAe,CAAC,KAAY,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QAChE,OAAO,IAAI,CAAC,WAAW,CAAa,GAAG,IAAI,CAAC,YAAY,YAAY,EAAE,EAAE,CAAC,CAAC;IAC5E,CAAC;IAED,UAAU,CAAC,SAAiB;QAC1B,OAAO,IAAI,CAAC,WAAW,CAAW,GAAG,IAAI,CAAC,YAAY,aAAa,SAAS,EAAE,CAAC,CAAC;IAClF,CAAC;IAED,cAAc,CAAC,IAAY,EAAE,MAAe;QAC1C,OAAO,IAAI,CAAC,WAAW,CACrB,GAAG,IAAI,CAAC,YAAY,mBAAmB,EACvC;YACE,MAAM,EAAE,MAAM;YACd,OAAO,EAAE,EAAE,cAAc,EAAE,kBAAkB,EAAE;YAC/C,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC;SACvC,CACF,CAAC;IACJ,CAAC;CACF"}
|
package/docs/payments.md
CHANGED
|
@@ -104,6 +104,60 @@ const result = await adminSdk.payments.checkout({
|
|
|
104
104
|
|
|
105
105
|
---
|
|
106
106
|
|
|
107
|
+
## Payments configuration
|
|
108
|
+
|
|
109
|
+
Admin-only tenant settings stored in `payments-configuration`.
|
|
110
|
+
|
|
111
|
+
### `GET /api/payments/configuration`
|
|
112
|
+
|
|
113
|
+
Returns the current payments configuration metadata. **Auth**: privileged.
|
|
114
|
+
|
|
115
|
+
**Response `200`**
|
|
116
|
+
|
|
117
|
+
```json
|
|
118
|
+
{
|
|
119
|
+
"key": "payments-configuration",
|
|
120
|
+
"metadata": {
|
|
121
|
+
"isEnabled": true,
|
|
122
|
+
"paymentSourceId": "integration-source-id",
|
|
123
|
+
"defaultCurrency": "ILS",
|
|
124
|
+
"gracePeriodDays": 3,
|
|
125
|
+
"successUrl": "https://your-app.com/billing/return?status=success",
|
|
126
|
+
"cancelUrl": "https://your-app.com/billing/return?status=cancel"
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
### `PUT /api/payments/configuration`
|
|
132
|
+
|
|
133
|
+
Creates or updates payments configuration. Partial `metadata` is merged with the existing record. **Auth**: privileged.
|
|
134
|
+
|
|
135
|
+
**Body**
|
|
136
|
+
|
|
137
|
+
```json
|
|
138
|
+
{
|
|
139
|
+
"metadata": {
|
|
140
|
+
"isEnabled": true,
|
|
141
|
+
"paymentSourceId": "integration-source-id",
|
|
142
|
+
"successUrl": "https://your-app.com/billing/return?status=success",
|
|
143
|
+
"cancelUrl": "https://your-app.com/billing/return?status=cancel"
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
| Field | Type | Description |
|
|
149
|
+
|---|---|---|
|
|
150
|
+
| `isEnabled` | boolean | Enable payments for the tenant |
|
|
151
|
+
| `paymentSourceId` | string | Integration source `_id` for the payment provider |
|
|
152
|
+
| `defaultCurrency` | string | Default ISO 4217 currency code |
|
|
153
|
+
| `gracePeriodDays` | number | Grace period after failed payment |
|
|
154
|
+
| `successUrl` | string | Default redirect URL after successful checkout |
|
|
155
|
+
| `cancelUrl` | string | Default redirect URL when checkout is canceled |
|
|
156
|
+
|
|
157
|
+
> **SDK:** `adminSdk.payments.getPaymentsConfiguration()` · `adminSdk.payments.updatePaymentsConfiguration(metadata)`
|
|
158
|
+
|
|
159
|
+
---
|
|
160
|
+
|
|
107
161
|
## Listing Plans and Subscriptions
|
|
108
162
|
|
|
109
163
|
### User SDK
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@qelos/sdk",
|
|
3
|
-
"version": "4.
|
|
3
|
+
"version": "4.2.0",
|
|
4
4
|
"description": "SDK for Qelos API",
|
|
5
5
|
"main": "./dist/index.js",
|
|
6
6
|
"types": "./dist/index.d.ts",
|
|
@@ -102,7 +102,7 @@
|
|
|
102
102
|
"access": "public"
|
|
103
103
|
},
|
|
104
104
|
"dependencies": {
|
|
105
|
-
"@qelos/global-types": "^4.
|
|
105
|
+
"@qelos/global-types": "^4.2.0"
|
|
106
106
|
},
|
|
107
107
|
"devDependencies": {
|
|
108
108
|
"tsx": "^4.21.0",
|
|
@@ -1,6 +1,10 @@
|
|
|
1
1
|
import { QelosSDKOptions, RequestExtra } from '../types';
|
|
2
2
|
import BaseSDK from '../base-sdk';
|
|
3
|
-
import {
|
|
3
|
+
import {
|
|
4
|
+
IIntegrationSource,
|
|
5
|
+
IIntegrationSourceStatusRequest,
|
|
6
|
+
IIntegrationSourceStatusResult,
|
|
7
|
+
} from '@qelos/global-types';
|
|
4
8
|
|
|
5
9
|
export default class QlIntegrationSources extends BaseSDK {
|
|
6
10
|
private relativePath = '/api/integration-sources';
|
|
@@ -40,4 +44,29 @@ export default class QlIntegrationSources extends BaseSDK {
|
|
|
40
44
|
})
|
|
41
45
|
}
|
|
42
46
|
|
|
47
|
+
checkStatus(
|
|
48
|
+
sourceId: string,
|
|
49
|
+
overrides?: Partial<Pick<IIntegrationSource, 'metadata' | 'authentication'>>,
|
|
50
|
+
): Promise<IIntegrationSourceStatusResult> {
|
|
51
|
+
return this.callJsonApi<IIntegrationSourceStatusResult>(
|
|
52
|
+
`${this.relativePath}/${sourceId}/status`,
|
|
53
|
+
{
|
|
54
|
+
method: 'post',
|
|
55
|
+
headers: { 'content-type': 'application/json' },
|
|
56
|
+
body: JSON.stringify(overrides ?? {}),
|
|
57
|
+
},
|
|
58
|
+
);
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
checkDraftStatus(source: IIntegrationSourceStatusRequest): Promise<IIntegrationSourceStatusResult> {
|
|
62
|
+
return this.callJsonApi<IIntegrationSourceStatusResult>(
|
|
63
|
+
`${this.relativePath}/status`,
|
|
64
|
+
{
|
|
65
|
+
method: 'post',
|
|
66
|
+
headers: { 'content-type': 'application/json' },
|
|
67
|
+
body: JSON.stringify(source),
|
|
68
|
+
},
|
|
69
|
+
);
|
|
70
|
+
}
|
|
71
|
+
|
|
43
72
|
}
|
|
@@ -3,8 +3,14 @@ import BaseSDK from '../base-sdk';
|
|
|
3
3
|
import {
|
|
4
4
|
IPlan, ISubscription, IInvoice, ICoupon,
|
|
5
5
|
BillableEntityType, SubscriptionStatus, InvoiceStatus, BillingCycle,
|
|
6
|
+
IPaymentsConfigurationMetadata,
|
|
6
7
|
} from '@qelos/global-types';
|
|
7
8
|
|
|
9
|
+
export interface PaymentsConfigurationRecord {
|
|
10
|
+
key: string;
|
|
11
|
+
metadata: IPaymentsConfigurationMetadata;
|
|
12
|
+
}
|
|
13
|
+
|
|
8
14
|
export interface AdminCheckoutRequest {
|
|
9
15
|
planId: string;
|
|
10
16
|
billingCycle: BillingCycle;
|
|
@@ -14,6 +20,8 @@ export interface AdminCheckoutRequest {
|
|
|
14
20
|
couponCode?: string;
|
|
15
21
|
successUrl?: string;
|
|
16
22
|
cancelUrl?: string;
|
|
23
|
+
/** When true, cancels any existing active/trialing subscription before checkout. */
|
|
24
|
+
reset?: boolean;
|
|
17
25
|
/**
|
|
18
26
|
* Admin-only. For plans with `dynamic: true`, sets the `dynamicAmount` on the
|
|
19
27
|
* pending subscription before initiating checkout. Regular users cannot set this;
|
|
@@ -181,4 +189,18 @@ export default class QlPaymentsAdmin extends BaseSDK {
|
|
|
181
189
|
deleteCoupon(couponId: string) {
|
|
182
190
|
return this.callJsonApi<ICoupon>(`/api/coupons/${couponId}`, { method: 'delete' });
|
|
183
191
|
}
|
|
192
|
+
|
|
193
|
+
/** Load tenant payments settings (`payments-configuration`). */
|
|
194
|
+
getPaymentsConfiguration() {
|
|
195
|
+
return this.callJsonApi<PaymentsConfigurationRecord>('/api/payments/configuration');
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
/** Update tenant payments settings. Partial metadata is merged with the existing record. */
|
|
199
|
+
updatePaymentsConfiguration(metadata: Partial<IPaymentsConfigurationMetadata>) {
|
|
200
|
+
return this.callJsonApi<PaymentsConfigurationRecord>('/api/payments/configuration', {
|
|
201
|
+
method: 'put',
|
|
202
|
+
headers: { 'content-type': 'application/json' },
|
|
203
|
+
body: JSON.stringify({ metadata }),
|
|
204
|
+
});
|
|
205
|
+
}
|
|
184
206
|
}
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
import * as assert from 'node:assert/strict';
|
|
2
|
+
import { test } from 'node:test';
|
|
3
|
+
import { IntegrationSourceKind } from '@qelos/global-types';
|
|
4
|
+
import { QelosSDKOptions } from '../../types';
|
|
5
|
+
import QlIntegrationSources from '../integration-sources';
|
|
6
|
+
|
|
7
|
+
function jsonResponse(body: unknown) {
|
|
8
|
+
const res = new Response(JSON.stringify(body));
|
|
9
|
+
res.headers.set('Content-Type', 'application/json');
|
|
10
|
+
return res;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
const connectedResult = {
|
|
14
|
+
status: 'connected' as const,
|
|
15
|
+
message: 'Connection verified',
|
|
16
|
+
kind: IntegrationSourceKind.Sumit,
|
|
17
|
+
checkedAt: '2026-07-23T05:00:00.000Z',
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
test('QlIntegrationSources status methods', async (t) => {
|
|
21
|
+
await t.test('checkStatus sends POST to saved source status path', async () => {
|
|
22
|
+
let url = '';
|
|
23
|
+
let init: RequestInit | undefined;
|
|
24
|
+
const options: QelosSDKOptions = {
|
|
25
|
+
appUrl: 'http://localhost:3000',
|
|
26
|
+
fetch: async (requestUrl, requestInit) => {
|
|
27
|
+
url = requestUrl.toString();
|
|
28
|
+
init = requestInit;
|
|
29
|
+
return jsonResponse(connectedResult);
|
|
30
|
+
},
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
const sdk = new QlIntegrationSources(options);
|
|
34
|
+
const result = await sdk.checkStatus('src-123');
|
|
35
|
+
|
|
36
|
+
assert.equal(url, 'http://localhost:3000/api/integration-sources/src-123/status');
|
|
37
|
+
assert.equal(init?.method, 'post');
|
|
38
|
+
assert.equal((init?.headers as Record<string, string>)['content-type'], 'application/json');
|
|
39
|
+
assert.deepEqual(JSON.parse(init?.body as string), {});
|
|
40
|
+
assert.deepEqual(result, connectedResult);
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
await t.test('checkStatus sends metadata and authentication overrides', async () => {
|
|
44
|
+
let init: RequestInit | undefined;
|
|
45
|
+
const options: QelosSDKOptions = {
|
|
46
|
+
appUrl: 'http://localhost:3000',
|
|
47
|
+
fetch: async (_url, requestInit) => {
|
|
48
|
+
init = requestInit;
|
|
49
|
+
return jsonResponse(connectedResult);
|
|
50
|
+
},
|
|
51
|
+
};
|
|
52
|
+
|
|
53
|
+
const sdk = new QlIntegrationSources(options);
|
|
54
|
+
await sdk.checkStatus('src-123', {
|
|
55
|
+
metadata: { companyId: '42' },
|
|
56
|
+
authentication: { apiKey: 'secret' },
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
assert.deepEqual(JSON.parse(init?.body as string), {
|
|
60
|
+
metadata: { companyId: '42' },
|
|
61
|
+
authentication: { apiKey: 'secret' },
|
|
62
|
+
});
|
|
63
|
+
});
|
|
64
|
+
|
|
65
|
+
await t.test('checkDraftStatus sends POST to draft status path', async () => {
|
|
66
|
+
let url = '';
|
|
67
|
+
let init: RequestInit | undefined;
|
|
68
|
+
const options: QelosSDKOptions = {
|
|
69
|
+
appUrl: 'http://localhost:3000',
|
|
70
|
+
fetch: async (requestUrl, requestInit) => {
|
|
71
|
+
url = requestUrl.toString();
|
|
72
|
+
init = requestInit;
|
|
73
|
+
return jsonResponse(connectedResult);
|
|
74
|
+
},
|
|
75
|
+
};
|
|
76
|
+
|
|
77
|
+
const draft = {
|
|
78
|
+
kind: IntegrationSourceKind.PayPal,
|
|
79
|
+
metadata: { environment: 'sandbox' },
|
|
80
|
+
authentication: { clientId: 'id', clientSecret: 'secret' },
|
|
81
|
+
};
|
|
82
|
+
|
|
83
|
+
const sdk = new QlIntegrationSources(options);
|
|
84
|
+
const result = await sdk.checkDraftStatus(draft);
|
|
85
|
+
|
|
86
|
+
assert.equal(url, 'http://localhost:3000/api/integration-sources/status');
|
|
87
|
+
assert.equal(init?.method, 'post');
|
|
88
|
+
assert.equal((init?.headers as Record<string, string>)['content-type'], 'application/json');
|
|
89
|
+
assert.deepEqual(JSON.parse(init?.body as string), draft);
|
|
90
|
+
assert.deepEqual(result, connectedResult);
|
|
91
|
+
});
|
|
92
|
+
|
|
93
|
+
await t.test('checkDraftStatus is kind-agnostic and works for non-payment sources too', async () => {
|
|
94
|
+
let init: RequestInit | undefined;
|
|
95
|
+
const emailConnectedResult = {
|
|
96
|
+
status: 'connected' as const,
|
|
97
|
+
message: 'SMTP connection verified',
|
|
98
|
+
kind: IntegrationSourceKind.Email,
|
|
99
|
+
checkedAt: '2026-07-23T05:00:00.000Z',
|
|
100
|
+
};
|
|
101
|
+
const options: QelosSDKOptions = {
|
|
102
|
+
appUrl: 'http://localhost:3000',
|
|
103
|
+
fetch: async (_url, requestInit) => {
|
|
104
|
+
init = requestInit;
|
|
105
|
+
return jsonResponse(emailConnectedResult);
|
|
106
|
+
},
|
|
107
|
+
};
|
|
108
|
+
|
|
109
|
+
const draft = {
|
|
110
|
+
kind: IntegrationSourceKind.Email,
|
|
111
|
+
metadata: { smtp: 'smtp.example.com', username: 'bot@example.com', email: 'bot@example.com', pop3: 'pop3.example.com', senderName: 'Bot' },
|
|
112
|
+
authentication: { password: 'secret' },
|
|
113
|
+
};
|
|
114
|
+
|
|
115
|
+
const sdk = new QlIntegrationSources(options);
|
|
116
|
+
const result = await sdk.checkDraftStatus(draft);
|
|
117
|
+
|
|
118
|
+
assert.deepEqual(JSON.parse(init?.body as string), draft);
|
|
119
|
+
assert.deepEqual(result, emailConnectedResult);
|
|
120
|
+
});
|
|
121
|
+
});
|
package/src/payments.ts
CHANGED
|
@@ -10,6 +10,11 @@ export interface CheckoutRequest {
|
|
|
10
10
|
couponCode?: string;
|
|
11
11
|
successUrl?: string;
|
|
12
12
|
cancelUrl?: string;
|
|
13
|
+
/**
|
|
14
|
+
* When true, cancels any existing active or trialing subscription for the
|
|
15
|
+
* authenticated billable entity before starting checkout (e.g. plan change).
|
|
16
|
+
*/
|
|
17
|
+
reset?: boolean;
|
|
13
18
|
/**
|
|
14
19
|
* Pre-created subscription ID. Required for dynamic plans — the admin must set
|
|
15
20
|
* `dynamicAmount` on the subscription before this checkout call will succeed.
|