Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Kptive Payment Sips Bundle Laravel Package

lelivrescolaire/kptive-payment-sips-bundle

Symfony bundle integrating the Kptive SIPS payment library, adding Atos Worldline SIPS support to Symfony applications. It wires the payment services into the framework so you can handle SIPS payment requests and responses within your project.

View on GitHub
Deep Wiki
Context7

Getting Started

Read this first: this is a Symfony bundle, not a Laravel package. There is no ServiceProvider, no facade, no config/kptive_payment_sips.php. composer require will pull symfony/http-kernel + symfony/dependency-injection, the bundle will not be auto-discovered, and the Bundle::getContainerExtension() machinery has no counterpart in Laravel. Combined with the fact that the repo is archived, 0 stars, 0 dependents, the correct mental model is:

Treat kptive-payment-sips-bundle as a reference implementation of the ATOS SIPS PayPage signing protocol, not as a dependency to install.

Minimal steps

  1. Clone the repo locally. Do not add it to composer.json.
  2. Open DependencyInjection/Configuration.php — this is the canonical list of everything SIPS needs: merchant ID, country code, currency, pathfile path, certificate path + passphrase, normal/abnormal return URLs, and the target SIPS endpoint (test vs. production).
  3. Open the request-building service next. It is the only non-obvious code in the bundle: it sorts the data array, URL-encodes it, computes the seal, and produces the Data / Encode / Seal (or DATA / SIGNATURE on newer SIPS) fields.
  4. Open the response-handling service. It parses the form-encoded callback and verifies the seal.
  5. Port those two classes into app/Services/Sips/ and delete the rest.

First use case — PayPage redirect:

POST /checkout          -> create Order, build signed payload, render auto-submit form (Blade)
POST /payment/sips/return -> verify seal, mark Order paid, redirect to thank-you

Map the bundle's config to your own config/sips.php:

return [
    'endpoint'   => env('SIPS_ENDPOINT', 'https://payment-webinit.simu.sips-atos.com/paymentInit'),
    'merchant_id' => env('SIPS_MERCHANT_ID'),
    'country'    => env('SIPS_COUNTRY', 'FR'),
    'currency'   => env('SIPS_CURRENCY', '978'), // EUR, ISO 4217 numeric
    'pathfile'   => storage_path('app/private/sips/pathfile'),
    'cert'       => storage_path('app/private/sips/certificate.p12'),
    'cert_pass'  => env('SIPS_CERT_PASS'),
    'return_url' => url('/payment/sips/return'),
];

Credentials come from the acquiring bank (Société Générale / ATOS), never from the repo.

Implementation Patterns

Pattern A — Port, don't install (do this). Copy RequestBuilder and ResponseParser into Laravel classes, inject config via constructor, and bind them in app/Providers/SipsServiceProvider.php. You keep the protocol knowledge (which is genuinely fiddly) and lose the container/config-loader baggage.

Pattern B — Sidecar microservice. If you must use the bundle verbatim, stand up a throwaway Symfony app with the bundle installed behind two routes (/build, /callback) and call it from Laravel over HTTP. Cheaper than trying to boot a Symfony DI container inside Laravel. Only worth it for a one-off migration.

Checkout controller shape

public function pay(Order $order, SipsRequestBuilder $builder)
{
    $payload = $builder->build([
        'amount'      => $order->total_cents,      // integer minor units
        'orderId'     => $order->reference,
        'customerEmail' => $order->email,
    ]);

    return view('sips.redirect', compact('payload'));
}

The Blade view is a <form method="POST" action="{{ config('sips.endpoint') }}"> with hidden Data/Encode/Seal inputs and a window.onload = () => document.forms[0].submit().

Callback controller shape

public function callback(Request $request, SipsResponseParser $parser)
{
    $result = $parser->parse($request->all()); // throws on bad seal

    DB::transaction(function () use ($result) {
        $order = Order::where('reference', $result->orderId)->lockForUpdate()->firstOrFail();
        $order->update(['state' => $result->isSuccess() ? 'paid' : 'failed', 'sips_raw' => $result->raw]);
    });

    event(new PaymentReceived($order));

    return redirect()->route('checkout.done', $order);
}

