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

Laravel Cashier订阅名称不更新,如何保留subscribed()方法判断套餐?

解决Laravel Cashier订阅名称不同步,保留subscribed()方法判断套餐的方案

最优方案:通过Stripe Webhook同步订阅名称到Cashier表

Cashier的subscribed('tier2')方法依赖于subscriptions表的name字段判断套餐,而Stripe门户修改订阅时不会自动同步这个字段,我们可以通过监听Stripe的customer.subscription.updated事件主动更新该字段,这完全符合Cashier的设计逻辑,不存在“修改Cashier管理的表不妥当”的问题。

具体步骤:

  1. 确保已配置Stripe Webhook并启用customer.subscription.updated事件监听
  2. 在Webhook处理逻辑中完成以下操作:
    • 通过Stripe订阅ID找到对应的Cashier订阅记录
    • 从Stripe返回的订阅数据中提取当前价格ID,再获取该价格关联的产品信息(产品名称或自定义套餐标识)
    • 更新订阅记录的name字段为套餐标识

代码示例:

// Webhook处理控制器中的方法
public function handleSubscriptionUpdated(array $payload)
{
    $stripeSubscription = $payload['data']['object'];
    $subscription = \Laravel\Cashier\Subscription::findByStripeId($stripeSubscription['id']);

    if (!$subscription) {
        return;
    }

    // 获取当前订阅的价格ID
    $priceId = $stripeSubscription['items']['data'][0]['price']['id'];
    // 从Stripe获取价格对应的产品信息
    $price = \Stripe\Price::retrieve($priceId);
    // 这里可以直接用产品名称,或者从产品metadata取自定义标识(更灵活)
    $planName = $price->product->name;
    // 若用metadata:$planName = $price->product->metadata['plan_slug'];

    $subscription->update(['name' => $planName]);
}

完成后,subscribed('tier2')就能正常判断用户当前的订阅套餐,同时保留Stripe门户的订阅管理功能。

备选方案:扩展User模型的subscribed方法(无需修改数据库)

如果不想修改subscriptions表,可以通过扩展User模型的subscribed方法,实现价格ID到套餐名称的映射,同时保留原有方法的功能。

具体步骤:

  1. 在User模型中定义价格与套餐名称的映射数组
  2. 重写subscribed方法,先调用父类逻辑,若未匹配则通过价格映射判断

代码示例:

// App\Models\User.php
use Laravel\Cashier\Billable;

class User extends Authenticatable
{
    use Billable;

    // 定义Stripe价格ID到套餐名称的映射
    protected $priceToPlan = [
        'price_xxxxxx' => 'tier1',
        'price_yyyyyy' => 'tier2',
        // 新增套餐时补充映射关系
    ];

    public function subscribed($plan = null, $subscription = 'default')
    {
        // 处理传入价格ID的情况,映射为套餐名称
        if ($plan && isset($this->priceToPlan[$plan])) {
            $plan = $this->priceToPlan[$plan];
        }

        // 先执行父类的subscribed逻辑
        $parentCheck = parent::subscribed($plan, $subscription);
        if ($parentCheck) {
            return true;
        }

        // 父类未匹配时,通过当前订阅的priceID判断
        $subscriptionInstance = $this->subscription($subscription);
        if (!$subscriptionInstance || !$subscriptionInstance->valid()) {
            return false;
        }

        return isset($this->priceToPlan[$subscriptionInstance->stripe_price]) 
            && $this->priceToPlan[$subscriptionInstance->stripe_price] === $plan;
    }
}

这种方式无需修改数据库,原有的subscribed('tier2')调用逻辑完全不变,同时兼容通过价格ID判断的场景。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.15 14:57:05