Carnet Wiki

paniers et commandes

Version 12 — Juin 2014 — 77.196.xx.xx

« Commandes » est un outil pour développeurs/intégrateurs et utilisateurs qui permet de gérer des commandes.
-  d’une part il permet aux utilisateurs de gérer les commandes depuis l’espace privé.
-  d’autre part, il fournit les outils permettant et aux développeurs et aux autres plugins de créer et manipuler des commandes.

Doc officielle de « commande » : http://contrib.spip.net/Commandes-4527

Éléments de doc

(de Tcharlss, le 21 mai 2014)

Un panier est séparé en 2 éléments :

-  le panier en lui même dans la table spip_paniers, il contient les trucs de base : identifiant, auteur, cookie, statut et date.

-  le contenu du panier dans la table spip_paniers_liens.
A chaque article du panier correspond une ligne dans cette table.
Elle contient 4 colonnes :

  • id_panier : l’identifiant du panier
  • id_objet : l’identifiant de l’objet
  • objet : le type d’objet
  • quantite : comme son nom l’indique

Pour ajouter un objet à un panier, on dispose d’un bouton d’action « remplir_panier », qui accepte 3 paramètres, et pas plus : objet-id_objet-quantite.

Ex :

[(#BOUTON_ACTION{
    'ajouter au panier',
    #URL_ACTION_AUTEUR{remplir_panier,#OBJET-#ID_OBJET,#SELF},
    ajax})]

On voit que ces 3 paramètres correspondent aux données de la ligne qui va être ajoutée (ou mise à jour) dans la table spip_paniers_liens.


FAQ

-  Comment gérer les tailles, couleurs et autres options d’un produit, lors d’une commande

-  Peut-on éditer une commande ? Oui, avec les crayons par exemple, en les paramétrant de manière à s’activer dans la partie privée, dans la page commande. Cf la vidéo


Témoignages d’utilisation


(De : Nathalie Brunelli, le 5 mai 2014 - complété le 25 juin pour la phase de paiement 21 mai 2014 )

Voici comment j’ai mis en place une boutique avec le trio Paniers-Commandes de Paniers-Commandes sous SPIP 3. Le paiement intervient à l’étape 7 et nécessite les plugins Paypal et Commandes payées par Paypal . Il s’agit donc plus exactement d’un bon de commande .
Le site sur lequel on peut voir le mécanisme en œuvre est bonplanmicro.com : regarder dans la rubrique « Promotions » pour voir les fiches-produits.
Étant donnée la demande particulière de mon client, je n’ai pas mis en place de paiement en ligne.

Étape 1
Installation et réglages de bases des plugins Commandes + Commandes de paniers + Paniers.

-  Pour Commandes : http://contrib.spip.net/Commandes-4527
-  Pour Commandes de paniers : http://plugins.spip.net/panier2commande.html
-  Pour Paniers : http://plugins.spip.net/paniers.html
-  La page qui m’a fait découvrir tout cela est ici : http://contrib.spip.net/Z-Commerce

Ces plugins ont été développés il y a quelques mois déjà, sur une belle idée collective de créer un système d’e-commerce digne de ce nom basé sur Zpip, mais ça a été abandonné, puis repris par d’autres, des versions différentes existent un peu partout. Récemment, certaines personnes très motivées ont repris ces pistes pour notre plus grand plaisir.
Il est à noter le fonctionnement très modulaire et la dépendance à d’autres plugins (notamment Saisies et API Prix) pour le bon fonctionnement de cette jolie mécanique (voir donc les docs respectives).

Étape 2
Création des champs extras sur la table spip_articles
 : pour l’affichage notamment de #PRIX et #PRIX_HT.

Étape 3
Préparation de la fiche-produit

Je suis partie du squelette article (à copier et renommer si on veut créer un squelette dédié à notre boutique)

  • Insertion de l’appel des champs créés pour mes besoins
  • Intégration du bouton « Ajouter au panier » :

