🐛 Fix licensing checkout and webhook (#1731)

This commit is contained in:
Luke Vella 2025-05-26 19:07:17 +01:00 committed by GitHub
parent 518b66aa9a
commit 3ae7f7e021
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
7 changed files with 30 additions and 31 deletions

View file

@ -46,15 +46,8 @@ if (env.LICENSE_API_AUTH_TOKEN) {
}),
),
async (c) => {
const {
type,
seats,
expiresAt,
licenseeEmail,
licenseeName,
version,
stripeCustomerId,
} = c.req.valid("json");
const { type, seats, expiresAt, licenseeEmail, licenseeName, version } =
c.req.valid("json");
try {
const license = await prisma.license.create({
@ -67,7 +60,6 @@ if (env.LICENSE_API_AUTH_TOKEN) {
expiresAt,
licenseeEmail,
licenseeName,
stripeCustomerId,
},
});
return c.json({

View file

@ -63,6 +63,7 @@ export async function GET(request: NextRequest) {
success_url: "https://rallly.co/licensing/thank-you",
metadata: {
licenseType: type,
version: 4,
seats,
} satisfies LicenseCheckoutMetadata,
});

View file

@ -1,3 +1,4 @@
import { env } from "@/env";
import { licensingClient } from "@/features/licensing/client";
import { licenseCheckoutMetadataSchema } from "@/features/licensing/schema";
import { subscriptionCheckoutMetadataSchema } from "@/features/subscription/schema";
@ -38,10 +39,11 @@ async function handleSelfHostedCheckoutSessionCompleted(
if (!success) {
// If there is no metadata than this is likely a donation from a payment link
console.info("No metadata found for session: ", checkoutSession.id);
return;
}
const { licenseType, seats } = data;
const { licenseType, version, seats } = data;
const customerDetails = checkoutSession.customer_details;
@ -63,13 +65,13 @@ async function handleSelfHostedCheckoutSessionCompleted(
type: licenseType,
licenseeEmail: email,
licenseeName: customerDetails.name ?? undefined,
version,
seats,
stripeCustomerId: checkoutSession.customer as string,
});
if (!license || !license.data) {
throw new Error(
`Failed to create team license for session: ${checkoutSession.id} - ${license?.error}`,
`Failed to create license for session: ${checkoutSession.id} - ${license?.error}`,
);
}
@ -79,7 +81,7 @@ async function handleSelfHostedCheckoutSessionCompleted(
to: email,
from: {
name: "Luke from Rallly",
address: process.env.SUPPORT_EMAIL,
address: env.SUPPORT_EMAIL,
},
props: {
licenseKey: license.data.key,

View file

@ -10,7 +10,7 @@ export class LicensingClient {
authToken?: string;
constructor({
apiUrl = "https://licensing.rallly.co",
apiUrl = "https://licensing.rallly.co/api/licensing/v1",
authToken,
}: {
apiUrl?: string;
@ -24,7 +24,7 @@ export class LicensingClient {
throw new Error("Licensing API auth token is not configured.");
}
const res = await fetch(`${this.apiUrl}/api/v1/licenses`, {
const res = await fetch(`${this.apiUrl}/licenses`, {
method: "POST",
headers: {
"Content-Type": "application/json",
@ -39,16 +39,13 @@ export class LicensingClient {
return createLicenseResponseSchema.parse(await res.json());
}
async validateLicenseKey(input: ValidateLicenseInputKeySchema) {
const res = await fetch(
`${this.apiUrl}/api/v1/licenses/actions/validate-key`,
{
const res = await fetch(`${this.apiUrl}/licenses/actions/validate-key`, {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify(input),
},
);
});
if (!res.ok) {
throw new Error("Failed to validate license key.");

View file

@ -31,12 +31,11 @@ export type ApiResponse<T> = {
export const createLicenseInputSchema = z.object({
type: licenseTypeSchema,
seats: z.number().optional(),
expiresAt: z.date().optional(),
seats: z.coerce.number().optional(),
expiresAt: z.coerce.date().optional(),
licenseeEmail: z.string().optional(),
licenseeName: z.string().optional(),
version: z.number().optional(),
stripeCustomerId: z.string().optional(),
version: z.coerce.number().optional(),
});
export type CreateLicenseInput = z.infer<typeof createLicenseInputSchema>;
@ -80,7 +79,8 @@ export type ValidateLicenseKeyResponse = z.infer<
export const licenseCheckoutMetadataSchema = z.object({
licenseType: licenseTypeSchema,
seats: z.number(),
version: z.coerce.number(),
seats: z.coerce.number(),
});
export type LicenseCheckoutMetadata = z.infer<

View file

@ -0,0 +1,8 @@
/*
Warnings:
- You are about to drop the column `stripe_customer_id` on the `licenses` table. All the data in the column will be lost.
*/
-- AlterTable
ALTER TABLE "licenses" DROP COLUMN "stripe_customer_id";

View file

@ -20,7 +20,6 @@ model License {
licenseeEmail String? @map("licensee_email")
licenseeName String? @map("licensee_name")
status LicenseStatus @default(ACTIVE) @map("status")
stripeCustomerId String? @map("stripe_customer_id")
validations LicenseValidation[]