visual-punchout.com

Documentation PunchOut

Cette page résume le fonctionnement d’un catalogue PunchOut. Les noms de champs OCI et cXML, ainsi que les exemples de code, restent dans leur forme d’origine.

1. Principe de base

Un PunchOut relie l’application d’achat de l’entreprise (ERP, e-procurement) au site marchand d’un fournisseur. L’acheteur ne ressaisit pas le catalogue : il « sort » vers la boutique du fournisseur, déjà reconnu, puis revient avec un panier structuré. La commande proprement dite reste ensuite dans le circuit d’approbation de l’acheteur.

Les deux rôles sont stables :

Session

Chaque visite est une session. L’acheteur y place un jeton (BuyerCookie en cXML, ou simplement le couple HOOK_URL + paramètres de contrôle en OCI). Le fournisseur doit le restituer au retour pour que le panier soit rattaché au bon utilisateur et à la bonne demande.

Retour panier

Le paiement n’a pas lieu sur le site fournisseur. L’utilisateur clique sur un bouton du type « retourner vers l’achat ». Le navigateur poste alors le contenu du panier vers une URL de callback fournie au début : HOOK_URL pour OCI, BrowserFormPost pour cXML. L’acheteur transforme ces lignes en demande d’achat.

  1. L’employé ouvre son outil d’achat et choisit un fournisseur PunchOut.
  2. L’outil transmet une demande de session (formulaire OCI ou message cXML).
  3. Le fournisseur reconnaît le compte et affiche son catalogue, sans nouvel identifiant saisi par l’employé.
  4. L’employé compose son panier.
  5. Le site fournisseur renvoie les lignes vers l’outil d’achat.
  6. L’employé soumet la demande ; plus tard, un bon de commande peut être transmis au fournisseur.

Deux standards couvrent l’essentiel des déploiements actuels. cXML est le plus répandu auprès des plateformes d’e-procurement. OCI (Open Catalog Interface) vient de l’écosystème SAP. Le scénario fonctionnel est le même ; le format des messages change.

2. PunchOut OCI

OCI est un échange HTTP de formulaires. L’ERP ouvre le catalogue en envoyant le navigateur de l’utilisateur vers l’URL du fournisseur, en POST le plus souvent, parfois en GET. Il n’y a pas d’enveloppe XML pour l’aller : ce sont des champs nommés.

Champs typiques à l’aller

ChampRôle
HOOK_URLAdresse où le fournisseur doit poster le panier. Sans elle, le retour ne sait pas où revenir.
USERNAME / PASSWORDCompte technique du client chez le fournisseur. Ce ne sont pas les identifiants personnels de l’employé.
~OkCodeCode de fonction SAP. ADDI signifie en pratique « ajouter les articles à la demande ». D’autres codes existent selon le scénario.
~CALLEROrigine de l’appel. CTLG indique un appel depuis le catalogue.
~TARGETCible de navigation HTML (_top, _parent…). Utile quand le catalogue était affiché dans un cadre.
OCI_VERSIONVersion du dialecte OCI attendue, souvent 4.0.

D’autres champs circulent selon les projets : charset, société, langue, centre de coûts. Le fournisseur les lit s’il les connaît et ignore le reste.

Formulaire d’ouverture

Exemple illustratif, à adapter. Les valeurs ne correspondent à aucun compte réel.

<form method="post" action="https://fournisseur.exemple/oci">
  <input type="hidden" name="USERNAME" value="compte-client">
  <input type="hidden" name="PASSWORD" value="secret-exemple">
  <input type="hidden" name="HOOK_URL" value="https://achat.exemple/oci/retour">
  <input type="hidden" name="~OkCode" value="ADDI">
  <input type="hidden" name="~CALLER" value="CTLG">
  <input type="hidden" name="~TARGET" value="_top">
  <input type="hidden" name="OCI_VERSION" value="4.0">
</form>

Retour panier

Le fournisseur répond par un POST vers HOOK_URL. Chaque article est un indice entre crochets, en commençant généralement à 1. Le nom du champ porte à la fois la donnée et le numéro de ligne.

ChampContenu
NEW_ITEM-DESCRIPTION[n]Libellé affiché à l’acheteur
NEW_ITEM-QUANTITY[n]Quantité
NEW_ITEM-UNIT[n]Unité (PCE, EA, KG…)
NEW_ITEM-PRICE[n]Prix unitaire
NEW_ITEM-CURRENCY[n]Devise
NEW_ITEM-VENDORMAT[n]Référence article chez le fournisseur
NEW_ITEM-MATGROUP[n]Groupe de marchandises ou code de classement
NEW_ITEM-MANUFACTCODE[n]Code fabricant
NEW_ITEM-MANUFACTMAT[n]Référence fabricant
NEW_ITEM-LEADTIME[n]Délai, souvent en jours
NEW_ITEM-DESCRIPTION[1]=Ramette papier A4
NEW_ITEM-QUANTITY[1]=5
NEW_ITEM-UNIT[1]=PCE
NEW_ITEM-PRICE[1]=4.50
NEW_ITEM-CURRENCY[1]=EUR
NEW_ITEM-VENDORMAT[1]=PAP-A4
NEW_ITEM-DESCRIPTION[2]=Stylo bille bleu
NEW_ITEM-QUANTITY[2]=10
NEW_ITEM-UNIT[2]=PCE
NEW_ITEM-PRICE[2]=0.80
NEW_ITEM-CURRENCY[2]=EUR
NEW_ITEM-VENDORMAT[2]=STYLO-B

