globodai-fam-sdk 1.1.8
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/README.md +642 -0
- package/dist/index.cjs +1010 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +2041 -0
- package/dist/index.d.ts +2041 -0
- package/dist/index.js +977 -0
- package/dist/index.js.map +1 -0
- package/dist/webhooks/index.cjs +121 -0
- package/dist/webhooks/index.cjs.map +1 -0
- package/dist/webhooks/index.d.cts +53 -0
- package/dist/webhooks/index.d.ts +53 -0
- package/dist/webhooks/index.js +117 -0
- package/dist/webhooks/index.js.map +1 -0
- package/dist/webhooks-DI8h2_AK.d.cts +51 -0
- package/dist/webhooks-DI8h2_AK.d.ts +51 -0
- package/package.json +91 -0
package/README.md
ADDED
|
@@ -0,0 +1,642 @@
|
|
|
1
|
+
<p align="center">
|
|
2
|
+
<img src="https://img.shields.io/badge/FAM-SDK-0066FF?style=for-the-badge&logoColor=white" alt="FAM SDK" height="40">
|
|
3
|
+
</p>
|
|
4
|
+
|
|
5
|
+
<h1 align="center">FAM SDK</h1>
|
|
6
|
+
|
|
7
|
+
<p align="center">
|
|
8
|
+
<strong>Official TypeScript SDK for the FAM API</strong><br>
|
|
9
|
+
<em>A type-safe, developer-friendly wrapper for Mangopay payment services</em>
|
|
10
|
+
</p>
|
|
11
|
+
|
|
12
|
+
<p align="center">
|
|
13
|
+
<a href="https://github.com/globodai-group/fam-sdk/actions/workflows/ci.yml"><img src="https://github.com/globodai-group/fam-sdk/actions/workflows/ci.yml/badge.svg" alt="CI"></a>
|
|
14
|
+
<a href="https://www.npmjs.com/package/globodai-fam-sdk"><img src="https://img.shields.io/npm/v/globodai-fam-sdk.svg?color=0066FF&label=npm" alt="npm version"></a>
|
|
15
|
+
<a href="https://www.npmjs.com/package/globodai-fam-sdk"><img src="https://img.shields.io/npm/dm/globodai-fam-sdk.svg?color=green&label=downloads" alt="npm downloads"></a>
|
|
16
|
+
<a href="https://bundlephobia.com/package/globodai-fam-sdk"><img src="https://img.shields.io/bundlephobia/minzip/globodai-fam-sdk?label=size&color=orange" alt="bundle size"></a>
|
|
17
|
+
<a href="https://opensource.org/licenses/MIT"><img src="https://img.shields.io/badge/license-MIT-blue.svg" alt="License: MIT"></a>
|
|
18
|
+
</p>
|
|
19
|
+
|
|
20
|
+
<p align="center">
|
|
21
|
+
<a href="#installation">Installation</a> •
|
|
22
|
+
<a href="#quick-start">Quick Start</a> •
|
|
23
|
+
<a href="#api-reference">API Reference</a> •
|
|
24
|
+
<a href="#webhooks">Webhooks</a> •
|
|
25
|
+
<a href="#error-handling">Error Handling</a> •
|
|
26
|
+
<a href="#contributing">Contributing</a>
|
|
27
|
+
</p>
|
|
28
|
+
|
|
29
|
+
---
|
|
30
|
+
|
|
31
|
+
## Highlights
|
|
32
|
+
|
|
33
|
+
- **Full TypeScript Support** — Strict types for all API requests and responses
|
|
34
|
+
- **Zero Dependencies** — Lightweight and secure, no external runtime dependencies
|
|
35
|
+
- **Dual Module Support** — Works with both ESM and CommonJS
|
|
36
|
+
- **Automatic Retries** — Built-in retry logic with exponential backoff
|
|
37
|
+
- **Comprehensive Errors** — Typed error classes for precise error handling
|
|
38
|
+
- **Webhook Verification** — Secure signature verification out of the box
|
|
39
|
+
|
|
40
|
+
## Requirements
|
|
41
|
+
|
|
42
|
+
- Node.js 18.0.0 or higher
|
|
43
|
+
- TypeScript 5.0+ (recommended)
|
|
44
|
+
|
|
45
|
+
## Installation
|
|
46
|
+
|
|
47
|
+
```bash
|
|
48
|
+
npm install globodai-fam-sdk
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
<details>
|
|
52
|
+
<summary>Using other package managers</summary>
|
|
53
|
+
|
|
54
|
+
```bash
|
|
55
|
+
# yarn
|
|
56
|
+
yarn add globodai-fam-sdk
|
|
57
|
+
|
|
58
|
+
# pnpm
|
|
59
|
+
pnpm add globodai-fam-sdk
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
</details>
|
|
63
|
+
|
|
64
|
+
## Quick Start
|
|
65
|
+
|
|
66
|
+
```typescript
|
|
67
|
+
import { Fam } from 'globodai-fam-sdk';
|
|
68
|
+
|
|
69
|
+
// Initialize the client
|
|
70
|
+
const fam = new Fam({
|
|
71
|
+
baseUrl: 'https://api.fam.com',
|
|
72
|
+
token: 'your-auth-token',
|
|
73
|
+
});
|
|
74
|
+
|
|
75
|
+
// Create a user
|
|
76
|
+
const user = await fam.users.createNatural({
|
|
77
|
+
Email: 'john.doe@example.com',
|
|
78
|
+
FirstName: 'John',
|
|
79
|
+
LastName: 'Doe',
|
|
80
|
+
Birthday: 631152000,
|
|
81
|
+
Nationality: 'FR',
|
|
82
|
+
CountryOfResidence: 'FR',
|
|
83
|
+
});
|
|
84
|
+
|
|
85
|
+
// Create a wallet
|
|
86
|
+
const wallet = await fam.wallets.create({
|
|
87
|
+
Owners: [user.Id],
|
|
88
|
+
Description: 'Main wallet',
|
|
89
|
+
Currency: 'EUR',
|
|
90
|
+
});
|
|
91
|
+
|
|
92
|
+
console.log(`Wallet created: ${wallet.Id}`);
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
## Configuration
|
|
96
|
+
|
|
97
|
+
```typescript
|
|
98
|
+
import { Fam } from 'globodai-fam-sdk';
|
|
99
|
+
import type { FamOptions } from 'globodai-fam-sdk';
|
|
100
|
+
|
|
101
|
+
const options: FamOptions = {
|
|
102
|
+
baseUrl: 'https://api.fam.com',
|
|
103
|
+
token: 'your-auth-token',
|
|
104
|
+
timeout: 30000, // Request timeout in ms (default: 30000)
|
|
105
|
+
retries: 3, // Retry attempts on network errors (default: 3)
|
|
106
|
+
};
|
|
107
|
+
|
|
108
|
+
const fam = new Fam(options);
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
## API Reference
|
|
112
|
+
|
|
113
|
+
### Users
|
|
114
|
+
|
|
115
|
+
<details open>
|
|
116
|
+
<summary><strong>Natural Users</strong></summary>
|
|
117
|
+
|
|
118
|
+
```typescript
|
|
119
|
+
// Create a natural user
|
|
120
|
+
const user = await fam.users.createNatural({
|
|
121
|
+
Email: 'user@example.com',
|
|
122
|
+
FirstName: 'John',
|
|
123
|
+
LastName: 'Doe',
|
|
124
|
+
Birthday: 631152000,
|
|
125
|
+
Nationality: 'FR',
|
|
126
|
+
CountryOfResidence: 'FR',
|
|
127
|
+
});
|
|
128
|
+
|
|
129
|
+
// Update a natural user
|
|
130
|
+
await fam.users.updateNatural(userId, {
|
|
131
|
+
FirstName: 'Jane',
|
|
132
|
+
});
|
|
133
|
+
|
|
134
|
+
// Get user details
|
|
135
|
+
const user = await fam.users.getUser(userId);
|
|
136
|
+
const naturalUser = await fam.users.getNaturalUser(userId);
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
</details>
|
|
140
|
+
|
|
141
|
+
<details>
|
|
142
|
+
<summary><strong>Legal Users</strong></summary>
|
|
143
|
+
|
|
144
|
+
```typescript
|
|
145
|
+
// Create a legal user
|
|
146
|
+
const company = await fam.users.createLegal({
|
|
147
|
+
Email: 'contact@company.com',
|
|
148
|
+
Name: 'ACME Corp',
|
|
149
|
+
LegalPersonType: 'BUSINESS',
|
|
150
|
+
LegalRepresentativeFirstName: 'John',
|
|
151
|
+
LegalRepresentativeLastName: 'Doe',
|
|
152
|
+
LegalRepresentativeBirthday: 631152000,
|
|
153
|
+
LegalRepresentativeNationality: 'FR',
|
|
154
|
+
LegalRepresentativeCountryOfResidence: 'FR',
|
|
155
|
+
});
|
|
156
|
+
|
|
157
|
+
// Update and retrieve
|
|
158
|
+
await fam.users.updateLegal(userId, { Name: 'ACME Corporation' });
|
|
159
|
+
const legalUser = await fam.users.getLegalUser(userId);
|
|
160
|
+
```
|
|
161
|
+
|
|
162
|
+
</details>
|
|
163
|
+
|
|
164
|
+
<details>
|
|
165
|
+
<summary><strong>User Resources</strong></summary>
|
|
166
|
+
|
|
167
|
+
```typescript
|
|
168
|
+
// Get user's wallets, cards, bank accounts, and transactions
|
|
169
|
+
const wallets = await fam.users.getWallets(userId);
|
|
170
|
+
const cards = await fam.users.getCards(userId);
|
|
171
|
+
const bankAccounts = await fam.users.getBankAccounts(userId);
|
|
172
|
+
const transactions = await fam.users.getTransactions(userId);
|
|
173
|
+
```
|
|
174
|
+
|
|
175
|
+
</details>
|
|
176
|
+
|
|
177
|
+
### Wallets
|
|
178
|
+
|
|
179
|
+
```typescript
|
|
180
|
+
// Create a wallet
|
|
181
|
+
const wallet = await fam.wallets.create({
|
|
182
|
+
Owners: [userId],
|
|
183
|
+
Description: 'EUR Wallet',
|
|
184
|
+
Currency: 'EUR',
|
|
185
|
+
});
|
|
186
|
+
|
|
187
|
+
// Get wallet details and transactions
|
|
188
|
+
const wallet = await fam.wallets.getWallet(walletId);
|
|
189
|
+
const transactions = await fam.wallets.getTransactions(walletId);
|
|
190
|
+
```
|
|
191
|
+
|
|
192
|
+
### Payments
|
|
193
|
+
|
|
194
|
+
<details open>
|
|
195
|
+
<summary><strong>Pay-ins</strong></summary>
|
|
196
|
+
|
|
197
|
+
```typescript
|
|
198
|
+
// Create a card direct payin
|
|
199
|
+
const payin = await fam.payins.create({
|
|
200
|
+
AuthorId: userId,
|
|
201
|
+
CreditedWalletId: walletId,
|
|
202
|
+
DebitedFunds: { Amount: 1000, Currency: 'EUR' },
|
|
203
|
+
Fees: { Amount: 0, Currency: 'EUR' },
|
|
204
|
+
CardId: cardId,
|
|
205
|
+
SecureModeReturnURL: 'https://example.com/return',
|
|
206
|
+
});
|
|
207
|
+
|
|
208
|
+
// Get payin details
|
|
209
|
+
const payin = await fam.payins.getPayin(payinId);
|
|
210
|
+
|
|
211
|
+
// Refund a payin
|
|
212
|
+
const refund = await fam.payins.refund(payinId, {
|
|
213
|
+
AuthorId: userId,
|
|
214
|
+
});
|
|
215
|
+
```
|
|
216
|
+
|
|
217
|
+
</details>
|
|
218
|
+
|
|
219
|
+
<details>
|
|
220
|
+
<summary><strong>Recurring Payments</strong></summary>
|
|
221
|
+
|
|
222
|
+
```typescript
|
|
223
|
+
// Create recurring payment registration
|
|
224
|
+
const recurring = await fam.payins.createRecurringPayment({
|
|
225
|
+
AuthorId: userId,
|
|
226
|
+
CardId: cardId,
|
|
227
|
+
CreditedWalletId: walletId,
|
|
228
|
+
FirstTransactionDebitedFunds: { Amount: 1000, Currency: 'EUR' },
|
|
229
|
+
FirstTransactionFees: { Amount: 0, Currency: 'EUR' },
|
|
230
|
+
});
|
|
231
|
+
|
|
232
|
+
// Create Customer-Initiated Transaction (CIT)
|
|
233
|
+
const cit = await fam.payins.createRecurringCit({
|
|
234
|
+
RecurringPayinRegistrationId: recurring.Id,
|
|
235
|
+
DebitedFunds: { Amount: 1000, Currency: 'EUR' },
|
|
236
|
+
Fees: { Amount: 0, Currency: 'EUR' },
|
|
237
|
+
SecureModeReturnURL: 'https://example.com/return',
|
|
238
|
+
});
|
|
239
|
+
|
|
240
|
+
// Create Merchant-Initiated Transaction (MIT)
|
|
241
|
+
const mit = await fam.payins.createRecurringMit({
|
|
242
|
+
RecurringPayinRegistrationId: recurring.Id,
|
|
243
|
+
DebitedFunds: { Amount: 1000, Currency: 'EUR' },
|
|
244
|
+
Fees: { Amount: 0, Currency: 'EUR' },
|
|
245
|
+
});
|
|
246
|
+
```
|
|
247
|
+
|
|
248
|
+
</details>
|
|
249
|
+
|
|
250
|
+
<details>
|
|
251
|
+
<summary><strong>Pay-outs</strong></summary>
|
|
252
|
+
|
|
253
|
+
```typescript
|
|
254
|
+
// Create a payout to bank account
|
|
255
|
+
const payout = await fam.payouts.create({
|
|
256
|
+
AuthorId: userId,
|
|
257
|
+
DebitedWalletId: walletId,
|
|
258
|
+
DebitedFunds: { Amount: 1000, Currency: 'EUR' },
|
|
259
|
+
Fees: { Amount: 0, Currency: 'EUR' },
|
|
260
|
+
BankAccountId: bankAccountId,
|
|
261
|
+
});
|
|
262
|
+
|
|
263
|
+
// Get payout details
|
|
264
|
+
const payout = await fam.payouts.getPayout(payoutId);
|
|
265
|
+
```
|
|
266
|
+
|
|
267
|
+
</details>
|
|
268
|
+
|
|
269
|
+
<details>
|
|
270
|
+
<summary><strong>Transfers</strong></summary>
|
|
271
|
+
|
|
272
|
+
```typescript
|
|
273
|
+
// Create a wallet-to-wallet transfer
|
|
274
|
+
const transfer = await fam.transfers.create({
|
|
275
|
+
AuthorId: userId,
|
|
276
|
+
DebitedWalletId: sourceWalletId,
|
|
277
|
+
CreditedWalletId: targetWalletId,
|
|
278
|
+
DebitedFunds: { Amount: 1000, Currency: 'EUR' },
|
|
279
|
+
Fees: { Amount: 0, Currency: 'EUR' },
|
|
280
|
+
});
|
|
281
|
+
|
|
282
|
+
// Create SCA transfer
|
|
283
|
+
const scaTransfer = await fam.transfers.createSca({
|
|
284
|
+
AuthorId: userId,
|
|
285
|
+
DebitedWalletId: sourceWalletId,
|
|
286
|
+
CreditedWalletId: targetWalletId,
|
|
287
|
+
DebitedFunds: { Amount: 5000, Currency: 'EUR' },
|
|
288
|
+
Fees: { Amount: 0, Currency: 'EUR' },
|
|
289
|
+
});
|
|
290
|
+
|
|
291
|
+
// Refund a transfer
|
|
292
|
+
const refund = await fam.transfers.refund(transferId, {
|
|
293
|
+
AuthorId: userId,
|
|
294
|
+
});
|
|
295
|
+
```
|
|
296
|
+
|
|
297
|
+
</details>
|
|
298
|
+
|
|
299
|
+
### Cards
|
|
300
|
+
|
|
301
|
+
<details open>
|
|
302
|
+
<summary><strong>Card Registration</strong></summary>
|
|
303
|
+
|
|
304
|
+
```typescript
|
|
305
|
+
// Create card registration
|
|
306
|
+
const registration = await fam.cardRegistrations.create({
|
|
307
|
+
UserId: userId,
|
|
308
|
+
Currency: 'EUR',
|
|
309
|
+
CardType: 'CB_VISA_MASTERCARD',
|
|
310
|
+
});
|
|
311
|
+
|
|
312
|
+
// Update with tokenized card data
|
|
313
|
+
const updated = await fam.cardRegistrations.update(registration.Id, {
|
|
314
|
+
RegistrationData: tokenizedData,
|
|
315
|
+
});
|
|
316
|
+
|
|
317
|
+
// Get card from registration
|
|
318
|
+
const card = await fam.cards.getCard(updated.CardId);
|
|
319
|
+
```
|
|
320
|
+
|
|
321
|
+
</details>
|
|
322
|
+
|
|
323
|
+
<details>
|
|
324
|
+
<summary><strong>Card Operations</strong></summary>
|
|
325
|
+
|
|
326
|
+
```typescript
|
|
327
|
+
// Get card details
|
|
328
|
+
const card = await fam.cards.getCard(cardId);
|
|
329
|
+
|
|
330
|
+
// Deactivate a card
|
|
331
|
+
await fam.cards.deactivate(cardId);
|
|
332
|
+
|
|
333
|
+
// Get card preauthorizations
|
|
334
|
+
const preauths = await fam.cards.getPreauthorizations(cardId);
|
|
335
|
+
```
|
|
336
|
+
|
|
337
|
+
</details>
|
|
338
|
+
|
|
339
|
+
<details>
|
|
340
|
+
<summary><strong>Preauthorizations</strong></summary>
|
|
341
|
+
|
|
342
|
+
```typescript
|
|
343
|
+
// Create a preauthorization
|
|
344
|
+
const preauth = await fam.preauthorizations.create({
|
|
345
|
+
AuthorId: userId,
|
|
346
|
+
DebitedFunds: { Amount: 10000, Currency: 'EUR' },
|
|
347
|
+
CardId: cardId,
|
|
348
|
+
SecureModeReturnURL: 'https://example.com/return',
|
|
349
|
+
});
|
|
350
|
+
|
|
351
|
+
// Cancel a preauthorization
|
|
352
|
+
await fam.preauthorizations.cancel(preauthId);
|
|
353
|
+
```
|
|
354
|
+
|
|
355
|
+
</details>
|
|
356
|
+
|
|
357
|
+
### User-Scoped Modules
|
|
358
|
+
|
|
359
|
+
<details open>
|
|
360
|
+
<summary><strong>Bank Accounts</strong></summary>
|
|
361
|
+
|
|
362
|
+
```typescript
|
|
363
|
+
const bankAccounts = fam.bankAccounts(userId);
|
|
364
|
+
|
|
365
|
+
// Create IBAN bank account
|
|
366
|
+
const iban = await bankAccounts.createIban({
|
|
367
|
+
OwnerName: 'John Doe',
|
|
368
|
+
OwnerAddress: {
|
|
369
|
+
AddressLine1: '1 rue de la Paix',
|
|
370
|
+
City: 'Paris',
|
|
371
|
+
PostalCode: '75001',
|
|
372
|
+
Country: 'FR',
|
|
373
|
+
},
|
|
374
|
+
IBAN: 'FR7630004000031234567890143',
|
|
375
|
+
});
|
|
376
|
+
|
|
377
|
+
// List and manage
|
|
378
|
+
const accounts = await bankAccounts.list();
|
|
379
|
+
const account = await bankAccounts.getAccount(accountId);
|
|
380
|
+
await bankAccounts.deactivate(accountId);
|
|
381
|
+
```
|
|
382
|
+
|
|
383
|
+
</details>
|
|
384
|
+
|
|
385
|
+
<details>
|
|
386
|
+
<summary><strong>KYC Documents</strong></summary>
|
|
387
|
+
|
|
388
|
+
```typescript
|
|
389
|
+
const kyc = fam.kyc(userId);
|
|
390
|
+
|
|
391
|
+
// Create and submit KYC document
|
|
392
|
+
const document = await kyc.create({ Type: 'IDENTITY_PROOF' });
|
|
393
|
+
await kyc.createPage(document.Id, fileBase64);
|
|
394
|
+
await kyc.submit(document.Id);
|
|
395
|
+
|
|
396
|
+
// Check status
|
|
397
|
+
const status = await kyc.getDocument(document.Id);
|
|
398
|
+
```
|
|
399
|
+
|
|
400
|
+
</details>
|
|
401
|
+
|
|
402
|
+
<details>
|
|
403
|
+
<summary><strong>UBO Declarations</strong></summary>
|
|
404
|
+
|
|
405
|
+
```typescript
|
|
406
|
+
const ubo = fam.ubo(userId);
|
|
407
|
+
|
|
408
|
+
// Create UBO declaration
|
|
409
|
+
const declaration = await ubo.createDeclaration();
|
|
410
|
+
|
|
411
|
+
// Add Ultimate Beneficial Owner
|
|
412
|
+
const owner = await ubo.createUbo(declaration.Id, {
|
|
413
|
+
FirstName: 'John',
|
|
414
|
+
LastName: 'Doe',
|
|
415
|
+
Birthday: 631152000,
|
|
416
|
+
Nationality: 'FR',
|
|
417
|
+
Address: {
|
|
418
|
+
AddressLine1: '1 rue de la Paix',
|
|
419
|
+
City: 'Paris',
|
|
420
|
+
PostalCode: '75001',
|
|
421
|
+
Country: 'FR',
|
|
422
|
+
},
|
|
423
|
+
Birthplace: { City: 'Paris', Country: 'FR' },
|
|
424
|
+
});
|
|
425
|
+
|
|
426
|
+
// Submit declaration
|
|
427
|
+
await ubo.submit(declaration.Id);
|
|
428
|
+
```
|
|
429
|
+
|
|
430
|
+
</details>
|
|
431
|
+
|
|
432
|
+
<details>
|
|
433
|
+
<summary><strong>SCA Recipients</strong></summary>
|
|
434
|
+
|
|
435
|
+
```typescript
|
|
436
|
+
const recipients = fam.scaRecipients(userId);
|
|
437
|
+
|
|
438
|
+
// Get schema for recipient type
|
|
439
|
+
const schema = await recipients.getSchema({
|
|
440
|
+
PayoutMethodType: 'IBAN',
|
|
441
|
+
RecipientType: 'Individual',
|
|
442
|
+
Currency: 'EUR',
|
|
443
|
+
Country: 'FR',
|
|
444
|
+
});
|
|
445
|
+
|
|
446
|
+
// Create recipient
|
|
447
|
+
const recipient = await recipients.create({
|
|
448
|
+
DisplayName: 'John Doe - Main Account',
|
|
449
|
+
PayoutMethodType: 'IBAN',
|
|
450
|
+
RecipientType: 'Individual',
|
|
451
|
+
Currency: 'EUR',
|
|
452
|
+
// ... schema-specific fields
|
|
453
|
+
});
|
|
454
|
+
```
|
|
455
|
+
|
|
456
|
+
</details>
|
|
457
|
+
|
|
458
|
+
### Subscriptions
|
|
459
|
+
|
|
460
|
+
```typescript
|
|
461
|
+
// Register a subscription
|
|
462
|
+
const subscription = await fam.subscriptions.register({
|
|
463
|
+
UserId: userId,
|
|
464
|
+
WalletId: walletId,
|
|
465
|
+
CardId: cardId,
|
|
466
|
+
Amount: { Amount: 999, Currency: 'EUR' },
|
|
467
|
+
Frequency: 'MONTHLY',
|
|
468
|
+
});
|
|
469
|
+
|
|
470
|
+
// Manage subscriptions
|
|
471
|
+
const subscriptions = await fam.subscriptions.list({ UserId: userId });
|
|
472
|
+
const subscription = await fam.subscriptions.getSubscription(subscriptionId);
|
|
473
|
+
|
|
474
|
+
// Lifecycle operations
|
|
475
|
+
await fam.subscriptions.enable(subscriptionId);
|
|
476
|
+
await fam.subscriptions.disable(subscriptionId);
|
|
477
|
+
await fam.subscriptions.cancel(subscriptionId);
|
|
478
|
+
```
|
|
479
|
+
|
|
480
|
+
## Webhooks
|
|
481
|
+
|
|
482
|
+
Verify and process webhook events securely:
|
|
483
|
+
|
|
484
|
+
```typescript
|
|
485
|
+
import { Webhooks } from 'globodai-fam-sdk/webhooks';
|
|
486
|
+
|
|
487
|
+
const webhooks = new Webhooks({
|
|
488
|
+
signingSecret: process.env.WEBHOOK_SECRET,
|
|
489
|
+
});
|
|
490
|
+
|
|
491
|
+
// Express.js example
|
|
492
|
+
app.post('/webhooks', express.raw({ type: 'application/json' }), (req, res) => {
|
|
493
|
+
const signature = req.headers['x-webhook-signature'] as string;
|
|
494
|
+
|
|
495
|
+
try {
|
|
496
|
+
const event = webhooks.constructEvent(req.body, signature);
|
|
497
|
+
|
|
498
|
+
switch (event.EventType) {
|
|
499
|
+
case 'PAYIN_NORMAL_SUCCEEDED':
|
|
500
|
+
handleSuccessfulPayin(event);
|
|
501
|
+
break;
|
|
502
|
+
case 'PAYIN_NORMAL_FAILED':
|
|
503
|
+
handleFailedPayin(event);
|
|
504
|
+
break;
|
|
505
|
+
case 'KYC_SUCCEEDED':
|
|
506
|
+
handleKycValidation(event);
|
|
507
|
+
break;
|
|
508
|
+
case 'FAM_SUBSCRIPTION_PAYMENT_SUCCEEDED':
|
|
509
|
+
handleSubscriptionPayment(event);
|
|
510
|
+
break;
|
|
511
|
+
}
|
|
512
|
+
|
|
513
|
+
res.status(200).json({ received: true });
|
|
514
|
+
} catch (error) {
|
|
515
|
+
console.error('Webhook error:', error);
|
|
516
|
+
res.status(400).json({ error: 'Invalid signature' });
|
|
517
|
+
}
|
|
518
|
+
});
|
|
519
|
+
```
|
|
520
|
+
|
|
521
|
+
## Error Handling
|
|
522
|
+
|
|
523
|
+
The SDK provides typed error classes for precise error handling:
|
|
524
|
+
|
|
525
|
+
```typescript
|
|
526
|
+
import {
|
|
527
|
+
ApiError,
|
|
528
|
+
AuthenticationError,
|
|
529
|
+
ValidationError,
|
|
530
|
+
NotFoundError,
|
|
531
|
+
RateLimitError,
|
|
532
|
+
NetworkError,
|
|
533
|
+
} from 'globodai-fam-sdk';
|
|
534
|
+
|
|
535
|
+
try {
|
|
536
|
+
const user = await fam.users.getUser('invalid-id');
|
|
537
|
+
} catch (error) {
|
|
538
|
+
if (error instanceof NotFoundError) {
|
|
539
|
+
// Resource not found (404)
|
|
540
|
+
console.error('User not found');
|
|
541
|
+
} else if (error instanceof AuthenticationError) {
|
|
542
|
+
// Invalid or expired token (401)
|
|
543
|
+
console.error('Please re-authenticate');
|
|
544
|
+
} else if (error instanceof ValidationError) {
|
|
545
|
+
// Invalid request data (400)
|
|
546
|
+
console.error('Validation errors:', error.errors);
|
|
547
|
+
} else if (error instanceof RateLimitError) {
|
|
548
|
+
// Too many requests (429)
|
|
549
|
+
console.error(`Rate limited. Retry after ${error.retryAfter}s`);
|
|
550
|
+
} else if (error instanceof NetworkError) {
|
|
551
|
+
// Connection/timeout errors
|
|
552
|
+
console.error('Network error:', error.message);
|
|
553
|
+
} else if (error instanceof ApiError) {
|
|
554
|
+
// Other API errors
|
|
555
|
+
console.error(`API error ${error.statusCode}: ${error.message}`);
|
|
556
|
+
}
|
|
557
|
+
}
|
|
558
|
+
```
|
|
559
|
+
|
|
560
|
+
## TypeScript
|
|
561
|
+
|
|
562
|
+
Full type definitions are included for all API operations:
|
|
563
|
+
|
|
564
|
+
```typescript
|
|
565
|
+
import type {
|
|
566
|
+
// Users
|
|
567
|
+
NaturalUser,
|
|
568
|
+
LegalUser,
|
|
569
|
+
CreateNaturalUserInput,
|
|
570
|
+
CreateLegalUserInput,
|
|
571
|
+
|
|
572
|
+
// Payments
|
|
573
|
+
Wallet,
|
|
574
|
+
Payin,
|
|
575
|
+
Payout,
|
|
576
|
+
Transfer,
|
|
577
|
+
|
|
578
|
+
// Cards
|
|
579
|
+
Card,
|
|
580
|
+
CardRegistration,
|
|
581
|
+
Preauthorization,
|
|
582
|
+
|
|
583
|
+
// KYC
|
|
584
|
+
KycDocument,
|
|
585
|
+
UboDeclaration,
|
|
586
|
+
|
|
587
|
+
// Subscriptions
|
|
588
|
+
RecurringSubscription,
|
|
589
|
+
} from 'globodai-fam-sdk';
|
|
590
|
+
```
|
|
591
|
+
|
|
592
|
+
## Development
|
|
593
|
+
|
|
594
|
+
```bash
|
|
595
|
+
# Install dependencies
|
|
596
|
+
npm install
|
|
597
|
+
|
|
598
|
+
# Run tests
|
|
599
|
+
npm test
|
|
600
|
+
|
|
601
|
+
# Run tests with coverage
|
|
602
|
+
npm run test:coverage
|
|
603
|
+
|
|
604
|
+
# Build
|
|
605
|
+
npm run build
|
|
606
|
+
|
|
607
|
+
# Lint & format
|
|
608
|
+
npm run lint
|
|
609
|
+
npm run format
|
|
610
|
+
|
|
611
|
+
# Type check
|
|
612
|
+
npm run typecheck
|
|
613
|
+
|
|
614
|
+
# Generate documentation
|
|
615
|
+
npm run docs
|
|
616
|
+
```
|
|
617
|
+
|
|
618
|
+
## Contributing
|
|
619
|
+
|
|
620
|
+
We welcome contributions! Please see our contributing guidelines:
|
|
621
|
+
|
|
622
|
+
1. Fork the repository
|
|
623
|
+
2. Create your feature branch (`git checkout -b feature/amazing-feature`)
|
|
624
|
+
3. Write tests for your changes
|
|
625
|
+
4. Ensure all tests pass (`npm test`)
|
|
626
|
+
5. Commit using [Conventional Commits](https://conventionalcommits.org) (`git commit -m 'feat: add amazing feature'`)
|
|
627
|
+
6. Push to the branch (`git push origin feature/amazing-feature`)
|
|
628
|
+
7. Open a Pull Request
|
|
629
|
+
|
|
630
|
+
## Security
|
|
631
|
+
|
|
632
|
+
If you discover a security vulnerability, please send an email to security@globodai.com instead of using the issue tracker.
|
|
633
|
+
|
|
634
|
+
## License
|
|
635
|
+
|
|
636
|
+
This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.
|
|
637
|
+
|
|
638
|
+
---
|
|
639
|
+
|
|
640
|
+
<p align="center">
|
|
641
|
+
Made with care by the <a href="https://globodai.com">Globodai</a> team
|
|
642
|
+
</p>
|