Reputation: 1075
Neither doc (https://stripe.com/docs/webhooks) nor SDK(stripe-php) uses any signature method. So I doubt, what if someone fake as official webhook sender?
In SDK, only retrieve event id successfully will consider a good webhook, I think it's too risky, isn't it?
Upvotes: 2
Views: 7799
Reputation: 2498
There are two ways to do this. They have been covered already but I will consolidate everything into a single answer.
Option 1
Check the event is valid (throws an exception if not).
\Stripe\Event::retrieve($event_id)
Option 2
HMAC the Stripe-Signature
header using the whsec*
key found in your dashboard.
// Set your secret key: remember to change this to your live secret key in production
// See your keys here: https://dashboard.stripe.com/account/apikeys
\Stripe\Stripe::setApiKey("sk_test_XXXXXXXXXXXXXXXXXXXXXXXXXXXXX");
// You can find your endpoint's secret in your webhook settings
$endpoint_secret = "whsec_...";
$payload = @file_get_contents("php://input");
$sig_header = $_SERVER["HTTP_STRIPE_SIGNATURE"];
$event = null;
try {
$event = \Stripe\Webhook::constructEvent(
$payload, $sig_header, $endpoint_secret
);
} catch(\UnexpectedValueException $e) {
// Invalid payload
http_response_code(400); // PHP 5.4 or greater
exit();
} catch(\Stripe\Error\SignatureVerification $e) {
// Invalid signature
http_response_code(400); // PHP 5.4 or greater
exit();
}
// Do something with $event
http_response_code(200); // PHP 5.4 or greater
Code from https://stripe.com/docs/webhooks/signatures
Option 1 is simpler, requires an extra call to the API but option 2 requires you store an extra key in your application and requires for code (I prefer option 1). I checked with Stripe support today and they confirmed they are both as good as each other in terms of verifying the validity of an API call so it is a matter of choice.
Upvotes: 3
Reputation: 2359
Stripe does provide signatures for web hooks. Take a look here: https://stripe.com/docs/webhooks#signatures
You can also take a look at this article: https://www.truespotmedia.com/testing-webhooks-in-stripe-with-php/
Here is some example code:
// Set your secret key: remember to change this to your live secret key in production
// See your keys here: https://dashboard.stripe.com/account/apikeys
\Stripe\Stripe::setApiKey("your secret api key");
// You can find your endpoint's secret in your webhook settings
$endpoint_secret = "whsec_...";
$payload = @file_get_contents("php://input");
$sig_header = $_SERVER["HTTP_STRIPE_SIGNATURE"];
$event = null;
try {
$event = \Stripe\Webhook::constructEvent(
$payload, $sig_header, $endpoint_secret
);
} catch(\UnexpectedValueException $e) {
// Invalid payload
http_response_code(400); // PHP 5.4 or greater
exit();
} catch(\Stripe\Error\SignatureVerification $e) {
// Invalid signature
http_response_code(400); // PHP 5.4 or greater
exit();
}
// Do something with $event
http_response_code(200); // PHP 5.4 or greater
Upvotes: 5
Reputation: 2218
You can solve this by saving the event id and then retrieving the event from stripe to make sure the event is valid:
\Stripe\Event::retrieve($event_id)
Upvotes: 2