[(#BOUTON_ACTION{<:action_ajouter:>,#URL_ACTION_AUTEUR{remplir_panier,article-#ID_ARTICLE,#SELF},ajax})]

  • Quelque part dans l’interface, j’ai mis le minipanier (fourni dans le plugin Paniers, dans noisettes/) :

<INCLURE{fond=inclure/minipanier}>
=> dès qu’on clique sur le bouton, le minipanier se met à jour.

  • Le bouton pour accéder au panier :
    <BOUCLE_ispanier(CONDITION){si #SESSION{id_panier}|oui}>
    [(#BOUTON_ACTION{<:paniers:voir_mon_panier:>,[(#URL_PAGE{commande_panier}|parametre_url{lang, #LANG})]})] 
    </BOUCLE_ispanier>

    (oui, parametre #LANG car mon site est trilingue. Pour ceux qui sont dans le même cas, je laisse les références au multilinguisme... ayant perdu parfois du temps avec ça)

Étape 4
Page de visualisation du panier

  • Chez moi, elle s’appelle commande_panier.
  • J’affiche le panier :

<div class="ajax">#FORMULAIRE_PANIER</div>

=> on affiche alors un tableau récapitulant les produits ajoutés au panier, leur quantité, leur prix, etc... avec la possibilité de modifier ces quantités (bouton Recalculer).

En dessous de ce code, j’ai inséré des boutons :

	
<BOUCLE_ispanier(CONDITION){si #SESSION{id_panier}|oui}>
<table class="nobord" width="100%">
<tr>
<td style="text-align:left" width="50%">[(#BOUTON_ACTION{<:mon_panier_vider:>,#URL_ACTION_AUTEUR{supprimer_panier_encours,'',#SELF},ajax})]</td>
<td style="text-align:right" width="50%">[(#BOUTON_ACTION{<:passer_etape_suivante:> 2 >>,[(#URL_PAGE{commande_validation}|parametre_url{lang, #LANG})]})]</td>
</tr>
</table>
</BOUCLE_ispanier>

Étape 5
Page de validation de la commande

Ma page commande_validation appelée contient :

  • une zone réservée à l’identification du visiteur : connexion ou inscription
  • le panier, de nouveau appelé
	 [(#REM) Récap panier ]
	  <h2><:paniers:mon_panier:></h2>
	      <div class="ajax">#FORMULAIRE_PANIER</div>
	      <BOUCLE_ispanier(CONDITION){si #SESSION{id_panier}|oui}>
	     	 <table class="nobord" width="100%"><tr>
	     	 <td style="text-align:left" width="50%">
[(#BOUTON_ACTION{<:mon_panier_vider:>,#URL_ACTION_AUTEUR{supprimer_panier_encours,'',#SELF},ajax})]      
	    	  </td>
	  	    <td style="text-align:right" width="50%">
	 	     <BOUCLE_isclient(CONDITION){si #SESSION{id_auteur}|oui}>
	    	  [(#BOUTON_ACTION{<:commander:>  >>,#URL_ACTION_AUTEUR{commandes_paniers,'',#URL_PAGE{commande_terminee}|parametre_url{lang, #LANG}},ajax})]
	    	  </BOUCLE_isclient>
	      	</td>
	     	 </tr></table>
		</BOUCLE_ispanier>

Notez que le bouton « commander » n’est visible que si le visiteur est devenu un auteur.
Un clic sur ce bouton provoque donc la transformation du panier en commande (c’est là qu’interviennent les bouts de code de Commandes de paniers). A cet instant, le panier est vidé, une commande est créée, commande que l’on aura le plaisir de trouver dans l’espace privé (Édition > Commandes).

Si vous avez installé Notifications avancées, la création de la commande (et les changements de statuts que vous opérerez dans le back-office) déclencheront l’envoi d’un email (tout cela est à configurer dans le plugin Commandes).

Étape 6
Page de remerciement

-* Ma page commande_terminée comporte un message de remerciement et la liste des commandes associées à l’auteur connecté.
Je pourrais tout aussi bien Dans ma page commande_terminée , ma boucle liste les commandes du client connecté ( ça me sert donc d’historique en même temps  ; si je voulais n’afficher que la dernière commande, dans ce cas je rajouterais à <code>BOUCLE_traitement(COMMANDES)</code > code>BOUCLE_traitement(COMMANDES ) le critère < code>0,1</code >. 0,1 ).

<code -* Ma dernière page commande_terminée comporte un message de remerciement et la liste des commandes associées à l’auteur connecté  :
<
code class=« spip »>

<:commande_merci :>

<:explication_fin_commande :>

<:commande_recapitulatif :>

#ANCRE_PAGINATION

<:commande_numero :>#REFERENCE

<:commande_date :> : #DATE

<:modifier_commande_statut :> [(#STATUT|commandes_lister_statuts)]

<:details_commande :>


[

(#PAGINATION)

]

message d’erreur


La boucle interroge la table spip_commandes et la table auxiliaire spip_commandes_details.

Mon expérience s’arrête là, pas de paiement donc, mais cette étape serait sans doute à intercaler entre la page de validation et la page de remerciement.


(de Nathalie B le 23 /06/2014, en attendant rédaction plus pédagogique et mieux mise en forme)

Je vais résumer ici ce que j’ai fait sur mon site pour le paiement via Paypal.

Le fichier inclure/commande récupère tous les détails de chaque commande :

Étape 7  :
Invitation Invitation au paiement

Installation et réglages de bases Gestion des plugins Paypal + Commandes commandes payées par Paypal . Paypal

- Pour Paypal : [http://plugins.spip.net/paypal.html->http://plugins.spip.net/paypal.html]
- Pour J’ai installé le plugin «  Commandes payées par Paypal : [http://plugins  » (http://plugins .
spip.net/commandes_paypal.html->http://plugins.spip.net/commandes_paypal.html]html) qui récupère le statut de la commande et les retours de Paypal (paiement complet, partiel ou rien) et qui change le statut de la commande en « payée ».

      <B_traitement>
      <h2><:commande_merci:></h2>


<h2><:commande_recapitulatif:></h2>
        
      #ANCRE_PAGINATION
 
<BOUCLE_traitement(COMMANDES){id_auteur=#SESSION{id_auteur}}{statut?}{tout}{par date} {inverse}{pagination 5}>
      <p><:commande_numero:><strong>#REFERENCE</strong><br />
      <:commande_date:> : [(#DATE|affdate_heure)]</p>
      
      <h3><:modifier_commande_statut:>
[(#STATUT|commandes_lister_statuts)]</h3>
      <br />
      <:details_commande:>
 
<INCLURE{fond=inclure/commande,id_commande=#ID_COMMANDE,statut=#STATUT}>
      <div class="separator"></div>


</BOUCLE_traitement>
      [<p class="pagination">(#PAGINATION)</p>]
      </B_traitement>
      
      <p><:commande_probleme:> <:ou_pas_connecte:></p>
            
      <//B_traitement>

Revenons à la page commande_terminée. Le fichier inclure/commande.html récupère tous les détails de chaque commande.
C’est dans ce fichier le < code>inclure/commande</code > que je place une invitation à payer (j’ai en effet opté pour une page de paiement à part) : Je ne la montre le lien vers le paiement que si le statut de la commande est « en attente de validation » (pour des raisons de fonctionnement de mon client (raisons persos : la commande doit être a alors été complétée par les vendeurs qui doivent renseigner ont renseigné taxes, frais de livraison, etc...).
D’autres messages apparaissent pour les autres statuts.

Mon code reprend le fichier inclure/commande.J’ajoute donc html et j’y ajoute (après <//B_details> et avant </BOUCLE_commande>) :

 [(#STATUT=={attente}|oui)
        <h2><a href="[(#URL_PAGE{commande_paiement}|parametre_url{id_commande,#ID_COMMANDE}
|parametre_url{lang, #LANG})]"><:commander_payer:></a></h2>       
]

Pour mon cas moi , c’est un lien vers la page de paiement, mais on peut tout tu peux parfaitement intégrer à fait intégrer ici le la place ton bouton « payer » de Paypal . ".

Étape 8 :
Le paiement

Mise en place du Le bouton Paypal

La doc en ligne du plugin est succincte mais je vous invite t’invite à regarder dans le fichier formulaires/paypal.html : on il y trouve a une liste de paramètres qui « parlent causent » avec Paypal, notamment « details », à utiliser à la place de « prix » pour transmettre un tableau contenant les articles de la commande. ).

Mon formulaire a cette tête là (’expedition’ est un champ extra que j’ai ajouté à la table spip_commandes et que les vendeurs renseignent au coup par coup) :

      #SET{prixTTC,#PRIX*}
      #SET{prixTTC,#PRIX*|plus{#GET{expedition}}}
      
      [(#FORMULAIRE_PAYPAL{#ARRAY{
      prix,#GET{prixTTC},
      libelle,Commande LE MARCHAND #REFERENCE,
      identifiant,#REFERENCE,
      redirect_ok,[(#URL_PAGE{commande_paiement_valide}|url_absolue)],
      first_name, #PRENOM,
      last_name, #NOM,
      email, #INFO_EMAIL{auteur, #SESSION{id_auteur}},
      }})]

Étape 9  :
Retour Retour vers le site après le paiement chez Paypal

Le retour vers votre site se fera grâce à 3 paramètres :

  • Utilisation du plugin « Commandes payées par Paypal » : il récupère le statut de la commande et les retours de Paypal (paiement complet, partiel ou rien) et change le statut de la commande en « payée ».
  • Réglages de votre compte Paypal (voir ci-après)
  • Préparation d’une page de retour que vous précisez dans l’appel du bouton (voir code ci-dessus) avec
    redirect_ok,[(#URL_PAGE{commande_paiement_valide}|url_absolue)].
    Rq : Le paramètre |url_absolue a eu son importance dans mon cas.

Paramétrages sur votre compte Paypal

Voilà comment ce retour a fonctionné chez moi :

  1. Sur le site de Paypal, dans Préférences > Notifications instantanées de paiement : j’active l’option de retour IPN.
    L’url de notification IPN à entrer est celle de votre site.
    Remarque : Elle n’a rien à voir avec la page de retour que vous prévoyez d’afficher au visiteur après la transaction chez Paypal, qui, elle, se renseigne dans l’appel de votre formulaire.

<blockquote class="spip">

Ce qu’en dit Tcharlss :
D’un côté, il y a l’URL de redirection après le paiement qui concerne le client. Elle est transmise directement via le formulaire de paiement paypal avec la paramètre redirect_ok.
De l’autre, il y a l’URL de notification IPN : il s’agit d’une notification « technique » qui indique si la transaction s’est bien passée : elle ne concerne pas directement le client.

</blockquote>

L’url à entrer est la page de remerciement que j’ai prévue sur mon site :
http://www.domaine.fr/spip.php?page=commande_paiement_valide

-* -# Réglage effectuéégalement , sur les indications du fichier infos.txt du plugin Paypal (je cite) :

<blockquote class="spip">

Indiquer que l’IPN envoyé par PAYPAL est UTF-8</quote >

<blockquote class="spip">

Indiquer que l’IPN envoyé par PAYPAL est UTF-8.
Un titre d’objet avec des caractères utf-8 et hop, le signal de validation IPN reçu par paypal foire (mauvais encodage).
Pour corriger cela :
-  Dans le compte marchand Paypal (s’y connecter).
-  Cliquer l’onglet « Préférences »
-  Partie « Préférences de ventes » (bas de la 2è colonne)
-  Cliquer le lien « Encodage de la langue »
-  Puis cliquer le bouton « Plus d’options »
-  Définir les 2 sélecteurs sur UTF-8 et valider
</quote > valider

Préparation de la page finale

Une Et dans ma page que j’ai appelée "commande_paiement_valide " comporte paiement_valide ", je mets un remerciement pour le paiement et un message qui explique ce qui se passera ensuite passe après dans le traitement de la commande.

On peut ici appeler les détails de la commande concernée par ce paiement si on a au préalable transmis l’id_commande dans l’url de redirection de #FORMULAIRE_PAYPAL :
redirect_ok=[(#URL_PAGE{commande_paiement_valide}|parametre_url{id_commande,#ID_COMMANDE}|url_absolue)],
et que l’on insére dans notre page :
<INCLURE{fond=inclure/commande,id_commande=#ID_COMMANDE,statut=#STATUT}>

-------------- =============

(de Tcharlss, le 6 mai 2014)

Depuis peu, Commandes prend en charge ces types « facturation » et « livraison ». Enfin, prendre en charge est un grand mot : il complète la liste des types proposés par la saisie #SAISIE{type_adresse}, qui est utilisée dans le formulaire d’édition d’une adresse, voilà tout.

Alors pour cette histoire de #TYPE sur les coordonnées, je crois que tu voulais des clarifications dans ton message précédent.
Le type sert à qualifier le lien entre une adresse un objet, et non pas l’adresse elle même. Là est la subtilité, il ne sert pas à dire : ceci est une adresse de type « livraison », mais : cette adresse est liée à cet objet en tant qu’adresse de type « livraison ». Autrement dit, le champ ’type’ n’est pas dans la table ’spip_adresses’, mais dans ’spip_adresses_liens’.
Tout l’intérêt, c’est qu’une même adresse peut être liée plusieurs fois à un objet grâce à ce champ ’type’. Par défaut, les tables de liens sont dépourvues de ce champ, ce qui fait qu’un objet ne peut-être lié à un autre objet qu’une seule fois : on ne peut par exemple associer un auteur à un article qu’une seule fois, tandis qu’on peut associer une adresse à un article plusieurs fois avec des types différents. (note : c’est aussi l’enjeu du plugin « rôles » de M.Marcillaud. Sauf qu’il parle de « rôle » au lieu de « type ».)

Si par exemple tu as un formulaire d’inscription perso, dans lequel tu veux proposer la saisie d’une adresse de livraison, tu peux faire comme ça :

- Dans le squelette du formulaire, les champs de l’adresse doivent être nommés comme ceux du formulaire d’édition normal d’une adresse : ’voie’, ’complement’ etc.
Tu peux ne mettre que ceux qui t’intéressent d’ailleurs, c’est l’intérêt.

- Dans les fonctions charger, verifier et traiter du formulaire, ’charger_fonction’ permet de réutiliser les fonctions de n’importe quel autre formulaire.
Par exemple, dans la fonction traiter, si tu rajoutes ceci en plus de tes traitements persos :

$associer_objet = "auteur|$id_auteur";
set_request('type','livraison');
// traitements du formulaire classique des adresses
$traiter_adresses_dist = charger_fonction('traiter', 'formulaires/editer_adresse');
$res = $traiter_adresses_dist('new',$retour,$associer_objet);

Hop, l’adresse va être créée et associée à l’auteur x, avec le type ’livraison’. Pour récupérer l’identifiant : $id_adresse = $res['id_adresse'];

Autrement, pour lier ponctuellement une adresse existante avec une commande par exemple :

include_spip('action/editer_liens');
objet_associer(array('adresse'=>$id_adresse), array('commande'=>$id_commande), array('type'=>'livraison'));

Mais attention ! Si jamais tu as besoin de lier 2 fois une même adresse à une commande, l’API a une limitation : elle est actuellement conçue pour faire un unique lien d’objet à objet. Donc en faisant comme suit, le 2e lien va écraser le premier (à moins d’avoir le plugin ’rôle’ installé) :

objet_associer(array('adresse'=>$id_adresse), array('commande'=>$id_commande), array('type'=>'livraison'));
objet_associer(array('adresse'=>$id_adresse), array('commande'=>$id_commande), array('type'=>'facturation'));

Dans ce cas là, il faut faire les liens « à la main » :

sql_insertq( 'spip_adresses_liens', array(
                'id_adresse' => $id_adresse,
                'objet' => 'commande',
                'id_objet' => $id_commande,
                'type' => 'livraison'
                )
            );
// idem pour facturation

A priori, tu devrais y retrouver les détails de la commande si ceux-ci ont été intégrés au bouton Paypal. Mais sinon (si tu as transmis ’prix’), la référence de ta commande (identifiant,#REFERENCE,) peut te servir à récupérer la bonne commande et ses détails dans une boucle.