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

lat4732's avatar
Level 12

Problem with event - not working

Hey!

I just registered an event to handle if the Stripe Subscription creation has been successful.

namespace App\Events;

use App\Providers\PaymentReceived;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Queue\InteractsWithQueue;
use Laravel\Cashier\Cashier;
use App\Models\StripeProducts;

class PaymentEventListener
{
    /**
     * Create the event listener.
     *
     * @return void
     */
    public function __construct($user, $payment_method)
    {
        $this->user = $user;
        $this->payment_method = $payment_method;
    }

    /**
     * Handle the event.
     *
     * @param  \App\Providers\PaymentReceived  $event
     * @return void
     */
    public function handle(PaymentReceived $event)
    {
        $companyData = DB::table('companies')->where('user_id', $this->user->id)->first();
        $companySetup = DB::table('company_set_ups')->where('company_id', $companyData->id)->with('plan', 'method')->first();

        $stripe = StripeProducts::where('plan_id', $companySetup->plan->id)->where('billing_cycle_months', $companySetup->selected_payment_plan_cycle)->first();

        $user = Cashier::findBillable($this->user->stripe_id);

        if($user->subscribed($companySetup->plan->name) === false) {
            $user->newSubscription($companySetup->plan->name, $stripe->stripe_price_id)->create($this->payment_method);
        }

        if($user->subscribed($companySetup->plan->name)) {
            // UPDATE Payment Completed
            DB::table('company_set_ups')->where('company_id', $companyData->id)->update([
                'payment_completed' => 1
            ]);
            // ADD ACTIONS
            DB::table('companies')->where('id', $companyData->id)->update([
                'actions' => $companySetup->plan->actions
            ]);

            return response()->json([
                'status' => 1
            ]);
        } else {
            return response()->json([
                'status' => 0
            ]);
        }
    }
}

here is the controller method for the stripe.pay.update.database route

public function stripePayUpdateDatabase(Request $request) {
        return event(new PaymentEventListener(auth()->user(), $request->paymentMethod));
}

Here is the form for the payment submission which is AJAX based

<form id="payment-form" data-secret="{{ $intent->client_secret }}">
<button id="submit_payment" class="stripe-button"><i class="icon-lock text-light"></i>@lang('main.business_setup_payment_card_pay_now') (${{ $setup->calculatePlanPrice() }})</button>
</form>

here is the JS for the form

var form = document.getElementById('payment-form');
var cardHolderName = document.getElementById('cardholder-name');
var clientSecret = form.dataset.secret;
form.addEventListener('submit', async function(event) {
    event.preventDefault();
    $("#card-errors").empty();
    $("#submit_payment").html('<i class="icon-spin5 animate-spin"></i> @lang("main.business_setup_payment_card_pay_button_proccess")');
    $("#submit_payment").attr('disabled', true);
    const { setupIntent, error } = await stripe.confirmCardSetup(
        clientSecret, {
            payment_method: {
                card,
                billing_details: { name: cardHolderName.value }
            }
        }
    );
    if (error) {
        $("#card-errors").empty();
        $("#card-errors").html("<i class='icon-warning'></i> " + error.message);
        $("#submit_payment").html('<i class="icon-lock text-light"></i>@lang("main.business_setup_payment_card_pay_now") ${{ $setup->plan->price * $setup->selected_payment_plan_cycle }}');
        $("#submit_payment").attr('disabled', false);
        $.ajax({
            url: '{{ route("stripe.pay.update.database.errors") }}',
            type: 'POST',
            data: {
                status: error.message
            }
        });
    } else {
        stripeTokenHandler(setupIntent);
        $.ajax({
            url: '{{ route("stripe.pay.update.database") }}',
            type: 'POST',
            success: function(response) {              
                if(response.status == 1) {
                    $("#card-successes").html('<i class="icon-check-1"></i> @lang("main.business_setup_payment_card_pay_success_message")');
                }
            }
        });
    }

});

// Submit the form with the token ID.
function stripeTokenHandler(setupIntent) {
    // Insert the token ID into the form so it gets submitted to the server
    var form = document.getElementById('payment-form');
    var hiddenInput = document.createElement('input');
    hiddenInput.setAttribute('type', 'hidden');
    hiddenInput.setAttribute('name', 'paymentMethod');
    hiddenInput.setAttribute('value', setupIntent.payment_method);
    form.appendChild(hiddenInput);
    // Submit the form
    form.submit();
}

