@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.d.ts
ADDED
|
@@ -0,0 +1,2559 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Vérifie la signature HMAC-SHA256 d'un événement webhook Sangho.
|
|
3
|
+
*
|
|
4
|
+
* @example
|
|
5
|
+
* ```typescript
|
|
6
|
+
* // `constructEvent` est une méthode statique de `Sangho`, pas une méthode
|
|
7
|
+
* // d'instance sur `sangho.webhooks` — pas besoin d'avoir instancié le client.
|
|
8
|
+
* const event = await Sangho.constructEvent(
|
|
9
|
+
* rawBody,
|
|
10
|
+
* request.headers['sangho-signature'],
|
|
11
|
+
* 'whsec_xxxxx'
|
|
12
|
+
* )
|
|
13
|
+
* ```
|
|
14
|
+
*/
|
|
15
|
+
declare function constructEvent<T = unknown>(payload: string | Uint8Array, signature: string, secret: string, tolerance?: number): Promise<{
|
|
16
|
+
id: string;
|
|
17
|
+
type: string;
|
|
18
|
+
created: number;
|
|
19
|
+
data: T;
|
|
20
|
+
}>;
|
|
21
|
+
|
|
22
|
+
interface ListParams {
|
|
23
|
+
/** Numéro de page (défaut : 1) */
|
|
24
|
+
page?: number;
|
|
25
|
+
/** Nombre d'éléments par page (défaut : 20, max : 100) */
|
|
26
|
+
page_size?: number;
|
|
27
|
+
/** Tri ex: "-created_at" (préfixe - pour DESC) */
|
|
28
|
+
ordering?: string;
|
|
29
|
+
/** Recherche full-text */
|
|
30
|
+
search?: string;
|
|
31
|
+
}
|
|
32
|
+
interface ListResponse<T> {
|
|
33
|
+
count: number;
|
|
34
|
+
next: string | null;
|
|
35
|
+
previous: string | null;
|
|
36
|
+
data: T[];
|
|
37
|
+
}
|
|
38
|
+
interface Timestamps {
|
|
39
|
+
created_at: string;
|
|
40
|
+
updated_at: string;
|
|
41
|
+
}
|
|
42
|
+
/** Montant monétaire exprimé en centimes (integer). Ex: 5000 = 50.00 XAF */
|
|
43
|
+
type AmountInCents = number;
|
|
44
|
+
/**
|
|
45
|
+
* Codes ISO 4217 actifs acceptés au niveau du *type* par le SDK.
|
|
46
|
+
*
|
|
47
|
+
* Important : cette liste ne représente que la validité ISO 4217 générale,
|
|
48
|
+
* PAS ce qu'un marchand donné a le droit d'utiliser. Sangho facture/entitle
|
|
49
|
+
* les devises par plan — un marchand ne peut utiliser à l'exécution que le
|
|
50
|
+
* sous-ensemble de devises inclus dans son plan (ou activé en backoffice).
|
|
51
|
+
* Utiliser une devise valide ISO 4217 mais hors plan est un problème
|
|
52
|
+
* *runtime*, tranché par le backend, qui répond avec une `SanghoError` dont
|
|
53
|
+
* `.code` vaut `CURRENCY_NOT_IN_PLAN` (ou `INVALID_CURRENCY` si le code
|
|
54
|
+
* n'est même pas un ISO 4217 reconnu) — voir `core/errors.ts`. Le SDK ne
|
|
55
|
+
* peut pas connaître statiquement le plan d'un marchand donné : il n'essaie
|
|
56
|
+
* donc pas d'imposer cette restriction au niveau des types, seulement la
|
|
57
|
+
* validité ISO 4217 elle-même.
|
|
58
|
+
*/
|
|
59
|
+
declare const ISO_4217_CURRENCIES: readonly ["AED", "AFN", "ALL", "AMD", "ANG", "AOA", "ARS", "AUD", "AWG", "AZN", "BAM", "BBD", "BDT", "BGN", "BHD", "BIF", "BMD", "BND", "BOB", "BRL", "BSD", "BTN", "BWP", "BYN", "BZD", "CAD", "CDF", "CHF", "CLP", "CNY", "COP", "CRC", "CUP", "CVE", "CZK", "DJF", "DKK", "DOP", "DZD", "EGP", "ERN", "ETB", "EUR", "FJD", "FKP", "GBP", "GEL", "GHS", "GIP", "GMD", "GNF", "GTQ", "GYD", "HKD", "HNL", "HTG", "HUF", "IDR", "ILS", "INR", "IQD", "IRR", "ISK", "JMD", "JOD", "JPY", "KES", "KGS", "KHR", "KMF", "KPW", "KRW", "KWD", "KYD", "KZT", "LAK", "LBP", "LKR", "LRD", "LSL", "LYD", "MAD", "MDL", "MGA", "MKD", "MMK", "MNT", "MOP", "MRU", "MUR", "MVR", "MWK", "MXN", "MYR", "MZN", "NAD", "NGN", "NIO", "NOK", "NPR", "NZD", "OMR", "PAB", "PEN", "PGK", "PHP", "PKR", "PLN", "PYG", "QAR", "RON", "RSD", "RUB", "RWF", "SAR", "SBD", "SCR", "SDG", "SEK", "SGD", "SHP", "SLE", "SOS", "SRD", "SSP", "STN", "SYP", "SZL", "THB", "TJS", "TMT", "TND", "TOP", "TRY", "TTD", "TWD", "TZS", "UAH", "UGX", "USD", "UYU", "UZS", "VES", "VND", "VUV", "WST", "XAF", "XCD", "XOF", "XPF", "YER", "ZAR", "ZMW", "ZWL"];
|
|
60
|
+
/**
|
|
61
|
+
* Devise ISO 4217 valide (union dérivée de `ISO_4217_CURRENCIES` — source
|
|
62
|
+
* de vérité unique). Ne préjuge pas de ce qu'un marchand a le droit
|
|
63
|
+
* d'utiliser : voir la note sur `ISO_4217_CURRENCIES` ci-dessus.
|
|
64
|
+
*/
|
|
65
|
+
type CurrencyCode = (typeof ISO_4217_CURRENCIES)[number];
|
|
66
|
+
/** Dictionnaire clé/valeur libre, max 50 clés, valeurs string. */
|
|
67
|
+
type Metadata = Record<string, string>;
|
|
68
|
+
interface Address {
|
|
69
|
+
line1: string;
|
|
70
|
+
line2?: string;
|
|
71
|
+
city: string;
|
|
72
|
+
state?: string;
|
|
73
|
+
postal_code?: string;
|
|
74
|
+
country: string;
|
|
75
|
+
}
|
|
76
|
+
interface SanghoOptions {
|
|
77
|
+
/** Override URL de base (utile pour tests/staging) */
|
|
78
|
+
baseURL?: string;
|
|
79
|
+
/** Timeout en ms (défaut : 30 000) */
|
|
80
|
+
timeout?: number;
|
|
81
|
+
/** Nombre de retries auto (défaut : 3) */
|
|
82
|
+
maxRetries?: number;
|
|
83
|
+
}
|
|
84
|
+
/**
|
|
85
|
+
* A utility type for creating class property interfaces that don't overwrite
|
|
86
|
+
* actual implementation values when used as type definitions
|
|
87
|
+
*/
|
|
88
|
+
type InterfaceOnly<T> = {
|
|
89
|
+
[P in keyof T]?: T[P];
|
|
90
|
+
};
|
|
91
|
+
interface DRFOptions {
|
|
92
|
+
name: string;
|
|
93
|
+
description: string;
|
|
94
|
+
renders: string[];
|
|
95
|
+
parses: string[];
|
|
96
|
+
actions?: Record<string, unknown>;
|
|
97
|
+
}
|
|
98
|
+
type ForeignKey = string | number | null;
|
|
99
|
+
|
|
100
|
+
type AppMode = "test" | "prod";
|
|
101
|
+
type AppEnvironment = "sandbox" | "live";
|
|
102
|
+
interface AppCriteria {
|
|
103
|
+
is_active?: boolean;
|
|
104
|
+
name?: string;
|
|
105
|
+
environment?: AppEnvironment;
|
|
106
|
+
mode?: AppMode;
|
|
107
|
+
[key: string]: string | number | boolean;
|
|
108
|
+
}
|
|
109
|
+
interface AppKey {
|
|
110
|
+
id: string;
|
|
111
|
+
value: string;
|
|
112
|
+
name: string;
|
|
113
|
+
is_active: boolean;
|
|
114
|
+
created_at: string;
|
|
115
|
+
}
|
|
116
|
+
interface AppKeys {
|
|
117
|
+
pk: AppKey;
|
|
118
|
+
sk: AppKey;
|
|
119
|
+
}
|
|
120
|
+
interface App extends Timestamps {
|
|
121
|
+
id: string;
|
|
122
|
+
object: "app";
|
|
123
|
+
name: string;
|
|
124
|
+
description?: string | null;
|
|
125
|
+
logo?: string | null;
|
|
126
|
+
mode: AppMode;
|
|
127
|
+
environment: AppEnvironment;
|
|
128
|
+
currency: string;
|
|
129
|
+
is_active: boolean;
|
|
130
|
+
is_verified: boolean;
|
|
131
|
+
allowed_hosts: string[];
|
|
132
|
+
allowed_ips: string[];
|
|
133
|
+
company?: ForeignKey;
|
|
134
|
+
}
|
|
135
|
+
interface Payloads$9 {
|
|
136
|
+
name?: string;
|
|
137
|
+
description?: string;
|
|
138
|
+
logo?: File | string;
|
|
139
|
+
allowed_hosts?: string[];
|
|
140
|
+
allowed_ips?: string[];
|
|
141
|
+
is_active?: boolean;
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
type AccountProperties = {
|
|
145
|
+
/**
|
|
146
|
+
* Retourne l'application liée à la clé secrète courante.
|
|
147
|
+
* Nécessite une clé secrète (`sk_prod_*` ou `sk_test_*`).
|
|
148
|
+
*
|
|
149
|
+
* @example
|
|
150
|
+
* const app = await sangho.account.retrieve()
|
|
151
|
+
* console.log(app.id, app.mode)
|
|
152
|
+
*/
|
|
153
|
+
retrieve(): Promise<App>;
|
|
154
|
+
};
|
|
155
|
+
|
|
156
|
+
type AppsProperties = {
|
|
157
|
+
/**
|
|
158
|
+
* Liste toutes les applications de l'owner authentifié.
|
|
159
|
+
* Si `criteria` est fourni, filtre les apps par les champs indiqués
|
|
160
|
+
* (transmis en query params). Sans critères, retourne tout.
|
|
161
|
+
*
|
|
162
|
+
* @param criteria - Filtres optionnels ex: `{ is_active: true, mode: "prod" }`
|
|
163
|
+
* @returns Tableau des apps correspondant aux critères
|
|
164
|
+
*
|
|
165
|
+
* @example
|
|
166
|
+
* const all = await sangho.apps.list()
|
|
167
|
+
* const prod = await sangho.apps.list({ mode: "prod", is_active: true })
|
|
168
|
+
*/
|
|
169
|
+
list(criteria?: AppCriteria): Promise<App[]>;
|
|
170
|
+
/**
|
|
171
|
+
* Récupère une application par son identifiant.
|
|
172
|
+
*
|
|
173
|
+
* @param id - Identifiant de l'application (ex: `"app_xxx"`)
|
|
174
|
+
* @returns Les données de l'application
|
|
175
|
+
*
|
|
176
|
+
* @example
|
|
177
|
+
* const app = await sangho.apps.retrieve("app_xxx")
|
|
178
|
+
* console.log(app.mode) // "test" | "prod"
|
|
179
|
+
*/
|
|
180
|
+
retrieve(id: string): Promise<App>;
|
|
181
|
+
/**
|
|
182
|
+
* Crée une nouvelle application.
|
|
183
|
+
* Si une app portant le même `name` existe déjà pour cet owner,
|
|
184
|
+
* le backend la retourne telle quelle (idempotent, HTTP 200).
|
|
185
|
+
*
|
|
186
|
+
* @param payloads - Champs de création (`name` recommandé)
|
|
187
|
+
* @returns L'application créée (HTTP 201) ou existante (HTTP 200)
|
|
188
|
+
*
|
|
189
|
+
* @example
|
|
190
|
+
* const app = await sangho.apps.create({ name: "Mon App" })
|
|
191
|
+
*/
|
|
192
|
+
create(payloads: Payloads$9): Promise<App>;
|
|
193
|
+
/**
|
|
194
|
+
* Met à jour les paramètres de l'application (mise à jour partielle).
|
|
195
|
+
* La modification est propagée en sandbox et en live automatiquement.
|
|
196
|
+
*
|
|
197
|
+
* @param id - Identifiant de l'application
|
|
198
|
+
* @param payloads - Champs à modifier (tous optionnels)
|
|
199
|
+
* @returns L'application mise à jour
|
|
200
|
+
*
|
|
201
|
+
* @example
|
|
202
|
+
* const app = await sangho.apps.update("app_xxx", {
|
|
203
|
+
* name: "Mon App v2",
|
|
204
|
+
* allowed_hosts: ["mon-site.com"],
|
|
205
|
+
* })
|
|
206
|
+
*/
|
|
207
|
+
update(id: string, payloads: Payloads$9): Promise<App>;
|
|
208
|
+
/**
|
|
209
|
+
* Suppression douce (soft-delete) de l'application.
|
|
210
|
+
* L'app est marquée `is_ready_to_delete` et purgée définitivement
|
|
211
|
+
* après un délai configuré côté backend.
|
|
212
|
+
*
|
|
213
|
+
* @param id - Identifiant de l'application
|
|
214
|
+
*
|
|
215
|
+
* @example
|
|
216
|
+
* await sangho.apps.delete("app_xxx")
|
|
217
|
+
*/
|
|
218
|
+
delete(id: string): Promise<void>;
|
|
219
|
+
/**
|
|
220
|
+
* Récupère les clés publique et secrète de l'application.
|
|
221
|
+
* Les valeurs retournées sont partiellement obfusquées
|
|
222
|
+
* (13 caractères visibles, reste masqué).
|
|
223
|
+
*
|
|
224
|
+
* @param id - Identifiant de l'application
|
|
225
|
+
* @returns `{ pk: AppKey, sk: AppKey }`
|
|
226
|
+
*
|
|
227
|
+
* @example
|
|
228
|
+
* const { pk, sk } = await sangho.apps.keys("app_xxx")
|
|
229
|
+
* console.log(pk.value) // "apk_live_xxxxx..."
|
|
230
|
+
*/
|
|
231
|
+
keys(id: string): Promise<AppKeys>;
|
|
232
|
+
/**
|
|
233
|
+
* Retourne les métadonnées DRF du endpoint `/apps/` :
|
|
234
|
+
* actions autorisées, schéma de champs, formats acceptés.
|
|
235
|
+
* N'exige pas d'authentification (découverte de schéma).
|
|
236
|
+
*/
|
|
237
|
+
options(): Promise<DRFOptions>;
|
|
238
|
+
};
|
|
239
|
+
|
|
240
|
+
type AddressType = "main" | "branch" | "billing" | "shipping";
|
|
241
|
+
interface CompanyAddress extends Timestamps {
|
|
242
|
+
id: string;
|
|
243
|
+
object: "address";
|
|
244
|
+
company: string;
|
|
245
|
+
type: AddressType;
|
|
246
|
+
line1: string;
|
|
247
|
+
line2?: string | null;
|
|
248
|
+
neighborhood?: string | null;
|
|
249
|
+
city: string;
|
|
250
|
+
state?: string | null;
|
|
251
|
+
province?: string | null;
|
|
252
|
+
postal_code: string;
|
|
253
|
+
country: string;
|
|
254
|
+
is_active: boolean;
|
|
255
|
+
full_address: string;
|
|
256
|
+
}
|
|
257
|
+
/** Champs requis à la création — alignés sur CreateAddressSerializer */
|
|
258
|
+
interface CreatePayloads$9 {
|
|
259
|
+
type?: AddressType;
|
|
260
|
+
line1: string;
|
|
261
|
+
line2?: string;
|
|
262
|
+
neighborhood?: string;
|
|
263
|
+
city: string;
|
|
264
|
+
state?: string;
|
|
265
|
+
province?: string;
|
|
266
|
+
postal_code: string;
|
|
267
|
+
country: string;
|
|
268
|
+
}
|
|
269
|
+
/** Champs PATCH — tous optionnels, alignés sur AddressSerializer */
|
|
270
|
+
interface Payloads$8 {
|
|
271
|
+
type?: AddressType;
|
|
272
|
+
line1?: string;
|
|
273
|
+
line2?: string;
|
|
274
|
+
neighborhood?: string;
|
|
275
|
+
city?: string;
|
|
276
|
+
state?: string;
|
|
277
|
+
province?: string;
|
|
278
|
+
postal_code?: string;
|
|
279
|
+
country?: string;
|
|
280
|
+
is_active?: boolean;
|
|
281
|
+
}
|
|
282
|
+
/** Filtres GET /addresses/ — alignés sur get_queryset() */
|
|
283
|
+
interface AddressCriteria {
|
|
284
|
+
type?: AddressType;
|
|
285
|
+
is_active?: boolean;
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
type AddressesProperties = {
|
|
289
|
+
/**
|
|
290
|
+
* Liste toutes les adresses de l'entreprise liée à l'app.
|
|
291
|
+
* Filtre par `type` et/ou `is_active` si `criteria` est fourni,
|
|
292
|
+
* sinon retourne toutes les adresses.
|
|
293
|
+
*
|
|
294
|
+
* @param criteria - Filtres optionnels (type, is_active)
|
|
295
|
+
* @returns Tableau des adresses correspondantes
|
|
296
|
+
*
|
|
297
|
+
* @example
|
|
298
|
+
* const all = await sangho.addresses.list()
|
|
299
|
+
* const billing = await sangho.addresses.list({ type: "billing" })
|
|
300
|
+
* const active = await sangho.addresses.list({ is_active: true })
|
|
301
|
+
*/
|
|
302
|
+
list(criteria?: AddressCriteria): Promise<CompanyAddress[]>;
|
|
303
|
+
/**
|
|
304
|
+
* Récupère une adresse par son identifiant.
|
|
305
|
+
*
|
|
306
|
+
* @param id - Identifiant de l'adresse
|
|
307
|
+
* @returns L'adresse correspondante
|
|
308
|
+
*
|
|
309
|
+
* @example
|
|
310
|
+
* const addr = await sangho.addresses.retrieve("123")
|
|
311
|
+
*/
|
|
312
|
+
retrieve(id: string): Promise<CompanyAddress>;
|
|
313
|
+
/**
|
|
314
|
+
* Crée une nouvelle adresse pour l'entreprise liée à l'app.
|
|
315
|
+
* Si `type` vaut `"main"`, les autres adresses principales
|
|
316
|
+
* sont automatiquement reclassées en `"branch"` (backend).
|
|
317
|
+
*
|
|
318
|
+
* @param payloads - `line1`, `city`, `postal_code`, `country` requis
|
|
319
|
+
* @returns L'adresse créée
|
|
320
|
+
*
|
|
321
|
+
* @example
|
|
322
|
+
* const addr = await sangho.addresses.create({
|
|
323
|
+
* type: "billing",
|
|
324
|
+
* line1: "123 Avenue Léon MBA",
|
|
325
|
+
* city: "Libreville",
|
|
326
|
+
* postal_code: "00000",
|
|
327
|
+
* country: "GA",
|
|
328
|
+
* })
|
|
329
|
+
*/
|
|
330
|
+
create(payloads: CreatePayloads$9): Promise<CompanyAddress>;
|
|
331
|
+
/**
|
|
332
|
+
* Met à jour partiellement une adresse (PATCH).
|
|
333
|
+
* L'adresse principale (`type: "main"`) ne peut pas être désactivée
|
|
334
|
+
* via `delete` — mais ses autres champs restent modifiables ici.
|
|
335
|
+
*
|
|
336
|
+
* @param id - Identifiant de l'adresse
|
|
337
|
+
* @param payloads - Champs à modifier (tous optionnels)
|
|
338
|
+
* @returns L'adresse mise à jour
|
|
339
|
+
*
|
|
340
|
+
* @example
|
|
341
|
+
* await sangho.addresses.update("123", { city: "Port-Gentil" })
|
|
342
|
+
*/
|
|
343
|
+
update(id: string, payloads: Payloads$8): Promise<CompanyAddress>;
|
|
344
|
+
/**
|
|
345
|
+
* Désactive une adresse (soft delete — `is_active: false`).
|
|
346
|
+
* Le backend retourne HTTP 204 sans corps.
|
|
347
|
+
* L'adresse principale (`type: "main"`) ne peut pas être supprimée.
|
|
348
|
+
*
|
|
349
|
+
* @param id - Identifiant de l'adresse
|
|
350
|
+
*
|
|
351
|
+
* @example
|
|
352
|
+
* await sangho.addresses.delete("123")
|
|
353
|
+
*/
|
|
354
|
+
delete(id: string): Promise<void>;
|
|
355
|
+
/**
|
|
356
|
+
* Retourne les métadonnées DRF du endpoint `/addresses/` :
|
|
357
|
+
* actions autorisées, schéma de champs, formats acceptés.
|
|
358
|
+
* N'exige pas d'authentification (découverte de schéma).
|
|
359
|
+
*/
|
|
360
|
+
options(): Promise<DRFOptions>;
|
|
361
|
+
};
|
|
362
|
+
|
|
363
|
+
type PaymentIntentStatus = "requires_payment_method" | "requires_confirmation" | "requires_action" | "pending" | "processing" | "requires_capture" | "canceled" | "succeeded";
|
|
364
|
+
type CancellationReason = "duplicate" | "fraudulent" | "requested_by_customer" | "abandoned";
|
|
365
|
+
/**
|
|
366
|
+
* Représente un PaymentIntent Sangho.
|
|
367
|
+
* Préfixe d'identifiant : `pi_xxx`
|
|
368
|
+
* Expand disponibles : `?expand=customer`, `?expand=payment_link`
|
|
369
|
+
*/
|
|
370
|
+
interface PaymentIntent extends Timestamps {
|
|
371
|
+
id: string;
|
|
372
|
+
object: "payment_intent";
|
|
373
|
+
reference: string;
|
|
374
|
+
customer_email?: string | null;
|
|
375
|
+
customer?: object | null;
|
|
376
|
+
currency: CurrencyCode;
|
|
377
|
+
amount: number;
|
|
378
|
+
status: PaymentIntentStatus;
|
|
379
|
+
description?: string | null;
|
|
380
|
+
payment_method?: string | null;
|
|
381
|
+
payment_method_types: string[];
|
|
382
|
+
category?: string | null;
|
|
383
|
+
url?: string | null;
|
|
384
|
+
payment_link?: string | null;
|
|
385
|
+
cancellation_reason?: string | null;
|
|
386
|
+
receipt_email?: string | null;
|
|
387
|
+
expires_at?: string | null;
|
|
388
|
+
metadata: Metadata;
|
|
389
|
+
}
|
|
390
|
+
/** Champs POST — alignés sur PaymentIntentSerializer + perform_create() */
|
|
391
|
+
interface CreatePayloads$8 {
|
|
392
|
+
amount: AmountInCents;
|
|
393
|
+
currency: CurrencyCode;
|
|
394
|
+
customer?: string;
|
|
395
|
+
description?: string;
|
|
396
|
+
payment_method?: string;
|
|
397
|
+
payment_method_types?: string[];
|
|
398
|
+
category?: string;
|
|
399
|
+
receipt_email?: string;
|
|
400
|
+
metadata?: Metadata;
|
|
401
|
+
/**
|
|
402
|
+
* Si `true`, le PaymentIntent passe immédiatement en `"processing"`
|
|
403
|
+
* après création (géré via `metadata._confirm_on_create` backend).
|
|
404
|
+
*/
|
|
405
|
+
confirm?: boolean;
|
|
406
|
+
}
|
|
407
|
+
/** Champs PATCH — tous optionnels */
|
|
408
|
+
interface Payloads$7 {
|
|
409
|
+
amount?: AmountInCents;
|
|
410
|
+
currency?: CurrencyCode;
|
|
411
|
+
customer?: string;
|
|
412
|
+
description?: string;
|
|
413
|
+
payment_method?: string;
|
|
414
|
+
payment_method_types?: string[];
|
|
415
|
+
receipt_email?: string;
|
|
416
|
+
metadata?: Metadata;
|
|
417
|
+
}
|
|
418
|
+
/** Paramètres POST /payment-intents/:id/confirm/ */
|
|
419
|
+
interface ConfirmPayloads {
|
|
420
|
+
payment_method?: string;
|
|
421
|
+
}
|
|
422
|
+
/** Paramètres POST /payment-intents/:id/capture/ */
|
|
423
|
+
interface CapturePayloads {
|
|
424
|
+
/** Montant à capturer en centimes (≤ montant original) */
|
|
425
|
+
amount_to_capture?: AmountInCents;
|
|
426
|
+
}
|
|
427
|
+
/** Paramètres POST /payment-intents/:id/cancel/ */
|
|
428
|
+
interface CancelPayloads {
|
|
429
|
+
cancellation_reason?: CancellationReason;
|
|
430
|
+
}
|
|
431
|
+
/** Filtres GET /payment-intents/ — alignés sur get_queryset() */
|
|
432
|
+
interface PaymentIntentCriteria extends ListParams {
|
|
433
|
+
status?: PaymentIntentStatus;
|
|
434
|
+
currency?: CurrencyCode;
|
|
435
|
+
customer?: string;
|
|
436
|
+
created_after?: string;
|
|
437
|
+
created_before?: string;
|
|
438
|
+
}
|
|
439
|
+
|
|
440
|
+
type PaymentIntentsProperties = {
|
|
441
|
+
/**
|
|
442
|
+
* Liste les PaymentIntents avec filtres et pagination.
|
|
443
|
+
*
|
|
444
|
+
* @param criteria - Filtres optionnels (status, currency, customer, dates, pagination)
|
|
445
|
+
* @returns Liste paginée de PaymentIntents
|
|
446
|
+
*
|
|
447
|
+
* @example
|
|
448
|
+
* const all = await sangho.paymentIntents.list()
|
|
449
|
+
* const succeeded = await sangho.paymentIntents.list({ status: "succeeded" })
|
|
450
|
+
* const byEmail = await sangho.paymentIntents.list({ customer: "jean@example.com" })
|
|
451
|
+
*/
|
|
452
|
+
list(criteria?: PaymentIntentCriteria): Promise<ListResponse<PaymentIntent>>;
|
|
453
|
+
/**
|
|
454
|
+
* Récupère un PaymentIntent par son identifiant.
|
|
455
|
+
* Ajouter `?expand=customer` ou `?expand=payment_link` pour les objets complets.
|
|
456
|
+
*
|
|
457
|
+
* @param id - Identifiant du PaymentIntent (format `pi_xxx`)
|
|
458
|
+
* @returns Le PaymentIntent correspondant
|
|
459
|
+
*
|
|
460
|
+
* @example
|
|
461
|
+
* const intent = await sangho.paymentIntents.retrieve("pi_xxx")
|
|
462
|
+
*/
|
|
463
|
+
retrieve(id: string): Promise<PaymentIntent>;
|
|
464
|
+
/**
|
|
465
|
+
* Crée un nouveau PaymentIntent.
|
|
466
|
+
* Statut initial : `"requires_payment_method"`.
|
|
467
|
+
* Si `confirm: true`, passe immédiatement en `"processing"`.
|
|
468
|
+
*
|
|
469
|
+
* @param payloads - `amount` et `currency` requis
|
|
470
|
+
* @returns Le PaymentIntent créé
|
|
471
|
+
*
|
|
472
|
+
* @example
|
|
473
|
+
* const intent = await sangho.paymentIntents.create({
|
|
474
|
+
* amount: 5000,
|
|
475
|
+
* currency: "XAF",
|
|
476
|
+
* description: "Commande #42",
|
|
477
|
+
* })
|
|
478
|
+
*/
|
|
479
|
+
create(payloads: CreatePayloads$8): Promise<PaymentIntent>;
|
|
480
|
+
/**
|
|
481
|
+
* Met à jour un PaymentIntent avant sa confirmation (PATCH).
|
|
482
|
+
*
|
|
483
|
+
* @param id - Identifiant du PaymentIntent (format `pi_xxx`)
|
|
484
|
+
* @param payloads - Champs à modifier (tous optionnels)
|
|
485
|
+
* @returns Le PaymentIntent mis à jour
|
|
486
|
+
*
|
|
487
|
+
* @example
|
|
488
|
+
* await sangho.paymentIntents.update("pi_xxx", {
|
|
489
|
+
* description: "Nouvelle description",
|
|
490
|
+
* metadata: { order_id: "42" },
|
|
491
|
+
* })
|
|
492
|
+
*/
|
|
493
|
+
update(id: string, payloads: Payloads$7): Promise<PaymentIntent>;
|
|
494
|
+
/**
|
|
495
|
+
* Annule un PaymentIntent via DELETE (alias de `cancel()`).
|
|
496
|
+
* Retourne le PaymentIntent avec `status: "canceled"` (HTTP 200).
|
|
497
|
+
* Ne fonctionne pas sur les statuts `"canceled"` ou `"succeeded"`.
|
|
498
|
+
*
|
|
499
|
+
* @param id - Identifiant du PaymentIntent (format `pi_xxx`)
|
|
500
|
+
* @returns Le PaymentIntent annulé
|
|
501
|
+
*
|
|
502
|
+
* @example
|
|
503
|
+
* const canceled = await sangho.paymentIntents.delete("pi_xxx")
|
|
504
|
+
*/
|
|
505
|
+
delete(id: string): Promise<PaymentIntent>;
|
|
506
|
+
/**
|
|
507
|
+
* Confirme un PaymentIntent pour déclencher le paiement.
|
|
508
|
+
* Statuts acceptés : `"requires_payment_method"`, `"requires_confirmation"`.
|
|
509
|
+
* Passe en `"processing"` après confirmation.
|
|
510
|
+
*
|
|
511
|
+
* @param id - Identifiant du PaymentIntent (format `pi_xxx`)
|
|
512
|
+
* @param payloads - Mode de paiement optionnel
|
|
513
|
+
* @returns Le PaymentIntent confirmé
|
|
514
|
+
*
|
|
515
|
+
* @example
|
|
516
|
+
* const intent = await sangho.paymentIntents.confirm("pi_xxx", {
|
|
517
|
+
* payment_method: "meth_xxx",
|
|
518
|
+
* })
|
|
519
|
+
*/
|
|
520
|
+
confirm(id: string, payloads?: ConfirmPayloads): Promise<PaymentIntent>;
|
|
521
|
+
/**
|
|
522
|
+
* Capture un PaymentIntent en mode de capture manuelle.
|
|
523
|
+
* Nécessite `status: "requires_capture"`.
|
|
524
|
+
* Passe en `"succeeded"` après capture.
|
|
525
|
+
*
|
|
526
|
+
* @param id - Identifiant du PaymentIntent (format `pi_xxx`)
|
|
527
|
+
* @param payloads - Montant à capturer (≤ montant original, optionnel)
|
|
528
|
+
* @returns Le PaymentIntent capturé
|
|
529
|
+
*
|
|
530
|
+
* @example
|
|
531
|
+
* await sangho.paymentIntents.capture("pi_xxx", { amount_to_capture: 3000 })
|
|
532
|
+
*/
|
|
533
|
+
capture(id: string, payloads?: CapturePayloads): Promise<PaymentIntent>;
|
|
534
|
+
/**
|
|
535
|
+
* Annule explicitement un PaymentIntent.
|
|
536
|
+
* Impossible si `status` vaut `"canceled"` ou `"succeeded"`.
|
|
537
|
+
*
|
|
538
|
+
* @param id - Identifiant du PaymentIntent (format `pi_xxx`)
|
|
539
|
+
* @param payloads - Raison d'annulation (défaut: `"requested_by_customer"`)
|
|
540
|
+
* @returns Le PaymentIntent annulé avec `status: "canceled"`
|
|
541
|
+
*
|
|
542
|
+
* @example
|
|
543
|
+
* await sangho.paymentIntents.cancel("pi_xxx", {
|
|
544
|
+
* cancellation_reason: "duplicate",
|
|
545
|
+
* })
|
|
546
|
+
*/
|
|
547
|
+
cancel(id: string, payloads?: CancelPayloads): Promise<PaymentIntent>;
|
|
548
|
+
/**
|
|
549
|
+
* Retourne les métadonnées DRF du endpoint `/payment-intents/` :
|
|
550
|
+
* actions autorisées, schéma de champs, formats acceptés.
|
|
551
|
+
*/
|
|
552
|
+
options(): Promise<DRFOptions>;
|
|
553
|
+
};
|
|
554
|
+
|
|
555
|
+
type CustomerStatus = "active" | "inactive" | "blocked";
|
|
556
|
+
interface Customer extends Timestamps {
|
|
557
|
+
id: string;
|
|
558
|
+
object: "customer";
|
|
559
|
+
app: string;
|
|
560
|
+
email: string;
|
|
561
|
+
name: string;
|
|
562
|
+
phone?: string | null;
|
|
563
|
+
address?: Address | null;
|
|
564
|
+
status: CustomerStatus;
|
|
565
|
+
is_blacklisted: boolean;
|
|
566
|
+
transactions_count: number;
|
|
567
|
+
total_spent: number;
|
|
568
|
+
metadata: Record<string, unknown>;
|
|
569
|
+
}
|
|
570
|
+
/** Champs requis à la création */
|
|
571
|
+
interface CreatePayloads$7 {
|
|
572
|
+
email: string;
|
|
573
|
+
name: string;
|
|
574
|
+
phone?: string;
|
|
575
|
+
metadata?: Record<string, unknown>;
|
|
576
|
+
}
|
|
577
|
+
/** Champs PATCH — tous optionnels */
|
|
578
|
+
interface Payloads$6 {
|
|
579
|
+
email?: string;
|
|
580
|
+
name?: string;
|
|
581
|
+
phone?: string;
|
|
582
|
+
status?: CustomerStatus;
|
|
583
|
+
metadata?: Record<string, unknown>;
|
|
584
|
+
}
|
|
585
|
+
/** Filtres GET /customers/ — alignés sur get_queryset() */
|
|
586
|
+
interface CustomerCriteria {
|
|
587
|
+
search?: string;
|
|
588
|
+
status?: CustomerStatus;
|
|
589
|
+
ordering?: string;
|
|
590
|
+
page?: number;
|
|
591
|
+
page_size?: number;
|
|
592
|
+
}
|
|
593
|
+
/** Filtres GET /customers/:id/transactions/ */
|
|
594
|
+
interface TransactionCriteria$1 {
|
|
595
|
+
page?: number;
|
|
596
|
+
page_size?: number;
|
|
597
|
+
ordering?: string;
|
|
598
|
+
}
|
|
599
|
+
|
|
600
|
+
type TransactionStatus = "approved" | "pending" | "completed" | "failed" | "refunded" | "disputed" | "canceled" | "cancelled";
|
|
601
|
+
type TransactionType = "deposit" | "refund" | "payout" | "withdraw" | "transfer";
|
|
602
|
+
/**
|
|
603
|
+
* Représente une transaction Sangho.
|
|
604
|
+
* Préfixe d'identifiant : `trans_xxx`
|
|
605
|
+
* Création impossible via API — résultat d'un PaymentIntent.
|
|
606
|
+
*/
|
|
607
|
+
interface Transaction extends Timestamps {
|
|
608
|
+
id: string;
|
|
609
|
+
object: "transaction";
|
|
610
|
+
amount: number;
|
|
611
|
+
fee: number;
|
|
612
|
+
commission: number;
|
|
613
|
+
commission_rate: number;
|
|
614
|
+
currency: "XAF";
|
|
615
|
+
status: TransactionStatus;
|
|
616
|
+
type: TransactionType;
|
|
617
|
+
description?: string | null;
|
|
618
|
+
payment_intent: string;
|
|
619
|
+
expiration_date?: string | null;
|
|
620
|
+
processed_at?: string | null;
|
|
621
|
+
metadata: Metadata;
|
|
622
|
+
}
|
|
623
|
+
/** Champs PATCH — uniquement description + metadata */
|
|
624
|
+
interface Payloads$5 {
|
|
625
|
+
description?: string;
|
|
626
|
+
metadata?: Metadata;
|
|
627
|
+
}
|
|
628
|
+
/** Filtres GET /transactions/ — alignés sur get_queryset() */
|
|
629
|
+
interface TransactionCriteria extends ListParams {
|
|
630
|
+
status?: TransactionStatus;
|
|
631
|
+
type?: TransactionType;
|
|
632
|
+
created_after?: string;
|
|
633
|
+
created_before?: string;
|
|
634
|
+
min_amount?: number;
|
|
635
|
+
max_amount?: number;
|
|
636
|
+
}
|
|
637
|
+
|
|
638
|
+
type PaymentMethodType$1 = "mobile_money" | "bank_card" | "paypal";
|
|
639
|
+
type MobileMoneyProvider = "orange" | "mtn" | "wave" | "airtel" | "moovv";
|
|
640
|
+
type CardBrand = "visa" | "mastercard" | "amex" | "discover" | "jcb" | "unionpay" | "local" | "unknown";
|
|
641
|
+
interface MobileMoneyDetails {
|
|
642
|
+
provider: MobileMoneyProvider;
|
|
643
|
+
phone_masked: string;
|
|
644
|
+
country: string;
|
|
645
|
+
}
|
|
646
|
+
interface BankCardDetails {
|
|
647
|
+
brand: CardBrand;
|
|
648
|
+
last4: string;
|
|
649
|
+
exp_month: number;
|
|
650
|
+
exp_year: number;
|
|
651
|
+
cardholder_name?: string;
|
|
652
|
+
funding: "credit" | "debit" | "prepaid" | "unknown";
|
|
653
|
+
country?: string;
|
|
654
|
+
}
|
|
655
|
+
interface PayPalDetails {
|
|
656
|
+
payer_id?: string;
|
|
657
|
+
}
|
|
658
|
+
/** Représente un mode de paiement Sangho. Préfixe : `meth_xxx` */
|
|
659
|
+
interface PaymentMethod extends Timestamps {
|
|
660
|
+
id: string;
|
|
661
|
+
object: "payment_method";
|
|
662
|
+
app: string;
|
|
663
|
+
customer?: string | null;
|
|
664
|
+
type: PaymentMethodType$1;
|
|
665
|
+
is_default: boolean;
|
|
666
|
+
mobile_money?: MobileMoneyDetails | null;
|
|
667
|
+
bank_card?: BankCardDetails | null;
|
|
668
|
+
paypal?: PayPalDetails | null;
|
|
669
|
+
metadata: Metadata;
|
|
670
|
+
}
|
|
671
|
+
interface AttachPayloads {
|
|
672
|
+
customer: string;
|
|
673
|
+
}
|
|
674
|
+
/** Filtres GET /payment-methods/ */
|
|
675
|
+
interface PaymentMethodCriteria extends ListParams {
|
|
676
|
+
customer?: string;
|
|
677
|
+
type?: PaymentMethodType$1;
|
|
678
|
+
}
|
|
679
|
+
|
|
680
|
+
type CustomersProperties = {
|
|
681
|
+
/**
|
|
682
|
+
* Liste les clients de l'app avec filtres optionnels.
|
|
683
|
+
* Recherche sur email, prénom et nom via `search`.
|
|
684
|
+
*
|
|
685
|
+
* @param criteria - Filtres optionnels (search, status, ordering, pagination)
|
|
686
|
+
* @returns Liste paginée de clients
|
|
687
|
+
*
|
|
688
|
+
* @example
|
|
689
|
+
* const all = await sangho.customers.list()
|
|
690
|
+
* const active = await sangho.customers.list({ status: "active" })
|
|
691
|
+
* const search = await sangho.customers.list({ search: "jean" })
|
|
692
|
+
*/
|
|
693
|
+
list(criteria?: CustomerCriteria): Promise<ListResponse<Customer>>;
|
|
694
|
+
/**
|
|
695
|
+
* Récupère un client par son identifiant.
|
|
696
|
+
*
|
|
697
|
+
* @param id - Identifiant du client (ex: `"cust_xxx"`)
|
|
698
|
+
* @returns Le client correspondant
|
|
699
|
+
*
|
|
700
|
+
* @example
|
|
701
|
+
* const customer = await sangho.customers.retrieve("cust_xxx")
|
|
702
|
+
*/
|
|
703
|
+
retrieve(id: string): Promise<Customer>;
|
|
704
|
+
/**
|
|
705
|
+
* Crée un nouveau client lié à l'app.
|
|
706
|
+
* Le champ `name` est automatiquement éclaté en `firstname`
|
|
707
|
+
* et `lastname` côté backend.
|
|
708
|
+
*
|
|
709
|
+
* @param payloads - `email` et `name` requis
|
|
710
|
+
* @returns Le client créé
|
|
711
|
+
*
|
|
712
|
+
* @example
|
|
713
|
+
* const customer = await sangho.customers.create({
|
|
714
|
+
* email: "jean@example.com",
|
|
715
|
+
* name: "Jean Ondo",
|
|
716
|
+
* })
|
|
717
|
+
*/
|
|
718
|
+
create(payloads: CreatePayloads$7): Promise<Customer>;
|
|
719
|
+
/**
|
|
720
|
+
* Met à jour partiellement un client (PATCH).
|
|
721
|
+
*
|
|
722
|
+
* @param id - Identifiant du client
|
|
723
|
+
* @param payloads - Champs à modifier (tous optionnels)
|
|
724
|
+
* @returns Le client mis à jour
|
|
725
|
+
*
|
|
726
|
+
* @example
|
|
727
|
+
* await sangho.customers.update("cust_xxx", { phone: "+24177000000" })
|
|
728
|
+
*/
|
|
729
|
+
update(id: string, payloads: Payloads$6): Promise<Customer>;
|
|
730
|
+
/**
|
|
731
|
+
* Supprime définitivement un client (hard delete).
|
|
732
|
+
* Le backend retourne HTTP 204 sans corps.
|
|
733
|
+
*
|
|
734
|
+
* @param id - Identifiant du client
|
|
735
|
+
*
|
|
736
|
+
* @example
|
|
737
|
+
* await sangho.customers.delete("cust_xxx")
|
|
738
|
+
*/
|
|
739
|
+
delete(id: string): Promise<void>;
|
|
740
|
+
/**
|
|
741
|
+
* Liste les transactions associées à un client.
|
|
742
|
+
*
|
|
743
|
+
* @param id - Identifiant du client
|
|
744
|
+
* @param criteria - Filtres de pagination optionnels
|
|
745
|
+
* @returns Liste paginée de transactions
|
|
746
|
+
*
|
|
747
|
+
* @example
|
|
748
|
+
* const txs = await sangho.customers.listTransactions("cust_xxx")
|
|
749
|
+
*
|
|
750
|
+
* @remarks Nécessite que l'action `GET /customers/:id/transactions/`
|
|
751
|
+
* soit déclarée côté backend (`@action` sur `CustomerViewSet`).
|
|
752
|
+
*/
|
|
753
|
+
listTransactions(id: string, criteria?: TransactionCriteria$1): Promise<ListResponse<Transaction>>;
|
|
754
|
+
/**
|
|
755
|
+
* Liste les modes de paiement enregistrés d'un client.
|
|
756
|
+
*
|
|
757
|
+
* @param id - Identifiant du client
|
|
758
|
+
* @returns Liste des modes de paiement
|
|
759
|
+
*
|
|
760
|
+
* @example
|
|
761
|
+
* const methods = await sangho.customers.listPaymentMethods("cust_xxx")
|
|
762
|
+
*
|
|
763
|
+
* @remarks Nécessite que l'action `GET /customers/:id/payment-methods/`
|
|
764
|
+
* soit déclarée côté backend (`@action` sur `CustomerViewSet`).
|
|
765
|
+
*/
|
|
766
|
+
listPaymentMethods(id: string): Promise<ListResponse<PaymentMethod>>;
|
|
767
|
+
/**
|
|
768
|
+
* Retourne les métadonnées DRF du endpoint `/customers/` :
|
|
769
|
+
* actions autorisées, schéma de champs, formats acceptés.
|
|
770
|
+
*/
|
|
771
|
+
options(): Promise<DRFOptions>;
|
|
772
|
+
};
|
|
773
|
+
|
|
774
|
+
type ProductStatus = "active" | "inactive" | "draft" | "archived";
|
|
775
|
+
/**
|
|
776
|
+
* Mappe `product_format` Django → type SDK via `get_type()`.
|
|
777
|
+
* `"physical"` et `"service"` sont les seuls choices Django natifs.
|
|
778
|
+
* `"digital"` est supporté par le mapping mais absent des choices.
|
|
779
|
+
*/
|
|
780
|
+
type ProductType = "physical" | "digital" | "service";
|
|
781
|
+
/**
|
|
782
|
+
* Image d'un produit — mappée depuis `ProductImageSerializer`.
|
|
783
|
+
* Pas de timestamps (absents des `Meta.fields`).
|
|
784
|
+
*/
|
|
785
|
+
interface ProductImage {
|
|
786
|
+
id: string;
|
|
787
|
+
product: string;
|
|
788
|
+
url: string;
|
|
789
|
+
alt?: string;
|
|
790
|
+
position: number;
|
|
791
|
+
is_primary: boolean;
|
|
792
|
+
}
|
|
793
|
+
/**
|
|
794
|
+
* Représente un produit Sangho.
|
|
795
|
+
* Préfixe d'identifiant : `prod_xxx`
|
|
796
|
+
*/
|
|
797
|
+
interface Product extends Timestamps {
|
|
798
|
+
id: string;
|
|
799
|
+
object: "product";
|
|
800
|
+
app: string;
|
|
801
|
+
name: string;
|
|
802
|
+
description?: string | null;
|
|
803
|
+
type: ProductType;
|
|
804
|
+
status: ProductStatus;
|
|
805
|
+
unit_amount: number;
|
|
806
|
+
currency: CurrencyCode;
|
|
807
|
+
stock?: number | null;
|
|
808
|
+
sku?: string | null;
|
|
809
|
+
is_shippable: boolean;
|
|
810
|
+
images: ProductImage[];
|
|
811
|
+
metadata: Metadata;
|
|
812
|
+
}
|
|
813
|
+
/** Champs POST — `name`, `unit_amount`, `currency` requis */
|
|
814
|
+
interface CreatePayloads$6 {
|
|
815
|
+
name: string;
|
|
816
|
+
description?: string;
|
|
817
|
+
type?: ProductType;
|
|
818
|
+
unit_amount: number;
|
|
819
|
+
currency: CurrencyCode;
|
|
820
|
+
stock?: number;
|
|
821
|
+
sku?: string;
|
|
822
|
+
is_shippable?: boolean;
|
|
823
|
+
metadata?: Metadata;
|
|
824
|
+
}
|
|
825
|
+
/** Champs PATCH — tous optionnels */
|
|
826
|
+
interface Payloads$4 {
|
|
827
|
+
name?: string;
|
|
828
|
+
description?: string;
|
|
829
|
+
type?: ProductType;
|
|
830
|
+
unit_amount?: number;
|
|
831
|
+
stock?: number;
|
|
832
|
+
sku?: string;
|
|
833
|
+
status?: ProductStatus;
|
|
834
|
+
is_shippable?: boolean;
|
|
835
|
+
metadata?: Metadata;
|
|
836
|
+
}
|
|
837
|
+
/** Filtres GET /products/ — alignés sur get_queryset() */
|
|
838
|
+
interface ProductCriteria extends ListParams {
|
|
839
|
+
status?: ProductStatus;
|
|
840
|
+
currency?: CurrencyCode;
|
|
841
|
+
}
|
|
842
|
+
|
|
843
|
+
type ProductsProperties = {
|
|
844
|
+
/**
|
|
845
|
+
* Liste les produits du catalogue avec filtres optionnels.
|
|
846
|
+
* Accessible avec clé publique ou secrète.
|
|
847
|
+
*
|
|
848
|
+
* @param criteria - Filtres (status, currency, search, ordering, pagination)
|
|
849
|
+
* @returns Liste paginée de produits
|
|
850
|
+
*
|
|
851
|
+
* @example
|
|
852
|
+
* const all = await sangho.products.list()
|
|
853
|
+
* const active = await sangho.products.list({ status: "active" })
|
|
854
|
+
* const search = await sangho.products.list({ search: "premium" })
|
|
855
|
+
*/
|
|
856
|
+
list(criteria?: ProductCriteria): Promise<ListResponse<Product>>;
|
|
857
|
+
/**
|
|
858
|
+
* Récupère un produit par son identifiant.
|
|
859
|
+
* Accessible avec clé publique ou secrète.
|
|
860
|
+
*
|
|
861
|
+
* @param id - Identifiant du produit (format `prod_xxx`)
|
|
862
|
+
* @returns Le produit correspondant
|
|
863
|
+
*
|
|
864
|
+
* @example
|
|
865
|
+
* const product = await sangho.products.retrieve("prod_xxx")
|
|
866
|
+
*/
|
|
867
|
+
retrieve(id: string): Promise<Product>;
|
|
868
|
+
/**
|
|
869
|
+
* Crée un nouveau produit dans le catalogue.
|
|
870
|
+
* Nécessite une clé secrète.
|
|
871
|
+
*
|
|
872
|
+
* @param payloads - `name`, `unit_amount` et `currency` requis
|
|
873
|
+
* @returns Le produit créé
|
|
874
|
+
*
|
|
875
|
+
* @example
|
|
876
|
+
* const product = await sangho.products.create({
|
|
877
|
+
* name: "Abonnement Premium",
|
|
878
|
+
* unit_amount: 9900,
|
|
879
|
+
* currency: "XAF",
|
|
880
|
+
* type: "service",
|
|
881
|
+
* })
|
|
882
|
+
*/
|
|
883
|
+
create(payloads: CreatePayloads$6): Promise<Product>;
|
|
884
|
+
/**
|
|
885
|
+
* Met à jour partiellement un produit (PATCH).
|
|
886
|
+
* Nécessite une clé secrète.
|
|
887
|
+
*
|
|
888
|
+
* @param id - Identifiant du produit (format `prod_xxx`)
|
|
889
|
+
* @param payloads - Champs à modifier (tous optionnels)
|
|
890
|
+
* @returns Le produit mis à jour
|
|
891
|
+
*
|
|
892
|
+
* @example
|
|
893
|
+
* await sangho.products.update("prod_xxx", { stock: 50 })
|
|
894
|
+
*/
|
|
895
|
+
update(id: string, payloads: Payloads$4): Promise<Product>;
|
|
896
|
+
/**
|
|
897
|
+
* Archive un produit (soft delete — `status: "archived"`).
|
|
898
|
+
* Le backend retourne HTTP 204 sans corps.
|
|
899
|
+
* Le produit reste accessible en lecture.
|
|
900
|
+
* Nécessite une clé secrète.
|
|
901
|
+
*
|
|
902
|
+
* @param id - Identifiant du produit (format `prod_xxx`)
|
|
903
|
+
*
|
|
904
|
+
* @example
|
|
905
|
+
* await sangho.products.delete("prod_xxx")
|
|
906
|
+
*
|
|
907
|
+
* @remarks
|
|
908
|
+
* Les actions dédiées `archive()` et `unarchive()` n'existent pas
|
|
909
|
+
* encore côté backend. Pour restaurer un produit archivé,
|
|
910
|
+
* utilisez `update(id, { status: "active" })`.
|
|
911
|
+
*/
|
|
912
|
+
delete(id: string): Promise<void>;
|
|
913
|
+
/**
|
|
914
|
+
* Retourne les métadonnées DRF du endpoint `/products/` :
|
|
915
|
+
* actions autorisées, schéma de champs, formats acceptés.
|
|
916
|
+
*/
|
|
917
|
+
options(): Promise<DRFOptions>;
|
|
918
|
+
};
|
|
919
|
+
|
|
920
|
+
type TransactionsProperties = {
|
|
921
|
+
/**
|
|
922
|
+
* Liste les transactions avec filtres optionnels.
|
|
923
|
+
* Les transactions sont créées automatiquement par les PaymentIntents —
|
|
924
|
+
* elles ne peuvent pas être créées via l'API.
|
|
925
|
+
*
|
|
926
|
+
* @param criteria - Filtres (status, type, montants, dates, pagination)
|
|
927
|
+
*/
|
|
928
|
+
list(criteria?: TransactionCriteria): Promise<ListResponse<Transaction>>;
|
|
929
|
+
/**
|
|
930
|
+
* Récupère une transaction par son identifiant.
|
|
931
|
+
* Ajouter `?expand=payment_intent` pour l'objet complet.
|
|
932
|
+
*
|
|
933
|
+
* @param id - Identifiant de la transaction (format `trans_xxx`)
|
|
934
|
+
*/
|
|
935
|
+
retrieve(id: string): Promise<Transaction>;
|
|
936
|
+
/**
|
|
937
|
+
* Met à jour la description ou les métadonnées d'une transaction (PATCH).
|
|
938
|
+
* Seuls `description` et `metadata` sont modifiables.
|
|
939
|
+
* Impossible sur les transactions dans un état final.
|
|
940
|
+
*
|
|
941
|
+
* @param id - Identifiant de la transaction
|
|
942
|
+
* @param payloads - `description` et/ou `metadata`
|
|
943
|
+
*/
|
|
944
|
+
update(id: string, payloads: Payloads$5): Promise<Transaction>;
|
|
945
|
+
/**
|
|
946
|
+
* Annule une transaction en statut `pending` ou `processing`.
|
|
947
|
+
* Impossible sur les transactions `completed`, `failed`, ou `cancelled`.
|
|
948
|
+
*
|
|
949
|
+
* @param id - Identifiant de la transaction (format `trans_xxx`)
|
|
950
|
+
*/
|
|
951
|
+
cancel(id: string): Promise<Transaction>;
|
|
952
|
+
/** Retourne les métadonnées DRF du endpoint `/transactions/`. */
|
|
953
|
+
options(): Promise<DRFOptions>;
|
|
954
|
+
};
|
|
955
|
+
|
|
956
|
+
type RefundStatus = "pending" | "processing" | "succeeded" | "failed" | "cancelled" | "expired";
|
|
957
|
+
type RefundReason = "duplicate" | "fraudulent" | "customer_request" | "product_issue" | "service_not_rendered";
|
|
958
|
+
/** Représente un remboursement Sangho. Préfixe : `refd_xxx` */
|
|
959
|
+
interface Refund extends Timestamps {
|
|
960
|
+
id: string;
|
|
961
|
+
object: "refund";
|
|
962
|
+
transaction: string;
|
|
963
|
+
amount: number;
|
|
964
|
+
currency: "XAF";
|
|
965
|
+
status: RefundStatus;
|
|
966
|
+
reason?: RefundReason | null;
|
|
967
|
+
description?: string | null;
|
|
968
|
+
failure_reason?: string | null;
|
|
969
|
+
metadata: Metadata;
|
|
970
|
+
}
|
|
971
|
+
/** Champs POST */
|
|
972
|
+
interface CreatePayloads$5 {
|
|
973
|
+
transaction: string;
|
|
974
|
+
amount?: number;
|
|
975
|
+
reason?: RefundReason;
|
|
976
|
+
description?: string;
|
|
977
|
+
metadata?: Metadata;
|
|
978
|
+
}
|
|
979
|
+
/** Filtres GET /refunds/ */
|
|
980
|
+
interface RefundCriteria extends ListParams {
|
|
981
|
+
transaction?: string;
|
|
982
|
+
status?: RefundStatus;
|
|
983
|
+
reason?: RefundReason;
|
|
984
|
+
}
|
|
985
|
+
|
|
986
|
+
type RefundsProperties = {
|
|
987
|
+
list(criteria?: RefundCriteria): Promise<ListResponse<Refund>>;
|
|
988
|
+
retrieve(id: string): Promise<Refund>;
|
|
989
|
+
/**
|
|
990
|
+
* Crée un remboursement sur une transaction réussie.
|
|
991
|
+
* Si `amount` est inférieur au montant original, le remboursement est partiel.
|
|
992
|
+
* @param payloads - `transaction` requis (ID `trans_xxx`)
|
|
993
|
+
*/
|
|
994
|
+
create(payloads: CreatePayloads$5): Promise<Refund>;
|
|
995
|
+
/**
|
|
996
|
+
* Annule un remboursement en statut `pending`.
|
|
997
|
+
* Impossible sur les remboursements `succeeded`, `failed` ou `expired`.
|
|
998
|
+
*/
|
|
999
|
+
cancel(id: string): Promise<Refund>;
|
|
1000
|
+
options(): Promise<DRFOptions>;
|
|
1001
|
+
};
|
|
1002
|
+
|
|
1003
|
+
type InvoiceStatus = "draft" | "open" | "paid" | "uncollectible" | "void";
|
|
1004
|
+
interface InvoiceLineItem {
|
|
1005
|
+
id?: string;
|
|
1006
|
+
description: string;
|
|
1007
|
+
quantity: number;
|
|
1008
|
+
unit_amount: number;
|
|
1009
|
+
amount: number;
|
|
1010
|
+
product?: string;
|
|
1011
|
+
metadata?: Metadata;
|
|
1012
|
+
}
|
|
1013
|
+
/** Ligne à fournir à la création */
|
|
1014
|
+
interface CreateLineItem {
|
|
1015
|
+
description: string;
|
|
1016
|
+
quantity: number;
|
|
1017
|
+
unit_amount: number;
|
|
1018
|
+
product?: string;
|
|
1019
|
+
metadata?: Metadata;
|
|
1020
|
+
}
|
|
1021
|
+
/**
|
|
1022
|
+
* Représente une facture Sangho.
|
|
1023
|
+
* Préfixe d'identifiant : `inv_xxx`
|
|
1024
|
+
* Devise fixe : XAF
|
|
1025
|
+
*/
|
|
1026
|
+
interface Invoice extends Timestamps {
|
|
1027
|
+
id: string;
|
|
1028
|
+
object: "invoice";
|
|
1029
|
+
app: string;
|
|
1030
|
+
customer: string;
|
|
1031
|
+
number: string;
|
|
1032
|
+
status: InvoiceStatus;
|
|
1033
|
+
currency: "XAF";
|
|
1034
|
+
subtotal: number;
|
|
1035
|
+
tax: number;
|
|
1036
|
+
tax_rate?: number | null;
|
|
1037
|
+
total: number;
|
|
1038
|
+
amount_paid: number;
|
|
1039
|
+
amount_remaining: number;
|
|
1040
|
+
description?: string | null;
|
|
1041
|
+
footer?: string | null;
|
|
1042
|
+
line_items: InvoiceLineItem[];
|
|
1043
|
+
due_date?: string | null;
|
|
1044
|
+
paid_at?: string | null;
|
|
1045
|
+
voided_at?: string | null;
|
|
1046
|
+
hosted_url?: string | null;
|
|
1047
|
+
pdf_url?: string | null;
|
|
1048
|
+
metadata: Metadata;
|
|
1049
|
+
}
|
|
1050
|
+
/** Champs POST */
|
|
1051
|
+
interface CreatePayloads$4 {
|
|
1052
|
+
customer: string;
|
|
1053
|
+
line_items: CreateLineItem[];
|
|
1054
|
+
description?: string;
|
|
1055
|
+
footer?: string;
|
|
1056
|
+
due_date?: string;
|
|
1057
|
+
tax_rate?: number;
|
|
1058
|
+
metadata?: Metadata;
|
|
1059
|
+
/** Si true, passe immédiatement en `"open"` et envoie par email */
|
|
1060
|
+
send_immediately?: boolean;
|
|
1061
|
+
}
|
|
1062
|
+
/** Champs PATCH — uniquement sur factures `draft` */
|
|
1063
|
+
interface Payloads$3 {
|
|
1064
|
+
description?: string;
|
|
1065
|
+
footer?: string;
|
|
1066
|
+
due_date?: string;
|
|
1067
|
+
tax_rate?: number;
|
|
1068
|
+
metadata?: Metadata;
|
|
1069
|
+
}
|
|
1070
|
+
/** Filtres GET /invoices/ */
|
|
1071
|
+
interface InvoiceCriteria extends ListParams {
|
|
1072
|
+
customer?: string;
|
|
1073
|
+
status?: InvoiceStatus;
|
|
1074
|
+
currency?: string;
|
|
1075
|
+
due_date_before?: string;
|
|
1076
|
+
due_date_after?: string;
|
|
1077
|
+
}
|
|
1078
|
+
|
|
1079
|
+
type InvoicesProperties = {
|
|
1080
|
+
/**
|
|
1081
|
+
* Liste les factures avec filtres optionnels.
|
|
1082
|
+
*
|
|
1083
|
+
* @param criteria - Filtres (customer, status, currency, due_date, pagination)
|
|
1084
|
+
*/
|
|
1085
|
+
list(criteria?: InvoiceCriteria): Promise<ListResponse<Invoice>>;
|
|
1086
|
+
/**
|
|
1087
|
+
* Récupère une facture par son identifiant.
|
|
1088
|
+
*
|
|
1089
|
+
* @param id - Identifiant de la facture (format `inv_xxx`)
|
|
1090
|
+
*/
|
|
1091
|
+
retrieve(id: string): Promise<Invoice>;
|
|
1092
|
+
/**
|
|
1093
|
+
* Crée une nouvelle facture en statut `draft`.
|
|
1094
|
+
* Si `send_immediately: true`, passe directement en `open`.
|
|
1095
|
+
*
|
|
1096
|
+
* @param payloads - `customer` et `line_items` requis
|
|
1097
|
+
*/
|
|
1098
|
+
create(payloads: CreatePayloads$4): Promise<Invoice>;
|
|
1099
|
+
/**
|
|
1100
|
+
* Met à jour une facture en statut `draft` (PATCH).
|
|
1101
|
+
* Impossible sur les factures `open`, `paid`, `void` ou `uncollectible`.
|
|
1102
|
+
*
|
|
1103
|
+
* @param id - Identifiant de la facture
|
|
1104
|
+
* @param payloads - Champs modifiables (description, footer, due_date, tax_rate)
|
|
1105
|
+
*/
|
|
1106
|
+
update(id: string, payloads: Payloads$3): Promise<Invoice>;
|
|
1107
|
+
/**
|
|
1108
|
+
* Supprime définitivement une facture.
|
|
1109
|
+
* Uniquement possible si `status === "draft"`.
|
|
1110
|
+
* Retourne HTTP 204 sans corps.
|
|
1111
|
+
*
|
|
1112
|
+
* @param id - Identifiant de la facture
|
|
1113
|
+
*/
|
|
1114
|
+
delete(id: string): Promise<void>;
|
|
1115
|
+
/**
|
|
1116
|
+
* Finalise et envoie une facture draft.
|
|
1117
|
+
* Passe en `status: "open"`.
|
|
1118
|
+
*
|
|
1119
|
+
* @param id - Identifiant de la facture
|
|
1120
|
+
*/
|
|
1121
|
+
send(id: string): Promise<Invoice>;
|
|
1122
|
+
/**
|
|
1123
|
+
* Marque une facture ouverte comme payée manuellement.
|
|
1124
|
+
* Passe en `status: "paid"`, peuple `paid_at` et `amount_paid`.
|
|
1125
|
+
*
|
|
1126
|
+
* @param id - Identifiant de la facture
|
|
1127
|
+
*/
|
|
1128
|
+
pay(id: string): Promise<Invoice>;
|
|
1129
|
+
/**
|
|
1130
|
+
* Annule une facture ouverte.
|
|
1131
|
+
* Passe en `status: "void"`, peuple `voided_at`.
|
|
1132
|
+
* Impossible sur les factures `paid` ou déjà `void`.
|
|
1133
|
+
*
|
|
1134
|
+
* @param id - Identifiant de la facture
|
|
1135
|
+
*/
|
|
1136
|
+
void(id: string): Promise<Invoice>;
|
|
1137
|
+
/**
|
|
1138
|
+
* Marque une facture ouverte comme irrécupérable.
|
|
1139
|
+
* Passe en `status: "uncollectible"`.
|
|
1140
|
+
*
|
|
1141
|
+
* @param id - Identifiant de la facture
|
|
1142
|
+
*/
|
|
1143
|
+
markUncollectible(id: string): Promise<Invoice>;
|
|
1144
|
+
/**
|
|
1145
|
+
* Retourne l'URL de téléchargement PDF d'une facture.
|
|
1146
|
+
* L'URL expire après 1 heure.
|
|
1147
|
+
*
|
|
1148
|
+
* @param id - Identifiant de la facture
|
|
1149
|
+
* @returns URL temporaire + date d'expiration ISO 8601
|
|
1150
|
+
*/
|
|
1151
|
+
getPdfUrl(id: string): Promise<{
|
|
1152
|
+
url: string;
|
|
1153
|
+
expires_at: string;
|
|
1154
|
+
}>;
|
|
1155
|
+
/** Retourne les métadonnées DRF du endpoint `/invoices/`. */
|
|
1156
|
+
options(): Promise<DRFOptions>;
|
|
1157
|
+
};
|
|
1158
|
+
|
|
1159
|
+
type PaymentLinkStatus = "active" | "inactive" | "archived";
|
|
1160
|
+
type PaymentLinkType = "product" | "custom" | "donation";
|
|
1161
|
+
type PaymentLinkValidityType = "unlimited" | "limited" | "one_time";
|
|
1162
|
+
interface PaymentLinkRedirectUrl {
|
|
1163
|
+
success?: string;
|
|
1164
|
+
cancel?: string;
|
|
1165
|
+
}
|
|
1166
|
+
/**
|
|
1167
|
+
* Représente un PaymentLink Sangho.
|
|
1168
|
+
* `products` contient des IDs string par défaut,
|
|
1169
|
+
* ou des objets Product complets si `?expand=products`.
|
|
1170
|
+
*/
|
|
1171
|
+
interface PaymentLink extends Timestamps {
|
|
1172
|
+
id: string;
|
|
1173
|
+
object: "payment_link";
|
|
1174
|
+
name?: string | null;
|
|
1175
|
+
description?: string | null;
|
|
1176
|
+
url: string;
|
|
1177
|
+
status: PaymentLinkStatus;
|
|
1178
|
+
currency: CurrencyCode;
|
|
1179
|
+
amount: number;
|
|
1180
|
+
full_amount: string;
|
|
1181
|
+
minimum_amount?: number | null;
|
|
1182
|
+
maximum_amount?: number | null;
|
|
1183
|
+
tax_amount?: number | null;
|
|
1184
|
+
discount_amount?: number | null;
|
|
1185
|
+
shipping_amount?: number | null;
|
|
1186
|
+
payment_link_type: PaymentLinkType;
|
|
1187
|
+
validity_type: PaymentLinkValidityType;
|
|
1188
|
+
expires_at?: string | null;
|
|
1189
|
+
max_usage?: number | null;
|
|
1190
|
+
redirect_url: PaymentLinkRedirectUrl;
|
|
1191
|
+
products: string[];
|
|
1192
|
+
product_quantity_settings: Record<string, number>;
|
|
1193
|
+
custom_fields: unknown[];
|
|
1194
|
+
advanced_options: Record<string, unknown>;
|
|
1195
|
+
metadata: Metadata;
|
|
1196
|
+
}
|
|
1197
|
+
/** Champs POST — alignés sur PaymentLinkSerializer + PaymentLinkValidator */
|
|
1198
|
+
interface CreatePayloads$3 {
|
|
1199
|
+
name?: string;
|
|
1200
|
+
description?: string;
|
|
1201
|
+
currency: CurrencyCode;
|
|
1202
|
+
payment_link_type?: PaymentLinkType;
|
|
1203
|
+
products?: string[];
|
|
1204
|
+
product_quantity_settings?: Record<string, number>;
|
|
1205
|
+
amount?: AmountInCents;
|
|
1206
|
+
minimum_amount?: AmountInCents;
|
|
1207
|
+
maximum_amount?: AmountInCents;
|
|
1208
|
+
redirect_url?: PaymentLinkRedirectUrl;
|
|
1209
|
+
max_usage?: number;
|
|
1210
|
+
validity_type?: PaymentLinkValidityType;
|
|
1211
|
+
expires_at?: string;
|
|
1212
|
+
custom_fields?: unknown[];
|
|
1213
|
+
advanced_options?: Record<string, unknown>;
|
|
1214
|
+
metadata?: Metadata;
|
|
1215
|
+
}
|
|
1216
|
+
/** Champs PATCH — tous optionnels */
|
|
1217
|
+
interface Payloads$2 {
|
|
1218
|
+
name?: string;
|
|
1219
|
+
description?: string;
|
|
1220
|
+
currency?: CurrencyCode;
|
|
1221
|
+
products?: string[];
|
|
1222
|
+
product_quantity_settings?: Record<string, number>;
|
|
1223
|
+
amount?: AmountInCents;
|
|
1224
|
+
minimum_amount?: AmountInCents;
|
|
1225
|
+
maximum_amount?: AmountInCents;
|
|
1226
|
+
redirect_url?: PaymentLinkRedirectUrl;
|
|
1227
|
+
max_usage?: number | null;
|
|
1228
|
+
validity_type?: PaymentLinkValidityType;
|
|
1229
|
+
expires_at?: string | null;
|
|
1230
|
+
custom_fields?: unknown[];
|
|
1231
|
+
advanced_options?: Record<string, unknown>;
|
|
1232
|
+
metadata?: Metadata;
|
|
1233
|
+
}
|
|
1234
|
+
/** Filtres GET /payment-links/ — alignés sur get_queryset() */
|
|
1235
|
+
interface PaymentLinkCriteria extends ListParams {
|
|
1236
|
+
status?: PaymentLinkStatus;
|
|
1237
|
+
currency?: CurrencyCode;
|
|
1238
|
+
}
|
|
1239
|
+
|
|
1240
|
+
type PaymentLinksProperties = {
|
|
1241
|
+
/**
|
|
1242
|
+
* Liste les liens de paiement avec filtres optionnels.
|
|
1243
|
+
*
|
|
1244
|
+
* @param criteria - Filtres (status, currency, search, ordering, pagination)
|
|
1245
|
+
* @returns Liste paginée de liens de paiement
|
|
1246
|
+
*
|
|
1247
|
+
* @example
|
|
1248
|
+
* const all = await sangho.paymentLinks.list()
|
|
1249
|
+
* const active = await sangho.paymentLinks.list({ status: "active" })
|
|
1250
|
+
* const search = await sangho.paymentLinks.list({ search: "promo" })
|
|
1251
|
+
*/
|
|
1252
|
+
list(criteria?: PaymentLinkCriteria): Promise<ListResponse<PaymentLink>>;
|
|
1253
|
+
/**
|
|
1254
|
+
* Récupère un lien de paiement par son identifiant.
|
|
1255
|
+
* Ajouter `?expand=products` pour obtenir les objets Product complets.
|
|
1256
|
+
*
|
|
1257
|
+
* @param id - Identifiant du lien (ex: `"link_xxx"`)
|
|
1258
|
+
* @returns Le lien de paiement correspondant
|
|
1259
|
+
*
|
|
1260
|
+
* @example
|
|
1261
|
+
* const link = await sangho.paymentLinks.retrieve("link_xxx")
|
|
1262
|
+
*/
|
|
1263
|
+
retrieve(id: string): Promise<PaymentLink>;
|
|
1264
|
+
/**
|
|
1265
|
+
* Crée un nouveau lien de paiement partageable.
|
|
1266
|
+
* Si `payment_link_type` vaut `"product"`, le champ `products` est requis.
|
|
1267
|
+
* Pour les autres types, `amount` et `currency` sont requis.
|
|
1268
|
+
*
|
|
1269
|
+
* @param payloads - Paramètres du lien (currency toujours requis)
|
|
1270
|
+
* @returns Le lien de paiement créé
|
|
1271
|
+
*
|
|
1272
|
+
* @example
|
|
1273
|
+
* const link = await sangho.paymentLinks.create({
|
|
1274
|
+
* currency: "XAF",
|
|
1275
|
+
* payment_link_type: "product",
|
|
1276
|
+
* products: ["prod_xxx"],
|
|
1277
|
+
* product_quantity_settings: { prod_xxx: 1 },
|
|
1278
|
+
* redirect_url: { success: "https://monsite.com/merci" },
|
|
1279
|
+
* })
|
|
1280
|
+
* console.log(link.url) // https://pay.sangho.ga/test/...
|
|
1281
|
+
*/
|
|
1282
|
+
create(payloads: CreatePayloads$3): Promise<PaymentLink>;
|
|
1283
|
+
/**
|
|
1284
|
+
* Met à jour partiellement un lien de paiement (PATCH).
|
|
1285
|
+
* PUT n'est pas supporté côté backend.
|
|
1286
|
+
*
|
|
1287
|
+
* @param id - Identifiant du lien
|
|
1288
|
+
* @param payloads - Champs à modifier (tous optionnels)
|
|
1289
|
+
* @returns Le lien mis à jour
|
|
1290
|
+
*
|
|
1291
|
+
* @example
|
|
1292
|
+
* await sangho.paymentLinks.update("link_xxx", {
|
|
1293
|
+
* max_usage: 100,
|
|
1294
|
+
* redirect_url: { success: "https://monsite.com/merci" },
|
|
1295
|
+
* })
|
|
1296
|
+
*/
|
|
1297
|
+
update(id: string, payloads: Payloads$2): Promise<PaymentLink>;
|
|
1298
|
+
/**
|
|
1299
|
+
* Archive un lien de paiement (soft delete).
|
|
1300
|
+
* Le backend ne supprime pas physiquement — l'historique est conservé.
|
|
1301
|
+
* Équivalent à `DELETE /payment-links/:id/` côté API.
|
|
1302
|
+
*
|
|
1303
|
+
* @param id - Identifiant du lien
|
|
1304
|
+
* @returns Le lien archivé (status: "archived")
|
|
1305
|
+
*
|
|
1306
|
+
* @example
|
|
1307
|
+
* const archived = await sangho.paymentLinks.delete("link_xxx")
|
|
1308
|
+
*/
|
|
1309
|
+
delete(id: string): Promise<PaymentLink>;
|
|
1310
|
+
/**
|
|
1311
|
+
* Archive explicitement un lien via `POST /payment-links/:id/archive/`.
|
|
1312
|
+
* Retourne une erreur si le lien est déjà archivé.
|
|
1313
|
+
*
|
|
1314
|
+
* @param id - Identifiant du lien
|
|
1315
|
+
* @returns Le lien archivé
|
|
1316
|
+
*
|
|
1317
|
+
* @example
|
|
1318
|
+
* await sangho.paymentLinks.archive("link_xxx")
|
|
1319
|
+
*/
|
|
1320
|
+
archive(id: string): Promise<PaymentLink>;
|
|
1321
|
+
/**
|
|
1322
|
+
* Restaure un lien archivé (`POST /payment-links/:id/restore/`).
|
|
1323
|
+
* Le lien repasse au statut `"active"`.
|
|
1324
|
+
* Retourne une erreur si le lien n'est pas archivé.
|
|
1325
|
+
*
|
|
1326
|
+
* @param id - Identifiant du lien
|
|
1327
|
+
* @returns Le lien restauré
|
|
1328
|
+
*
|
|
1329
|
+
* @example
|
|
1330
|
+
* await sangho.paymentLinks.restore("link_xxx")
|
|
1331
|
+
*/
|
|
1332
|
+
restore(id: string): Promise<PaymentLink>;
|
|
1333
|
+
/**
|
|
1334
|
+
* Retourne les métadonnées DRF du endpoint `/payment-links/` :
|
|
1335
|
+
* actions autorisées, schéma de champs, formats acceptés.
|
|
1336
|
+
*/
|
|
1337
|
+
options(): Promise<DRFOptions>;
|
|
1338
|
+
};
|
|
1339
|
+
|
|
1340
|
+
type CheckoutSessionStatus = "open" | "complete" | "expired" | "payment_failed" | "processing";
|
|
1341
|
+
type CheckoutMode = "payment" | "subscription" | "setup";
|
|
1342
|
+
/** Ligne de commande — type local, découplé de payment-links */
|
|
1343
|
+
interface LineItem {
|
|
1344
|
+
product: string;
|
|
1345
|
+
quantity: number;
|
|
1346
|
+
unit_amount?: number;
|
|
1347
|
+
name?: string;
|
|
1348
|
+
currency?: CurrencyCode;
|
|
1349
|
+
}
|
|
1350
|
+
/**
|
|
1351
|
+
* Représente une CheckoutSession Sangho.
|
|
1352
|
+
* Préfixe d'identifiant : `sess_xxx`
|
|
1353
|
+
*/
|
|
1354
|
+
interface CheckoutSession extends Timestamps {
|
|
1355
|
+
id: string;
|
|
1356
|
+
object: "checkout_session";
|
|
1357
|
+
app: string;
|
|
1358
|
+
url: string;
|
|
1359
|
+
status: CheckoutSessionStatus;
|
|
1360
|
+
mode: CheckoutMode;
|
|
1361
|
+
customer?: string | null;
|
|
1362
|
+
customer_email?: string | null;
|
|
1363
|
+
currency: CurrencyCode;
|
|
1364
|
+
amount_total: AmountInCents;
|
|
1365
|
+
shipping_amount?: number | null;
|
|
1366
|
+
discount_amount?: number | null;
|
|
1367
|
+
line_items: LineItem[];
|
|
1368
|
+
success_url: string;
|
|
1369
|
+
cancel_url?: string | null;
|
|
1370
|
+
payment_intent?: string | null;
|
|
1371
|
+
subscription?: string | null;
|
|
1372
|
+
expires_at: string;
|
|
1373
|
+
metadata: Metadata;
|
|
1374
|
+
}
|
|
1375
|
+
/** Champs POST — `success_url`, `line_items`, `currency` requis */
|
|
1376
|
+
interface CreatePayloads$2 {
|
|
1377
|
+
success_url: string;
|
|
1378
|
+
line_items: LineItem[];
|
|
1379
|
+
currency: CurrencyCode;
|
|
1380
|
+
mode?: CheckoutMode;
|
|
1381
|
+
customer?: string;
|
|
1382
|
+
customer_email?: string;
|
|
1383
|
+
cancel_url?: string;
|
|
1384
|
+
shipping_amount?: AmountInCents;
|
|
1385
|
+
discount_amount?: AmountInCents;
|
|
1386
|
+
payment_method_types?: string[];
|
|
1387
|
+
/** Durée de validité en secondes (défaut: 1800, max: 86400) */
|
|
1388
|
+
expires_in?: number;
|
|
1389
|
+
metadata?: Metadata;
|
|
1390
|
+
}
|
|
1391
|
+
/** Filtres GET /checkout-sessions/ */
|
|
1392
|
+
interface CheckoutSessionCriteria extends ListParams {
|
|
1393
|
+
status?: CheckoutSessionStatus;
|
|
1394
|
+
mode?: CheckoutMode;
|
|
1395
|
+
customer?: string;
|
|
1396
|
+
created_after?: string;
|
|
1397
|
+
created_before?: string;
|
|
1398
|
+
}
|
|
1399
|
+
|
|
1400
|
+
type CheckoutSessionsProperties = {
|
|
1401
|
+
/**
|
|
1402
|
+
* Liste les sessions de checkout avec filtres optionnels.
|
|
1403
|
+
*
|
|
1404
|
+
* @param criteria - Filtres (status, mode, customer, dates, pagination)
|
|
1405
|
+
* @returns Liste paginée de sessions
|
|
1406
|
+
*
|
|
1407
|
+
* @example
|
|
1408
|
+
* const all = await sangho.checkoutSessions.list()
|
|
1409
|
+
* const open = await sangho.checkoutSessions.list({ status: "open" })
|
|
1410
|
+
* const subs = await sangho.checkoutSessions.list({ mode: "subscription" })
|
|
1411
|
+
*/
|
|
1412
|
+
list(criteria?: CheckoutSessionCriteria): Promise<ListResponse<CheckoutSession>>;
|
|
1413
|
+
/**
|
|
1414
|
+
* Récupère une session de checkout par son identifiant.
|
|
1415
|
+
* Si la session est expirée mais encore marquée `"open"`,
|
|
1416
|
+
* le backend la bascule automatiquement en `"expired"`.
|
|
1417
|
+
* Accessible avec clé publique ou secrète.
|
|
1418
|
+
*
|
|
1419
|
+
* @param id - Identifiant de la session (format `sess_xxx`)
|
|
1420
|
+
*/
|
|
1421
|
+
retrieve(id: string): Promise<CheckoutSession>;
|
|
1422
|
+
/**
|
|
1423
|
+
* Crée une session de checkout hébergée.
|
|
1424
|
+
* En mode `"payment"`, un PaymentIntent est automatiquement créé.
|
|
1425
|
+
* `success_url`, `line_items` et `currency` sont requis.
|
|
1426
|
+
*
|
|
1427
|
+
* @param payloads - Paramètres de la session
|
|
1428
|
+
* @returns La session avec son URL de redirection
|
|
1429
|
+
*
|
|
1430
|
+
* @example
|
|
1431
|
+
* const session = await sangho.checkoutSessions.create({
|
|
1432
|
+
* success_url: "https://monsite.com/merci",
|
|
1433
|
+
* cancel_url: "https://monsite.com/annulation",
|
|
1434
|
+
* currency: "XAF",
|
|
1435
|
+
* line_items: [{ product: "prod_xxx", quantity: 1 }],
|
|
1436
|
+
* })
|
|
1437
|
+
* window.location.href = session.url
|
|
1438
|
+
*/
|
|
1439
|
+
create(payloads: CreatePayloads$2): Promise<CheckoutSession>;
|
|
1440
|
+
/**
|
|
1441
|
+
* Expire manuellement une session ouverte
|
|
1442
|
+
* (`POST /checkout-sessions/:id/expire/`).
|
|
1443
|
+
* Retourne une erreur si la session n'est pas en statut `"open"`.
|
|
1444
|
+
* Équivalent à `DELETE /checkout-sessions/:id/`.
|
|
1445
|
+
*
|
|
1446
|
+
* @param id - Identifiant de la session (format `sess_xxx`)
|
|
1447
|
+
* @returns La session expirée
|
|
1448
|
+
*
|
|
1449
|
+
* @example
|
|
1450
|
+
* await sangho.checkoutSessions.expire("sess_xxx")
|
|
1451
|
+
*/
|
|
1452
|
+
expire(id: string): Promise<CheckoutSession>;
|
|
1453
|
+
/**
|
|
1454
|
+
* Alias de `expire()` — expire la session au lieu de la supprimer.
|
|
1455
|
+
* Le backend ne supprime pas physiquement les sessions.
|
|
1456
|
+
*
|
|
1457
|
+
* @param id - Identifiant de la session (format `sess_xxx`)
|
|
1458
|
+
*/
|
|
1459
|
+
delete(id: string): Promise<CheckoutSession>;
|
|
1460
|
+
/**
|
|
1461
|
+
* Retourne les métadonnées DRF du endpoint `/checkout-sessions/`.
|
|
1462
|
+
*/
|
|
1463
|
+
options(): Promise<DRFOptions>;
|
|
1464
|
+
};
|
|
1465
|
+
|
|
1466
|
+
type SubscriptionStatus = "trialing" | "active" | "past_due" | "paused" | "canceled" | "unpaid" | "expired";
|
|
1467
|
+
type BillingInterval = "day" | "week" | "month" | "year";
|
|
1468
|
+
type CollectionMethod = "charge_automatically" | "send_invoice";
|
|
1469
|
+
/**
|
|
1470
|
+
* Représente un abonnement Sangho.
|
|
1471
|
+
* Préfixe d'identifiant : `sub_xxx`
|
|
1472
|
+
*/
|
|
1473
|
+
interface Subscription extends Timestamps {
|
|
1474
|
+
id: string;
|
|
1475
|
+
object: "subscription";
|
|
1476
|
+
app: string;
|
|
1477
|
+
customer: string;
|
|
1478
|
+
status: SubscriptionStatus;
|
|
1479
|
+
currency: "XAF";
|
|
1480
|
+
unit_amount: number;
|
|
1481
|
+
interval: BillingInterval;
|
|
1482
|
+
interval_count: number;
|
|
1483
|
+
collection_method: CollectionMethod;
|
|
1484
|
+
current_period_start: string;
|
|
1485
|
+
current_period_end: string;
|
|
1486
|
+
trial_start?: string | null;
|
|
1487
|
+
trial_end?: string | null;
|
|
1488
|
+
canceled_at?: string | null;
|
|
1489
|
+
cancel_at_period_end: boolean;
|
|
1490
|
+
product?: string | null;
|
|
1491
|
+
payment_method?: string | null;
|
|
1492
|
+
metadata: Metadata;
|
|
1493
|
+
}
|
|
1494
|
+
/** Champs POST */
|
|
1495
|
+
interface CreatePayloads$1 {
|
|
1496
|
+
customer: string;
|
|
1497
|
+
unit_amount: number;
|
|
1498
|
+
interval: BillingInterval;
|
|
1499
|
+
interval_count?: number;
|
|
1500
|
+
product?: string;
|
|
1501
|
+
payment_method?: string;
|
|
1502
|
+
collection_method?: CollectionMethod;
|
|
1503
|
+
trial_period_days?: number;
|
|
1504
|
+
cancel_at_period_end?: boolean;
|
|
1505
|
+
metadata?: Metadata;
|
|
1506
|
+
}
|
|
1507
|
+
/** Champs PATCH */
|
|
1508
|
+
interface Payloads$1 {
|
|
1509
|
+
unit_amount?: number;
|
|
1510
|
+
payment_method?: string;
|
|
1511
|
+
collection_method?: CollectionMethod;
|
|
1512
|
+
cancel_at_period_end?: boolean;
|
|
1513
|
+
metadata?: Metadata;
|
|
1514
|
+
}
|
|
1515
|
+
/** Filtres GET /subscriptions/ */
|
|
1516
|
+
interface SubscriptionCriteria extends ListParams {
|
|
1517
|
+
customer?: string;
|
|
1518
|
+
status?: SubscriptionStatus;
|
|
1519
|
+
currency?: string;
|
|
1520
|
+
}
|
|
1521
|
+
|
|
1522
|
+
type SubscriptionsProperties = {
|
|
1523
|
+
list(criteria?: SubscriptionCriteria): Promise<ListResponse<Subscription>>;
|
|
1524
|
+
retrieve(id: string): Promise<Subscription>;
|
|
1525
|
+
/**
|
|
1526
|
+
* Crée un abonnement récurrent.
|
|
1527
|
+
* Si `trial_period_days > 0`, démarre en statut `"trialing"`.
|
|
1528
|
+
* @param payloads - `customer`, `unit_amount` et `interval` requis
|
|
1529
|
+
*/
|
|
1530
|
+
create(payloads: CreatePayloads$1): Promise<Subscription>;
|
|
1531
|
+
update(id: string, payloads: Payloads$1): Promise<Subscription>;
|
|
1532
|
+
/**
|
|
1533
|
+
* Annule un abonnement.
|
|
1534
|
+
* `cancel_at_period_end: true` (défaut) → annulation à la fin de la période.
|
|
1535
|
+
* `cancel_at_period_end: false` → annulation immédiate.
|
|
1536
|
+
*/
|
|
1537
|
+
cancel(id: string, payloads?: {
|
|
1538
|
+
cancel_at_period_end?: boolean;
|
|
1539
|
+
}): Promise<Subscription>;
|
|
1540
|
+
/** Réactive un abonnement `canceled`, `past_due` ou `unpaid`. */
|
|
1541
|
+
reactivate(id: string): Promise<Subscription>;
|
|
1542
|
+
/** Suspend un abonnement actif (passe en `"paused"`). */
|
|
1543
|
+
pause(id: string): Promise<Subscription>;
|
|
1544
|
+
/** Reprend un abonnement `"paused"`. */
|
|
1545
|
+
resume(id: string): Promise<Subscription>;
|
|
1546
|
+
options(): Promise<DRFOptions>;
|
|
1547
|
+
};
|
|
1548
|
+
|
|
1549
|
+
type PaymentMethodsProperties = {
|
|
1550
|
+
list(criteria?: PaymentMethodCriteria): Promise<ListResponse<PaymentMethod>>;
|
|
1551
|
+
retrieve(id: string): Promise<PaymentMethod>;
|
|
1552
|
+
/**
|
|
1553
|
+
* Attache un mode de paiement à un client.
|
|
1554
|
+
* @param id - Identifiant du mode de paiement (`meth_xxx`)
|
|
1555
|
+
* @param payloads - `customer` requis
|
|
1556
|
+
*/
|
|
1557
|
+
attach(id: string, payloads: AttachPayloads): Promise<PaymentMethod>;
|
|
1558
|
+
/** Détache un mode de paiement de son client. */
|
|
1559
|
+
detach(id: string): Promise<PaymentMethod>;
|
|
1560
|
+
/** Définit un mode de paiement comme défaut pour son client. */
|
|
1561
|
+
setDefault(id: string): Promise<PaymentMethod>;
|
|
1562
|
+
options(): Promise<DRFOptions>;
|
|
1563
|
+
};
|
|
1564
|
+
|
|
1565
|
+
type ReceiptStatus = "draft" | "issued" | "voided" | "archived";
|
|
1566
|
+
type PaymentMethodType = "card" | "mobile_money" | "bank_transfer" | "e_wallet";
|
|
1567
|
+
interface ReceiptItem {
|
|
1568
|
+
id: string;
|
|
1569
|
+
description: string;
|
|
1570
|
+
quantity: number;
|
|
1571
|
+
unit_amount: number;
|
|
1572
|
+
amount: number;
|
|
1573
|
+
currency: "XAF";
|
|
1574
|
+
}
|
|
1575
|
+
/**
|
|
1576
|
+
* Représente un reçu Sangho.
|
|
1577
|
+
* Préfixe d'identifiant : `rec_xxx`
|
|
1578
|
+
* Devise fixe : XAF — en lecture seule.
|
|
1579
|
+
*/
|
|
1580
|
+
interface Receipt extends Timestamps {
|
|
1581
|
+
id: string;
|
|
1582
|
+
object: "receipt";
|
|
1583
|
+
app: string;
|
|
1584
|
+
number: string;
|
|
1585
|
+
customer: string;
|
|
1586
|
+
transaction?: string | null;
|
|
1587
|
+
status: ReceiptStatus;
|
|
1588
|
+
payment_method: PaymentMethodType;
|
|
1589
|
+
currency: "XAF";
|
|
1590
|
+
subtotal: number;
|
|
1591
|
+
tax: number;
|
|
1592
|
+
total: number;
|
|
1593
|
+
shipping_amount: number;
|
|
1594
|
+
discount_amount: number;
|
|
1595
|
+
items: ReceiptItem[];
|
|
1596
|
+
pdf_url?: string | null;
|
|
1597
|
+
issue_date: string;
|
|
1598
|
+
metadata: Metadata;
|
|
1599
|
+
}
|
|
1600
|
+
/** Filtres GET /receipts/ */
|
|
1601
|
+
interface ReceiptCriteria extends ListParams {
|
|
1602
|
+
customer?: string;
|
|
1603
|
+
transaction?: string;
|
|
1604
|
+
status?: ReceiptStatus;
|
|
1605
|
+
}
|
|
1606
|
+
|
|
1607
|
+
type ReceiptsProperties = {
|
|
1608
|
+
/**
|
|
1609
|
+
* Liste les reçus de l'app avec filtres optionnels.
|
|
1610
|
+
*
|
|
1611
|
+
* @param criteria - Filtres (customer, transaction, status, pagination)
|
|
1612
|
+
*
|
|
1613
|
+
* @example
|
|
1614
|
+
* const all = await sangho.receipts.list()
|
|
1615
|
+
* const paid = await sangho.receipts.list({ status: "issued" })
|
|
1616
|
+
*/
|
|
1617
|
+
list(criteria?: ReceiptCriteria): Promise<ListResponse<Receipt>>;
|
|
1618
|
+
/**
|
|
1619
|
+
* Récupère un reçu par son identifiant.
|
|
1620
|
+
*
|
|
1621
|
+
* @param id - Identifiant du reçu (format `rec_xxx`)
|
|
1622
|
+
*/
|
|
1623
|
+
retrieve(id: string): Promise<Receipt>;
|
|
1624
|
+
/**
|
|
1625
|
+
* Retourne l'URL de téléchargement PDF du reçu.
|
|
1626
|
+
* L'URL expire après 1 heure.
|
|
1627
|
+
*
|
|
1628
|
+
* @param id - Identifiant du reçu
|
|
1629
|
+
* @returns URL temporaire + date d'expiration ISO 8601
|
|
1630
|
+
*
|
|
1631
|
+
* @example
|
|
1632
|
+
* const { url } = await sangho.receipts.getPdfUrl("rec_xxx")
|
|
1633
|
+
* window.open(url)
|
|
1634
|
+
*/
|
|
1635
|
+
getPdfUrl(id: string): Promise<{
|
|
1636
|
+
url: string;
|
|
1637
|
+
expires_at: string;
|
|
1638
|
+
}>;
|
|
1639
|
+
/** Retourne les métadonnées DRF du endpoint `/receipts/`. */
|
|
1640
|
+
options(): Promise<DRFOptions>;
|
|
1641
|
+
};
|
|
1642
|
+
|
|
1643
|
+
type WebhookEventType = "payment_intent.created" | "payment_intent.succeeded" | "payment_intent.payment_failed" | "payment_intent.canceled" | "payment_intent.requires_action" | "transaction.created" | "transaction.succeeded" | "transaction.failed" | "transaction.refunded" | "customer.created" | "customer.updated" | "customer.deleted" | "invoice.created" | "invoice.paid" | "invoice.payment_failed" | "invoice.voided" | "subscription.created" | "subscription.updated" | "subscription.canceled" | "subscription.trial_ending" | "refund.created" | "refund.updated" | "refund.failed" | "checkout.session.completed" | "checkout.session.expired" | "payout.created" | "payout.paid" | "payout.failed";
|
|
1644
|
+
type WebhookStatus = "ACTIVE" | "INACTIVE" | "DISABLED";
|
|
1645
|
+
type WebhookSecurityProfile = "HMAC_SHA256" | "JWT" | "BASIC";
|
|
1646
|
+
type DeliveryStatus = "pending" | "delivered" | "failed" | "retrying";
|
|
1647
|
+
interface WebhookRetryPolicy {
|
|
1648
|
+
max_attempts: number;
|
|
1649
|
+
backoff_type: "linear" | "exponential";
|
|
1650
|
+
initial_delay_seconds: number;
|
|
1651
|
+
}
|
|
1652
|
+
/** Représente un webhook Sangho. Préfixe : `wh_xxx` */
|
|
1653
|
+
interface Webhook extends Timestamps {
|
|
1654
|
+
id: string;
|
|
1655
|
+
object: "webhook";
|
|
1656
|
+
app: string;
|
|
1657
|
+
name: string;
|
|
1658
|
+
url: string;
|
|
1659
|
+
status: WebhookStatus;
|
|
1660
|
+
events: WebhookEventType[];
|
|
1661
|
+
security_profile: WebhookSecurityProfile;
|
|
1662
|
+
secret_preview: string;
|
|
1663
|
+
ssl_verification: boolean;
|
|
1664
|
+
retry_policy: WebhookRetryPolicy;
|
|
1665
|
+
rate_limit: number;
|
|
1666
|
+
timeout: number;
|
|
1667
|
+
failure_count: number;
|
|
1668
|
+
last_delivery_at?: string | null;
|
|
1669
|
+
metadata: Metadata;
|
|
1670
|
+
}
|
|
1671
|
+
interface WebhookDelivery extends Timestamps {
|
|
1672
|
+
id: string;
|
|
1673
|
+
object: "webhook_delivery";
|
|
1674
|
+
webhook: string;
|
|
1675
|
+
event_type: WebhookEventType | "webhook.test";
|
|
1676
|
+
url: string;
|
|
1677
|
+
status: DeliveryStatus;
|
|
1678
|
+
http_status?: number | null;
|
|
1679
|
+
is_successful: boolean;
|
|
1680
|
+
attempts: number;
|
|
1681
|
+
next_retry_at?: string | null;
|
|
1682
|
+
response_body?: string | null;
|
|
1683
|
+
response_time_ms?: number | null;
|
|
1684
|
+
delivered_at?: string | null;
|
|
1685
|
+
metadata: Metadata;
|
|
1686
|
+
}
|
|
1687
|
+
/** Champs POST */
|
|
1688
|
+
interface CreatePayloads {
|
|
1689
|
+
name: string;
|
|
1690
|
+
url: string;
|
|
1691
|
+
events: WebhookEventType[];
|
|
1692
|
+
security_profile?: WebhookSecurityProfile;
|
|
1693
|
+
ssl_verification?: boolean;
|
|
1694
|
+
retry_policy?: Partial<WebhookRetryPolicy>;
|
|
1695
|
+
rate_limit?: number;
|
|
1696
|
+
timeout?: number;
|
|
1697
|
+
metadata?: Metadata;
|
|
1698
|
+
}
|
|
1699
|
+
/** Champs PATCH */
|
|
1700
|
+
interface Payloads {
|
|
1701
|
+
name?: string;
|
|
1702
|
+
url?: string;
|
|
1703
|
+
events?: WebhookEventType[];
|
|
1704
|
+
status?: WebhookStatus;
|
|
1705
|
+
security_profile?: WebhookSecurityProfile;
|
|
1706
|
+
ssl_verification?: boolean;
|
|
1707
|
+
retry_policy?: Partial<WebhookRetryPolicy>;
|
|
1708
|
+
rate_limit?: number;
|
|
1709
|
+
timeout?: number;
|
|
1710
|
+
metadata?: Metadata;
|
|
1711
|
+
}
|
|
1712
|
+
/** Filtres GET /webhooks/ */
|
|
1713
|
+
interface WebhookCriteria extends ListParams {
|
|
1714
|
+
status?: WebhookStatus;
|
|
1715
|
+
}
|
|
1716
|
+
/** Filtres GET /webhooks/:id/deliveries/ */
|
|
1717
|
+
interface DeliveryCriteria extends ListParams {
|
|
1718
|
+
event_type?: WebhookEventType;
|
|
1719
|
+
status?: DeliveryStatus;
|
|
1720
|
+
}
|
|
1721
|
+
|
|
1722
|
+
type WebhooksProperties = {
|
|
1723
|
+
list(criteria?: WebhookCriteria): Promise<ListResponse<Webhook>>;
|
|
1724
|
+
retrieve(id: string): Promise<Webhook>;
|
|
1725
|
+
/**
|
|
1726
|
+
* Crée un endpoint webhook.
|
|
1727
|
+
* Le secret de signature est retourné en clair une seule fois dans la réponse.
|
|
1728
|
+
* Stockez-le immédiatement — il ne sera plus accessible ensuite.
|
|
1729
|
+
*/
|
|
1730
|
+
create(payloads: CreatePayloads): Promise<Webhook & {
|
|
1731
|
+
secret: string;
|
|
1732
|
+
}>;
|
|
1733
|
+
update(id: string, payloads: Payloads): Promise<Webhook>;
|
|
1734
|
+
/** Supprime un webhook (HTTP 204). */
|
|
1735
|
+
delete(id: string): Promise<void>;
|
|
1736
|
+
/** Désactive un webhook sans le supprimer (passe en `"INACTIVE"`). */
|
|
1737
|
+
disable(id: string): Promise<Webhook>;
|
|
1738
|
+
/** Réactive un webhook désactivé (passe en `"ACTIVE"`). */
|
|
1739
|
+
enable(id: string): Promise<Webhook>;
|
|
1740
|
+
/**
|
|
1741
|
+
* Régénère le secret HMAC du webhook.
|
|
1742
|
+
* L'ancien secret est invalidé immédiatement.
|
|
1743
|
+
* @returns Le nouveau secret en clair (une seule fois)
|
|
1744
|
+
*/
|
|
1745
|
+
rollSecret(id: string): Promise<{
|
|
1746
|
+
secret: string;
|
|
1747
|
+
}>;
|
|
1748
|
+
/** Envoie un événement test au webhook pour vérifier la connectivité. */
|
|
1749
|
+
sendTestEvent(id: string): Promise<WebhookDelivery>;
|
|
1750
|
+
listDeliveries(id: string, criteria?: DeliveryCriteria): Promise<ListResponse<WebhookDelivery>>;
|
|
1751
|
+
retrieveDelivery(webhookId: string, deliveryId: string): Promise<WebhookDelivery>;
|
|
1752
|
+
/** Rejoue une livraison échouée. */
|
|
1753
|
+
retryDelivery(webhookId: string, deliveryId: string): Promise<WebhookDelivery>;
|
|
1754
|
+
options(): Promise<DRFOptions>;
|
|
1755
|
+
};
|
|
1756
|
+
|
|
1757
|
+
interface SecurityProfile extends Timestamps {
|
|
1758
|
+
id: string;
|
|
1759
|
+
app: string;
|
|
1760
|
+
/** IPs autorisées — liste vide = toutes autorisées */
|
|
1761
|
+
allowed_ips: string[];
|
|
1762
|
+
/** Montant max par transaction en centimes */
|
|
1763
|
+
max_transaction_amount?: AmountInCents;
|
|
1764
|
+
/** Montant max par jour en centimes */
|
|
1765
|
+
max_daily_amount?: AmountInCents;
|
|
1766
|
+
/** Nombre max de transactions par heure */
|
|
1767
|
+
max_hourly_transactions?: number;
|
|
1768
|
+
require_cvv: boolean;
|
|
1769
|
+
require_3ds: boolean;
|
|
1770
|
+
block_vpn: boolean;
|
|
1771
|
+
block_tor: boolean;
|
|
1772
|
+
allowed_countries: string[];
|
|
1773
|
+
}
|
|
1774
|
+
interface UpdateSecurityProfileParams {
|
|
1775
|
+
allowed_ips?: string[];
|
|
1776
|
+
max_transaction_amount?: AmountInCents;
|
|
1777
|
+
max_daily_amount?: AmountInCents;
|
|
1778
|
+
max_hourly_transactions?: number;
|
|
1779
|
+
require_cvv?: boolean;
|
|
1780
|
+
require_3ds?: boolean;
|
|
1781
|
+
block_vpn?: boolean;
|
|
1782
|
+
block_tor?: boolean;
|
|
1783
|
+
allowed_countries?: string[];
|
|
1784
|
+
}
|
|
1785
|
+
|
|
1786
|
+
type SecurityProperties = {
|
|
1787
|
+
/**
|
|
1788
|
+
* Récupère le profil de sécurité de l'application.
|
|
1789
|
+
*
|
|
1790
|
+
* @example
|
|
1791
|
+
* ```typescript
|
|
1792
|
+
* const profile = await sangho.security.retrieve()
|
|
1793
|
+
* console.log(profile.allowed_ips)
|
|
1794
|
+
* ```
|
|
1795
|
+
*/
|
|
1796
|
+
retrieve(): Promise<SecurityProfile>;
|
|
1797
|
+
/** Met à jour les paramètres de sécurité. */
|
|
1798
|
+
update(params: UpdateSecurityProfileParams): Promise<SecurityProfile>;
|
|
1799
|
+
/**
|
|
1800
|
+
* Ajoute des adresses IP à la liste blanche.
|
|
1801
|
+
*
|
|
1802
|
+
* @param ips - Liste d'IPs au format CIDR (ex: `["192.168.1.0/24"]`)
|
|
1803
|
+
*/
|
|
1804
|
+
addAllowedIps(ips: string[]): Promise<SecurityProfile>;
|
|
1805
|
+
/** Retire des adresses IP de la liste blanche. */
|
|
1806
|
+
removeAllowedIps(ips: string[]): Promise<SecurityProfile>;
|
|
1807
|
+
};
|
|
1808
|
+
|
|
1809
|
+
type PartnerStatus = "active" | "inactive";
|
|
1810
|
+
type PartnerService = "PAYMENT" | "FRAUD" | "KYC" | "SETTLEMENT";
|
|
1811
|
+
/** Représente un partenaire Sangho. Lecture seule. */
|
|
1812
|
+
interface Partner extends Timestamps {
|
|
1813
|
+
id: string;
|
|
1814
|
+
object: "partner";
|
|
1815
|
+
name: string;
|
|
1816
|
+
webhook_url: string;
|
|
1817
|
+
services: PartnerService[];
|
|
1818
|
+
status: PartnerStatus;
|
|
1819
|
+
last_used?: string | null;
|
|
1820
|
+
}
|
|
1821
|
+
/** Filtres GET /partners/ */
|
|
1822
|
+
interface PartnerCriteria extends ListParams {
|
|
1823
|
+
status?: PartnerStatus;
|
|
1824
|
+
}
|
|
1825
|
+
|
|
1826
|
+
type PartnersProperties = {
|
|
1827
|
+
/**
|
|
1828
|
+
* Liste les partenaires actifs de la plateforme.
|
|
1829
|
+
* Lecture seule — les partenaires ne peuvent pas être créés via l'API.
|
|
1830
|
+
*/
|
|
1831
|
+
list(criteria?: PartnerCriteria): Promise<ListResponse<Partner>>;
|
|
1832
|
+
/**
|
|
1833
|
+
* Récupère un partenaire par son identifiant.
|
|
1834
|
+
* @param id - Identifiant du partenaire
|
|
1835
|
+
*/
|
|
1836
|
+
retrieve(id: string): Promise<Partner>;
|
|
1837
|
+
options(): Promise<DRFOptions>;
|
|
1838
|
+
};
|
|
1839
|
+
|
|
1840
|
+
type ReaderType = "android" | "firmware" | "virtual";
|
|
1841
|
+
type ReaderStatus = "online" | "offline" | "disabled";
|
|
1842
|
+
type TerminalSessionStatus = "pending" | "payment_method_presented" | "processing" | "succeeded" | "failed" | "canceled" | "timed_out";
|
|
1843
|
+
type TerminalPaymentMethodType = "card" | "mobile_money" | "qr_code";
|
|
1844
|
+
type OfflineSyncStatus = "pending" | "syncing" | "synced" | "conflict" | "failed";
|
|
1845
|
+
interface TerminalReader extends Timestamps {
|
|
1846
|
+
id: string;
|
|
1847
|
+
object: "terminal_reader";
|
|
1848
|
+
app: string;
|
|
1849
|
+
label: string;
|
|
1850
|
+
serial_number: string;
|
|
1851
|
+
reader_type: ReaderType;
|
|
1852
|
+
location?: string | null;
|
|
1853
|
+
status: ReaderStatus;
|
|
1854
|
+
reader_token: string;
|
|
1855
|
+
reader_token_expires: string;
|
|
1856
|
+
last_seen_at?: string | null;
|
|
1857
|
+
metadata: Metadata;
|
|
1858
|
+
}
|
|
1859
|
+
interface CreateReaderPayloads {
|
|
1860
|
+
label: string;
|
|
1861
|
+
serial_number: string;
|
|
1862
|
+
reader_type?: ReaderType;
|
|
1863
|
+
location?: string;
|
|
1864
|
+
metadata?: Metadata;
|
|
1865
|
+
}
|
|
1866
|
+
interface ReaderCriteria extends ListParams {
|
|
1867
|
+
status?: ReaderStatus;
|
|
1868
|
+
reader_type?: ReaderType;
|
|
1869
|
+
}
|
|
1870
|
+
interface TerminalSession extends Timestamps {
|
|
1871
|
+
id: string;
|
|
1872
|
+
object: "terminal_session";
|
|
1873
|
+
app: string;
|
|
1874
|
+
reader_id: string;
|
|
1875
|
+
payment_intent_id: string | null;
|
|
1876
|
+
amount: number;
|
|
1877
|
+
currency: "XAF";
|
|
1878
|
+
status: TerminalSessionStatus;
|
|
1879
|
+
payment_method_type?: TerminalPaymentMethodType | null;
|
|
1880
|
+
failure_reason?: string | null;
|
|
1881
|
+
processor_ref?: string | null;
|
|
1882
|
+
client_secret: string;
|
|
1883
|
+
expires_at: string;
|
|
1884
|
+
metadata: Metadata;
|
|
1885
|
+
}
|
|
1886
|
+
interface CreateSessionPayloads {
|
|
1887
|
+
reader: string;
|
|
1888
|
+
amount: number;
|
|
1889
|
+
description?: string;
|
|
1890
|
+
category?: string;
|
|
1891
|
+
metadata?: Metadata;
|
|
1892
|
+
}
|
|
1893
|
+
interface PresentPaymentPayloads {
|
|
1894
|
+
payment_method_type: TerminalPaymentMethodType;
|
|
1895
|
+
nonce: string;
|
|
1896
|
+
}
|
|
1897
|
+
interface SessionStatus {
|
|
1898
|
+
id: string;
|
|
1899
|
+
status: TerminalSessionStatus;
|
|
1900
|
+
payment_intent_status: string | null;
|
|
1901
|
+
failure_reason: string | null;
|
|
1902
|
+
}
|
|
1903
|
+
interface SessionCriteria extends ListParams {
|
|
1904
|
+
status?: TerminalSessionStatus;
|
|
1905
|
+
reader?: string;
|
|
1906
|
+
}
|
|
1907
|
+
interface OfflineTransactionPayload {
|
|
1908
|
+
local_id: string;
|
|
1909
|
+
amount: number;
|
|
1910
|
+
payment_method_type: TerminalPaymentMethodType;
|
|
1911
|
+
card_token?: string;
|
|
1912
|
+
captured_at: string;
|
|
1913
|
+
reader_id?: string;
|
|
1914
|
+
metadata?: Metadata;
|
|
1915
|
+
}
|
|
1916
|
+
interface SyncPayloads {
|
|
1917
|
+
transactions: OfflineTransactionPayload[];
|
|
1918
|
+
}
|
|
1919
|
+
interface SyncResult {
|
|
1920
|
+
local_id: string;
|
|
1921
|
+
sync_status: OfflineSyncStatus;
|
|
1922
|
+
payment_intent?: string | null;
|
|
1923
|
+
error?: string;
|
|
1924
|
+
}
|
|
1925
|
+
interface SyncResponse {
|
|
1926
|
+
synced: number;
|
|
1927
|
+
results: SyncResult[];
|
|
1928
|
+
}
|
|
1929
|
+
interface OfflineTransaction extends Timestamps {
|
|
1930
|
+
id: string;
|
|
1931
|
+
object: "offline_transaction";
|
|
1932
|
+
app: string;
|
|
1933
|
+
local_id: string;
|
|
1934
|
+
amount: number;
|
|
1935
|
+
currency: "XAF";
|
|
1936
|
+
payment_method_type: TerminalPaymentMethodType;
|
|
1937
|
+
captured_at: string;
|
|
1938
|
+
sync_status: OfflineSyncStatus;
|
|
1939
|
+
synced_at?: string | null;
|
|
1940
|
+
payment_intent?: string | null;
|
|
1941
|
+
sync_error?: string | null;
|
|
1942
|
+
metadata: Metadata;
|
|
1943
|
+
}
|
|
1944
|
+
|
|
1945
|
+
type ReadersProperties = {
|
|
1946
|
+
/**
|
|
1947
|
+
* Liste tous les terminaux enregistrés pour l'application authentifiée.
|
|
1948
|
+
* Les résultats sont paginés et filtrables par statut ou type.
|
|
1949
|
+
*
|
|
1950
|
+
* @param criteria - Filtres optionnels
|
|
1951
|
+
* @returns Liste paginée des terminaux
|
|
1952
|
+
*
|
|
1953
|
+
* @example
|
|
1954
|
+
* // Tous les terminaux
|
|
1955
|
+
* const all = await sangho.terminal.readers.list()
|
|
1956
|
+
*
|
|
1957
|
+
* // Seulement les terminaux Android en ligne
|
|
1958
|
+
* const actifs = await sangho.terminal.readers.list({
|
|
1959
|
+
* reader_type: "android",
|
|
1960
|
+
* status: "online",
|
|
1961
|
+
* })
|
|
1962
|
+
*/
|
|
1963
|
+
list(criteria?: ReaderCriteria): Promise<ListResponse<TerminalReader>>;
|
|
1964
|
+
/**
|
|
1965
|
+
* Récupère un terminal par son identifiant.
|
|
1966
|
+
*
|
|
1967
|
+
* @param id - Identifiant du terminal (préfixe `rdr_`)
|
|
1968
|
+
* @returns Les données complètes du terminal
|
|
1969
|
+
*
|
|
1970
|
+
* @example
|
|
1971
|
+
* const reader = await sangho.terminal.readers.retrieve("rdr_xxx")
|
|
1972
|
+
* console.log(reader.status) // "online" | "offline" | "disabled"
|
|
1973
|
+
* console.log(reader.reader_type) // "android" | "firmware" | "virtual"
|
|
1974
|
+
*/
|
|
1975
|
+
retrieve(id: string): Promise<TerminalReader>;
|
|
1976
|
+
/**
|
|
1977
|
+
* Enregistre un nouveau terminal physique ou virtuel.
|
|
1978
|
+
* À appeler **une seule fois** lors du provisionnement du device.
|
|
1979
|
+
* Le `reader_token` retourné doit être stocké dans le keystore sécurisé
|
|
1980
|
+
* de l'appareil (Android Keystore, HSM firmware, etc.).
|
|
1981
|
+
*
|
|
1982
|
+
* @param payloads - Données d'enregistrement
|
|
1983
|
+
* @returns Le terminal créé avec son `reader_token` initial (valide 24h)
|
|
1984
|
+
*
|
|
1985
|
+
* @example
|
|
1986
|
+
* // Provisionnement d'un terminal Android Sunmi T2
|
|
1987
|
+
* const reader = await sangho.terminal.readers.create({
|
|
1988
|
+
* label: "Caisse 1 — Libreville",
|
|
1989
|
+
* serial_number: "SN-SUNMI-T2-001",
|
|
1990
|
+
* reader_type: "android",
|
|
1991
|
+
* location: "Magasin Owendo, Libreville",
|
|
1992
|
+
* metadata: { store_id: "store_owendo" },
|
|
1993
|
+
* })
|
|
1994
|
+
*
|
|
1995
|
+
* // Stocker reader.reader_token dans le keystore Android sécurisé
|
|
1996
|
+
* await secureStorage.set("reader_token", reader.reader_token)
|
|
1997
|
+
*/
|
|
1998
|
+
create(payloads: CreateReaderPayloads): Promise<TerminalReader>;
|
|
1999
|
+
/**
|
|
2000
|
+
* Met à jour les informations d'un terminal (mise à jour partielle).
|
|
2001
|
+
* Utile pour changer le label ou déplacer un terminal vers une autre localisation.
|
|
2002
|
+
*
|
|
2003
|
+
* @param id - Identifiant du terminal
|
|
2004
|
+
* @param payloads - Champs à modifier (tous optionnels)
|
|
2005
|
+
* @returns Le terminal mis à jour
|
|
2006
|
+
*
|
|
2007
|
+
* @example
|
|
2008
|
+
* const reader = await sangho.terminal.readers.update("rdr_xxx", {
|
|
2009
|
+
* label: "Caisse 2 — Owendo",
|
|
2010
|
+
* location: "Magasin Port, Libreville",
|
|
2011
|
+
* })
|
|
2012
|
+
*/
|
|
2013
|
+
update(id: string, payloads: Partial<CreateReaderPayloads>): Promise<TerminalReader>;
|
|
2014
|
+
/**
|
|
2015
|
+
* Désactive définitivement un terminal.
|
|
2016
|
+
* Un terminal désactivé ne peut plus créer de sessions ni signaler son heartbeat.
|
|
2017
|
+
* Opération irréversible depuis le SDK — la réactivation se fait via le dashboard.
|
|
2018
|
+
*
|
|
2019
|
+
* @param id - Identifiant du terminal à désactiver
|
|
2020
|
+
* @returns Le terminal avec `status: "disabled"`
|
|
2021
|
+
*
|
|
2022
|
+
* @example
|
|
2023
|
+
* // Terminal volé ou hors service
|
|
2024
|
+
* await sangho.terminal.readers.disable("rdr_xxx")
|
|
2025
|
+
*/
|
|
2026
|
+
disable(id: string): Promise<TerminalReader>;
|
|
2027
|
+
/**
|
|
2028
|
+
* Renouvelle le `reader_token` d'un terminal.
|
|
2029
|
+
* Le token a une durée de vie de **24h** ; à appeler automatiquement
|
|
2030
|
+
* au démarrage de l'application POS si `reader_token_expires` est dépassé.
|
|
2031
|
+
*
|
|
2032
|
+
* @param id - Identifiant du terminal
|
|
2033
|
+
* @returns Nouveau `reader_token` et sa date d'expiration `reader_token_expires`
|
|
2034
|
+
*
|
|
2035
|
+
* @example
|
|
2036
|
+
* const { reader_token, reader_token_expires } = await sangho.terminal.readers.refreshToken("rdr_xxx")
|
|
2037
|
+
* await secureStorage.set("reader_token", reader_token)
|
|
2038
|
+
* await secureStorage.set("reader_token_expires", reader_token_expires)
|
|
2039
|
+
*/
|
|
2040
|
+
refreshToken(id: string): Promise<{
|
|
2041
|
+
reader_token: string;
|
|
2042
|
+
reader_token_expires: string;
|
|
2043
|
+
}>;
|
|
2044
|
+
/**
|
|
2045
|
+
* Signale que le terminal est actif (keep-alive).
|
|
2046
|
+
* À appeler en tâche de fond **toutes les 30 secondes**.
|
|
2047
|
+
* Met à jour `last_seen_at` et maintient le statut `"online"`.
|
|
2048
|
+
* Un terminal sans heartbeat depuis > 2 min passe automatiquement en `"offline"`.
|
|
2049
|
+
*
|
|
2050
|
+
* @param id - Identifiant du terminal
|
|
2051
|
+
* @returns Statut courant et timestamp de dernière activité
|
|
2052
|
+
*
|
|
2053
|
+
* @example
|
|
2054
|
+
* // Background worker — toutes les 30s
|
|
2055
|
+
* setInterval(async () => {
|
|
2056
|
+
* const { status, last_seen_at } = await sangho.terminal.readers.heartbeat("rdr_xxx")
|
|
2057
|
+
* if (status === "offline") reinitialiserConnexion()
|
|
2058
|
+
* }, 30_000)
|
|
2059
|
+
*/
|
|
2060
|
+
heartbeat(id: string): Promise<{
|
|
2061
|
+
status: string;
|
|
2062
|
+
last_seen_at: string;
|
|
2063
|
+
}>;
|
|
2064
|
+
/**
|
|
2065
|
+
* Retourne les métadonnées DRF du endpoint `/terminal/readers/` :
|
|
2066
|
+
* actions autorisées, schéma de champs, filtres disponibles.
|
|
2067
|
+
*/
|
|
2068
|
+
options(): Promise<DRFOptions>;
|
|
2069
|
+
};
|
|
2070
|
+
type SessionsProperties = {
|
|
2071
|
+
/**
|
|
2072
|
+
* Liste les sessions de paiement terminal.
|
|
2073
|
+
* Filtrables par statut ou par terminal.
|
|
2074
|
+
*
|
|
2075
|
+
* @param criteria - Filtres optionnels
|
|
2076
|
+
* @returns Liste paginée des sessions
|
|
2077
|
+
*
|
|
2078
|
+
* @example
|
|
2079
|
+
* // Sessions en attente sur un terminal donné
|
|
2080
|
+
* const pending = await sangho.terminal.sessions.list({
|
|
2081
|
+
* reader: "rdr_xxx",
|
|
2082
|
+
* status: "pending",
|
|
2083
|
+
* })
|
|
2084
|
+
*/
|
|
2085
|
+
list(criteria?: SessionCriteria): Promise<ListResponse<TerminalSession>>;
|
|
2086
|
+
/**
|
|
2087
|
+
* Récupère une session de paiement terminal par son identifiant.
|
|
2088
|
+
*
|
|
2089
|
+
* @param id - Identifiant de la session (préfixe `tsess_`)
|
|
2090
|
+
* @returns Les données complètes de la session
|
|
2091
|
+
*
|
|
2092
|
+
* @example
|
|
2093
|
+
* const session = await sangho.terminal.sessions.retrieve("tsess_xxx")
|
|
2094
|
+
* console.log(session.status) // "pending" | "succeeded" | ...
|
|
2095
|
+
* console.log(session.amount) // montant en XAF
|
|
2096
|
+
*/
|
|
2097
|
+
retrieve(id: string): Promise<TerminalSession>;
|
|
2098
|
+
/**
|
|
2099
|
+
* Crée une nouvelle session de paiement sur un terminal.
|
|
2100
|
+
* Déclenche l'affichage du montant sur l'écran du terminal.
|
|
2101
|
+
* La session expire automatiquement après le délai configuré (`expires_at`).
|
|
2102
|
+
*
|
|
2103
|
+
* @param payloads - Données de la session (reader, amount requis)
|
|
2104
|
+
* @returns La session créée avec son `client_secret` (utilisé par le POS)
|
|
2105
|
+
*
|
|
2106
|
+
* @example
|
|
2107
|
+
* const session = await sangho.terminal.sessions.create({
|
|
2108
|
+
* reader: "rdr_xxx",
|
|
2109
|
+
* amount: 15_000, // 15 000 XAF
|
|
2110
|
+
* description: "Vente caisse 1",
|
|
2111
|
+
* category: "product",
|
|
2112
|
+
* metadata: { order_id: "ORD-2024-001" },
|
|
2113
|
+
* })
|
|
2114
|
+
*
|
|
2115
|
+
* // Afficher le montant sur le terminal
|
|
2116
|
+
* afficherEcran(`Montant : ${session.amount} XAF — Présentez votre carte`)
|
|
2117
|
+
*/
|
|
2118
|
+
create(payloads: CreateSessionPayloads): Promise<TerminalSession>;
|
|
2119
|
+
/**
|
|
2120
|
+
* Notifie le backend que le client a présenté un moyen de paiement.
|
|
2121
|
+
* Le `nonce` est fourni par le SDK constructeur du terminal (Sunmi, PAX, Ingenico…)
|
|
2122
|
+
* après lecture NFC/EMV — il ne doit **jamais** contenir le PAN brut.
|
|
2123
|
+
*
|
|
2124
|
+
* Authentification : accepte la `sk_xxx` **ou** le `reader_token` du terminal
|
|
2125
|
+
* (permission `IsTerminalToken` côté backend).
|
|
2126
|
+
*
|
|
2127
|
+
* @param id - Identifiant de la session
|
|
2128
|
+
* @param payloads - Type de moyen de paiement et nonce constructeur
|
|
2129
|
+
* @returns La session mise à jour (status → `"payment_method_presented"`)
|
|
2130
|
+
*
|
|
2131
|
+
* @example
|
|
2132
|
+
* // Après lecture NFC depuis le SDK Sunmi
|
|
2133
|
+
* const nonce = await sunmiSDK.readNFC() // ex: "emv_nonce_xxx"
|
|
2134
|
+
*
|
|
2135
|
+
* await sangho.terminal.sessions.presentPaymentMethod("tsess_xxx", {
|
|
2136
|
+
* payment_method_type: "card",
|
|
2137
|
+
* nonce,
|
|
2138
|
+
* })
|
|
2139
|
+
*
|
|
2140
|
+
* // Mobile Money (MTN, Airtel)
|
|
2141
|
+
* await sangho.terminal.sessions.presentPaymentMethod("tsess_xxx", {
|
|
2142
|
+
* payment_method_type: "mobile_money",
|
|
2143
|
+
* nonce: "mm_nonce_yyy",
|
|
2144
|
+
* })
|
|
2145
|
+
*/
|
|
2146
|
+
presentPaymentMethod(id: string, payloads: PresentPaymentPayloads): Promise<TerminalSession>;
|
|
2147
|
+
/**
|
|
2148
|
+
* Interroge le statut courant d'une session (polling léger).
|
|
2149
|
+
* À appeler en boucle (~1,5s d'intervalle) jusqu'à obtenir un statut terminal.
|
|
2150
|
+
*
|
|
2151
|
+
* **Statuts terminaux** : `succeeded` | `failed` | `canceled` | `timed_out`
|
|
2152
|
+
* **Statuts transitoires** : `pending` | `payment_method_presented` | `processing`
|
|
2153
|
+
*
|
|
2154
|
+
* @param id - Identifiant de la session
|
|
2155
|
+
* @returns Statut de la session + statut du PaymentIntent associé
|
|
2156
|
+
*
|
|
2157
|
+
* @example
|
|
2158
|
+
* async function attendreResultat(sessionId: string): Promise<SessionStatus> {
|
|
2159
|
+
* const debut = Date.now()
|
|
2160
|
+
* while (Date.now() - debut < 30_000) {
|
|
2161
|
+
* const s = await sangho.terminal.sessions.pollStatus(sessionId)
|
|
2162
|
+
* if (["succeeded", "failed", "canceled", "timed_out"].includes(s.status)) {
|
|
2163
|
+
* return s
|
|
2164
|
+
* }
|
|
2165
|
+
* await sleep(1_500)
|
|
2166
|
+
* }
|
|
2167
|
+
* await sangho.terminal.sessions.cancel(sessionId)
|
|
2168
|
+
* throw new Error("Timeout dépassé")
|
|
2169
|
+
* }
|
|
2170
|
+
*
|
|
2171
|
+
* const result = await attendreResultat("tsess_xxx")
|
|
2172
|
+
* if (result.status === "succeeded") imprimerRecu(result)
|
|
2173
|
+
* else afficherEcran(`Refusé : ${result.failure_reason}`)
|
|
2174
|
+
*/
|
|
2175
|
+
pollStatus(id: string): Promise<SessionStatus>;
|
|
2176
|
+
/**
|
|
2177
|
+
* Annule une session de paiement en cours.
|
|
2178
|
+
* Seules les sessions en statut `pending` ou `payment_method_presented`
|
|
2179
|
+
* peuvent être annulées. Une session `processing` ou `succeeded` ne peut plus l'être.
|
|
2180
|
+
*
|
|
2181
|
+
* @param id - Identifiant de la session à annuler
|
|
2182
|
+
* @returns La session avec `status: "canceled"`
|
|
2183
|
+
*
|
|
2184
|
+
* @example
|
|
2185
|
+
* // Annulation par le caissier
|
|
2186
|
+
* await sangho.terminal.sessions.cancel("tsess_xxx")
|
|
2187
|
+
* afficherEcran("Paiement annulé")
|
|
2188
|
+
*/
|
|
2189
|
+
cancel(id: string): Promise<TerminalSession>;
|
|
2190
|
+
/**
|
|
2191
|
+
* Retourne les métadonnées DRF du endpoint `/terminal/sessions/`.
|
|
2192
|
+
*/
|
|
2193
|
+
options(): Promise<DRFOptions>;
|
|
2194
|
+
};
|
|
2195
|
+
type OfflineProperties = {
|
|
2196
|
+
/**
|
|
2197
|
+
* Synchronise un batch de transactions capturées hors-ligne avec le backend.
|
|
2198
|
+
* À appeler dès que la connectivité réseau est rétablie.
|
|
2199
|
+
*
|
|
2200
|
+
* Chaque transaction est identifiée par son `local_id` (généré par le POS).
|
|
2201
|
+
* Le backend retourne le résultat individuel de chaque transaction
|
|
2202
|
+
* (`synced` | `conflict` | `failed`).
|
|
2203
|
+
*
|
|
2204
|
+
* ⚠️ Le `card_token` doit être un token constructeur — **jamais le PAN brut**.
|
|
2205
|
+
*
|
|
2206
|
+
* @param payloads - Tableau des transactions à synchroniser
|
|
2207
|
+
* @returns Nombre de transactions synchronisées + détail par `local_id`
|
|
2208
|
+
*
|
|
2209
|
+
* @example
|
|
2210
|
+
* const queue: OfflineTransactionPayload[] = [
|
|
2211
|
+
* {
|
|
2212
|
+
* local_id: "LOCAL-001",
|
|
2213
|
+
* amount: 8_500,
|
|
2214
|
+
* payment_method_type: "card",
|
|
2215
|
+
* card_token: "tok_constructeur_xxx",
|
|
2216
|
+
* captured_at: "2024-11-15T10:23:00Z",
|
|
2217
|
+
* reader_id: "rdr_xxx",
|
|
2218
|
+
* metadata: { order_id: "ORD-001" },
|
|
2219
|
+
* },
|
|
2220
|
+
* ]
|
|
2221
|
+
*
|
|
2222
|
+
* const result = await sangho.terminal.offline.sync({ transactions: queue })
|
|
2223
|
+
* console.log(`${result.synced} / ${queue.length} synchronisées`)
|
|
2224
|
+
*
|
|
2225
|
+
* result.results
|
|
2226
|
+
* .filter(r => r.sync_status === "failed")
|
|
2227
|
+
* .forEach(r => console.error(`Échec ${r.local_id} : ${r.error}`))
|
|
2228
|
+
*/
|
|
2229
|
+
sync(payloads: SyncPayloads): Promise<SyncResponse>;
|
|
2230
|
+
/**
|
|
2231
|
+
* Liste les transactions offline enregistrées pour cette application.
|
|
2232
|
+
* Filtrables par `sync_status` pour retrouver les transactions en échec.
|
|
2233
|
+
*
|
|
2234
|
+
* @param criteria - Filtres optionnels (`sync_status`, `page`)
|
|
2235
|
+
* @returns Liste paginée des transactions offline
|
|
2236
|
+
*
|
|
2237
|
+
* @example
|
|
2238
|
+
* // Transactions en conflit à résoudre manuellement
|
|
2239
|
+
* const conflits = await sangho.terminal.offline.list({ sync_status: "conflict" })
|
|
2240
|
+
*
|
|
2241
|
+
* // Toutes les transactions non encore synchronisées
|
|
2242
|
+
* const pending = await sangho.terminal.offline.list({ sync_status: "pending" })
|
|
2243
|
+
*/
|
|
2244
|
+
list(criteria?: {
|
|
2245
|
+
sync_status?: string;
|
|
2246
|
+
page?: number;
|
|
2247
|
+
}): Promise<ListResponse<OfflineTransaction>>;
|
|
2248
|
+
/**
|
|
2249
|
+
* Retourne les métadonnées DRF du endpoint `/terminal/offline/sync/`.
|
|
2250
|
+
*/
|
|
2251
|
+
options(): Promise<DRFOptions>;
|
|
2252
|
+
};
|
|
2253
|
+
type TerminalProperties = {
|
|
2254
|
+
/**
|
|
2255
|
+
* Gestion des terminaux physiques (Android, firmware, virtuels).
|
|
2256
|
+
*
|
|
2257
|
+
* Un **terminal** représente un appareil de paiement enregistré :
|
|
2258
|
+
* caisse Android (Sunmi, PAX), firmware embarqué (Ingenico, Verifone),
|
|
2259
|
+
* ou terminal virtuel pour les tests.
|
|
2260
|
+
*
|
|
2261
|
+
* Cycle de vie d'un terminal :
|
|
2262
|
+
* ```
|
|
2263
|
+
* create() → heartbeat() (toutes 30s) → refreshToken() (toutes 24h) → disable()
|
|
2264
|
+
* ```
|
|
2265
|
+
*
|
|
2266
|
+
* @example
|
|
2267
|
+
* // Provisionnement initial
|
|
2268
|
+
* const reader = await sangho.terminal.readers.create({
|
|
2269
|
+
* label: "Caisse 1 — Libreville",
|
|
2270
|
+
* serial_number: "SN-SUNMI-T2-001",
|
|
2271
|
+
* reader_type: "android",
|
|
2272
|
+
* })
|
|
2273
|
+
*/
|
|
2274
|
+
readers: ReadersProperties;
|
|
2275
|
+
/**
|
|
2276
|
+
* Gestion des sessions de paiement terminal.
|
|
2277
|
+
*
|
|
2278
|
+
* Une **session** représente une tentative de paiement initiée depuis
|
|
2279
|
+
* un terminal physique. Elle orchestre le cycle :
|
|
2280
|
+
* ```
|
|
2281
|
+
* create() → presentPaymentMethod() → pollStatus() → [succeeded | failed | cancel()]
|
|
2282
|
+
* ```
|
|
2283
|
+
*
|
|
2284
|
+
* @example
|
|
2285
|
+
* // Flux complet de paiement terminal
|
|
2286
|
+
* const session = await sangho.terminal.sessions.create({ reader: "rdr_xxx", amount: 15_000 })
|
|
2287
|
+
* await sangho.terminal.sessions.presentPaymentMethod(session.id, { payment_method_type: "card", nonce })
|
|
2288
|
+
* const result = await pollJusquaResultat(session.id)
|
|
2289
|
+
*/
|
|
2290
|
+
sessions: SessionsProperties;
|
|
2291
|
+
/**
|
|
2292
|
+
* Synchronisation des transactions capturées hors-ligne.
|
|
2293
|
+
*
|
|
2294
|
+
* Quand la connexion réseau est indisponible (zone blanche, coupure),
|
|
2295
|
+
* le terminal capture les paiements localement puis les synchronise
|
|
2296
|
+
* avec `sync()` dès le retour du réseau.
|
|
2297
|
+
*
|
|
2298
|
+
* ```
|
|
2299
|
+
* [réseau absent] capturer localement → stocker en queue locale
|
|
2300
|
+
* [réseau rétabli] offline.sync({ transactions: queue })
|
|
2301
|
+
* ```
|
|
2302
|
+
*
|
|
2303
|
+
* @example
|
|
2304
|
+
* // Au retour du réseau
|
|
2305
|
+
* const result = await sangho.terminal.offline.sync({ transactions: localQueue })
|
|
2306
|
+
* console.log(`${result.synced} transactions synchronisées`)
|
|
2307
|
+
*/
|
|
2308
|
+
offline: OfflineProperties;
|
|
2309
|
+
};
|
|
2310
|
+
|
|
2311
|
+
/** Résultat de la purge des données sandbox — voir SandboxModule.reset(). */
|
|
2312
|
+
interface SandboxResetResult {
|
|
2313
|
+
object: "sandbox.reset";
|
|
2314
|
+
/** Nombre d'enregistrements supprimés par modèle (ex: `{ customer: 12, product: 5 }`) */
|
|
2315
|
+
deleted: Record<string, number>;
|
|
2316
|
+
total_deleted: number;
|
|
2317
|
+
errors: string[];
|
|
2318
|
+
}
|
|
2319
|
+
|
|
2320
|
+
type SandboxProperties = {
|
|
2321
|
+
/**
|
|
2322
|
+
* Purge toutes les données sandbox de l'application (clé test uniquement).
|
|
2323
|
+
*
|
|
2324
|
+
* @example
|
|
2325
|
+
* await sangho.sandbox.reset()
|
|
2326
|
+
*/
|
|
2327
|
+
reset(): Promise<SandboxResetResult>;
|
|
2328
|
+
};
|
|
2329
|
+
|
|
2330
|
+
type ApiKeyType = "public" | "secret";
|
|
2331
|
+
interface HttpClientConfig {
|
|
2332
|
+
baseURL: string;
|
|
2333
|
+
timeout: number;
|
|
2334
|
+
maxRetries: number;
|
|
2335
|
+
sandbox: boolean;
|
|
2336
|
+
apiKey: string;
|
|
2337
|
+
}
|
|
2338
|
+
declare class HttpClient {
|
|
2339
|
+
readonly keyType: ApiKeyType;
|
|
2340
|
+
private readonly config;
|
|
2341
|
+
constructor(config: HttpClientConfig);
|
|
2342
|
+
assertSecretKey(methodName: string): void;
|
|
2343
|
+
get<T, P extends object = object>(path: string, params?: P): Promise<T>;
|
|
2344
|
+
post<T>(path: string, body: unknown, idempotencyKey?: string): Promise<T>;
|
|
2345
|
+
patch<T>(path: string, body: unknown): Promise<T>;
|
|
2346
|
+
put<T>(path: string, body: unknown): Promise<T>;
|
|
2347
|
+
delete<T = void>(path: string): Promise<T>;
|
|
2348
|
+
options<T = unknown>(path: string): Promise<T>;
|
|
2349
|
+
private buildURL;
|
|
2350
|
+
private baseHeaders;
|
|
2351
|
+
private request;
|
|
2352
|
+
/**
|
|
2353
|
+
* Détermine si une SanghoError est transitoire et mérite un retry :
|
|
2354
|
+
* 429 (rate limit) ou 5xx (erreur serveur). Jamais les 4xx restants
|
|
2355
|
+
* (400/401/403/404/409/422) — ce sont des erreurs permanentes côté client.
|
|
2356
|
+
*/
|
|
2357
|
+
private isRetryable;
|
|
2358
|
+
private handleResponse;
|
|
2359
|
+
private sleep;
|
|
2360
|
+
}
|
|
2361
|
+
|
|
2362
|
+
/**
|
|
2363
|
+
* Classe de base dont héritent tous les modules Sangho.
|
|
2364
|
+
*
|
|
2365
|
+
* Pattern : composition via injection de `HttpClient`.
|
|
2366
|
+
* Jamais d'héritage multiple — un seul HttpClient partagé par instance Sangho.
|
|
2367
|
+
*
|
|
2368
|
+
* @example
|
|
2369
|
+
* ```typescript
|
|
2370
|
+
* export class CustomersModule extends BaseModule {
|
|
2371
|
+
* async create(params: CreateCustomerParams): Promise<Customer> {
|
|
2372
|
+
* this.http.assertSecretKey("customers.create");
|
|
2373
|
+
* return this.http.post<Customer>("/customers/", params);
|
|
2374
|
+
* }
|
|
2375
|
+
* }
|
|
2376
|
+
* ```
|
|
2377
|
+
*/
|
|
2378
|
+
declare class BaseModule {
|
|
2379
|
+
/** Client HTTP partagé — ne jamais exposer publiquement. */
|
|
2380
|
+
protected readonly http: HttpClient;
|
|
2381
|
+
constructor(http: HttpClient);
|
|
2382
|
+
}
|
|
2383
|
+
|
|
2384
|
+
declare const Sangho_base: {
|
|
2385
|
+
new (...args: any[]): {};
|
|
2386
|
+
} & typeof BaseModule;
|
|
2387
|
+
/**
|
|
2388
|
+
* Client principal du SDK Sangho.
|
|
2389
|
+
*
|
|
2390
|
+
* @example
|
|
2391
|
+
* ```typescript
|
|
2392
|
+
* // Côté serveur — clé secrète
|
|
2393
|
+
* const sangho = new Sangho("sk_prod_xxx")
|
|
2394
|
+
* const intent = await sangho.paymentIntents.create({ amount: 5000, currency: "XAF" })
|
|
2395
|
+
*
|
|
2396
|
+
* // Côté navigateur — clé publique (checkout uniquement)
|
|
2397
|
+
* const sangho = new Sangho("pk_prod_xxx")
|
|
2398
|
+
* const session = await sangho.checkoutSessions.retrieve("cs_xxx")
|
|
2399
|
+
* ```
|
|
2400
|
+
*/
|
|
2401
|
+
declare class Sangho extends Sangho_base {
|
|
2402
|
+
readonly account: InterfaceOnly<AccountProperties>;
|
|
2403
|
+
readonly apps: InterfaceOnly<AppsProperties>;
|
|
2404
|
+
readonly addresses: InterfaceOnly<AddressesProperties>;
|
|
2405
|
+
readonly customers: InterfaceOnly<CustomersProperties>;
|
|
2406
|
+
readonly products: InterfaceOnly<ProductsProperties>;
|
|
2407
|
+
readonly paymentIntents: InterfaceOnly<PaymentIntentsProperties>;
|
|
2408
|
+
readonly transactions: InterfaceOnly<TransactionsProperties>;
|
|
2409
|
+
readonly refunds: InterfaceOnly<RefundsProperties>;
|
|
2410
|
+
readonly invoices: InterfaceOnly<InvoicesProperties>;
|
|
2411
|
+
readonly paymentLinks: InterfaceOnly<PaymentLinksProperties>;
|
|
2412
|
+
readonly checkoutSessions: InterfaceOnly<CheckoutSessionsProperties>;
|
|
2413
|
+
readonly subscriptions: InterfaceOnly<SubscriptionsProperties>;
|
|
2414
|
+
readonly paymentMethods: InterfaceOnly<PaymentMethodsProperties>;
|
|
2415
|
+
readonly receipts: InterfaceOnly<ReceiptsProperties>;
|
|
2416
|
+
readonly webhooks: InterfaceOnly<WebhooksProperties>;
|
|
2417
|
+
readonly security: InterfaceOnly<SecurityProperties>;
|
|
2418
|
+
readonly partners: InterfaceOnly<PartnersProperties>;
|
|
2419
|
+
readonly terminal: InterfaceOnly<TerminalProperties>;
|
|
2420
|
+
readonly sandbox: InterfaceOnly<SandboxProperties>;
|
|
2421
|
+
constructor(apiKey: string, options?: SanghoOptions);
|
|
2422
|
+
/**
|
|
2423
|
+
* Vérifie et parse un événement webhook entrant.
|
|
2424
|
+
* Valide la signature HMAC-SHA256 + protection anti-replay (5 min).
|
|
2425
|
+
*
|
|
2426
|
+
* @param payload - Corps brut de la requête (Buffer ou string)
|
|
2427
|
+
* @param signature - Header `Sangho-Signature` de la requête
|
|
2428
|
+
* @param secret - Secret du webhook (depuis le dashboard)
|
|
2429
|
+
*
|
|
2430
|
+
* @example
|
|
2431
|
+
* ```typescript
|
|
2432
|
+
* // Express
|
|
2433
|
+
* app.post('/webhooks/sangho', express.raw({ type: 'application/json' }), (req, res) => {
|
|
2434
|
+
* const event = Sangho.constructEvent(
|
|
2435
|
+
* req.body,
|
|
2436
|
+
* req.headers['sangho-signature'],
|
|
2437
|
+
* process.env.SANGHO_WEBHOOK_SECRET
|
|
2438
|
+
* )
|
|
2439
|
+
* if (event.type === 'payment_intent.succeeded') {
|
|
2440
|
+
* await fulfillOrder(event.data)
|
|
2441
|
+
* }
|
|
2442
|
+
* res.json({ received: true })
|
|
2443
|
+
* })
|
|
2444
|
+
* ```
|
|
2445
|
+
*/
|
|
2446
|
+
static constructEvent: typeof constructEvent;
|
|
2447
|
+
}
|
|
2448
|
+
|
|
2449
|
+
/**
|
|
2450
|
+
* Catégorie large de l'erreur (`err.type`).
|
|
2451
|
+
*
|
|
2452
|
+
* Les 7 premières valeurs sont exactement le taxonomie `type` renvoyée par
|
|
2453
|
+
* le backend (cf. `backend/api/exceptions.py`) sur toute réponse HTTP
|
|
2454
|
+
* d'erreur. `NETWORK_ERROR` et `TIMEOUT_ERROR` sont deux catégories
|
|
2455
|
+
* additionnelles, propres au SDK : elles ne correspondent à aucune réponse
|
|
2456
|
+
* HTTP puisque la requête n'a justement jamais abouti côté serveur.
|
|
2457
|
+
*/
|
|
2458
|
+
type SanghoErrorType = "AUTHENTICATION_ERROR" | "PERMISSION_ERROR" | "NOT_FOUND_ERROR" | "CONFLICT_ERROR" | "VALIDATION_ERROR" | "RATE_LIMIT_ERROR" | "API_ERROR" | "NETWORK_ERROR" | "TIMEOUT_ERROR";
|
|
2459
|
+
interface SanghoErrorResponse {
|
|
2460
|
+
message: string;
|
|
2461
|
+
type?: string;
|
|
2462
|
+
code?: string;
|
|
2463
|
+
detail?: string | Record<string, string[]>;
|
|
2464
|
+
errors?: Record<string, string[]>;
|
|
2465
|
+
status?: number;
|
|
2466
|
+
param?: string;
|
|
2467
|
+
}
|
|
2468
|
+
/**
|
|
2469
|
+
* Classe de base — toutes les erreurs Sangho en héritent.
|
|
2470
|
+
*/
|
|
2471
|
+
declare class SanghoError extends Error {
|
|
2472
|
+
/**
|
|
2473
|
+
* Catégorie large de l'erreur, une des 9 valeurs `SanghoErrorType`
|
|
2474
|
+
* (`VALIDATION_ERROR`, `RATE_LIMIT_ERROR`, `NETWORK_ERROR`, ...).
|
|
2475
|
+
* Utile pour un `switch`/branchement générique.
|
|
2476
|
+
*/
|
|
2477
|
+
readonly type: SanghoErrorType;
|
|
2478
|
+
/**
|
|
2479
|
+
* Code métier précis renvoyé par le backend (`raw.code`), ex :
|
|
2480
|
+
* `AMOUNT_TOO_SMALL`, `INSUFFICIENT_FUNDS`, `CUSTOMER_NOT_FOUND`,
|
|
2481
|
+
* `INVALID_API_KEY`, `CURRENCY_NOT_IN_PLAN`... Le catalogue de codes est
|
|
2482
|
+
* possédé et versionné côté backend et continuera de grandir — c'est
|
|
2483
|
+
* pourquoi ce champ est typé `string` plutôt qu'une union fermée.
|
|
2484
|
+
*
|
|
2485
|
+
* Quand l'erreur n'a jamais atteint le backend (`SanghoNetworkError`,
|
|
2486
|
+
* `SanghoTimeoutError` — pas de corps de réponse à lire), `code` retombe
|
|
2487
|
+
* sur la même valeur que `type`.
|
|
2488
|
+
*/
|
|
2489
|
+
readonly code: string;
|
|
2490
|
+
readonly statusCode?: number;
|
|
2491
|
+
readonly raw?: SanghoErrorResponse;
|
|
2492
|
+
constructor(message: string, type?: SanghoErrorType, statusCode?: number, raw?: SanghoErrorResponse);
|
|
2493
|
+
}
|
|
2494
|
+
/**
|
|
2495
|
+
* 401 — Clé API invalide, expirée ou absente.
|
|
2496
|
+
*/
|
|
2497
|
+
declare class SanghoAuthError extends SanghoError {
|
|
2498
|
+
constructor(message?: string, raw?: SanghoErrorResponse);
|
|
2499
|
+
}
|
|
2500
|
+
/**
|
|
2501
|
+
* 403 — Clé publique utilisée pour une opération réservée aux clés secrètes.
|
|
2502
|
+
* Catégorie (`type`) : `PERMISSION_ERROR` — c'est bien un problème de
|
|
2503
|
+
* permission ; `code` reste `PUBLIC_KEY_NOT_ALLOWED` (ou équivalent envoyé
|
|
2504
|
+
* par le backend) pour distinguer précisément ce cas des autres 403.
|
|
2505
|
+
*/
|
|
2506
|
+
declare class SanghoPublicKeyError extends SanghoError {
|
|
2507
|
+
constructor(message?: string, raw?: SanghoErrorResponse);
|
|
2508
|
+
}
|
|
2509
|
+
/**
|
|
2510
|
+
* 403 — Permissions insuffisantes.
|
|
2511
|
+
*/
|
|
2512
|
+
declare class SanghoPermissionError extends SanghoError {
|
|
2513
|
+
constructor(message?: string, raw?: SanghoErrorResponse);
|
|
2514
|
+
}
|
|
2515
|
+
/**
|
|
2516
|
+
* 404 — Ressource introuvable.
|
|
2517
|
+
*/
|
|
2518
|
+
declare class SanghoNotFoundError extends SanghoError {
|
|
2519
|
+
constructor(message?: string, raw?: SanghoErrorResponse);
|
|
2520
|
+
}
|
|
2521
|
+
/**
|
|
2522
|
+
* 422 — Données invalides (erreurs de validation champ par champ).
|
|
2523
|
+
*/
|
|
2524
|
+
declare class SanghoValidationError extends SanghoError {
|
|
2525
|
+
readonly fieldErrors: Record<string, string[]>;
|
|
2526
|
+
readonly param?: string;
|
|
2527
|
+
constructor(raw: SanghoErrorResponse);
|
|
2528
|
+
}
|
|
2529
|
+
/**
|
|
2530
|
+
* 429 — Trop de requêtes. `retryAfter` indique le délai (secondes) avant retry.
|
|
2531
|
+
*/
|
|
2532
|
+
declare class SanghoRateLimitError extends SanghoError {
|
|
2533
|
+
readonly retryAfter?: number;
|
|
2534
|
+
constructor(retryAfter?: number, raw?: SanghoErrorResponse);
|
|
2535
|
+
}
|
|
2536
|
+
/**
|
|
2537
|
+
* 409 — Clé d'idempotence réutilisée avec un payload différent.
|
|
2538
|
+
* Catégorie (`type`) : `CONFLICT_ERROR` — même famille que les autres 409.
|
|
2539
|
+
*/
|
|
2540
|
+
declare class SanghoIdempotencyError extends SanghoError {
|
|
2541
|
+
constructor(raw?: SanghoErrorResponse);
|
|
2542
|
+
}
|
|
2543
|
+
/**
|
|
2544
|
+
* Erreur réseau (pas de réponse du serveur). Catégorie SDK-only : la requête
|
|
2545
|
+
* n'a jamais atteint le backend, donc pas de `raw`/`code` métier précis —
|
|
2546
|
+
* `code` retombe sur `NETWORK_ERROR` (== `type`).
|
|
2547
|
+
*/
|
|
2548
|
+
declare class SanghoNetworkError extends SanghoError {
|
|
2549
|
+
constructor(message?: string);
|
|
2550
|
+
}
|
|
2551
|
+
/**
|
|
2552
|
+
* Timeout dépassé. Catégorie SDK-only, même raisonnement que
|
|
2553
|
+
* `SanghoNetworkError` : `code` retombe sur `TIMEOUT_ERROR` (== `type`).
|
|
2554
|
+
*/
|
|
2555
|
+
declare class SanghoTimeoutError extends SanghoError {
|
|
2556
|
+
constructor(timeout: number);
|
|
2557
|
+
}
|
|
2558
|
+
|
|
2559
|
+
export { type Address, type AmountInCents, type App, type AppKey, type AppKeys, type CheckoutSession, type CurrencyCode, type Customer, type Invoice, type ListParams, type ListResponse, type Metadata, type Partner, type PaymentIntent, type PaymentLink, type PaymentMethod, type Product, type ProductImage, type Receipt, type Refund, type SandboxResetResult, Sangho, SanghoAuthError, SanghoError, type SanghoErrorResponse, type SanghoErrorType, SanghoIdempotencyError, SanghoNetworkError, SanghoNotFoundError, type SanghoOptions, SanghoPermissionError, SanghoPublicKeyError, SanghoRateLimitError, SanghoTimeoutError, SanghoValidationError, type SecurityProfile, type Subscription, type Timestamps, type Transaction, type UpdateSecurityProfileParams, type Webhook, type WebhookDelivery, constructEvent, Sangho as default };
|