Lemon Squeezy API完全指南:在Next.js billing app中实现订阅CRUD操作

📅 2026/7/17 13:26:04 👁️ 阅读次数 📝 编程学习
Lemon Squeezy API完全指南:在Next.js billing app中实现订阅CRUD操作

Lemon Squeezy API完全指南:在Next.js billing app中实现订阅CRUD操作

【免费下载链接】nextjs-billingNext.js billing app with Lemon Squeezy项目地址: https://gitcode.com/gh_mirrors/ne/nextjs-billing

在当今的SaaS(软件即服务)时代,构建一个可靠的订阅计费系统是每个开发者面临的挑战。幸运的是,借助Lemon Squeezy API和Next.js框架,我们可以快速搭建一个功能完整的计费系统。本文将为你详细介绍如何在Next.js billing应用中实现订阅的创建、读取、更新和删除(CRUD)操作,让你轻松管理用户订阅生命周期。😊

为什么选择Lemon Squeezy与Next.js组合?

Lemon Squeezy作为一款现代化的支付处理平台,提供了简洁的API接口和丰富的订阅管理功能。结合Next.js 14的App Router架构,我们可以构建出高性能、SEO友好的订阅计费应用。这个组合特别适合初创公司和独立开发者,因为它降低了支付集成的复杂度,让你能专注于核心业务逻辑。

项目架构概览

我们的Next.js billing应用采用了分层架构设计,确保代码的清晰性和可维护性:

  • 前端层:使用React组件展示订阅计划和用户订阅状态
  • API层:处理Lemon Squeezy API调用和Webhook接收
  • 数据层:通过Drizzle ORM管理PostgreSQL数据库
  • 配置层:集中管理Lemon Squeezy认证和环境变量

环境配置与初始化

开始之前,我们需要配置Lemon Squeezy环境变量。在项目根目录的.env文件中,添加以下关键配置:

LEMONSQUEEZY_API_KEY=你的API密钥 LEMONSQUEEZY_STORE_ID=你的商店ID LEMONSQUEEZY_WEBHOOK_SECRET=你的Webhook密钥 WEBHOOK_URL=你的Webhook接收地址 POSTGRES_URL=你的数据库连接字符串

在src/config/lemonsqueezy.ts中,我们配置了Lemon Squeezy SDK的初始化函数:

export function configureLemonSqueezy() { lemonSqueezySetup({ apiKey: process.env.LEMONSQUEEZY_API_KEY, onError: (error) => { console.error(error); throw new Error(`Lemon Squeezy API error: ${error.message}`); }, }); }

数据库模型设计

订阅系统的核心是数据模型。在src/db/schema.ts中,我们定义了以下关键表结构:

订阅计划表(plans)

存储Lemon Squeezy中的产品变体信息,包括价格、计费周期、试用期等。

用户订阅表(subscriptions)

跟踪用户的订阅状态,包含订阅ID、订单ID、状态、续费日期等关键字段。

Webhook事件表(webhookEvents)

记录所有从Lemon Squeezy接收的Webhook事件,确保事件处理的可靠性。

实现订阅CRUD操作

1. 创建订阅(Create)

创建订阅的核心是生成结账链接。在src/app/actions.ts中,getCheckoutURL函数负责这一过程:

export async function getCheckoutURL(variantId: number, embed = false) { configureLemonSqueezy(); const checkout = await createCheckout( process.env.LEMONSQUEEZY_STORE_ID!, variantId, { checkoutOptions: { embed, media: false, logo: !embed }, checkoutData: { email: session.user.email ?? undefined, custom: { user_id: session.user.id }, }, productOptions: { enabledVariants: [variantId], redirectUrl: `${process.env.NEXT_PUBLIC_APP_URL}/dashboard/billing/`, receiptButtonText: "Go to Dashboard", receiptThankYouNote: "Thank you for signing up!", }, }, ); return checkout.data?.data.attributes.url; }

这个函数会生成一个独特的结账URL,用户点击后可以完成订阅购买流程。

2. 读取订阅(Read)

获取用户订阅信息是计费面板的核心功能。getUserSubscriptions函数从数据库中查询当前用户的所有订阅:

export async function getUserSubscriptions() { const session = await auth(); if (!session?.user) { return []; } return await db .select() .from(subscriptions) .where(eq(subscriptions.userId, session.user.id)); }

在src/components/dashboard/billing/subscription/subscriptions.tsx组件中,订阅信息被优雅地展示给用户,包括状态、价格、续费日期等关键信息。

3. 更新订阅(Update)

订阅更新主要包括两个操作:暂停订阅和更改订阅计划。

暂停订阅

pauseUserSubscription函数允许用户临时暂停订阅:

