dodo-best-practices
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseDodo Payments Integration Guide
Dodo Payments 集成指南
Always consult docs.dodopayments.com for the latest API reference and code examples.
Dodo Payments is the all-in-one engine to launch, scale, and monetize worldwide. Designed for SaaS and AI products, it handles payments, billing, subscriptions, and distribution without extra engineering.
请始终参考docs.dodopayments.com获取最新的API参考文档和代码示例。
Dodo Payments 是一款一站式引擎,助力全球范围内的产品上线、规模化运营与变现。专为SaaS和AI产品设计,无需额外工程投入即可处理支付、计费、订阅与分发事宜。
Quick Reference
快速参考
Environment Variables
环境变量
- - Your API key from the dashboard
DODO_PAYMENTS_API_KEY - - Webhook signing secret for verification
DODO_PAYMENTS_WEBHOOK_SECRET
- - 从控制台获取的API密钥
DODO_PAYMENTS_API_KEY - - 用于验证的Webhook签名密钥
DODO_PAYMENTS_WEBHOOK_SECRET
API Environments
API环境
- Live Mode: (default)
https://api.dodopayments.com - Test Mode: with
https://api.dodopayments.comenvironment: 'test_mode'
- 生产模式:(默认)
https://api.dodopayments.com - 测试模式:,需设置
https://api.dodopayments.comenvironment: 'test_mode'
Dashboard URLs
控制台链接
- Main Dashboard: app.dodopayments.com
- API Keys: Dashboard → Developer → API
- Webhooks: Dashboard → Developer → Webhooks
- Products: Dashboard → Products
- 主控制台:app.dodopayments.com
- API密钥:控制台 → 开发者 → API
- Webhook:控制台 → 开发者 → Webhooks
- 产品:控制台 → 产品
SDK Installation
SDK安装
TypeScript/JavaScript
TypeScript/JavaScript
bash
npm install dodopaymentsbash
npm install dodopaymentsor
or
yarn add dodopayments
yarn add dodopayments
or
or
pnpm add dodopayments
```typescript
import DodoPayments from 'dodopayments';
const client = new DodoPayments({
bearerToken: process.env.DODO_PAYMENTS_API_KEY,
environment: 'live_mode', // or 'test_mode'
});pnpm add dodopayments
```typescript
import DodoPayments from 'dodopayments';
const client = new DodoPayments({
bearerToken: process.env.DODO_PAYMENTS_API_KEY,
environment: 'live_mode', // or 'test_mode'
});Python
Python
bash
pip install dodopaymentspython
from dodopayments import DodoPayments
client = DodoPayments(bearer_token=os.environ["DODO_PAYMENTS_API_KEY"])bash
pip install dodopaymentspython
from dodopayments import DodoPayments
client = DodoPayments(bearer_token=os.environ["DODO_PAYMENTS_API_KEY"])Go
Go
bash
go get github.com/dodopayments/dodopayments-gogo
import "github.com/dodopayments/dodopayments-go"
client := dodopayments.NewClient(
option.WithBearerToken(os.Getenv("DODO_PAYMENTS_API_KEY")),
)bash
go get github.com/dodopayments/dodopayments-gogo
import "github.com/dodopayments/dodopayments-go"
client := dodopayments.NewClient(
option.WithBearerToken(os.Getenv("DODO_PAYMENTS_API_KEY")),
)PHP
PHP
bash
composer require dodopayments/clientphp
use Dodopayments\Client;
$client = new Client(bearerToken: getenv('DODO_PAYMENTS_API_KEY'));bash
composer require dodopayments/clientphp
use Dodopayments\Client;
$client = new Client(bearerToken: getenv('DODO_PAYMENTS_API_KEY'));Core Concepts
核心概念
Products
产品
Products are the items you sell. Create them in the dashboard or via API:
- One-time: Single purchase products
- Subscription: Recurring billing products
产品是您销售的商品。可在控制台或通过API创建:
- 一次性产品:单次购买的产品
- 订阅产品:定期计费的产品
Checkout Sessions
结账会话
The primary way to collect payments. Create a checkout session and redirect customers:
typescript
const session = await client.checkoutSessions.create({
product_cart: [
{ product_id: 'prod_xxxxx', quantity: 1 }
],
customer: {
email: 'customer@example.com',
name: 'John Doe',
},
return_url: 'https://yoursite.com/success',
});
// Redirect customer to: session.checkout_url这是收取付款的主要方式。创建结账会话并将客户重定向至对应页面:
typescript
const session = await client.checkoutSessions.create({
product_cart: [
{ product_id: 'prod_xxxxx', quantity: 1 }
],
customer: {
email: 'customer@example.com',
name: 'John Doe',
},
return_url: 'https://yoursite.com/success',
});
// 重定向客户至:session.checkout_urlWebhooks
Webhook
Listen to events for real-time updates:
- - Payment completed
payment.succeeded - - Payment failed
payment.failed - - Subscription activated
subscription.active - - Subscription cancelled
subscription.cancelled - - Refund processed
refund.succeeded - - Dispute received
dispute.opened - - License key generated
license_key.created
监听事件以获取实时更新:
- - 付款完成
payment.succeeded - - 付款失败
payment.failed - - 订阅已激活
subscription.active - - 订阅已取消
subscription.cancelled - - 退款已处理
refund.succeeded - - 收到争议请求
dispute.opened - - 生成许可证密钥
license_key.created
Common Integration Patterns
常见集成模式
One-Time Payment Flow
一次性付款流程
- Create product in dashboard
- Create checkout session with product ID
- Redirect customer to checkout URL
- Handle webhook
payment.succeeded - Fulfill order / grant access
typescript
// Create checkout for one-time payment
const session = await client.checkoutSessions.create({
product_cart: [{ product_id: 'prod_one_time_product', quantity: 1 }],
customer: { email: 'customer@example.com' },
return_url: 'https://yoursite.com/success',
});- 在控制台创建产品
- 使用产品ID创建结账会话
- 将客户重定向至结账URL
- 处理Webhook事件
payment.succeeded - 履行订单 / 授予访问权限
typescript
// 创建一次性付款的结账会话
const session = await client.checkoutSessions.create({
product_cart: [{ product_id: 'prod_one_time_product', quantity: 1 }],
customer: { email: 'customer@example.com' },
return_url: 'https://yoursite.com/success',
});Subscription Flow
订阅流程
- Create subscription product in dashboard
- Create checkout session
- Handle webhook to grant access
subscription.active - Handle to revoke access
subscription.cancelled
typescript
// Create checkout for subscription
const session = await client.checkoutSessions.create({
product_cart: [{ product_id: 'prod_monthly_subscription', quantity: 1 }],
subscription_data: { trial_period_days: 14 }, // Optional trial
customer: { email: 'customer@example.com' },
return_url: 'https://yoursite.com/success',
});- 在控制台创建订阅产品
- 创建结账会话
- 处理Webhook事件以授予访问权限
subscription.active - 处理事件以收回访问权限
subscription.cancelled
typescript
// 创建订阅的结账会话
const session = await client.checkoutSessions.create({
product_cart: [{ product_id: 'prod_monthly_subscription', quantity: 1 }],
subscription_data: { trial_period_days: 14 }, // 可选试用期
customer: { email: 'customer@example.com' },
return_url: 'https://yoursite.com/success',
});Webhook Verification
Webhook验证
Always verify webhook signatures:
typescript
import crypto from 'crypto';
function verifyWebhook(payload: string, signature: string, secret: string): boolean {
const expectedSignature = crypto
.createHmac('sha256', secret)
.update(payload)
.digest('hex');
return crypto.timingSafeEqual(
Buffer.from(signature),
Buffer.from(expectedSignature)
);
}务必验证Webhook签名:
typescript
import crypto from 'crypto';
function verifyWebhook(payload: string, signature: string, secret: string): boolean {
const expectedSignature = crypto
.createHmac('sha256', secret)
.update(payload)
.digest('hex');
return crypto.timingSafeEqual(
Buffer.from(signature),
Buffer.from(expectedSignature)
);
}API Key Management
API密钥管理
Generation
生成步骤
- Navigate to Dashboard → Developer → API
- Click "Create API Key"
- Copy and securely store the key
- 导航至控制台 → 开发者 → API
- 点击"创建API密钥"
- 复制并安全存储密钥
Security Best Practices
安全最佳实践
- Never expose API keys in client-side code
- Use environment variables
- Rotate keys periodically
- Use test mode keys for development
- 切勿在客户端代码中暴露API密钥
- 使用环境变量存储密钥
- 定期轮换密钥
- 开发时使用测试模式密钥
Customer Portal
客户门户
Allow customers to manage their subscriptions:
typescript
const portal = await client.customers.createPortalSession({
customer_id: 'cust_xxxxx',
return_url: 'https://yoursite.com/account',
});
// Redirect to: portal.url允许客户管理他们的订阅:
typescript
const portal = await client.customers.createPortalSession({
customer_id: 'cust_xxxxx',
return_url: 'https://yoursite.com/account',
});
// 重定向至:portal.urlError Handling
错误处理
Handle API errors gracefully:
typescript
try {
const session = await client.checkoutSessions.create({...});
} catch (error) {
if (error.status === 400) {
// Invalid request - check parameters
} else if (error.status === 401) {
// Invalid API key
} else if (error.status === 429) {
// Rate limited - implement backoff
}
}优雅地处理API错误:
typescript
try {
const session = await client.checkoutSessions.create({...});
} catch (error) {
if (error.status === 400) {
// 请求无效 - 检查参数
} else if (error.status === 401) {
// API密钥无效
} else if (error.status === 429) {
// 请求超限 - 实现退避机制
}
}Testing
测试
Test Mode
测试模式
- Use test API keys (start with )
sk_test_ - Test webhooks with dashboard tools
- Use test card numbers:
- - Success
4242 4242 4242 4242 - - Decline
4000 0000 0000 0002
- 使用测试API密钥(以开头)
sk_test_ - 使用控制台工具测试Webhook
- 使用测试卡号:
- - 付款成功
4242 4242 4242 4242 - - 付款被拒绝
4000 0000 0000 0002
Local Development
本地开发
Use ngrok or similar for webhook testing:
bash
ngrok http 3000Then configure the ngrok URL as your webhook endpoint in the dashboard.
使用ngrok或类似工具进行Webhook测试:
bash
ngrok http 3000然后在控制台中将ngrok URL配置为您的Webhook端点。
Framework Integration
框架集成
Next.js
Next.js
Use API routes for server-side operations:
typescript
// app/api/checkout/route.ts
import { NextResponse } from 'next/server';
import DodoPayments from 'dodopayments';
const client = new DodoPayments({
bearerToken: process.env.DODO_PAYMENTS_API_KEY!,
});
export async function POST(req: Request) {
const { productId, email } = await req.json();
const session = await client.checkoutSessions.create({
product_cart: [{ product_id: productId, quantity: 1 }],
customer: { email },
return_url: `${process.env.NEXT_PUBLIC_URL}/success`,
});
return NextResponse.json({ url: session.checkout_url });
}使用API路由处理服务器端操作:
typescript
// app/api/checkout/route.ts
import { NextResponse } from 'next/server';
import DodoPayments from 'dodopayments';
const client = new DodoPayments({
bearerToken: process.env.DODO_PAYMENTS_API_KEY!,
});
export async function POST(req: Request) {
const { productId, email } = await req.json();
const session = await client.checkoutSessions.create({
product_cart: [{ product_id: productId, quantity: 1 }],
customer: { email },
return_url: `${process.env.NEXT_PUBLIC_URL}/success`,
});
return NextResponse.json({ url: session.checkout_url });
}Express.js
Express.js
typescript
import express from 'express';
import DodoPayments from 'dodopayments';
const app = express();
const client = new DodoPayments({ bearerToken: process.env.DODO_PAYMENTS_API_KEY! });
app.post('/create-checkout', async (req, res) => {
const session = await client.checkoutSessions.create({
product_cart: [{ product_id: req.body.productId, quantity: 1 }],
customer: { email: req.body.email },
return_url: 'https://yoursite.com/success',
});
res.json({ url: session.checkout_url });
});typescript
import express from 'express';
import DodoPayments from 'dodopayments';
const app = express();
const client = new DodoPayments({ bearerToken: process.env.DODO_PAYMENTS_API_KEY! });
app.post('/create-checkout', async (req, res) => {
const session = await client.checkoutSessions.create({
product_cart: [{ product_id: req.body.productId, quantity: 1 }],
customer: { email: req.body.email },
return_url: 'https://yoursite.com/success',
});
res.json({ url: session.checkout_url });
});