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

Paymentsips Bundle Laravel Package

jrk/paymentsips-bundle

Symfony bundle for PaymentsIPS integration, providing configuration and services to add payment processing to Symfony applications. It helps wire payment flows with less boilerplate and quicker setup, making PaymentsIPS gateway adoption straightforward.

View on GitHub
Deep Wiki
Context7

Getting Started

  • Reality check before anything else: jrk/paymentsips-bundle is a Symfony2 bundle, not a Laravel package. It ships a *Bundle class, a DependencyInjection/*Extension, a Resources/config/services.yml, and expects registration in app/AppKernel.php. composer require jrk/paymentsips-bundle will not give you a service provider, config publishing, or facades. Treat it as a reference implementation / PHP source drop, not a drop-in dependency. There is no Laravel path to "just install it."
  • Where to look first, in this order:
    1. DependencyInjection/Configuration.php and ...Extension.php — this is the real API surface. It tells you the required parameters: merchant ID, country, currency, the pathfile path, and the path/certificate files used to sign requests.
    2. Resources/config/routing.yml — the bundle exposes a route for the return/callback URL. That route name and path shape are what you must replicate in routes/web.php.
    3. The service that builds the payment request (usually a thin wrapper around ATOS' Caisse/PaymentRequest toolkit) and the one that parses the response.
  • First use case to target: redirect-to-bank checkout. Customer clicks "Pay", you build a signed SIPS request, auto-submit an HTML form to the acquirer, customer pays, SIPS posts back to your callback URL, you validate the signature and mark the order paid.
  • Minimal viable port for Laravel: copy the two service classes out of the bundle into app/Services/Sips/ (or app/Support/Payments/), replace the Symfony container wiring with constructor injection via a PaymentServiceProvider, and replace the bundle's config.yml block with a config/payments.php file. Keep the ATOS toolkit files (bin/, lib/) exactly as vendored — they are the bank's signed binaries and must not be rewritten.
  • Before writing code: confirm with your acquirer which protocol you're on. This bundle targets the classic SIPS/1 flow (merchant sends a pathfile + request fields, bank returns a parm blob / reference). SIPS/2 and Paybox/OSB use different field sets and a JSON or key-versioned seal. If your contract is OSB or SIPS/2, most of this bundle's request-building code is wrong for you.

Implementation Patterns

  • Config-shaped service. Mirror the bundle's parameter block in a Laravel config file and inject it, so test vs. production differs only by .env:
// config/payments.php
return [
    'sips' => [
        'merchant_id'   => env('SIPS_MERCHANT_ID'),
        'country'       => 'FR',
        'currency'      => 'EUR',
        'pathfile'      => storage_path('sips/pathfile'),
        'key'           => storage_path('sips/'.env('SIPS_MERCHANT_ID').'.key'),
        'cert'          => storage_path('sips/'.env('SIPS_MERCHANT_ID').'.crt'),
        'normal_return' => route('sips.return'),
        'cancel_return' => route('sips.cancel'),
        'auto_return'   => route('sips.server'),
    ],
];
  • Never trust the browser return. SIPS sends a customer-facing redirect and a server-to-server callback. Mark the order paid only from the server-to-server leg (or from a redirect whose seal validates and whose reference you re-query against the bank). The bundle's example controller validates on redirect; that's fine for UX, not for books.
  • Build the request, then render an auto-submitting form. Classic pattern:
public function checkout(Order $order, SipsGateway $sips)
{
    $request = $sips->buildRequest([
        'amount'      => $this->toMinorUnits($order->total, 'EUR'),
        'currency'    => '978', // ISO 4217 numeric for EUR
        'order_id'    => $order->reference,
        'customer'    => ['email' => $order->email],
    ]);

    return view('checkout.redirect', [
        'action' => $sips->gatewayUrl(),
        'fields' => $request,   // signed fields
    ]);
}
  • Bind the gateway behind an interface so SIPS is swappable later:
interface PaymentGateway {
    public function buildRequest(array $payload): array;
    public function verifyResponse(array $response): bool;
    public function gatewayUrl(): string;
}

Then SipsGateway implements PaymentGateway and bind in AppServiceProvider. This is the difference between "stuck with SIPS forever" and "can drop in Stripe/Adyen for another market later."

  • Callback route as a queued job with idempotency. Don't mutate order state inline in the controller. Look up the order by PSP reference, dispatch ProcessSipsCallback, and inside the job: (1) verify seal, (2) DB::transaction + lockForUpdate(), (3) check transition is legal (pending → paid only, never paid → paid), (4) log. Key idempotency on the SIPS reference field.
  • Store the request payload for reconciliation. When SIPS comes back you'll want to compare against what you sent. A payment_attempts table with order_id, reference, amount, currency, status, raw_response (json) saves hours of "why did this one fail?" debugging.
  • Test against the SIPS sandbox with fixture requests. The bundle has no test suite — you must write one. Build a handful of known-good request/response vector pairs from the acquirer's test environment and use them as contract tests. If the acquirer provides test cards, wire them into a manual QA checklist, not necessarily automated tests.
  • Amount handling is the classic trap. SIPS uses minor units (cents). 123.45 EUR → 12345. Use integer math throughout; don't do intval($order->total * 100) — use bcmul or a money library. Currency is the ISO 4217 numeric code (978 for EUR), not the alpha code.

Gotchas and Tips

  • Composer will probably refuse to install it. Symfony2-era bundles pin PHP ~5.3–5.6 and symfony/* ~2.x, all EOL. Even if it resolves on a modern PHP runtime you gain nothing without porting. Expect composer require to either fail or drag in a wall of deprecated transitive dependencies. Don't fight it — clone the repo and copy the classes you need.
  • PSR-0 vs PSR-4. The bundle almost certainly uses PSR-0 autoloading. When you lift classes into your app, rewrite namespaces to PSR-4 or they silently won't autoload in a Laravel context.
  • PHP 5 idioms everywhere. array(), no scalar type hints, no return types, possibly long-removed functions (each(), create_function()), and $HTTP_RAW_POST_DATA-era code. Budget mechanical modernization before the code will even pass a linter on PHP 8.2/8.3. Run it through PHPStan level 5+ before you trust it in a payment path.
  • The seal logic is where bugs hide. The bundle demonstrates ATOS' seal computation (field concatenation in a specific order, optional $ prefix on empty fields, then cert signing). If your acquirer's contract uses SHA-256 seal (key_version present) rather than legacy SHA-1, this code is wrong, not just outdated. Silent declines are the symptom — you won't see an exception, just a rejected transaction. Log the bank's response code separately from the seal verification result so you can tell the two failure modes apart.
  • Logging secrets. Audit the vendored code for the signing key or certificate being written to Symfony's logger (or to error_log) in debug mode. If it's there, strip those calls before the fork goes to production. Do the same for anything that serializes the request object — payment credentials should never end up in a stack trace.
  • License status is unclear. Many micro Symfony bundles ship without an explicit license file. Before you fork, confirm there's a LICENSE or explicit grant in composer.json. If not, you have no legal right to copy the code, and the whole reference-implementation plan collapses. Check first.
  • 3DS2 / SCA is almost certainly absent. PSD2 SCA has required 3DS2 for EU card traffic since 2021. A Symfony2-era bundle almost certainly implements 3DS1 or plain redirect. If your traffic is EU cardholders, confirm in writing with your acquirer that plain redirect is acceptable (it usually isn't for card-not-present). If 3DS2 is mandatory and this bundle doesn't do it, the package cannot be leveraged at all — go to Worldline's current SDK.
  • Extension points in the bundle are Symfony-shaped, not useful in Laravel. The Extension/CompilerPass pattern has no analog. Don't try to port it — you'd be building a container adapter for a container you're not using. Replace it with a ServiceProvider + config file and move on.
  • Callback endpoint must be reachable from the internet and exempt from CSRF. SIPS posts form data. If you put the route behind web middleware with CSRF verification, every callback will 419. Put it in routes/web.php but exclude CSRF for that path, or place it in routes/api.php with session handling configured. Verify the seal, not the CSRF token.
  • Idempotency and replay protection. SIPS may retry callbacks (network flaps are common with redirect flows). If your callback handler isn't idempotent on (reference, amount, currency), retries will double-credit or corrupt state. Test by firing the same callback twice in the sandbox and verifying no state change the second time.
  • Reconciliation is not optional. Callback loss is real. Schedule a daily job that pulls SIPS' transaction report (or queries the acquirer API for stuck pending orders) and repairs state. Anything pending > X hours should alert someone.
  • If you're on Symfony 2.x already, you can actually use this thing — but Symfony 2 has been EOL since November 2018, and every dependency is a liability. That's a bigger problem than this bundle.
  • When to walk away. If the acquirer offers a maintained SDK, an Omnipay Worldline driver, or a current French-market package, use that instead. Fork this only if it's the sole surviving implementation of a legacy SIPS contract you're contractually locked into — and then budget one to two sprints for extraction, modernization, testing, callback hardening, and reconciliation, not the time you'd spend wiring up a working library.
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.
novasa/laravel-language-center
opencage/geocode
adolfoholzer/parameters
livenetworks/ln-starter
shitoudev/permissionmanager
johannesclimacus/laravel-tui
hocvt/seotools
vitalybaev/sypexgeo
amphibee/themosis-ignition
gito-me/fast-excel
frankyso/laravel-ipaymu
geolize-studio/laravel-chile
boomerangui/chat
cgv/localized-resource
noith/settings
kda/laravel-package
kda/filament-dynamic-navigation
bypersoft/signbox
pairus/product-data
fayne/laravel-filament-cms-core