@adonis-agora/payments 0.2.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/CHANGELOG.md +27 -0
- package/dist/commands/main.d.ts +16 -0
- package/dist/commands/main.d.ts.map +1 -0
- package/dist/commands/main.js +17 -0
- package/dist/commands/main.js.map +1 -0
- package/dist/commands/make_billable.d.ts +16 -0
- package/dist/commands/make_billable.d.ts.map +1 -0
- package/dist/commands/make_billable.js +30 -0
- package/dist/commands/make_billable.js.map +1 -0
- package/dist/commands/make_webhook_handler.d.ts +20 -0
- package/dist/commands/make_webhook_handler.d.ts.map +1 -0
- package/dist/commands/make_webhook_handler.js +34 -0
- package/dist/commands/make_webhook_handler.js.map +1 -0
- package/dist/commands/payments_sync.d.ts +20 -0
- package/dist/commands/payments_sync.d.ts.map +1 -0
- package/dist/commands/payments_sync.js +95 -0
- package/dist/commands/payments_sync.js.map +1 -0
- package/dist/commands/payments_webhook.d.ts +19 -0
- package/dist/commands/payments_webhook.d.ts.map +1 -0
- package/dist/commands/payments_webhook.js +123 -0
- package/dist/commands/payments_webhook.js.map +1 -0
- package/dist/configure.d.ts +12 -0
- package/dist/configure.d.ts.map +1 -0
- package/dist/configure.js +34 -0
- package/dist/configure.js.map +1 -0
- package/dist/providers/payments_provider.d.ts +15 -0
- package/dist/providers/payments_provider.d.ts.map +1 -0
- package/dist/providers/payments_provider.js +155 -0
- package/dist/providers/payments_provider.js.map +1 -0
- package/dist/src/billing/billing_overview.d.ts +26 -0
- package/dist/src/billing/billing_overview.d.ts.map +1 -0
- package/dist/src/billing/billing_overview.js +27 -0
- package/dist/src/billing/billing_overview.js.map +1 -0
- package/dist/src/billing/billing_store.d.ts +73 -0
- package/dist/src/billing/billing_store.d.ts.map +1 -0
- package/dist/src/billing/billing_store.js +2 -0
- package/dist/src/billing/billing_store.js.map +1 -0
- package/dist/src/billing/index.d.ts +8 -0
- package/dist/src/billing/index.d.ts.map +1 -0
- package/dist/src/billing/index.js +6 -0
- package/dist/src/billing/index.js.map +1 -0
- package/dist/src/billing/lucid_billing_store.d.ts +84 -0
- package/dist/src/billing/lucid_billing_store.d.ts.map +1 -0
- package/dist/src/billing/lucid_billing_store.js +143 -0
- package/dist/src/billing/lucid_billing_store.js.map +1 -0
- package/dist/src/billing/metered_bill.d.ts +60 -0
- package/dist/src/billing/metered_bill.d.ts.map +1 -0
- package/dist/src/billing/metered_bill.js +46 -0
- package/dist/src/billing/metered_bill.js.map +1 -0
- package/dist/src/billing/mixins/index.d.ts +6 -0
- package/dist/src/billing/mixins/index.d.ts.map +1 -0
- package/dist/src/billing/mixins/index.js +6 -0
- package/dist/src/billing/mixins/index.js.map +1 -0
- package/dist/src/billing/mixins/with_billable.d.ts +23 -0
- package/dist/src/billing/mixins/with_billable.d.ts.map +1 -0
- package/dist/src/billing/mixins/with_billable.js +33 -0
- package/dist/src/billing/mixins/with_billable.js.map +1 -0
- package/dist/src/billing/mixins/with_payment.d.ts +45 -0
- package/dist/src/billing/mixins/with_payment.d.ts.map +1 -0
- package/dist/src/billing/mixins/with_payment.js +94 -0
- package/dist/src/billing/mixins/with_payment.js.map +1 -0
- package/dist/src/billing/mixins/with_subscription.d.ts +50 -0
- package/dist/src/billing/mixins/with_subscription.d.ts.map +1 -0
- package/dist/src/billing/mixins/with_subscription.js +95 -0
- package/dist/src/billing/mixins/with_subscription.js.map +1 -0
- package/dist/src/billing/mixins/with_usage_event.d.ts +22 -0
- package/dist/src/billing/mixins/with_usage_event.d.ts.map +1 -0
- package/dist/src/billing/mixins/with_usage_event.js +39 -0
- package/dist/src/billing/mixins/with_usage_event.js.map +1 -0
- package/dist/src/billing/mixins/with_webhook_event.d.ts +21 -0
- package/dist/src/billing/mixins/with_webhook_event.d.ts.map +1 -0
- package/dist/src/billing/mixins/with_webhook_event.js +42 -0
- package/dist/src/billing/mixins/with_webhook_event.js.map +1 -0
- package/dist/src/billing/webhook_dispatcher.d.ts +79 -0
- package/dist/src/billing/webhook_dispatcher.d.ts.map +1 -0
- package/dist/src/billing/webhook_dispatcher.js +125 -0
- package/dist/src/billing/webhook_dispatcher.js.map +1 -0
- package/dist/src/billing/webhook_events.d.ts +49 -0
- package/dist/src/billing/webhook_events.d.ts.map +1 -0
- package/dist/src/billing/webhook_events.js +44 -0
- package/dist/src/billing/webhook_events.js.map +1 -0
- package/dist/src/billing/webhook_processor.d.ts +39 -0
- package/dist/src/billing/webhook_processor.d.ts.map +1 -0
- package/dist/src/billing/webhook_processor.js +209 -0
- package/dist/src/billing/webhook_processor.js.map +1 -0
- package/dist/src/define_config.d.ts +251 -0
- package/dist/src/define_config.d.ts.map +1 -0
- package/dist/src/define_config.js +67 -0
- package/dist/src/define_config.js.map +1 -0
- package/dist/src/diagnostics.d.ts +155 -0
- package/dist/src/diagnostics.d.ts.map +1 -0
- package/dist/src/diagnostics.js +153 -0
- package/dist/src/diagnostics.js.map +1 -0
- package/dist/src/driver.d.ts +222 -0
- package/dist/src/driver.d.ts.map +1 -0
- package/dist/src/driver.js +2 -0
- package/dist/src/driver.js.map +1 -0
- package/dist/src/drivers/abacate.d.ts +35 -0
- package/dist/src/drivers/abacate.d.ts.map +1 -0
- package/dist/src/drivers/abacate.js +381 -0
- package/dist/src/drivers/abacate.js.map +1 -0
- package/dist/src/drivers/asaas.d.ts +36 -0
- package/dist/src/drivers/asaas.d.ts.map +1 -0
- package/dist/src/drivers/asaas.js +455 -0
- package/dist/src/drivers/asaas.js.map +1 -0
- package/dist/src/drivers/stripe.d.ts +36 -0
- package/dist/src/drivers/stripe.d.ts.map +1 -0
- package/dist/src/drivers/stripe.js +392 -0
- package/dist/src/drivers/stripe.js.map +1 -0
- package/dist/src/drivers/woovi.d.ts +49 -0
- package/dist/src/drivers/woovi.d.ts.map +1 -0
- package/dist/src/drivers/woovi.js +339 -0
- package/dist/src/drivers/woovi.js.map +1 -0
- package/dist/src/ensure_customer.d.ts +23 -0
- package/dist/src/ensure_customer.d.ts.map +1 -0
- package/dist/src/ensure_customer.js +25 -0
- package/dist/src/ensure_customer.js.map +1 -0
- package/dist/src/hooks/webhook_handlers.d.ts +50 -0
- package/dist/src/hooks/webhook_handlers.d.ts.map +1 -0
- package/dist/src/hooks/webhook_handlers.js +53 -0
- package/dist/src/hooks/webhook_handlers.js.map +1 -0
- package/dist/src/http.d.ts +24 -0
- package/dist/src/http.d.ts.map +1 -0
- package/dist/src/http.js +52 -0
- package/dist/src/http.js.map +1 -0
- package/dist/src/index.d.ts +29 -0
- package/dist/src/index.d.ts.map +1 -0
- package/dist/src/index.js +15 -0
- package/dist/src/index.js.map +1 -0
- package/dist/src/invoice/drivers/asaas.d.ts +23 -0
- package/dist/src/invoice/drivers/asaas.d.ts.map +1 -0
- package/dist/src/invoice/drivers/asaas.js +85 -0
- package/dist/src/invoice/drivers/asaas.js.map +1 -0
- package/dist/src/invoice/drivers/enotas.d.ts +23 -0
- package/dist/src/invoice/drivers/enotas.d.ts.map +1 -0
- package/dist/src/invoice/drivers/enotas.js +83 -0
- package/dist/src/invoice/drivers/enotas.js.map +1 -0
- package/dist/src/invoice/drivers/focus.d.ts +23 -0
- package/dist/src/invoice/drivers/focus.d.ts.map +1 -0
- package/dist/src/invoice/drivers/focus.js +90 -0
- package/dist/src/invoice/drivers/focus.js.map +1 -0
- package/dist/src/invoice/drivers/plugnotas.d.ts +22 -0
- package/dist/src/invoice/drivers/plugnotas.d.ts.map +1 -0
- package/dist/src/invoice/drivers/plugnotas.js +81 -0
- package/dist/src/invoice/drivers/plugnotas.js.map +1 -0
- package/dist/src/invoice/drivers/tecnospeed.d.ts +29 -0
- package/dist/src/invoice/drivers/tecnospeed.d.ts.map +1 -0
- package/dist/src/invoice/drivers/tecnospeed.js +87 -0
- package/dist/src/invoice/drivers/tecnospeed.js.map +1 -0
- package/dist/src/invoice/emit_invoice.d.ts +45 -0
- package/dist/src/invoice/emit_invoice.d.ts.map +1 -0
- package/dist/src/invoice/emit_invoice.js +72 -0
- package/dist/src/invoice/emit_invoice.js.map +1 -0
- package/dist/src/invoice/invoice_manager.d.ts +12 -0
- package/dist/src/invoice/invoice_manager.d.ts.map +1 -0
- package/dist/src/invoice/invoice_manager.js +35 -0
- package/dist/src/invoice/invoice_manager.js.map +1 -0
- package/dist/src/invoice/invoice_provider.d.ts +48 -0
- package/dist/src/invoice/invoice_provider.d.ts.map +1 -0
- package/dist/src/invoice/invoice_provider.js +2 -0
- package/dist/src/invoice/invoice_provider.js.map +1 -0
- package/dist/src/money.d.ts +11 -0
- package/dist/src/money.d.ts.map +1 -0
- package/dist/src/money.js +14 -0
- package/dist/src/money.js.map +1 -0
- package/dist/src/payments_manager.d.ts +40 -0
- package/dist/src/payments_manager.d.ts.map +1 -0
- package/dist/src/payments_manager.js +94 -0
- package/dist/src/payments_manager.js.map +1 -0
- package/dist/src/services/main.d.ts +6 -0
- package/dist/src/services/main.d.ts.map +1 -0
- package/dist/src/services/main.js +17 -0
- package/dist/src/services/main.js.map +1 -0
- package/dist/src/telescope/index.d.ts +3 -0
- package/dist/src/telescope/index.d.ts.map +1 -0
- package/dist/src/telescope/index.js +2 -0
- package/dist/src/telescope/index.js.map +1 -0
- package/dist/src/telescope/payments_watcher.d.ts +27 -0
- package/dist/src/telescope/payments_watcher.d.ts.map +1 -0
- package/dist/src/telescope/payments_watcher.js +58 -0
- package/dist/src/telescope/payments_watcher.js.map +1 -0
- package/dist/src/telescope/telescope-sdk.d.ts +21 -0
- package/dist/src/telescope/telescope-sdk.d.ts.map +1 -0
- package/dist/src/telescope/telescope-sdk.js +11 -0
- package/dist/src/telescope/telescope-sdk.js.map +1 -0
- package/dist/src/testing/fake_payments_driver.d.ts +64 -0
- package/dist/src/testing/fake_payments_driver.d.ts.map +1 -0
- package/dist/src/testing/fake_payments_driver.js +171 -0
- package/dist/src/testing/fake_payments_driver.js.map +1 -0
- package/dist/src/testing/in_memory_billing_store.d.ts +110 -0
- package/dist/src/testing/in_memory_billing_store.d.ts.map +1 -0
- package/dist/src/testing/in_memory_billing_store.js +136 -0
- package/dist/src/testing/in_memory_billing_store.js.map +1 -0
- package/dist/src/testing/index.d.ts +6 -0
- package/dist/src/testing/index.d.ts.map +1 -0
- package/dist/src/testing/index.js +4 -0
- package/dist/src/testing/index.js.map +1 -0
- package/dist/src/testing/mutable_clock.d.ts +12 -0
- package/dist/src/testing/mutable_clock.d.ts.map +1 -0
- package/dist/src/testing/mutable_clock.js +20 -0
- package/dist/src/testing/mutable_clock.js.map +1 -0
- package/dist/src/types.d.ts +178 -0
- package/dist/src/types.d.ts.map +1 -0
- package/dist/src/types.js +9 -0
- package/dist/src/types.js.map +1 -0
- package/dist/src/webhook_handlers.d.ts +76 -0
- package/dist/src/webhook_handlers.d.ts.map +1 -0
- package/dist/src/webhook_handlers.js +128 -0
- package/dist/src/webhook_handlers.js.map +1 -0
- package/dist/src/webhook_security.d.ts +29 -0
- package/dist/src/webhook_security.d.ts.map +1 -0
- package/dist/src/webhook_security.js +53 -0
- package/dist/src/webhook_security.js.map +1 -0
- package/dist/stubs/config/payments.stub +101 -0
- package/dist/stubs/database/migrations/create_billing_tables.stub +90 -0
- package/dist/stubs/main.d.ts +9 -0
- package/dist/stubs/main.d.ts.map +1 -0
- package/dist/stubs/main.js +16 -0
- package/dist/stubs/main.js.map +1 -0
- package/dist/stubs/make/billable/main.stub +28 -0
- package/dist/stubs/make/webhook_handler/main.stub +29 -0
- package/package.json +150 -0
|
@@ -0,0 +1,222 @@
|
|
|
1
|
+
import type { CheckoutSession, Customer, Invoice, InvoiceOptions, Money, Payment, PaymentMethodName, Refund, Subscription, WebhookEvent } from './types.js';
|
|
2
|
+
/**
|
|
3
|
+
* The provider-agnostic payment driver contract (Omnipay-style).
|
|
4
|
+
*
|
|
5
|
+
* Every gateway driver (Stripe, AbacatePay, Asaas, Woovi) implements this interface,
|
|
6
|
+
* normalizing its own API onto the shared domain types. The billing layer and application
|
|
7
|
+
* code depend only on this contract, so swapping gateways is a config change.
|
|
8
|
+
*/
|
|
9
|
+
export interface PaymentsDriver {
|
|
10
|
+
/** Stable provider name, e.g. `'stripe'`, `'abacate'`, `'asaas'`, `'woovi'`. */
|
|
11
|
+
readonly provider: string;
|
|
12
|
+
/**
|
|
13
|
+
* The payment methods this gateway supports (canonical names). Used by the router to
|
|
14
|
+
* reject a method the provider can't handle — e.g. routing `credit_card` to a Pix-only
|
|
15
|
+
* gateway (AbacatePay, Woovi) throws a clear error.
|
|
16
|
+
*/
|
|
17
|
+
readonly supportedMethods: readonly PaymentMethodName[];
|
|
18
|
+
/**
|
|
19
|
+
* Optional capabilities beyond the core contract. A driver that lacks a capability
|
|
20
|
+
* still implements the method (it must — the interface demands it) but throws a clear
|
|
21
|
+
* "not supported" error; the manager checks this before delegating so callers discover
|
|
22
|
+
* the limitation early instead of at the gateway.
|
|
23
|
+
*/
|
|
24
|
+
readonly capabilities?: {
|
|
25
|
+
/** Full refunds against a payment. Woovi/OpenPix lacks it. */
|
|
26
|
+
refunds?: boolean;
|
|
27
|
+
/** Lists gateway invoices. Woovi/OpenPix has no invoice concept. */
|
|
28
|
+
invoices?: boolean;
|
|
29
|
+
/** Recurring subscriptions. InfinitePay-style links lack it. */
|
|
30
|
+
subscriptions?: boolean;
|
|
31
|
+
};
|
|
32
|
+
/** Create a customer at the gateway. Returns the gateway customer. */
|
|
33
|
+
createCustomer(input: CreateCustomerInput): Promise<Customer>;
|
|
34
|
+
/** Look up a customer by its gateway id. */
|
|
35
|
+
findCustomer(customerId: string): Promise<Customer | null>;
|
|
36
|
+
/** Update customer details at the gateway. */
|
|
37
|
+
updateCustomer(customerId: string, input: UpdateCustomerInput): Promise<Customer>;
|
|
38
|
+
/** Charge a customer (or a standalone amount) and return the payment. */
|
|
39
|
+
charge(input: ChargeInput): Promise<Payment>;
|
|
40
|
+
/** Find a payment by its gateway id. */
|
|
41
|
+
findPayment(gatewayId: string): Promise<Payment | null>;
|
|
42
|
+
/** Refund a payment, optionally a partial amount. */
|
|
43
|
+
refund(paymentGatewayId: string, amount?: Money): Promise<Refund>;
|
|
44
|
+
/** Create a hosted checkout session and return the redirect URL. */
|
|
45
|
+
createCheckout(input: CheckoutInput): Promise<CheckoutSession>;
|
|
46
|
+
/** Create a recurring subscription at the gateway. */
|
|
47
|
+
createSubscription(input: CreateSubscriptionInput): Promise<Subscription>;
|
|
48
|
+
/** Cancel a subscription (optionally immediately, skipping the grace period). */
|
|
49
|
+
cancelSubscription(subscriptionGatewayId: string, options?: {
|
|
50
|
+
atPeriodEnd?: boolean;
|
|
51
|
+
}): Promise<Subscription>;
|
|
52
|
+
/** Update a subscription's amount/description at the gateway. */
|
|
53
|
+
updateSubscription(subscriptionGatewayId: string, input: UpdateSubscriptionInput): Promise<Subscription>;
|
|
54
|
+
/** Find a subscription by its gateway id. */
|
|
55
|
+
findSubscription(gatewayId: string): Promise<Subscription | null>;
|
|
56
|
+
/** List invoices for a customer. */
|
|
57
|
+
listInvoices(customerId: string): Promise<Invoice[]>;
|
|
58
|
+
/**
|
|
59
|
+
* Verify the webhook signature and normalize the raw payload into a {@link WebhookEvent}.
|
|
60
|
+
* Throws when the signature is invalid.
|
|
61
|
+
*/
|
|
62
|
+
parseWebhook(rawBody: string, headers: Record<string, string | string[] | undefined>): WebhookEvent;
|
|
63
|
+
}
|
|
64
|
+
export interface CreateCustomerInput {
|
|
65
|
+
email?: string;
|
|
66
|
+
name?: string;
|
|
67
|
+
/** CPF/CNPJ (BR gateways) or tax id. */
|
|
68
|
+
taxId?: string;
|
|
69
|
+
/** Extra provider-specific fields, e.g. phone, address. */
|
|
70
|
+
metadata?: Record<string, unknown>;
|
|
71
|
+
}
|
|
72
|
+
export interface UpdateCustomerInput {
|
|
73
|
+
email?: string;
|
|
74
|
+
name?: string;
|
|
75
|
+
taxId?: string;
|
|
76
|
+
metadata?: Record<string, unknown>;
|
|
77
|
+
}
|
|
78
|
+
/**
|
|
79
|
+
* Checkout transparente: a card tokenized in the frontend, plus the holder info most BR
|
|
80
|
+
* gateways require (Asaas `creditCardToken`/`creditCardHolderInfo`, Stripe
|
|
81
|
+
* `payment_method`). First-class so drivers map it without metadata hacks — shared by
|
|
82
|
+
* one-off {@link ChargeInput.card} and recurring {@link CreateSubscriptionInput.card}.
|
|
83
|
+
*/
|
|
84
|
+
export interface CardInput {
|
|
85
|
+
token: string;
|
|
86
|
+
holder?: {
|
|
87
|
+
name: string;
|
|
88
|
+
email: string;
|
|
89
|
+
cpfCnpj: string;
|
|
90
|
+
postalCode: string;
|
|
91
|
+
addressNumber: string;
|
|
92
|
+
phone: string;
|
|
93
|
+
};
|
|
94
|
+
remoteIp?: string;
|
|
95
|
+
}
|
|
96
|
+
export interface ChargeInput {
|
|
97
|
+
/** Gateway customer id. When absent, some gateways charge without a customer. */
|
|
98
|
+
customerId?: string;
|
|
99
|
+
amount: Money;
|
|
100
|
+
/** ISO 4217 code, lowercase (defaults to the driver's configured currency). */
|
|
101
|
+
currency?: string;
|
|
102
|
+
description?: string;
|
|
103
|
+
/** Payment method (e.g. `'pix'`, `'credit_card'`, `'boleto'`). Gateway-dependent. */
|
|
104
|
+
method?: string;
|
|
105
|
+
/** For card payments: the payment method/token id at the gateway. */
|
|
106
|
+
paymentMethodId?: string;
|
|
107
|
+
/**
|
|
108
|
+
* Checkout transparente: card tokenized in the frontend, plus the holder info most BR
|
|
109
|
+
* gateways require. First-class so drivers map it without metadata hacks.
|
|
110
|
+
*/
|
|
111
|
+
card?: CardInput;
|
|
112
|
+
/**
|
|
113
|
+
* The payer's fiscal data — the single source used when an invoice is emitted with
|
|
114
|
+
* this charge. Falls back to `card.holder` (cpfCnpj/name/email) when absent, so a
|
|
115
|
+
* card checkout that also wants a fiscal note doesn't restate the holder.
|
|
116
|
+
*/
|
|
117
|
+
customer?: {
|
|
118
|
+
name?: string;
|
|
119
|
+
taxId?: string;
|
|
120
|
+
email?: string;
|
|
121
|
+
};
|
|
122
|
+
/** Idempotency key — reusing it must not double-charge. */
|
|
123
|
+
idempotencyKey?: string;
|
|
124
|
+
/**
|
|
125
|
+
* Split the payment across recipients (marketplace-style). Each entry names the gateway
|
|
126
|
+
* wallet/account receiving a share, by percent and/or a fixed amount. Asaas maps it to
|
|
127
|
+
* the `split` array on the charge; other gateways accept it when supported.
|
|
128
|
+
*/
|
|
129
|
+
split?: Array<{
|
|
130
|
+
/** Gateway wallet/recipient id. */
|
|
131
|
+
walletId: string;
|
|
132
|
+
/** Percent of the charge value this wallet receives (0–100). */
|
|
133
|
+
percentualValue?: number;
|
|
134
|
+
/** Fixed amount (cents) this wallet receives. */
|
|
135
|
+
fixedValue?: number;
|
|
136
|
+
}>;
|
|
137
|
+
/**
|
|
138
|
+
* Your own reference echoed back on the gateway payment — the stable id webhook
|
|
139
|
+
* handlers use to route a payment back to your local record. Many BR gateways expose
|
|
140
|
+
* it as `externalReference` (Asaas) or `correlationID` (Woovi); Stripe maps it into
|
|
141
|
+
* metadata. Distinct from `idempotencyKey`: idempotency protects against duplicate
|
|
142
|
+
* charges, `externalReference` is for routing. Prefer it over digging into `event.raw`.
|
|
143
|
+
*/
|
|
144
|
+
externalReference?: string;
|
|
145
|
+
/**
|
|
146
|
+
* Emit an invoice for this charge: `true` uses the default invoice provider, a string
|
|
147
|
+
* names one from `invoice.providers`, or pass {@link InvoiceOptions} for overrides.
|
|
148
|
+
*/
|
|
149
|
+
invoice?: boolean | string | InvoiceOptions;
|
|
150
|
+
/** Extra provider-specific fields. */
|
|
151
|
+
metadata?: Record<string, unknown>;
|
|
152
|
+
}
|
|
153
|
+
export interface CheckoutInput {
|
|
154
|
+
/** Gateway customer id. */
|
|
155
|
+
customerId?: string;
|
|
156
|
+
amount: Money;
|
|
157
|
+
currency?: string;
|
|
158
|
+
description?: string;
|
|
159
|
+
successUrl: string;
|
|
160
|
+
cancelUrl?: string;
|
|
161
|
+
/** For subscription checkouts: the price/plan id. */
|
|
162
|
+
planId?: string;
|
|
163
|
+
/** Trial days for a subscription checkout. */
|
|
164
|
+
trialDays?: number;
|
|
165
|
+
/** Idempotency key — reusing it must not create a duplicate session. */
|
|
166
|
+
idempotencyKey?: string;
|
|
167
|
+
/** Emit an invoice for this checkout: `true`/name/options. */
|
|
168
|
+
invoice?: boolean | string | InvoiceOptions;
|
|
169
|
+
/** Extra provider-specific fields. */
|
|
170
|
+
metadata?: Record<string, unknown>;
|
|
171
|
+
}
|
|
172
|
+
export interface CreateSubscriptionInput {
|
|
173
|
+
customerId: string;
|
|
174
|
+
/** Price/plan id at the gateway. */
|
|
175
|
+
planId: string;
|
|
176
|
+
/** Amount in the currency's smallest unit (e.g. cents) — required by BR gateways. */
|
|
177
|
+
amount?: Money;
|
|
178
|
+
/** Billing cycle. Defaults to `'MONTHLY'` (Asaas, AbacatePay). */
|
|
179
|
+
cycle?: 'WEEKLY' | 'BIWEEKLY' | 'MONTHLY' | 'QUARTERLY' | 'SEMIANNUALLY' | 'YEARLY';
|
|
180
|
+
/** Payment method for the recurring charges (e.g. `'pix'`, `'credit_card'`). */
|
|
181
|
+
method?: string;
|
|
182
|
+
/** Description shown on the recurring charges. */
|
|
183
|
+
description?: string;
|
|
184
|
+
/** Trial days before the first charge. */
|
|
185
|
+
trialDays?: number;
|
|
186
|
+
/** First due date (ISO date) — required by some BR gateways (e.g. Asaas). */
|
|
187
|
+
startDate?: string;
|
|
188
|
+
/**
|
|
189
|
+
* Checkout transparente for recurring charges: a card tokenized in the frontend (plus
|
|
190
|
+
* holder info) so the gateway auto-charges the card each cycle. Asaas maps it to
|
|
191
|
+
* `creditCardToken`/`creditCardHolderInfo`; other gateways accept it when supported.
|
|
192
|
+
*/
|
|
193
|
+
card?: CardInput;
|
|
194
|
+
/**
|
|
195
|
+
* The payer's fiscal/identity data. Gateways that create subscriptions with an inline
|
|
196
|
+
* customer (Woovi, AbacatePay) use it instead of a pre-created `customerId`.
|
|
197
|
+
*/
|
|
198
|
+
customer?: {
|
|
199
|
+
name?: string;
|
|
200
|
+
email?: string;
|
|
201
|
+
taxId?: string;
|
|
202
|
+
};
|
|
203
|
+
/**
|
|
204
|
+
* Your own reference echoed on the gateway subscription (and its generated charges) —
|
|
205
|
+
* the stable id webhook handlers use to route a subscription payment back to your
|
|
206
|
+
* local record. Asaas propagates it to every installment payment's `externalReference`.
|
|
207
|
+
*/
|
|
208
|
+
externalReference?: string;
|
|
209
|
+
/** Emit an invoice for this subscription's charges: `true`/name/options. */
|
|
210
|
+
invoice?: boolean | string | InvoiceOptions;
|
|
211
|
+
/** Extra provider-specific fields. */
|
|
212
|
+
metadata?: Record<string, unknown>;
|
|
213
|
+
}
|
|
214
|
+
export interface UpdateSubscriptionInput {
|
|
215
|
+
/** New amount in the currency's smallest unit. */
|
|
216
|
+
amount?: Money;
|
|
217
|
+
/** New description. */
|
|
218
|
+
description?: string;
|
|
219
|
+
/** Extra provider-specific fields. */
|
|
220
|
+
metadata?: Record<string, unknown>;
|
|
221
|
+
}
|
|
222
|
+
//# sourceMappingURL=driver.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"driver.d.ts","sourceRoot":"","sources":["../../src/driver.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"driver.js","sourceRoot":"","sources":["../../src/driver.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import type { AbacateDriverConfig } from '../define_config.js';
|
|
2
|
+
import type { ChargeInput, CheckoutInput, CreateCustomerInput, CreateSubscriptionInput, PaymentsDriver, UpdateCustomerInput, UpdateSubscriptionInput } from '../driver.js';
|
|
3
|
+
import type { EmitInvoiceContext } from '../invoice/emit_invoice.js';
|
|
4
|
+
import type { CheckoutSession, Customer, Invoice, Money, Payment, Refund, Subscription, WebhookEvent } from '../types.js';
|
|
5
|
+
/**
|
|
6
|
+
* AbacatePay driver — Brazilian gateway for Pix and card payments with a developer-first
|
|
7
|
+
* API (REST v2, `https://api.abacatepay.com/v2`). Uses `fetch` directly (no SDK
|
|
8
|
+
* dependency). Webhooks are validated with an HMAC-SHA256 signature using the public key.
|
|
9
|
+
*/
|
|
10
|
+
export declare class AbacateDriver implements PaymentsDriver {
|
|
11
|
+
#private;
|
|
12
|
+
readonly provider = "abacate";
|
|
13
|
+
readonly supportedMethods: readonly ["pix", "boleto", "undefined"];
|
|
14
|
+
readonly capabilities: {
|
|
15
|
+
refunds: boolean;
|
|
16
|
+
subscriptions: boolean;
|
|
17
|
+
};
|
|
18
|
+
constructor(ctx: EmitInvoiceContext, config?: AbacateDriverConfig);
|
|
19
|
+
createCustomer(input: CreateCustomerInput): Promise<Customer>;
|
|
20
|
+
findCustomer(customerId: string): Promise<Customer | null>;
|
|
21
|
+
updateCustomer(customerId: string, input: UpdateCustomerInput): Promise<Customer>;
|
|
22
|
+
charge(input: ChargeInput): Promise<Payment>;
|
|
23
|
+
findPayment(gatewayId: string): Promise<Payment | null>;
|
|
24
|
+
refund(paymentGatewayId: string, _amount?: Money): Promise<Refund>;
|
|
25
|
+
createCheckout(input: CheckoutInput): Promise<CheckoutSession>;
|
|
26
|
+
createSubscription(input: CreateSubscriptionInput): Promise<Subscription>;
|
|
27
|
+
cancelSubscription(subscriptionGatewayId: string, _options?: {
|
|
28
|
+
atPeriodEnd?: boolean;
|
|
29
|
+
}): Promise<Subscription>;
|
|
30
|
+
findSubscription(gatewayId: string): Promise<Subscription | null>;
|
|
31
|
+
updateSubscription(subscriptionGatewayId: string, input: UpdateSubscriptionInput): Promise<Subscription>;
|
|
32
|
+
listInvoices(customerId: string): Promise<Invoice[]>;
|
|
33
|
+
parseWebhook(rawBody: string, headers: Record<string, string | string[] | undefined>): WebhookEvent;
|
|
34
|
+
}
|
|
35
|
+
//# sourceMappingURL=abacate.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"abacate.d.ts","sourceRoot":"","sources":["../../../src/drivers/abacate.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,qBAAqB,CAAC;AAM/D,OAAO,KAAK,EACV,WAAW,EACX,aAAa,EACb,mBAAmB,EACnB,uBAAuB,EACvB,cAAc,EACd,mBAAmB,EACnB,uBAAuB,EACxB,MAAM,cAAc,CAAC;AAGtB,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,4BAA4B,CAAC;AAErE,OAAO,KAAK,EACV,eAAe,EACf,QAAQ,EACR,OAAO,EACP,KAAK,EACL,OAAO,EACP,MAAM,EACN,YAAY,EACZ,YAAY,EACb,MAAM,aAAa,CAAC;AA+CrB;;;;GAIG;AACH,qBAAa,aAAc,YAAW,cAAc;;IAClD,QAAQ,CAAC,QAAQ,aAAa;IAE9B,QAAQ,CAAC,gBAAgB,0CAA2C;IACpE,QAAQ,CAAC,YAAY;;;MAA0C;gBAOnD,GAAG,EAAE,kBAAkB,EAAE,MAAM,GAAE,mBAAwB;IAiB/D,cAAc,CAAC,KAAK,EAAE,mBAAmB,GAAG,OAAO,CAAC,QAAQ,CAAC;IAY7D,YAAY,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,QAAQ,GAAG,IAAI,CAAC;IAU1D,cAAc,CAAC,UAAU,EAAE,MAAM,EAAE,KAAK,EAAE,mBAAmB,GAAG,OAAO,CAAC,QAAQ,CAAC;IAcjF,MAAM,CAAC,KAAK,EAAE,WAAW,GAAG,OAAO,CAAC,OAAO,CAAC;IAyE5C,WAAW,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,GAAG,IAAI,CAAC;IAUvD,MAAM,CAAC,gBAAgB,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,KAAK,GAAG,OAAO,CAAC,MAAM,CAAC;IAyBlE,cAAc,CAAC,KAAK,EAAE,aAAa,GAAG,OAAO,CAAC,eAAe,CAAC;IA6B9D,kBAAkB,CAAC,KAAK,EAAE,uBAAuB,GAAG,OAAO,CAAC,YAAY,CAAC;IAgBzE,kBAAkB,CACtB,qBAAqB,EAAE,MAAM,EAC7B,QAAQ,CAAC,EAAE;QAAE,WAAW,CAAC,EAAE,OAAO,CAAA;KAAE,GACnC,OAAO,CAAC,YAAY,CAAC;IAUlB,gBAAgB,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,GAAG,IAAI,CAAC;IAYjE,kBAAkB,CACtB,qBAAqB,EAAE,MAAM,EAC7B,KAAK,EAAE,uBAAuB,GAC7B,OAAO,CAAC,YAAY,CAAC;IAgBlB,YAAY,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,EAAE,CAAC;IAsB1D,YAAY,CACV,OAAO,EAAE,MAAM,EACf,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE,GAAG,SAAS,CAAC,GACrD,YAAY;CAuIhB"}
|
|
@@ -0,0 +1,381 @@
|
|
|
1
|
+
import { publishPaymentDiagnostics, publishRefundDiagnostics, publishSubscriptionDiagnostics, } from '../diagnostics.js';
|
|
2
|
+
import { headerValue, httpRequest, isNotFound } from '../http.js';
|
|
3
|
+
import { emitInvoiceIfRequested } from '../invoice/emit_invoice.js';
|
|
4
|
+
import { fromDecimal, toDecimal } from '../money.js';
|
|
5
|
+
import { verifyHmacSignature } from '../webhook_security.js';
|
|
6
|
+
/**
|
|
7
|
+
* AbacatePay driver — Brazilian gateway for Pix and card payments with a developer-first
|
|
8
|
+
* API (REST v2, `https://api.abacatepay.com/v2`). Uses `fetch` directly (no SDK
|
|
9
|
+
* dependency). Webhooks are validated with an HMAC-SHA256 signature using the public key.
|
|
10
|
+
*/
|
|
11
|
+
export class AbacateDriver {
|
|
12
|
+
provider = 'abacate';
|
|
13
|
+
// AbacatePay is Pix-first — no credit card.
|
|
14
|
+
supportedMethods = ['pix', 'boleto', 'undefined'];
|
|
15
|
+
capabilities = { refunds: true, subscriptions: true };
|
|
16
|
+
#baseUrl;
|
|
17
|
+
#publicKey;
|
|
18
|
+
#invoiceCtx;
|
|
19
|
+
#bearerToken;
|
|
20
|
+
constructor(ctx, config = {}) {
|
|
21
|
+
this.#invoiceCtx = ctx;
|
|
22
|
+
const apiKey = config.apiKey ?? process.env.ABACATE_API_KEY;
|
|
23
|
+
if (!apiKey) {
|
|
24
|
+
throw new Error('[payments] AbacatePay driver requires an API key. Set `ABACATE_API_KEY` env or pass `apiKey` to `payments.abacate()`.');
|
|
25
|
+
}
|
|
26
|
+
this.#baseUrl = 'https://api.abacatepay.com/v2';
|
|
27
|
+
// `webhookSecret` is the Agora-convention alias for AbacatePay's dashboard
|
|
28
|
+
// "public key" (the HMAC secret used to sign webhooks).
|
|
29
|
+
this.#publicKey = config.webhookSecret ?? config.publicKey ?? process.env.ABACATE_PUBLIC_KEY;
|
|
30
|
+
this.#bearerToken = apiKey;
|
|
31
|
+
}
|
|
32
|
+
// ── Customers ────────────────────────────────────────────────────────────────────────
|
|
33
|
+
async createCustomer(input) {
|
|
34
|
+
const data = await this.#request('/customer/create', {
|
|
35
|
+
method: 'POST',
|
|
36
|
+
body: {
|
|
37
|
+
...(input.name !== undefined ? { name: input.name } : {}),
|
|
38
|
+
...(input.email !== undefined ? { email: input.email } : {}),
|
|
39
|
+
...(input.taxId !== undefined ? { taxId: input.taxId } : {}),
|
|
40
|
+
},
|
|
41
|
+
});
|
|
42
|
+
return this.#mapCustomer(data);
|
|
43
|
+
}
|
|
44
|
+
async findCustomer(customerId) {
|
|
45
|
+
try {
|
|
46
|
+
const data = await this.#request(`/customer/get/${customerId}`);
|
|
47
|
+
return this.#mapCustomer(data);
|
|
48
|
+
}
|
|
49
|
+
catch (error) {
|
|
50
|
+
if (isNotFound(error))
|
|
51
|
+
return null;
|
|
52
|
+
throw error;
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
async updateCustomer(customerId, input) {
|
|
56
|
+
const data = await this.#request(`/customer/update/${customerId}`, {
|
|
57
|
+
method: 'PATCH',
|
|
58
|
+
body: {
|
|
59
|
+
...(input.name !== undefined ? { name: input.name } : {}),
|
|
60
|
+
...(input.email !== undefined ? { email: input.email } : {}),
|
|
61
|
+
...(input.taxId !== undefined ? { taxId: input.taxId } : {}),
|
|
62
|
+
},
|
|
63
|
+
});
|
|
64
|
+
return this.#mapCustomer(data);
|
|
65
|
+
}
|
|
66
|
+
// ── Payments ─────────────────────────────────────────────────────────────────────────
|
|
67
|
+
async charge(input) {
|
|
68
|
+
if (!input.customerId) {
|
|
69
|
+
throw new Error('[payments] AbacatePay requires a customer for every charge.');
|
|
70
|
+
}
|
|
71
|
+
// Transparent checkout (`POST /v2/transparents/create`): PIX/Boleto inline, no
|
|
72
|
+
// redirect — the response carries the QR/barcode directly. Needs the payer's
|
|
73
|
+
// name + taxId, resolved from the charge's fiscal `customer` or the gateway customer.
|
|
74
|
+
const method = input.method ?? 'pix';
|
|
75
|
+
const customer = await this.#resolveTransparentCustomer(input);
|
|
76
|
+
const data = await this.#request('/v2/transparents/create', {
|
|
77
|
+
method: 'POST',
|
|
78
|
+
body: {
|
|
79
|
+
method: this.#mapMethod(method),
|
|
80
|
+
data: {
|
|
81
|
+
amount: input.amount,
|
|
82
|
+
...(input.description !== undefined ? { description: input.description } : {}),
|
|
83
|
+
...(input.externalReference !== undefined ? { externalId: input.externalReference } : {}),
|
|
84
|
+
...(input.externalReference === undefined && input.idempotencyKey !== undefined
|
|
85
|
+
? { externalId: input.idempotencyKey }
|
|
86
|
+
: {}),
|
|
87
|
+
customer,
|
|
88
|
+
},
|
|
89
|
+
},
|
|
90
|
+
});
|
|
91
|
+
const payment = this.#mapTransparentPayment(data, input);
|
|
92
|
+
await emitInvoiceIfRequested(this.#invoiceCtx, input, payment, this);
|
|
93
|
+
publishPaymentDiagnostics(payment);
|
|
94
|
+
return payment;
|
|
95
|
+
}
|
|
96
|
+
/** The transparent checkout needs `{ name, taxId }` — from `input.customer` or the gateway customer. */
|
|
97
|
+
async #resolveTransparentCustomer(input) {
|
|
98
|
+
if (input.customer?.name && input.customer.taxId) {
|
|
99
|
+
return {
|
|
100
|
+
name: input.customer.name,
|
|
101
|
+
taxId: input.customer.taxId,
|
|
102
|
+
...(input.customer.email !== undefined ? { email: input.customer.email } : {}),
|
|
103
|
+
};
|
|
104
|
+
}
|
|
105
|
+
const customer = await this.findCustomer(input.customerId);
|
|
106
|
+
if (!customer?.name || !customer.taxId) {
|
|
107
|
+
throw new Error('[payments] AbacatePay transparent checkout needs the payer name + taxId — pass `customer` on the charge, or create the gateway customer with them.');
|
|
108
|
+
}
|
|
109
|
+
return {
|
|
110
|
+
name: customer.name,
|
|
111
|
+
taxId: customer.taxId,
|
|
112
|
+
...(customer.email !== undefined ? { email: customer.email } : {}),
|
|
113
|
+
};
|
|
114
|
+
}
|
|
115
|
+
#mapTransparentPayment(data, input) {
|
|
116
|
+
const method = input.method === 'boleto' ? 'boleto' : 'pix';
|
|
117
|
+
const result = {
|
|
118
|
+
id: data.id,
|
|
119
|
+
gatewayId: data.id,
|
|
120
|
+
provider: this.provider,
|
|
121
|
+
amount: { amount: input.amount, currency: 'brl' },
|
|
122
|
+
status: 'pending',
|
|
123
|
+
...(input.customerId !== undefined ? { customerId: input.customerId } : {}),
|
|
124
|
+
method,
|
|
125
|
+
createdAt: new Date().toISOString(),
|
|
126
|
+
payload: data,
|
|
127
|
+
};
|
|
128
|
+
if (data.brCodeBase64)
|
|
129
|
+
result.pixQrCode = data.brCodeBase64;
|
|
130
|
+
if (data.brCode)
|
|
131
|
+
result.pixCopiaECola = data.brCode;
|
|
132
|
+
if (data.url)
|
|
133
|
+
result.hostedUrl = data.url;
|
|
134
|
+
return result;
|
|
135
|
+
}
|
|
136
|
+
async findPayment(gatewayId) {
|
|
137
|
+
try {
|
|
138
|
+
const data = await this.#request(`/billing/get/${gatewayId}`);
|
|
139
|
+
return this.#mapPayment(data);
|
|
140
|
+
}
|
|
141
|
+
catch (error) {
|
|
142
|
+
if (isNotFound(error))
|
|
143
|
+
return null;
|
|
144
|
+
throw error;
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
async refund(paymentGatewayId, _amount) {
|
|
148
|
+
const data = await this.#request(`/billing/refund/${paymentGatewayId}`, {
|
|
149
|
+
method: 'POST',
|
|
150
|
+
body: {},
|
|
151
|
+
});
|
|
152
|
+
const refund = {
|
|
153
|
+
id: data.id,
|
|
154
|
+
gatewayId: data.id,
|
|
155
|
+
provider: this.provider,
|
|
156
|
+
amount: {
|
|
157
|
+
amount: data.amount !== undefined ? fromDecimal(data.amount) : 0,
|
|
158
|
+
currency: data.currency ?? 'brl',
|
|
159
|
+
},
|
|
160
|
+
status: 'succeeded',
|
|
161
|
+
createdAt: data.createdAt ?? new Date().toISOString(),
|
|
162
|
+
};
|
|
163
|
+
publishRefundDiagnostics(refund);
|
|
164
|
+
return refund;
|
|
165
|
+
}
|
|
166
|
+
// ── Checkout ─────────────────────────────────────────────────────────────────────────
|
|
167
|
+
async createCheckout(input) {
|
|
168
|
+
if (!input.customerId) {
|
|
169
|
+
throw new Error('[payments] AbacatePay requires a customer for checkout.');
|
|
170
|
+
}
|
|
171
|
+
const data = await this.#request('/billing/create', {
|
|
172
|
+
method: 'POST',
|
|
173
|
+
body: {
|
|
174
|
+
customerId: input.customerId,
|
|
175
|
+
amount: toDecimal(input.amount),
|
|
176
|
+
...(input.description !== undefined ? { description: input.description } : {}),
|
|
177
|
+
},
|
|
178
|
+
});
|
|
179
|
+
return {
|
|
180
|
+
id: data.id,
|
|
181
|
+
gatewayId: data.id,
|
|
182
|
+
provider: this.provider,
|
|
183
|
+
url: data.url ?? '',
|
|
184
|
+
status: 'open',
|
|
185
|
+
amount: {
|
|
186
|
+
amount: data.amount !== undefined ? fromDecimal(data.amount) : input.amount,
|
|
187
|
+
currency: data.currency ?? 'brl',
|
|
188
|
+
},
|
|
189
|
+
customerId: input.customerId,
|
|
190
|
+
...(data.pix?.copiaECola !== undefined ? { pixCopiaECola: data.pix.copiaECola } : {}),
|
|
191
|
+
};
|
|
192
|
+
}
|
|
193
|
+
// ── Subscriptions ────────────────────────────────────────────────────────────────────
|
|
194
|
+
async createSubscription(input) {
|
|
195
|
+
const data = await this.#request('/subscription/create', {
|
|
196
|
+
method: 'POST',
|
|
197
|
+
body: {
|
|
198
|
+
customerId: input.customerId,
|
|
199
|
+
...(input.amount !== undefined ? { amount: toDecimal(input.amount) } : {}),
|
|
200
|
+
frequency: input.cycle ?? 'MONTHLY',
|
|
201
|
+
...(input.startDate !== undefined ? { nextBillingAt: input.startDate } : {}),
|
|
202
|
+
...(input.description !== undefined ? { description: input.description } : {}),
|
|
203
|
+
},
|
|
204
|
+
});
|
|
205
|
+
const subscription = this.#mapSubscription(data, input.customerId);
|
|
206
|
+
publishSubscriptionDiagnostics(subscription, 'subscription.created');
|
|
207
|
+
return subscription;
|
|
208
|
+
}
|
|
209
|
+
async cancelSubscription(subscriptionGatewayId, _options) {
|
|
210
|
+
const data = await this.#request(`/subscription/cancel/${subscriptionGatewayId}`, { method: 'POST', body: {} });
|
|
211
|
+
const subscription = this.#mapSubscription(data);
|
|
212
|
+
publishSubscriptionDiagnostics(subscription, 'subscription.canceled');
|
|
213
|
+
return subscription;
|
|
214
|
+
}
|
|
215
|
+
async findSubscription(gatewayId) {
|
|
216
|
+
try {
|
|
217
|
+
const data = await this.#request(`/subscription/get/${gatewayId}`);
|
|
218
|
+
return this.#mapSubscription(data);
|
|
219
|
+
}
|
|
220
|
+
catch (error) {
|
|
221
|
+
if (isNotFound(error))
|
|
222
|
+
return null;
|
|
223
|
+
throw error;
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
async updateSubscription(subscriptionGatewayId, input) {
|
|
227
|
+
const data = await this.#request(`/subscription/update/${subscriptionGatewayId}`, {
|
|
228
|
+
method: 'PATCH',
|
|
229
|
+
body: {
|
|
230
|
+
...(input.amount !== undefined ? { amount: toDecimal(input.amount) } : {}),
|
|
231
|
+
...(input.description !== undefined ? { description: input.description } : {}),
|
|
232
|
+
},
|
|
233
|
+
});
|
|
234
|
+
return this.#mapSubscription(data);
|
|
235
|
+
}
|
|
236
|
+
// ── Invoices ─────────────────────────────────────────────────────────────────────────
|
|
237
|
+
async listInvoices(customerId) {
|
|
238
|
+
const data = await this.#request(`/billing/list?customerId=${encodeURIComponent(customerId)}`);
|
|
239
|
+
return (data.billings ?? []).map((billing) => ({
|
|
240
|
+
id: billing.id,
|
|
241
|
+
gatewayId: billing.id,
|
|
242
|
+
provider: this.provider,
|
|
243
|
+
customerId,
|
|
244
|
+
status: billing.status === 'PAID' ? 'paid' : billing.status === 'CANCELED' ? 'void' : 'open',
|
|
245
|
+
amount: {
|
|
246
|
+
amount: billing.amount !== undefined ? fromDecimal(billing.amount) : 0,
|
|
247
|
+
currency: billing.currency ?? 'brl',
|
|
248
|
+
},
|
|
249
|
+
createdAt: billing.createdAt ?? new Date().toISOString(),
|
|
250
|
+
...(billing.url !== undefined ? { hostedPdfUrl: billing.url } : {}),
|
|
251
|
+
payload: billing,
|
|
252
|
+
}));
|
|
253
|
+
}
|
|
254
|
+
// ── Webhooks ─────────────────────────────────────────────────────────────────────────
|
|
255
|
+
parseWebhook(rawBody, headers) {
|
|
256
|
+
// AbacatePay signs the raw body with HMAC-SHA256 (base64) in `x-webhook-signature`,
|
|
257
|
+
// keyed by the public key from the dashboard. Strict when a key is configured.
|
|
258
|
+
if (this.#publicKey !== undefined) {
|
|
259
|
+
const signature = headerValue(headers, 'x-webhook-signature');
|
|
260
|
+
if (!verifyHmacSignature(rawBody, signature, this.#publicKey, 'sha256')) {
|
|
261
|
+
throw new Error('[payments] Invalid or missing AbacatePay webhook signature.');
|
|
262
|
+
}
|
|
263
|
+
}
|
|
264
|
+
const payload = JSON.parse(rawBody);
|
|
265
|
+
const event = payload.event ?? 'unknown';
|
|
266
|
+
return {
|
|
267
|
+
id: payload.id ?? `${event}-${Math.random()}`,
|
|
268
|
+
provider: this.provider,
|
|
269
|
+
type: this.#mapWebhookType(event),
|
|
270
|
+
createdAt: new Date().toISOString(),
|
|
271
|
+
data: payload.data ?? {},
|
|
272
|
+
raw: payload,
|
|
273
|
+
};
|
|
274
|
+
}
|
|
275
|
+
// ── Mappers ──────────────────────────────────────────────────────────────────────────
|
|
276
|
+
#mapCustomer(data) {
|
|
277
|
+
return {
|
|
278
|
+
id: data.id,
|
|
279
|
+
...(data.name !== undefined ? { name: data.name } : {}),
|
|
280
|
+
...(data.email !== undefined ? { email: data.email } : {}),
|
|
281
|
+
...(data.taxId !== undefined ? { taxId: data.taxId } : {}),
|
|
282
|
+
};
|
|
283
|
+
}
|
|
284
|
+
#mapPayment(data, fallbackCustomerId) {
|
|
285
|
+
const customerId = data.customer?.id ?? fallbackCustomerId;
|
|
286
|
+
const result = {
|
|
287
|
+
id: data.id,
|
|
288
|
+
gatewayId: data.id,
|
|
289
|
+
provider: this.provider,
|
|
290
|
+
amount: {
|
|
291
|
+
amount: data.amount !== undefined ? fromDecimal(data.amount) : 0,
|
|
292
|
+
currency: data.currency ?? 'brl',
|
|
293
|
+
},
|
|
294
|
+
status: data.status === 'PAID' || data.status === 'COMPLETED'
|
|
295
|
+
? 'paid'
|
|
296
|
+
: data.status === 'REFUNDED'
|
|
297
|
+
? 'refunded'
|
|
298
|
+
: data.status === 'CANCELED'
|
|
299
|
+
? 'canceled'
|
|
300
|
+
: 'pending',
|
|
301
|
+
payload: data,
|
|
302
|
+
createdAt: data.createdAt ?? new Date().toISOString(),
|
|
303
|
+
};
|
|
304
|
+
if (customerId !== undefined)
|
|
305
|
+
result.customerId = customerId;
|
|
306
|
+
if (data.pix?.qrCode !== undefined)
|
|
307
|
+
result.pixQrCode = data.pix.qrCode;
|
|
308
|
+
if (data.pix?.copiaECola !== undefined)
|
|
309
|
+
result.pixCopiaECola = data.pix.copiaECola;
|
|
310
|
+
if (data.url !== undefined)
|
|
311
|
+
result.hostedUrl = data.url;
|
|
312
|
+
if (data.paidAt !== undefined)
|
|
313
|
+
result.paidAt = data.paidAt;
|
|
314
|
+
return result;
|
|
315
|
+
}
|
|
316
|
+
#mapSubscription(data, fallbackCustomerId) {
|
|
317
|
+
const statusMap = {
|
|
318
|
+
ACTIVE: 'active',
|
|
319
|
+
COMPLETED: 'active',
|
|
320
|
+
CANCELLED: 'canceled',
|
|
321
|
+
EXPIRED: 'ended',
|
|
322
|
+
};
|
|
323
|
+
return {
|
|
324
|
+
id: data.id,
|
|
325
|
+
gatewayId: data.id,
|
|
326
|
+
provider: this.provider,
|
|
327
|
+
customerId: data.customer?.id ?? fallbackCustomerId ?? '',
|
|
328
|
+
status: statusMap[data.status] ?? 'active',
|
|
329
|
+
planId: data.frequency ?? '',
|
|
330
|
+
amount: {
|
|
331
|
+
amount: data.amount !== undefined ? fromDecimal(data.amount) : 0,
|
|
332
|
+
currency: 'brl',
|
|
333
|
+
},
|
|
334
|
+
...(data.nextBillingAt !== undefined ? { endsAt: data.nextBillingAt } : {}),
|
|
335
|
+
payload: data,
|
|
336
|
+
createdAt: data.createdAt ?? new Date().toISOString(),
|
|
337
|
+
};
|
|
338
|
+
}
|
|
339
|
+
#mapWebhookType(event) {
|
|
340
|
+
switch (event) {
|
|
341
|
+
case 'checkout.completed':
|
|
342
|
+
case 'transparent.completed':
|
|
343
|
+
return 'payment.succeeded';
|
|
344
|
+
case 'checkout.refunded':
|
|
345
|
+
case 'transparent.refunded':
|
|
346
|
+
return 'payment.refunded';
|
|
347
|
+
case 'checkout.disputed':
|
|
348
|
+
case 'transparent.disputed':
|
|
349
|
+
return 'payment.failed';
|
|
350
|
+
case 'subscription.completed':
|
|
351
|
+
return 'subscription.created';
|
|
352
|
+
case 'subscription.renewed':
|
|
353
|
+
return 'subscription.updated';
|
|
354
|
+
case 'subscription.cancelled':
|
|
355
|
+
return 'subscription.canceled';
|
|
356
|
+
default:
|
|
357
|
+
return event;
|
|
358
|
+
}
|
|
359
|
+
}
|
|
360
|
+
#mapMethod(method) {
|
|
361
|
+
switch (method) {
|
|
362
|
+
case 'pix':
|
|
363
|
+
return 'PIX';
|
|
364
|
+
case 'credit_card':
|
|
365
|
+
return 'CARD';
|
|
366
|
+
case 'boleto':
|
|
367
|
+
return 'BOLETO';
|
|
368
|
+
default:
|
|
369
|
+
return 'PIX';
|
|
370
|
+
}
|
|
371
|
+
}
|
|
372
|
+
async #request(path, options = {}) {
|
|
373
|
+
return httpRequest(path, {
|
|
374
|
+
baseUrl: this.#baseUrl,
|
|
375
|
+
...(options.method !== undefined ? { method: options.method } : {}),
|
|
376
|
+
...(options.body !== undefined ? { body: options.body } : {}),
|
|
377
|
+
bearerToken: this.#bearerToken,
|
|
378
|
+
});
|
|
379
|
+
}
|
|
380
|
+
}
|
|
381
|
+
//# sourceMappingURL=abacate.js.map
|