If you liked what you've learned so far, dive in!
Subscribe to get access to this tutorial plus
video, code and script downloads.
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.
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.
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:
... 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.
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.
"Houston: no signs of life"
Start the conversation!
// 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
}
}