You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Stripe订阅升级时按比例计费金额计算异常问题

Stripe订阅升级时按比例计费金额计算错误问题

我配置了Stripe定期付费订阅服务,包含Basic套餐(30美元)和Premium套餐(40美元)。用户先订阅Basic套餐,几天后切换至Premium套餐,操作流程是先取消当前订阅再创建新订阅,但设置按比例计费日期后,金额计算结果不正确,相关代码如下:

if(auth()->check()){ 
    $authUserPlan = SubscribedUser::where('user_id',auth()->user()->id)->first();           
} 
if(isset($authUserPlan) && !empty($authUserPlan)){
    // Retrieve user's current subscription
    $currentSubscription = $stripe->subscriptions->retrieve(
        $authUserPlan->stripe_subscription_id,
        []
    );      
    // Calculate the remaining time in the current billing period
    $currentPeriodEnd = Carbon::createFromTimestamp($currentSubscription->current_period_end);
    $remainingTime = now()->diffInHours($currentPeriodEnd);

    // Calculate the proration date 
        $prorationDate = $currentPeriodEnd->subHours($remainingTime); 
        $currentTimestamp = time(); 
        $new_date = strtotime('+2 minutes', $currentTimestamp);

        // Cancel the current subscription immediately
         $stripe->subscriptions->update( 
            $currentSubscription->id, ['cancel_at_period_end' => true] 
         );

    // Create a new subscription for the user 
    $newSubscription = $stripe->subscriptions->create([ 
        'customer' => auth()->user()->stripe_id, 
        'items' => [ 
            ['price' => $plan->stripe_plan], // Replace 'price' with the new price ID 
         ],              
        'billing_cycle_anchor' => $new_date,     
        'proration_behavior' => 'always_invoice', 
    ]); 
} 

问题根源分析

  • 订阅取消方式错误:cancel_at_period_end = true是设置订阅在当前周期结束后自动取消,并非立即终止,会导致新旧订阅重叠,干扰计费逻辑。
  • 按比例计费日期设置无效且错误:
    • $currentPeriodEnd->subHours($remainingTime)计算后结果就是当前时间,完全多余;
    • 强制设置billing_cycle_anchor为当前时间+2分钟,破坏了Stripe默认的计费周期锚点,导致按比例费用计算偏离预期。
  • 升级流程不合理:手动取消再创建订阅的方式,会丢失原有订阅的周期上下文,无法让Stripe基于原周期自动计算按比例费用。

正确实现方案

直接使用Stripe的订阅更新API处理升级,无需手动取消,让系统自动计算按比例费用:

if(auth()->check()){ 
    $authUserPlan = SubscribedUser::where('user_id', auth()->user()->id)->first();           
} 
if(isset($authUserPlan) && !empty($authUserPlan)){
    // 获取当前订阅
    $currentSubscription = $stripe->subscriptions->retrieve(
        $authUserPlan->stripe_subscription_id,
        []
    );      

    // 直接更新订阅,切换至Premium套餐
    $updatedSubscription = $stripe->subscriptions->update(
        $currentSubscription->id,
        [
            'items' => [
                [
                    'id' => $currentSubscription->items->data[0]->id,
                    'price' => $plan->stripe_plan, // Premium套餐的Stripe价格ID
                ],
            ],
            'proration_behavior' => 'always_invoice', // 立即生成按比例费用账单
        ]
    );

    // 更新本地数据库的订阅记录
    $authUserPlan->stripe_subscription_id = $updatedSubscription->id;
    $authUserPlan->plan_id = $plan->id; // 替换为新套餐的ID
    $authUserPlan->save();
}

核心说明

  • 无需手动取消订阅:Stripe会自动处理旧套餐的终止与新套餐的生效,同时计算当前时间到原周期结束的差价(Premium比Basic贵10美元,按剩余周期比例收取)。
  • 保留原计费锚点:升级后沿用原订阅的current_period_end作为新周期的锚点,保证计费周期的一致性。
  • 自动按比例计费:Stripe会自动核算用户已使用Basic套餐的时长,扣除对应费用后,收取剩余周期内Premium套餐的费用,无需手动计算时间差。

内容的提问来源于stack exchange,提问作者Testuser

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.27 17:27:41