sequra/middleware
Laravel middleware package for integrating SeQura payment and financing services into your application, providing request handling hooks and configuration to route eligible checkouts through SeQura.
Before you composer require, understand what you're getting. This is a 0-star, 0-dependent package published by SeQura (the Spanish BNPL provider) to support their own cloud connectors — Magento Cloud, PrestaShop, WooCommerce SaaS, etc. It is not a general-purpose Laravel package with a service provider, config file, and facades. Expect a library of transport/domain classes you wire up yourself.
composer require sequra/middleware
Then immediately do this:
vendor/sequra/middleware/composer.json — check the autoload.psr-4 prefix so you know the real namespace (likely SeQura\Middleware\ or SeQura\Core\), and check whether it targets PSR-15/PSR-18 interfaces, a framework-agnostic HTTP client, or Laravel directly. That single file tells you which of the two "middleware" meanings applies:
src/ tree with find vendor/sequra/middleware/src -name '*.php' | head -50. Look for Client, Signature, Webhook/Notification, Order, Builder, Credentials. Those are your entry points.README.md or docs/ in the package itself before trusting anything on the GitHub repo — the integration-middleware repo is aimed at SeQura's own connector teams, so the in-repo examples are the closest thing to documentation.First use case: signature-verified webhook/notification handling. The most valuable and most self-contained piece of any SeQura middleware is validating that an incoming order-status callback genuinely came from SeQura before you mark an order as paid or shipped. Get that working against a sandbox merchant account before touching anything else.
// routes/api.php
Route::post('/sequra/notify', [SeQuraCallbackController::class, 'handle'])
->withoutMiddleware(['web'])
->name('sequra.notify');
Register the route outside auth middleware — SeQura authenticates via signature/HMAC, not a session.
Wrap the library in your own adapter. Because the package is unversioned in practice (a single release dated 2026-10-29, no dependents), never let its classes leak into your controllers or domain code. Define a thin interface and bind it:
// app/Contracts/PaymentGateway.php
interface PaymentGateway {
public function createCheckout(Order $order): string; // returns redirect URL
public function handleNotification(Request $request): NotificationResult;
}
// app/Providers/AppServiceProvider.php
$this->app->bind(PaymentGateway::class, SeQuraGateway::class);
This lets you swap or fork the package when SeQura ships a breaking change, which is a realistic possibility given the release cadence.
Webhook processing pattern — verify, persist, queue, acknowledge.
public function handle(Request $request)
{
$payload = $request->getContent();
if (! $this->sequra->verifySignature($payload, $request->headers->all())) {
Log::warning('sequra.invalid_signature', ['ip' => $request->ip()]);
abort(401);
}
// Persist raw payload first — never parse-and-forget.
$event = SeQuraEvent::create([
'external_id' => $request->input('id'),
'type' => $request->input('event'),
'payload' => $payload,
]);
ProcessSeQuraEvent::dispatch($event)->onQueue('payments');
return response()->noContent(); // 204/200 fast; SeQura will retry on failure
}
Idempotency is non-negotiable: put a unique index on the SeQura event/order identifier and use firstOrCreate. Retries and duplicate deliveries are the norm in payment callbacks.
Two-way flow. Payment integrations are rarely webhook-only. Expect to also call out to SeQura to synchronise order status (shipped, cancelled, refunded). Isolate outbound HTTP in a single client class, inject GuzzleHttp\ClientInterface (or the package's own client abstraction) so you can fake it in tests, and set aggressive timeouts:
Http::baseUrl(config('services.sequra.base_url'))
->withToken(config('services.sequra.api_key'))
->timeout(5)
->retry(2, 200, throw: false)
->post('/orders/'.$reference.'/ship');
Environment config. Put merchant credentials in config/services.php and .env (SEQRAA_MERCHANT_ID, SEQRAA_API_KEY, SEQRAA_ENV=sandbox), not in the package's own config if it has one. If the package ships a config file, publish it and then copy the values you need into services.php so credentials live in one place.
Testing. Record real sandbox request/response pairs into tests/Fixtures/sequra/ and replay them. Build a fake PaymentGateway implementation for feature tests so the package is only exercised in a dedicated integration test suite that runs against the sandbox.
composer.json ("sequra/middleware": "1.0.0" — no caret), and consider vendoring/forking it into your own namespace. There is no Stack Overflow corpus for it, so every answer lives in vendor/.Psr\Http\Message\ServerRequestInterface handling or RequestHandlerInterface, it's PSR-15 and you'll need a bridge (or Laravel's own middleware wrapping) to run it. If it just exposes services, skip the middleware register entirely. Getting this wrong is the most likely way to waste a day.X-SeQura-Signature vs x-sequra-signature), and whether the HMAC is computed over the raw body versus a re-encoded JSON payload. Always hash $request->getContent() — never json_encode($request->all()), since key ordering and whitespace will differ and produce intermittent 401s.VerifyCsrfToken. Laravel 11+ routes in api.php are fine, but if you register the callback in web.php (common in older apps) add it to $except. Payment callbacks failing with 419 is a very common first-day bug.grep -r "interface " vendor/sequra/middleware/src and bind those to your own implementations in a service provider. If the package hard-codes new GuzzleClient() inside a class, that's your first fork candidate.php artisan vendor:publish --provider="SeQura\..." errors, the package simply doesn't ship publishable assets; don't chase it.How can I help you explore Laravel packages today?