Before event creation it was just a simple route that is returning json response to a AJAX call and it was working perfectly (but insecure) and I decided to move this into an event and now it doesn't work. How can I make this work and also do you have any tips how to improve security for these payments?

0 likes
21 replies
lat4732's avatar
Level 12

I'm just getting page refresh. nothing other.

Snapey's avatar
public function stripePayUpdateDatabase(Request $request) {
        PaymentEventListener::dispatch(auth()->user(), $request->paymentMethod));
}

Why are you doing the work in the event?

Snapey's avatar

@Laralex normally, fire an event and create a listener that hears the event and performs the action

lat4732's avatar
Level 12

@Snapey Ok.. I think I created my event & listener not by the book. I added in EventServiceProvider

PaymentReceived::class => [
      PaymentEventListener::class
],

and then ran php artisan event:generate. Then I saw in app\Events the PaymentEventListener.php. I have nothing in app\Listeners. Is that how it should be?

sr57's avatar

Hi @laralex

Have you declare (use ) your event é listener classe in your EventServiceProvider?

lat4732's avatar
Level 12

@sr57 This is my EventServiceProvider


namespace App\Providers;

use Illuminate\Auth\Events\Registered;
use Illuminate\Auth\Listeners\SendEmailVerificationNotification;
use Illuminate\Foundation\Support\Providers\EventServiceProvider as ServiceProvider;
use Illuminate\Support\Facades\Event;
use App\Listeners\StripeEventListener;
use Laravel\Cashier\Events\WebhookReceived;
use App\Events\PaymentEventListener;

class EventServiceProvider extends ServiceProvider
{
    /**
     * The event listener mappings for the application.
     *
     * @var array
     */
    protected $listen = [
        Registered::class => [
            SendEmailVerificationNotification::class,
        ],
        WebhookReceived::class => [
            StripeEventListener::class,
        ],
        PaymentReceived::class => [
            PaymentEventListener::class
        ],
    ];

    /**
     * Register any events for your application.
     *
     * @return void
     */
    public function boot()
    {
        //
    }
}

sr57's avatar

Add

use App\Event\PaymentReceived;

Wat's this line App\Events\PaymentEventListener; ? a listener in the event directory?

You shloud have

use App\Listeners\PaymentEventListener; and your listener file in this directory.

lat4732's avatar
Level 12

@sr57 That was supposed to be the name of the listener but I have no idea why php artisan event:generate created the event with this name... Here are the contents for PaymentEventListener. Please, note that I'm using event&listeners for first time.

app\Events\PaymentEventListener.php

<?php

namespace App\Events;

use App\Providers\PaymentReceived;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Queue\InteractsWithQueue;
use Laravel\Cashier\Cashier;

class PaymentEventListener
{
    /**
     * Create the event listener.
     *
     * @return void
     */
    public function __construct($user, $payment_method)
    {
        $this->user = $user;
        $this->payment_method = $payment_method;
    }

    /**
     * Handle the event.
     *
     * @param  \App\Providers\PaymentReceived  $event
     * @return void
     */
    public function handle(PaymentReceived $event)
    {
        $companyData = DB::table('companies')->where('user_id', $this->user->id)->first();
        $companySetup = DB::table('company_set_ups')->where('company_id', $companyData->id)->with('plan', 'method')->first();

        $stripe = DB::table('stripe_products')->where('plan_id', $companySetup->plan->id)->where('billing_cycle_months', $companySetup->selected_payment_plan_cycle)->first();

        $user = Cashier::findBillable($this->user->stripe_id);

        if($user->subscribed($companySetup->plan->name) === false) {
            $user->newSubscription($companySetup->plan->name, $stripe->stripe_price_id)->create($this->payment_method);
        }

        if($user->subscribed($companySetup->plan->name)) {
            // UPDATE Payment Completed
            DB::table('company_set_ups')->where('company_id', $companyData->id)->update([
                'payment_completed' => 1
            ]);
            // ADD ACTIONS
            DB::table('companies')->where('id', $companyData->id)->update([
                'actions' => $companySetup->plan->actions
            ]);

            return response()->json([
                'status' => 1
            ]);
        }
        
        return response()->json([
            'status' => 0
        ]);
        
    }
}
lat4732's avatar
Level 12

@sr57 This is what I'm getting on php artisan event:list

+----------------------------------------+-------------------------------------------------------------+
| Event                                  | Listeners                                                   |
+----------------------------------------+-------------------------------------------------------------+
| App\Event\PaymentReceived              | App\Events\PaymentEventListener                             |
| Illuminate\Auth\Events\Registered      | Illuminate\Auth\Listeners\SendEmailVerificationNotification |
| Laravel\Cashier\Events\WebhookReceived | App\Listeners\StripeEventListener                           |
+----------------------------------------+-------------------------------------------------------------+

