@dodopayments/tanstack package 为你的 TanStack Start project 提供三个 request handlers。Checkout 返回 checkout URLs,CustomerPortal 将 customer 导向 Customer Portal,而 Webhooks 会验证 webhook events 并将其路由到你的代码。每个 handler 都接收标准的 Request 并返回 Response,因此你可以从 server route handler 中调用它。
Checkout Handler
使用 static、dynamic 和 checkout session flows 创建 checkout URLs。
Customer Portal
让 customers 管理其 subscriptions 和 details。
Webhooks
接收并处理 Dodo Payments webhook events。
安装
1
Install the Package
在 project root 中运行此命令:该 package 还需要
zod 3.25 或更高版本,并将其列为 peer dependency。2
Set Up Environment Variables
在 project root 中创建一个 TanStack Start 会加载
.env file。在 Developer → API Keys 下创建 API key。在 Developer → Webhooks 下添加 webhook endpoint,并将其 Signing secret 复制到 DODO_PAYMENTS_WEBHOOK_KEY:.env files,而 server routes 会从 process.env 中读取这些值。DODO_PAYMENTS_RETURN_URL 是 customers 在 checkout 后到达的页面。如果你不传入 environment,handlers 会使用 live_mode。test mode API key 只能与 test_mode 配合使用。Route Handler 示例
这些示例是位于
src/routes/api/ 中的 TanStack Start server routes。每个示例都会在 createFileRoute 的 server.handlers 下定义其 handlers。较旧的 TanStack Start releases(例如 1.129)会从 @tanstack/react-start/server 使用 createServerFileRoute 定义 server routes,并改用 .methods() call。Dodo Payments handlers 在两种 APIs 中的工作方式相同:将 request 传给它们。- Checkout Handler
- Customer Portal Handler
- Webhook Handler
使用此 handler 将 Dodo Payments checkout 添加到你的 app。
GET handler 提供 static checkout。POST handler 提供 checkout sessions;当你设置 type: "dynamic" 时,它也提供 dynamic checkout。dynamic checkout 示例假设你已设置 type: "dynamic"。Checkout Route Handler
checkout handler 支持使用 Dodo Payments 收款的三种方式:- **Static Payment Links:**可分享的 URLs,无需代码即可收款。
- **Dynamic Payment Links:**使用自定义 details 生成的 payment links。它们使用 deprecated endpoints。
- **Checkout Sessions:**支持 product cart、customer details 和 customization options 的 hosted checkout。这是推荐的 flow。
Checkout 接收以下 options:
对于
GET requests,handler 提供 static checkout。对于 POST requests,当 type 为 dynamic 时,它会创建 dynamic payment link;否则会创建 checkout session。
Static Checkout (GET)
Static Checkout (GET)
支持的 Query Parameters
固定收取的金额(以 major currency units 表示),例如对于 $12.50,使用
12.5。仅适用于 Pay What You Want products;如果低于 product 的 minimum price,则会忽略该值。email 与 disableEmail=true 同时存在时。handler 会将其 config 中的 returnUrl 以 redirect_url 的形式添加到 link。Response Format
Static checkout 返回包含 checkout URL 的 JSON response。在 test mode 中,URL 使用test.checkout.dodopayments.com:Dynamic Checkout (POST)
Dynamic Checkout (POST)
- 在 POST request 中将 parameters 作为 JSON body 发送。
- 支持 one-time 和 recurring payments。handler 会获取 product;如果 product 是 recurring,则创建 subscription,否则创建 one-time payment。
- body 需要
billing(包括street、city、state、country和zipcode)以及customer,此外还需要product_id或product_cart。Subscriptions 需要product_id。 - 关于所有支持的 body fields,请参阅:
Response Format
Dynamic checkout 返回包含 payment link(作为 checkout URL)的 JSON response:Checkout Sessions (POST)
Checkout Sessions (POST)
Checkout sessions 会为 one-time purchases 和 subscriptions 创建 hosted checkout,并提供完整的 customization 控制。
product_cart 是唯一必需的 field,并且至少需要一个 product。如果 body 没有 return_url,handler 会使用其 config 中的 returnUrl。每个 checkout_url 只能使用一次,并会在 24 小时后过期;如果传入 confirm: true,则会在 15 分钟后过期。使用 payment_method_id 创建的 session 不会返回 checkout_url,因此 handler 会响应 400。如需了解更多详情及所有支持的 fields,请参阅 Checkout Sessions Integration Guide。Response Format
Checkout sessions 返回包含 checkout URL 的 JSON response:Customer Portal Route Handler
Customer Portal route handler 会为你传入的 customer 创建 Customer Portal session,并将 browser 重定向到该 session。CustomerPortal 接收与 Checkout 相同的 bearerToken 和 environment options。
Query Parameters
如果缺少customer_id,handler 会返回 400;如果无法创建 portal session,则返回 500。
Webhook Route Handler
webhook route handler 会使用你的 webhook secret 验证每个 request;该 secret 作为webhookKey 传入,然后才运行你的代码:
- **Method:**仅支持 POST requests。其他 methods 返回 405。
- **Signature Verification:**使用
webhookKey,按照 Standard Webhooks specification 验证webhook-id、webhook-timestamp和webhook-signatureheaders。验证失败时返回 401。 - **Payload Validation:**使用 Zod 验证 payload。payload 无效时返回 400。
- Error Handling:
- 401:Invalid signature
- 400:Invalid payload
- 500:验证期间发生 Internal error
- **Event Routing:**对每个 event 调用
onPayload,然后调用对应 event type 的 handler,并返回 200。