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

Dhlparcelapibundle Laravel Package

keesschepers/dhlparcelapibundle

A Symfony bundle for integrating the DHL Parcel API into PHP applications. It helps configure DHL Parcel credentials and access shipping services such as creating shipments, generating labels, and tracking parcels from within Symfony.

View on GitHub
Deep Wiki
Context7

Getting Started

Decide the mode before you type composer require. This package is a Symfony 2 bundle, not a Laravel library. In a Laravel app there is no supported install path — the bundle's *Bundle class, DI extension, and XML/YAML service wiring are not consumed by Laravel's container. Treat this package as reference source code, not a dependency. Concretely: clone the repo and read it; do not add it to composer.json.

Reading order (this is the "getting started" that actually pays off):

  1. DependencyInjection/ — the configuration tree. This tells you every credential and environment option the DHL client needs (API key/secret, test vs production base URL, account/customer IDs). That config tree is your config/dhlparcel.php spec.
  2. Resources/config/*.xml|yml — the service definitions. This shows which class wraps the HTTP client and how it's constructed. That class is the only thing worth porting.
  3. The wrapper service class itself — request builders, DTOs, response parsers. This is where the DHL payload schemas, auth headers, and error handling live.
  4. Any *Bundle.php and event subscribers — ignore these. They are Symfony glue with zero value in Laravel.

If you are on a legacy Symfony 2.x app (the only context where this installs), the minimal steps are: register the bundle in AppKernel.php, add the dhl_parcel_api config block with sandbox credentials, inject the service into a controller via the service container, and call it directly. That's the intended happy path.

First use case: manual label creation in an internal admin tool. Not checkout, not customer-facing tracking. Generate a single label for an order from an admin screen, print it, and inspect the raw response. That gives you your first recorded sandbox fixture and confirms whether the DHL contract this bundle targets is still accepted.

Before writing any code, open the DHL Parcel Benelux developer documentation and diff it against what you found in step 3. DHL moved from older SOAP/XML interfaces toward REST/JSON; if the bundle targets the old contract, your real starting point is the official docs, and this repo is just a shape reference.

Implementation Patterns

Extract-then-wrap (the primary pattern). Read the bundle's request builders and response parsers and write them down as a contract — endpoint paths, auth headers, payload fields, error codes. Then build a Laravel-native client against that contract:

// config/dhlparcel.php
return [
    'base_url'  => env('DHL_PARCEL_BASE_URL', 'https://sandbox...'),
    'api_key'   => env('DHL_PARCEL_API_KEY'),
    'api_secret'=> env('DHL_PARCEL_API_SECRET'),
    'account_id'=> env('DHL_PARCEL_ACCOUNT_ID'),
];
// app/Services/Shipping/DhlParcelClient.php
class DhlParcelClient
{
    public function __construct(private array $config) {}

    public function createLabel(LabelRequest $request): LabelResponse
    {
        $response = Http::withBasicAuth($this->config['api_key'], $this->config['api_secret'])
            ->baseUrl($this->config['base_url'])
            ->acceptJson()
            ->post('/shipments', $request->toArray());

        $response->throw();
        return LabelResponse::fromArray($response->json());
    }
}

Bind it in a service provider, keep controllers thin, and put all DHL logic behind one class.

Interface boundary. Wrap the client behind a ShippingProvider interface with a DhlParcelAdapter. This contains DHL-specific logic to one file and makes a later switch to a maintained SDK or an aggregator a one-line binding change, not a refactor.

Sandbox-first contract tests. Before wiring to fulfilment, record real sandbox responses and assert your parsers handle them. The bundle gives you the shape; only the sandbox confirms it's current.

Asynchronous label generation. Label creation is often a synchronous step in fulfilment. Put it on a queued job with retry and backoff, and enforce idempotency so a retry doesn't produce a duplicate shipment and duplicate carrier charge.

Legacy Symfony pattern. If you're genuinely in Symfony 2.x: inject the bundle's service into controllers, keep the config tree per environment (test vs production), and do not let the API client leak into domain code — same interface boundary applies.

Gotchas and Tips

  • It will not install into Laravel. Attempting composer require pulls Symfony 2-era constraints (PHP 5.x/7.0-era Guzzle, PHPUnit) that conflict with any modern app. This is a dead end that eats time — don't start there.
  • Symfony 2 reached EOL in November 2018. No security patches, no PHP 8.x compatibility. If you vendor any of this code, expect deprecation notices, dynamic-property warnings, and possible fatals from removed functions. Run PHPStan (level 5+) on anything you copy before trusting it.
  • API drift is silent. A Symfony2-era bundle almost certainly targets the older DHL contract. Endpoint or schema changes surface as runtime parse failures, not deprecation warnings. Validate responses strictly and alert on non-2xx and schema mismatches.
  • Idempotency. Retries without idempotency keys create duplicate labels and duplicate charges. Confirm whether the DHL API you target supports idempotent requests and enforce it in the client.
  • Credential rotation. Sandbox-to-production credential swaps are a common outage cause. Treat credentials as config with expiry monitoring, not hardcoded values.
  • Never block a customer-facing path on a DHL call. Latency and outages back up order processing. Queue it, retry it, and surface status asynchronously.
  • The only reusable seam is the wrapper service. The config tree, DI wiring, and subscribers are disposable. Extract the transport logic (signature calculation, label PDF assembly) only if it's genuinely non-trivial — otherwise re-derive it from the docs.
  • Zero stars, zero dependents, no maintainer. There is no upstream to escalate to and no community to catch regressions. If you vendor anything, you own it permanently — including a security review on every PHP runtime upgrade. Make that an explicit, signed-off decision.
  • Debugging tip: log raw request/response pairs from the extracted client at the start. When a production label fails, the raw body is what tells you whether it's auth, schema, or a carrier outage — the bundle's own error handling won't help, and there's no community corpus to search.
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.
pharaonic/laravel-notification-dependencies
beautinow/translug
dev-brainiac/bot-cloaked
octoberrain/html
octoberrain/extension
octoberrain/exception
octoberrain/contracts
frankyso/ipaymu
3mdikram/worldmoneywords
snowsoft/config
itmosoft/laravel-subscriptions
larva/laravel-ai-qwen
adachsoft/api-version-bundle
cgv/localized-resource
noith/settings
kda/laravel-package
kda/filament-dynamic-navigation
bypersoft/signbox
pairus/product-data
fayne/laravel-filament-cms-core