v1.3.27-c: Add adjustment/summary action for meter event
This commit is contained in:
@@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"name": "@bowong/better-auth-stripe",
|
"name": "@bowong/better-auth-stripe",
|
||||||
"author": "Bowong",
|
"author": "Bowong",
|
||||||
"version": "1.3.27-a",
|
"version": "1.3.27-c",
|
||||||
"main": "dist/index.cjs",
|
"main": "dist/index.cjs",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"keywords": [
|
"keywords": [
|
||||||
|
|||||||
140
src/index.ts
140
src/index.ts
@@ -19,6 +19,7 @@ import {
|
|||||||
onSubscriptionUpdated,
|
onSubscriptionUpdated,
|
||||||
} from "./hooks";
|
} from "./hooks";
|
||||||
import type {
|
import type {
|
||||||
|
actionType,
|
||||||
InputSubscription,
|
InputSubscription,
|
||||||
StripeOptions,
|
StripeOptions,
|
||||||
StripePlan,
|
StripePlan,
|
||||||
@@ -67,13 +68,7 @@ export const stripe = <O extends StripeOptions>(options: O) => {
|
|||||||
const client = options.stripeClient;
|
const client = options.stripeClient;
|
||||||
|
|
||||||
const referenceMiddleware = (
|
const referenceMiddleware = (
|
||||||
action:
|
action: actionType,
|
||||||
| "upgrade-subscription"
|
|
||||||
| "list-subscription"
|
|
||||||
| "cancel-subscription"
|
|
||||||
| "restore-subscription"
|
|
||||||
| "meter-event"
|
|
||||||
| "billing-portal",
|
|
||||||
) =>
|
) =>
|
||||||
createAuthMiddleware(async (ctx) => {
|
createAuthMiddleware(async (ctx) => {
|
||||||
const session = ctx.context.session;
|
const session = ctx.context.session;
|
||||||
@@ -1221,7 +1216,6 @@ export const stripe = <O extends StripeOptions>(options: O) => {
|
|||||||
{
|
{
|
||||||
method: "POST",
|
method: "POST",
|
||||||
body: z.object({
|
body: z.object({
|
||||||
meter_id: z.string(),
|
|
||||||
event_name: z.string(),
|
event_name: z.string(),
|
||||||
payload: z.object({
|
payload: z.object({
|
||||||
value: z.string(),
|
value: z.string(),
|
||||||
@@ -1265,17 +1259,17 @@ export const stripe = <O extends StripeOptions>(options: O) => {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
const submitPayload = {
|
try {
|
||||||
|
const bodyPayload = {
|
||||||
|
event_name: ctx.body.event_name,
|
||||||
|
payload: {
|
||||||
value: ctx.body.payload.value,
|
value: ctx.body.payload.value,
|
||||||
stripe_customer_id: customerId,
|
stripe_customer_id: customerId,
|
||||||
|
},
|
||||||
|
identifier: ctx.body.identifier
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
const {identifier, payload, timestamp} = await client.v2.billing.meterEvents.create(bodyPayload);
|
||||||
const {identifier, payload, timestamp} = await client.billing.meterEvents.create({
|
|
||||||
event_name: ctx.body.event_name,
|
|
||||||
payload: submitPayload,
|
|
||||||
identifier: ctx.body.identifier
|
|
||||||
});
|
|
||||||
|
|
||||||
return ctx.json({
|
return ctx.json({
|
||||||
identifier,
|
identifier,
|
||||||
@@ -1293,6 +1287,122 @@ export const stripe = <O extends StripeOptions>(options: O) => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
),
|
),
|
||||||
|
adjustBillingMeterEvent: createAuthEndpoint(
|
||||||
|
"/subscription/meter-event/adjust", // https://docs.stripe.com/api/v2/billing-meter-adjustment
|
||||||
|
{
|
||||||
|
method: "POST",
|
||||||
|
body: z.object({
|
||||||
|
event_name: z.string(),
|
||||||
|
type: z.enum(["cancel"]),
|
||||||
|
cancel: z.object({
|
||||||
|
identifier: z.string(),
|
||||||
|
}),
|
||||||
|
}),
|
||||||
|
use: [sessionMiddleware, referenceMiddleware("adjust-meter-event")],
|
||||||
|
},
|
||||||
|
async (ctx) => {
|
||||||
|
const bodyPayload = ctx.body
|
||||||
|
try {
|
||||||
|
const result = await client.v2.billing.meterEventAdjustments.create(bodyPayload);
|
||||||
|
|
||||||
|
return ctx.json(result);
|
||||||
|
} catch (error: any) {
|
||||||
|
ctx.context.logger.error(
|
||||||
|
"Error submitting meter event",
|
||||||
|
error,
|
||||||
|
);
|
||||||
|
throw new APIError("BAD_REQUEST", {
|
||||||
|
message: error.message,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
),
|
||||||
|
summaryBillingMeterEvent: createAuthEndpoint(
|
||||||
|
"/subscription/meter-event/summary", // https://docs.stripe.com/api/billing/meter-event-summary
|
||||||
|
{
|
||||||
|
method: "GET",
|
||||||
|
query: z.object({
|
||||||
|
id: z.string().meta({
|
||||||
|
description: "The id of the meter event, ie: 'mtr_test_61Q8nQMqIFK9fRQmr41CMAXJrFdZ5MnA'"
|
||||||
|
}),
|
||||||
|
start_time: z.number().meta({
|
||||||
|
description: "Unix timestamp in seconds"
|
||||||
|
}),
|
||||||
|
end_time: z.number().meta({
|
||||||
|
description: "Unix timestamp in seconds"
|
||||||
|
}),
|
||||||
|
value_grouping_window: z.enum(['day', 'hour']),
|
||||||
|
ending_before: z.string().optional().meta({
|
||||||
|
description: "A cursor for use in pagination"
|
||||||
|
}),
|
||||||
|
starting_after: z.string().optional().meta({
|
||||||
|
description: "A cursor for use in pagination"
|
||||||
|
}),
|
||||||
|
limit: z.number().optional().meta({
|
||||||
|
description: "A limit on the number of objects to be returned. Limit can range between 1 and 100, and the default is 10."
|
||||||
|
})
|
||||||
|
}),
|
||||||
|
use: [
|
||||||
|
sessionMiddleware,
|
||||||
|
referenceMiddleware("meter-event-summary"),
|
||||||
|
]
|
||||||
|
},
|
||||||
|
async (ctx) => {
|
||||||
|
const {user} = ctx.context.session;
|
||||||
|
let customerId = user.stripeCustomerId;
|
||||||
|
const referenceId = ctx.body.referenceId || user.id;
|
||||||
|
|
||||||
|
if (!customerId) {
|
||||||
|
const subscription = await ctx.context.adapter
|
||||||
|
.findMany<Subscription>({
|
||||||
|
model: "subscription",
|
||||||
|
where: [
|
||||||
|
{
|
||||||
|
field: "referenceId",
|
||||||
|
value: referenceId,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
})
|
||||||
|
.then((subs) =>
|
||||||
|
subs.find(
|
||||||
|
(sub) => sub.status === "active" || sub.status === "trialing",
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
customerId = subscription?.stripeCustomerId;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!customerId) {
|
||||||
|
throw new APIError("BAD_REQUEST", {
|
||||||
|
message: "No Stripe customer found for this user",
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
const result = await client.billing.meters.listEventSummaries(
|
||||||
|
ctx.query.id,
|
||||||
|
{
|
||||||
|
customer: customerId,
|
||||||
|
start_time: ctx.query.start_time,
|
||||||
|
end_time: ctx.query.end_time,
|
||||||
|
limit: ctx.query.limit,
|
||||||
|
starting_after: ctx.query.starting_after,
|
||||||
|
ending_before: ctx.query.ending_before,
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
return ctx.json(result);
|
||||||
|
} catch (error: any) {
|
||||||
|
ctx.context.logger.error(
|
||||||
|
"Error submitting meter event",
|
||||||
|
error,
|
||||||
|
);
|
||||||
|
throw new APIError("BAD_REQUEST", {
|
||||||
|
message: error.message,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
} as const;
|
} as const;
|
||||||
return {
|
return {
|
||||||
id: "stripe",
|
id: "stripe",
|
||||||
|
|||||||
21
src/types.ts
21
src/types.ts
@@ -90,6 +90,16 @@ export type StripePlan = {
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export type actionType =
|
||||||
|
| "upgrade-subscription"
|
||||||
|
| "list-subscription"
|
||||||
|
| "cancel-subscription"
|
||||||
|
| "restore-subscription"
|
||||||
|
| "meter-event"
|
||||||
|
| "adjust-meter-event"
|
||||||
|
| "meter-event-summary"
|
||||||
|
| "billing-portal";
|
||||||
|
|
||||||
export interface Subscription {
|
export interface Subscription {
|
||||||
/**
|
/**
|
||||||
* Database identifier
|
* Database identifier
|
||||||
@@ -267,13 +277,7 @@ export interface StripeOptions {
|
|||||||
user: User & Record<string, any>;
|
user: User & Record<string, any>;
|
||||||
session: Session & Record<string, any>;
|
session: Session & Record<string, any>;
|
||||||
referenceId: string;
|
referenceId: string;
|
||||||
action:
|
action: actionType;
|
||||||
| "upgrade-subscription"
|
|
||||||
| "list-subscription"
|
|
||||||
| "cancel-subscription"
|
|
||||||
| "restore-subscription"
|
|
||||||
| "meter-event"
|
|
||||||
| "billing-portal";
|
|
||||||
},
|
},
|
||||||
ctx: GenericEndpointContext,
|
ctx: GenericEndpointContext,
|
||||||
) => Promise<boolean>;
|
) => Promise<boolean>;
|
||||||
@@ -328,4 +332,5 @@ export interface StripeOptions {
|
|||||||
schema?: InferOptionSchema<typeof subscriptions & typeof user>;
|
schema?: InferOptionSchema<typeof subscriptions & typeof user>;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface InputSubscription extends Omit<Subscription, "id"> {}
|
export interface InputSubscription extends Omit<Subscription, "id"> {
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user