@basaltkit/subscriptions 2.1.0 → 2.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/dist/index.d.ts +19 -1
- package/dist/index.js +26 -0
- package/package.json +3 -3
package/dist/index.d.ts
CHANGED
|
@@ -161,6 +161,24 @@ declare class WebhookInvalidError extends BasaltError {
|
|
|
161
161
|
readonly status = 400;
|
|
162
162
|
constructor();
|
|
163
163
|
}
|
|
164
|
+
/**
|
|
165
|
+
* Thrown when a gateway is asked to verify a webhook but no signing secret is
|
|
166
|
+
* configured. Verification fails closed: an unauthenticated callback must never
|
|
167
|
+
* be trusted (anyone could forge a `payment.succeeded`).
|
|
168
|
+
*/
|
|
169
|
+
declare class WebhookSecretMissingError extends BasaltError {
|
|
170
|
+
readonly status = 500;
|
|
171
|
+
constructor(gateway: string);
|
|
172
|
+
}
|
|
173
|
+
/**
|
|
174
|
+
* Thrown when a confirmed payment's amount does not match the amount that was
|
|
175
|
+
* originally requested for that payment id — an underpayment, or a forged /
|
|
176
|
+
* mis-routed callback trying to settle an invoice for less.
|
|
177
|
+
*/
|
|
178
|
+
declare class PaymentAmountMismatchError extends BasaltError {
|
|
179
|
+
readonly status = 400;
|
|
180
|
+
constructor(paymentId: string, expected: number, actual: number);
|
|
181
|
+
}
|
|
164
182
|
/** Gateway-agnostic webhook event, already translated to domain terms. */
|
|
165
183
|
interface WebhookEvent {
|
|
166
184
|
/** Unique id at the gateway — used for idempotent processing. */
|
|
@@ -847,4 +865,4 @@ declare function billingRoutes(options: BillingRoutesOptions): BasaltRoute[];
|
|
|
847
865
|
*/
|
|
848
866
|
declare function billingWebhookRoute(gateway: BillingGateway): BasaltRoute;
|
|
849
867
|
|
|
850
|
-
export { type BillingGateway, type BillingPeriod, type BillingRoutesOptions, type CheckoutInput, type CreateSubscriptionInput, FakeBillingGateway, FakePaymentGateway, FeatureUnavailableError, type FeatureValue, GatewayUnsupportedError, type HandleEventResult, MemoryPaymentStore, MemoryRecurringStore, MemorySubscriptionStore, MemoryUsageStore, MemoryWebhookStore, type Meter, type NewPayment, NotSubscribedError, type PaymentApplyResult, type PaymentEvent, type PaymentGateway, type PaymentInstruction, PaymentLedger, type PaymentLedgerEvent, type PaymentLedgerEvents, type PaymentLedgerListener, type PaymentLedgerOptions, type PaymentRecord, type PaymentRecordStatus, type PaymentRequest, type PaymentStore, type PlanDefinition, type Plans, type PortalInput, QuotaExceededError, type RecurringBillingOptions, type RecurringInterval, RecurringReferenceBilling, type RecurringStatus, type RecurringStore, type RecurringSubscription, type RedisLike, RedisUsageStore, type RedisUsageStoreOptions, type RedisWebhookClient, RedisWebhookStore, type RedisWebhookStoreOptions, SUBSCRIPTIONS, StripeBillingGateway, type StripeGatewayOptions, StripeRequestError, type SubscribeInput, type SubscriptionRecord, type SubscriptionStatus, type SubscriptionStore, Subscriptions, type SubscriptionsOptions, type SubscriptionsPluginOptions, type SwapInput, UnknownPlanError, type UsageConsumeResult, type UsageStore, type WebhookEvent, WebhookInvalidError, type WebhookStore, addInterval, assertMinorUnits, billingRoutes, billingWebhookRoute, currencyDecimals, definePlans, featureLimit, formatMoney, isMeter, isMinorUnits, meter, planPrice, subscriptionsPlugin, toMajor, toMinor };
|
|
868
|
+
export { type BillingGateway, type BillingPeriod, type BillingRoutesOptions, type CheckoutInput, type CreateSubscriptionInput, FakeBillingGateway, FakePaymentGateway, FeatureUnavailableError, type FeatureValue, GatewayUnsupportedError, type HandleEventResult, MemoryPaymentStore, MemoryRecurringStore, MemorySubscriptionStore, MemoryUsageStore, MemoryWebhookStore, type Meter, type NewPayment, NotSubscribedError, PaymentAmountMismatchError, type PaymentApplyResult, type PaymentEvent, type PaymentGateway, type PaymentInstruction, PaymentLedger, type PaymentLedgerEvent, type PaymentLedgerEvents, type PaymentLedgerListener, type PaymentLedgerOptions, type PaymentRecord, type PaymentRecordStatus, type PaymentRequest, type PaymentStore, type PlanDefinition, type Plans, type PortalInput, QuotaExceededError, type RecurringBillingOptions, type RecurringInterval, RecurringReferenceBilling, type RecurringStatus, type RecurringStore, type RecurringSubscription, type RedisLike, RedisUsageStore, type RedisUsageStoreOptions, type RedisWebhookClient, RedisWebhookStore, type RedisWebhookStoreOptions, SUBSCRIPTIONS, StripeBillingGateway, type StripeGatewayOptions, StripeRequestError, type SubscribeInput, type SubscriptionRecord, type SubscriptionStatus, type SubscriptionStore, Subscriptions, type SubscriptionsOptions, type SubscriptionsPluginOptions, type SwapInput, UnknownPlanError, type UsageConsumeResult, type UsageStore, type WebhookEvent, WebhookInvalidError, WebhookSecretMissingError, type WebhookStore, addInterval, assertMinorUnits, billingRoutes, billingWebhookRoute, currencyDecimals, definePlans, featureLimit, formatMoney, isMeter, isMinorUnits, meter, planPrice, subscriptionsPlugin, toMajor, toMinor };
|
package/dist/index.js
CHANGED
|
@@ -160,6 +160,24 @@ var WebhookInvalidError = class extends BasaltError2 {
|
|
|
160
160
|
super("BILLING_WEBHOOK_INVALID", "Webhook signature verification failed.");
|
|
161
161
|
}
|
|
162
162
|
};
|
|
163
|
+
var WebhookSecretMissingError = class extends BasaltError2 {
|
|
164
|
+
status = 500;
|
|
165
|
+
constructor(gateway) {
|
|
166
|
+
super(
|
|
167
|
+
"BILLING_WEBHOOK_SECRET_MISSING",
|
|
168
|
+
`${gateway}: cannot verify a webhook without a configured signing secret \u2014 refusing to trust an unsigned callback.`
|
|
169
|
+
);
|
|
170
|
+
}
|
|
171
|
+
};
|
|
172
|
+
var PaymentAmountMismatchError = class extends BasaltError2 {
|
|
173
|
+
status = 400;
|
|
174
|
+
constructor(paymentId, expected, actual) {
|
|
175
|
+
super(
|
|
176
|
+
"BILLING_PAYMENT_AMOUNT_MISMATCH",
|
|
177
|
+
`Payment ${paymentId} was requested for ${expected} but the webhook confirmed ${actual} \u2014 refusing to mark it paid.`
|
|
178
|
+
);
|
|
179
|
+
}
|
|
180
|
+
};
|
|
163
181
|
var FakeBillingGateway = class {
|
|
164
182
|
name = "fake";
|
|
165
183
|
created = [];
|
|
@@ -303,6 +321,12 @@ var PaymentLedger = class {
|
|
|
303
321
|
let record;
|
|
304
322
|
try {
|
|
305
323
|
const status = event.type === "payment.succeeded" ? "paid" : "failed";
|
|
324
|
+
if (status === "paid") {
|
|
325
|
+
const existing = await this.store.get(event.paymentId);
|
|
326
|
+
if (existing && existing.amount > 0 && event.amount !== existing.amount) {
|
|
327
|
+
throw new PaymentAmountMismatchError(event.paymentId, existing.amount, event.amount);
|
|
328
|
+
}
|
|
329
|
+
}
|
|
306
330
|
await this.store.setStatus(event.paymentId, status, {
|
|
307
331
|
amount: event.amount,
|
|
308
332
|
...event.raw !== void 0 ? { raw: event.raw } : {}
|
|
@@ -1002,6 +1026,7 @@ export {
|
|
|
1002
1026
|
MemoryUsageStore,
|
|
1003
1027
|
MemoryWebhookStore,
|
|
1004
1028
|
NotSubscribedError,
|
|
1029
|
+
PaymentAmountMismatchError,
|
|
1005
1030
|
PaymentLedger,
|
|
1006
1031
|
QuotaExceededError,
|
|
1007
1032
|
RecurringReferenceBilling,
|
|
@@ -1013,6 +1038,7 @@ export {
|
|
|
1013
1038
|
Subscriptions,
|
|
1014
1039
|
UnknownPlanError,
|
|
1015
1040
|
WebhookInvalidError,
|
|
1041
|
+
WebhookSecretMissingError,
|
|
1016
1042
|
addInterval,
|
|
1017
1043
|
assertMinorUnits,
|
|
1018
1044
|
billingRoutes,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@basaltkit/subscriptions",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.2.0",
|
|
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",
|
|
@@ -14,8 +14,8 @@
|
|
|
14
14
|
"dist"
|
|
15
15
|
],
|
|
16
16
|
"dependencies": {
|
|
17
|
-
"@basaltkit/
|
|
18
|
-
"@basaltkit/
|
|
17
|
+
"@basaltkit/core": "^1.0.0",
|
|
18
|
+
"@basaltkit/fastify": "^1.1.0"
|
|
19
19
|
},
|
|
20
20
|
"peerDependencies": {
|
|
21
21
|
"zod": "^3.24.0 || ^4.0.0"
|