Skip to content

Creem 支付集成指南

Creem 是一个专为独立开发者和小团队设计的支付平台,类似于 LemonSqueezy、Paddle。主打简单易用,帮助开发者快速接入支付功能,无需担心税务合规问题。

为什么选择 Creem#

特性说明
开发者友好简洁的 API,快速集成
税务托管自动处理增值税、销售税
无主体限制个人开发者可直接使用
全球支付支持多种货币和支付方式
订阅管理内置订阅计费功能

快速开始#

1. 注册账户#

  1. 访问 creem.io
  2. 创建账户并完成验证
  3. 添加收款方式(银行账户/PayPal)

2. 创建产品#

Dashboard → Products → Create Product

名称: Pro Plan
描述: 专业版订阅
定价: $19/月
类型: 订阅 或 一次性

3. 获取 API 密钥#

Settings → API Keys

API Key: creem_xxxxx
Webhook Secret: whsec_xxxxx

Checkout 集成#

创建 Checkout 会话#

app/api/checkout/route.ts
export async function POST(req: Request) {
const { productId, email } = await req.json()
const response = await fetch('https://api.creem.io/v1/checkouts', {
method: 'POST',
headers: {
'Authorization': `Bearer ${process.env.CREEM_API_KEY}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
product_id: productId,
customer_email: email,
success_url: `${process.env.NEXT_PUBLIC_URL}/success`,
cancel_url: `${process.env.NEXT_PUBLIC_URL}/cancel`,
}),
})
const data = await response.json()
return Response.json({ url: data.url })
}

客户端跳转#

async function handleCheckout() {
const response = await fetch('/api/checkout', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
productId: 'prod_xxx',
email: user.email,
}),
})
const { url } = await response.json()
window.location.href = url
}

Checkout 链接#

也可以直接使用产品的 Checkout 链接:

https://checkout.creem.io/p/prod_xxx?email=user@example.com

订阅管理#

获取订阅状态#

async function getSubscription(subscriptionId: string) {
const response = await fetch(
`https://api.creem.io/v1/subscriptions/${subscriptionId}`,
{
headers: {
Authorization: `Bearer ${process.env.CREEM_API_KEY}`,
},
}
)
return response.json()
}

取消订阅#

async function cancelSubscription(subscriptionId: string) {
await fetch(
`https://api.creem.io/v1/subscriptions/${subscriptionId}/cancel`,
{
method: 'POST',
headers: {
Authorization: `Bearer ${process.env.CREEM_API_KEY}`,
},
}
)
}

客户门户#

让用户自助管理订阅:

async function getPortalUrl(customerId: string) {
const response = await fetch(
'https://api.creem.io/v1/billing-portal/sessions',
{
method: 'POST',
headers: {
'Authorization': `Bearer ${process.env.CREEM_API_KEY}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
customer_id: customerId,
return_url: `${process.env.NEXT_PUBLIC_URL}/account`,
}),
}
)
const data = await response.json()
return data.url
}

Webhook 处理#

配置 Webhook#

Settings → Webhooks → Add Endpoint

URL: https://your-domain.com/api/webhook
Events: checkout.completed, subscription.updated, ...

处理事件#

app/api/webhook/route.ts
import crypto from 'crypto'
export async function POST(req: Request) {
const body = await req.text()
const signature = req.headers.get('creem-signature')
// 验证签名
const expectedSignature = crypto
.createHmac('sha256', process.env.CREEM_WEBHOOK_SECRET!)
.update(body)
.digest('hex')
if (signature !== expectedSignature) {
return new Response('Invalid signature', { status: 400 })
}
const event = JSON.parse(body)
switch (event.type) {
case 'checkout.completed':
await handleCheckoutCompleted(event.data)
break
case 'subscription.created':
await handleSubscriptionCreated(event.data)
break
case 'subscription.updated':
await handleSubscriptionUpdated(event.data)
break
case 'subscription.canceled':
await handleSubscriptionCanceled(event.data)
break
case 'payment.failed':
await handlePaymentFailed(event.data)
break
}
return new Response('OK')
}

常用事件#

事件触发时机
checkout.completed支付成功
subscription.created新建订阅
subscription.updated订阅更新
subscription.canceled订阅取消
payment.succeeded付款成功
payment.failed付款失败

实战示例#

Next.js 完整集成#

lib/creem.ts
const CREEM_API_URL = 'https://api.creem.io/v1'
export async function createCheckout(productId: string, email: string) {
const response = await fetch(`${CREEM_API_URL}/checkouts`, {
method: 'POST',
headers: {
'Authorization': `Bearer ${process.env.CREEM_API_KEY}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
product_id: productId,
customer_email: email,
success_url: `${process.env.NEXT_PUBLIC_URL}/success`,
cancel_url: `${process.env.NEXT_PUBLIC_URL}/pricing`,
}),
})
if (!response.ok) {
throw new Error('Failed to create checkout')
}
return response.json()
}
export async function getCustomerSubscriptions(customerId: string) {
const response = await fetch(
`${CREEM_API_URL}/customers/${customerId}/subscriptions`,
{
headers: {
Authorization: `Bearer ${process.env.CREEM_API_KEY}`,
},
}
)
return response.json()
}

定价页面#

app/pricing/page.tsx
'use client'
import { useState } from 'react'
const plans = [
{ id: 'prod_free', name: 'Free', price: 0, features: ['基础功能'] },
{ id: 'prod_pro', name: 'Pro', price: 19, features: ['全部功能', '优先支持'] },
]
export default function PricingPage() {
const [loading, setLoading] = useState<string | null>(null)
async function handleSubscribe(productId: string) {
setLoading(productId)
const response = await fetch('/api/checkout', {
method: 'POST',
body: JSON.stringify({ productId }),
})
const { url } = await response.json()
window.location.href = url
}
return (
<div className="grid grid-cols-2 gap-4">
{plans.map((plan) => (
<div key={plan.id} className="border p-6 rounded-lg">
<h3>{plan.name}</h3>
<p>${plan.price}/</p>
<ul>
{plan.features.map((f) => (
<li key={f}>{f}</li>
))}
</ul>
<button
onClick={() => handleSubscribe(plan.id)}
disabled={loading === plan.id}
>
{loading === plan.id ? '处理中...' : '订阅'}
</button>
</div>
))}
</div>
)
}

Creem vs LemonSqueezy vs Paddle#

特性CreemLemonSqueezyPaddle
目标用户独立开发者独立开发者SaaS 公司
费率5% + $0.55% + $0.55-8%
税务处理
订阅管理
客户门户
API 复杂度简单中等复杂
文档质量优秀优秀

选择建议

最佳实践#

1. 存储客户信息#

// 在数据库中关联 Creem 客户 ID
await db.user.update({
where: { id: userId },
data: {
creemCustomerId: event.data.customer_id,
subscriptionId: event.data.subscription_id,
subscriptionStatus: 'active',
},
})

2. 处理支付失败#

async function handlePaymentFailed(data) {
// 发送提醒邮件
await sendEmail(data.customer_email, {
subject: '支付失败提醒',
body: '您的订阅付款失败,请更新支付方式。',
})
// 更新用户状态
await db.user.update({
where: { creemCustomerId: data.customer_id },
data: { subscriptionStatus: 'past_due' },
})
}

3. 验证 Webhook 签名#

始终验证签名,防止伪造请求。

常见问题#

支持哪些支付方式?#

如何处理退款?#

Dashboard 中手动处理,或通过 API:

await fetch(`https://api.creem.io/v1/payments/${paymentId}/refund`, {
method: 'POST',
headers: {
Authorization: `Bearer ${process.env.CREEM_API_KEY}`,
},
})

收款周期是多久?#

通常 7-14 个工作日到账,具体取决于收款方式。

参考资料#