@vitrindigital/node 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +185 -0
- package/dist/index.cjs +461 -0
- package/dist/index.d.cts +428 -0
- package/dist/index.d.ts +428 -0
- package/dist/index.js +426 -0
- package/package.json +38 -0
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,428 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* HTTP client interno do SDK.
|
|
3
|
+
*
|
|
4
|
+
* Responsabilidades:
|
|
5
|
+
* - Adicionar headers padrão (Authorization, User-Agent, Content-Type)
|
|
6
|
+
* - Serializar/deserializar JSON
|
|
7
|
+
* - Mapear erros HTTP pra `VitrinError`*
|
|
8
|
+
* - Retry automático em 429 e 5xx (até 3 tentativas, backoff exponencial)
|
|
9
|
+
* - Idempotency-Key opcional pra POSTs (evita duplo-débito quando o cliente
|
|
10
|
+
* retenta uma chamada que já chegou no servidor)
|
|
11
|
+
*/
|
|
12
|
+
interface VitrinClientOptions {
|
|
13
|
+
/** Chave da API (vd_test_* ou vd_live_*). */
|
|
14
|
+
apiKey: string;
|
|
15
|
+
/** Override da URL base. Default: https://api.vitrin.digital/api/v1 */
|
|
16
|
+
baseUrl?: string;
|
|
17
|
+
/** Timeout por request em ms. Default: 30000 (30s). */
|
|
18
|
+
timeout?: number;
|
|
19
|
+
/** Max retries em 429/5xx. Default: 3. */
|
|
20
|
+
maxRetries?: number;
|
|
21
|
+
}
|
|
22
|
+
interface RequestOptions {
|
|
23
|
+
method?: 'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE';
|
|
24
|
+
body?: unknown;
|
|
25
|
+
query?: Record<string, string | number | boolean | undefined | null>;
|
|
26
|
+
/** Idempotency-Key — recomendado em POSTs com efeito (criar charge, etc). */
|
|
27
|
+
idempotencyKey?: string;
|
|
28
|
+
}
|
|
29
|
+
declare class VitrinClient {
|
|
30
|
+
readonly baseUrl: string;
|
|
31
|
+
private readonly apiKey;
|
|
32
|
+
private readonly timeout;
|
|
33
|
+
private readonly maxRetries;
|
|
34
|
+
constructor(opts: VitrinClientOptions);
|
|
35
|
+
/** Helper público pra resources. */
|
|
36
|
+
request<T = unknown>(path: string, options?: RequestOptions): Promise<T>;
|
|
37
|
+
private buildUrl;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* Tipos compartilhados. Refletem os JSONs retornados pela API.
|
|
42
|
+
*
|
|
43
|
+
* Mantidos como interfaces genéricas (em vez de unions super-precisas) pra
|
|
44
|
+
* que mudanças não-quebra-API no backend não exijam major bump no SDK.
|
|
45
|
+
*/
|
|
46
|
+
type PaymentMethod = 'PIX' | 'PIX_AUTOMATIC' | 'BOLETO' | 'CREDIT_CARD';
|
|
47
|
+
type TransactionStatus = 'pending' | 'confirmed' | 'received' | 'overdue' | 'refunded' | 'chargeback' | 'failed' | 'canceled';
|
|
48
|
+
interface Customer {
|
|
49
|
+
id: string;
|
|
50
|
+
name: string;
|
|
51
|
+
email: string;
|
|
52
|
+
cpf_cnpj: string;
|
|
53
|
+
phone?: string;
|
|
54
|
+
address?: string;
|
|
55
|
+
address_number?: string;
|
|
56
|
+
province?: string;
|
|
57
|
+
postal_code?: string;
|
|
58
|
+
city?: string;
|
|
59
|
+
state?: string;
|
|
60
|
+
provider_customer_id?: string;
|
|
61
|
+
created_at: string;
|
|
62
|
+
updated_at: string;
|
|
63
|
+
}
|
|
64
|
+
interface Plan {
|
|
65
|
+
id: string;
|
|
66
|
+
name: string;
|
|
67
|
+
slug: string;
|
|
68
|
+
description: string;
|
|
69
|
+
price: string;
|
|
70
|
+
billing_cycle: 'weekly' | 'biweekly' | 'monthly' | 'bimonthly' | 'quarterly' | 'semiannually' | 'yearly';
|
|
71
|
+
is_active: boolean;
|
|
72
|
+
created_at: string;
|
|
73
|
+
updated_at: string;
|
|
74
|
+
}
|
|
75
|
+
interface Product {
|
|
76
|
+
id: string;
|
|
77
|
+
name: string;
|
|
78
|
+
slug: string;
|
|
79
|
+
description: string;
|
|
80
|
+
price: string;
|
|
81
|
+
product_type: 'one_time' | 'pack' | 'credits';
|
|
82
|
+
is_active: boolean;
|
|
83
|
+
created_at: string;
|
|
84
|
+
updated_at: string;
|
|
85
|
+
}
|
|
86
|
+
interface Subscription {
|
|
87
|
+
id: string;
|
|
88
|
+
customer: string;
|
|
89
|
+
plan: string;
|
|
90
|
+
status: 'pending' | 'active' | 'overdue' | 'canceled' | 'expired';
|
|
91
|
+
billing_type: PaymentMethod;
|
|
92
|
+
current_period_start: string | null;
|
|
93
|
+
current_period_end: string | null;
|
|
94
|
+
canceled_at: string | null;
|
|
95
|
+
created_at: string;
|
|
96
|
+
updated_at: string;
|
|
97
|
+
}
|
|
98
|
+
interface Transaction {
|
|
99
|
+
id: string;
|
|
100
|
+
customer: string;
|
|
101
|
+
subscription: string | null;
|
|
102
|
+
provider_payment_id: string;
|
|
103
|
+
description: string;
|
|
104
|
+
amount: string;
|
|
105
|
+
net_amount: string;
|
|
106
|
+
platform_fee: string;
|
|
107
|
+
provider_fee: string;
|
|
108
|
+
billing_type: PaymentMethod;
|
|
109
|
+
installments: number;
|
|
110
|
+
status: TransactionStatus;
|
|
111
|
+
pix_qr_code?: string;
|
|
112
|
+
pix_copy_paste?: string;
|
|
113
|
+
boleto_url?: string;
|
|
114
|
+
boleto_barcode?: string;
|
|
115
|
+
due_date?: string | null;
|
|
116
|
+
paid_at?: string | null;
|
|
117
|
+
refunded_at?: string | null;
|
|
118
|
+
anticipated: boolean;
|
|
119
|
+
anticipation_fee: string;
|
|
120
|
+
created_at: string;
|
|
121
|
+
updated_at: string;
|
|
122
|
+
}
|
|
123
|
+
interface PaginatedList<T> {
|
|
124
|
+
count: number;
|
|
125
|
+
next: string | null;
|
|
126
|
+
previous: string | null;
|
|
127
|
+
results: T[];
|
|
128
|
+
}
|
|
129
|
+
/** Response do GET /balance/. */
|
|
130
|
+
interface Balance {
|
|
131
|
+
available: number;
|
|
132
|
+
total: number;
|
|
133
|
+
pending: number;
|
|
134
|
+
withdrawal_fees: {
|
|
135
|
+
pix: number;
|
|
136
|
+
ted: number;
|
|
137
|
+
};
|
|
138
|
+
}
|
|
139
|
+
/** Response do GET /balance/scheduled/. */
|
|
140
|
+
interface ScheduledReceivable {
|
|
141
|
+
release_date: string;
|
|
142
|
+
amount: number;
|
|
143
|
+
method: PaymentMethod;
|
|
144
|
+
installment: string | null;
|
|
145
|
+
transaction_id: string;
|
|
146
|
+
anticipated: boolean;
|
|
147
|
+
}
|
|
148
|
+
interface ScheduledReceivablesResponse {
|
|
149
|
+
horizon_days: number;
|
|
150
|
+
total_scheduled: number;
|
|
151
|
+
count: number;
|
|
152
|
+
by_day: Array<{
|
|
153
|
+
date: string;
|
|
154
|
+
total: number;
|
|
155
|
+
count: number;
|
|
156
|
+
}>;
|
|
157
|
+
items: ScheduledReceivable[];
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
interface CreateChargeParams {
|
|
161
|
+
customer_id: string;
|
|
162
|
+
amount: number | string;
|
|
163
|
+
billing_type: 'PIX' | 'BOLETO' | 'CREDIT_CARD';
|
|
164
|
+
description?: string;
|
|
165
|
+
due_date?: string;
|
|
166
|
+
installments?: number;
|
|
167
|
+
credit_card_token?: string;
|
|
168
|
+
/** Idempotency-Key (header) — recomendado pra evitar duplo-débito em retry. */
|
|
169
|
+
idempotencyKey?: string;
|
|
170
|
+
}
|
|
171
|
+
interface RefundParams {
|
|
172
|
+
/** Valor parcial em reais. Omitir = reembolso total. */
|
|
173
|
+
amount?: number | string;
|
|
174
|
+
pin: string;
|
|
175
|
+
}
|
|
176
|
+
interface ListChargesParams {
|
|
177
|
+
status?: string;
|
|
178
|
+
billing_type?: string;
|
|
179
|
+
customer_id?: string;
|
|
180
|
+
date_from?: string;
|
|
181
|
+
date_to?: string;
|
|
182
|
+
min_amount?: number;
|
|
183
|
+
max_amount?: number;
|
|
184
|
+
page?: number;
|
|
185
|
+
}
|
|
186
|
+
declare class Charges {
|
|
187
|
+
private client;
|
|
188
|
+
constructor(client: VitrinClient);
|
|
189
|
+
/** Cria uma cobrança avulsa (PIX/Boleto/Cartão). */
|
|
190
|
+
create(params: CreateChargeParams): Promise<Transaction>;
|
|
191
|
+
retrieve(id: string): Promise<Transaction>;
|
|
192
|
+
list(params?: ListChargesParams): Promise<PaginatedList<Transaction>>;
|
|
193
|
+
refund(id: string, params: RefundParams): Promise<Transaction>;
|
|
194
|
+
cancel(id: string, pin: string): Promise<{
|
|
195
|
+
status: string;
|
|
196
|
+
}>;
|
|
197
|
+
/** Status atual da transação (consultado no provedor). */
|
|
198
|
+
status(id: string): Promise<{
|
|
199
|
+
status: string;
|
|
200
|
+
raw?: unknown;
|
|
201
|
+
}>;
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
interface CreateCustomerParams {
|
|
205
|
+
name: string;
|
|
206
|
+
email: string;
|
|
207
|
+
cpf_cnpj: string;
|
|
208
|
+
phone?: string;
|
|
209
|
+
address?: string;
|
|
210
|
+
address_number?: string;
|
|
211
|
+
province?: string;
|
|
212
|
+
postal_code?: string;
|
|
213
|
+
city?: string;
|
|
214
|
+
state?: string;
|
|
215
|
+
}
|
|
216
|
+
type UpdateCustomerParams = Partial<CreateCustomerParams>;
|
|
217
|
+
declare class Customers {
|
|
218
|
+
private client;
|
|
219
|
+
constructor(client: VitrinClient);
|
|
220
|
+
create(params: CreateCustomerParams): Promise<Customer>;
|
|
221
|
+
retrieve(id: string): Promise<Customer>;
|
|
222
|
+
list(params?: {
|
|
223
|
+
page?: number;
|
|
224
|
+
search?: string;
|
|
225
|
+
}): Promise<PaginatedList<Customer>>;
|
|
226
|
+
update(id: string, params: UpdateCustomerParams): Promise<Customer>;
|
|
227
|
+
delete(id: string): Promise<void>;
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
interface CreatePlanParams {
|
|
231
|
+
name: string;
|
|
232
|
+
description?: string;
|
|
233
|
+
price: number | string;
|
|
234
|
+
billing_cycle: Plan['billing_cycle'];
|
|
235
|
+
}
|
|
236
|
+
type UpdatePlanParams = Partial<CreatePlanParams> & {
|
|
237
|
+
is_active?: boolean;
|
|
238
|
+
};
|
|
239
|
+
declare class Plans {
|
|
240
|
+
private client;
|
|
241
|
+
constructor(client: VitrinClient);
|
|
242
|
+
create(params: CreatePlanParams): Promise<Plan>;
|
|
243
|
+
retrieve(id: string): Promise<Plan>;
|
|
244
|
+
list(params?: {
|
|
245
|
+
page?: number;
|
|
246
|
+
}): Promise<PaginatedList<Plan>>;
|
|
247
|
+
update(id: string, params: UpdatePlanParams): Promise<Plan>;
|
|
248
|
+
delete(id: string): Promise<void>;
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
interface CreateSubscriptionParams {
|
|
252
|
+
customer_id: string;
|
|
253
|
+
plan_id: string;
|
|
254
|
+
billing_type: 'PIX' | 'CREDIT_CARD' | 'BOLETO';
|
|
255
|
+
credit_card_token?: string;
|
|
256
|
+
next_due_date?: string;
|
|
257
|
+
}
|
|
258
|
+
declare class Subscriptions {
|
|
259
|
+
private client;
|
|
260
|
+
constructor(client: VitrinClient);
|
|
261
|
+
create(params: CreateSubscriptionParams): Promise<Subscription>;
|
|
262
|
+
retrieve(id: string): Promise<Subscription>;
|
|
263
|
+
list(params?: {
|
|
264
|
+
page?: number;
|
|
265
|
+
status?: string;
|
|
266
|
+
}): Promise<PaginatedList<Subscription>>;
|
|
267
|
+
cancel(id: string, pin: string): Promise<Subscription>;
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
interface CreateProductParams {
|
|
271
|
+
name: string;
|
|
272
|
+
description?: string;
|
|
273
|
+
price: number | string;
|
|
274
|
+
product_type?: 'one_time' | 'pack' | 'credits';
|
|
275
|
+
}
|
|
276
|
+
type UpdateProductParams = Partial<CreateProductParams> & {
|
|
277
|
+
is_active?: boolean;
|
|
278
|
+
};
|
|
279
|
+
declare class Products {
|
|
280
|
+
private client;
|
|
281
|
+
constructor(client: VitrinClient);
|
|
282
|
+
create(params: CreateProductParams): Promise<Product>;
|
|
283
|
+
retrieve(id: string): Promise<Product>;
|
|
284
|
+
list(params?: {
|
|
285
|
+
page?: number;
|
|
286
|
+
}): Promise<PaginatedList<Product>>;
|
|
287
|
+
update(id: string, params: UpdateProductParams): Promise<Product>;
|
|
288
|
+
delete(id: string): Promise<void>;
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
declare class BalanceAPI {
|
|
292
|
+
private client;
|
|
293
|
+
constructor(client: VitrinClient);
|
|
294
|
+
/** Saldo atual: disponível, pendente e total. */
|
|
295
|
+
retrieve(): Promise<Balance>;
|
|
296
|
+
/** Cronograma de recebíveis futuros (Pix D+1, Boleto D+2, Cartão D+30·N). */
|
|
297
|
+
scheduled(daysAhead?: number): Promise<ScheduledReceivablesResponse>;
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
/**
|
|
301
|
+
* Validação de webhooks Vitrin → seu backend.
|
|
302
|
+
*
|
|
303
|
+
* Toda chamada que a Vitrin faz pra sua URL de webhook leva:
|
|
304
|
+
* X-Vitrin-Signature: HMAC-SHA256 do body cru com `webhook_secret`
|
|
305
|
+
* X-Vitrin-Timestamp: epoch UTC em segundos
|
|
306
|
+
* X-Vitrin-Event: tipo do evento (ex: "Autorizado")
|
|
307
|
+
* X-Vitrin-Event-Id: ID único pra idempotência
|
|
308
|
+
*
|
|
309
|
+
* Use `Webhooks.constructEvent` no handler do seu backend pra validar
|
|
310
|
+
* antes de processar — protege contra requisições forjadas.
|
|
311
|
+
*/
|
|
312
|
+
interface WebhookEvent<T = Record<string, unknown>> {
|
|
313
|
+
/** Tipo do evento (ex: "Autorizado", "Estornado"). */
|
|
314
|
+
type: string;
|
|
315
|
+
/** ID único do evento (use pra idempotência). */
|
|
316
|
+
id: string;
|
|
317
|
+
/** Timestamp em ms da epoch UTC. */
|
|
318
|
+
timestampMs: number;
|
|
319
|
+
/** Payload original já parseado. */
|
|
320
|
+
data: T;
|
|
321
|
+
}
|
|
322
|
+
interface ConstructEventOptions {
|
|
323
|
+
/** Body cru (string ou Buffer) recebido — NÃO o objeto parseado. */
|
|
324
|
+
payload: string | Buffer;
|
|
325
|
+
/** Header X-Vitrin-Signature. */
|
|
326
|
+
signature: string | null | undefined;
|
|
327
|
+
/** Header X-Vitrin-Timestamp (segundos). */
|
|
328
|
+
timestamp?: string | null | undefined;
|
|
329
|
+
/** Header X-Vitrin-Event. */
|
|
330
|
+
eventType?: string | null | undefined;
|
|
331
|
+
/** Header X-Vitrin-Event-Id. */
|
|
332
|
+
eventId?: string | null | undefined;
|
|
333
|
+
/** Webhook secret da org (org.webhook_secret no nosso backend). */
|
|
334
|
+
secret: string;
|
|
335
|
+
/** Tolerância de timestamp (ms) — rejeita se headers vierem stale.
|
|
336
|
+
* Default: 5 minutos. Passe 0 pra desabilitar. */
|
|
337
|
+
toleranceMs?: number;
|
|
338
|
+
}
|
|
339
|
+
declare const Webhooks: {
|
|
340
|
+
/** Valida a assinatura e retorna o evento parseado. Lança em qualquer falha. */
|
|
341
|
+
constructEvent<T = Record<string, unknown>>(opts: ConstructEventOptions): WebhookEvent<T>;
|
|
342
|
+
};
|
|
343
|
+
|
|
344
|
+
/**
|
|
345
|
+
* Hierarquia de erros do SDK. Todos descendem de `VitrinError`.
|
|
346
|
+
*
|
|
347
|
+
* VitrinError — base, qualquer falha conhecida do SDK
|
|
348
|
+
* ├─ VitrinAuthError — 401/403 (chave inválida ou sem permissão)
|
|
349
|
+
* ├─ VitrinValidationError — 400/422 (DRF retornou field errors)
|
|
350
|
+
* ├─ VitrinRateLimitError — 429
|
|
351
|
+
* ├─ VitrinNotFoundError — 404
|
|
352
|
+
* ├─ VitrinServerError — 5xx
|
|
353
|
+
* └─ VitrinNetworkError — falha antes da resposta (DNS, timeout...)
|
|
354
|
+
*
|
|
355
|
+
* Toda instância carrega `statusCode`, `body` (resposta crua) e `requestId`
|
|
356
|
+
* (header X-Request-ID se presente) pra logging.
|
|
357
|
+
*/
|
|
358
|
+
declare class VitrinError extends Error {
|
|
359
|
+
readonly statusCode?: number;
|
|
360
|
+
readonly body?: unknown;
|
|
361
|
+
readonly requestId?: string;
|
|
362
|
+
constructor(message: string, opts?: {
|
|
363
|
+
statusCode?: number;
|
|
364
|
+
body?: unknown;
|
|
365
|
+
requestId?: string;
|
|
366
|
+
});
|
|
367
|
+
}
|
|
368
|
+
declare class VitrinAuthError extends VitrinError {
|
|
369
|
+
}
|
|
370
|
+
declare class VitrinValidationError extends VitrinError {
|
|
371
|
+
readonly fieldErrors?: Record<string, string[]>;
|
|
372
|
+
constructor(message: string, opts?: {
|
|
373
|
+
statusCode?: number;
|
|
374
|
+
body?: unknown;
|
|
375
|
+
requestId?: string;
|
|
376
|
+
fieldErrors?: Record<string, string[]>;
|
|
377
|
+
});
|
|
378
|
+
}
|
|
379
|
+
declare class VitrinRateLimitError extends VitrinError {
|
|
380
|
+
}
|
|
381
|
+
declare class VitrinNotFoundError extends VitrinError {
|
|
382
|
+
}
|
|
383
|
+
declare class VitrinServerError extends VitrinError {
|
|
384
|
+
}
|
|
385
|
+
declare class VitrinNetworkError extends VitrinError {
|
|
386
|
+
}
|
|
387
|
+
|
|
388
|
+
/**
|
|
389
|
+
* @vitrindigital/node — SDK oficial Node.js da Vitrin Digital.
|
|
390
|
+
*
|
|
391
|
+
* @example
|
|
392
|
+
* ```ts
|
|
393
|
+
* import { Vitrin } from '@vitrindigital/node';
|
|
394
|
+
*
|
|
395
|
+
* const vitrin = new Vitrin({ apiKey: process.env.VITRIN_API_KEY! });
|
|
396
|
+
*
|
|
397
|
+
* const customer = await vitrin.customers.create({
|
|
398
|
+
* name: 'Maria Silva',
|
|
399
|
+
* email: 'maria@test.com',
|
|
400
|
+
* cpf_cnpj: '12345678901',
|
|
401
|
+
* });
|
|
402
|
+
*
|
|
403
|
+
* const charge = await vitrin.charges.create({
|
|
404
|
+
* customer_id: customer.id,
|
|
405
|
+
* amount: 99.90,
|
|
406
|
+
* billing_type: 'PIX',
|
|
407
|
+
* description: 'Mensalidade abril',
|
|
408
|
+
* idempotencyKey: `mensalidade-${customer.id}-2026-04`,
|
|
409
|
+
* });
|
|
410
|
+
*
|
|
411
|
+
* console.log(charge.pix_qr_code);
|
|
412
|
+
* ```
|
|
413
|
+
*/
|
|
414
|
+
|
|
415
|
+
declare class Vitrin {
|
|
416
|
+
readonly client: VitrinClient;
|
|
417
|
+
readonly charges: Charges;
|
|
418
|
+
readonly customers: Customers;
|
|
419
|
+
readonly plans: Plans;
|
|
420
|
+
readonly subscriptions: Subscriptions;
|
|
421
|
+
readonly products: Products;
|
|
422
|
+
readonly balance: BalanceAPI;
|
|
423
|
+
constructor(opts: VitrinClientOptions);
|
|
424
|
+
/** Acesso bruto pro caso de endpoint não coberto pelos resources. */
|
|
425
|
+
request<T = unknown>(path: string, options?: Parameters<VitrinClient['request']>[1]): Promise<T>;
|
|
426
|
+
}
|
|
427
|
+
|
|
428
|
+
export { type Balance, type ConstructEventOptions, type Customer, type PaginatedList, type PaymentMethod, type Plan, type Product, type RequestOptions, type ScheduledReceivable, type ScheduledReceivablesResponse, type Subscription, type Transaction, type TransactionStatus, Vitrin, VitrinAuthError, type VitrinClientOptions, VitrinError, VitrinNetworkError, VitrinNotFoundError, VitrinRateLimitError, VitrinServerError, VitrinValidationError, type WebhookEvent, Webhooks };
|