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

Colissimo Bundle Laravel Package

lexik/colissimo-bundle

Symfony bundle for Colissimo shipping integration. Generate labels, print parcel documents, and track deliveries via the Colissimo web services API, with configurable credentials, addresses, and label formats for simple French postal shipping workflows.

View on GitHub
Deep Wiki
Context7

Getting Started

Don't install the bundle. lexik/colissimo-bundle is a Symfony 2 bundle — it registers a Bundle class, ships XML/YAML service definitions, and has no Laravel service provider, facade, or config publishing. composer require lexik/colissimo-bundle in a Laravel 10/11 app will at best fail to autoload anything useful and at worst drag EOL Symfony 2 components in. Treat the package as a reference implementation, not a dependency.

What you actually consume is the thing it wraps: lexik/ws-colissimo, a SOAP client for La Poste's WSColiPosteLetterService. Minimal path:

composer require lexik/ws-colissimo
php -m | grep soap   # ext-soap must be present in the image
  1. Read the underlying library's README first. The bundle's entire job is DI wiring + config; the request/response shape (generateLabel([...]), getBordereau(), messages) lives in lexik/ws-colissimo. Everything below maps to that API.
  2. Config goes in config/services.php + .env, not app/config/config.yml:
    'colissimo' => [
        'wsdl'     => env('COLISSIMO_WSDL'),
        'login'    => env('COLISSIMO_LOGIN'),
        'password' => env('COLISSIMO_PASSWORD'),
    ],
    
    These map to the library constructor args (WSDL URL, WS-Security login, password, SOAP options). Production and validation URLs are different — keep both in .env.example.
  3. Bind a singleton in AppServiceProvider::register() so the SOAP client isn't rebuilt per resolution:
    $this->app->singleton(ColissimoClient::class, fn () => new ColissimoClient(
        config('services.colissimo.wsdl'),
        config('services.colissimo.login'),
        config('services.colissimo.password'),
    ));
    
  4. First use case: an artisan command (php artisan colissimo:smoke) that generates one label for hard-coded sender/addressee with outputFormat: 'PDF', base64-decodes getBordereau(), asserts the bytes start with %PDF, and writes /tmp/test.pdf. Only wire it into orders after that passes against the sandbox.

Implementation Patterns

Don't use the vendor client in controllers. Wrap it behind an interface so the SOAP detail never leaks into your domain and so you can swap to a carrier aggregator later (Sendcloud/Boxtal) without touching checkout code.

interface ShippingProvider
{
    public function createLabel(Shipment $shipment): Label;
    public function track(string $trackingNumber): TrackingStatus;
}

Constructor injection over app(). Laravel makes container lookups easy; resist it. The Symfony bundle's whole value proposition was "inject the service" — preserve that habit.

final class ColissimoShippingProvider implements ShippingProvider
{
    public function __construct(private ColissimoClient $client) {}

    public function createLabel(Shipment $shipment): Label
    {
        $response = $this->client->generateLabel([
            'outputFormat' => 'PDF',
            'letter'  => ['service' => 'DOM'],
            'parcel'  => ['weight' => $shipment->weightKg()],
            'sender'    => $shipment->sender->toColissimoArray(),
            'addressee' => $shipment->recipient->toColissimoArray(),
        ]);

        $this->guardAgainstColissimoErrors($response);

        return new Label(base64_decode($response->getBordereau()));
    }
}

Keep array-key mapping in value objects. Colissimo requests are large associative arrays with fussy keys (addressee.line1, parcel.weight, letter.service). Put Address::toColissimoArray() / Parcel::toColissimoArray() next to your models so a schema change is one edit, not a grep across controllers.

Run label generation on a queue. The endpoint is slow and flaky. Dispatch a GenerateShippingLabel job from an OrderPaid listener, with $tries = 3 and exponential backoff. Check "does a label already exist for this order?" at the top of the job — retries must be idempotent or you'll burn duplicate bordereaux.

Persist the PDF, don't regenerate it. Decode getBordereau() once, Storage::disk('shipments')->put("labels/{$order->id}.pdf", $pdf), and serve from there. Customers hitting "print label" should never trigger a SOAP call.

Surface Colissimo's business errors. A successful HTTP/SOAP round-trip can still carry error-level entries in the response messages array. Parse them, log the message text verbatim (it's often French and is your only diagnostic signal), and throw a domain exception — never return a half-built label.

Test by binding a fake, not by hitting La Poste.

$this->app->instance(
    ColissimoClient::class,
    new FakeColissimoClient(base64_encode('%PDF-1.4 ...')),
);

That's the whole reason you wrapped the interface — the vendor class itself has no meaningful test seam.

Log the envelope, redact the credentials. When something breaks, the SOAP request/response body is what you need. Log it at debug level with the WS-Security header stripped.

Gotchas and Tips

  • ext-soap will be missing from your deploy image. Sail, Forge-provisioned boxes, and slim Docker base images routinely omit it. Add docker-php-ext-install soap (plus libxml2-dev) or your first production label fails at runtime, not build time. Gate deploys on php -m | grep -q soap.
  • The credentials are WS-Security credentials, not the Colissimo web portal login. They come from the contract and are typically different. Mixing them up produces an opaque auth fault with no useful message.
  • No Flex recipe, no auto-discovery, no config:cache integration. Anything the bundle did at container-compile time you now do in AppServiceProvider. Remember php artisan config:cache bakes .env values — use config('services.colissimo.*') at runtime, never env().
  • WSDL caching bites during rotation. The SoapClient will cache the WSDL locally (default cache_wsdl behaviour) and happily use a stale one after La Poste moves the endpoint. Pin an explicit cache path per environment and clear it in your deploy script; when you see "could not connect" against a URL that works in curl, this is usually why.
  • PHP 8 compatibility is not guaranteed. Check the underlying library's composer.json PHP constraint before committing. If it's ~5.6|~7.0, you're maintaining a fork — budget for that explicitly rather than discovering it in CI.
  • Set connection_timeout low. SOAP defaults are generous; a 60s hang inside even a queued job stalls a worker. 10–15s with a queue retry is a better trade than one long block.
  • Idempotency keys are your responsibility. The library (and the bundle) provide no duplicate protection. Store a deterministic key per order/shipment before the call and check it in the retry path, or a timeout-plus-retry becomes two labels and a carrier dispute.
  • Address validation failures are the most common error class. Colissimo is strict about line formatting, postcodes, and country-specific fields; international parcels additionally need customs declarations that the wrapper does not model for you. Validate and normalise addresses before the call so failures are deterministic and visible in your own logs.
  • Tracking status semantics are undocumented in English. The status codes and their mapping (in transit / delivered / returned / awaiting pickup) need a lookup table you own and version. Don't assume the code strings are self-describing.
  • Maintenance reality: 17 stars, zero dependents, an EOL Symfony 2 target. Assume no upstream fixes, monitor La Poste's WSDL for drift, and keep the ShippingProvider boundary clean so switching to an aggregator is a week's work, not a rewrite.
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.
skyraptor/chatter
edlugz/sasapay
abbasudo/artisan-route
mirvan/ippanel
ignibyte/aic-framework
glavweb/data-schema-bundle
glavweb/datagrid-bundle
tacticmedia/scim-server
uni-method/frame
neika-ai/sdk
adachsoft/php-code-style
pharaonic/laravel-notification-dependencies
beautinow/translug
dev-brainiac/bot-cloaked
octoberrain/html
octoberrain/extension
octoberrain/exception
octoberrain/contracts
adachsoft/api-version-bundle
cgv/localized-resource