@sanghosdk/js 0.1.2
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 +57 -0
- package/README.md +366 -0
- package/dist/index.cjs +1395 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +2559 -0
- package/dist/index.d.ts +2559 -0
- package/dist/index.js +1379 -0
- package/dist/index.js.map +1 -0
- package/package.json +82 -0
package/dist/index.cjs
ADDED
|
@@ -0,0 +1,1395 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, '__esModule', { value: true });
|
|
4
|
+
|
|
5
|
+
/* sangho-sdk-js v0.1.2 — https://docs.sangho.ga/sdks/js */
|
|
6
|
+
|
|
7
|
+
// core/errors.ts
|
|
8
|
+
var KNOWN_ERROR_TYPES = [
|
|
9
|
+
"AUTHENTICATION_ERROR",
|
|
10
|
+
"PERMISSION_ERROR",
|
|
11
|
+
"NOT_FOUND_ERROR",
|
|
12
|
+
"CONFLICT_ERROR",
|
|
13
|
+
"VALIDATION_ERROR",
|
|
14
|
+
"RATE_LIMIT_ERROR",
|
|
15
|
+
"API_ERROR",
|
|
16
|
+
"NETWORK_ERROR",
|
|
17
|
+
"TIMEOUT_ERROR"
|
|
18
|
+
];
|
|
19
|
+
function resolveErrorType(defaultType, raw) {
|
|
20
|
+
const backendType = raw?.type?.toUpperCase();
|
|
21
|
+
if (backendType && KNOWN_ERROR_TYPES.includes(backendType)) {
|
|
22
|
+
return backendType;
|
|
23
|
+
}
|
|
24
|
+
return defaultType;
|
|
25
|
+
}
|
|
26
|
+
var SanghoError = class extends Error {
|
|
27
|
+
/**
|
|
28
|
+
* Catégorie large de l'erreur, une des 9 valeurs `SanghoErrorType`
|
|
29
|
+
* (`VALIDATION_ERROR`, `RATE_LIMIT_ERROR`, `NETWORK_ERROR`, ...).
|
|
30
|
+
* Utile pour un `switch`/branchement générique.
|
|
31
|
+
*/
|
|
32
|
+
type;
|
|
33
|
+
/**
|
|
34
|
+
* Code métier précis renvoyé par le backend (`raw.code`), ex :
|
|
35
|
+
* `AMOUNT_TOO_SMALL`, `INSUFFICIENT_FUNDS`, `CUSTOMER_NOT_FOUND`,
|
|
36
|
+
* `INVALID_API_KEY`, `CURRENCY_NOT_IN_PLAN`... Le catalogue de codes est
|
|
37
|
+
* possédé et versionné côté backend et continuera de grandir — c'est
|
|
38
|
+
* pourquoi ce champ est typé `string` plutôt qu'une union fermée.
|
|
39
|
+
*
|
|
40
|
+
* Quand l'erreur n'a jamais atteint le backend (`SanghoNetworkError`,
|
|
41
|
+
* `SanghoTimeoutError` — pas de corps de réponse à lire), `code` retombe
|
|
42
|
+
* sur la même valeur que `type`.
|
|
43
|
+
*/
|
|
44
|
+
code;
|
|
45
|
+
statusCode;
|
|
46
|
+
raw;
|
|
47
|
+
constructor(message, type = "API_ERROR", statusCode, raw) {
|
|
48
|
+
super(message);
|
|
49
|
+
this.name = "SanghoError";
|
|
50
|
+
this.type = resolveErrorType(type, raw);
|
|
51
|
+
this.code = raw?.code ?? this.type;
|
|
52
|
+
this.statusCode = statusCode;
|
|
53
|
+
this.raw = raw;
|
|
54
|
+
Object.setPrototypeOf(this, new.target.prototype);
|
|
55
|
+
}
|
|
56
|
+
};
|
|
57
|
+
var SanghoAuthError = class extends SanghoError {
|
|
58
|
+
constructor(message = "Invalid or missing API key.", raw) {
|
|
59
|
+
super(message, "AUTHENTICATION_ERROR", 401, raw);
|
|
60
|
+
this.name = "SanghoAuthError";
|
|
61
|
+
}
|
|
62
|
+
};
|
|
63
|
+
var SanghoPublicKeyError = class extends SanghoError {
|
|
64
|
+
constructor(message = "Public key not allowed for this operation.", raw) {
|
|
65
|
+
super(
|
|
66
|
+
message,
|
|
67
|
+
"PERMISSION_ERROR",
|
|
68
|
+
403,
|
|
69
|
+
raw
|
|
70
|
+
// ← raw transmis
|
|
71
|
+
);
|
|
72
|
+
this.name = "SanghoPublicKeyError";
|
|
73
|
+
}
|
|
74
|
+
};
|
|
75
|
+
var SanghoPermissionError = class extends SanghoError {
|
|
76
|
+
constructor(message = "You do not have permission to perform this action.", raw) {
|
|
77
|
+
super(message, "PERMISSION_ERROR", 403, raw);
|
|
78
|
+
this.name = "SanghoPermissionError";
|
|
79
|
+
}
|
|
80
|
+
};
|
|
81
|
+
var SanghoNotFoundError = class extends SanghoError {
|
|
82
|
+
constructor(message = "Resource not found.", raw) {
|
|
83
|
+
super(message, "NOT_FOUND_ERROR", 404, raw);
|
|
84
|
+
this.name = "SanghoNotFoundError";
|
|
85
|
+
}
|
|
86
|
+
};
|
|
87
|
+
var SanghoValidationError = class extends SanghoError {
|
|
88
|
+
fieldErrors;
|
|
89
|
+
param;
|
|
90
|
+
constructor(raw) {
|
|
91
|
+
const fields = typeof raw.detail === "object" ? raw.detail : raw.errors ?? {};
|
|
92
|
+
const summary = Object.entries(fields).map(([k, v]) => `${k}: ${v.join(", ")}`).join(" | ");
|
|
93
|
+
super(summary || raw.message || "Validation error", "VALIDATION_ERROR", 422, raw);
|
|
94
|
+
this.name = "SanghoValidationError";
|
|
95
|
+
this.fieldErrors = fields;
|
|
96
|
+
}
|
|
97
|
+
};
|
|
98
|
+
var SanghoRateLimitError = class extends SanghoError {
|
|
99
|
+
retryAfter;
|
|
100
|
+
constructor(retryAfter, raw) {
|
|
101
|
+
super(
|
|
102
|
+
raw?.message ?? `Rate limit exceeded.${retryAfter ? ` Retry after ${retryAfter}s.` : ""}`,
|
|
103
|
+
"RATE_LIMIT_ERROR",
|
|
104
|
+
429,
|
|
105
|
+
raw
|
|
106
|
+
);
|
|
107
|
+
this.name = "SanghoRateLimitError";
|
|
108
|
+
this.retryAfter = retryAfter;
|
|
109
|
+
}
|
|
110
|
+
};
|
|
111
|
+
var SanghoIdempotencyError = class extends SanghoError {
|
|
112
|
+
constructor(raw) {
|
|
113
|
+
super(
|
|
114
|
+
"Idempotency key reused with different request parameters.",
|
|
115
|
+
"CONFLICT_ERROR",
|
|
116
|
+
409,
|
|
117
|
+
raw
|
|
118
|
+
);
|
|
119
|
+
this.name = "SanghoIdempotencyError";
|
|
120
|
+
}
|
|
121
|
+
};
|
|
122
|
+
var SanghoNetworkError = class extends SanghoError {
|
|
123
|
+
constructor(message = "Network error. Please check your connection.") {
|
|
124
|
+
super(message, "NETWORK_ERROR");
|
|
125
|
+
this.name = "SanghoNetworkError";
|
|
126
|
+
}
|
|
127
|
+
};
|
|
128
|
+
var SanghoTimeoutError = class extends SanghoError {
|
|
129
|
+
constructor(timeout) {
|
|
130
|
+
super(`Request timed out after ${timeout}ms.`, "TIMEOUT_ERROR");
|
|
131
|
+
this.name = "SanghoTimeoutError";
|
|
132
|
+
}
|
|
133
|
+
};
|
|
134
|
+
|
|
135
|
+
// core/http.ts
|
|
136
|
+
function generateUUID() {
|
|
137
|
+
if (typeof crypto !== "undefined" && crypto.randomUUID) {
|
|
138
|
+
return crypto.randomUUID();
|
|
139
|
+
}
|
|
140
|
+
return "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g, (c) => {
|
|
141
|
+
const r = Math.random() * 16 | 0;
|
|
142
|
+
const v = c === "x" ? r : r & 3 | 8;
|
|
143
|
+
return v.toString(16);
|
|
144
|
+
});
|
|
145
|
+
}
|
|
146
|
+
var SDK_VERSION = "__SDK_VERSION__";
|
|
147
|
+
var HttpClient = class {
|
|
148
|
+
keyType;
|
|
149
|
+
config;
|
|
150
|
+
constructor(config) {
|
|
151
|
+
this.config = config;
|
|
152
|
+
this.keyType = config.apiKey.startsWith("pk_") ? "public" : "secret";
|
|
153
|
+
}
|
|
154
|
+
assertSecretKey(methodName) {
|
|
155
|
+
if (this.keyType === "public") {
|
|
156
|
+
throw new SanghoPublicKeyError(
|
|
157
|
+
`The method "${methodName}" requires a Secret Key or a Terminal Session.`
|
|
158
|
+
);
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
async get(path, params) {
|
|
162
|
+
const url = this.buildURL(path, params);
|
|
163
|
+
return this.request("GET", url);
|
|
164
|
+
}
|
|
165
|
+
async post(path, body, idempotencyKey) {
|
|
166
|
+
const url = this.buildURL(path);
|
|
167
|
+
return this.request("POST", url, body, {
|
|
168
|
+
"Idempotency-Key": idempotencyKey ?? generateUUID()
|
|
169
|
+
});
|
|
170
|
+
}
|
|
171
|
+
async patch(path, body) {
|
|
172
|
+
const url = this.buildURL(path);
|
|
173
|
+
return this.request("PATCH", url, body);
|
|
174
|
+
}
|
|
175
|
+
async put(path, body) {
|
|
176
|
+
const url = this.buildURL(path);
|
|
177
|
+
return this.request("PUT", url, body);
|
|
178
|
+
}
|
|
179
|
+
async delete(path) {
|
|
180
|
+
const url = this.buildURL(path);
|
|
181
|
+
return this.request("DELETE", url);
|
|
182
|
+
}
|
|
183
|
+
async options(path) {
|
|
184
|
+
const url = this.buildURL(path);
|
|
185
|
+
return this.request("OPTIONS", url);
|
|
186
|
+
}
|
|
187
|
+
buildURL(path, params) {
|
|
188
|
+
const base = this.config.baseURL.replace(/\/$/, "");
|
|
189
|
+
const full = `${base}${path}`;
|
|
190
|
+
if (!params || Object.keys(params).length === 0) return full;
|
|
191
|
+
const search = new URLSearchParams();
|
|
192
|
+
for (const [k, v] of Object.entries(params)) {
|
|
193
|
+
if (v !== void 0 && v !== null) {
|
|
194
|
+
search.set(k, String(v));
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
const qs = search.toString();
|
|
198
|
+
return qs ? `${full}?${qs}` : full;
|
|
199
|
+
}
|
|
200
|
+
baseHeaders(extra) {
|
|
201
|
+
return {
|
|
202
|
+
Authorization: `Bearer ${this.config.apiKey}`,
|
|
203
|
+
"Content-Type": "application/json",
|
|
204
|
+
Accept: "application/json",
|
|
205
|
+
"X-Sangho-SDK": `js/${SDK_VERSION}`,
|
|
206
|
+
"X-Sangho-Environment": this.config.sandbox ? "sandbox" : "live",
|
|
207
|
+
...extra
|
|
208
|
+
};
|
|
209
|
+
}
|
|
210
|
+
async request(method, url, body, extraHeaders, attempt = 0) {
|
|
211
|
+
const controller = new AbortController();
|
|
212
|
+
const timer = setTimeout(() => controller.abort(), this.config.timeout);
|
|
213
|
+
try {
|
|
214
|
+
const response = await fetch(url, {
|
|
215
|
+
method,
|
|
216
|
+
headers: this.baseHeaders(extraHeaders),
|
|
217
|
+
signal: controller.signal,
|
|
218
|
+
...body !== void 0 ? { body: JSON.stringify(body) } : {}
|
|
219
|
+
});
|
|
220
|
+
clearTimeout(timer);
|
|
221
|
+
return await this.handleResponse(response);
|
|
222
|
+
} catch (err) {
|
|
223
|
+
clearTimeout(timer);
|
|
224
|
+
if (err instanceof SanghoError) {
|
|
225
|
+
if (this.isRetryable(err) && attempt < this.config.maxRetries) {
|
|
226
|
+
const delay = err instanceof SanghoRateLimitError && err.retryAfter ? err.retryAfter * 1e3 : Math.pow(2, attempt) * 500;
|
|
227
|
+
await this.sleep(delay);
|
|
228
|
+
return this.request(method, url, body, extraHeaders, attempt + 1);
|
|
229
|
+
}
|
|
230
|
+
throw err;
|
|
231
|
+
}
|
|
232
|
+
if (err instanceof DOMException && err.name === "AbortError") {
|
|
233
|
+
throw new SanghoTimeoutError(this.config.timeout);
|
|
234
|
+
}
|
|
235
|
+
if (err instanceof TypeError) {
|
|
236
|
+
if (attempt < this.config.maxRetries) {
|
|
237
|
+
await this.sleep(Math.pow(2, attempt) * 500);
|
|
238
|
+
return this.request(method, url, body, extraHeaders, attempt + 1);
|
|
239
|
+
}
|
|
240
|
+
throw new SanghoNetworkError(err.message);
|
|
241
|
+
}
|
|
242
|
+
throw err;
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
/**
|
|
246
|
+
* Détermine si une SanghoError est transitoire et mérite un retry :
|
|
247
|
+
* 429 (rate limit) ou 5xx (erreur serveur). Jamais les 4xx restants
|
|
248
|
+
* (400/401/403/404/409/422) — ce sont des erreurs permanentes côté client.
|
|
249
|
+
*/
|
|
250
|
+
isRetryable(err) {
|
|
251
|
+
if (err instanceof SanghoRateLimitError) return true;
|
|
252
|
+
return typeof err.statusCode === "number" && err.statusCode >= 500;
|
|
253
|
+
}
|
|
254
|
+
async handleResponse(response) {
|
|
255
|
+
if (response.status === 204) return void 0;
|
|
256
|
+
let data;
|
|
257
|
+
try {
|
|
258
|
+
data = await response.json();
|
|
259
|
+
} catch {
|
|
260
|
+
data = {};
|
|
261
|
+
}
|
|
262
|
+
if (response.ok) return data;
|
|
263
|
+
const raw = data;
|
|
264
|
+
const errorResponse = {
|
|
265
|
+
message: raw["message"] ?? raw["detail"] ?? "API error",
|
|
266
|
+
type: raw["type"],
|
|
267
|
+
code: raw["code"],
|
|
268
|
+
detail: raw["detail"],
|
|
269
|
+
errors: raw["errors"],
|
|
270
|
+
status: response.status,
|
|
271
|
+
param: raw["param"]
|
|
272
|
+
};
|
|
273
|
+
const message = errorResponse.message;
|
|
274
|
+
const code = errorResponse.code?.toLowerCase();
|
|
275
|
+
switch (response.status) {
|
|
276
|
+
case 401:
|
|
277
|
+
throw new SanghoAuthError(message, errorResponse);
|
|
278
|
+
case 403:
|
|
279
|
+
if (code === "public_key_not_allowed") {
|
|
280
|
+
throw new SanghoPublicKeyError(message, errorResponse);
|
|
281
|
+
}
|
|
282
|
+
throw new SanghoPermissionError(message, errorResponse);
|
|
283
|
+
case 404:
|
|
284
|
+
throw new SanghoNotFoundError(message, errorResponse);
|
|
285
|
+
case 409:
|
|
286
|
+
throw new SanghoIdempotencyError(errorResponse);
|
|
287
|
+
case 422:
|
|
288
|
+
throw new SanghoValidationError(errorResponse);
|
|
289
|
+
case 429: {
|
|
290
|
+
const retryAfter = raw["retry_after"] ?? Number(response.headers.get("Retry-After") ?? 60);
|
|
291
|
+
throw new SanghoRateLimitError(retryAfter, errorResponse);
|
|
292
|
+
}
|
|
293
|
+
default:
|
|
294
|
+
throw new SanghoError(message, "API_ERROR", response.status, errorResponse);
|
|
295
|
+
}
|
|
296
|
+
}
|
|
297
|
+
sleep(ms) {
|
|
298
|
+
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
299
|
+
}
|
|
300
|
+
};
|
|
301
|
+
|
|
302
|
+
// modules/base.ts
|
|
303
|
+
var BaseModule = class {
|
|
304
|
+
/** Client HTTP partagé — ne jamais exposer publiquement. */
|
|
305
|
+
http;
|
|
306
|
+
constructor(http) {
|
|
307
|
+
this.http = http;
|
|
308
|
+
}
|
|
309
|
+
};
|
|
310
|
+
|
|
311
|
+
// modules/account.ts
|
|
312
|
+
var AccountModule = class extends BaseModule {
|
|
313
|
+
constructor(http) {
|
|
314
|
+
super(http);
|
|
315
|
+
this.http = http;
|
|
316
|
+
}
|
|
317
|
+
account = {
|
|
318
|
+
retrieve: () => this._retrieve()
|
|
319
|
+
};
|
|
320
|
+
/**
|
|
321
|
+
* Retourne l'application associée à la clé secrète utilisée pour la requête.
|
|
322
|
+
* Équivalent de `apps.retrieve(id)` sans avoir à connaître l'ID au préalable —
|
|
323
|
+
* pratique comme "who am I" / health-check d'introspection.
|
|
324
|
+
*/
|
|
325
|
+
_retrieve() {
|
|
326
|
+
this.http.assertSecretKey("account.retrieve");
|
|
327
|
+
return this.http.get("/account/");
|
|
328
|
+
}
|
|
329
|
+
};
|
|
330
|
+
|
|
331
|
+
// modules/apps.ts
|
|
332
|
+
var AppsModule = class extends BaseModule {
|
|
333
|
+
constructor(http) {
|
|
334
|
+
super(http);
|
|
335
|
+
this.http = http;
|
|
336
|
+
}
|
|
337
|
+
apps = {
|
|
338
|
+
list: (criteria) => this._list(criteria),
|
|
339
|
+
retrieve: (id) => this._retrieve(id),
|
|
340
|
+
create: (payloads) => this._create(payloads),
|
|
341
|
+
update: (id, payloads) => this._update(id, payloads),
|
|
342
|
+
delete: (id) => this._delete(id),
|
|
343
|
+
keys: (id) => this._keys(id),
|
|
344
|
+
options: () => this._options()
|
|
345
|
+
};
|
|
346
|
+
_list(criteria) {
|
|
347
|
+
this.http.assertSecretKey("apps.list");
|
|
348
|
+
return this.http.get("/apps/", criteria);
|
|
349
|
+
}
|
|
350
|
+
_retrieve(id) {
|
|
351
|
+
this.http.assertSecretKey("apps.retrieve");
|
|
352
|
+
return this.http.get(`/apps/${id}/`);
|
|
353
|
+
}
|
|
354
|
+
_create(payloads) {
|
|
355
|
+
this.http.assertSecretKey("apps.create");
|
|
356
|
+
return this.http.post("/apps/", payloads);
|
|
357
|
+
}
|
|
358
|
+
_update(id, payloads) {
|
|
359
|
+
this.http.assertSecretKey("apps.update");
|
|
360
|
+
return this.http.patch(`/apps/${id}/`, payloads);
|
|
361
|
+
}
|
|
362
|
+
_delete(id) {
|
|
363
|
+
this.http.assertSecretKey("apps.delete");
|
|
364
|
+
return this.http.delete(`/apps/${id}/`);
|
|
365
|
+
}
|
|
366
|
+
_keys(id) {
|
|
367
|
+
this.http.assertSecretKey("apps.keys");
|
|
368
|
+
return this.http.get(`/apps/${id}/keys/`);
|
|
369
|
+
}
|
|
370
|
+
_options() {
|
|
371
|
+
return this.http.options("/apps/");
|
|
372
|
+
}
|
|
373
|
+
};
|
|
374
|
+
|
|
375
|
+
// modules/addresses.ts
|
|
376
|
+
var AddressesModule = class extends BaseModule {
|
|
377
|
+
constructor(http) {
|
|
378
|
+
super(http);
|
|
379
|
+
this.http = http;
|
|
380
|
+
}
|
|
381
|
+
addresses = {
|
|
382
|
+
list: (criteria) => this._list(criteria),
|
|
383
|
+
retrieve: (id) => this._retrieve(id),
|
|
384
|
+
create: (payloads) => this._create(payloads),
|
|
385
|
+
update: (id, payloads) => this._update(id, payloads),
|
|
386
|
+
delete: (id) => this._delete(id),
|
|
387
|
+
options: () => this._options()
|
|
388
|
+
};
|
|
389
|
+
_list(criteria) {
|
|
390
|
+
this.http.assertSecretKey("addresses.list");
|
|
391
|
+
return this.http.get("/addresses/", criteria);
|
|
392
|
+
}
|
|
393
|
+
_retrieve(id) {
|
|
394
|
+
this.http.assertSecretKey("addresses.retrieve");
|
|
395
|
+
return this.http.get(`/addresses/${id}/`);
|
|
396
|
+
}
|
|
397
|
+
_create(payloads) {
|
|
398
|
+
this.http.assertSecretKey("addresses.create");
|
|
399
|
+
return this.http.post("/addresses/", payloads);
|
|
400
|
+
}
|
|
401
|
+
_update(id, payloads) {
|
|
402
|
+
this.http.assertSecretKey("addresses.update");
|
|
403
|
+
return this.http.patch(`/addresses/${id}/`, payloads);
|
|
404
|
+
}
|
|
405
|
+
_delete(id) {
|
|
406
|
+
this.http.assertSecretKey("addresses.delete");
|
|
407
|
+
return this.http.delete(`/addresses/${id}/`);
|
|
408
|
+
}
|
|
409
|
+
_options() {
|
|
410
|
+
return this.http.options("/addresses/");
|
|
411
|
+
}
|
|
412
|
+
};
|
|
413
|
+
|
|
414
|
+
// modules/customers.ts
|
|
415
|
+
var CustomersModule = class extends BaseModule {
|
|
416
|
+
constructor(http) {
|
|
417
|
+
super(http);
|
|
418
|
+
this.http = http;
|
|
419
|
+
}
|
|
420
|
+
customers = {
|
|
421
|
+
list: (criteria) => this._list(criteria),
|
|
422
|
+
retrieve: (id) => this._retrieve(id),
|
|
423
|
+
create: (payloads) => this._create(payloads),
|
|
424
|
+
update: (id, payloads) => this._update(id, payloads),
|
|
425
|
+
delete: (id) => this._delete(id),
|
|
426
|
+
listTransactions: (id, criteria) => this._listTransactions(id, criteria),
|
|
427
|
+
listPaymentMethods: (id) => this._listPaymentMethods(id),
|
|
428
|
+
options: () => this._options()
|
|
429
|
+
};
|
|
430
|
+
_list(criteria) {
|
|
431
|
+
this.http.assertSecretKey("customers.list");
|
|
432
|
+
return this.http.get("/customers/", criteria);
|
|
433
|
+
}
|
|
434
|
+
_retrieve(id) {
|
|
435
|
+
this.http.assertSecretKey("customers.retrieve");
|
|
436
|
+
return this.http.get(`/customers/${id}/`);
|
|
437
|
+
}
|
|
438
|
+
_create(payloads) {
|
|
439
|
+
this.http.assertSecretKey("customers.create");
|
|
440
|
+
return this.http.post("/customers/", payloads);
|
|
441
|
+
}
|
|
442
|
+
_update(id, payloads) {
|
|
443
|
+
this.http.assertSecretKey("customers.update");
|
|
444
|
+
return this.http.patch(`/customers/${id}/`, payloads);
|
|
445
|
+
}
|
|
446
|
+
_delete(id) {
|
|
447
|
+
this.http.assertSecretKey("customers.delete");
|
|
448
|
+
return this.http.delete(`/customers/${id}/`);
|
|
449
|
+
}
|
|
450
|
+
_listTransactions(id, criteria) {
|
|
451
|
+
this.http.assertSecretKey("customers.listTransactions");
|
|
452
|
+
return this.http.get(
|
|
453
|
+
`/customers/${id}/transactions/`,
|
|
454
|
+
criteria
|
|
455
|
+
);
|
|
456
|
+
}
|
|
457
|
+
_listPaymentMethods(id) {
|
|
458
|
+
this.http.assertSecretKey("customers.listPaymentMethods");
|
|
459
|
+
return this.http.get(
|
|
460
|
+
`/customers/${id}/payment-methods/`
|
|
461
|
+
);
|
|
462
|
+
}
|
|
463
|
+
_options() {
|
|
464
|
+
return this.http.options("/customers/");
|
|
465
|
+
}
|
|
466
|
+
};
|
|
467
|
+
|
|
468
|
+
// modules/products.ts
|
|
469
|
+
var ProductsModule = class extends BaseModule {
|
|
470
|
+
constructor(http) {
|
|
471
|
+
super(http);
|
|
472
|
+
this.http = http;
|
|
473
|
+
}
|
|
474
|
+
products = {
|
|
475
|
+
list: (criteria) => this._list(criteria),
|
|
476
|
+
retrieve: (id) => this._retrieve(id),
|
|
477
|
+
create: (payloads) => this._create(payloads),
|
|
478
|
+
update: (id, payloads) => this._update(id, payloads),
|
|
479
|
+
delete: (id) => this._delete(id),
|
|
480
|
+
options: () => this._options()
|
|
481
|
+
};
|
|
482
|
+
_list(criteria) {
|
|
483
|
+
this.http.assertSecretKey("products.list");
|
|
484
|
+
return this.http.get("/products/", criteria);
|
|
485
|
+
}
|
|
486
|
+
_retrieve(id) {
|
|
487
|
+
this.http.assertSecretKey("products.retrieve");
|
|
488
|
+
return this.http.get(`/products/${id}/`);
|
|
489
|
+
}
|
|
490
|
+
_create(payloads) {
|
|
491
|
+
this.http.assertSecretKey("products.create");
|
|
492
|
+
return this.http.post("/products/", payloads);
|
|
493
|
+
}
|
|
494
|
+
_update(id, payloads) {
|
|
495
|
+
this.http.assertSecretKey("products.update");
|
|
496
|
+
return this.http.patch(`/products/${id}/`, payloads);
|
|
497
|
+
}
|
|
498
|
+
_delete(id) {
|
|
499
|
+
this.http.assertSecretKey("products.delete");
|
|
500
|
+
return this.http.delete(`/products/${id}/`);
|
|
501
|
+
}
|
|
502
|
+
_options() {
|
|
503
|
+
return this.http.options("/products/");
|
|
504
|
+
}
|
|
505
|
+
};
|
|
506
|
+
|
|
507
|
+
// modules/payment-intents.ts
|
|
508
|
+
var PaymentIntentsModule = class extends BaseModule {
|
|
509
|
+
constructor(http) {
|
|
510
|
+
super(http);
|
|
511
|
+
this.http = http;
|
|
512
|
+
}
|
|
513
|
+
paymentIntents = {
|
|
514
|
+
list: (criteria) => this._list(criteria),
|
|
515
|
+
retrieve: (id) => this._retrieve(id),
|
|
516
|
+
create: (payloads) => this._create(payloads),
|
|
517
|
+
update: (id, payloads) => this._update(id, payloads),
|
|
518
|
+
delete: (id) => this._delete(id),
|
|
519
|
+
confirm: (id, payloads) => this._confirm(id, payloads),
|
|
520
|
+
capture: (id, payloads) => this._capture(id, payloads),
|
|
521
|
+
cancel: (id, payloads) => this._cancel(id, payloads),
|
|
522
|
+
options: () => this._options()
|
|
523
|
+
};
|
|
524
|
+
_list(criteria) {
|
|
525
|
+
this.http.assertSecretKey("paymentIntents.list");
|
|
526
|
+
return this.http.get("/payment-intents/", criteria);
|
|
527
|
+
}
|
|
528
|
+
_retrieve(id) {
|
|
529
|
+
this.http.assertSecretKey("paymentIntents.retrieve");
|
|
530
|
+
return this.http.get(`/payment-intents/${id}/`);
|
|
531
|
+
}
|
|
532
|
+
_create(payloads) {
|
|
533
|
+
this.http.assertSecretKey("paymentIntents.create");
|
|
534
|
+
return this.http.post("/payment-intents/", payloads);
|
|
535
|
+
}
|
|
536
|
+
_update(id, payloads) {
|
|
537
|
+
this.http.assertSecretKey("paymentIntents.update");
|
|
538
|
+
return this.http.patch(`/payment-intents/${id}/`, payloads);
|
|
539
|
+
}
|
|
540
|
+
_delete(id) {
|
|
541
|
+
this.http.assertSecretKey("paymentIntents.delete");
|
|
542
|
+
return this.http.delete(`/payment-intents/${id}/`);
|
|
543
|
+
}
|
|
544
|
+
_confirm(id, payloads) {
|
|
545
|
+
this.http.assertSecretKey("paymentIntents.confirm");
|
|
546
|
+
return this.http.post(`/payment-intents/${id}/confirm/`, payloads ?? {});
|
|
547
|
+
}
|
|
548
|
+
_capture(id, payloads) {
|
|
549
|
+
this.http.assertSecretKey("paymentIntents.capture");
|
|
550
|
+
return this.http.post(`/payment-intents/${id}/capture/`, payloads ?? {});
|
|
551
|
+
}
|
|
552
|
+
_cancel(id, payloads) {
|
|
553
|
+
this.http.assertSecretKey("paymentIntents.cancel");
|
|
554
|
+
return this.http.post(`/payment-intents/${id}/cancel/`, payloads ?? {});
|
|
555
|
+
}
|
|
556
|
+
_options() {
|
|
557
|
+
return this.http.options("/payment-intents/");
|
|
558
|
+
}
|
|
559
|
+
};
|
|
560
|
+
|
|
561
|
+
// modules/transactions.ts
|
|
562
|
+
var TransactionsModule = class extends BaseModule {
|
|
563
|
+
constructor(http) {
|
|
564
|
+
super(http);
|
|
565
|
+
this.http = http;
|
|
566
|
+
}
|
|
567
|
+
transactions = {
|
|
568
|
+
list: (criteria) => this._list(criteria),
|
|
569
|
+
retrieve: (id) => this._retrieve(id),
|
|
570
|
+
update: (id, payloads) => this._update(id, payloads),
|
|
571
|
+
cancel: (id) => this._cancel(id),
|
|
572
|
+
options: () => this._options()
|
|
573
|
+
};
|
|
574
|
+
_list(criteria) {
|
|
575
|
+
this.http.assertSecretKey("transactions.list");
|
|
576
|
+
return this.http.get("/transactions/", criteria);
|
|
577
|
+
}
|
|
578
|
+
_retrieve(id) {
|
|
579
|
+
this.http.assertSecretKey("transactions.retrieve");
|
|
580
|
+
return this.http.get(`/transactions/${id}/`);
|
|
581
|
+
}
|
|
582
|
+
_update(id, payloads) {
|
|
583
|
+
this.http.assertSecretKey("transactions.update");
|
|
584
|
+
return this.http.patch(`/transactions/${id}/`, payloads);
|
|
585
|
+
}
|
|
586
|
+
_cancel(id) {
|
|
587
|
+
this.http.assertSecretKey("transactions.cancel");
|
|
588
|
+
return this.http.post(`/transactions/${id}/cancel/`, {});
|
|
589
|
+
}
|
|
590
|
+
_options() {
|
|
591
|
+
return this.http.options("/transactions/");
|
|
592
|
+
}
|
|
593
|
+
};
|
|
594
|
+
|
|
595
|
+
// modules/refunds.ts
|
|
596
|
+
var RefundsModule = class extends BaseModule {
|
|
597
|
+
constructor(http) {
|
|
598
|
+
super(http);
|
|
599
|
+
this.http = http;
|
|
600
|
+
}
|
|
601
|
+
refunds = {
|
|
602
|
+
list: (criteria) => this._list(criteria),
|
|
603
|
+
retrieve: (id) => this._retrieve(id),
|
|
604
|
+
create: (payloads) => this._create(payloads),
|
|
605
|
+
cancel: (id) => this._cancel(id),
|
|
606
|
+
options: () => this._options()
|
|
607
|
+
};
|
|
608
|
+
_list(criteria) {
|
|
609
|
+
this.http.assertSecretKey("refunds.list");
|
|
610
|
+
return this.http.get("/refunds/", criteria);
|
|
611
|
+
}
|
|
612
|
+
_retrieve(id) {
|
|
613
|
+
this.http.assertSecretKey("refunds.retrieve");
|
|
614
|
+
return this.http.get(`/refunds/${id}/`);
|
|
615
|
+
}
|
|
616
|
+
_create(payloads) {
|
|
617
|
+
this.http.assertSecretKey("refunds.create");
|
|
618
|
+
return this.http.post("/refunds/", payloads);
|
|
619
|
+
}
|
|
620
|
+
_cancel(id) {
|
|
621
|
+
this.http.assertSecretKey("refunds.cancel");
|
|
622
|
+
return this.http.post(`/refunds/${id}/cancel/`, {});
|
|
623
|
+
}
|
|
624
|
+
_options() {
|
|
625
|
+
return this.http.options("/refunds/");
|
|
626
|
+
}
|
|
627
|
+
};
|
|
628
|
+
|
|
629
|
+
// modules/invoices.ts
|
|
630
|
+
var InvoicesModule = class extends BaseModule {
|
|
631
|
+
constructor(http) {
|
|
632
|
+
super(http);
|
|
633
|
+
this.http = http;
|
|
634
|
+
}
|
|
635
|
+
invoices = {
|
|
636
|
+
list: (criteria) => this._list(criteria),
|
|
637
|
+
retrieve: (id) => this._retrieve(id),
|
|
638
|
+
create: (payloads) => this._create(payloads),
|
|
639
|
+
update: (id, payloads) => this._update(id, payloads),
|
|
640
|
+
delete: (id) => this._delete(id),
|
|
641
|
+
send: (id) => this._send(id),
|
|
642
|
+
pay: (id) => this._pay(id),
|
|
643
|
+
void: (id) => this._void(id),
|
|
644
|
+
markUncollectible: (id) => this._markUncollectible(id),
|
|
645
|
+
getPdfUrl: (id) => this._getPdfUrl(id),
|
|
646
|
+
options: () => this._options()
|
|
647
|
+
};
|
|
648
|
+
_list(criteria) {
|
|
649
|
+
this.http.assertSecretKey("invoices.list");
|
|
650
|
+
return this.http.get("/invoices/", criteria);
|
|
651
|
+
}
|
|
652
|
+
_retrieve(id) {
|
|
653
|
+
this.http.assertSecretKey("invoices.retrieve");
|
|
654
|
+
return this.http.get(`/invoices/${id}/`);
|
|
655
|
+
}
|
|
656
|
+
_create(payloads) {
|
|
657
|
+
this.http.assertSecretKey("invoices.create");
|
|
658
|
+
return this.http.post("/invoices/", payloads);
|
|
659
|
+
}
|
|
660
|
+
_update(id, payloads) {
|
|
661
|
+
this.http.assertSecretKey("invoices.update");
|
|
662
|
+
return this.http.patch(`/invoices/${id}/`, payloads);
|
|
663
|
+
}
|
|
664
|
+
_delete(id) {
|
|
665
|
+
this.http.assertSecretKey("invoices.delete");
|
|
666
|
+
return this.http.delete(`/invoices/${id}/`);
|
|
667
|
+
}
|
|
668
|
+
_send(id) {
|
|
669
|
+
this.http.assertSecretKey("invoices.send");
|
|
670
|
+
return this.http.post(`/invoices/${id}/send/`, {});
|
|
671
|
+
}
|
|
672
|
+
_pay(id) {
|
|
673
|
+
this.http.assertSecretKey("invoices.pay");
|
|
674
|
+
return this.http.post(`/invoices/${id}/pay/`, {});
|
|
675
|
+
}
|
|
676
|
+
_void(id) {
|
|
677
|
+
this.http.assertSecretKey("invoices.void");
|
|
678
|
+
return this.http.post(`/invoices/${id}/void/`, {});
|
|
679
|
+
}
|
|
680
|
+
_markUncollectible(id) {
|
|
681
|
+
this.http.assertSecretKey("invoices.markUncollectible");
|
|
682
|
+
return this.http.post(`/invoices/${id}/mark-uncollectible/`, {});
|
|
683
|
+
}
|
|
684
|
+
_getPdfUrl(id) {
|
|
685
|
+
this.http.assertSecretKey("invoices.getPdfUrl");
|
|
686
|
+
return this.http.get(`/invoices/${id}/pdf/`);
|
|
687
|
+
}
|
|
688
|
+
_options() {
|
|
689
|
+
return this.http.options("/invoices/");
|
|
690
|
+
}
|
|
691
|
+
};
|
|
692
|
+
|
|
693
|
+
// modules/payment-links.ts
|
|
694
|
+
var PaymentLinksModule = class extends BaseModule {
|
|
695
|
+
constructor(http) {
|
|
696
|
+
super(http);
|
|
697
|
+
this.http = http;
|
|
698
|
+
}
|
|
699
|
+
paymentLinks = {
|
|
700
|
+
list: (criteria) => this._list(criteria),
|
|
701
|
+
retrieve: (id) => this._retrieve(id),
|
|
702
|
+
create: (payloads) => this._create(payloads),
|
|
703
|
+
update: (id, payloads) => this._update(id, payloads),
|
|
704
|
+
delete: (id) => this._delete(id),
|
|
705
|
+
archive: (id) => this._archive(id),
|
|
706
|
+
restore: (id) => this._restore(id),
|
|
707
|
+
options: () => this._options()
|
|
708
|
+
};
|
|
709
|
+
_list(criteria) {
|
|
710
|
+
this.http.assertSecretKey("paymentLinks.list");
|
|
711
|
+
return this.http.get("/payment-links/", criteria);
|
|
712
|
+
}
|
|
713
|
+
_retrieve(id) {
|
|
714
|
+
this.http.assertSecretKey("paymentLinks.retrieve");
|
|
715
|
+
return this.http.get(`/payment-links/${id}/`);
|
|
716
|
+
}
|
|
717
|
+
_create(payloads) {
|
|
718
|
+
this.http.assertSecretKey("paymentLinks.create");
|
|
719
|
+
return this.http.post("/payment-links/", payloads);
|
|
720
|
+
}
|
|
721
|
+
_update(id, payloads) {
|
|
722
|
+
this.http.assertSecretKey("paymentLinks.update");
|
|
723
|
+
return this.http.patch(`/payment-links/${id}/`, payloads);
|
|
724
|
+
}
|
|
725
|
+
_delete(id) {
|
|
726
|
+
this.http.assertSecretKey("paymentLinks.delete");
|
|
727
|
+
return this.http.delete(`/payment-links/${id}/`);
|
|
728
|
+
}
|
|
729
|
+
_archive(id) {
|
|
730
|
+
this.http.assertSecretKey("paymentLinks.archive");
|
|
731
|
+
return this.http.post(`/payment-links/${id}/archive/`, {});
|
|
732
|
+
}
|
|
733
|
+
_restore(id) {
|
|
734
|
+
this.http.assertSecretKey("paymentLinks.restore");
|
|
735
|
+
return this.http.post(`/payment-links/${id}/restore/`, {});
|
|
736
|
+
}
|
|
737
|
+
_options() {
|
|
738
|
+
return this.http.options("/payment-links/");
|
|
739
|
+
}
|
|
740
|
+
};
|
|
741
|
+
|
|
742
|
+
// modules/checkout-sessions.ts
|
|
743
|
+
var CheckoutSessionsModule = class extends BaseModule {
|
|
744
|
+
constructor(http) {
|
|
745
|
+
super(http);
|
|
746
|
+
this.http = http;
|
|
747
|
+
}
|
|
748
|
+
checkoutSessions = {
|
|
749
|
+
list: (criteria) => this._list(criteria),
|
|
750
|
+
retrieve: (id) => this._retrieve(id),
|
|
751
|
+
create: (payloads) => this._create(payloads),
|
|
752
|
+
expire: (id) => this._expire(id),
|
|
753
|
+
delete: (id) => this._delete(id),
|
|
754
|
+
options: () => this._options()
|
|
755
|
+
};
|
|
756
|
+
_list(criteria) {
|
|
757
|
+
this.http.assertSecretKey("checkoutSessions.list");
|
|
758
|
+
return this.http.get("/checkout-sessions/", criteria);
|
|
759
|
+
}
|
|
760
|
+
_retrieve(id) {
|
|
761
|
+
return this.http.get(`/checkout-sessions/${id}/`);
|
|
762
|
+
}
|
|
763
|
+
_create(payloads) {
|
|
764
|
+
this.http.assertSecretKey("checkoutSessions.create");
|
|
765
|
+
return this.http.post("/checkout-sessions/", payloads);
|
|
766
|
+
}
|
|
767
|
+
_expire(id) {
|
|
768
|
+
this.http.assertSecretKey("checkoutSessions.expire");
|
|
769
|
+
return this.http.post(`/checkout-sessions/${id}/expire/`, {});
|
|
770
|
+
}
|
|
771
|
+
_delete(id) {
|
|
772
|
+
this.http.assertSecretKey("checkoutSessions.delete");
|
|
773
|
+
return this.http.delete(`/checkout-sessions/${id}/`);
|
|
774
|
+
}
|
|
775
|
+
_options() {
|
|
776
|
+
return this.http.options("/checkout-sessions/");
|
|
777
|
+
}
|
|
778
|
+
};
|
|
779
|
+
|
|
780
|
+
// modules/subscriptions.ts
|
|
781
|
+
var SubscriptionsModule = class extends BaseModule {
|
|
782
|
+
constructor(http) {
|
|
783
|
+
super(http);
|
|
784
|
+
this.http = http;
|
|
785
|
+
}
|
|
786
|
+
subscriptions = {
|
|
787
|
+
list: (criteria) => this._list(criteria),
|
|
788
|
+
retrieve: (id) => this._retrieve(id),
|
|
789
|
+
create: (payloads) => this._create(payloads),
|
|
790
|
+
update: (id, payloads) => this._update(id, payloads),
|
|
791
|
+
cancel: (id, payloads) => this._cancel(id, payloads),
|
|
792
|
+
reactivate: (id) => this._reactivate(id),
|
|
793
|
+
pause: (id) => this._pause(id),
|
|
794
|
+
resume: (id) => this._resume(id),
|
|
795
|
+
options: () => this._options()
|
|
796
|
+
};
|
|
797
|
+
_list(criteria) {
|
|
798
|
+
this.http.assertSecretKey("subscriptions.list");
|
|
799
|
+
return this.http.get("/subscriptions/", criteria);
|
|
800
|
+
}
|
|
801
|
+
_retrieve(id) {
|
|
802
|
+
this.http.assertSecretKey("subscriptions.retrieve");
|
|
803
|
+
return this.http.get(`/subscriptions/${id}/`);
|
|
804
|
+
}
|
|
805
|
+
_create(payloads) {
|
|
806
|
+
this.http.assertSecretKey("subscriptions.create");
|
|
807
|
+
return this.http.post("/subscriptions/", payloads);
|
|
808
|
+
}
|
|
809
|
+
_update(id, payloads) {
|
|
810
|
+
this.http.assertSecretKey("subscriptions.update");
|
|
811
|
+
return this.http.patch(`/subscriptions/${id}/`, payloads);
|
|
812
|
+
}
|
|
813
|
+
_cancel(id, payloads) {
|
|
814
|
+
this.http.assertSecretKey("subscriptions.cancel");
|
|
815
|
+
return this.http.post(`/subscriptions/${id}/cancel/`, payloads ?? {});
|
|
816
|
+
}
|
|
817
|
+
_reactivate(id) {
|
|
818
|
+
this.http.assertSecretKey("subscriptions.reactivate");
|
|
819
|
+
return this.http.post(`/subscriptions/${id}/reactivate/`, {});
|
|
820
|
+
}
|
|
821
|
+
_pause(id) {
|
|
822
|
+
this.http.assertSecretKey("subscriptions.pause");
|
|
823
|
+
return this.http.post(`/subscriptions/${id}/pause/`, {});
|
|
824
|
+
}
|
|
825
|
+
_resume(id) {
|
|
826
|
+
this.http.assertSecretKey("subscriptions.resume");
|
|
827
|
+
return this.http.post(`/subscriptions/${id}/resume/`, {});
|
|
828
|
+
}
|
|
829
|
+
_options() {
|
|
830
|
+
return this.http.options("/subscriptions/");
|
|
831
|
+
}
|
|
832
|
+
};
|
|
833
|
+
|
|
834
|
+
// modules/payment-methods.ts
|
|
835
|
+
var PaymentMethodsModule = class extends BaseModule {
|
|
836
|
+
constructor(http) {
|
|
837
|
+
super(http);
|
|
838
|
+
this.http = http;
|
|
839
|
+
}
|
|
840
|
+
paymentMethods = {
|
|
841
|
+
list: (criteria) => this._list(criteria),
|
|
842
|
+
retrieve: (id) => this._retrieve(id),
|
|
843
|
+
attach: (id, payloads) => this._attach(id, payloads),
|
|
844
|
+
detach: (id) => this._detach(id),
|
|
845
|
+
setDefault: (id) => this._setDefault(id),
|
|
846
|
+
options: () => this._options()
|
|
847
|
+
};
|
|
848
|
+
_list(criteria) {
|
|
849
|
+
this.http.assertSecretKey("paymentMethods.list");
|
|
850
|
+
return this.http.get("/payment-methods/", criteria);
|
|
851
|
+
}
|
|
852
|
+
_retrieve(id) {
|
|
853
|
+
this.http.assertSecretKey("paymentMethods.retrieve");
|
|
854
|
+
return this.http.get(`/payment-methods/${id}/`);
|
|
855
|
+
}
|
|
856
|
+
_attach(id, payloads) {
|
|
857
|
+
this.http.assertSecretKey("paymentMethods.attach");
|
|
858
|
+
return this.http.post(`/payment-methods/${id}/attach/`, payloads);
|
|
859
|
+
}
|
|
860
|
+
_detach(id) {
|
|
861
|
+
this.http.assertSecretKey("paymentMethods.detach");
|
|
862
|
+
return this.http.post(`/payment-methods/${id}/detach/`, {});
|
|
863
|
+
}
|
|
864
|
+
_setDefault(id) {
|
|
865
|
+
this.http.assertSecretKey("paymentMethods.setDefault");
|
|
866
|
+
return this.http.post(`/payment-methods/${id}/set-default/`, {});
|
|
867
|
+
}
|
|
868
|
+
_options() {
|
|
869
|
+
return this.http.options("/payment-methods/");
|
|
870
|
+
}
|
|
871
|
+
};
|
|
872
|
+
|
|
873
|
+
// modules/receipts.ts
|
|
874
|
+
var ReceiptsModule = class extends BaseModule {
|
|
875
|
+
constructor(http) {
|
|
876
|
+
super(http);
|
|
877
|
+
this.http = http;
|
|
878
|
+
}
|
|
879
|
+
receipts = {
|
|
880
|
+
list: (criteria) => this._list(criteria),
|
|
881
|
+
retrieve: (id) => this._retrieve(id),
|
|
882
|
+
getPdfUrl: (id) => this._getPdfUrl(id),
|
|
883
|
+
options: () => this._options()
|
|
884
|
+
};
|
|
885
|
+
_list(criteria) {
|
|
886
|
+
this.http.assertSecretKey("receipts.list");
|
|
887
|
+
return this.http.get("/receipts/", criteria);
|
|
888
|
+
}
|
|
889
|
+
_retrieve(id) {
|
|
890
|
+
this.http.assertSecretKey("receipts.retrieve");
|
|
891
|
+
return this.http.get(`/receipts/${id}/`);
|
|
892
|
+
}
|
|
893
|
+
_getPdfUrl(id) {
|
|
894
|
+
this.http.assertSecretKey("receipts.getPdfUrl");
|
|
895
|
+
return this.http.get(`/receipts/${id}/pdf/`);
|
|
896
|
+
}
|
|
897
|
+
_options() {
|
|
898
|
+
return this.http.options("/receipts/");
|
|
899
|
+
}
|
|
900
|
+
};
|
|
901
|
+
|
|
902
|
+
// modules/webhooks.ts
|
|
903
|
+
var WebhooksModule = class extends BaseModule {
|
|
904
|
+
constructor(http) {
|
|
905
|
+
super(http);
|
|
906
|
+
this.http = http;
|
|
907
|
+
}
|
|
908
|
+
webhooks = {
|
|
909
|
+
list: (criteria) => this._list(criteria),
|
|
910
|
+
retrieve: (id) => this._retrieve(id),
|
|
911
|
+
create: (payloads) => this._create(payloads),
|
|
912
|
+
update: (id, payloads) => this._update(id, payloads),
|
|
913
|
+
delete: (id) => this._delete(id),
|
|
914
|
+
disable: (id) => this._disable(id),
|
|
915
|
+
enable: (id) => this._enable(id),
|
|
916
|
+
rollSecret: (id) => this._rollSecret(id),
|
|
917
|
+
sendTestEvent: (id) => this._sendTestEvent(id),
|
|
918
|
+
listDeliveries: (id, criteria) => this._listDeliveries(id, criteria),
|
|
919
|
+
retrieveDelivery: (webhookId, deliveryId) => this._retrieveDelivery(webhookId, deliveryId),
|
|
920
|
+
retryDelivery: (webhookId, deliveryId) => this._retryDelivery(webhookId, deliveryId),
|
|
921
|
+
options: () => this._options()
|
|
922
|
+
};
|
|
923
|
+
_list(criteria) {
|
|
924
|
+
this.http.assertSecretKey("webhooks.list");
|
|
925
|
+
return this.http.get("/webhooks/", criteria);
|
|
926
|
+
}
|
|
927
|
+
_retrieve(id) {
|
|
928
|
+
this.http.assertSecretKey("webhooks.retrieve");
|
|
929
|
+
return this.http.get(`/webhooks/${id}/`);
|
|
930
|
+
}
|
|
931
|
+
_create(payloads) {
|
|
932
|
+
this.http.assertSecretKey("webhooks.create");
|
|
933
|
+
return this.http.post("/webhooks/", payloads);
|
|
934
|
+
}
|
|
935
|
+
_update(id, payloads) {
|
|
936
|
+
this.http.assertSecretKey("webhooks.update");
|
|
937
|
+
return this.http.patch(`/webhooks/${id}/`, payloads);
|
|
938
|
+
}
|
|
939
|
+
_delete(id) {
|
|
940
|
+
this.http.assertSecretKey("webhooks.delete");
|
|
941
|
+
return this.http.delete(`/webhooks/${id}/`);
|
|
942
|
+
}
|
|
943
|
+
_disable(id) {
|
|
944
|
+
this.http.assertSecretKey("webhooks.disable");
|
|
945
|
+
return this.http.post(`/webhooks/${id}/disable/`, {});
|
|
946
|
+
}
|
|
947
|
+
_enable(id) {
|
|
948
|
+
this.http.assertSecretKey("webhooks.enable");
|
|
949
|
+
return this.http.post(`/webhooks/${id}/enable/`, {});
|
|
950
|
+
}
|
|
951
|
+
_rollSecret(id) {
|
|
952
|
+
this.http.assertSecretKey("webhooks.rollSecret");
|
|
953
|
+
return this.http.post(`/webhooks/${id}/roll-secret/`, {});
|
|
954
|
+
}
|
|
955
|
+
_sendTestEvent(id) {
|
|
956
|
+
this.http.assertSecretKey("webhooks.sendTestEvent");
|
|
957
|
+
return this.http.post(`/webhooks/${id}/test/`, {});
|
|
958
|
+
}
|
|
959
|
+
_listDeliveries(id, criteria) {
|
|
960
|
+
this.http.assertSecretKey("webhooks.listDeliveries");
|
|
961
|
+
return this.http.get(
|
|
962
|
+
`/webhooks/${id}/deliveries/`,
|
|
963
|
+
criteria
|
|
964
|
+
);
|
|
965
|
+
}
|
|
966
|
+
_retrieveDelivery(webhookId, deliveryId) {
|
|
967
|
+
this.http.assertSecretKey("webhooks.retrieveDelivery");
|
|
968
|
+
return this.http.get(
|
|
969
|
+
`/webhooks/${webhookId}/deliveries/${deliveryId}/`
|
|
970
|
+
);
|
|
971
|
+
}
|
|
972
|
+
_retryDelivery(webhookId, deliveryId) {
|
|
973
|
+
this.http.assertSecretKey("webhooks.retryDelivery");
|
|
974
|
+
return this.http.post(
|
|
975
|
+
`/webhooks/${webhookId}/deliveries/${deliveryId}/retry/`,
|
|
976
|
+
{}
|
|
977
|
+
);
|
|
978
|
+
}
|
|
979
|
+
_options() {
|
|
980
|
+
return this.http.options("/webhooks/");
|
|
981
|
+
}
|
|
982
|
+
};
|
|
983
|
+
|
|
984
|
+
// modules/security.ts
|
|
985
|
+
var SecurityModule = class extends BaseModule {
|
|
986
|
+
constructor(http) {
|
|
987
|
+
super(http);
|
|
988
|
+
this.http = http;
|
|
989
|
+
}
|
|
990
|
+
security = {
|
|
991
|
+
retrieve: () => this._retrieve(),
|
|
992
|
+
update: (params) => this._update(params),
|
|
993
|
+
addAllowedIps: (ips) => this._addAllowedIps(ips),
|
|
994
|
+
removeAllowedIps: (ips) => this._removeAllowedIps(ips)
|
|
995
|
+
};
|
|
996
|
+
_retrieve() {
|
|
997
|
+
this.http.assertSecretKey("security.retrieve");
|
|
998
|
+
return this.http.get("/security/me/");
|
|
999
|
+
}
|
|
1000
|
+
_update(params) {
|
|
1001
|
+
this.http.assertSecretKey("security.update");
|
|
1002
|
+
return this.http.patch("/security/update_me/", params);
|
|
1003
|
+
}
|
|
1004
|
+
// Pas d'action dédiée côté backend pour l'ajout/retrait d'IPs : on relit le
|
|
1005
|
+
// profil, on recompose la liste complète, puis on la renvoie via update_me/.
|
|
1006
|
+
async _addAllowedIps(ips) {
|
|
1007
|
+
this.http.assertSecretKey("security.addAllowedIps");
|
|
1008
|
+
const profile = await this._retrieve();
|
|
1009
|
+
const merged = Array.from(/* @__PURE__ */ new Set([...profile.allowed_ips, ...ips]));
|
|
1010
|
+
return this._update({ allowed_ips: merged });
|
|
1011
|
+
}
|
|
1012
|
+
async _removeAllowedIps(ips) {
|
|
1013
|
+
this.http.assertSecretKey("security.removeAllowedIps");
|
|
1014
|
+
const profile = await this._retrieve();
|
|
1015
|
+
const remaining = profile.allowed_ips.filter((ip) => !ips.includes(ip));
|
|
1016
|
+
return this._update({ allowed_ips: remaining });
|
|
1017
|
+
}
|
|
1018
|
+
};
|
|
1019
|
+
|
|
1020
|
+
// modules/partners.ts
|
|
1021
|
+
var PartnersModule = class extends BaseModule {
|
|
1022
|
+
constructor(http) {
|
|
1023
|
+
super(http);
|
|
1024
|
+
this.http = http;
|
|
1025
|
+
}
|
|
1026
|
+
partners = {
|
|
1027
|
+
list: (criteria) => this._list(criteria),
|
|
1028
|
+
retrieve: (id) => this._retrieve(id),
|
|
1029
|
+
options: () => this._options()
|
|
1030
|
+
};
|
|
1031
|
+
_list(criteria) {
|
|
1032
|
+
this.http.assertSecretKey("partners.list");
|
|
1033
|
+
return this.http.get("/partners/", criteria);
|
|
1034
|
+
}
|
|
1035
|
+
_retrieve(id) {
|
|
1036
|
+
this.http.assertSecretKey("partners.retrieve");
|
|
1037
|
+
return this.http.get(`/partners/${id}/`);
|
|
1038
|
+
}
|
|
1039
|
+
_options() {
|
|
1040
|
+
return this.http.options("/partners/");
|
|
1041
|
+
}
|
|
1042
|
+
};
|
|
1043
|
+
|
|
1044
|
+
// modules/terminal.ts
|
|
1045
|
+
var TerminalModule = class extends BaseModule {
|
|
1046
|
+
constructor(http) {
|
|
1047
|
+
super(http);
|
|
1048
|
+
this.http = http;
|
|
1049
|
+
}
|
|
1050
|
+
terminal = {
|
|
1051
|
+
// ── Readers ───────────────────────────────────────────────────────
|
|
1052
|
+
readers: {
|
|
1053
|
+
list: (criteria) => this._listReaders(criteria),
|
|
1054
|
+
retrieve: (id) => this._retrieveReader(id),
|
|
1055
|
+
create: (payloads) => this._createReader(payloads),
|
|
1056
|
+
update: (id, payloads) => this._updateReader(id, payloads),
|
|
1057
|
+
disable: (id) => this._disableReader(id),
|
|
1058
|
+
refreshToken: (id) => this._refreshToken(id),
|
|
1059
|
+
heartbeat: (id) => this._heartbeat(id),
|
|
1060
|
+
options: () => this._readerOptions()
|
|
1061
|
+
},
|
|
1062
|
+
// ── Sessions ──────────────────────────────────────────────────────
|
|
1063
|
+
sessions: {
|
|
1064
|
+
list: (criteria) => this._listSessions(criteria),
|
|
1065
|
+
retrieve: (id) => this._retrieveSession(id),
|
|
1066
|
+
create: (payloads) => this._createSession(payloads),
|
|
1067
|
+
presentPaymentMethod: (id, payloads) => this._presentPayment(id, payloads),
|
|
1068
|
+
pollStatus: (id) => this._pollStatus(id),
|
|
1069
|
+
cancel: (id) => this._cancelSession(id),
|
|
1070
|
+
options: () => this._sessionOptions()
|
|
1071
|
+
},
|
|
1072
|
+
// ── Offline sync ──────────────────────────────────────────────────
|
|
1073
|
+
offline: {
|
|
1074
|
+
sync: (payloads) => this._syncOffline(payloads),
|
|
1075
|
+
list: (criteria) => this._listOffline(criteria),
|
|
1076
|
+
options: () => this._offlineOptions()
|
|
1077
|
+
}
|
|
1078
|
+
};
|
|
1079
|
+
// ── Reader methods ──────────────────────────────────────────────────────────
|
|
1080
|
+
_listReaders(criteria) {
|
|
1081
|
+
this.http.assertSecretKey("terminal.readers.list");
|
|
1082
|
+
return this.http.get("/terminal/readers/", criteria);
|
|
1083
|
+
}
|
|
1084
|
+
_retrieveReader(id) {
|
|
1085
|
+
this.http.assertSecretKey("terminal.readers.retrieve");
|
|
1086
|
+
return this.http.get(`/terminal/readers/${id}/`);
|
|
1087
|
+
}
|
|
1088
|
+
_createReader(payloads) {
|
|
1089
|
+
this.http.assertSecretKey("terminal.readers.create");
|
|
1090
|
+
return this.http.post("/terminal/readers/", payloads);
|
|
1091
|
+
}
|
|
1092
|
+
_updateReader(id, payloads) {
|
|
1093
|
+
this.http.assertSecretKey("terminal.readers.update");
|
|
1094
|
+
return this.http.patch(`/terminal/readers/${id}/`, payloads);
|
|
1095
|
+
}
|
|
1096
|
+
_disableReader(id) {
|
|
1097
|
+
this.http.assertSecretKey("terminal.readers.disable");
|
|
1098
|
+
return this.http.delete(`/terminal/readers/${id}/`);
|
|
1099
|
+
}
|
|
1100
|
+
_refreshToken(id) {
|
|
1101
|
+
this.http.assertSecretKey("terminal.readers.refreshToken");
|
|
1102
|
+
return this.http.post(
|
|
1103
|
+
`/terminal/readers/${id}/refresh-token/`,
|
|
1104
|
+
{}
|
|
1105
|
+
);
|
|
1106
|
+
}
|
|
1107
|
+
_heartbeat(id) {
|
|
1108
|
+
this.http.assertSecretKey("terminal.readers.heartbeat");
|
|
1109
|
+
return this.http.post(
|
|
1110
|
+
`/terminal/readers/${id}/heartbeat/`,
|
|
1111
|
+
{}
|
|
1112
|
+
);
|
|
1113
|
+
}
|
|
1114
|
+
_readerOptions() {
|
|
1115
|
+
return this.http.options("/terminal/readers/");
|
|
1116
|
+
}
|
|
1117
|
+
// ── Session methods ─────────────────────────────────────────────────────────
|
|
1118
|
+
_listSessions(criteria) {
|
|
1119
|
+
this.http.assertSecretKey("terminal.sessions.list");
|
|
1120
|
+
return this.http.get("/terminal/sessions/", criteria);
|
|
1121
|
+
}
|
|
1122
|
+
_retrieveSession(id) {
|
|
1123
|
+
this.http.assertSecretKey("terminal.sessions.retrieve");
|
|
1124
|
+
return this.http.get(`/terminal/sessions/${id}/`);
|
|
1125
|
+
}
|
|
1126
|
+
_createSession(payloads) {
|
|
1127
|
+
this.http.assertSecretKey("terminal.sessions.create");
|
|
1128
|
+
return this.http.post("/terminal/sessions/", payloads);
|
|
1129
|
+
}
|
|
1130
|
+
_presentPayment(id, payloads) {
|
|
1131
|
+
this.http.assertSecretKey("terminal.sessions.presentPaymentMethod");
|
|
1132
|
+
return this.http.post(
|
|
1133
|
+
`/terminal/sessions/${id}/present-payment-method/`,
|
|
1134
|
+
payloads
|
|
1135
|
+
);
|
|
1136
|
+
}
|
|
1137
|
+
_pollStatus(id) {
|
|
1138
|
+
this.http.assertSecretKey("terminal.sessions.pollStatus");
|
|
1139
|
+
return this.http.get(`/terminal/sessions/${id}/status/`);
|
|
1140
|
+
}
|
|
1141
|
+
_cancelSession(id) {
|
|
1142
|
+
this.http.assertSecretKey("terminal.sessions.cancel");
|
|
1143
|
+
return this.http.post(`/terminal/sessions/${id}/cancel/`, {});
|
|
1144
|
+
}
|
|
1145
|
+
_sessionOptions() {
|
|
1146
|
+
return this.http.options("/terminal/sessions/");
|
|
1147
|
+
}
|
|
1148
|
+
// ── Offline methods ─────────────────────────────────────────────────────────
|
|
1149
|
+
_syncOffline(payloads) {
|
|
1150
|
+
this.http.assertSecretKey("terminal.offline.sync");
|
|
1151
|
+
return this.http.post("/terminal/offline/sync/", payloads);
|
|
1152
|
+
}
|
|
1153
|
+
_listOffline(criteria) {
|
|
1154
|
+
this.http.assertSecretKey("terminal.offline.list");
|
|
1155
|
+
return this.http.get(
|
|
1156
|
+
"/terminal/offline/sync/",
|
|
1157
|
+
criteria
|
|
1158
|
+
);
|
|
1159
|
+
}
|
|
1160
|
+
_offlineOptions() {
|
|
1161
|
+
return this.http.options("/terminal/offline/sync/");
|
|
1162
|
+
}
|
|
1163
|
+
};
|
|
1164
|
+
|
|
1165
|
+
// modules/sandbox.ts
|
|
1166
|
+
var SandboxModule = class extends BaseModule {
|
|
1167
|
+
constructor(http) {
|
|
1168
|
+
super(http);
|
|
1169
|
+
this.http = http;
|
|
1170
|
+
}
|
|
1171
|
+
sandbox = {
|
|
1172
|
+
reset: () => this._reset()
|
|
1173
|
+
};
|
|
1174
|
+
/**
|
|
1175
|
+
* Supprime toutes les données sandbox de l'application courante (customers,
|
|
1176
|
+
* products, payment_intents, transactions, refunds, invoices,
|
|
1177
|
+
* checkout_sessions, subscriptions, payment_methods, receipts).
|
|
1178
|
+
*
|
|
1179
|
+
* L'app elle-même, ses clés API et ses paramètres sont conservés.
|
|
1180
|
+
* Bloqué par le backend si la clé utilisée est une clé live (`sk_prod_*`).
|
|
1181
|
+
*
|
|
1182
|
+
* @example
|
|
1183
|
+
* await sangho.sandbox.reset()
|
|
1184
|
+
*/
|
|
1185
|
+
_reset() {
|
|
1186
|
+
this.http.assertSecretKey("sandbox.reset");
|
|
1187
|
+
return this.http.post("/reset/", {});
|
|
1188
|
+
}
|
|
1189
|
+
};
|
|
1190
|
+
|
|
1191
|
+
// utils/webhook.ts
|
|
1192
|
+
var TOLERANCE_SECONDS = 300;
|
|
1193
|
+
async function constructEvent(payload, signature, secret, tolerance = TOLERANCE_SECONDS) {
|
|
1194
|
+
const rawPayload = typeof payload === "string" ? new TextEncoder().encode(payload) : payload;
|
|
1195
|
+
const parts = Object.fromEntries(
|
|
1196
|
+
signature.split(",").map((part) => {
|
|
1197
|
+
const idx = part.indexOf("=");
|
|
1198
|
+
return [part.slice(0, idx), part.slice(idx + 1)];
|
|
1199
|
+
})
|
|
1200
|
+
);
|
|
1201
|
+
const timestamp = Number(parts["t"]);
|
|
1202
|
+
const expectedSig = parts["v1"];
|
|
1203
|
+
if (!timestamp || !expectedSig) {
|
|
1204
|
+
throw new SanghoError(
|
|
1205
|
+
"Invalid Sangho-Signature header format.",
|
|
1206
|
+
"API_ERROR"
|
|
1207
|
+
);
|
|
1208
|
+
}
|
|
1209
|
+
const now = Math.floor(Date.now() / 1e3);
|
|
1210
|
+
if (Math.abs(now - timestamp) > tolerance) {
|
|
1211
|
+
throw new SanghoError(
|
|
1212
|
+
`Webhook timestamp too old (${Math.abs(now - timestamp)}s). Possible replay attack. Tolerance is ${tolerance}s.`,
|
|
1213
|
+
"API_ERROR"
|
|
1214
|
+
);
|
|
1215
|
+
}
|
|
1216
|
+
const signedPayload = `${timestamp}.${new TextDecoder().decode(rawPayload)}`;
|
|
1217
|
+
const computedSig = await hmacSha256(secret, signedPayload);
|
|
1218
|
+
if (!timingSafeEqual(computedSig, expectedSig)) {
|
|
1219
|
+
throw new SanghoError(
|
|
1220
|
+
"Webhook signature mismatch. Verify your webhook secret.",
|
|
1221
|
+
"AUTHENTICATION_ERROR",
|
|
1222
|
+
401
|
|
1223
|
+
);
|
|
1224
|
+
}
|
|
1225
|
+
const body = JSON.parse(new TextDecoder().decode(rawPayload));
|
|
1226
|
+
return body;
|
|
1227
|
+
}
|
|
1228
|
+
async function hmacSha256(secret, message) {
|
|
1229
|
+
const encoder = new TextEncoder();
|
|
1230
|
+
if (typeof crypto !== "undefined" && crypto.subtle) {
|
|
1231
|
+
const key = await crypto.subtle.importKey(
|
|
1232
|
+
"raw",
|
|
1233
|
+
encoder.encode(secret),
|
|
1234
|
+
{ name: "HMAC", hash: "SHA-256" },
|
|
1235
|
+
false,
|
|
1236
|
+
["sign"]
|
|
1237
|
+
);
|
|
1238
|
+
const sig = await crypto.subtle.sign("HMAC", key, encoder.encode(message));
|
|
1239
|
+
return Array.from(new Uint8Array(sig)).map((b) => b.toString(16).padStart(2, "0")).join("");
|
|
1240
|
+
}
|
|
1241
|
+
const { createHmac } = await import('crypto');
|
|
1242
|
+
return createHmac("sha256", secret).update(message).digest("hex");
|
|
1243
|
+
}
|
|
1244
|
+
function timingSafeEqual(a, b) {
|
|
1245
|
+
if (a.length !== b.length) return false;
|
|
1246
|
+
let diff = 0;
|
|
1247
|
+
for (let i = 0; i < a.length; i++) {
|
|
1248
|
+
diff |= a.charCodeAt(i) ^ b.charCodeAt(i);
|
|
1249
|
+
}
|
|
1250
|
+
return diff === 0;
|
|
1251
|
+
}
|
|
1252
|
+
|
|
1253
|
+
// utils/mixins.ts
|
|
1254
|
+
function Mixins(BaseClass, ...Bases) {
|
|
1255
|
+
class MixinsClass extends BaseClass {
|
|
1256
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any -- même raison : args passés tel quel aux constructeurs de Bases.
|
|
1257
|
+
constructor(...args) {
|
|
1258
|
+
super(...args);
|
|
1259
|
+
Bases.forEach((Base) => {
|
|
1260
|
+
const instance = new Base(...args);
|
|
1261
|
+
Object.getOwnPropertyNames(instance).forEach((name) => {
|
|
1262
|
+
if (name !== "constructor") {
|
|
1263
|
+
const descriptor = Object.getOwnPropertyDescriptor(instance, name);
|
|
1264
|
+
if (descriptor) {
|
|
1265
|
+
Object.defineProperty(this, name, descriptor);
|
|
1266
|
+
}
|
|
1267
|
+
}
|
|
1268
|
+
});
|
|
1269
|
+
const proto = Base.prototype;
|
|
1270
|
+
Object.getOwnPropertyNames(proto).forEach((name) => {
|
|
1271
|
+
if (name !== "constructor") {
|
|
1272
|
+
const descriptor = Object.getOwnPropertyDescriptor(proto, name);
|
|
1273
|
+
if (descriptor) {
|
|
1274
|
+
Object.defineProperty(MixinsClass.prototype, name, descriptor);
|
|
1275
|
+
}
|
|
1276
|
+
}
|
|
1277
|
+
});
|
|
1278
|
+
});
|
|
1279
|
+
}
|
|
1280
|
+
}
|
|
1281
|
+
return MixinsClass;
|
|
1282
|
+
}
|
|
1283
|
+
|
|
1284
|
+
// client.ts
|
|
1285
|
+
var VALID_KEY_PREFIXES = ["pk_prod_", "sk_prod_", "pk_test_", "sk_test_"];
|
|
1286
|
+
function validateApiKey(key) {
|
|
1287
|
+
if (!key || typeof key !== "string") {
|
|
1288
|
+
throw new SanghoError(
|
|
1289
|
+
"API key must be a non-empty string. Find your API keys at https://dash.sangho.ga/project/api-keys.",
|
|
1290
|
+
"AUTHENTICATION_ERROR"
|
|
1291
|
+
);
|
|
1292
|
+
}
|
|
1293
|
+
if (!VALID_KEY_PREFIXES.some((prefix) => key.startsWith(prefix))) {
|
|
1294
|
+
throw new SanghoError(
|
|
1295
|
+
`Invalid API key format: "${key.slice(0, 10)}...". Keys must start with pk_prod_, sk_prod_, pk_test_, or sk_test_.`,
|
|
1296
|
+
"AUTHENTICATION_ERROR"
|
|
1297
|
+
);
|
|
1298
|
+
}
|
|
1299
|
+
if (key.length < 20) {
|
|
1300
|
+
throw new SanghoError("API key is too short.", "AUTHENTICATION_ERROR");
|
|
1301
|
+
}
|
|
1302
|
+
}
|
|
1303
|
+
function validateBaseURL(baseURL) {
|
|
1304
|
+
let url;
|
|
1305
|
+
try {
|
|
1306
|
+
url = new URL(baseURL);
|
|
1307
|
+
} catch {
|
|
1308
|
+
throw new SanghoError(`Invalid baseURL: "${baseURL}".`, "API_ERROR");
|
|
1309
|
+
}
|
|
1310
|
+
const isLocal = url.hostname === "localhost" || url.hostname === "127.0.0.1";
|
|
1311
|
+
if (url.protocol !== "https:" && !isLocal) {
|
|
1312
|
+
throw new SanghoError(
|
|
1313
|
+
`Refusing to send API keys over a non-HTTPS baseURL: "${baseURL}". Use an https:// URL (localhost/127.0.0.1 are exempt for local development).`,
|
|
1314
|
+
"API_ERROR"
|
|
1315
|
+
);
|
|
1316
|
+
}
|
|
1317
|
+
}
|
|
1318
|
+
var Sangho = class extends Mixins(
|
|
1319
|
+
BaseModule,
|
|
1320
|
+
AccountModule,
|
|
1321
|
+
AppsModule,
|
|
1322
|
+
AddressesModule,
|
|
1323
|
+
CustomersModule,
|
|
1324
|
+
ProductsModule,
|
|
1325
|
+
PaymentIntentsModule,
|
|
1326
|
+
TransactionsModule,
|
|
1327
|
+
RefundsModule,
|
|
1328
|
+
InvoicesModule,
|
|
1329
|
+
PaymentLinksModule,
|
|
1330
|
+
CheckoutSessionsModule,
|
|
1331
|
+
SubscriptionsModule,
|
|
1332
|
+
PaymentMethodsModule,
|
|
1333
|
+
ReceiptsModule,
|
|
1334
|
+
WebhooksModule,
|
|
1335
|
+
SecurityModule,
|
|
1336
|
+
PartnersModule,
|
|
1337
|
+
TerminalModule,
|
|
1338
|
+
SandboxModule
|
|
1339
|
+
) {
|
|
1340
|
+
constructor(apiKey, options = {}) {
|
|
1341
|
+
validateApiKey(apiKey);
|
|
1342
|
+
const isSandbox = apiKey.startsWith("pk_test_") || apiKey.startsWith("sk_test_");
|
|
1343
|
+
const baseURL = options.baseURL ?? "https://api.sangho.ga/v1";
|
|
1344
|
+
validateBaseURL(baseURL);
|
|
1345
|
+
const http = new HttpClient({
|
|
1346
|
+
apiKey,
|
|
1347
|
+
baseURL,
|
|
1348
|
+
timeout: options.timeout ?? 3e4,
|
|
1349
|
+
maxRetries: options.maxRetries ?? 3,
|
|
1350
|
+
sandbox: isSandbox
|
|
1351
|
+
});
|
|
1352
|
+
super(http);
|
|
1353
|
+
}
|
|
1354
|
+
/**
|
|
1355
|
+
* Vérifie et parse un événement webhook entrant.
|
|
1356
|
+
* Valide la signature HMAC-SHA256 + protection anti-replay (5 min).
|
|
1357
|
+
*
|
|
1358
|
+
* @param payload - Corps brut de la requête (Buffer ou string)
|
|
1359
|
+
* @param signature - Header `Sangho-Signature` de la requête
|
|
1360
|
+
* @param secret - Secret du webhook (depuis le dashboard)
|
|
1361
|
+
*
|
|
1362
|
+
* @example
|
|
1363
|
+
* ```typescript
|
|
1364
|
+
* // Express
|
|
1365
|
+
* app.post('/webhooks/sangho', express.raw({ type: 'application/json' }), (req, res) => {
|
|
1366
|
+
* const event = Sangho.constructEvent(
|
|
1367
|
+
* req.body,
|
|
1368
|
+
* req.headers['sangho-signature'],
|
|
1369
|
+
* process.env.SANGHO_WEBHOOK_SECRET
|
|
1370
|
+
* )
|
|
1371
|
+
* if (event.type === 'payment_intent.succeeded') {
|
|
1372
|
+
* await fulfillOrder(event.data)
|
|
1373
|
+
* }
|
|
1374
|
+
* res.json({ received: true })
|
|
1375
|
+
* })
|
|
1376
|
+
* ```
|
|
1377
|
+
*/
|
|
1378
|
+
static constructEvent = constructEvent;
|
|
1379
|
+
};
|
|
1380
|
+
|
|
1381
|
+
exports.Sangho = Sangho;
|
|
1382
|
+
exports.SanghoAuthError = SanghoAuthError;
|
|
1383
|
+
exports.SanghoError = SanghoError;
|
|
1384
|
+
exports.SanghoIdempotencyError = SanghoIdempotencyError;
|
|
1385
|
+
exports.SanghoNetworkError = SanghoNetworkError;
|
|
1386
|
+
exports.SanghoNotFoundError = SanghoNotFoundError;
|
|
1387
|
+
exports.SanghoPermissionError = SanghoPermissionError;
|
|
1388
|
+
exports.SanghoPublicKeyError = SanghoPublicKeyError;
|
|
1389
|
+
exports.SanghoRateLimitError = SanghoRateLimitError;
|
|
1390
|
+
exports.SanghoTimeoutError = SanghoTimeoutError;
|
|
1391
|
+
exports.SanghoValidationError = SanghoValidationError;
|
|
1392
|
+
exports.constructEvent = constructEvent;
|
|
1393
|
+
exports.default = Sangho;
|
|
1394
|
+
//# sourceMappingURL=index.cjs.map
|
|
1395
|
+
//# sourceMappingURL=index.cjs.map
|