How should I rename them? And why event with no Listener and listener without event? I have no idea what you're talking about

sr57's avatar
sr57
Best Answer
Level 39

Normal versus your code and wrong see my comment 2 posts before

You should have

use App\Listeners\PaymentEventListener; and your listener file in this directory.

Events must be in app\Events

Listeners in app\Listeners

lat4732's avatar
Level 12

@sr57 Ok I deleted old event & listener and changed my EventServiceProvider to

use App\Events\PaymentReceived;
use App\Listeners\PaymentEventListener;

// .......

then ran php artisan event:generate and I now have app\Events\PaymentReceived.php and app\Listeners\PaymentEventListener.php.

lat4732's avatar
Level 12

So.. My event contains app\Events\PaymentReceived.php

namespace App\Events;

use Illuminate\Broadcasting\Channel;
use Illuminate\Broadcasting\InteractsWithSockets;
use Illuminate\Broadcasting\PresenceChannel;
use Illuminate\Broadcasting\PrivateChannel;
use Illuminate\Contracts\Broadcasting\ShouldBroadcast;
use Illuminate\Foundation\Events\Dispatchable;
use Illuminate\Queue\SerializesModels;

class PaymentReceived
{
    use Dispatchable, InteractsWithSockets, SerializesModels;

    /**
     * Create a new event instance.
     *
     * @return void
     */
    public function __construct()
    {
        //
    }

    /**
     * Get the channels the event should broadcast on.
     *
     * @return \Illuminate\Broadcasting\Channel|array
     */
    public function broadcastOn()
    {
        return new PrivateChannel('channel-name');
    }
}

and my listener app\Listeners\PaymentEventListener.php

namespace App\Listeners;

use App\Events\PaymentReceived;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Queue\InteractsWithQueue;
use Laravel\Cashier\Cashier;

class PaymentEventListener
{
    /**
     * Create the event listener.
     *
     * @return void
     */
    public function __construct($user, $payment_method)
    {
        $this->user = $user;
        $this->payment_method = $payment_method;
    }

    /**
     * Handle the event.
     *
     * @param  \App\Events\PaymentReceived  $event
     * @return void
     */
    public function handle(PaymentReceived $event)
    {
        $companyData = DB::table('companies')->where('user_id', $this->user->id)->first();
        $companySetup = DB::table('company_set_ups')->where('company_id', $companyData->id)->with('plan', 'method')->first();

        $stripe = DB::table('stripe_products')->where('plan_id', $companySetup->plan->id)->where('billing_cycle_months', $companySetup->selected_payment_plan_cycle)->first();

        $user = Cashier::findBillable($this->user->stripe_id);

        if($user->subscribed($companySetup->plan->name) === false) {
            $user->newSubscription($companySetup->plan->name, $stripe->stripe_price_id)->create($this->payment_method);
        }

        if($user->subscribed($companySetup->plan->name)) {
            // UPDATE Payment Completed
            DB::table('company_set_ups')->where('company_id', $companyData->id)->update([
                'payment_completed' => 1
            ]);
            // ADD ACTIONS
            DB::table('companies')->where('id', $companyData->id)->update([
                'actions' => $companySetup->plan->actions
            ]);
        }        
    }
}
sr57's avatar

@Laralex

Declare them in EventServiceProvider , and it should work (use a log in both event & listener to verify)

lat4732's avatar
Level 12

@sr57 But I have no idea what to do with the event code. The listener is ready but what should the event contains?

sr57's avatar

@Laralex

Nothing to just fire the event

or an example from me

public function __construct(Album $album)
{
	dump("app/Event/AlbumCreated __constuct");
    $this->album = $album;
}
lat4732's avatar
Level 12

And is there any way to make the listener return a response? I want something like

$event = PaymentReceived::dispatch(auth()->user(), $request->paymentMethod);

if($event->status == "succeed") {
      return redirect()->to()........;
}

and when I dispatch() event how these auth()->user() and $request->paymentMethod are passed to the listener?

Snapey's avatar

@Laralex no, if you want a return value don't use events and listeners, just put the code in your controller

sr57's avatar

@laralex

Should be time to close the thread from the OP question and open another if your have other question.

1 like
sr57's avatar

@laralex

Difficult to close a thread when you ask two different questions in the same :-)

1 like

Please or to participate in this conversation.