ediverse Explorer la plateforme

À la une PEPPOL BIS Billing 3.0 L’obligation européenne d’e-invoicing arrive : France sept 2026, Belgique janv 2026, Allemagne 2025.

cXML PunchOutOrderMessage

Message qui clôt une session punchout et transfère le panier que l'utilisateur a construit chez le fournisseur vers l'ERP de l'acheteur. Posté par le navigateur, pas par le serveur fournisseur — particularité capitale du flux.

Objet de la transaction

Quand l'utilisateur clique sur "Checkout" dans le catalogue du fournisseur, le fournisseur ne poste pas le panier en serveur-à-serveur. Il génère une page HTML avec un <form> caché contenant le PunchOutOrderMessage en cXML, et soumet ce formulaire depuis le navigateur de l'utilisateur, qui le relaie vers la BrowserFormPost URL communiquée par l'ERP au moment du setup.

L'ERP réassocie le panier reçu à sa demande d'origine grâce au BuyerCookie — c'est le seul lien entre le PunchOutSetupRequest et ce message. Le PunchOutOrderMessage n'est pas une commande au sens cXML : c'est un panier qui sera transformé en OrderRequest après validation interne dans l'ERP.

Structure XML

Le DTD déclare : PunchOutOrderMessage (BuyerCookie, PunchOutOrderMessageHeader, ItemIn*). Le contenu utile est donc en trois blocs : le cookie qui sert de corrélation de session, un header qui résume les montants, et la liste des articles que l'utilisateur a placés dans son panier.

Le PunchOutOrderMessageHeader est défini comme : (SourcingStatus?, Total, ShipTo?, Shipping?, Tax?, SupplierOrderInfo?). Seul Total est obligatoire au contenu. L'attribut operationAllowed est #REQUIRED et indique le type d'opération que l'acheteur peut faire sur le panier : create (utiliser tel quel), inspect (le réouvrir en lecture seule plus tard) ou edit (le réouvrir pour modification — implique que le fournisseur stocke l'état pour pouvoir le restaurer).

xml punchout-order-message.cxml.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE cXML SYSTEM "http://xml.cxml.org/schemas/cXML/1.2.069/cXML.dtd">
<cXML payloadID="260513.150500.poom@supplier.example"
      timestamp="2026-05-13T15:05:00+02:00"
      version="1.2.069">
  <Header>
    <From>
      <Credential domain="DUNS"><Identity>987654321</Identity></Credential>
    </From>
    <To>
      <Credential domain="DUNS"><Identity>123456789</Identity></Credential>
    </To>
    <Sender>
      <Credential domain="DUNS">
        <Identity>987654321</Identity>
        <SharedSecret>shared-secret-here</SharedSecret>
      </Credential>
      <UserAgent>supplier-catalog/3.2</UserAgent>
    </Sender>
  </Header>
  <Message>
    <PunchOutOrderMessage>
      <BuyerCookie>session-abc-12345</BuyerCookie>
      <PunchOutOrderMessageHeader operationAllowed="edit">
        <Total>
          <Money currency="EUR">129.97</Money>
        </Total>
        <ShipTo>
          <Address>
            <Name xml:lang="fr">Acheteur SA — Site Paris</Name>
            <PostalAddress>
              <Street>10 rue de la Paix</Street>
              <City>Paris</City>
              <PostalCode>75002</PostalCode>
              <Country isoCountryCode="FR">France</Country>
            </PostalAddress>
          </Address>
        </ShipTo>
      </PunchOutOrderMessageHeader>
      <ItemIn quantity="3" lineNumber="1">
        <ItemID>
          <SupplierPartID>SKU-A100</SupplierPartID>
        </ItemID>
        <ItemDetail>
          <UnitPrice><Money currency="EUR">29.99</Money></UnitPrice>
          <Description xml:lang="fr">Chaise de bureau ergonomique noire</Description>
          <UnitOfMeasure>EA</UnitOfMeasure>
          <Classification domain="UNSPSC">56101504</Classification>
          <ManufacturerName>Acme Furniture</ManufacturerName>
        </ItemDetail>
      </ItemIn>
      <ItemIn quantity="2" lineNumber="2">
        <ItemID>
          <SupplierPartID>SKU-B200</SupplierPartID>
        </ItemID>
        <ItemDetail>
          <UnitPrice><Money currency="EUR">20.00</Money></UnitPrice>
          <Description xml:lang="fr">Repose-pieds réglable</Description>
          <UnitOfMeasure>EA</UnitOfMeasure>
          <Classification domain="UNSPSC">56121601</Classification>
          <ManufacturerName>Acme Furniture</ManufacturerName>
        </ItemDetail>
      </ItemIn>
    </PunchOutOrderMessage>
  </Message>
</cXML>

Requis vs optionnel

Dans le corps du message : BuyerCookie et PunchOutOrderMessageHeader sont obligatoires (cardinalité 1), les ItemIn* sont optionnels mais en pratique présents — c'est l'objet du message. Un panier vide est théoriquement possible (utilisateur qui sort sans rien acheter) mais inhabituel.

Sur PunchOutOrderMessageHeader : operationAllowed est #REQUIRED, quoteStatus a une valeur par défaut "final" (alternative : "pending"). Le contenu impose un Total obligatoire ; ShipTo, Shipping, Tax, SourcingStatus et SupplierOrderInfo sont optionnels.

Sur chaque ItemIn : quantity est #REQUIRED, lineNumber est #IMPLIED (mais quasi systématiquement fourni). Le contenu impose ItemID et ItemDetail. Le ItemDetail impose UnitPrice, au moins une Description, UnitOfMeasure et au moins une Classification.

Patterns courants

Le navigateur comme courrier n'est pas un détail : cela signifie que le serveur fournisseur ne connaît jamais l'URL BrowserFormPost sous sa forme finale (il pourrait être derrière un load balancer interne de l'acheteur). Il ne signe pas non plus le message côté HTTP — c'est le contenu cXML lui-même qui porte les credentials, et l'ERP authentifie via le SharedSecret partagé et le BuyerCookie.

Le panier d'un punchout est complet et autonome : pas de référence à un quelconque OrderRequest préalable. Chaque ItemIn doit porter le prix, la description, l'unité et la classification. L'ERP s'en servira pour générer son propre OrderRequest après validation.

Astuce d'implémentation : générer aussi un identifiant côté supplier dans SupplierOrderInfo pour pouvoir corréler ultérieurement OrderRequest ↔ panier punchout.

Flux Punchout (vue finale)

Le PunchOutOrderMessage est l'étape 2 du flux complet :

plaintext punchout-checkout-flow.txt
Acheteur (ERP)         Navigateur utilisateur         Fournisseur (catalogue)
      │                          │                                  │
      │                          │   (session web active)           │
      │                          │◄─────────────────────────────────┤
      │                          │                                  │
      │                          │   l'utilisateur clique "Checkout"
      │                          │                                  │
      │                          │   1. génère PunchOutOrderMessage │
      │                          │      avec BuyerCookie + ItemIn*  │
      │                          │◄─────────────────────────────────┤
      │                          │                                  │
      │  2. HTTP POST navigateur ► BrowserFormPost URL (cXML body)  │
      │◄═════════════════════════╪                                  │
      │                          │                                  │
      │  3. ERP réassocie via BuyerCookie, charge le panier         │
      │  4. workflow validation interne, puis...                    │
      │                          │                                  │
      │  5. OrderRequest (serveur-à-serveur)                        │
      ├──────────────────────────────────────────────────────────►  │

Documentation