I am testing webhook with payment gateway Paystack with ngrok and spatie webhook-client, with my route in the route/api.php. and I keep getting 404 not found at the status response when the event is triggered. But if the webhook route is moved to web.php route I get response 419 unknown state. don't know why. Please I am new to all these just following to learn.
**Route in api.php**
Route::webhooks('paystack-webhook');
and VerifyCsrfToken.php
protected $except = [
'https://17c5dbf1bd87.ngrok.io/paystack/webhook',
];
webhook-client.php
<?php
return [
'configs' => [
[
/*
* This package supports multiple webhook receiving endpoints. If you only have
* one endpoint receiving webhooks, you can use 'default'.
*/
'name' => 'default',
/*
* We expect that every webhook call will be signed using a secret. This secret
* is used to verify that the payload has not been tampered with.
*/
'signing_secret' => env('PAYSTACK_SECRET_KEY'),
/*
* The name of the header containing the signature.
*/
'signature_header_name' => 'x-paystack-signature',
/*
* This class will verify that the content of the signature header is valid.
*
* It should implement \Spatie\WebhookClient\SignatureValidator\SignatureValidator
*/
'signature_validator' => App\Handler\CustomSignatureValidator::class,
/*
* This class determines if the webhook call should be stored and processed.
*/
'webhook_profile' => \Spatie\WebhookClient\WebhookProfile\ProcessEverythingWebhookProfile::class,
/*
* This class determines the response on a valid webhook call.
*/
'webhook_response' => \Spatie\WebhookClient\WebhookResponse\DefaultRespondsTo::class,
/*
* The classname of the model to be used to store call. The class should be equal
* or extend Spatie\WebhookClient\Models\WebhookCall.
*/
'webhook_model' => \Spatie\WebhookClient\Models\WebhookCall::class,
/*
* The class name of the job that will process the webhook request.
*
* This should be set to a class that extends \Spatie\WebhookClient\ProcessWebhookJob.
*/
'process_webhook_job' => App\Handler\ProcessWebhook::class,
],
],
];
ProcessWebhook.php
<?php
namespace App\Handler;
//App/Handler/ProcessWebhook.php
use \Spatie\WebhookClient\ProcessWebhookJob;
//The class extends "ProcessWebhookJob" class as that is the class
//that will handle the job of processing our webhook before we have
//access to it.class ProcessWebhook extends ProcessWebhookJob
class ProcessWebhook extends ProcessWebhookJob
{
public function handle() {
$data = json_decode($this->webhookCall, true);
//Do something with the event
logger($data['payload']);
http_response_code(200); //Acknowledge you received the response
}
}
CustomSignatureValidator.php
<?php
//App/Handler/CustomSignatureValidator.php
namespace App\Handler;
use Illuminate\Http\Request;
use Spatie\WebhookClient\Exceptions\WebhookFailed;
use Spatie\WebhookClient\WebhookConfig;
use Spatie\WebhookClient\SignatureValidator\SignatureValidator;
class PaystackSignature implements SignatureValidator
{
public function isValid(Request $request, WebhookConfig $config): bool
{
$signature = $request->header($config->signatureHeaderName);
if (! $signature) {
return false;
}
$signingSecret = $config->signingSecret;
if (empty($signingSecret)) {
throw WebhookFailed::signingSecretNotSet();
}
$computedSignature = hash_hmac('sha512', $request->getContent(), $signingSecret);
return hash_equals($signature, $computedSignature);
}
}
Response
Route List
you are mismatching some things here. let's say you want to handle the webhook through web. then you have to put a route in your web.php
file. (make sure to put it at the bottom of your route file if you use domain routing or to be safe put it just at the bottom)
Route::webhooks('paystack/webhook');
then add that route to your verify csrf middleware except
protected $except = [
'paystack/*',
];
and then your webhook url for paystack will be
ngrock-generated-host/paystack/webhook
now if you want to handle it through api then put the route at api.php
file
Route::webhooks('paystack/webhook');
you need not to put it at the except of verify csrf middleware as it will be handled with api. and your webhook url for paystack will be
ngrock-generated-host/api/paystack/webhook
Thank you @zahid hasan emon, I have tried your suggestion with web.php route and I got 500 internal server error response, then I tried it with api route and I got 404 not found response. maybe am still missing something
do you put the
api
prefix for the api route in your paystack webhook url?? and if you get 500 for web, then it means it's receiving the webhook but something is going wrong when handling the webhook. check the response or the log to find out what is going wrong.api prefix? not I didn't, but now I did and is responding with 500 internal server error but I will check the log as you said
now you are receiving the webhook but something goes wrong when handling it..check out what's going on that causes 500 error.
I did check the log and this is causing the error [2020-12-03 09:54:51] local.ERROR:
App\Handler\CustomSignatureValidator
is not a valid signature validator class.