@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.
Files changed (222) hide show
  1. package/CHANGELOG.md +27 -0
  2. package/dist/commands/main.d.ts +16 -0
  3. package/dist/commands/main.d.ts.map +1 -0
  4. package/dist/commands/main.js +17 -0
  5. package/dist/commands/main.js.map +1 -0
  6. package/dist/commands/make_billable.d.ts +16 -0
  7. package/dist/commands/make_billable.d.ts.map +1 -0
  8. package/dist/commands/make_billable.js +30 -0
  9. package/dist/commands/make_billable.js.map +1 -0
  10. package/dist/commands/make_webhook_handler.d.ts +20 -0
  11. package/dist/commands/make_webhook_handler.d.ts.map +1 -0
  12. package/dist/commands/make_webhook_handler.js +34 -0
  13. package/dist/commands/make_webhook_handler.js.map +1 -0
  14. package/dist/commands/payments_sync.d.ts +20 -0
  15. package/dist/commands/payments_sync.d.ts.map +1 -0
  16. package/dist/commands/payments_sync.js +95 -0
  17. package/dist/commands/payments_sync.js.map +1 -0
  18. package/dist/commands/payments_webhook.d.ts +19 -0
  19. package/dist/commands/payments_webhook.d.ts.map +1 -0
  20. package/dist/commands/payments_webhook.js +123 -0
  21. package/dist/commands/payments_webhook.js.map +1 -0
  22. package/dist/configure.d.ts +12 -0
  23. package/dist/configure.d.ts.map +1 -0
  24. package/dist/configure.js +34 -0
  25. package/dist/configure.js.map +1 -0
  26. package/dist/providers/payments_provider.d.ts +15 -0
  27. package/dist/providers/payments_provider.d.ts.map +1 -0
  28. package/dist/providers/payments_provider.js +155 -0
  29. package/dist/providers/payments_provider.js.map +1 -0
  30. package/dist/src/billing/billing_overview.d.ts +26 -0
  31. package/dist/src/billing/billing_overview.d.ts.map +1 -0
  32. package/dist/src/billing/billing_overview.js +27 -0
  33. package/dist/src/billing/billing_overview.js.map +1 -0
  34. package/dist/src/billing/billing_store.d.ts +73 -0
  35. package/dist/src/billing/billing_store.d.ts.map +1 -0
  36. package/dist/src/billing/billing_store.js +2 -0
  37. package/dist/src/billing/billing_store.js.map +1 -0
  38. package/dist/src/billing/index.d.ts +8 -0
  39. package/dist/src/billing/index.d.ts.map +1 -0
  40. package/dist/src/billing/index.js +6 -0
  41. package/dist/src/billing/index.js.map +1 -0
  42. package/dist/src/billing/lucid_billing_store.d.ts +84 -0
  43. package/dist/src/billing/lucid_billing_store.d.ts.map +1 -0
  44. package/dist/src/billing/lucid_billing_store.js +143 -0
  45. package/dist/src/billing/lucid_billing_store.js.map +1 -0
  46. package/dist/src/billing/metered_bill.d.ts +60 -0
  47. package/dist/src/billing/metered_bill.d.ts.map +1 -0
  48. package/dist/src/billing/metered_bill.js +46 -0
  49. package/dist/src/billing/metered_bill.js.map +1 -0
  50. package/dist/src/billing/mixins/index.d.ts +6 -0
  51. package/dist/src/billing/mixins/index.d.ts.map +1 -0
  52. package/dist/src/billing/mixins/index.js +6 -0
  53. package/dist/src/billing/mixins/index.js.map +1 -0
  54. package/dist/src/billing/mixins/with_billable.d.ts +23 -0
  55. package/dist/src/billing/mixins/with_billable.d.ts.map +1 -0
  56. package/dist/src/billing/mixins/with_billable.js +33 -0
  57. package/dist/src/billing/mixins/with_billable.js.map +1 -0
  58. package/dist/src/billing/mixins/with_payment.d.ts +45 -0
  59. package/dist/src/billing/mixins/with_payment.d.ts.map +1 -0
  60. package/dist/src/billing/mixins/with_payment.js +94 -0
  61. package/dist/src/billing/mixins/with_payment.js.map +1 -0
  62. package/dist/src/billing/mixins/with_subscription.d.ts +50 -0
  63. package/dist/src/billing/mixins/with_subscription.d.ts.map +1 -0
  64. package/dist/src/billing/mixins/with_subscription.js +95 -0
  65. package/dist/src/billing/mixins/with_subscription.js.map +1 -0
  66. package/dist/src/billing/mixins/with_usage_event.d.ts +22 -0
  67. package/dist/src/billing/mixins/with_usage_event.d.ts.map +1 -0
  68. package/dist/src/billing/mixins/with_usage_event.js +39 -0
  69. package/dist/src/billing/mixins/with_usage_event.js.map +1 -0
  70. package/dist/src/billing/mixins/with_webhook_event.d.ts +21 -0
  71. package/dist/src/billing/mixins/with_webhook_event.d.ts.map +1 -0
  72. package/dist/src/billing/mixins/with_webhook_event.js +42 -0
  73. package/dist/src/billing/mixins/with_webhook_event.js.map +1 -0
  74. package/dist/src/billing/webhook_dispatcher.d.ts +79 -0
  75. package/dist/src/billing/webhook_dispatcher.d.ts.map +1 -0
  76. package/dist/src/billing/webhook_dispatcher.js +125 -0
  77. package/dist/src/billing/webhook_dispatcher.js.map +1 -0
  78. package/dist/src/billing/webhook_events.d.ts +49 -0
  79. package/dist/src/billing/webhook_events.d.ts.map +1 -0
  80. package/dist/src/billing/webhook_events.js +44 -0
  81. package/dist/src/billing/webhook_events.js.map +1 -0
  82. package/dist/src/billing/webhook_processor.d.ts +39 -0
  83. package/dist/src/billing/webhook_processor.d.ts.map +1 -0
  84. package/dist/src/billing/webhook_processor.js +209 -0
  85. package/dist/src/billing/webhook_processor.js.map +1 -0
  86. package/dist/src/define_config.d.ts +251 -0
  87. package/dist/src/define_config.d.ts.map +1 -0
  88. package/dist/src/define_config.js +67 -0
  89. package/dist/src/define_config.js.map +1 -0
  90. package/dist/src/diagnostics.d.ts +155 -0
  91. package/dist/src/diagnostics.d.ts.map +1 -0
  92. package/dist/src/diagnostics.js +153 -0
  93. package/dist/src/diagnostics.js.map +1 -0
  94. package/dist/src/driver.d.ts +222 -0
  95. package/dist/src/driver.d.ts.map +1 -0
  96. package/dist/src/driver.js +2 -0
  97. package/dist/src/driver.js.map +1 -0
  98. package/dist/src/drivers/abacate.d.ts +35 -0
  99. package/dist/src/drivers/abacate.d.ts.map +1 -0
  100. package/dist/src/drivers/abacate.js +381 -0
  101. package/dist/src/drivers/abacate.js.map +1 -0
  102. package/dist/src/drivers/asaas.d.ts +36 -0
  103. package/dist/src/drivers/asaas.d.ts.map +1 -0
  104. package/dist/src/drivers/asaas.js +455 -0
  105. package/dist/src/drivers/asaas.js.map +1 -0
  106. package/dist/src/drivers/stripe.d.ts +36 -0
  107. package/dist/src/drivers/stripe.d.ts.map +1 -0
  108. package/dist/src/drivers/stripe.js +392 -0
  109. package/dist/src/drivers/stripe.js.map +1 -0
  110. package/dist/src/drivers/woovi.d.ts +49 -0
  111. package/dist/src/drivers/woovi.d.ts.map +1 -0
  112. package/dist/src/drivers/woovi.js +339 -0
  113. package/dist/src/drivers/woovi.js.map +1 -0
  114. package/dist/src/ensure_customer.d.ts +23 -0
  115. package/dist/src/ensure_customer.d.ts.map +1 -0
  116. package/dist/src/ensure_customer.js +25 -0
  117. package/dist/src/ensure_customer.js.map +1 -0
  118. package/dist/src/hooks/webhook_handlers.d.ts +50 -0
  119. package/dist/src/hooks/webhook_handlers.d.ts.map +1 -0
  120. package/dist/src/hooks/webhook_handlers.js +53 -0
  121. package/dist/src/hooks/webhook_handlers.js.map +1 -0
  122. package/dist/src/http.d.ts +24 -0
  123. package/dist/src/http.d.ts.map +1 -0
  124. package/dist/src/http.js +52 -0
  125. package/dist/src/http.js.map +1 -0
  126. package/dist/src/index.d.ts +29 -0
  127. package/dist/src/index.d.ts.map +1 -0
  128. package/dist/src/index.js +15 -0
  129. package/dist/src/index.js.map +1 -0
  130. package/dist/src/invoice/drivers/asaas.d.ts +23 -0
  131. package/dist/src/invoice/drivers/asaas.d.ts.map +1 -0
  132. package/dist/src/invoice/drivers/asaas.js +85 -0
  133. package/dist/src/invoice/drivers/asaas.js.map +1 -0
  134. package/dist/src/invoice/drivers/enotas.d.ts +23 -0
  135. package/dist/src/invoice/drivers/enotas.d.ts.map +1 -0
  136. package/dist/src/invoice/drivers/enotas.js +83 -0
  137. package/dist/src/invoice/drivers/enotas.js.map +1 -0
  138. package/dist/src/invoice/drivers/focus.d.ts +23 -0
  139. package/dist/src/invoice/drivers/focus.d.ts.map +1 -0
  140. package/dist/src/invoice/drivers/focus.js +90 -0
  141. package/dist/src/invoice/drivers/focus.js.map +1 -0
  142. package/dist/src/invoice/drivers/plugnotas.d.ts +22 -0
  143. package/dist/src/invoice/drivers/plugnotas.d.ts.map +1 -0
  144. package/dist/src/invoice/drivers/plugnotas.js +81 -0
  145. package/dist/src/invoice/drivers/plugnotas.js.map +1 -0
  146. package/dist/src/invoice/drivers/tecnospeed.d.ts +29 -0
  147. package/dist/src/invoice/drivers/tecnospeed.d.ts.map +1 -0
  148. package/dist/src/invoice/drivers/tecnospeed.js +87 -0
  149. package/dist/src/invoice/drivers/tecnospeed.js.map +1 -0
  150. package/dist/src/invoice/emit_invoice.d.ts +45 -0
  151. package/dist/src/invoice/emit_invoice.d.ts.map +1 -0
  152. package/dist/src/invoice/emit_invoice.js +72 -0
  153. package/dist/src/invoice/emit_invoice.js.map +1 -0
  154. package/dist/src/invoice/invoice_manager.d.ts +12 -0
  155. package/dist/src/invoice/invoice_manager.d.ts.map +1 -0
  156. package/dist/src/invoice/invoice_manager.js +35 -0
  157. package/dist/src/invoice/invoice_manager.js.map +1 -0
  158. package/dist/src/invoice/invoice_provider.d.ts +48 -0
  159. package/dist/src/invoice/invoice_provider.d.ts.map +1 -0
  160. package/dist/src/invoice/invoice_provider.js +2 -0
  161. package/dist/src/invoice/invoice_provider.js.map +1 -0
  162. package/dist/src/money.d.ts +11 -0
  163. package/dist/src/money.d.ts.map +1 -0
  164. package/dist/src/money.js +14 -0
  165. package/dist/src/money.js.map +1 -0
  166. package/dist/src/payments_manager.d.ts +40 -0
  167. package/dist/src/payments_manager.d.ts.map +1 -0
  168. package/dist/src/payments_manager.js +94 -0
  169. package/dist/src/payments_manager.js.map +1 -0
  170. package/dist/src/services/main.d.ts +6 -0
  171. package/dist/src/services/main.d.ts.map +1 -0
  172. package/dist/src/services/main.js +17 -0
  173. package/dist/src/services/main.js.map +1 -0
  174. package/dist/src/telescope/index.d.ts +3 -0
  175. package/dist/src/telescope/index.d.ts.map +1 -0
  176. package/dist/src/telescope/index.js +2 -0
  177. package/dist/src/telescope/index.js.map +1 -0
  178. package/dist/src/telescope/payments_watcher.d.ts +27 -0
  179. package/dist/src/telescope/payments_watcher.d.ts.map +1 -0
  180. package/dist/src/telescope/payments_watcher.js +58 -0
  181. package/dist/src/telescope/payments_watcher.js.map +1 -0
  182. package/dist/src/telescope/telescope-sdk.d.ts +21 -0
  183. package/dist/src/telescope/telescope-sdk.d.ts.map +1 -0
  184. package/dist/src/telescope/telescope-sdk.js +11 -0
  185. package/dist/src/telescope/telescope-sdk.js.map +1 -0
  186. package/dist/src/testing/fake_payments_driver.d.ts +64 -0
  187. package/dist/src/testing/fake_payments_driver.d.ts.map +1 -0
  188. package/dist/src/testing/fake_payments_driver.js +171 -0
  189. package/dist/src/testing/fake_payments_driver.js.map +1 -0
  190. package/dist/src/testing/in_memory_billing_store.d.ts +110 -0
  191. package/dist/src/testing/in_memory_billing_store.d.ts.map +1 -0
  192. package/dist/src/testing/in_memory_billing_store.js +136 -0
  193. package/dist/src/testing/in_memory_billing_store.js.map +1 -0
  194. package/dist/src/testing/index.d.ts +6 -0
  195. package/dist/src/testing/index.d.ts.map +1 -0
  196. package/dist/src/testing/index.js +4 -0
  197. package/dist/src/testing/index.js.map +1 -0
  198. package/dist/src/testing/mutable_clock.d.ts +12 -0
  199. package/dist/src/testing/mutable_clock.d.ts.map +1 -0
  200. package/dist/src/testing/mutable_clock.js +20 -0
  201. package/dist/src/testing/mutable_clock.js.map +1 -0
  202. package/dist/src/types.d.ts +178 -0
  203. package/dist/src/types.d.ts.map +1 -0
  204. package/dist/src/types.js +9 -0
  205. package/dist/src/types.js.map +1 -0
  206. package/dist/src/webhook_handlers.d.ts +76 -0
  207. package/dist/src/webhook_handlers.d.ts.map +1 -0
  208. package/dist/src/webhook_handlers.js +128 -0
  209. package/dist/src/webhook_handlers.js.map +1 -0
  210. package/dist/src/webhook_security.d.ts +29 -0
  211. package/dist/src/webhook_security.d.ts.map +1 -0
  212. package/dist/src/webhook_security.js +53 -0
  213. package/dist/src/webhook_security.js.map +1 -0
  214. package/dist/stubs/config/payments.stub +101 -0
  215. package/dist/stubs/database/migrations/create_billing_tables.stub +90 -0
  216. package/dist/stubs/main.d.ts +9 -0
  217. package/dist/stubs/main.d.ts.map +1 -0
  218. package/dist/stubs/main.js +16 -0
  219. package/dist/stubs/main.js.map +1 -0
  220. package/dist/stubs/make/billable/main.stub +28 -0
  221. package/dist/stubs/make/webhook_handler/main.stub +29 -0
  222. 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,2 @@
1
+ export {};
2
+ //# sourceMappingURL=driver.js.map
@@ -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