redirect back after checkout

This commit is contained in:
Shawn Erquhart
2025-03-03 11:47:45 -05:00
parent 29e1297ab0
commit 3078dc6794
3 changed files with 9 additions and 22 deletions

View File

@@ -1,6 +1,6 @@
import { Polar } from "@convex-dev/polar"; import { Polar } from "@convex-dev/polar";
import { api, components } from "./_generated/api"; import { api, components } from "./_generated/api";
import { QueryCtx, mutation, query, action } from "./_generated/server"; import { QueryCtx, mutation, query } from "./_generated/server";
import { v } from "convex/values"; import { v } from "convex/values";
import { Id } from "./_generated/dataModel"; import { Id } from "./_generated/dataModel";
@@ -43,27 +43,8 @@ export const {
listAllProducts, listAllProducts,
} = polar.api(); } = polar.api();
export const { generateCustomerPortalUrl } = polar.checkoutApi(); export const { generateCustomerPortalUrl, generateCheckoutLink } =
polar.checkoutApi();
// Custom implementation of generateCheckoutLink that accepts a productKey
export const generateCheckoutLink = action({
args: {
productIds: v.array(v.string()),
origin: v.string(),
},
handler: async (ctx, args) => {
const user = await ctx.runQuery(api.example.getCurrentUser);
if (!user) throw new Error("No user found");
const session = await polar.createCheckoutSession(ctx, {
productIds: args.productIds,
userId: user._id,
email: user.email,
origin: args.origin,
});
return { url: session.url };
},
});
// In a real app you'll set up authentication, we just use a // In a real app you'll set up authentication, we just use a
// fake user for the example. // fake user for the example.

View File

@@ -95,11 +95,13 @@ export class Polar<
userId, userId,
email, email,
origin, origin,
successUrl,
}: { }: {
productIds: string[]; productIds: string[];
userId: string; userId: string;
email: string; email: string;
origin: string; origin: string;
successUrl: string;
} }
): Promise<Checkout> { ): Promise<Checkout> {
const dbCustomer = await ctx.runQuery( const dbCustomer = await ctx.runQuery(
@@ -128,6 +130,7 @@ export class Polar<
allowDiscountCodes: true, allowDiscountCodes: true,
customerId, customerId,
embedOrigin: origin, embedOrigin: origin,
successUrl,
...(productIds.length === 1 ...(productIds.length === 1
? { productId: productIds[0] } ? { productId: productIds[0] }
: { products: productIds }), : { products: productIds }),
@@ -275,6 +278,7 @@ export class Polar<
args: { args: {
productIds: v.array(v.string()), productIds: v.array(v.string()),
origin: v.string(), origin: v.string(),
successUrl: v.string(),
}, },
returns: v.object({ returns: v.object({
url: v.string(), url: v.string(),
@@ -286,6 +290,7 @@ export class Polar<
userId, userId,
email, email,
origin: args.origin, origin: args.origin,
successUrl: args.successUrl,
}); });
return { url }; return { url };
}, },

View File

@@ -59,6 +59,7 @@ export const CheckoutLink = ({
void generateCheckoutLink({ void generateCheckoutLink({
productIds, productIds,
origin: window.location.origin, origin: window.location.origin,
successUrl: window.location.href,
}).then(({ url }) => setCheckoutLink(url)); }).then(({ url }) => setCheckoutLink(url));
}, [productIds]); }, [productIds]);