Search by

astral-php / astral-shipping

astral-php

Frais de port multi-options pour Astral : forfait, barèmes poids/pays, Colissimo, Mondial Relay, retrait boutique, API agrégateur (Sendcloud)

Package info

github.com/astral-php/astral-shipping

pkg:composer/astral-php/astral-shipping

Statistics

Installs: 5

Dependents: 1

Suggesters: 0

Stars: 0

Open Issues: 0

0.1.0 2026-10-11 07:13 UTC

This package is auto-updated.

Last update: 2026-10-11 07:20:54 UTC


README

Frais de port multi-options pour Astral : forfait, retrait boutique, barèmes pays × poids (Colissimo / Mondial Relay), API agrégateur (Sendcloud).

PHP astral-core Tests License: MIT

Statut : 0.1.0 — MVP. Publiable sur Packagist.
Philosophie Astral : explicite, sans magie, opt-in — tu déclares les méthodes actives, rien n’est découvert automatiquement.
Ce n’est pas une version 1.0 : voir Limites MVP.

Compatibilité

astral-core PHP astral-shipping
^1.2 8.1 → 8.4 0.x

Le domaine (calcul des offres) n’a aucune dépendance au core : seuls le ServiceProvider, les DAOs et la commande console en ont.

Limites MVP (0.1.0)

Sujet Réalité
Colissimo / Mondial Relay Barèmes contrat (shipping_rates / CSV) — pas d’API transporteur officielle
Grilles tarifaires Non incluses (dépendent de ton contrat ; CSV d’exemple fictif)
Points relais Le package exige pickup_point_id ; le widget navigateur reste à brancher (doc transporteur)
Sendcloud API v2 optionnelle (SENDCLOUD_*) — panne isolée, autres méthodes restent
Boutique Intégré dans Astral Shop (profil standard : forfait + retrait) ; profils avancés = backlog shop

Installation

composer require astral-php/astral-shipping

Développement local (workspace components-astral) :

"repositories": [{ "type": "path", "url": "../components-astral/astral-shipping", "options": { "symlink": true } }]
composer require astral-php/astral-shipping:@dev

1. ServiceProvider — config/dependencies.php

return [
    // …
    AstralShipping\ShippingServiceProvider::class,
];

2. Migrations

