PHPackages                             keirontw/relay-point-bundle - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [Payment Processing](/categories/payments)
4. /
5. keirontw/relay-point-bundle

ActiveSymfony-bundle[Payment Processing](/categories/payments)

keirontw/relay-point-bundle
===========================

Carrier-agnostic relay point (point relais) selection bundle for Symfony

v1.0.0(4d ago)00MITPHP ^8.1

Since Jul 7Compare

[ Source](https://github.com/BastienMesnil/relay-point-bundle)[ Packagist](https://packagist.org/packages/keirontw/relay-point-bundle)[ RSS](/packages/keirontw-relay-point-bundle/feed)WikiDiscussions Synced today

READMEChangelog (1)Dependencies (9)Versions (2)Used By (0)

Keirontw Relay Point Bundle
===========================

[](#keirontw-relay-point-bundle)

Carrier-agnostic relay point ("point relais") selection for any Symfony project — no e-commerce framework required. Provides a search/geocoding API, a session-backed selection store, and a ready-to-embed Stimulus widget.

Supported carriers: Mondial Relay, Chronopost, Shop2Shop, Colissimo, InPost, Colis Privé, DPD, DHL, Packeta, PostNL, Bpost, GLS.

Installation
------------

[](#installation)

```
composer require keirontw/relay-point-bundle
```

Register the bundle in `config/bundles.php` (skip this step if you use Symfony Flex and it was added automatically):

```
return [
    // ...
    Keirontw\RelayPointBundle\KeirontwRelayPointBundle::class => ['all' => true],
];
```

Import the shop routes in `config/routes.yaml`:

```
keirontw_relay_point:
    resource: '@KeirontwRelayPointBundle/config/routes/shop.yaml'
```

Configuration
-------------

[](#configuration)

Create `config/packages/keirontw_relay_point.yaml` and enable the carriers you need. Every carrier is disabled by default; only `enabled: true` carriers get wired into the container.

```
keirontw_relay_point:
    geocoding:
        provider: addok   # addok (default, free, FR-only) | nominatim | google_maps | photon | custom

    providers:
        mondial_relay:
            enabled: true
            account: '%env(MONDIAL_RELAY_ACCOUNT)%'
            password: '%env(MONDIAL_RELAY_PASSWORD)%'
            shipping_method_codes: ['mondial_relay_fr']

        colissimo:
            enabled: true
            account_number: '%env(COLISSIMO_ACCOUNT)%'
            password: '%env(COLISSIMO_PASSWORD)%'
            shipping_method_codes: ['colissimo_relay']
```

See `src/DependencyInjection/Configuration.php` for the full tree (every carrier's required options) and `src/Provider/**` for the corresponding provider implementation.

To plug your own backend instead of Addok/Nominatim/Google/Photon, set `geocoding.provider: custom` and alias the interface yourself:

```
services:
    Keirontw\RelayPointBundle\Geocoding\GeocodingProviderInterface: '@App\Geocoding\MyProvider'
```

To add a carrier the bundle doesn't ship, implement `Keirontw\RelayPointBundle\RelayPoint\RelayPointProviderInterface` — it's autoconfigured and auto-tagged, no manual service registration needed.

Frontend assets
---------------

[](#frontend-assets)

The widget is a Stimulus controller. Wire it depending on your asset pipeline:

**AssetMapper** — nothing to do. If `symfony/asset-mapper` is installed, the bundle registers its `assets/shop` directory (under the `keirontw_relay_point` namespace) automatically via `prependExtensionConfig`. The controller is picked up by `symfony/stimulus-bundle`'s auto-discovery like any other mapped asset.

**Webpack Encore** — copy `assets/shop/controllers/relay-point-picker_controller.js` into your own `assets/controllers/` and register it in your `assets/controllers.json`(or `symfony_ux` autodiscovery if you vendor it via a package).

The widget also expects [Leaflet](https://leafletjs.com/) (`L` global) to be loaded on the page for the map panel.

Embedding the widget
--------------------

[](#embedding-the-widget)

Include the template wherever you want the picker to render (checkout step, an admin order edit page, anywhere):

```
{% include '@KeirontwRelayPointBundle/shop/relay_point_picker.html.twig' with {
    searchUrl:   path('keirontw_relay_point_shop_search'),
    geocodeUrl:  path('keirontw_relay_point_shop_geocode'),
    selectUrl:   path('keirontw_relay_point_shop_select'),
    methodCodes: ['mondial_relay_fr'],
    cartToken:   cart.token,
} %}
```

`methodCodes` should be the subset of your configured `shipping_method_codes` that are actually active for the current order/cart (e.g. the customer's chosen shipping method, if it's a relay-point one). The widget only searches carriers whose method code is in that list.

See the docblock at the top of `templates/shop/relay_point_picker.html.twig` for the full list of optional variables (pre-filled address, CSS variable theming) and the Twig blocks you can override via `{% embed %}`.

Reading the customer's selection
--------------------------------

[](#reading-the-customers-selection)

The bundle does **not** assume any order/cart model — you decide when and how to persist the selection. The widget POSTs to `keirontw_relay_point_shop_select` on every pick, which stores it in the session via `RelayPointSessionStorage`.

### Option A — automatic, via the built-in checkout listener

[](#option-a--automatic-via-the-built-in-checkout-listener)

Implement `RelayPointAddressApplierInterface` once in your app:

```
use Keirontw\RelayPointBundle\Checkout\RelayPointAddressApplierInterface;
use Keirontw\RelayPointBundle\RelayPoint\SelectedRelayPoint;

final class RelayPointOrderApplier implements RelayPointAddressApplierInterface
{
    public function getCartToken(object $event): ?string
    {
        return $event->getOrder()->getTokenValue(); // adapt to your event/order model
    }

    public function apply(object $event, SelectedRelayPoint $point): void
    {
        $order = $event->getOrder();
        $order->setShippingAddress(/* map $point->street, ->city, ->postcode, ->countryCode, ... */);
    }
}
```

Then point the bundle at your own checkout-completed event:

```
# config/packages/keirontw_relay_point.yaml
keirontw_relay_point:
    checkout_listener:
        enabled: true
        event_class: App\Event\CheckoutCompletedEvent
```

The bundle registers `RelayPointCheckoutListener` as a `kernel.event_listener` for that event class. It reads the session selection, calls your applier, and clears the session — you never touch `RelayPointSessionStorage` directly. Your `RelayPointAddressApplierInterface` implementation must be the only service implementing the interface (or aliased explicitly) so autowiring can find it.

### Option B — manual

[](#option-b--manual)

Skip the config above and read the storage yourself wherever you need it:

```
use Keirontw\RelayPointBundle\RelayPoint\RelayPointSessionStorage;

$selected = $relayPointStorage->get($cartToken);
if ($selected !== null) {
    // ... apply it, then:
    $relayPointStorage->clear($cartToken);
}
```

`SelectedRelayPoint` (returned by `->get()`) exposes: `id`, `name`, `street`, `postcode`, `city`, `countryCode`, `latitude`, `longitude`, `carrierCode`, `shippingMethodCode`, `distanceInMeters`, `openingHours`.

Development
-----------

[](#development)

```
composer install
composer test        # phpunit — boots a minimal kernel with only this bundle + framework-bundle
vendor/bin/phpstan analyse
```

License
-------

[](#license)

MIT

###  Health Score

38

—

LowBetter than 83% of packages

Maintenance99

Actively maintained with recent releases

Popularity0

Limited adoption so far

Community2

Small or concentrated contributor base

Maturity42

Maturing project, gaining track record

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Unknown

Total

1

Last Release

4d ago

### Community

Maintainers

![](https://www.gravatar.com/avatar/7d0d1cc4a4560d61c8ac63f3f919b2689157708bad324fde5e270c54107d7f45?d=identicon)[keirontw](/maintainers/keirontw)

---

Tags

symfonycolissimocheckoutSymfony Bundleinpostpickupmondial-relaychronopostrelay-pointpoint-relais

###  Code Quality

TestsPHPUnit

Static AnalysisPHPStan

Type Coverage Yes

### Embed Badge

![Health badge](/badges/keirontw-relay-point-bundle/health.svg)

```
[![Health](https://phpackages.com/badges/keirontw-relay-point-bundle/health.svg)](https://phpackages.com/packages/keirontw-relay-point-bundle)
```

###  Alternatives

[easycorp/easyadmin-bundle

Admin generator for Symfony applications

4.3k17.9M389](/packages/easycorp-easyadmin-bundle)[sulu/sulu

Core framework that implements the functionality of the Sulu content management system

1.3k1.4M206](/packages/sulu-sulu)[kimai/kimai

Kimai - Time Tracking

4.8k9.0k1](/packages/kimai-kimai)[shopware/core

Shopware platform is the core for all Shopware ecommerce products.

585.6M582](/packages/shopware-core)[web-auth/webauthn-framework

FIDO2/Webauthn library for PHP and Symfony Bundle.

515100.5k3](/packages/web-auth-webauthn-framework)[web-auth/webauthn-symfony-bundle

FIDO2/Webauthn Security Bundle For Symfony

66529.9k11](/packages/web-auth-webauthn-symfony-bundle)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
