@olympio/payment-gateway 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.
@@ -0,0 +1,351 @@
1
+ import Stripe from 'stripe';
2
+
3
+ /**
4
+ * Recursos que um gateway pode ou não suportar. Cada adapter declara seu
5
+ * conjunto; o consumidor checa antes de chamar, evitando erros crus do gateway.
6
+ */
7
+ declare const Capability: {
8
+ readonly PIX: "pix";
9
+ readonly BOLETO: "boleto";
10
+ readonly CARD: "card";
11
+ readonly REFUND: "refund";
12
+ readonly SUBSCRIPTIONS: "subscriptions";
13
+ };
14
+ type Capability = (typeof Capability)[keyof typeof Capability];
15
+ declare function hasCapability(caps: ReadonlySet<Capability>, capability: Capability): boolean;
16
+
17
+ /**
18
+ * Value object monetário em unidades mínimas (centavos), evitando erros de
19
+ * ponto flutuante. Stripe trabalha em centavos; Asaas em decimal — os mappers
20
+ * de cada adapter convertem para/desta representação única.
21
+ */
22
+ declare class Money {
23
+ readonly cents: number;
24
+ readonly currency: string;
25
+ private constructor();
26
+ static fromCents(cents: number, currency: string): Money;
27
+ static fromDecimal(amount: number, currency: string): Money;
28
+ toDecimal(): number;
29
+ equals(other: Money): boolean;
30
+ }
31
+
32
+ /** Meio de pagamento normalizado entre gateways. */
33
+ type PaymentMethod = 'pix' | 'boleto' | 'card';
34
+
35
+ type ChargeStatus = 'pending' | 'paid' | 'failed' | 'refunded' | 'canceled';
36
+ /** Dados extras de PIX, presentes quando o meio é 'pix'. */
37
+ interface PixDetails {
38
+ qrCode?: string;
39
+ copyPaste?: string;
40
+ expiresAt?: Date;
41
+ }
42
+ /** Dados extras de boleto, presentes quando o meio é 'boleto'. */
43
+ interface BoletoDetails {
44
+ url?: string;
45
+ barcode?: string;
46
+ dueDate?: Date;
47
+ }
48
+ /** Cobrança avulsa normalizada. */
49
+ interface Charge {
50
+ id: string;
51
+ status: ChargeStatus;
52
+ amount: Money;
53
+ paymentMethod: PaymentMethod;
54
+ customerId?: string;
55
+ description?: string;
56
+ pix?: PixDetails;
57
+ boleto?: BoletoDetails;
58
+ createdAt: Date;
59
+ metadata?: Record<string, string>;
60
+ }
61
+ interface CreateChargeInput {
62
+ amount: Money;
63
+ paymentMethod: PaymentMethod;
64
+ customerId: string;
65
+ description?: string;
66
+ /** Token de cartão (quando paymentMethod === 'card'). */
67
+ cardToken?: string;
68
+ /** Vencimento (boleto). */
69
+ dueDate?: Date;
70
+ /** IP do pagador. Exigido pelo Asaas em cobranças de cartão (anti-fraude). */
71
+ remoteIp?: string;
72
+ /** Chave de idempotência para evitar cobranças duplicadas. */
73
+ idempotencyKey?: string;
74
+ metadata?: Record<string, string>;
75
+ }
76
+ interface RefundChargeInput {
77
+ chargeId: string;
78
+ /** Estorno parcial; ausente = estorno total. */
79
+ amount?: Money;
80
+ idempotencyKey?: string;
81
+ }
82
+
83
+ /** Cliente normalizado, como representado dentro do gateway. */
84
+ interface Customer {
85
+ /** Identificador do cliente no gateway. */
86
+ id: string;
87
+ name: string;
88
+ email?: string;
89
+ /** CPF/CNPJ. Obrigatório em alguns gateways (ex.: Asaas). */
90
+ taxId?: string;
91
+ phone?: string;
92
+ metadata?: Record<string, string>;
93
+ }
94
+ interface CreateCustomerInput {
95
+ name: string;
96
+ email?: string;
97
+ taxId?: string;
98
+ phone?: string;
99
+ idempotencyKey?: string;
100
+ metadata?: Record<string, string>;
101
+ }
102
+ interface UpdateCustomerInput {
103
+ name?: string;
104
+ email?: string;
105
+ taxId?: string;
106
+ phone?: string;
107
+ metadata?: Record<string, string>;
108
+ }
109
+
110
+ /** Gateways suportados. Adicionar um novo gateway começa por aqui. */
111
+ type Provider = "asaas" | "stripe" | "dom";
112
+
113
+ type SubscriptionStatus = 'active' | 'canceled' | 'past_due';
114
+ type BillingInterval = 'weekly' | 'monthly' | 'yearly';
115
+ /** Assinatura recorrente normalizada. */
116
+ interface Subscription {
117
+ id: string;
118
+ status: SubscriptionStatus;
119
+ customerId: string;
120
+ amount: Money;
121
+ interval: BillingInterval;
122
+ createdAt: Date;
123
+ metadata?: Record<string, string>;
124
+ }
125
+ interface CreateSubscriptionInput {
126
+ customerId: string;
127
+ amount: Money;
128
+ interval: BillingInterval;
129
+ paymentMethod: PaymentMethod;
130
+ /** Token de cartão (quando paymentMethod === 'card'). */
131
+ cardToken?: string;
132
+ idempotencyKey?: string;
133
+ metadata?: Record<string, string>;
134
+ }
135
+
136
+ /**
137
+ * Evento de webhook normalizado entre gateways. O campo `raw` sempre preserva
138
+ * o payload original; eventos não reconhecidos viram `type: 'unknown'` em vez
139
+ * de serem engolidos ou de quebrarem o processamento.
140
+ */
141
+ type WebhookEvent = {
142
+ type: 'charge.paid';
143
+ data: Charge;
144
+ raw: unknown;
145
+ } | {
146
+ type: 'charge.failed';
147
+ data: Charge;
148
+ raw: unknown;
149
+ } | {
150
+ type: 'charge.refunded';
151
+ data: Charge;
152
+ raw: unknown;
153
+ } | {
154
+ type: 'subscription.renewed';
155
+ data: Subscription;
156
+ raw: unknown;
157
+ } | {
158
+ type: 'subscription.canceled';
159
+ data: Subscription;
160
+ raw: unknown;
161
+ } | {
162
+ type: 'unknown';
163
+ data: null;
164
+ raw: unknown;
165
+ };
166
+ type WebhookEventType = WebhookEvent['type'];
167
+ /** Entrada para verificação + parsing de um webhook recebido. */
168
+ interface WebhookInput {
169
+ /** Corpo bruto da requisição (string ou Buffer), necessário p/ verificar assinatura. */
170
+ payload: string | Buffer;
171
+ headers: Record<string, string>;
172
+ /** Segredo de verificação (signing secret do Stripe, token do Asaas). */
173
+ secret: string;
174
+ }
175
+
176
+ interface CustomerPort {
177
+ create(input: CreateCustomerInput): Promise<Customer>;
178
+ get(id: string): Promise<Customer | null>;
179
+ update(id: string, input: UpdateCustomerInput): Promise<Customer>;
180
+ delete(id: string): Promise<void>;
181
+ }
182
+ interface ChargePort {
183
+ create(input: CreateChargeInput): Promise<Charge>;
184
+ get(id: string): Promise<Charge | null>;
185
+ cancel(id: string): Promise<Charge>;
186
+ refund(input: RefundChargeInput): Promise<Charge>;
187
+ }
188
+ interface SubscriptionPort {
189
+ create(input: CreateSubscriptionInput): Promise<Subscription>;
190
+ get(id: string): Promise<Subscription | null>;
191
+ cancel(id: string): Promise<Subscription>;
192
+ }
193
+ interface WebhookPort {
194
+ /** Verifica a assinatura e normaliza o evento recebido. */
195
+ verifyAndParse(input: WebhookInput): WebhookEvent;
196
+ }
197
+ /**
198
+ * Porta principal: contrato comum implementado por todos os adapters.
199
+ *
200
+ * `TRaw` é o tipo do client nativo do gateway, exposto pelo escape hatch
201
+ * `raw()` para recursos exclusivos que o contrato comum não cobre.
202
+ */
203
+ interface PaymentGateway<TRaw = unknown> {
204
+ readonly provider: Provider;
205
+ readonly capabilities: ReadonlySet<Capability>;
206
+ supports(capability: Capability): boolean;
207
+ readonly customers: CustomerPort;
208
+ readonly charges: ChargePort;
209
+ readonly subscriptions: SubscriptionPort;
210
+ readonly webhooks: WebhookPort;
211
+ /** Escape hatch: client nativo do gateway, tipado por adapter. */
212
+ raw(): TRaw;
213
+ }
214
+
215
+ interface StripeGatewayConfig {
216
+ apiKey: string;
217
+ /** Signing secret para verificar webhooks. */
218
+ webhookSecret?: string;
219
+ }
220
+ declare class StripeGateway implements PaymentGateway<Stripe> {
221
+ private readonly config;
222
+ readonly provider: "stripe";
223
+ readonly capabilities: ReadonlySet<Capability>;
224
+ private readonly client;
225
+ readonly customers: CustomerPort;
226
+ readonly charges: ChargePort;
227
+ readonly subscriptions: SubscriptionPort;
228
+ readonly webhooks: WebhookPort;
229
+ constructor(config: StripeGatewayConfig, client?: Stripe);
230
+ supports(capability: Capability): boolean;
231
+ raw(): Stripe;
232
+ private requireMethod;
233
+ private buildCustomerPort;
234
+ private buildChargePort;
235
+ private buildSubscriptionPort;
236
+ private buildWebhookPort;
237
+ }
238
+
239
+ /** Erro bruto de uma resposta não-2xx do Asaas, normalizado depois pelo adapter. */
240
+ declare class AsaasApiError extends Error {
241
+ readonly status: number;
242
+ readonly body: unknown;
243
+ constructor(status: number, body: unknown);
244
+ }
245
+ /**
246
+ * Transporte HTTP do Asaas. É a dependência injetável do adapter (também o que
247
+ * `raw()` devolve), o que torna o gateway testável com um fake in-memory.
248
+ */
249
+ interface AsaasHttpClient {
250
+ get<T>(path: string): Promise<T>;
251
+ post<T>(path: string, body?: unknown): Promise<T>;
252
+ delete<T>(path: string): Promise<T>;
253
+ }
254
+ interface AsaasHttpConfig {
255
+ apiKey: string;
256
+ /** Base da API. Padrão: produção. Use a URL de sandbox em testes/homologação. */
257
+ baseUrl?: string;
258
+ }
259
+ /** Implementação padrão baseada em `fetch` (Node 18+). */
260
+ declare function createAsaasHttpClient(config: AsaasHttpConfig): AsaasHttpClient;
261
+
262
+ interface AsaasGatewayConfig extends AsaasHttpConfig {
263
+ /** Token configurado no Asaas para autenticar webhooks recebidos. */
264
+ webhookToken?: string;
265
+ }
266
+ declare class AsaasGateway implements PaymentGateway<AsaasHttpClient> {
267
+ private readonly config;
268
+ readonly provider: "asaas";
269
+ readonly capabilities: ReadonlySet<Capability>;
270
+ private readonly http;
271
+ readonly customers: CustomerPort;
272
+ readonly charges: ChargePort;
273
+ readonly subscriptions: SubscriptionPort;
274
+ readonly webhooks: WebhookPort;
275
+ constructor(config: AsaasGatewayConfig, http?: AsaasHttpClient);
276
+ supports(capability: Capability): boolean;
277
+ raw(): AsaasHttpClient;
278
+ private buildCustomerPort;
279
+ private buildChargePort;
280
+ private buildSubscriptionPort;
281
+ private buildWebhookPort;
282
+ }
283
+
284
+ interface DomGatewayConfig {
285
+ apiKey: string;
286
+ webhookToken?: string;
287
+ baseUrl?: string;
288
+ }
289
+
290
+ /**
291
+ * Configuração discriminada por `provider`. Adicionar um novo gateway começa
292
+ * por estender esta união e o `switch` em `createGateway`.
293
+ */
294
+ type GatewayConfig = ({
295
+ provider: 'stripe';
296
+ } & StripeGatewayConfig) | ({
297
+ provider: 'asaas';
298
+ } & AsaasGatewayConfig) | ({
299
+ provider: 'dom';
300
+ } & DomGatewayConfig);
301
+ /** Ponto de entrada: instancia o adapter correto a partir da config. */
302
+ declare function createGateway(config: GatewayConfig): PaymentGateway;
303
+
304
+ interface GatewayErrorOptions {
305
+ /** Erro original do gateway/SDK, preservado para diagnóstico. */
306
+ cause?: unknown;
307
+ /** Payload/objeto bruto retornado pelo gateway. */
308
+ raw?: unknown;
309
+ }
310
+ /** Código normalizado de erro, estável entre gateways. */
311
+ type GatewayErrorCode = 'card_declined' | 'authentication' | 'rate_limit' | 'validation' | 'unsupported_capability' | 'gateway_unavailable' | 'unknown';
312
+ /** Base de todos os erros normalizados da lib. */
313
+ declare abstract class GatewayError extends Error {
314
+ readonly provider: Provider;
315
+ abstract readonly code: GatewayErrorCode;
316
+ readonly raw?: unknown;
317
+ constructor(provider: Provider, message: string, options?: GatewayErrorOptions);
318
+ }
319
+ declare class CardDeclinedError extends GatewayError {
320
+ readonly code = "card_declined";
321
+ constructor(provider: Provider, options?: GatewayErrorOptions);
322
+ }
323
+ declare class AuthenticationError extends GatewayError {
324
+ readonly code = "authentication";
325
+ constructor(provider: Provider, options?: GatewayErrorOptions);
326
+ }
327
+ declare class RateLimitError extends GatewayError {
328
+ readonly code = "rate_limit";
329
+ constructor(provider: Provider, options?: GatewayErrorOptions);
330
+ }
331
+ declare class ValidationError extends GatewayError {
332
+ readonly code = "validation";
333
+ constructor(provider: Provider, message: string, options?: GatewayErrorOptions);
334
+ }
335
+ declare class GatewayUnavailableError extends GatewayError {
336
+ readonly code = "gateway_unavailable";
337
+ constructor(provider: Provider, options?: GatewayErrorOptions);
338
+ }
339
+ /** Erro genérico para casos não mapeados, preservando o erro original. */
340
+ declare class UnknownGatewayError extends GatewayError {
341
+ readonly code = "unknown";
342
+ constructor(provider: Provider, message: string, options?: GatewayErrorOptions);
343
+ }
344
+ /** Lançado ao chamar uma operação que o gateway não suporta. */
345
+ declare class UnsupportedCapabilityError extends GatewayError {
346
+ readonly capability: Capability;
347
+ readonly code = "unsupported_capability";
348
+ constructor(provider: Provider, capability: Capability, options?: GatewayErrorOptions);
349
+ }
350
+
351
+ export { AsaasApiError, AsaasGateway, type AsaasGatewayConfig, type AsaasHttpClient, type AsaasHttpConfig, AuthenticationError, type BillingInterval, type BoletoDetails, Capability, CardDeclinedError, type Charge, type ChargePort, type ChargeStatus, type CreateChargeInput, type CreateCustomerInput, type CreateSubscriptionInput, type Customer, type CustomerPort, type GatewayConfig, GatewayError, type GatewayErrorCode, type GatewayErrorOptions, GatewayUnavailableError, Money, type PaymentGateway, type PaymentMethod, type PixDetails, type Provider, RateLimitError, type RefundChargeInput, StripeGateway, type StripeGatewayConfig, type Subscription, type SubscriptionPort, type SubscriptionStatus, UnknownGatewayError, UnsupportedCapabilityError, type UpdateCustomerInput, ValidationError, type WebhookEvent, type WebhookEventType, type WebhookInput, type WebhookPort, createAsaasHttpClient, createGateway, hasCapability };