Version imprimable du sujet

Cliquez ici pour voir ce sujet dans son format original

Forum osCommerce-fr _ Developpement OsC2.3 _ Oscommerce et Paypal

Écrit par : krokus 18 Nov 2012, 13:57

Bonjour, un petit truc qui me gene depuis quelque temps entre Oscommerce et Paypal.
Oscommerce valide une commande par le retour du client sur la page checkout_success, Paypal fait un retour automatique du client apres paiement mais uniquement pour ceux qui payent avec un compte Paypal.
Donc un client qui paye sur le site Paypal avec une carte bancaire sans etre inscrit chez Paypal n'a pas de retour automatique ( et Paypal l'indique bien dans la description).
Pas de retour sur la page checkout_success veut dire pas de decompte du stock ni d'envoi d'email, la commande etant bien enregistre puisque le module paypal l'enregistre avant l'envoi sur le site Paypal.
Y aurait'il un moyen de lui faire valider la commande non pas sur le retour sur la page checkout_success mais sur la reception du paiement qui elle est bien enregistre dans le site.
Ce probleme devant bien apparaitre aussi avec d'autre moyen de paiement à partir du moment ou le retour vers la page checkout_success ce passe mal ou si le client referme son navigateur avant le retour automatique.

Écrit par : Gnidhal 18 Nov 2012, 15:51

Il existe une contribution qui pré-enregistre les commande avant paiement : http://addons.oscommerce.com/info/1168 mais je ne suis pas sur qu'elle soit absolument pertinente aujourd'hui.
Le problème de non validation de la commande existe en effet de manière récurrente (mais rare tout-de-même : environ 1%) avec certains types de paiement par CB.
Avec la plupart des modules de paiement (CMCIC, ATOS...) la validation silencieuse depuis le serveur de paiement est faite généralement même si le client ne revient pas sur checkout_success (qui active le checkout_process).
Ceci explique un taux de perte en baisse qui tend vers le nul au fur et à mesure de l'évolution des serveurs de paiement et de leur vitesse de validation. La principale cause étant en effet une lenteur de réponse du serveur de paiement qui fait sortir cette validation hors de la durée de session.
Les plus performants de ce coté sont le CMCIC (CM Nord et Est et CIC) et Systempay qui ne perdent jamais de commande.
Concernant le problème Paypal dont tu parles, avec Paypal IPN, même si la validation silencieuse ne se fait pas, la commande est enregistrée sur le site avec un status approprié (pending).
Une consultation de ton compte Paypal te permet alors de vérifier si cette commande est payée et de la valider manuellement depuis le back-office.
Aucune perte donc.

Écrit par : krokus 18 Nov 2012, 20:44