export async function pauseUserSubscription(id: string) { configureLemonSqueezy(); const pausedSub = await updateSubscription(id, { pause: { mode: "void" }, }); // 更新数据库中的订阅状态 await db .update(subscriptions) .set({ isPaused: true, status: pausedSub.data.data.attributes.status, statusFormatted: pausedSub.data.data.attributes.status_formatted, }) .where(eq(subscriptions.lemonSqueezyId, id)); }
更改订阅计划

changePlan函数处理用户升级或降级订阅计划的需求:

export async function changePlan(currentPlanId: number, newPlanId: number) { // 获取当前订阅和新计划信息 // 调用Lemon Squeezy API更新订阅 // 同步更新本地数据库 }

4. 删除订阅(Delete)

取消订阅是订阅生命周期的重要环节。cancelSub函数处理订阅取消逻辑:

export async function cancelSub(id: string) { configureLemonSqueezy(); const cancelledSub = await cancelSubscription(id); if (cancelledSub.error) { throw new Error(cancelledSub.error.message); } // 更新数据库中的订阅状态 await db .update(subscriptions) .set({ status: cancelledSub.data.data.attributes.status, statusFormatted: cancelledSub.data.data.attributes.status_formatted, endsAt: cancelledSub.data.data.attributes.ends_at, }) .where(eq(subscriptions.lemonSqueezyId, id)); revalidatePath("/"); return cancelledSub; }

Webhook事件处理

Webhook是Lemon Squeezy与你的应用实时同步的关键机制。在src/app/api/webhook/route.ts中,我们实现了安全的Webhook接收端点:

安全性验证

// 验证请求签名 const hmac = Buffer.from( crypto.createHmac("sha256", secret).update(rawBody).digest("hex"), "hex", ); if (!crypto.timingSafeEqual(hmac, signature)) { return new Response("Invalid signature", { status: 400 }); }

事件处理

processWebhookEvent函数处理不同类型的订阅事件:

if (webhookEvent.eventName.startsWith("subscription_")) { // 处理订阅创建、更新等事件 const updateData: NewSubscription = { lemonSqueezyId: eventBody.data.id, orderId: attributes.order_id as number, name: attributes.user_name as string, email: attributes.user_email as string, status: attributes.status as string, // ... 其他字段 }; // 创建或更新数据库记录 await db.insert(subscriptions).values(updateData).onConflictDoUpdate({ target: subscriptions.lemonSqueezyId, set: updateData, }); }

订阅计划同步

保持本地计划数据与Lemon Squeezy同步至关重要。syncPlans函数从Lemon Squeezy API获取所有产品变体并更新本地数据库:

export async function syncPlans() { configureLemonSqueezy(); // 获取Lemon Squeezy中的所有产品 const products = await getAllProducts({ filter: { storeId: process.env.LEMONSQUEEZY_STORE_ID }, include: ["variants"], }); // 遍历产品并同步变体信息 for (const product of products.data?.data ?? []) { const variants = product.relationships.variants.data; for (const variant of variants) { const variantData = await getVariant(variant.id); // 将变体信息保存到数据库 await _addVariant({ productId: product.id, productName: product.attributes.name, variantId: variantData.data.data.id, name: variantData.data.data.attributes.name, // ... 其他字段 }); } } }

最佳实践与优化建议

1. 错误处理与日志记录

始终在关键操作中添加适当的错误处理和日志记录,特别是在API调用和数据库操作中。

2. 数据一致性

使用数据库事务确保数据的一致性,特别是在处理Webhook事件时。

3. 性能优化

  • 实现订阅数据的缓存机制
  • 使用增量同步减少API调用
  • 优化数据库查询索引

4. 安全性考虑

  • 验证所有用户输入
  • 实施速率限制防止滥用
  • 定期轮换API密钥

部署与生产环境准备

1. 环境配置

确保生产环境正确配置所有必要的环境变量,特别是:

  • 生产环境的Lemon Squeezy API密钥
  • 正确的Webhook URL和密钥
  • 生产数据库连接字符串

2. Webhook设置

在生产环境的Lemon Squeezy商店中配置Webhook,至少订阅以下事件:

  • subscription_created
  • subscription_updated
  • subscription_payment_success

3. 监控与告警

设置监控系统跟踪:

  • Webhook接收成功率
  • 订阅同步状态
  • API调用错误率

总结

通过本文的指导,你已经掌握了在Next.js应用中集成Lemon Squeezy API实现完整订阅CRUD操作的核心技术。从环境配置到数据库设计,从订阅管理到Webhook处理,每个环节都经过精心设计和实现。

这个Next.js billing应用模板为你提供了一个坚实的起点,你可以基于此构建更复杂的计费逻辑,如:

  • 使用量计费(usage-based billing)
  • 多货币支持
  • 优惠券和折扣系统
  • 发票和收据管理

记住,良好的订阅管理不仅仅是技术实现,更是用户体验的重要组成部分。通过清晰的订阅状态展示、便捷的操作界面和可靠的事件处理,你可以为用户提供优质的计费体验。

现在,你已经具备了构建专业级SaaS订阅系统的能力。开始使用这个模板,将你的创意转化为可持续的商业模式吧!🚀

【免费下载链接】nextjs-billingNext.js billing app with Lemon Squeezy项目地址: https://gitcode.com/gh_mirrors/ne/nextjs-billing

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考