Copie stubs/database/migrations/* vers database/migrations/ du projet hôte, puis :

php bin/console migrate
Table Rôle
shipping_rates Barèmes : méthode × pays × tranche de poids (centimes)
order_shipments Snapshot du mode de livraison de chaque commande

3. Variables d'environnement (si sendcloud est activé)

Copier stubs/.env.shipping.example dans ton .env.

4. Configuration — config/app.php

Modèle : stubs/config/shipping.example.php.

MVP boutique (recommandé pour démarrer) :

'shipping' => [
    'methods' => ['flat_rate', 'store_pickup'],
    'free_shipping_threshold_cents' => 6000,
    'rates_source' => 'config',
    'http_timeout' => 10,
    'flat_rate' => [
        'price_cents' => 590,
        'label'       => 'Livraison standard',
        'countries'   => ['FR'],
        'days'        => 4,
    ],
    'store_pickup' => ['label' => 'Retrait en boutique'],
    'rates' => [],
],

Méthodes avancées (à activer explicitement + barèmes / clés) :

'methods' => ['flat_rate', 'store_pickup', 'colissimo_home', 'colissimo_pickup', 'mondial_relay', 'sendcloud'],
'rates_source' => 'database', // ou 'config' + tableau 'rates'
'sendcloud' => ['cache_ttl' => 3600, 'markup_cents' => 0, 'carriers' => null],

Les méthodes disponibles

Code Classe Source du tarif Point relais
flat_rate FlatRateMethod Forfait (config) Non
store_pickup StorePickupMethod Gratuit Non
colissimo_home ColissimoMethod Barème shipping_rates Non
colissimo_pickup ColissimoMethod(pickup: true) Barème Oui
mondial_relay MondialRelayMethod Barème Oui
mondial_relay_home MondialRelayMethod(relay: false) Barème Non
sendcloud SendcloudMethod API Sendcloud (N offres, cache) Selon l'offre
(la tienne) ShippingMethodInterface À toi de voir —

Pourquoi des barèmes pour Colissimo et Mondial Relay ? Parce que tes tarifs dépendent de ton contrat : on les saisit (ou importe en CSV) une fois, le calcul reste instantané, hors-ligne et testable. Voir docs/colissimo-mondial-relay.md.

Utilisation

use AstralShipping\Models\{Address, ShippingContext};
use AstralShipping\Service\ShippingService;

// 1. Contexte : montants en CENTIMES, poids en GRAMMES
$context = new ShippingContext(
    subtotalCents: 4990,
    weightGrams: 1200,
    destination: new Address('FR', '75001', 'Paris'),
);

// 2. Lister les offres (triées par prix)
$quotes = $shipping->quotes($context);

// 3. Valider le choix du client — le prix est TOUJOURS recalculé côté serveur
$selection = $shipping->select($context, $_POST['shipping_method'], $_POST['pickup_point_id'] ?? null, $_POST['pickup_point_label'] ?? null);

// 4. Total à encaisser (→ astral-payment)
$total = $shipping->total($context->subtotalCents, $selection);

// 5. À la création de la commande : snapshot
$shipmentDao->record($orderId, $selection);

Vue : stubs/views/shipping/options.php → views/partials/. Exemple de contrôleur : examples/checkout-integration.php et docs/checkout-integration.md.

Barèmes

En base (recommandé)

Import CSV :

php bin/console shipping:rates:import database/rates.csv --replace

Colonnes : method_code,country,min_weight_g,max_weight_g,price_eur,estimated_days. Voir stubs/database/rates.example.csv (valeurs fictives).

Règles : poids en grammes, bornes inclusives (0–500 puis 501–1000), pays exact prioritaire sur *, à égalité le tarif le plus bas.

En config (sans base)

'rates_source' => 'config',
'rates' => [
    ['method' => 'colissimo_home', 'country' => 'FR', 'min_g' => 0, 'max_g' => 500, 'price_cents' => 495, 'days' => 2],
],

Ajouter un transporteur

Implémente ShippingMethodInterface (3 méthodes) et enregistre-la dans ton AppServiceProvider. Guide : docs/extending.md.

Principes de conception

  • Explicite : méthodes déclarées une à une, pas d'auto-découverte, pas de lazy-loading.
  • Centimes et grammes (int), jamais de float pour l'argent.
  • Serveur maître : le client envoie un code, jamais un prix.
  • Pannes isolées : si l'API d'un transporteur tombe, ses offres disparaissent, les autres restent (erreur loguée via Core\Logger).
  • Snapshot : le port d'une commande est figé dans order_shipments.
  • Opt-in : le cœur d'Astral n'est pas modifié ; tout vit dans app/ + ce package.

Structure

src/
  ShippingServiceProvider.php   # câblage conteneur (méthodes lues dans config)
  Contract/                     # ShippingMethodInterface, RateLookupInterface, HttpClientInterface
  Method/                       # FlatRate, StorePickup, TableRate, Colissimo, MondialRelay, Sendcloud
  Rate/ArrayRateTable.php       # barème en mémoire (config / tests)
  Dao/                          # ShippingRateDao, OrderShipmentDao (AbstractDao)
  Service/                      # ShippingCalculator, ShippingService
  Models/                       # Address, ShippingContext, ShippingQuote, Rate, PickupPoint, ShippingSelection…
  Events/ShippingMethodSelected # événement optionnel
  Http/CurlHttpClient.php       # client HTTP par défaut
  Console/ImportRatesCommand.php
  Exception/
stubs/
  .env.shipping.example
  config/shipping.example.php
  database/migrations/
  database/rates.example.csv
  views/shipping/options.php

Tests

composer install
composer test

La suite couvre le calcul (forfait, seuil de gratuité, barèmes, priorité pays), SendcloudMethod (client HTTP factice, cache, filtres), le calculateur (tri, doublons, isolation des pannes) et la sélection (point relais obligatoire, prix recalculé). 25 tests (2026-10).

Licence

MIT