Warm tip: This article is reproduced from serverfault.com, please click

I keep getting 404 not found while testing webhook with spatie webhook client and ngrok

发布于 2020-12-02 21:54:44

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',
];

From my Paytack Dashboard

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

status response from ngrok

Route List

Route List

Questioner
Adam
Viewed
0
zahid hasan emon 2020-12-03 12:27:52

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