通过Stripe Checkout Session创建订阅时如何设置cancel_at结束日期?
解决Stripe Checkout Session订阅到期设置问题
方案一:Webhook事件触发后补设订阅到期时间
- 创建Checkout Session时,在
subscription_data的元数据里存入计划的结束时间戳,同时动态定义一次性产品和订阅项的定价(无需后台提前创建):
$stripe->checkout->sessions->create([ 'payment_method_types' => ['card'], 'line_items' => [ // 一次性产品(动态定义) [ 'price_data' => [ 'currency' => 'usd', 'product_data' => ['name' => '一次性配件'], 'unit_amount' => 2000, // 对应20美元 ], 'quantity' => 1, ], // 订阅项(动态定义) [ 'price_data' => [ 'currency' => 'usd', 'product_data' => ['name' => '月度会员'], 'recurring' => ['interval' => 'month'], 'unit_amount' => 1000, // 对应10美元/月 ], 'quantity' => 1, ], ], 'mode' => 'payment', // 同时支持一次性付款与订阅创建 'subscription_data' => [ 'metadata' => [ 'cancel_at_timestamp' => strtotime('+3 months'), // 示例:3个月后到期 ], ], 'success_url' => 'https://yourdomain.com/success', 'cancel_url' => 'https://yourdomain.com/cancel', ]);
- 监听
checkout.session.completedWebhook事件,会话完成后提取订阅ID,调用更新接口设置cancel_at:
// Webhook处理逻辑 $payload = @file_get_contents('php://input'); $event = \Stripe\Event::constructFromJson($payload); if ($event->type === 'checkout.session.completed') { $session = $event->data->object; $subscriptionId = $session->subscription; if ($subscriptionId) { $cancelAt = $session->subscription_data->metadata['cancel_at_timestamp'] ?? null; if ($cancelAt) { $stripe->subscriptions->update( $subscriptionId, ['cancel_at' => $cancelAt] ); } } }
方案二:固定周期订阅自动到期(适合非精确日期场景)
如果订阅是固定时长(比如3个月),可以直接在订阅定价里设置周期数,同时开启周期结束后自动取消:
// 订阅项的price_data配置 'price_data' => [ 'currency' => 'usd', 'product_data' => ['name' => '3个月会员'], 'recurring' => [ 'interval' => 'month', 'interval_count' => 3, ], 'unit_amount' => 3000, // 对应3个月总价30美元 ], 'subscription_data' => [ 'cancel_at_period_end' => true, ],
此方法无需额外Webhook,但只能按订阅周期结束,无法指定具体日期。
关键注意点
- 使用
mode:payment可同时完成一次性产品结算与订阅创建,符合你的流程需求。 - 动态定义的产品/定价仅在当前Checkout流程中生效,不会留存到Stripe后台。
- 确保Webhook配置正确,能正常接收
checkout.session.completed事件,否则无法触发订阅到期时间的更新。
内容的提问来源于stack exchange,提问作者Ahammad Jaffer
相关产品推荐
相关产品推荐