Integration tips:

  • Idempotency is mandatory. SIPS retries callbacks. Guard with a unique index on transaction_id or a processed_at timestamp checked inside the transaction.
  • The browser redirect is not authoritative. Only the server-to-server callback is. Show "pending" if the user lands back before the callback arrives; resolve via reconciliation.
  • CSRF: exclude the callback route in app/Http/Middleware/VerifyCsrfToken.php ($except = ['payment/sips/return']) and never put auth middleware on it.
  • Reconciliation job: the bundle covers PayPage only. SIPS Office (SOAP extract) is what you need to close pending orders — write a sips:reconcile command that pulls the daily file and compares. This is usually more valuable than the redirect flow itself.
  • Testing: there's no SDK to fake, so feature-test by POSTing a callback you signed with the test certificate. Keep a tests/Fixtures/sips/ certificate pair.
  • Events over returns: fire PaymentReceived / PaymentFailed so order, mail, and fulfilment logic stay decoupled from the controller.

Gotchas and Tips

  • Archived = no patches. Expect Composer conflict pain if you actually install it: pinned symfony/* constraints from the 2.x/3.x era will fight Laravel 10/11's transitive deps. This is the main reason to port instead of require.
  • Certificate paths are the #1 failure mode. Several versions resolve paths relative to the bundle's Resources/ directory. Always pass absolute paths from storage_path() / base_path() and check is_readable() at boot.
  • The seal is computed over the exact Data string. Keys sorted, URL-encoded once. Any normalization, reordering, or double http_build_query() breaks it silently — SIPS will just reject the request with a generic code. Unit-test the builder against a known-good vector from the bank's tool.
  • Callback body is form-encoded, not JSON. Use $request->all(); don't reach for $request->json().
  • Currency + amount. Amount is in minor units (cents) and currency is ISO 4217 numeric (978, not EUR). Off-by-100 bugs are the classic first-day incident.
  • Return URL behind a proxy. SIPS redirects to whatever absolute URL you submitted. If APP_URL/TrustProxies is misconfigured you'll get http:// or an internal host and a silent 404 on the way back.
  • Store the raw response verbatim (Data, Encode, Seal) in a text column. Bank support will only investigate if you can quote the exact payload, and it's your only debugging surface.
  • Log everything to a dedicated channel (storage/logs/sips.log) from day one, not after the first production failure.
  • Response code mapping — write an explicit enum/map from SIPS codes to your states. Don't str_contains the response. Log unknown codes rather than defaulting to "failed".
  • Extension points, if you do use the bundle: the response handler is typically swappable via a service alias override, and a Symfony event dispatcher fires on callback. Neither maps to Laravel's container, so porting gives you the same seams via Event::dispatch.
  • PCI scope: SIPS is a redirect gateway — card data never touches your server. Never log or persist anything card-shaped, and don't accept a "just add a card form" request without going through the bank's hosted fields.
  • Sandbox first. The bundle ships test endpoints, but the credentials are yours to obtain; there is no community support channel (archived, zero dependents), so budget time for reading the bank's PDF spec rather than searching for answers.
Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
3mdikram/worldmoneywords
snowsoft/config
itmosoft/laravel-subscriptions
larva/laravel-ai-qwen
diephp/sequences
users-au/socialite-provider
twidpay/twid-logger
mrnewport/laravel-plaid
mrnewport/laravel-repo
mrnewport/laravel-docsign
mrnewport/laravel-stow
mrnewport/laravel-flow
mrnewport/laravel-priceable
mrnewport/laravel-nestedterms
fredmeng/laravel-apidoc-generator
itstructure/laravel-multilingual-tools
pdustdar/elasticsearch
markupai/php-sdk
rlacerda83/lumem-microservice-shipment
uni-method/symfony-lib