@geekapps/billing-fastify 0.1.0 → 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/README.md +30 -0
- package/dist/index.d.ts +225 -3
- package/dist/index.js +111 -0
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -48,3 +48,33 @@ await client.customers.create({ name: "...", email: "..." });
|
|
|
48
48
|
```
|
|
49
49
|
|
|
50
50
|
O `mode` (dev/prod) é configurado uma única vez ao instanciar o cliente — nenhum método individual precisa recebê-lo novamente.
|
|
51
|
+
|
|
52
|
+
## Cobrança avulsa simples (sempre cartão)
|
|
53
|
+
|
|
54
|
+
`charges.charge` cobra direto no cartão padrão já salvo do cliente; se ele ainda não tiver um, retorna uma URL de checkout para cadastrar o cartão e pagar.
|
|
55
|
+
|
|
56
|
+
```ts
|
|
57
|
+
const result = await client.charges.charge(customerId, 5000); // R$ 50,00
|
|
58
|
+
|
|
59
|
+
if (!result.charged_off_session) {
|
|
60
|
+
// abra result.checkout_url em uma nova aba para o cliente cadastrar o cartão
|
|
61
|
+
}
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
## Assinatura de plano (checkout + confirmação + status)
|
|
65
|
+
|
|
66
|
+
```ts
|
|
67
|
+
const { checkout_url, checkout_token, management_token } = await client.plans.checkout(planId, {
|
|
68
|
+
customer: { name, email },
|
|
69
|
+
});
|
|
70
|
+
|
|
71
|
+
// redirecione o cliente para checkout_url, depois confirme o pagamento:
|
|
72
|
+
const status = await client.checkout.waitUntilPaid(checkout_token);
|
|
73
|
+
|
|
74
|
+
// guarde management_token — a qualquer momento depois, verifique se a assinatura
|
|
75
|
+
// segue ativa e qual item ela cobre (rota pública, sem autenticação):
|
|
76
|
+
const subStatus = await client.subscriptions.checkByToken(management_token);
|
|
77
|
+
if (subStatus.subscription.active) {
|
|
78
|
+
console.log("cobrando", subStatus.item.name);
|
|
79
|
+
}
|
|
80
|
+
```
|
package/dist/index.d.ts
CHANGED
|
@@ -76,6 +76,23 @@ interface Charge {
|
|
|
76
76
|
}
|
|
77
77
|
interface CreateChargeResult extends Charge {
|
|
78
78
|
}
|
|
79
|
+
interface QuickChargeInput {
|
|
80
|
+
customer_id: string;
|
|
81
|
+
/** Valor em centavos. */
|
|
82
|
+
amount: number;
|
|
83
|
+
currency?: string;
|
|
84
|
+
description?: string;
|
|
85
|
+
metadata?: Record<string, unknown>;
|
|
86
|
+
}
|
|
87
|
+
interface QuickChargeResult {
|
|
88
|
+
/** true quando o cartão salvo do cliente foi cobrado direto (sem fricção) — nesse
|
|
89
|
+
* caso `checkout_url` vem `null` e `charge.status` já reflete o resultado (PAID ou
|
|
90
|
+
* PROCESSING). false quando o cliente ainda não tem cartão salvo (ou o cartão salvo
|
|
91
|
+
* falhou) — abra `checkout_url` para ele cadastrar o cartão e completar o pagamento. */
|
|
92
|
+
charged_off_session: boolean;
|
|
93
|
+
checkout_url: string | null;
|
|
94
|
+
charge: Charge;
|
|
95
|
+
}
|
|
79
96
|
interface CustomerInput {
|
|
80
97
|
name: string;
|
|
81
98
|
email: string;
|
|
@@ -115,11 +132,18 @@ type BillingRecurringInterval = "WEEKLY" | "MONTHLY" | "QUARTERLY" | "YEARLY";
|
|
|
115
132
|
type BillingRecurringStatus = "ACTIVE" | "TRIALING" | "PAST_DUE" | "PAUSED" | "CANCELLED" | "EXPIRED";
|
|
116
133
|
type ProrationPolicy = "IMMEDIATE" | "AT_RENEWAL";
|
|
117
134
|
interface CreateBillingPlanInput {
|
|
118
|
-
|
|
135
|
+
/** Página de planos (BillingPlanPage) à qual este plano pertence. */
|
|
136
|
+
plan_page_id: string;
|
|
137
|
+
/** Item de catálogo (BillingItem) do qual nome/preço são copiados na criação. */
|
|
138
|
+
item_id: string;
|
|
139
|
+
name?: string;
|
|
119
140
|
description?: string;
|
|
120
|
-
amount
|
|
141
|
+
amount?: number;
|
|
121
142
|
currency?: string;
|
|
122
143
|
interval: BillingRecurringInterval;
|
|
144
|
+
/** Preço cobrado no ciclo anual (cents) — quando presente, habilita a opção de
|
|
145
|
+
* cobrança anual (`billing_period: "annual"`) no checkout público deste plano. */
|
|
146
|
+
annual_amount?: number;
|
|
123
147
|
features?: string[];
|
|
124
148
|
limits?: Record<string, string | number>;
|
|
125
149
|
return_url?: string;
|
|
@@ -128,11 +152,14 @@ interface CreateBillingPlanInput {
|
|
|
128
152
|
interface BillingPlanSummary {
|
|
129
153
|
id: string;
|
|
130
154
|
org_id: string;
|
|
155
|
+
plan_page_id: string;
|
|
156
|
+
item_id: string;
|
|
131
157
|
name: string;
|
|
132
158
|
description: string | null;
|
|
133
159
|
amount: number;
|
|
134
160
|
currency: string;
|
|
135
161
|
interval: BillingRecurringInterval;
|
|
162
|
+
annual_amount: number | null;
|
|
136
163
|
features: string[] | null;
|
|
137
164
|
limits: Record<string, string | number> | null;
|
|
138
165
|
active: boolean;
|
|
@@ -141,6 +168,81 @@ interface BillingPlanSummary {
|
|
|
141
168
|
created_at: string;
|
|
142
169
|
updated_at: string;
|
|
143
170
|
}
|
|
171
|
+
/** Plano como retornado pelas rotas públicas (`/public/orgs/:slug/billing-plans` e
|
|
172
|
+
* `/public/orgs/:slug/plan-pages/:pageSlug`) — subconjunto de campos, sem dados internos
|
|
173
|
+
* (org_id, stripe ids, etc), pensado para renderizar uma página de preços. */
|
|
174
|
+
interface PublicBillingPlan {
|
|
175
|
+
id: string;
|
|
176
|
+
name: string;
|
|
177
|
+
description: string | null;
|
|
178
|
+
amount: number;
|
|
179
|
+
currency: string;
|
|
180
|
+
interval: BillingRecurringInterval;
|
|
181
|
+
annual_amount: number | null;
|
|
182
|
+
features: string[] | null;
|
|
183
|
+
return_url: string | null;
|
|
184
|
+
}
|
|
185
|
+
interface PublicPlanBranding {
|
|
186
|
+
logo_url: string | null;
|
|
187
|
+
background_color: string | null;
|
|
188
|
+
card_background_color: string | null;
|
|
189
|
+
card_border_color: string | null;
|
|
190
|
+
accent_color: string | null;
|
|
191
|
+
headline: string | null;
|
|
192
|
+
subheadline: string | null;
|
|
193
|
+
cta_label: string | null;
|
|
194
|
+
}
|
|
195
|
+
interface PublicOrganization {
|
|
196
|
+
id: string;
|
|
197
|
+
name: string;
|
|
198
|
+
slug: string;
|
|
199
|
+
avatar_url: string | null;
|
|
200
|
+
}
|
|
201
|
+
interface ListPublicPlansResult {
|
|
202
|
+
organization: PublicOrganization;
|
|
203
|
+
branding: PublicPlanBranding;
|
|
204
|
+
plans: PublicBillingPlan[];
|
|
205
|
+
}
|
|
206
|
+
interface GetPublicPlanPageResult extends ListPublicPlansResult {
|
|
207
|
+
page: {
|
|
208
|
+
id: string;
|
|
209
|
+
slug: string;
|
|
210
|
+
title: string;
|
|
211
|
+
description: string | null;
|
|
212
|
+
};
|
|
213
|
+
}
|
|
214
|
+
type BillingPeriod = "monthly" | "annual";
|
|
215
|
+
interface PlanCheckoutCustomerInput {
|
|
216
|
+
name: string;
|
|
217
|
+
email: string;
|
|
218
|
+
tax_id?: string;
|
|
219
|
+
phone?: string;
|
|
220
|
+
}
|
|
221
|
+
interface PlanCheckoutInput {
|
|
222
|
+
customer: PlanCheckoutCustomerInput;
|
|
223
|
+
/** Para onde redirecionar o cliente após a confirmação do pagamento. */
|
|
224
|
+
return_url?: string;
|
|
225
|
+
/** Cobrar no ciclo mensal (padrão) ou anual — anual só é aceito se o plano tiver
|
|
226
|
+
* `annual_amount` configurado, senão a API retorna 422. */
|
|
227
|
+
billing_period?: BillingPeriod;
|
|
228
|
+
}
|
|
229
|
+
interface PlanCheckoutResult {
|
|
230
|
+
checkout_token: string;
|
|
231
|
+
/** URL hospedada da Geekapps para o cliente completar o pagamento — abra em uma nova
|
|
232
|
+
* aba/WebView ou redirecione o navegador do cliente para cá. */
|
|
233
|
+
checkout_url: string;
|
|
234
|
+
subscription_id: string;
|
|
235
|
+
/** Token permanente — guarde-o (associado ao seu usuário) para depois checar se a
|
|
236
|
+
* assinatura está ativa e qual item ela cobre via `subscriptions.checkByToken`. */
|
|
237
|
+
management_token: string;
|
|
238
|
+
}
|
|
239
|
+
type CheckoutSessionStatus = "PENDING" | "PROCESSING" | "PAID" | "FAILED" | "EXPIRED" | "REFUNDED" | "CANCELLED";
|
|
240
|
+
interface CheckoutStatusResult {
|
|
241
|
+
status: CheckoutSessionStatus;
|
|
242
|
+
paid_at: string | null;
|
|
243
|
+
provider_url: string | null;
|
|
244
|
+
return_url: string | null;
|
|
245
|
+
}
|
|
144
246
|
interface Subscription {
|
|
145
247
|
id: string;
|
|
146
248
|
org_id: string;
|
|
@@ -156,6 +258,43 @@ interface Subscription {
|
|
|
156
258
|
created_at: string;
|
|
157
259
|
updated_at: string;
|
|
158
260
|
}
|
|
261
|
+
/** Item que a assinatura cobre no momento — snapshot atual, atualizado a cada troca
|
|
262
|
+
* de plano (não referencia o item do plano original se ele já foi trocado). */
|
|
263
|
+
interface SubscriptionItemSummary {
|
|
264
|
+
id: string;
|
|
265
|
+
name: string;
|
|
266
|
+
amount: number;
|
|
267
|
+
currency: string;
|
|
268
|
+
}
|
|
269
|
+
interface SubscriptionPlanSummary {
|
|
270
|
+
id: string;
|
|
271
|
+
item_id: string;
|
|
272
|
+
name: string;
|
|
273
|
+
amount: number;
|
|
274
|
+
currency: string;
|
|
275
|
+
interval: BillingRecurringInterval;
|
|
276
|
+
}
|
|
277
|
+
/**
|
|
278
|
+
* Resultado de `subscriptions.checkByToken` / `GET /public/plan-management/:token` —
|
|
279
|
+
* pensado para responder exatamente "esta assinatura está ativa? de qual item?" sem
|
|
280
|
+
* exigir login nem credenciais de service account, tanto no seu backend quanto
|
|
281
|
+
* diretamente do client-side do seu app (o token não expõe nada sensível).
|
|
282
|
+
*/
|
|
283
|
+
interface SubscriptionStatusResult {
|
|
284
|
+
subscription: {
|
|
285
|
+
id: string;
|
|
286
|
+
status: BillingRecurringStatus;
|
|
287
|
+
/** true quando status é ACTIVE, TRIALING ou PAST_DUE — o atalho que a maioria dos
|
|
288
|
+
* apps quer pra decidir se libera acesso ou não. */
|
|
289
|
+
active: boolean;
|
|
290
|
+
cancel_at_period_end: boolean;
|
|
291
|
+
current_period_end: string | null;
|
|
292
|
+
};
|
|
293
|
+
/** Item que está sendo cobrado atualmente nesta assinatura. */
|
|
294
|
+
item: SubscriptionItemSummary;
|
|
295
|
+
plan: SubscriptionPlanSummary | null;
|
|
296
|
+
available_plans: SubscriptionPlanSummary[];
|
|
297
|
+
}
|
|
159
298
|
interface CreateOrderInput {
|
|
160
299
|
amount?: number;
|
|
161
300
|
currency?: string;
|
|
@@ -190,6 +329,20 @@ declare class ChargesResource {
|
|
|
190
329
|
* acompanhar até que estejam prontos.
|
|
191
330
|
*/
|
|
192
331
|
create(input: CreateChargeInput): Promise<CreateChargeResult>;
|
|
332
|
+
/**
|
|
333
|
+
* Cobrança avulsa simples, sempre em cartão — cobra direto no cartão padrão já
|
|
334
|
+
* salvo do cliente (sem fricção nenhuma). Se ele ainda não tiver um cartão salvo,
|
|
335
|
+
* retorna `checkout_url` para você abrir (ex: nova aba) e o cliente cadastrar o
|
|
336
|
+
* cartão e pagar.
|
|
337
|
+
*
|
|
338
|
+
* ```ts
|
|
339
|
+
* const result = await client.charges.charge(customerId, 5000); // R$ 50,00
|
|
340
|
+
* if (!result.charged_off_session) {
|
|
341
|
+
* window.open(result.checkout_url!, "_blank");
|
|
342
|
+
* }
|
|
343
|
+
* ```
|
|
344
|
+
*/
|
|
345
|
+
charge(customerId: string, amountCents: number, options?: Omit<QuickChargeInput, "customer_id" | "amount">): Promise<QuickChargeResult>;
|
|
193
346
|
get(id: string): Promise<Charge>;
|
|
194
347
|
getStatus(id: string): Promise<{
|
|
195
348
|
status: Charge["status"];
|
|
@@ -198,6 +351,30 @@ declare class ChargesResource {
|
|
|
198
351
|
refund(id: string): Promise<Charge>;
|
|
199
352
|
}
|
|
200
353
|
|
|
354
|
+
interface WaitUntilPaidOptions {
|
|
355
|
+
/** Intervalo entre tentativas, em ms. Default: 2000. */
|
|
356
|
+
intervalMs?: number;
|
|
357
|
+
/** Tempo máximo de espera antes de desistir, em ms. Default: 5 minutos. */
|
|
358
|
+
timeoutMs?: number;
|
|
359
|
+
}
|
|
360
|
+
declare class CheckoutResource {
|
|
361
|
+
private readonly http;
|
|
362
|
+
constructor(http: HttpClient);
|
|
363
|
+
/** Consulta o status atual de uma cobrança/checkout pelo `checkout_token` retornado
|
|
364
|
+
* por `plans.checkout()` (ou qualquer outro fluxo de cobrança do SDK). Sincroniza com
|
|
365
|
+
* o provedor de pagamento sob o capô quando ainda está PENDING. */
|
|
366
|
+
getStatus(checkoutToken: string): Promise<CheckoutStatusResult>;
|
|
367
|
+
/**
|
|
368
|
+
* Faz polling de `getStatus` até o pagamento ser confirmado (ou falhar/expirar) — é
|
|
369
|
+
* a forma recomendada de confirmar, depois de redirecionar o cliente para a
|
|
370
|
+
* `checkout_url`, que a assinatura realmente foi paga antes de liberar acesso.
|
|
371
|
+
*
|
|
372
|
+
* Resolve quando o status deixa de ser PENDING/PROCESSING. Lança um erro se o tempo
|
|
373
|
+
* limite (`timeoutMs`) for atingido antes disso.
|
|
374
|
+
*/
|
|
375
|
+
waitUntilPaid(checkoutToken: string, options?: WaitUntilPaidOptions): Promise<CheckoutStatusResult>;
|
|
376
|
+
}
|
|
377
|
+
|
|
201
378
|
declare class CustomersResource {
|
|
202
379
|
private readonly http;
|
|
203
380
|
constructor(http: HttpClient);
|
|
@@ -248,14 +425,58 @@ declare class PlansResource {
|
|
|
248
425
|
/** Não há hard-delete de planos (assinaturas existentes ainda referenciam) — para
|
|
249
426
|
* remover um plano do catálogo público, arquive-o. */
|
|
250
427
|
archive(id: string): Promise<BillingPlanSummary>;
|
|
428
|
+
/** Lista os planos ativos de uma org pelo slug público — página fixa legada, sem
|
|
429
|
+
* suporte a múltiplas páginas. Prefira `getPublicPage` para orgs com várias páginas. */
|
|
430
|
+
listPublic(orgSlug: string): Promise<ListPublicPlansResult>;
|
|
431
|
+
/** Busca uma página de planos pública específica pelo slug da org + slug da página. */
|
|
432
|
+
getPublicPage(orgSlug: string, pageSlug: string): Promise<GetPublicPlanPageResult>;
|
|
433
|
+
/**
|
|
434
|
+
* Inicia a assinatura de um plano para um cliente final: cria (ou reaproveita) o
|
|
435
|
+
* `Customer` pelo e-mail, cria a `Subscription` e retorna uma URL de checkout hospedada
|
|
436
|
+
* pela Geekapps para o cliente confirmar o pagamento.
|
|
437
|
+
*
|
|
438
|
+
* Fluxo típico:
|
|
439
|
+
* ```ts
|
|
440
|
+
* const { checkout_url, checkout_token } = await client.plans.checkout(planId, {
|
|
441
|
+
* customer: { name, email },
|
|
442
|
+
* });
|
|
443
|
+
* // redirecione o cliente (ou abra checkout_url em uma WebView/nova aba)
|
|
444
|
+
* window.location.href = checkout_url;
|
|
445
|
+
*
|
|
446
|
+
* // depois do retorno, confirme se realmente foi pago:
|
|
447
|
+
* const { status } = await client.checkout.waitUntilPaid(checkout_token);
|
|
448
|
+
* if (status === "PAID") { /* liberar acesso *\/ }
|
|
449
|
+
* ```
|
|
450
|
+
*
|
|
451
|
+
* Não requer autenticação — pode ser chamado a partir do backend do dev sem token de
|
|
452
|
+
* service account, ou do próprio SDK server-side usando qualquer token válido.
|
|
453
|
+
*/
|
|
454
|
+
checkout(planId: string, input: PlanCheckoutInput): Promise<PlanCheckoutResult>;
|
|
251
455
|
}
|
|
252
456
|
|
|
253
457
|
declare class SubscriptionsResource {
|
|
254
458
|
private readonly http;
|
|
255
459
|
constructor(http: HttpClient);
|
|
460
|
+
/** Requer autenticação (service account) — lista todas as assinaturas da sua org. */
|
|
256
461
|
list(): Promise<Subscription[]>;
|
|
462
|
+
/** Requer autenticação (service account). */
|
|
257
463
|
get(id: string): Promise<Subscription>;
|
|
464
|
+
/** Requer autenticação (service account). */
|
|
258
465
|
cancel(id: string): Promise<Subscription>;
|
|
466
|
+
/**
|
|
467
|
+
* Verifica se uma assinatura está ativa e qual item ela cobre, usando o
|
|
468
|
+
* `management_token` retornado por `plans.checkout()` — rota pública, sem
|
|
469
|
+
* autenticação, segura para chamar tanto do seu backend quanto (via fetch direto,
|
|
470
|
+
* sem o SDK) do client-side do seu app.
|
|
471
|
+
*
|
|
472
|
+
* ```ts
|
|
473
|
+
* const status = await client.subscriptions.checkByToken(managementToken);
|
|
474
|
+
* if (status.subscription.active) {
|
|
475
|
+
* console.log("cobrando", status.item.name);
|
|
476
|
+
* }
|
|
477
|
+
* ```
|
|
478
|
+
*/
|
|
479
|
+
checkByToken(managementToken: string): Promise<SubscriptionStatusResult>;
|
|
259
480
|
}
|
|
260
481
|
|
|
261
482
|
interface BillingClientOptions extends Omit<HttpClientOptions, "baseUrl"> {
|
|
@@ -264,6 +485,7 @@ interface BillingClientOptions extends Omit<HttpClientOptions, "baseUrl"> {
|
|
|
264
485
|
declare class BillingClient {
|
|
265
486
|
private readonly http;
|
|
266
487
|
readonly charges: ChargesResource;
|
|
488
|
+
readonly checkout: CheckoutResource;
|
|
267
489
|
readonly customers: CustomersResource;
|
|
268
490
|
readonly items: ItemsResource;
|
|
269
491
|
readonly orders: OrdersResource;
|
|
@@ -332,4 +554,4 @@ declare module "fastify" {
|
|
|
332
554
|
}
|
|
333
555
|
declare const _default: FastifyPluginAsync<BillingPluginOptions>;
|
|
334
556
|
|
|
335
|
-
export { BillingApiError, BillingClient, type BillingClientOptions, type BillingItem, type BillingPlanSummary, type BillingPluginOptions, type BillingRecurringInterval, type BillingRecurringStatus, type Charge, type ChargeStatus, ChargesResource, type CreateBillingPlanInput, type CreateChargeInput, type CreateChargeResult, type CreateOrderInput, type CreateOrderResult, type Customer, type CustomerInput, CustomersResource, HttpClient, type HttpClientOptions, type ItemInput, ItemsResource, OrdersResource, type PaymentMethod, PlansResource, type ProrationPolicy, type ServiceAccountOptions, ServiceAccountTokenProvider, type Subscription, SubscriptionsResource, type TokenResolver, _default as billingPlugin, createServiceAccountToken };
|
|
557
|
+
export { BillingApiError, BillingClient, type BillingClientOptions, type BillingItem, type BillingPeriod, type BillingPlanSummary, type BillingPluginOptions, type BillingRecurringInterval, type BillingRecurringStatus, type Charge, type ChargeStatus, ChargesResource, CheckoutResource, type CheckoutSessionStatus, type CheckoutStatusResult, type CreateBillingPlanInput, type CreateChargeInput, type CreateChargeResult, type CreateOrderInput, type CreateOrderResult, type Customer, type CustomerInput, CustomersResource, type GetPublicPlanPageResult, HttpClient, type HttpClientOptions, type ItemInput, ItemsResource, type ListPublicPlansResult, OrdersResource, type PaymentMethod, type PlanCheckoutCustomerInput, type PlanCheckoutInput, type PlanCheckoutResult, PlansResource, type ProrationPolicy, type PublicBillingPlan, type PublicOrganization, type PublicPlanBranding, type QuickChargeInput, type QuickChargeResult, type ServiceAccountOptions, ServiceAccountTokenProvider, type Subscription, type SubscriptionItemSummary, type SubscriptionPlanSummary, type SubscriptionStatusResult, SubscriptionsResource, type TokenResolver, type WaitUntilPaidOptions, _default as billingPlugin, createServiceAccountToken };
|
package/dist/index.js
CHANGED
|
@@ -220,6 +220,26 @@ var ChargesResource = class {
|
|
|
220
220
|
create(input) {
|
|
221
221
|
return this.http.post("/charges", input);
|
|
222
222
|
}
|
|
223
|
+
/**
|
|
224
|
+
* Cobrança avulsa simples, sempre em cartão — cobra direto no cartão padrão já
|
|
225
|
+
* salvo do cliente (sem fricção nenhuma). Se ele ainda não tiver um cartão salvo,
|
|
226
|
+
* retorna `checkout_url` para você abrir (ex: nova aba) e o cliente cadastrar o
|
|
227
|
+
* cartão e pagar.
|
|
228
|
+
*
|
|
229
|
+
* ```ts
|
|
230
|
+
* const result = await client.charges.charge(customerId, 5000); // R$ 50,00
|
|
231
|
+
* if (!result.charged_off_session) {
|
|
232
|
+
* window.open(result.checkout_url!, "_blank");
|
|
233
|
+
* }
|
|
234
|
+
* ```
|
|
235
|
+
*/
|
|
236
|
+
charge(customerId, amountCents, options) {
|
|
237
|
+
return this.http.post("/charges/quick", {
|
|
238
|
+
customer_id: customerId,
|
|
239
|
+
amount: amountCents,
|
|
240
|
+
...options
|
|
241
|
+
});
|
|
242
|
+
}
|
|
223
243
|
get(id) {
|
|
224
244
|
return this.http.get(`/charges/${id}`);
|
|
225
245
|
}
|
|
@@ -234,6 +254,42 @@ var ChargesResource = class {
|
|
|
234
254
|
}
|
|
235
255
|
};
|
|
236
256
|
|
|
257
|
+
// src/resources/checkout.ts
|
|
258
|
+
var CheckoutResource = class {
|
|
259
|
+
constructor(http) {
|
|
260
|
+
this.http = http;
|
|
261
|
+
}
|
|
262
|
+
/** Consulta o status atual de uma cobrança/checkout pelo `checkout_token` retornado
|
|
263
|
+
* por `plans.checkout()` (ou qualquer outro fluxo de cobrança do SDK). Sincroniza com
|
|
264
|
+
* o provedor de pagamento sob o capô quando ainda está PENDING. */
|
|
265
|
+
getStatus(checkoutToken) {
|
|
266
|
+
return this.http.get(`/checkout/${checkoutToken}/status`);
|
|
267
|
+
}
|
|
268
|
+
/**
|
|
269
|
+
* Faz polling de `getStatus` até o pagamento ser confirmado (ou falhar/expirar) — é
|
|
270
|
+
* a forma recomendada de confirmar, depois de redirecionar o cliente para a
|
|
271
|
+
* `checkout_url`, que a assinatura realmente foi paga antes de liberar acesso.
|
|
272
|
+
*
|
|
273
|
+
* Resolve quando o status deixa de ser PENDING/PROCESSING. Lança um erro se o tempo
|
|
274
|
+
* limite (`timeoutMs`) for atingido antes disso.
|
|
275
|
+
*/
|
|
276
|
+
async waitUntilPaid(checkoutToken, options = {}) {
|
|
277
|
+
const intervalMs = options.intervalMs ?? 2e3;
|
|
278
|
+
const timeoutMs = options.timeoutMs ?? 5 * 60 * 1e3;
|
|
279
|
+
const deadline = Date.now() + timeoutMs;
|
|
280
|
+
for (; ; ) {
|
|
281
|
+
const result = await this.getStatus(checkoutToken);
|
|
282
|
+
if (result.status !== "PENDING" && result.status !== "PROCESSING") {
|
|
283
|
+
return result;
|
|
284
|
+
}
|
|
285
|
+
if (Date.now() >= deadline) {
|
|
286
|
+
throw new Error(`Tempo limite excedido aguardando confirma\xE7\xE3o de pagamento (checkout_token=${checkoutToken}).`);
|
|
287
|
+
}
|
|
288
|
+
await new Promise((resolve) => setTimeout(resolve, intervalMs));
|
|
289
|
+
}
|
|
290
|
+
}
|
|
291
|
+
};
|
|
292
|
+
|
|
237
293
|
// src/resources/customers.ts
|
|
238
294
|
var CustomersResource = class {
|
|
239
295
|
constructor(http) {
|
|
@@ -316,6 +372,40 @@ var PlansResource = class {
|
|
|
316
372
|
archive(id) {
|
|
317
373
|
return this.http.patch(`/billing-plans/${id}`, { active: false });
|
|
318
374
|
}
|
|
375
|
+
// ─── Rotas públicas (sem auth — usadas para montar sua própria página de preços) ──
|
|
376
|
+
/** Lista os planos ativos de uma org pelo slug público — página fixa legada, sem
|
|
377
|
+
* suporte a múltiplas páginas. Prefira `getPublicPage` para orgs com várias páginas. */
|
|
378
|
+
listPublic(orgSlug) {
|
|
379
|
+
return this.http.get(`/public/orgs/${orgSlug}/billing-plans`);
|
|
380
|
+
}
|
|
381
|
+
/** Busca uma página de planos pública específica pelo slug da org + slug da página. */
|
|
382
|
+
getPublicPage(orgSlug, pageSlug) {
|
|
383
|
+
return this.http.get(`/public/orgs/${orgSlug}/plan-pages/${pageSlug}`);
|
|
384
|
+
}
|
|
385
|
+
/**
|
|
386
|
+
* Inicia a assinatura de um plano para um cliente final: cria (ou reaproveita) o
|
|
387
|
+
* `Customer` pelo e-mail, cria a `Subscription` e retorna uma URL de checkout hospedada
|
|
388
|
+
* pela Geekapps para o cliente confirmar o pagamento.
|
|
389
|
+
*
|
|
390
|
+
* Fluxo típico:
|
|
391
|
+
* ```ts
|
|
392
|
+
* const { checkout_url, checkout_token } = await client.plans.checkout(planId, {
|
|
393
|
+
* customer: { name, email },
|
|
394
|
+
* });
|
|
395
|
+
* // redirecione o cliente (ou abra checkout_url em uma WebView/nova aba)
|
|
396
|
+
* window.location.href = checkout_url;
|
|
397
|
+
*
|
|
398
|
+
* // depois do retorno, confirme se realmente foi pago:
|
|
399
|
+
* const { status } = await client.checkout.waitUntilPaid(checkout_token);
|
|
400
|
+
* if (status === "PAID") { /* liberar acesso *\/ }
|
|
401
|
+
* ```
|
|
402
|
+
*
|
|
403
|
+
* Não requer autenticação — pode ser chamado a partir do backend do dev sem token de
|
|
404
|
+
* service account, ou do próprio SDK server-side usando qualquer token válido.
|
|
405
|
+
*/
|
|
406
|
+
checkout(planId, input) {
|
|
407
|
+
return this.http.post(`/public/billing-plans/${planId}/checkout`, input);
|
|
408
|
+
}
|
|
319
409
|
};
|
|
320
410
|
|
|
321
411
|
// src/resources/subscriptions.ts
|
|
@@ -323,15 +413,34 @@ var SubscriptionsResource = class {
|
|
|
323
413
|
constructor(http) {
|
|
324
414
|
this.http = http;
|
|
325
415
|
}
|
|
416
|
+
/** Requer autenticação (service account) — lista todas as assinaturas da sua org. */
|
|
326
417
|
list() {
|
|
327
418
|
return this.http.get("/billing-subscriptions");
|
|
328
419
|
}
|
|
420
|
+
/** Requer autenticação (service account). */
|
|
329
421
|
get(id) {
|
|
330
422
|
return this.http.get(`/billing-subscriptions/${id}`);
|
|
331
423
|
}
|
|
424
|
+
/** Requer autenticação (service account). */
|
|
332
425
|
cancel(id) {
|
|
333
426
|
return this.http.patch(`/billing-subscriptions/${id}/cancel`);
|
|
334
427
|
}
|
|
428
|
+
/**
|
|
429
|
+
* Verifica se uma assinatura está ativa e qual item ela cobre, usando o
|
|
430
|
+
* `management_token` retornado por `plans.checkout()` — rota pública, sem
|
|
431
|
+
* autenticação, segura para chamar tanto do seu backend quanto (via fetch direto,
|
|
432
|
+
* sem o SDK) do client-side do seu app.
|
|
433
|
+
*
|
|
434
|
+
* ```ts
|
|
435
|
+
* const status = await client.subscriptions.checkByToken(managementToken);
|
|
436
|
+
* if (status.subscription.active) {
|
|
437
|
+
* console.log("cobrando", status.item.name);
|
|
438
|
+
* }
|
|
439
|
+
* ```
|
|
440
|
+
*/
|
|
441
|
+
checkByToken(managementToken) {
|
|
442
|
+
return this.http.get(`/public/plan-management/${managementToken}`);
|
|
443
|
+
}
|
|
335
444
|
};
|
|
336
445
|
|
|
337
446
|
// src/client.ts
|
|
@@ -339,6 +448,7 @@ var BillingClient = class {
|
|
|
339
448
|
constructor(options) {
|
|
340
449
|
this.http = new HttpClient(options);
|
|
341
450
|
this.charges = new ChargesResource(this.http);
|
|
451
|
+
this.checkout = new CheckoutResource(this.http);
|
|
342
452
|
this.customers = new CustomersResource(this.http);
|
|
343
453
|
this.items = new ItemsResource(this.http);
|
|
344
454
|
this.orders = new OrdersResource(this.http);
|
|
@@ -444,6 +554,7 @@ export {
|
|
|
444
554
|
BillingApiError,
|
|
445
555
|
BillingClient,
|
|
446
556
|
ChargesResource,
|
|
557
|
+
CheckoutResource,
|
|
447
558
|
CustomersResource,
|
|
448
559
|
HttpClient,
|
|
449
560
|
ItemsResource,
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../node_modules/.bun/fastify-plugin@6.0.0/node_modules/fastify-plugin/lib/getPluginName.js","../../../node_modules/.bun/fastify-plugin@6.0.0/node_modules/fastify-plugin/lib/toCamelCase.js","../../../node_modules/.bun/fastify-plugin@6.0.0/node_modules/fastify-plugin/index.js","../src/errors.ts","../src/http.ts","../src/resources/charges.ts","../src/resources/customers.ts","../src/resources/items.ts","../src/resources/orders.ts","../src/resources/plans.ts","../src/resources/subscriptions.ts","../src/client.ts","../src/plugin.ts","../src/service-account.ts"],"sourcesContent":["'use strict'\n\nconst fpStackTracePattern = /at\\s(?:.*\\.)?plugin\\s.*\\n\\s*(.*)/\nconst fileNamePattern = /(\\w*(\\.\\w*)*)\\..*/\n\nmodule.exports = function getPluginName (fn) {\n if (fn.name.length > 0) return fn.name\n\n const stackTraceLimit = Error.stackTraceLimit\n Error.stackTraceLimit = 10\n try {\n throw new Error('anonymous function')\n } catch (e) {\n Error.stackTraceLimit = stackTraceLimit\n return extractPluginName(e.stack)\n }\n}\n\nfunction extractPluginName (stack) {\n const m = stack.match(fpStackTracePattern)\n\n // get last section of path and match for filename\n return m ? m[1].split(/[/\\\\]/).slice(-1)[0].match(fileNamePattern)[1] : 'anonymous'\n}\nmodule.exports.extractPluginName = extractPluginName\n","'use strict'\n\nmodule.exports = function toCamelCase (name) {\n if (name[0] === '@') {\n name = name.slice(1).replace('/', '-')\n }\n return name.replace(/-(.)/g, function (match, g1) {\n return g1.toUpperCase()\n })\n}\n","'use strict'\n\nconst getPluginName = require('./lib/getPluginName')\nconst toCamelCase = require('./lib/toCamelCase')\n\nlet count = 0\n\nfunction plugin (fn, options = {}) {\n let autoName = false\n\n if (fn.default !== undefined) {\n // Support for 'export default' behaviour in transpiled ECMAScript module\n fn = fn.default\n }\n\n if (typeof fn !== 'function') {\n throw new TypeError(\n `fastify-plugin expects a function, instead got a '${typeof fn}'`\n )\n }\n\n if (typeof options === 'string') {\n options = {\n fastify: options\n }\n }\n\n if (\n typeof options !== 'object' ||\n Array.isArray(options) ||\n options === null\n ) {\n throw new TypeError('The options object should be an object')\n }\n\n if (options.fastify !== undefined && typeof options.fastify !== 'string') {\n throw new TypeError(`fastify-plugin expects a version string, instead got '${typeof options.fastify}'`)\n }\n\n if (!options.name) {\n autoName = true\n options.name = getPluginName(fn) + '-auto-' + count++\n }\n\n fn[Symbol.for('skip-override')] = options.encapsulate !== true\n fn[Symbol.for('fastify.display-name')] = options.name\n fn[Symbol.for('plugin-meta')] = options\n\n // Faux modules support\n if (!fn.default) {\n fn.default = fn\n }\n\n // TypeScript support for named imports\n // See https://github.com/fastify/fastify/issues/2404 for more details\n // The type definitions would have to be update to match this.\n const camelCase = toCamelCase(options.name)\n if (!autoName && !fn[camelCase]) {\n fn[camelCase] = fn\n }\n\n return fn\n}\n\nmodule.exports = plugin\nmodule.exports.default = plugin\nmodule.exports.fastifyPlugin = plugin\n","export class BillingApiError extends Error {\n constructor(\n public readonly status: number,\n message: string,\n public readonly detail?: string,\n ) {\n super(detail ? `${message}: ${detail}` : message);\n this.name = \"BillingApiError\";\n }\n\n get isNotFound() {\n return this.status === 404;\n }\n\n get isUnauthorized() {\n return this.status === 401;\n }\n\n get isForbidden() {\n return this.status === 403;\n }\n\n get isRateLimited() {\n return this.status === 429;\n }\n\n get isValidationError() {\n return this.status === 400 || this.status === 422;\n }\n}\n","import { BillingApiError } from \"./errors.js\";\n\nexport type TokenResolver = string | (() => string | Promise<string>);\n\nexport interface HttpClientOptions {\n baseUrl: string;\n token: TokenResolver;\n organizationId?: string | (() => string | Promise<string>);\n /**\n * Ambiente de billing (dev/prod) — enviado via header x-billing-mode em toda chamada\n * feita por esta instância. Defina uma vez aqui; os métodos individuais (charges.create,\n * customers.list, etc) nunca precisam recebê-lo de novo. Default: \"prod\".\n */\n mode?: string | (() => string | Promise<string>);\n}\n\nconst DEFAULT_MODE = \"prod\";\n\nexport class HttpClient {\n private readonly baseUrl: string;\n private readonly token: TokenResolver;\n private readonly organizationId?: string | (() => string | Promise<string>);\n private readonly mode: string | (() => string | Promise<string>);\n\n constructor(options: HttpClientOptions) {\n this.baseUrl = options.baseUrl.replace(/\\/$/, \"\");\n this.token = options.token;\n this.organizationId = options.organizationId;\n this.mode = options.mode ?? DEFAULT_MODE;\n }\n\n private async resolveToken(): Promise<string> {\n return typeof this.token === \"function\" ? await this.token() : this.token;\n }\n\n private async resolveOrgId(): Promise<string | undefined> {\n if (!this.organizationId) return undefined;\n return typeof this.organizationId === \"function\"\n ? await this.organizationId()\n : this.organizationId;\n }\n\n private async resolveMode(): Promise<string> {\n return typeof this.mode === \"function\" ? await this.mode() : this.mode;\n }\n\n async request<T = unknown>(\n method: string,\n path: string,\n body?: unknown,\n ): Promise<T> {\n const token = await this.resolveToken();\n const orgId = await this.resolveOrgId();\n const mode = await this.resolveMode();\n\n const res = await fetch(`${this.baseUrl}${path}`, {\n method,\n headers: {\n Authorization: `Bearer ${token}`,\n ...(body !== undefined ? { \"Content-Type\": \"application/json\" } : {}),\n ...(orgId ? { \"x-org-id\": orgId } : {}),\n \"x-billing-mode\": mode,\n },\n ...(body !== undefined ? { body: JSON.stringify(body) } : {}),\n });\n\n if (!res.ok) {\n const err = await res.json().catch(() => ({})) as {\n error?: string;\n message?: string;\n };\n throw new BillingApiError(\n res.status,\n err.error ?? err.message ?? `HTTP ${res.status}`,\n );\n }\n\n if (res.status === 202 || res.status === 204) {\n if (res.status === 204) return undefined as T;\n return res.json().catch(() => undefined) as Promise<T>;\n }\n return res.json() as Promise<T>;\n }\n\n get<T>(path: string) {\n return this.request<T>(\"GET\", path);\n }\n\n post<T>(path: string, body?: unknown) {\n return this.request<T>(\"POST\", path, body);\n }\n\n put<T>(path: string, body?: unknown) {\n return this.request<T>(\"PUT\", path, body);\n }\n\n patch<T>(path: string, body?: unknown) {\n return this.request<T>(\"PATCH\", path, body);\n }\n\n delete<T = void>(path: string) {\n return this.request<T>(\"DELETE\", path);\n }\n}\n","import type { HttpClient } from \"../http.js\";\nimport type { Charge, CreateChargeInput, CreateChargeResult } from \"../types.js\";\n\nexport class ChargesResource {\n constructor(private readonly http: HttpClient) {}\n\n list(params?: { installment_group_id?: string }): Promise<Charge[]> {\n const qs = params?.installment_group_id\n ? `?installment_group_id=${encodeURIComponent(params.installment_group_id)}`\n : \"\";\n return this.http.get<Charge[]>(`/charges${qs}`);\n }\n\n /**\n * Cria uma cobrança (PIX, boleto ou cartão). A geração de fato acontece de forma\n * assíncrona no backend — a resposta volta com a charge em PENDING, sem os campos\n * do método (QR code, boleto, etc) ainda preenchidos. Use `get`/`getStatus` para\n * acompanhar até que estejam prontos.\n */\n create(input: CreateChargeInput): Promise<CreateChargeResult> {\n return this.http.post<CreateChargeResult>(\"/charges\", input);\n }\n\n get(id: string): Promise<Charge> {\n return this.http.get<Charge>(`/charges/${id}`);\n }\n\n getStatus(id: string): Promise<{ status: Charge[\"status\"] }> {\n return this.http.get(`/charges/${id}/status`);\n }\n\n cancel(id: string): Promise<Charge> {\n return this.http.patch<Charge>(`/charges/${id}/cancel`);\n }\n\n refund(id: string): Promise<Charge> {\n return this.http.post<Charge>(`/charges/${id}/refund`);\n }\n}\n","import type { HttpClient } from \"../http.js\";\nimport type { Customer, CustomerInput } from \"../types.js\";\n\nexport class CustomersResource {\n constructor(private readonly http: HttpClient) {}\n\n list(): Promise<Customer[]> {\n return this.http.get<Customer[]>(\"/customers\");\n }\n\n create(input: CustomerInput): Promise<Customer> {\n return this.http.post<Customer>(\"/customers\", input);\n }\n\n get(id: string): Promise<Customer> {\n return this.http.get<Customer>(`/customers/${id}`);\n }\n\n update(id: string, input: Partial<CustomerInput>): Promise<Customer> {\n return this.http.patch<Customer>(`/customers/${id}`, input);\n }\n}\n","import type { HttpClient } from \"../http.js\";\nimport type { BillingItem } from \"../types.js\";\n\nexport interface ItemInput {\n name: string;\n description?: string;\n amount: number;\n currency?: string;\n}\n\nexport class ItemsResource {\n constructor(private readonly http: HttpClient) {}\n\n list(): Promise<BillingItem[]> {\n return this.http.get<BillingItem[]>(\"/items\");\n }\n\n create(input: ItemInput): Promise<BillingItem> {\n return this.http.post<BillingItem>(\"/items\", input);\n }\n\n get(id: string): Promise<BillingItem> {\n return this.http.get<BillingItem>(`/items/${id}`);\n }\n\n update(id: string, input: Partial<ItemInput>): Promise<BillingItem> {\n return this.http.patch<BillingItem>(`/items/${id}`, input);\n }\n}\n","import type { HttpClient } from \"../http.js\";\nimport type { CreateOrderInput, CreateOrderResult } from \"../types.js\";\n\nexport class OrdersResource {\n constructor(private readonly http: HttpClient) {}\n\n /**\n * Cria um pedido parcelado (parcelamento real via cobranças avulsas agendadas,\n * não assinatura). Retorna o `client_secret` da 1ª parcela para o front-end\n * confirmar via Stripe Elements — as parcelas seguintes são cobradas\n * automaticamente pelo backend no cartão salvo.\n */\n create(input: CreateOrderInput): Promise<CreateOrderResult> {\n return this.http.post<CreateOrderResult>(\"/orders\", input);\n }\n\n list(): Promise<unknown[]> {\n return this.http.get(\"/orders\");\n }\n\n get(id: string): Promise<unknown> {\n return this.http.get(`/orders/${id}`);\n }\n}\n","import type { HttpClient } from \"../http.js\";\nimport type { BillingPlanSummary, CreateBillingPlanInput } from \"../types.js\";\n\nexport class PlansResource {\n constructor(private readonly http: HttpClient) {}\n\n list(): Promise<BillingPlanSummary[]> {\n return this.http.get<BillingPlanSummary[]>(\"/billing-plans\");\n }\n\n get(id: string): Promise<BillingPlanSummary> {\n return this.http.get<BillingPlanSummary>(`/billing-plans/${id}`);\n }\n\n create(input: CreateBillingPlanInput): Promise<BillingPlanSummary> {\n return this.http.post<BillingPlanSummary>(\"/billing-plans\", input);\n }\n\n update(id: string, input: Partial<CreateBillingPlanInput> & { active?: boolean }): Promise<BillingPlanSummary> {\n return this.http.patch<BillingPlanSummary>(`/billing-plans/${id}`, input);\n }\n\n /** Não há hard-delete de planos (assinaturas existentes ainda referenciam) — para\n * remover um plano do catálogo público, arquive-o. */\n archive(id: string): Promise<BillingPlanSummary> {\n return this.http.patch<BillingPlanSummary>(`/billing-plans/${id}`, { active: false });\n }\n}\n","import type { HttpClient } from \"../http.js\";\nimport type { Subscription } from \"../types.js\";\n\nexport class SubscriptionsResource {\n constructor(private readonly http: HttpClient) {}\n\n list(): Promise<Subscription[]> {\n return this.http.get<Subscription[]>(\"/billing-subscriptions\");\n }\n\n get(id: string): Promise<Subscription> {\n return this.http.get<Subscription>(`/billing-subscriptions/${id}`);\n }\n\n cancel(id: string): Promise<Subscription> {\n return this.http.patch<Subscription>(`/billing-subscriptions/${id}/cancel`);\n }\n}\n","import { HttpClient, type HttpClientOptions } from \"./http.js\";\nimport { ChargesResource } from \"./resources/charges.js\";\nimport { CustomersResource } from \"./resources/customers.js\";\nimport { ItemsResource } from \"./resources/items.js\";\nimport { OrdersResource } from \"./resources/orders.js\";\nimport { PlansResource } from \"./resources/plans.js\";\nimport { SubscriptionsResource } from \"./resources/subscriptions.js\";\n\nexport interface BillingClientOptions\n extends Omit<HttpClientOptions, \"baseUrl\"> {\n baseUrl?: string;\n}\n\nexport class BillingClient {\n private readonly http: HttpClient;\n\n readonly charges: ChargesResource;\n readonly customers: CustomersResource;\n readonly items: ItemsResource;\n readonly orders: OrdersResource;\n readonly plans: PlansResource;\n readonly subscriptions: SubscriptionsResource;\n\n constructor(options: HttpClientOptions) {\n this.http = new HttpClient(options);\n\n this.charges = new ChargesResource(this.http);\n this.customers = new CustomersResource(this.http);\n this.items = new ItemsResource(this.http);\n this.orders = new OrdersResource(this.http);\n this.plans = new PlansResource(this.http);\n this.subscriptions = new SubscriptionsResource(this.http);\n }\n}\n","import type { FastifyInstance, FastifyPluginAsync } from \"fastify\";\nimport fp from \"fastify-plugin\";\nimport { BillingClient } from \"./client.js\";\nimport { ServiceAccountTokenProvider, type ServiceAccountOptions } from \"./service-account.js\";\n\nexport interface BillingPluginOptions {\n /** Geekapps Billing API base URL */\n baseUrl: string;\n /** Service account credentials — required */\n serviceAccount: ServiceAccountOptions;\n /** Ambiente de billing (dev/prod). Default: \"prod\". */\n mode?: string;\n}\n\ndeclare module \"fastify\" {\n interface FastifyInstance {\n billingClient: BillingClient;\n }\n}\n\nconst billingPlugin: FastifyPluginAsync<BillingPluginOptions> = async (\n fastify: FastifyInstance,\n options: BillingPluginOptions,\n) => {\n const tokenProvider = new ServiceAccountTokenProvider(options.serviceAccount);\n\n const client = new BillingClient({\n baseUrl: options.baseUrl,\n token: () => tokenProvider.getToken(),\n organizationId: () => tokenProvider.getOrganizationId() as Promise<string>,\n mode: options.mode,\n });\n\n fastify.decorate(\"billingClient\", client);\n};\n\nexport default fp(billingPlugin, {\n fastify: \">=4.0.0\",\n name: \"@geekapps/billing-fastify\",\n});\n","import type { TokenResolver } from \"./http.js\";\n\nexport interface ServiceAccountOptions {\n /** Geekapps Auth issuer base URL (e.g. https://accounts-api.geekapps.com.br) */\n issuerUrl: string;\n clientId: string;\n clientSecret: string;\n /** Seconds before expiry to proactively refresh. Defaults to 30. */\n refreshBeforeExpirySeconds?: number;\n}\n\ninterface CachedToken {\n value: string;\n expiresAt: number; // ms epoch\n organizationId: string | undefined;\n}\n\nfunction decodeJwtPayload(token: string): Record<string, unknown> {\n try {\n const [, payload] = token.split(\".\");\n if (!payload) return {};\n const json = Buffer.from(payload, \"base64url\").toString(\"utf-8\");\n return JSON.parse(json) as Record<string, unknown>;\n } catch {\n return {};\n }\n}\n\n/**\n * Fetches a short-lived token from the Geekapps Auth service using\n * client_credentials grant and caches it until near expiry.\n *\n * The organizationId claim is extracted automatically from the JWT payload.\n */\nexport class ServiceAccountTokenProvider {\n private readonly issuerUrl: string;\n private readonly clientId: string;\n private readonly clientSecret: string;\n private readonly refreshBeforeMs: number;\n private cached: CachedToken | null = null;\n private inflight: Promise<CachedToken> | null = null;\n\n constructor(options: ServiceAccountOptions) {\n this.issuerUrl = options.issuerUrl.replace(/\\/$/, \"\");\n this.clientId = options.clientId;\n this.clientSecret = options.clientSecret;\n this.refreshBeforeMs = (options.refreshBeforeExpirySeconds ?? 30) * 1000;\n }\n\n private async ensureFresh(): Promise<CachedToken> {\n const now = Date.now();\n\n if (this.cached && this.cached.expiresAt - now > this.refreshBeforeMs) {\n return this.cached;\n }\n\n if (this.inflight) return this.inflight;\n\n this.inflight = this.fetchToken().finally(() => {\n this.inflight = null;\n });\n\n return this.inflight;\n }\n\n /** Returns a valid access token. */\n getToken(): Promise<string> {\n return this.ensureFresh().then((c) => c.value);\n }\n\n /** Returns the organizationId embedded in the service account JWT. */\n getOrganizationId(): Promise<string | undefined> {\n return this.ensureFresh().then((c) => c.organizationId);\n }\n\n private async fetchToken(): Promise<CachedToken> {\n const credentials = Buffer.from(`${this.clientId}:${this.clientSecret}`).toString(\"base64\");\n\n const res = await fetch(`${this.issuerUrl}/auth/token`, {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n Authorization: `Basic ${credentials}`,\n },\n body: JSON.stringify({ grant_type: \"service_account\" }),\n });\n\n if (!res.ok) {\n const err = await res.json().catch(() => ({})) as { error?: string };\n throw new Error(\n `ServiceAccount token fetch failed (${res.status}): ${err.error ?? \"unknown error\"}`,\n );\n }\n\n const data = await res.json() as { access_token: string; expires_in?: number };\n\n const claims = decodeJwtPayload(data.access_token);\n const organizationId =\n typeof claims.organizationId === \"string\" ? claims.organizationId :\n typeof claims.organization_id === \"string\" ? claims.organization_id :\n undefined;\n\n const expiresInMs = (data.expires_in ?? 420) * 1000;\n this.cached = {\n value: data.access_token,\n expiresAt: Date.now() + expiresInMs,\n organizationId,\n };\n\n return this.cached;\n }\n\n /** Returns this provider as a TokenResolver to pass directly to BillingClient. */\n asTokenResolver(): TokenResolver {\n return () => this.getToken();\n }\n}\n\n/** Convenience factory. Returns a TokenResolver ready for use in BillingClient. */\nexport function createServiceAccountToken(\n options: ServiceAccountOptions,\n): TokenResolver {\n return new ServiceAccountTokenProvider(options).asTokenResolver();\n}\n"],"mappings":"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","names":["fp"]}
|
|
1
|
+
{"version":3,"sources":["../../../node_modules/.bun/fastify-plugin@6.0.0/node_modules/fastify-plugin/lib/getPluginName.js","../../../node_modules/.bun/fastify-plugin@6.0.0/node_modules/fastify-plugin/lib/toCamelCase.js","../../../node_modules/.bun/fastify-plugin@6.0.0/node_modules/fastify-plugin/index.js","../src/errors.ts","../src/http.ts","../src/resources/charges.ts","../src/resources/checkout.ts","../src/resources/customers.ts","../src/resources/items.ts","../src/resources/orders.ts","../src/resources/plans.ts","../src/resources/subscriptions.ts","../src/client.ts","../src/plugin.ts","../src/service-account.ts"],"sourcesContent":["'use strict'\n\nconst fpStackTracePattern = /at\\s(?:.*\\.)?plugin\\s.*\\n\\s*(.*)/\nconst fileNamePattern = /(\\w*(\\.\\w*)*)\\..*/\n\nmodule.exports = function getPluginName (fn) {\n if (fn.name.length > 0) return fn.name\n\n const stackTraceLimit = Error.stackTraceLimit\n Error.stackTraceLimit = 10\n try {\n throw new Error('anonymous function')\n } catch (e) {\n Error.stackTraceLimit = stackTraceLimit\n return extractPluginName(e.stack)\n }\n}\n\nfunction extractPluginName (stack) {\n const m = stack.match(fpStackTracePattern)\n\n // get last section of path and match for filename\n return m ? m[1].split(/[/\\\\]/).slice(-1)[0].match(fileNamePattern)[1] : 'anonymous'\n}\nmodule.exports.extractPluginName = extractPluginName\n","'use strict'\n\nmodule.exports = function toCamelCase (name) {\n if (name[0] === '@') {\n name = name.slice(1).replace('/', '-')\n }\n return name.replace(/-(.)/g, function (match, g1) {\n return g1.toUpperCase()\n })\n}\n","'use strict'\n\nconst getPluginName = require('./lib/getPluginName')\nconst toCamelCase = require('./lib/toCamelCase')\n\nlet count = 0\n\nfunction plugin (fn, options = {}) {\n let autoName = false\n\n if (fn.default !== undefined) {\n // Support for 'export default' behaviour in transpiled ECMAScript module\n fn = fn.default\n }\n\n if (typeof fn !== 'function') {\n throw new TypeError(\n `fastify-plugin expects a function, instead got a '${typeof fn}'`\n )\n }\n\n if (typeof options === 'string') {\n options = {\n fastify: options\n }\n }\n\n if (\n typeof options !== 'object' ||\n Array.isArray(options) ||\n options === null\n ) {\n throw new TypeError('The options object should be an object')\n }\n\n if (options.fastify !== undefined && typeof options.fastify !== 'string') {\n throw new TypeError(`fastify-plugin expects a version string, instead got '${typeof options.fastify}'`)\n }\n\n if (!options.name) {\n autoName = true\n options.name = getPluginName(fn) + '-auto-' + count++\n }\n\n fn[Symbol.for('skip-override')] = options.encapsulate !== true\n fn[Symbol.for('fastify.display-name')] = options.name\n fn[Symbol.for('plugin-meta')] = options\n\n // Faux modules support\n if (!fn.default) {\n fn.default = fn\n }\n\n // TypeScript support for named imports\n // See https://github.com/fastify/fastify/issues/2404 for more details\n // The type definitions would have to be update to match this.\n const camelCase = toCamelCase(options.name)\n if (!autoName && !fn[camelCase]) {\n fn[camelCase] = fn\n }\n\n return fn\n}\n\nmodule.exports = plugin\nmodule.exports.default = plugin\nmodule.exports.fastifyPlugin = plugin\n","export class BillingApiError extends Error {\n constructor(\n public readonly status: number,\n message: string,\n public readonly detail?: string,\n ) {\n super(detail ? `${message}: ${detail}` : message);\n this.name = \"BillingApiError\";\n }\n\n get isNotFound() {\n return this.status === 404;\n }\n\n get isUnauthorized() {\n return this.status === 401;\n }\n\n get isForbidden() {\n return this.status === 403;\n }\n\n get isRateLimited() {\n return this.status === 429;\n }\n\n get isValidationError() {\n return this.status === 400 || this.status === 422;\n }\n}\n","import { BillingApiError } from \"./errors.js\";\n\nexport type TokenResolver = string | (() => string | Promise<string>);\n\nexport interface HttpClientOptions {\n baseUrl: string;\n token: TokenResolver;\n organizationId?: string | (() => string | Promise<string>);\n /**\n * Ambiente de billing (dev/prod) — enviado via header x-billing-mode em toda chamada\n * feita por esta instância. Defina uma vez aqui; os métodos individuais (charges.create,\n * customers.list, etc) nunca precisam recebê-lo de novo. Default: \"prod\".\n */\n mode?: string | (() => string | Promise<string>);\n}\n\nconst DEFAULT_MODE = \"prod\";\n\nexport class HttpClient {\n private readonly baseUrl: string;\n private readonly token: TokenResolver;\n private readonly organizationId?: string | (() => string | Promise<string>);\n private readonly mode: string | (() => string | Promise<string>);\n\n constructor(options: HttpClientOptions) {\n this.baseUrl = options.baseUrl.replace(/\\/$/, \"\");\n this.token = options.token;\n this.organizationId = options.organizationId;\n this.mode = options.mode ?? DEFAULT_MODE;\n }\n\n private async resolveToken(): Promise<string> {\n return typeof this.token === \"function\" ? await this.token() : this.token;\n }\n\n private async resolveOrgId(): Promise<string | undefined> {\n if (!this.organizationId) return undefined;\n return typeof this.organizationId === \"function\"\n ? await this.organizationId()\n : this.organizationId;\n }\n\n private async resolveMode(): Promise<string> {\n return typeof this.mode === \"function\" ? await this.mode() : this.mode;\n }\n\n async request<T = unknown>(\n method: string,\n path: string,\n body?: unknown,\n ): Promise<T> {\n const token = await this.resolveToken();\n const orgId = await this.resolveOrgId();\n const mode = await this.resolveMode();\n\n const res = await fetch(`${this.baseUrl}${path}`, {\n method,\n headers: {\n Authorization: `Bearer ${token}`,\n ...(body !== undefined ? { \"Content-Type\": \"application/json\" } : {}),\n ...(orgId ? { \"x-org-id\": orgId } : {}),\n \"x-billing-mode\": mode,\n },\n ...(body !== undefined ? { body: JSON.stringify(body) } : {}),\n });\n\n if (!res.ok) {\n const err = await res.json().catch(() => ({})) as {\n error?: string;\n message?: string;\n };\n throw new BillingApiError(\n res.status,\n err.error ?? err.message ?? `HTTP ${res.status}`,\n );\n }\n\n if (res.status === 202 || res.status === 204) {\n if (res.status === 204) return undefined as T;\n return res.json().catch(() => undefined) as Promise<T>;\n }\n return res.json() as Promise<T>;\n }\n\n get<T>(path: string) {\n return this.request<T>(\"GET\", path);\n }\n\n post<T>(path: string, body?: unknown) {\n return this.request<T>(\"POST\", path, body);\n }\n\n put<T>(path: string, body?: unknown) {\n return this.request<T>(\"PUT\", path, body);\n }\n\n patch<T>(path: string, body?: unknown) {\n return this.request<T>(\"PATCH\", path, body);\n }\n\n delete<T = void>(path: string) {\n return this.request<T>(\"DELETE\", path);\n }\n}\n","import type { HttpClient } from \"../http.js\";\nimport type { Charge, CreateChargeInput, CreateChargeResult, QuickChargeInput, QuickChargeResult } from \"../types.js\";\n\nexport class ChargesResource {\n constructor(private readonly http: HttpClient) {}\n\n list(params?: { installment_group_id?: string }): Promise<Charge[]> {\n const qs = params?.installment_group_id\n ? `?installment_group_id=${encodeURIComponent(params.installment_group_id)}`\n : \"\";\n return this.http.get<Charge[]>(`/charges${qs}`);\n }\n\n /**\n * Cria uma cobrança (PIX, boleto ou cartão). A geração de fato acontece de forma\n * assíncrona no backend — a resposta volta com a charge em PENDING, sem os campos\n * do método (QR code, boleto, etc) ainda preenchidos. Use `get`/`getStatus` para\n * acompanhar até que estejam prontos.\n */\n create(input: CreateChargeInput): Promise<CreateChargeResult> {\n return this.http.post<CreateChargeResult>(\"/charges\", input);\n }\n\n /**\n * Cobrança avulsa simples, sempre em cartão — cobra direto no cartão padrão já\n * salvo do cliente (sem fricção nenhuma). Se ele ainda não tiver um cartão salvo,\n * retorna `checkout_url` para você abrir (ex: nova aba) e o cliente cadastrar o\n * cartão e pagar.\n *\n * ```ts\n * const result = await client.charges.charge(customerId, 5000); // R$ 50,00\n * if (!result.charged_off_session) {\n * window.open(result.checkout_url!, \"_blank\");\n * }\n * ```\n */\n charge(customerId: string, amountCents: number, options?: Omit<QuickChargeInput, \"customer_id\" | \"amount\">): Promise<QuickChargeResult> {\n return this.http.post<QuickChargeResult>(\"/charges/quick\", {\n customer_id: customerId,\n amount: amountCents,\n ...options,\n });\n }\n\n get(id: string): Promise<Charge> {\n return this.http.get<Charge>(`/charges/${id}`);\n }\n\n getStatus(id: string): Promise<{ status: Charge[\"status\"] }> {\n return this.http.get(`/charges/${id}/status`);\n }\n\n cancel(id: string): Promise<Charge> {\n return this.http.patch<Charge>(`/charges/${id}/cancel`);\n }\n\n refund(id: string): Promise<Charge> {\n return this.http.post<Charge>(`/charges/${id}/refund`);\n }\n}\n","import type { HttpClient } from \"../http.js\";\nimport type { CheckoutStatusResult } from \"../types.js\";\n\nexport interface WaitUntilPaidOptions {\n /** Intervalo entre tentativas, em ms. Default: 2000. */\n intervalMs?: number;\n /** Tempo máximo de espera antes de desistir, em ms. Default: 5 minutos. */\n timeoutMs?: number;\n}\n\nexport class CheckoutResource {\n constructor(private readonly http: HttpClient) {}\n\n /** Consulta o status atual de uma cobrança/checkout pelo `checkout_token` retornado\n * por `plans.checkout()` (ou qualquer outro fluxo de cobrança do SDK). Sincroniza com\n * o provedor de pagamento sob o capô quando ainda está PENDING. */\n getStatus(checkoutToken: string): Promise<CheckoutStatusResult> {\n return this.http.get<CheckoutStatusResult>(`/checkout/${checkoutToken}/status`);\n }\n\n /**\n * Faz polling de `getStatus` até o pagamento ser confirmado (ou falhar/expirar) — é\n * a forma recomendada de confirmar, depois de redirecionar o cliente para a\n * `checkout_url`, que a assinatura realmente foi paga antes de liberar acesso.\n *\n * Resolve quando o status deixa de ser PENDING/PROCESSING. Lança um erro se o tempo\n * limite (`timeoutMs`) for atingido antes disso.\n */\n async waitUntilPaid(checkoutToken: string, options: WaitUntilPaidOptions = {}): Promise<CheckoutStatusResult> {\n const intervalMs = options.intervalMs ?? 2000;\n const timeoutMs = options.timeoutMs ?? 5 * 60 * 1000;\n const deadline = Date.now() + timeoutMs;\n\n for (;;) {\n const result = await this.getStatus(checkoutToken);\n if (result.status !== \"PENDING\" && result.status !== \"PROCESSING\") {\n return result;\n }\n if (Date.now() >= deadline) {\n throw new Error(`Tempo limite excedido aguardando confirmação de pagamento (checkout_token=${checkoutToken}).`);\n }\n await new Promise((resolve) => setTimeout(resolve, intervalMs));\n }\n }\n}\n","import type { HttpClient } from \"../http.js\";\nimport type { Customer, CustomerInput } from \"../types.js\";\n\nexport class CustomersResource {\n constructor(private readonly http: HttpClient) {}\n\n list(): Promise<Customer[]> {\n return this.http.get<Customer[]>(\"/customers\");\n }\n\n create(input: CustomerInput): Promise<Customer> {\n return this.http.post<Customer>(\"/customers\", input);\n }\n\n get(id: string): Promise<Customer> {\n return this.http.get<Customer>(`/customers/${id}`);\n }\n\n update(id: string, input: Partial<CustomerInput>): Promise<Customer> {\n return this.http.patch<Customer>(`/customers/${id}`, input);\n }\n}\n","import type { HttpClient } from \"../http.js\";\nimport type { BillingItem } from \"../types.js\";\n\nexport interface ItemInput {\n name: string;\n description?: string;\n amount: number;\n currency?: string;\n}\n\nexport class ItemsResource {\n constructor(private readonly http: HttpClient) {}\n\n list(): Promise<BillingItem[]> {\n return this.http.get<BillingItem[]>(\"/items\");\n }\n\n create(input: ItemInput): Promise<BillingItem> {\n return this.http.post<BillingItem>(\"/items\", input);\n }\n\n get(id: string): Promise<BillingItem> {\n return this.http.get<BillingItem>(`/items/${id}`);\n }\n\n update(id: string, input: Partial<ItemInput>): Promise<BillingItem> {\n return this.http.patch<BillingItem>(`/items/${id}`, input);\n }\n}\n","import type { HttpClient } from \"../http.js\";\nimport type { CreateOrderInput, CreateOrderResult } from \"../types.js\";\n\nexport class OrdersResource {\n constructor(private readonly http: HttpClient) {}\n\n /**\n * Cria um pedido parcelado (parcelamento real via cobranças avulsas agendadas,\n * não assinatura). Retorna o `client_secret` da 1ª parcela para o front-end\n * confirmar via Stripe Elements — as parcelas seguintes são cobradas\n * automaticamente pelo backend no cartão salvo.\n */\n create(input: CreateOrderInput): Promise<CreateOrderResult> {\n return this.http.post<CreateOrderResult>(\"/orders\", input);\n }\n\n list(): Promise<unknown[]> {\n return this.http.get(\"/orders\");\n }\n\n get(id: string): Promise<unknown> {\n return this.http.get(`/orders/${id}`);\n }\n}\n","import type { HttpClient } from \"../http.js\";\nimport type {\n BillingPlanSummary,\n CreateBillingPlanInput,\n GetPublicPlanPageResult,\n ListPublicPlansResult,\n PlanCheckoutInput,\n PlanCheckoutResult,\n} from \"../types.js\";\n\nexport class PlansResource {\n constructor(private readonly http: HttpClient) {}\n\n list(): Promise<BillingPlanSummary[]> {\n return this.http.get<BillingPlanSummary[]>(\"/billing-plans\");\n }\n\n get(id: string): Promise<BillingPlanSummary> {\n return this.http.get<BillingPlanSummary>(`/billing-plans/${id}`);\n }\n\n create(input: CreateBillingPlanInput): Promise<BillingPlanSummary> {\n return this.http.post<BillingPlanSummary>(\"/billing-plans\", input);\n }\n\n update(id: string, input: Partial<CreateBillingPlanInput> & { active?: boolean }): Promise<BillingPlanSummary> {\n return this.http.patch<BillingPlanSummary>(`/billing-plans/${id}`, input);\n }\n\n /** Não há hard-delete de planos (assinaturas existentes ainda referenciam) — para\n * remover um plano do catálogo público, arquive-o. */\n archive(id: string): Promise<BillingPlanSummary> {\n return this.http.patch<BillingPlanSummary>(`/billing-plans/${id}`, { active: false });\n }\n\n // ─── Rotas públicas (sem auth — usadas para montar sua própria página de preços) ──\n\n /** Lista os planos ativos de uma org pelo slug público — página fixa legada, sem\n * suporte a múltiplas páginas. Prefira `getPublicPage` para orgs com várias páginas. */\n listPublic(orgSlug: string): Promise<ListPublicPlansResult> {\n return this.http.get<ListPublicPlansResult>(`/public/orgs/${orgSlug}/billing-plans`);\n }\n\n /** Busca uma página de planos pública específica pelo slug da org + slug da página. */\n getPublicPage(orgSlug: string, pageSlug: string): Promise<GetPublicPlanPageResult> {\n return this.http.get<GetPublicPlanPageResult>(`/public/orgs/${orgSlug}/plan-pages/${pageSlug}`);\n }\n\n /**\n * Inicia a assinatura de um plano para um cliente final: cria (ou reaproveita) o\n * `Customer` pelo e-mail, cria a `Subscription` e retorna uma URL de checkout hospedada\n * pela Geekapps para o cliente confirmar o pagamento.\n *\n * Fluxo típico:\n * ```ts\n * const { checkout_url, checkout_token } = await client.plans.checkout(planId, {\n * customer: { name, email },\n * });\n * // redirecione o cliente (ou abra checkout_url em uma WebView/nova aba)\n * window.location.href = checkout_url;\n *\n * // depois do retorno, confirme se realmente foi pago:\n * const { status } = await client.checkout.waitUntilPaid(checkout_token);\n * if (status === \"PAID\") { /* liberar acesso *\\/ }\n * ```\n *\n * Não requer autenticação — pode ser chamado a partir do backend do dev sem token de\n * service account, ou do próprio SDK server-side usando qualquer token válido.\n */\n checkout(planId: string, input: PlanCheckoutInput): Promise<PlanCheckoutResult> {\n return this.http.post<PlanCheckoutResult>(`/public/billing-plans/${planId}/checkout`, input);\n }\n}\n","import type { HttpClient } from \"../http.js\";\nimport type { Subscription, SubscriptionStatusResult } from \"../types.js\";\n\nexport class SubscriptionsResource {\n constructor(private readonly http: HttpClient) {}\n\n /** Requer autenticação (service account) — lista todas as assinaturas da sua org. */\n list(): Promise<Subscription[]> {\n return this.http.get<Subscription[]>(\"/billing-subscriptions\");\n }\n\n /** Requer autenticação (service account). */\n get(id: string): Promise<Subscription> {\n return this.http.get<Subscription>(`/billing-subscriptions/${id}`);\n }\n\n /** Requer autenticação (service account). */\n cancel(id: string): Promise<Subscription> {\n return this.http.patch<Subscription>(`/billing-subscriptions/${id}/cancel`);\n }\n\n /**\n * Verifica se uma assinatura está ativa e qual item ela cobre, usando o\n * `management_token` retornado por `plans.checkout()` — rota pública, sem\n * autenticação, segura para chamar tanto do seu backend quanto (via fetch direto,\n * sem o SDK) do client-side do seu app.\n *\n * ```ts\n * const status = await client.subscriptions.checkByToken(managementToken);\n * if (status.subscription.active) {\n * console.log(\"cobrando\", status.item.name);\n * }\n * ```\n */\n checkByToken(managementToken: string): Promise<SubscriptionStatusResult> {\n return this.http.get<SubscriptionStatusResult>(`/public/plan-management/${managementToken}`);\n }\n}\n","import { HttpClient, type HttpClientOptions } from \"./http.js\";\nimport { ChargesResource } from \"./resources/charges.js\";\nimport { CheckoutResource } from \"./resources/checkout.js\";\nimport { CustomersResource } from \"./resources/customers.js\";\nimport { ItemsResource } from \"./resources/items.js\";\nimport { OrdersResource } from \"./resources/orders.js\";\nimport { PlansResource } from \"./resources/plans.js\";\nimport { SubscriptionsResource } from \"./resources/subscriptions.js\";\n\nexport interface BillingClientOptions\n extends Omit<HttpClientOptions, \"baseUrl\"> {\n baseUrl?: string;\n}\n\nexport class BillingClient {\n private readonly http: HttpClient;\n\n readonly charges: ChargesResource;\n readonly checkout: CheckoutResource;\n readonly customers: CustomersResource;\n readonly items: ItemsResource;\n readonly orders: OrdersResource;\n readonly plans: PlansResource;\n readonly subscriptions: SubscriptionsResource;\n\n constructor(options: HttpClientOptions) {\n this.http = new HttpClient(options);\n\n this.charges = new ChargesResource(this.http);\n this.checkout = new CheckoutResource(this.http);\n this.customers = new CustomersResource(this.http);\n this.items = new ItemsResource(this.http);\n this.orders = new OrdersResource(this.http);\n this.plans = new PlansResource(this.http);\n this.subscriptions = new SubscriptionsResource(this.http);\n }\n}\n","import type { FastifyInstance, FastifyPluginAsync } from \"fastify\";\nimport fp from \"fastify-plugin\";\nimport { BillingClient } from \"./client.js\";\nimport { ServiceAccountTokenProvider, type ServiceAccountOptions } from \"./service-account.js\";\n\nexport interface BillingPluginOptions {\n /** Geekapps Billing API base URL */\n baseUrl: string;\n /** Service account credentials — required */\n serviceAccount: ServiceAccountOptions;\n /** Ambiente de billing (dev/prod). Default: \"prod\". */\n mode?: string;\n}\n\ndeclare module \"fastify\" {\n interface FastifyInstance {\n billingClient: BillingClient;\n }\n}\n\nconst billingPlugin: FastifyPluginAsync<BillingPluginOptions> = async (\n fastify: FastifyInstance,\n options: BillingPluginOptions,\n) => {\n const tokenProvider = new ServiceAccountTokenProvider(options.serviceAccount);\n\n const client = new BillingClient({\n baseUrl: options.baseUrl,\n token: () => tokenProvider.getToken(),\n organizationId: () => tokenProvider.getOrganizationId() as Promise<string>,\n mode: options.mode,\n });\n\n fastify.decorate(\"billingClient\", client);\n};\n\nexport default fp(billingPlugin, {\n fastify: \">=4.0.0\",\n name: \"@geekapps/billing-fastify\",\n});\n","import type { TokenResolver } from \"./http.js\";\n\nexport interface ServiceAccountOptions {\n /** Geekapps Auth issuer base URL (e.g. https://accounts-api.geekapps.com.br) */\n issuerUrl: string;\n clientId: string;\n clientSecret: string;\n /** Seconds before expiry to proactively refresh. Defaults to 30. */\n refreshBeforeExpirySeconds?: number;\n}\n\ninterface CachedToken {\n value: string;\n expiresAt: number; // ms epoch\n organizationId: string | undefined;\n}\n\nfunction decodeJwtPayload(token: string): Record<string, unknown> {\n try {\n const [, payload] = token.split(\".\");\n if (!payload) return {};\n const json = Buffer.from(payload, \"base64url\").toString(\"utf-8\");\n return JSON.parse(json) as Record<string, unknown>;\n } catch {\n return {};\n }\n}\n\n/**\n * Fetches a short-lived token from the Geekapps Auth service using\n * client_credentials grant and caches it until near expiry.\n *\n * The organizationId claim is extracted automatically from the JWT payload.\n */\nexport class ServiceAccountTokenProvider {\n private readonly issuerUrl: string;\n private readonly clientId: string;\n private readonly clientSecret: string;\n private readonly refreshBeforeMs: number;\n private cached: CachedToken | null = null;\n private inflight: Promise<CachedToken> | null = null;\n\n constructor(options: ServiceAccountOptions) {\n this.issuerUrl = options.issuerUrl.replace(/\\/$/, \"\");\n this.clientId = options.clientId;\n this.clientSecret = options.clientSecret;\n this.refreshBeforeMs = (options.refreshBeforeExpirySeconds ?? 30) * 1000;\n }\n\n private async ensureFresh(): Promise<CachedToken> {\n const now = Date.now();\n\n if (this.cached && this.cached.expiresAt - now > this.refreshBeforeMs) {\n return this.cached;\n }\n\n if (this.inflight) return this.inflight;\n\n this.inflight = this.fetchToken().finally(() => {\n this.inflight = null;\n });\n\n return this.inflight;\n }\n\n /** Returns a valid access token. */\n getToken(): Promise<string> {\n return this.ensureFresh().then((c) => c.value);\n }\n\n /** Returns the organizationId embedded in the service account JWT. */\n getOrganizationId(): Promise<string | undefined> {\n return this.ensureFresh().then((c) => c.organizationId);\n }\n\n private async fetchToken(): Promise<CachedToken> {\n const credentials = Buffer.from(`${this.clientId}:${this.clientSecret}`).toString(\"base64\");\n\n const res = await fetch(`${this.issuerUrl}/auth/token`, {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n Authorization: `Basic ${credentials}`,\n },\n body: JSON.stringify({ grant_type: \"service_account\" }),\n });\n\n if (!res.ok) {\n const err = await res.json().catch(() => ({})) as { error?: string };\n throw new Error(\n `ServiceAccount token fetch failed (${res.status}): ${err.error ?? \"unknown error\"}`,\n );\n }\n\n const data = await res.json() as { access_token: string; expires_in?: number };\n\n const claims = decodeJwtPayload(data.access_token);\n const organizationId =\n typeof claims.organizationId === \"string\" ? claims.organizationId :\n typeof claims.organization_id === \"string\" ? claims.organization_id :\n undefined;\n\n const expiresInMs = (data.expires_in ?? 420) * 1000;\n this.cached = {\n value: data.access_token,\n expiresAt: Date.now() + expiresInMs,\n organizationId,\n };\n\n return this.cached;\n }\n\n /** Returns this provider as a TokenResolver to pass directly to BillingClient. */\n asTokenResolver(): TokenResolver {\n return () => this.getToken();\n }\n}\n\n/** Convenience factory. Returns a TokenResolver ready for use in BillingClient. */\nexport function createServiceAccountToken(\n options: ServiceAccountOptions,\n): TokenResolver {\n return new ServiceAccountTokenProvider(options).asTokenResolver();\n}\n"],"mappings":"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","names":["fp"]}
|