@basaltkit/subscriptions 1.0.0 → 1.0.1
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/LICENSE +1 -1
- package/dist/index.d.ts +90 -1
- package/dist/index.js +17 -0
- package/package.json +1 -1
package/LICENSE
CHANGED
package/dist/index.d.ts
CHANGED
|
@@ -261,6 +261,95 @@ declare class FakeBillingGateway implements BillingGateway {
|
|
|
261
261
|
verifyWebhook(rawBody: string, signature: string | undefined): WebhookEvent;
|
|
262
262
|
}
|
|
263
263
|
|
|
264
|
+
/**
|
|
265
|
+
* One-off / reference / mobile-money payments — the model used by Angolan
|
|
266
|
+
* providers (ProxyPay, EMIS/Multicaixa, AppyPay, UNITEL Money), where there's no
|
|
267
|
+
* card-on-file recurring charge or self-service portal. This complements
|
|
268
|
+
* `BillingGateway` (card subscriptions). Recurring billing is modelled by
|
|
269
|
+
* creating one payment per period (invoice → reference → webhook confirms → the
|
|
270
|
+
* period is activated).
|
|
271
|
+
*/
|
|
272
|
+
/** A one-off payment request handed to a `PaymentGateway`. */
|
|
273
|
+
interface PaymentRequest {
|
|
274
|
+
/** Who is paying — a tenant/user/customer id you reconcile against. */
|
|
275
|
+
billableId: string;
|
|
276
|
+
/** Amount in the currency's major unit (e.g. 5000 = 5000,00 Kz). */
|
|
277
|
+
amount: number;
|
|
278
|
+
/** ISO 4217. Defaults to the gateway's own (AOA for Angolan gateways). */
|
|
279
|
+
currency?: string;
|
|
280
|
+
/** Your order/invoice id — for idempotency and reconciliation. */
|
|
281
|
+
reference?: string;
|
|
282
|
+
description?: string;
|
|
283
|
+
customer?: {
|
|
284
|
+
name?: string;
|
|
285
|
+
email?: string;
|
|
286
|
+
phone?: string;
|
|
287
|
+
};
|
|
288
|
+
/** When the reference / request stops being payable (epoch ms). */
|
|
289
|
+
expiresAt?: number;
|
|
290
|
+
/** Passed to the gateway and echoed back on the webhook. */
|
|
291
|
+
metadata?: Record<string, string>;
|
|
292
|
+
}
|
|
293
|
+
/** How the customer is told to pay — a reference, a redirect, or a push. */
|
|
294
|
+
interface PaymentInstruction {
|
|
295
|
+
/** The gateway's id for this payment (status checks + reconciliation). */
|
|
296
|
+
id: string;
|
|
297
|
+
status: 'pending' | 'paid' | 'failed';
|
|
298
|
+
/** Reference-based (Multicaixa/EMIS): the entity + reference to pay. */
|
|
299
|
+
reference?: {
|
|
300
|
+
entity: string;
|
|
301
|
+
reference: string;
|
|
302
|
+
amount: number;
|
|
303
|
+
};
|
|
304
|
+
/** Redirect-based (hosted page): send the customer here. */
|
|
305
|
+
url?: string;
|
|
306
|
+
/** Push-based (mobile money): a prompt was sent to this phone. */
|
|
307
|
+
push?: {
|
|
308
|
+
phone: string;
|
|
309
|
+
};
|
|
310
|
+
/** The raw gateway payload, for logging/debugging. */
|
|
311
|
+
raw?: unknown;
|
|
312
|
+
}
|
|
313
|
+
/** A payment webhook, translated to domain terms — gateway payloads never leak. */
|
|
314
|
+
interface PaymentEvent {
|
|
315
|
+
/** Unique id at the gateway — for idempotent processing. */
|
|
316
|
+
id: string;
|
|
317
|
+
type: 'payment.succeeded' | 'payment.failed';
|
|
318
|
+
/** The gateway payment/reference id from `createPayment`. */
|
|
319
|
+
paymentId: string;
|
|
320
|
+
amount: number;
|
|
321
|
+
/** From the request metadata, when the gateway echoes it back. */
|
|
322
|
+
billableId?: string;
|
|
323
|
+
reference?: string;
|
|
324
|
+
raw?: unknown;
|
|
325
|
+
}
|
|
326
|
+
/**
|
|
327
|
+
* Payment gateway driver contract for one-off / reference / mobile-money
|
|
328
|
+
* charges. The app talks to Basalt; only drivers talk to ProxyPay / EMIS / etc.
|
|
329
|
+
* A driver translates raw webhook payloads into `PaymentEvent`.
|
|
330
|
+
*/
|
|
331
|
+
interface PaymentGateway {
|
|
332
|
+
readonly name: string;
|
|
333
|
+
/** Create a payment — returns a reference, a redirect URL, or a push. */
|
|
334
|
+
createPayment(request: PaymentRequest): Promise<PaymentInstruction>;
|
|
335
|
+
/**
|
|
336
|
+
* Verifies the signature and translates the payload. Throws
|
|
337
|
+
* `WebhookInvalidError` on a bad signature; returns null for a verified event
|
|
338
|
+
* that isn't a payment (gateways emit event types we don't act on).
|
|
339
|
+
*/
|
|
340
|
+
verifyWebhook(rawBody: string, signature: string | undefined): PaymentEvent | null;
|
|
341
|
+
/** Poll a payment's status — a fallback when you can't receive webhooks. */
|
|
342
|
+
getPayment?(id: string): Promise<PaymentInstruction>;
|
|
343
|
+
}
|
|
344
|
+
/** Controllable in-process payment gateway — the test/dev driver. */
|
|
345
|
+
declare class FakePaymentGateway implements PaymentGateway {
|
|
346
|
+
readonly name = "fake";
|
|
347
|
+
readonly payments: PaymentRequest[];
|
|
348
|
+
private counter;
|
|
349
|
+
createPayment(request: PaymentRequest): Promise<PaymentInstruction>;
|
|
350
|
+
verifyWebhook(rawBody: string, signature: string | undefined): PaymentEvent;
|
|
351
|
+
}
|
|
352
|
+
|
|
264
353
|
declare class StripeRequestError extends BasaltError {
|
|
265
354
|
readonly httpStatus: number;
|
|
266
355
|
constructor(httpStatus: number, message: string);
|
|
@@ -473,4 +562,4 @@ declare function billingRoutes(options: BillingRoutesOptions): BasaltRoute[];
|
|
|
473
562
|
*/
|
|
474
563
|
declare function billingWebhookRoute(gateway: BillingGateway): BasaltRoute;
|
|
475
564
|
|
|
476
|
-
export { type BillingGateway, type BillingPeriod, type BillingRoutesOptions, type CheckoutInput, type CreateSubscriptionInput, FakeBillingGateway, FeatureUnavailableError, type FeatureValue, GatewayUnsupportedError, MemorySubscriptionStore, MemoryUsageStore, MemoryWebhookStore, type Meter, NotSubscribedError, type PlanDefinition, type Plans, type PortalInput, QuotaExceededError, type RedisLike, RedisUsageStore, type RedisUsageStoreOptions, type RedisWebhookClient, RedisWebhookStore, type RedisWebhookStoreOptions, SUBSCRIPTIONS, StripeBillingGateway, type StripeGatewayOptions, StripeRequestError, type SubscriptionRecord, type SubscriptionStatus, type SubscriptionStore, Subscriptions, type SubscriptionsOptions, type SubscriptionsPluginOptions, type SwapInput, UnknownPlanError, type UsageConsumeResult, type UsageStore, type WebhookEvent, WebhookInvalidError, type WebhookStore, billingRoutes, billingWebhookRoute, definePlans, featureLimit, isMeter, meter, planPrice, subscriptionsPlugin };
|
|
565
|
+
export { type BillingGateway, type BillingPeriod, type BillingRoutesOptions, type CheckoutInput, type CreateSubscriptionInput, FakeBillingGateway, FakePaymentGateway, FeatureUnavailableError, type FeatureValue, GatewayUnsupportedError, MemorySubscriptionStore, MemoryUsageStore, MemoryWebhookStore, type Meter, NotSubscribedError, type PaymentEvent, type PaymentGateway, type PaymentInstruction, type PaymentRequest, type PlanDefinition, type Plans, type PortalInput, QuotaExceededError, type RedisLike, RedisUsageStore, type RedisUsageStoreOptions, type RedisWebhookClient, RedisWebhookStore, type RedisWebhookStoreOptions, SUBSCRIPTIONS, StripeBillingGateway, type StripeGatewayOptions, StripeRequestError, type SubscriptionRecord, type SubscriptionStatus, type SubscriptionStore, Subscriptions, type SubscriptionsOptions, type SubscriptionsPluginOptions, type SwapInput, UnknownPlanError, type UsageConsumeResult, type UsageStore, type WebhookEvent, WebhookInvalidError, type WebhookStore, billingRoutes, billingWebhookRoute, definePlans, featureLimit, isMeter, meter, planPrice, subscriptionsPlugin };
|
package/dist/index.js
CHANGED
|
@@ -193,6 +193,22 @@ var FakeBillingGateway = class {
|
|
|
193
193
|
}
|
|
194
194
|
};
|
|
195
195
|
|
|
196
|
+
// src/payment.ts
|
|
197
|
+
var FakePaymentGateway = class {
|
|
198
|
+
name = "fake";
|
|
199
|
+
payments = [];
|
|
200
|
+
counter = 0;
|
|
201
|
+
async createPayment(request) {
|
|
202
|
+
this.payments.push(request);
|
|
203
|
+
const id = `fake_pay_${++this.counter}`;
|
|
204
|
+
return { id, status: "pending", reference: { entity: "00000", reference: id, amount: request.amount } };
|
|
205
|
+
}
|
|
206
|
+
verifyWebhook(rawBody, signature) {
|
|
207
|
+
if (signature !== "valid") throw new WebhookInvalidError();
|
|
208
|
+
return JSON.parse(rawBody);
|
|
209
|
+
}
|
|
210
|
+
};
|
|
211
|
+
|
|
196
212
|
// src/drivers/stripe.ts
|
|
197
213
|
import { createHmac, timingSafeEqual } from "crypto";
|
|
198
214
|
import { BasaltError as BasaltError3 } from "@basaltkit/core";
|
|
@@ -692,6 +708,7 @@ function billingWebhookRoute(gateway) {
|
|
|
692
708
|
}
|
|
693
709
|
export {
|
|
694
710
|
FakeBillingGateway,
|
|
711
|
+
FakePaymentGateway,
|
|
695
712
|
FeatureUnavailableError,
|
|
696
713
|
GatewayUnsupportedError,
|
|
697
714
|
MemorySubscriptionStore,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@basaltkit/subscriptions",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.1",
|
|
4
4
|
"description": "Billing for Basalt, Cashier/Soulbscription-style: declarative plans, subscriptions with trials, feature flags, usage limits, gateway drivers and idempotent webhooks.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|