返回顶部
s

stripe-integration-expertStripe集成专家

Stripe Integration Expert

作者: admin | 来源: ClawHub
源自
ClawHub
版本
V 1.0.0
安全检测
已通过
294
下载量
免费
免费
0
收藏
概述
安装方式
版本历史

stripe-integration-expert

Stripe 集成专家

层级: 强大
类别: 工程团队
领域: 支付/计费基础设施



概述

实现生产级 Stripe 集成:含试用和按比例计算的订阅、一次性支付、基于使用量的计费、结账会话、幂等 Webhook 处理器、客户门户和发票开具。涵盖 Next.js、Express 和 Django 模式。



核心能力

  • - 订阅生命周期管理(创建、升级、降级、取消、暂停)
  • 试用处理与转化追踪
  • 按比例计算与信用额度应用
  • 基于使用量的计量定价计费
  • 带签名验证的幂等 Webhook 处理器
  • 客户门户集成
  • 发票生成与 PDF 访问
  • 完整的 Stripe CLI 本地测试环境搭建

使用场景

  • - 为任何 Web 应用添加订阅计费功能
  • 实现含按比例计算的套餐升级/降级
  • 构建基于使用量或席位数的计费系统
  • 调试 Webhook 投递失败问题
  • 从一种计费模型迁移到另一种

订阅生命周期状态机

免费试用 ──付费──► 活跃 ──取消──► 待取消 ──周期结束──► 已取消
│ │ │
│ 降级 重新激活
│ ▼ │
│ 降级中 ──周期结束──► 活跃(更低套餐) │
│ │
└──试用结束未付款──► 逾期 ──付款失败3次──► 已取消

付款成功


活跃

数据库订阅状态值:

trialing | active | pastdue | canceled | cancelpending | paused | unpaid

Stripe 客户端设置

typescript
// lib/stripe.ts
import Stripe from stripe

export const stripe = new Stripe(process.env.STRIPESECRETKEY!, {
apiVersion: 2024-04-10,
typescript: true,
appInfo: {
name: myapp,
version: 1.0.0,
},
})

// 按套餐的价格ID(在环境变量中设置)
export const PLANS = {
starter: {
monthly: process.env.STRIPESTARTERMONTHLYPRICEID!,
yearly: process.env.STRIPESTARTERYEARLYPRICEID!,
features: [5个项目, 1万次事件],
},
pro: {
monthly: process.env.STRIPEPROMONTHLYPRICEID!,
yearly: process.env.STRIPEPROYEARLYPRICEID!,
features: [无限项目, 100万次事件],
},
} as const



结账会话(Next.js App Router)

typescript
// app/api/billing/checkout/route.ts
import { NextResponse } from next/server
import { stripe } from @/lib/stripe
import { getAuthUser } from @/lib/auth
import { db } from @/lib/db

export async function POST(req: Request) {
const user = await getAuthUser()
if (!user) return NextResponse.json({ error: 未授权 }, { status: 401 })

const { priceId, interval = monthly } = await req.json()

// 获取或创建 Stripe 客户
let stripeCustomerId = user.stripeCustomerId
if (!stripeCustomerId) {
const customer = await stripe.customers.create({
email: user.email,
name: 用户名未定义,
metadata: { userId: user.id },
})
stripeCustomerId = customer.id
await db.user.update({ where: { id: user.id }, data: { stripeCustomerId } })
}

const session = await stripe.checkout.sessions.create({
customer: stripeCustomerId,
mode: subscription,
paymentmethodtypes: [card],
line_items: [{ price: priceId, quantity: 1 }],
allowpromotioncodes: true,
subscription_data: {
trialperioddays: user.hasHadTrial ? undefined : 14,
metadata: { userId: user.id },
},
successurl: ${process.env.NEXTPUBLICAPPURL}/dashboard?sessionid={CHECKOUTSESSION_ID},
cancelurl: ${process.env.NEXTPUBLICAPPURL}/pricing,
metadata: { userId: user.id },
})

return NextResponse.json({ url: session.url })
}



订阅升级/降级

