Flag of Ukraine
SymfonyCasts stands united with the people of Ukraine
This course is archived!
This tutorial uses an older version of Symfony of the stripe-php SDK. The majority of the concepts are still valid, though there *are* differences. We've done our best to add notes & comments that describe these changes.

Live Webhook Testing with Ngrok

Keep on Learning!

If you liked what you've learned so far, dive in!
Subscribe to get access to this tutorial plus
video, code and script downloads.

Start your All-Access Pass
Buy just this tutorial for $12.00

If the automated tests aren't your thing, or if you just really want to see your webhooks in action... in real life, you've got two options.

Testing on Beta

The best way, honestly, is to test your webhooks for real, out in the wild, on a beta server. Yep, I simply mean: deploy your code to beta, setup a webhook to point to your beta server, and then start creating test subscriptions through your site.

The only problem is that some webhooks are harder to simulate than others. Want to simulate customer.subscription.deleted? No problem: create a subscription on your site, then log into Stripe and cancel it. Then watch the webhook magic happen.

But faking the invoice.payment_failed webhook because your card is being declined on subscription renewal... well... that's a bit harder. You could wait 1 month and see what happens... if you have a lot of time. Or, you could temporarily create a new subscription plan and set its interval to one day.

Then, you can test a different situation each day: like make sure the subscription renewal webhook works, then update your card to one that will fail, wait one more day, and see how your system handles the invoice.payment_failed webhook.

It's not perfect, it's slow, but it's totally real-world.

Using your Local Machine with Ngrok

The second option is to point a webhook at your local development machine. But wait! That's not possible: our local machine is not accessible by the internet.

Well... that doesn't have to be true. By using a cool utility called Ngrok, you can temporarily tunnel a public URL to your computer.

Let's try it! Since I already have ngrok installed, I can use it from any directory on my system:

ngrok http 8000

That will expose port 8000 - the one we're serving our site on - to the web via this cool public URL.

Copy that and paste it into your browser! Ah, that's a little security check that prevents any non-local users from accessing our dev environment. Just for now, go into the web/ directory, open app_dev.php, and comment-out the two security lines:

33 lines web/app_dev.php
... lines 1 - 12
if (isset($_SERVER['HTTP_CLIENT_IP'])
|| isset($_SERVER['HTTP_X_FORWARDED_FOR'])
|| !(in_array(@$_SERVER['REMOTE_ADDR'], ['127.0.0.1', 'fe80::1', '::1']) || php_sapi_name() === 'cli-server')
) {
// header('HTTP/1.0 403 Forbidden');
// exit('You are not allowed to access this file. Check '.basename(__FILE__).' for more information.');
}
... lines 20 - 33

Refresh again! Hey, it's our site! Via a public URL.

Using the Ngrok URL as a Webhook Endpoint

Now we're super dangerous! In your Stripe Webhook configuration, add an endpoint. Paste the URL and put this in the "Test" environment. For now, just receive the customer.subscription.deleted event. Create the endpoint!

Oh, wait, make sure the endpoint URL ends in /webhooks/stripe. That's better!

In our app, we already have an active subscription. So, in Stripe, click "Customers" and open our one Customer. Find the top subscription and... cancel it! Immediately!

That should cause a webhook to be sent to our local machine. So, moment of truth: refresh the account page! Oh no! The subscription doesn't look canceled!

Hmm, go back to Stripe. At the bottom of the Customer page, you can see all the events for this Customer. Or, another way to look at this is by clicking "Events & webhooks" on the left. Ah! And we can see the customer.subscription.deleted event! And at the bottom, it shows that the webhook to our ngrok URL was successful.

So, refresh the account page again. Ah, now the subscription is canceled. We were just too fast the first time.

So, choose your favorite method of testing these crazy webhook things, and make sure they are bug-free.

Leave a comment!

0
Login or Register to join the conversation
Cat in space

"Houston: no signs of life"
Start the conversation!

This tutorial uses an older version of Symfony of the stripe-php SDK. The majority of the concepts are still valid, though there *are* differences. We've done our best to add notes & comments that describe these changes.

What PHP libraries does this tutorial use?

// composer.json
{
    "require": {
        "php": ">=5.5.9, <7.4",
        "symfony/symfony": "3.1.*", // v3.1.10
        "doctrine/orm": "^2.5", // v2.7.2
        "doctrine/doctrine-bundle": "^1.6", // 1.6.8
        "doctrine/doctrine-cache-bundle": "^1.2", // 1.3.0
        "symfony/swiftmailer-bundle": "^2.3", // v2.6.2
        "symfony/monolog-bundle": "^2.8", // v2.12.1
        "symfony/polyfill-apcu": "^1.0", // v1.3.0
        "sensio/distribution-bundle": "^5.0", // v5.0.22
        "sensio/framework-extra-bundle": "^3.0.2", // v3.0.26
        "incenteev/composer-parameter-handler": "^2.0", // v2.1.2
        "friendsofsymfony/user-bundle": "~2.0.1", // v2.0.1
        "stof/doctrine-extensions-bundle": "^1.2", // v1.2.2
        "stripe/stripe-php": "^3.15", // v3.23.0
        "doctrine/doctrine-migrations-bundle": "^1.1", // v1.2.1
        "phpunit/phpunit": "^5.5", // 5.7.20
        "composer/package-versions-deprecated": "^1.11" // 1.11.99
    },
    "require-dev": {
        "sensio/generator-bundle": "^3.0", // v3.1.4
        "symfony/phpunit-bridge": "^3.0", // v3.3.0
        "hautelook/alice-bundle": "^1.3", // v1.4.1
        "doctrine/data-fixtures": "^1.2" // v1.2.2
    }
}
userVoice