Le testeur OCI de ce site prépare ce formulaire, vous laisse l’envoyer, puis décode les NEW_ITEM-* reçus sur la HOOK_URL.

3. PunchOut cXML

cXML est un document XML échangé en HTTP. L’aller n’est pas un formulaire visible : le système d’achat poste un PunchOutSetupRequest au endpoint du fournisseur. La réponse contient une URL de page de démarrage. Le navigateur de l’utilisateur n’intervient qu’ensuite.

PunchOutSetupRequest

Le message a un en-tête d’identité et un corps de requête.

Pour edit et inspect, un bloc SelectedItem (ou équivalent) désigne la référence à rouvrir.

<?xml version="1.0" encoding="UTF-8"?>
<cXML payloadID="setup.exemple@achat.local" timestamp="2026-09-22T15:00:00Z">
  <Header>
    <From>
      <Credential domain="NetworkId"><Identity>AcheteurDemo</Identity></Credential>
    </From>
    <To>
      <Credential domain="DUNS"><Identity>FournisseurDemo</Identity></Credential>
    </To>
    <Sender>
      <Credential domain="NetworkId">
        <Identity>AcheteurDemo</Identity>
        <SharedSecret>secret-demo</SharedSecret>
      </Credential>
      <UserAgent>visual-punchout.com</UserAgent>
    </Sender>
  </Header>
  <Request deploymentMode="test">
    <PunchOutSetupRequest operation="create">
      <BuyerCookie>BC-EXEMPLE-001</BuyerCookie>
      <Extrinsic name="UserEmail">jean.dupont@exemple.fr</Extrinsic>
      <BrowserFormPost>
        <URL>https://achat.exemple/cxml/retour</URL>
      </BrowserFormPost>
      <ShipTo>
        <Address addressID="default">
          <Name xml:lang="fr">Jean Dupont</Name>
          <PostalAddress>
            <Street>12 rue de la Paix</Street>
            <City>Paris</City>
            <PostalCode>75002</PostalCode>
            <Country isoCountryCode="FR">FR</Country>
          </PostalAddress>
        </Address>
      </ShipTo>
    </PunchOutSetupRequest>
  </Request>
</cXML>

PunchOutSetupResponse et StartPage

Si la session est acceptée, le fournisseur répond avec un statut 200 et une URL. L’outil d’achat redirige alors le navigateur vers cette page : c’est le catalogue, déjà positionné sur le bon compte.

<cXML payloadID="reponse.exemple@fournisseur.local" timestamp="2026-09-22T15:00:01Z">
  <Response>
    <Status code="200" text="OK"/>
    <PunchOutSetupResponse>
      <StartPage>
        <URL>https://fournisseur.exemple/catalogue?session=abc</URL>
      </StartPage>
    </PunchOutSetupResponse>
  </Response>
</cXML>

Un code autre que 200, ou une page HTML d’erreur, indique un rejet : secret incorrect, identité inconnue, URL mal formée. Ce testeur affiche le code HTTP, le statut cXML s’il est lisible, et le corps brut.

PunchOutOrderMessage

Au moment de revenir, le catalogue poste un PunchOutOrderMessage vers l’URL BrowserFormPost. Le transport habituel est un formulaire dont le champ s’appelle cxml-urlencoded ou cxml-base64. Le message reprend le BuyerCookie, un en-tête avec l’opération et le total, puis une balise ItemIn par ligne.

<cXML payloadID="poom.exemple@fournisseur.local" timestamp="2026-09-22T15:04:00Z">
  <Message>
    <PunchOutOrderMessage>
      <BuyerCookie>BC-EXEMPLE-001</BuyerCookie>
      <PunchOutOrderMessageHeader operation="create">
        <Total><Money currency="EUR">9.00</Money></Total>
      </PunchOutOrderMessageHeader>
      <ItemIn quantity="2">
        <ItemID><SupplierPartID>PAP-A4</SupplierPartID></ItemID>
        <ItemDetail>
          <UnitPrice><Money currency="EUR">4.50</Money></UnitPrice>
          <Description xml:lang="fr">Ramette papier A4</Description>
          <UnitOfMeasure>EA</UnitOfMeasure>
          <Classification domain="UNSPSC">14111507</Classification>
        </ItemDetail>
      </ItemIn>
    </PunchOutOrderMessage>
  </Message>
</cXML>

Le BuyerCookie permet de retrouver la session ouverte au setup. S’il ne correspond pas, l’acheteur ne peut pas ranger le panier au bon endroit.

4. OrderRequest

Le PunchOut s’arrête au panier. Quand la demande est approuvée, l’acheteur peut envoyer un OrderRequest : numéro de commande, date, total, adresses de livraison et de facturation, lignes ItemOut (quantité, référence, prix, unité, classification). Le fournisseur répond par un statut cXML. Ce n’est plus une session de navigation : c’est un message serveur à serveur, comme le setup.

5. Comment s’en servir ici

Les URL d’exemple pointent vers le fournisseur simulé (mock/). Vous pouvez les remplacer par un endpoint réel. Les secrets préremplis sont fictifs.

Pour un fournisseur externe, l’URL de retour (HOOK_URL ou BrowserFormPost) doit être joignable depuis le navigateur qui affiche le catalogue. En local, cela fonctionne avec le fournisseur simulé. Un catalogue hébergé ailleurs ne pourra poster vers localhost que si le navigateur qui fait le retour est la même machine.