Je crois que tu n'as pas compris, il ne s'agit pas de perte ou de commande non enregistre, il s'agit de commande non valide par le retour sur checkout_success et donc pas de decompte de stock ni d'envoi d'email, alors oui on peut toujours valider la commande apres mais la n'est pas la question (meme si il n'existe pas à ce jour de module pour faire cela sur la 2.3).
La question est y aurait'il un moyen de valider la commande par le retour de paiement plutot que par le retour sur la page checkout_success.

Écrit par : Gnidhal 19 Nov 2012, 22:22

C'est ce que j'avais compris mais j'ai élargi.
Je ne vois pas le but de ta demande :
tu as la commande dans le back-office, tu peux donc la traiter après l'avoir changé de statut manuellement.
Ce qui te gène il me semble c'est que le stock ne soit pas décompté.
Dans ce cas une petite modification du script orders.php de l'admin pourrait mettre à jour le stock des commandes dans le status "pending", voire faire cela automatiquement lors du passage de l'état "pendng" à un autre état valide (autre que annulé par exemple)
Dans ta commande tu as une liste des produits qui sont vendus (table orders_products), une petite fonction peut récupérer la liste et mettre à jour les stocks des produits concernés.
C'est ça que tu veux ?

Parce que ta "validation par le retour paiement" est un concept qui m'échappe. Soit IPN valide, et les stocks sont mis à jour, soit il ne valide pas et ta commande est "pending" (en attente), soit il annule et la commande est détruite.
On peut pousser le luxe un peu plus loin :
ajout d'une table sql traçant les mouvements de stock.
Quand le décompte de stock est effectué par un script automatique, on a une trace qui défini que les produits de cette commande ont été décomptés du stock.
2 ou 3 scripts sont concernés : checkout_process, ipn.php et éventuellement le script spécifique de validation de la banque avec certains modules (cmcic par exemple)
Pour exemple, l'action de mise à jour des stock se passe ici dans le checkout_process de la 2.3.1

CODE
for ($i=0, $n=sizeof($order->products); $i<$n; $i++) {
// Stock Update - Joao Correia
if (STOCK_LIMITED == 'true') {
if (DOWNLOAD_ENABLED == 'true') {
$stock_query_raw = "SELECT products_quantity, pad.products_attributes_filename
FROM " . TABLE_PRODUCTS . " p
LEFT JOIN " . TABLE_PRODUCTS_ATTRIBUTES . " pa
ON p.products_id=pa.products_id
LEFT JOIN " . TABLE_PRODUCTS_ATTRIBUTES_DOWNLOAD . " pad
ON pa.products_attributes_id=pad.products_attributes_id
WHERE p.products_id = '" . tep_get_prid($order->products[$i]['id']) . "'";
// Will work with only one option for downloadable products
// otherwise, we have to build the query dynamically with a loop
$products_attributes = $order->products[$i]['attributes'];
if (is_array($products_attributes)) {
$stock_query_raw .= " AND pa.options_id = '" . $products_attributes[0]['option_id'] . "' AND pa.options_values_id = '" . $products_attributes[0]['value_id'] . "'";
}
$stock_query = tep_db_query($stock_query_raw);
} else {
$stock_query = tep_db_query("select products_quantity from " . TABLE_PRODUCTS . " where products_id = '" . tep_get_prid($order->products[$i]['id']) . "'");
}
if (tep_db_num_rows($stock_query) > 0) {
$stock_values = tep_db_fetch_array($stock_query);
// do not decrement quantities if products_attributes_filename exists
if ((DOWNLOAD_ENABLED != 'true') || (!$stock_values['products_attributes_filename'])) {
$stock_left = $stock_values['products_quantity'] - $order->products[$i]['qty'];
} else {
$stock_left = $stock_values['products_quantity'];
}
tep_db_query("update " . TABLE_PRODUCTS . " set products_quantity = '" . $stock_left . "' where products_id = '" . tep_get_prid($order->products[$i]['id']) . "'");
if ( ($stock_left < 1) && (STOCK_ALLOW_CHECKOUT == 'false') ) {
tep_db_query("update " . TABLE_PRODUCTS . " set products_status = '0' where products_id = '" . tep_get_prid($order->products[$i]['id']) . "'");
}
}
}

// Update products_ordered (for bestsellers list)
tep_db_query("update " . TABLE_PRODUCTS . " set products_ordered = products_ordered + " . sprintf('%d', $order->products[$i]['qty']) . " where products_id = '" . tep_get_prid($order->products[$i]['id']) . "'");

$sql_data_array = array('orders_id' => $insert_id,
'products_id' => tep_get_prid($order->products[$i]['id']),
'products_model' => $order->products[$i]['model'],
'products_name' => $order->products[$i]['name'],
'products_price' => $order->products[$i]['price'],
'final_price' => $order->products[$i]['final_price'],
'products_tax' => $order->products[$i]['tax'],
'products_quantity' => $order->products[$i]['qty']);
tep_db_perform(TABLE_ORDERS_PRODUCTS, $sql_data_array);
$order_products_id = tep_db_insert_id();

//------insert customer choosen option to order--------
$attributes_exist = '0';
$products_ordered_attributes = '';
if (isset($order->products[$i]['attributes'])) {
$attributes_exist = '1';
for ($j=0, $n2=sizeof($order->products[$i]['attributes']); $j<$n2; $j++) {
if (DOWNLOAD_ENABLED == 'true') {
$attributes_query = "select popt.products_options_name,
poval.products_options_values_name,
pa.options_values_price, pa.
price_prefix, pad.products_attributes_maxdays,
pad.products_attributes_maxcount , pad.products_attributes_filename
from " . TABLE_PRODUCTS_OPTIONS . " popt, " . TABLE_PRODUCTS_OPTIONS_VALUES . " poval, " . TABLE_PRODUCTS_ATTRIBUTES . " pa
left join " . TABLE_PRODUCTS_ATTRIBUTES_DOWNLOAD . " pad
on pa.products_attributes_id=pad.products_attributes_id
where pa.products_id = '" . $order->products[$i]['id'] . "'
and pa.options_id = '" . $order->products[$i]['attributes'][$j]['option_id'] . "'
and pa.options_id = popt.products_options_id
and pa.options_values_id = '" . $order->products[$i]['attributes'][$j]['value_id'] . "'
and pa.options_values_id = poval.products_options_values_id
and popt.language_id = '" . $languages_id . "'
and poval.language_id = '" . $languages_id . "'";
$attributes = tep_db_query($attributes_query);
} else {
$attributes = tep_db_query("select popt.products_options_name, poval.products_options_values_name, pa.options_values_price, pa.price_prefix
from " .
TABLE_PRODUCTS_OPTIONS . " popt, " .
TABLE_PRODUCTS_OPTIONS_VALUES . " poval, " .
TABLE_PRODUCTS_ATTRIBUTES . " pa
where pa.products_id = '" . $order->products[$i]['id'] . "'
and pa.options_id = '" . $order->products[$i]['attributes'][$j]['option_id'] . "'
and pa.options_id = popt.products_options_id
and pa.options_values_id = '" . $order->products[$i]['attributes'][$j]['value_id'] . "'
and pa.options_values_id = poval.products_options_values_id
and popt.language_id = '" . $languages_id . "' and poval.language_id = '" . $languages_id . "'");
}
$attributes_values = tep_db_fetch_array($attributes);

$sql_data_array = array('orders_id' => $insert_id,
'orders_products_id' => $order_products_id,
'products_options' => $attributes_values['products_options_name'],
'products_options_values' => $attributes_values['products_options_values_name'],
'options_values_price' => $attributes_values['options_values_price'],
'price_prefix' => $attributes_values['price_prefix']);
tep_db_perform(TABLE_ORDERS_PRODUCTS_ATTRIBUTES, $sql_data_array);

if ((DOWNLOAD_ENABLED == 'true') && isset($attributes_values['products_attributes_filename']) && tep_not_null($attributes_values['products_attributes_filename'])) {
$sql_data_array = array('orders_id' => $insert_id,
'orders_products_id' => $order_products_id,
'orders_products_filename' => $attributes_values['products_attributes_filename'],
'download_maxdays' => $attributes_values['products_attributes_maxdays'],
'download_count' => $attributes_values['products_attributes_maxcount']);
tep_db_perform(TABLE_ORDERS_PRODUCTS_DOWNLOAD, $sql_data_array);
}
$products_ordered_attributes .= "\n\t" . $attributes_values['products_options_name'] . ' ' . $attributes_values['products_options_values_name'];
}
}
//------insert customer choosen option eof ----
$products_ordered .= $order->products[$i]['qty'] .
' x ' . $order->products[$i]['name'] . ' (' . $order->products[$i]['model'] . ') = ' .
$currencies->display_price($order->products[$i]['final_price'], $order->products[$i]['tax'], $order->products[$i]['qty']) .
$products_ordered_attributes . "\n";
}

Tu peux transformer cette section en fonction ou simplement ajouter une ligne pour mettre à jour une table de traçage du stock.
Parallèlement tu peux t'inspirer de ce code pour créer une fonction dans l'admin qui va valider les stocks d'une commande et renseigner la même table de traçage.
Cette table de traçage a son intérêt car tu sais ainsi à quel moment une commande a été décomptée du stock et tu peux même te servir de la même fonction pour réintégrer le contenu d'une commande qui aurait été annulée (paiement par chèque jamais reçu par exemple)
En poussant plus loin on pourrait même créer une gestion de stock avancée avec le flux hebdo ou mensuel de chaque produit et prévoir tes réappros en conséquence.
Mais dans tous les cas, il va falloir coder. A moins qu'une contrib de ce type existe ? je n'en ai pas connaissance.

osCommerce est un gros "Meccano" du code de vente en ligne. Tu as le châssis, à toi d'inventer les modules qu'il te plait d'avoir.
Le code est tellement simple et évident que c'est à la porté de beaucoup de développeurs amateurs.

Écrit par : krokus 20 Nov 2012, 17:10

Merci Gnidhal pour ta reponse je vais me plonger dedans, la ou soit tu as tord soit j'ai un bug sur ma version c'est que le retour IPN ne valide pas une commande ni ne decompte un stock il enregistre juste dans la base si le paiement est fait ou pas, c'est le retour du client sur la page checkout_process qui valide la commande, decompte le stock et fait l'envoi automatique de l'email.
Pourquoi je parlais de validation par retour de paiement, bon c'est peut etre pas le terme exacte disons plutot le retour IPN qui sur beaucoup d'autre CMS valide la commande meme si le client ne revient pas sur le site, la rien alors bug ou pas bug je ne sais pas

Écrit par : Gnidhal 20 Nov 2012, 18:36

Peut-être bug dans ton IPN ou plutôt dans la config de ton compte paypal.
Paypal a changé beaucoup de choses l'été passé et dans le compte marchand tu dois peut-être configurer le chemin du script de validation IPN.
Voir la doc Paypal ou contacter directement le support Paypal sur le sujet.
J'ai été obligé de forcer les derniers comptes Paypal pour que cette validation silencieuse se fasse sans quoi un message d'erreur de ce type m'était envoyé :

Citation
Vérifiez le serveur gérant les notifications instantanées de paiement (IPN) PayPal. Les IPN envoyées à ces URL ont échoué :
-http://www.monsite.com/ext/modules/payment/paypal_ipn/ipn.php?language=french

Après une configuration manuelle, les ipn sont revenues... à voir de ce coté.

Écrit par : spacemoo 18 Jun 2013, 05:38

Bonjour.
Je déterre le sujet car apparemment il n'y a toujours pas de solution au problème.
Pour moi aussi c'est un gros problème et je ne pense pas que ce soit un "petit" problème car a chaque fois les puristes minimisent les impacts de ce problème de retour de paiement.
En gros si j'ai tout compris, lorsque un client paye par paypal, le script ipn valide la commande et vide le stock vendu et crée la facture envoi le mail.
Si le client paye par carte bleu ET ne clique pas sur le bouton, la commande est validé, mais le stock non vidé et le mail de confirmation non envoyé....C'est problématique lorsque l'on vent 2 fois le même produit dans une nuit alors qu'on en a qu' un en stock et ça oblige aussi a faire des inventaires réguliers car des fois on peu oublier de retirer du stock manuellement... bref ça fais 3 ans que ça dure.
J'ai une version 2.2RC2 d' Oscommerce et le module paypal standard.
Je me demande en fait si il n'aurais pas un 3 eme état de notification que l'on pourrait prendre en compte dans l'ipn.
Quelqu'un aurait il une doc précise récente et pas trop imbitable de Paypal ?
J'essaie aussi de trouver une solution au problème car c'est lourd a gérer.
Cordialement
SpaceMoO

Écrit par : krokus 18 Jun 2013, 10:47

bonjour, non pas de solution, même sur le forum US quand tu poses la question ils ne comprennent pas le probleme et te parle de reglage mal fait dans ton compte paypal alors que c'est un probleme purement oscommerce.
Pourquoi Oscommerce utilise le retour sur la page checkout_success pour valider une commande et pas le retour IPN, mystere, pourtant si tu as un retour IPN positif c'est que le paiement est OK donc la commande devrait etre validé, mais non il faut en plus le retour sur la page checkout_success, je ne suis pas programmeur, mais la seul façon pour moi de corriger ce bug (be oui c'est un bug) serait de modifier le fichier IPN pour qu'en plus d'enregistrer le paiement (ce qu'il fait tres bien) il valide aussi la commande et envoi l'email de confirmation de commande et que le retour sur la page checkout_success ne soit plus qu'accessoire, comme il l'est sur beaucoup d'autres cms.

Écrit par : spacemoo 19 Jun 2013, 05:37

Bonjour krokus et merci pour tes infos.
Il faut quand même reconnaître qu'a la base le problème vient du client ,je m'explique :
Si le client paye par carte bleue sur Paypal, à la fin de la procédure, il doit cliquer sur le bouton "retour au site marchand", et a 90% les gens ne le font pas. (Pour ceux qui cliquent, le stock est bien déduit et le mail est envoyé)
Donc la difficulté, c est de gérer l'erreur des gens . Il faudrait que quelqu'un de sympa nous explique exactement ce qui se passe au niveau du paiement lorsque l 'on paye avec paypal avec le module standard. Malheureusement le site Paypal est une usine a gaz et c'est super compliqué a comprendre.
Cependant, je pense que la solution ne viendra jamais du coté de paypal, donc il faut s'adapter et trouver le moyen de faire fonctionner l'oscommerce avec ce qu'on nous donne.Toutes les infos sont les bienvenues du moment qu'elles sont constructive.
merci pour les idées
cordialement
SpaceMoO

Écrit par : krokus 19 Jun 2013, 07:34

90% t'as de la chance, mes clients doivent etre fainiant je suis plus proche des 100%

Écrit par : infobarquee 12 Jul 2013, 23:01

bonjour,
je viens aussi d'avoir le même soucis.
validation du paiement dans l'admin après paiement par CB sur paypal, mais le stock n'a pas été déduit de l'achat.
pour une autre application dans mon boulot, j'utilise la validation ipn en vérifiant s'il y a "verified" dans le retour afin de valider un compte.
mais avec la 2.3.3, si l'on ne valide pas sur continuer au retour sur la boutique, ca ne déduit pas du stock.
va falloir que je creuse dans les lignes pour trouver une parade, car c'est vraiment génant cette histoire.

après, a voir comment gère oscommerce si on clique sur le lien à la fin du paiement avec paypal au lieu de laisser faire le décompte de 5-7s.

Propulsé par Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)