Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.

SeanKimball's avatar

Spark 4.x webhooks and the 'default' plan

I've been struggling with Spark for a good 2 weeks now - luckily, the more I struggle, the more I learn. But I still have some questions.

webhooks, events and listeners.

https://spark.laravel.com/docs/spark-stripe/configuration.html

Is fairly clear in the docs, I managed to get them setup in Stripe, setup the local CLI endpoint, setup a new listener for the webhooks so I can drop the output to a log and watch the responses come in. HOWEVER, I see several events in the Spark distribution and no listeners. When I cancel or resume a subscription the webhooks are logged , but the subscriptions table does NOT get updated.

$this->user->personalTeam()->subscription()->stripe_status

Still returns "active" Do I actually have to manually create the listeners and add methods for updating subscriptions and subscription items? or is this what the artisan cashier:webhook --url command is doing,, which will not work in a dev environment.

Plans sparkPlan()

Where is this coming from? trialDays, price etc are never populated from everything I can tell, you can't actually get a price from the sparkPlan() or subscription() methods.

$this->user->personalTeam()->sparkPlan()

Spark\Plan {#1598 ▼ // resources/views/dashboard.blade.php
  +id: "price_1Nqge12anG5eHydGv14jgTZq"
  +name: "Individual Subscription"
  +interval: "monthly"
  +trialDays: null
  +price: null
  +currency: null
  +rawPrice: null
  +monthlyIncentive: ""
  +yearlyIncentive: ""
  +shortDescription: "Unlimited access to subscription"
  +features: array:3 [▶]
  +options: array:3 [▶]
  +active: true
}

Finally, plan names

It seems that the subscription('default') has been hard coded in theCreateSubscription action all plans have the name "default" regardless of what you call them in stripe and spark.config. Things like:

$team->subscription('Team Subscription')->canceled()
$team->subscription('Individual Subscription')->onTrial()

Will always fail because the subscription is always created with the name "default" so basically this means I can only have one subscription per model since changing subscriptions just replaces the 'default' subscription. Really just want a confirmation on that one.

Is it possible the cookbook is out of date and missing some info for binding to the Team model? I did notice that the migrations were not updated and migrate was adding the extra stripe fields to both User and Team models.

0 likes
1 reply
LaryAI's avatar
Level 58

Based on the question description, it seems that the user is facing several issues with Spark 4.x webhooks and the 'default' plan. Here's a solution to each problem mentioned:

  1. Issue with webhooks and updating subscriptions: It appears that the webhooks are being logged, but the subscriptions table is not getting updated. To resolve this, you need to manually create listeners and add methods for updating subscriptions and subscription items. The artisan cashier:webhook --url command is not suitable for a development environment. Here's an example of how you can create a listener and update the subscriptions table:
// Create a new listener for the subscription webhook events
php artisan make:listener SubscriptionUpdatedListener

// In the created listener class, handle the subscription updated event
public function handle(SubscriptionUpdated $event)
{
    // Update the subscriptions table with the new subscription status
    $subscription = $event->subscription;
    $subscription->user->personalTeam()->subscription()->update([
        'stripe_status' => $subscription->stripe_status,
    ]);
}
  1. Issue with retrieving plan details using sparkPlan(): The sparkPlan() method does not populate the trial days, price, or other plan details. To retrieve the plan details, you can use the plan() method instead. Here's an example:
$plan = $this->user->personalTeam()->subscription()->plan();
$plan->id; // Get the plan ID
$plan->name; // Get the plan name
$plan->interval; // Get the plan interval
// Retrieve other plan details as needed
  1. Issue with plan names always being 'default': It seems that the subscription('default') has been hard-coded in the CreateSubscription action, causing all plans to have the name 'default'. This means you can only have one subscription per model since changing subscriptions replaces the 'default' subscription. To have different plan names, you need to modify the CreateSubscription action and pass the desired plan name when creating a subscription. Here's an example:
$team->newSubscription('subscription-name', 'plan-id')->create();

Make sure to replace 'subscription-name' with the desired name for the subscription and 'plan-id' with the actual plan ID from Stripe.

Regarding the possibility of the cookbook being out of date, it's recommended to refer to the official Laravel Spark documentation and the Laravel Cashier documentation for the most up-to-date information.

Remember to adjust the code examples according to your specific implementation and requirements.

Please or to participate in this conversation.