typescript
// lib/billing.ts
export async function changeSubscriptionPlan(
subscriptionId: string,
newPriceId: string,
immediate = false
) {
const subscription = await stripe.subscriptions.retrieve(subscriptionId)
const currentItem = subscription.items.data[0]

if (immediate) {
// 升级:立即应用并计算按比例费用
return stripe.subscriptions.update(subscriptionId, {
items: [{ id: currentItem.id, price: newPriceId }],
prorationbehavior: alwaysinvoice,
billingcycleanchor: unchanged,
})
} else {
// 降级:在周期结束时应用,不计算按比例费用
return stripe.subscriptions.update(subscriptionId, {
items: [{ id: currentItem.id, price: newPriceId }],
proration_behavior: none,
billingcycleanchor: unchanged,
})
}
}

// 在确认升级前预览按比例费用
export async function previewProration(subscriptionId: string, newPriceId: string) {
const subscription = await stripe.subscriptions.retrieve(subscriptionId)
const prorationDate = Math.floor(Date.now() / 1000)

const invoice = await stripe.invoices.retrieveUpcoming({
customer: subscription.customer as string,
subscription: subscriptionId,
subscription_items: [{ id: subscription.items.data[0].id, price: newPriceId }],
subscriptionprorationdate: prorationDate,
})

return {
amountDue: invoice.amount_due,
prorationDate,
lineItems: invoice.lines.data,
}
}



完整的 Webhook 处理器(幂等)

typescript
// app/api/webhooks/stripe/route.ts
import { NextResponse } from next/server
import { headers } from next/headers
import { stripe } from @/lib/stripe
import { db } from @/lib/db
import Stripe from stripe

// 已处理事件表,确保幂等性
async function hasProcessedEvent(eventId: string): Promise {
const existing = await db.stripeEvent.findUnique({ where: { id: eventId } })
return !!existing
}

async function markEventProcessed(eventId: string, type: string) {
await db.stripeEvent.create({ data: { id: eventId, type, processedAt: new Date() } })
}

export async function POST(req: Request) {
const body = await req.text()
const signature = headers().get(stripe-signature)!

let event: Stripe.Event
try {
event = stripe.webhooks.constructEvent(body, signature, process.env.STRIPEWEBHOOKSECRET!)
} catch (err) {
console.error(Webhook 签名验证失败:, err)
return NextResponse.json({ error: 无效签名 }, { status: 400 })
}

// 幂等性检查
if (await hasProcessedEvent(event.id)) {
return NextResponse.json({ received: true, skipped: true })
}

try {
switch (event.type) {
case checkout.session.completed:
await handleCheckoutCompleted(event.data.object as Stripe.Checkout.Session)
break

case customer.subscription.created:
case customer.subscription.updated:
await handleSubscriptionUpdated(event.data.object as Stripe.Subscription)
break

case customer.subscription.deleted:
await handleSubscriptionDeleted(event.data.object as Stripe.Subscription)
break

case invoice.payment_succeeded:
await handleInvoicePaymentSucceeded(event.data.object as Stripe.Invoice)
break

case invoice.payment_failed:
await handleInvoicePaymentFailed(event.data.object as Stripe.Invoice)
break

default:
console.log(未处理的事件类型:${event.type})
}

await markEventProcessed(event.id, event.type)
return NextResponse.json({ received: true })
} catch (err) {
console.error(处理 Webhook ${event.type} 时出错:, err)
// 返回 500 让 Stripe 重试——不标记为已处理
return NextResponse.json({ error: 处理失败 }, { status: 500 })
}
}

async function handleCheckoutCompleted(session: Stripe.Checkout.Session) {
if (session.mode

标签

skill ai

通过对话安装

该技能支持在以下平台通过对话安装:

OpenClaw WorkBuddy QClaw Kimi Claude

方式一:安装 SkillHub 和技能

帮我安装 SkillHub 和 stripe-integration-expert-1776176172 技能

方式二:设置 SkillHub 为优先技能安装源

设置 SkillHub 为我的优先技能安装源,然后帮我安装 stripe-integration-expert-1776176172 技能

通过命令行安装

skillhub install stripe-integration-expert-1776176172

下载

⬇ 下载 stripe-integration-expert v1.0.0(免费)

文件大小: 4.88 KB | 发布时间: 2026-4-15 10:41

v1.0.0 最新 2026-4-15 10:41
Initial publish

Archiver·手机版·闲社网·闲社论坛·羊毛社区· 多链控股集团有限公司 · 苏ICP备2025199260号-1

Powered by Discuz! X5.0   © 2024-2025 闲社网·线报更新论坛·羊毛分享社区·http://xianshe.com

p2p_official_large
返回顶部