Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

commandes en double #46

Closed
nicolain06 opened this issue Feb 2, 2016 · 75 comments
Closed

commandes en double #46

nicolain06 opened this issue Feb 2, 2016 · 75 comments

Comments

@nicolain06
Copy link

Bonjour, certaines commandes sont doublées après réception du paiement : 2 commandes identiques sont insérées à la même seconde. Avez-vous déjà eu le soucis ? une idée pour le corriger ?

@tucoinfo
Copy link
Contributor

tucoinfo commented Feb 2, 2016

Bonjour, moi aussi, mais depuis quelques jours seulement, et sans avoir touché au site.

OVH mutu - PS 1.6.1.1 - TGGATOS v3.1.0 (Mercanet)

@nicolain06
Copy link
Author

idem, je n'ai rien touché et ça arrive depuis quelques jours également. PS 1.6.1.4 (dernière version) - ça marchait parfaitement avant.

@tucoinfo
Copy link
Contributor

tucoinfo commented Feb 2, 2016

Ca sent le petit changement coté bancaire/ATOS. Perso je n'ai reçu aucun avertissement de leur part (même jamais rien). Je suis certain que TGG va nous tirer ça au clair.

@TrogloGeek
Copy link
Owner

Hello,

Je suis certain que TGG va nous tirer ça au clair.

Pas si sur, j'ai rejoint la start up française LiveMon en fin d'année dernière et cela me laisse peut de temps pour jouer avec PrestaShop.

@nicolain06 Quelle banque ? Quelle version du module ?

@nicolain06 @tucoinfo Vos doublons sont-ils liés tous deux au même ID panier ou le panier est-il lui aussi dupliqué ?

step 1

Vérifiez les response logs du module pour regarder si les réponses relatives à ces commandes sont présentes en double aussi. Le module vérifie que le panier n'est pas déjà associé à une commande avant de traiter la réponse bancaire, mais comme le reste de PrestaShop ce module n'utilise pas de transactions SQL => une race condition reste possible, dans certains cas de forte charge j'ai pu observer des serveurs SIPS envoyant des séquences de validation de commande incohérentes (souvent une réponse de transaction annulée + une réponse de transaction confirmée).

step 2

Vérifier si ces commandes contenaient un ou plusieurs produits en rupture de stock : cette partie du code de PrestaShop est bien connu pour avoir provoqué de nombreuses anomalies sur les commandes (commandes sans statut, commandes corrompues, commandes avec séquence de statuts incohérente...).

step 3

Pourriez-vous lister tous les deux les modules greffés sur les hooks de validation de commande et de changement de statut de commande voir s'il y a là un point commun suspect ?

@tucoinfo
Copy link
Contributor

tucoinfo commented Feb 2, 2016

Salut Damien,

Vos doublons sont-ils liés tous deux au même ID panier ou le panier est-il lui aussi dupliqué ?

Oui, liés au même ID panier, oui le panier est visiblement dupliqué avec 2 IDs différents.

step 1

Oui, le .log montre des doublons : même transaction_id, même order_id, tout pareil sauf customer_email et customer_ip_address qui sont vides dans le 2ème.
Certes, la DB devient lourde pour une mutu, le BO est très lent (bug BO je pense) mais le FO va plutôt bien. Cela dit je dois de toute façon trouver du temps pour migrer sur mon SD.

step 2

Peut pas conclure de mon coté. Une commande avec alerte mail de rupture mais pas encore vraiment le cas (juste en dessous du seuil d'alerte).

step 3

Je ne sais pas si c'est tout ceci mais voici :
actionOrderReturn :
-- Customer loyalty and rewards
-- Mail alerts
actionOrderStatusPostUpdate :
-- Cross-selling
actionOrderStatusUpdate :
-- Customer loyalty and rewards
displayOrderConfirmation :
-- GG Analytics

@TrogloGeek
Copy link
Owner

Oui, liés au même ID panier, oui le panier est visiblement dupliqué avec 2 IDs différents.

Comment cela ? le doublon ne peut pas à la fois être lié au même ID panier et à l'ID un panier dupliqué.

Oui, le .log montre des doublons : même transaction_id, même order_id, tout pareil sauf customer_email et customer_ip_address qui sont vides dans le 2ème.

Oui, le .log montre des doublons : même transaction_id, même order_id, tout pareil sauf customer_email et customer_ip_address qui sont vides dans le 2ème.

Quid du return_context ? Si l'une des deux réponses est la réponse silencieuse, l'autre le retour utilisateur alors il s'agit d'une cinématique normale.

@nicolain06
Copy link
Author

Banque SMC, version 4.0.0 du module.

J'ai bien les entrées en double dans le log, ainsi que dans la base de données. Le id_cart est le même sur les deux enregistrements (voir PJ des logs & bdd)

Step 2 : aucune commande contenant des produits en rupture

Step 3 :
actionOrderReturn :
-- Customer loyalty and rewards
-- Mail alerts
actionOrderStatusPostUpdate
-- Meilleures ventes
-- Tableau de bord des tendances
actionOrderStatusUpdate
-- expertise prestashop
-- programme de fidélité
-- programme parrainage client
-- home page top seller tab
-- home page top seller carrousel

1
2
3

@tucoinfo
Copy link
Contributor

tucoinfo commented Feb 3, 2016

Comment cela ? le doublon ne peut pas à la fois être lié au même ID panier et à l'ID un panier dupliqué

ID panier A = ID order X
ID panier A = ID order Y

Quid du return_context ? Si l'une des deux réponses est la réponse silencieuse, l'autre le retour utilisateur alors il s'agit d'une cinématique normale.

Je ne sais pas trop, mes entrées return_context ont toujours était non renseigné selon le log.

@nicolain06
Copy link
Author

PS : même soucis depuis quelques jours sur un autre prestashop complètement séparé avec le module v3.3.1

@tucoinfo
Copy link
Contributor

tucoinfo commented Feb 3, 2016

PS : même soucis depuis quelques jours sur un autre prestashop complètement séparé avec le module v3.3.1

Oups je vois ça moi aussi sur un autre site PS 1.6.0.14 / TGGATOS 3.4.0 et là il n'y a vraiment aucun souci de puissance (SD optimisé).

@84pixels
Copy link

84pixels commented Feb 4, 2016

Même problème sur Prestashop 1.6.0.6 et le module TGG 4.0.0 avec Sherlocks LCL.

  • Commandes en double avec le même ID de transaction.
  • Pas de rupture de stock dans les commandes concernées
  • Doublons dans les logs :

2016-02-04-a-11 25 17

@TrogloGeek
Copy link
Owner

Ce ne sont pas des doublons : une response_type user et une silent correspondent au workflow standard.

Le problème semble venir d'une race condition à débusquer dans PaymentModule::validateOrder() entre
if (Validate::isLoadedObject($this->context->cart) && $this->context->cart->OrderExists() == false) {
et $result = $order->add();

Lorsque plusieurs personnes se mettent subitement à avoir un problème de timing sur des versions différentes, il faut généralement rechercher quel est le webservice commun dont les latences ont récemment augmenté.

@TrogloGeek
Copy link
Owner

PS: il vaut mieux désactiver temporairement le mode NO_RESPONSE_PAGE qui renforce les risques de déclancher cette race condition en diminuant fortement le délai entre les réponses silencieuses et retour utilisateur.

Je vois une manière de résoudre ce problème de race condition interne à PrestaShop depuis le module via une page de mise en attente avec ping ajax et une table de verrou sur les ID paniers, mais cela représente un temps de développement substantiel dont je ne dispose pas actuellement.

@TrogloGeek
Copy link
Owner

ERRATUM
SIPS doit avoir changé son mode de fonctionnement : auparavant l'utilisateur était mis en attente de la fin de la réponse silencieuse avant soit qu'il soit renvoyé vers la boutique (NO_RESPONSE_PAGE) ou que la banque lui présente la page de confirmation.

La race condition n'était auparavant pas possible grâce à cette mise en attente de la fin de réponse silencieuse, cette mise en attente a du être retirée par SIPS, il faut les contacter à ce sujet (je n'ai personnellement aucun contrat VAD et donc aucun accès support auprès de SIPS ou d'une banque exploitant SIPS).

@tucoinfo
Copy link
Contributor

tucoinfo commented Feb 5, 2016

Je vais les contacter et plus on sera nombreux plus on aura de réponses.

@TrogloGeek
Copy link
Owner

Un workaround temporaire bien immonde pourra être simplement d'ajouter un sleep() ou usleep() sur le controlleur userreturn donnant un délai suffisant (le délai nécessaire dépendant des performances de la boutique, 200ms devraient suffire pour une boutique rapide, jusqu'à 2s pour les plus lentes) à la réponse silencieuse pour enregistrer la commande en BdD avant que la réponse utilisateur ne commence son traitement.
La fiabilité de ce fix ne sera bien évidemment parfaite, on ne corrige jamais une race condition par une attente aveugle via un délai réglé minutieusement au pifomètre, mais cela devrait sérieusement réduire les occurences de cette race condition.

Si quelqu'un a un peu de temps pour coder, il faudrait implémenter une table de verrou sur l'ID panier et mettre l'utilisateur en attente tant que le verrou est en place. Ou implémenter les transactions avec rollback.

@TrogloGeek
Copy link
Owner

Je vais les contacter et plus on sera nombreux plus on aura de réponses.

Oui, avec SIPS il faut monter au créneau en masse, si un seul utilisateur a un problème, ce n'est pas leur problème.

@84pixels
Copy link

84pixels commented Feb 5, 2016

Bonjour,
Quelles questions doit on leurs poser?

@tucoinfo
Copy link
Contributor

tucoinfo commented Feb 5, 2016

Réponse Mercanet :

Il semble que depuis le début de la semaine, le module Prestashop gère en double les commandes recevant 2 log (réponse automatique et réponses manuelle) provenant de nos serveurs
La commande n'est pas doublée sur le compte.
Nous vous invitons à prendre contact avec Prestashop afin de leur soumettre les cas : Prestatshop doit effectuer une correction dans leur traitement des log reçus par nos serveurs.

@nicolain06
Copy link
Author

par rapport à l'idée de faire un "quick fix", où verriez-vous le sleep? quel fichier / fonction exactement ?

@TrogloGeek
Copy link
Owner

@tucoinfo leur a tu bien expliqué que le problème venait du fait qu'ils ne mettent plus le client en attente que la réponse silencieuse soit terminée ?

@tucoinfo
Copy link
Contributor

tucoinfo commented Feb 5, 2016

a tu bien expliqué que le problème venait du fait qu'ils ne mettent plus le client en attente que la réponse silencieuse soit terminée ?

Ca oui mais je suis à 3 A/R déjà pour obtenir la confirmation. J'ai effectivement l'impression de parler à ma banque et non pas ATOS...

@tucoinfo
Copy link
Contributor

tucoinfo commented Feb 9, 2016

Dernière réponse en date :

Si vous êtes parmi les cas suivants, sachez que depuis la semaine dernière, la réponse automatique et la réponse manuelle sont envoyées avec un léger decallage. Prestashop considère ainsi qu'il s'agit de 2 commandes différentes, d'où ses doublons :

  • clic internaute sur "retour boutique"
  • paramétrage du "no respons page"sur votre api.

@TrogloGeek
Copy link
Owner

Thanks pour l'update

Vous avez pu juguler vos doublons par l'ajout d'un délai ? Je sais c'est très moche comme méthode (il a fallu me faire violence pour la proposer) mais le rapport efficacité coût devrait être redoutable.

@nicolain06
Copy link
Author

J'ai testé avec un sleep(3) sur plusieurs boutiques différentes ayant le soucis, & j'ai toujours la commande en double... bien que décalée de 3 secondes.

@TrogloGeek
Copy link
Owner

où le sleep a-t-il été ajouté ?

@nicolain06
Copy link
Author

sur userreturn.php (voir PJ)

capture d ecran 2016-02-09 a 09 37 31

@TrogloGeek
Copy link
Owner

étrange la réponse silencieuse devrait avoir largement le temps de créer la commande durant ces 3 secondes.

Pourriez-vous me donner les heures dans les logs du module pour les deux réponses et les date_add des deux exemplaires de la commande ?

@nicolain06
Copy link
Author

Les voici

capture d ecran 2016-02-09 a 09 50 32
capture d ecran 2016-02-09 a 09 50 01
capture d ecran 2016-02-09 a 09 45 16

@TrogloGeek
Copy link
Owner

@mockassin La réponse silencieuse n'est pas 100% fiable, le traitement de la réponse utilisateur sert de fallback pour les cas où la banque échoue à envoyer la réponse silencieuse (il m'est arrivé d'avoir des journées où 25% des réponses silencieuses étaient en échec sur une boutique dont j'avais la maintenance). Vous pouvez désactiver le traitement de la réponse utilisateur si vous le désirez mais vous risquez de perdre des informations de paiement.

@TrogloGeek
Copy link
Owner

D'ailleurs cela ne renforce pas réellement la sécurité non plus, car c'est l'encapsulation crypto des requêtes et réponses est le seul garant de la non manipulation des paiements. Le reste n'est que sparadraps.

@TrogloGeek
Copy link
Owner

J'ai enfin pu prendre quelques heures pour m'installer un environnement de développement PrestaShop et ajouter une gestion de la concurrence au module pour la version 4.1.0.

La version 4.1.0 utilise une table pour générer un lock sur un identifiant de panier.
Chaque contexte de réponse tente d'obtenir le lock avant de la traiter, le comportement en cas d'échec change selon le contexte:
Une réponse silencieuse s'arrête si elle n'a pas obtenu le lock.
Une réponse utilisateur se met en attente 3s (configurable via l'onglet "avancé" de la config) en vérifiant toutes les 100ms si le lock est toujours actif. Dès que le lock est retiré le traitement continue. Si au bout des 3s (configurable) le lock est toujours actif, une page, indiquant que la boutique est en attente du traitement bancaire et que l'email de confirmation sera envoyé dès la fin de celui ci, est présentée à l'utilisateur.

Cette page est très crue, si votre boutique est lente et risque donc de présenter cette page à l'utilisateur, customisez-la : https://github.com/TrogloGeek/prestashop-tggatos-module/blob/RC_4.1.0/views/templates/front/processing_payment_response.tpl

Idéalement plutôt qu'une boucle d'attente PHP il faudrait présenter une page d'attente immédiatement et faire la boucle d'attente en polling ajax, mais je n'ai pas le temps pour une modification aussi lourde.

Quelques personnes pourraient-elle tester la 4.1.0 et me faire des retours que je sache si je peux la basculer en version par défaut ?

@tucoinfo
Copy link
Contributor

Bonjour Damien, merci de vos efforts. J'ai plusieurs v3.x dont une qui est encore sur PS1.4. Je peux plaquer les fichiers par dessus tout simplement ?

@TrogloGeek
Copy link
Owner

Il vaudrait mieux utiliser GIT pour mettre à jour, il y a eu des fichiers renommés ou supprimés, et puis cela permet aussi de ne pas oublier une modification effectuée en local qui serait écrasée...
Écrire par dessus devrait fonctionner mais il restera des fichiers "morts" et inutiles.

@tranxene2000
Copy link

Bonjour,
Jusqu'à apparition de ce problème tout a bien fonctionné pendant un an et demi.
Puis, j'ai installé la version 4.1.0. et mis la temporisation à 3 sec. puis à 5 sec.
Mais dans les 2 cas de figure j'ai des commandes en double.
Dommage c'était super Trogglo ... mais le module officiel reste apparemment la seule solution.

@TrogloGeek
Copy link
Owner

Mais le module officiel reste apparemment la seule solution.

Je ne sais pas si cela a été corrigé mais la dernière fois que j'ai eu le module officiel entre les mains (cela date de plusieurs années) son problème était justement de perdre des commandes en cas de défaillance d'une réponse.

Je n'ai malheureusement pas de contrat VAD SIPS donc pas de certificat pour tester mes modifications. Si quelqu'un a un contrat (de préférence encore en pré-production) et peut me prêter le certificat pour faire des testes et corriger cela...

@tucoinfo
Copy link
Contributor

tucoinfo commented Apr 22, 2016

Si quelqu'un a un contrat (de préférence encore en pré-production) et peut me prêter le certificat pour faire des testes et corriger cela...

Suis en prod mais je veux bien (mes doublons sont réduits mais il en reste).

@BenoitGoimier
Copy link

@fenaille tu peux encore améliorer en faisant

public function orderExists($id_cart)
{
    return (bool)Db::getInstance()->getValue('SELECT count(*) FROM `'._DB_PREFIX_.'orders` WHERE `id_cart` = '.(int)$id_cart);
}

@tranxene2000
Copy link

Si vous avez pu accéder à un certificat et tester, tenez nous SVP au courant.

@TrogloGeek
Copy link
Owner

Hello, j'ai enfin du temps et de l'énergie à consacrer à ce problème aujourd'hui et j'ai pu reproduire le problème avec la dernière version du module, donc je vais pouvoir travailler dessus \o/.

La boucle d'attente fonctionne correctement, la persistance du problème vient que j'ai oublier de tenir compte du cache de Cart::orderExists() dont nous avons parlé précédemment. Je corrige ça.

TrogloGeek pushed a commit that referenced this issue Apr 24, 2016
Purges Cart::orderExists() cache before processing user response.
@TrogloGeek
Copy link
Owner

J'ai enfin pu reproduire après avoir fixé (le problème côté SIPS est aléatoire, la plupart du temps le serveur bancaire me met correctement en attente de la fin de la réponse silencieuse avant de me rediriger). Le commit 4bff99d corrige le problème sur mes tests.

@TrogloGeek
Copy link
Owner

@tranxene2000, @tucoinfo, avez-vous pu tester la dernière version ?

@tranxene2000
Copy link

Tout d'abord, merci (pour tous les sites concernés) de votre intervention.
Je l'ai mis en place ce jour. Pour le moment pas de commandes du tout :)
Je vous donnerai le feedback dans tous les cas de figure.

@tucoinfo
Copy link
Contributor

tucoinfo commented Apr 26, 2016

Merci Damien. Idem, RC4.1.1 tourne sur 3 sites peu actifs. Je passerai sur un dernier plus busy après quelques commandes réussies.

@TrogloGeek
Copy link
Owner

Pas de nouvelles, bonne nouvelle ?

@tucoinfo
Copy link
Contributor

tucoinfo commented May 5, 2016

Pour l'instant que de bonnes nouvelles sur 3 petits sites. Coincidence, j'ai eu un doublon PayPal après cette dernière mise à jour, certainement rien à voir puisque pas d'overrides si je ne m'abuse. Donc je vais upgrader un site plus important pour finaliser le test.

@TrogloGeek
Copy link
Owner

Merci pour le retour @tucoinfo.

Coincidence, j'ai eu un doublon PayPal après cette dernière mise à jour, certainement rien à voir puisque pas d'overrides si je ne m'abuse.

En effet, j'ai mis un point d'honneur en développant ce module a ne pas utiliser d'override du Core (ce qui m'aurait permis des fonctionnalités bien plus avancées et de simplifier certaines parties du code) car une méthode de paiement étant un connecteur terminal dans la plupart des cinématiques ne doit pas avoir d'influence sur le comportement de la boutique. (Sauf cas bien spécifiques, mais qui sont hors du cadre de la mission de ce module).
Donc à priori, il n'y a en effet aucune raison pour que le doublon de Paypal ne soit en rapport avec la mise à jour de TggAtos, simplement le fonctionnement de PaymentModule::validateOrder() ne garantit pas de verrou exclusif sur le panier durant son traitement, TggAtos y est devenu particulièrement sensible depuis que SIPS parallélise parfois les deux réponses d'où ce patch, mais en réalité la plupart des méthodes de paiement y sont vulnérables.

Un des défauts inhérent à cette absence de verrou sur le panier pouvant être posé par une méthode de paiement est que l'utilisateur peut, via un second onglet, modifier le contenu du panier lorsqu'il est sur le serveur de paiement et que le montant a donc déjà été fixé.

@tranxene2000
Copy link

De mon côté une dizaine de commandes carte bancaire sans problème. Je redonnerai le feedback plus tard à nouveau pour dire la situation mais ça a l'air d'être résolu.
Thank you Mr TrogloGeek

@TrogloGeek
Copy link
Owner

Pas de quoi, on ne laisse pas trainer un logiciel défectueux dans la nature, surtout quand il s'agit d'un connecteur de paiement.
Désolé d'avoir été si long à réagir, mais depuis que je travaille chez LiveMon j'ai des semaines de travail bien remplies ;-).

@tucoinfo
Copy link
Contributor

Donc, sur le dernier des sites à upgrader on tourne également sans doublon depuis une bonne semaine maintenant. En ce qui me concerne c'est résolu. Merci Damien.

@TrogloGeek
Copy link
Owner

Et merci à tous ceux qui m'ont fourni les informations dont j'avais besoin pour travailler sur le problème.

@tranxene2000
Copy link

Je confirme aussi. Ça tourne tjs sans doublons. Un grand merci.

@wizidot
Copy link

wizidot commented Dec 12, 2016

Bon,
La solution proposée n'est pas pour moi très pertinente. Car elle part du principe que la commande est achevée et enregistrée. Sauf que le délais d'enregistrement d'une commande est variable, il peu y avoir des traitements plus ou moins longs (envoi d'emails, génération de factures...). Et le fait de voir si un order existe implique que ce traitement soit terminé. Or les appels depuis atos sont parfois très rapprochés (moins d'une seconde) et la deuxième commande se crée alors que la première n'est pas encore terminée.. Que faire...
Et bien ma proposition est d'aller plutôt regarder du coté de la querystring envoyée à Atos, vous retrouverez 2 urls . moi j'utilise mercanet et leur "fameux..." module prestashop.
Mes 2 paramètres chelou sont :

Et vous me croyez ou pas, mais ces 2 urls sont appelées en fin de paiement. Et ces 2 urls créent des commandes..
validation.php

// If the sealed is valid, we create the order / payment and redirect the customer
if ((bool)$is_sealed == true ) {
    $error = true;
    if($data['responseCode'] == "00"){
    // Create Order / Payment "Ho ben tiens quelle bonne idée, si on créait une commande"
    $notification = new MercanetNotification();
    $notification->notify($raw_data, $params['Seal']);
    $error=false;
    }

notification.php

// If the sealed is valid, we create the order / payment and redirect the customer
if ((bool)$is_sealed == true) {
    // Create Order / Payment
    $notification = new MercanetNotification();//"Ho ben tiens quelle bonne idée, si on créait une commande"
    $notification->notify($raw_data, $params['Seal']);
}

Voilà voilà.... Alors en plus d'être des chêvres, il font du mauvais fromage...
Bon autant dire que j'ai commenté le code dans validation.php pour ne plus a avoir à gérer de commandes multiples.

Si ma solution vous semble moisie, dites-le moi....
@+

@TrogloGeek
Copy link
Owner

Bonjour, ce support concerne le module TggAtos, je peux difficilement gérer le support à la fois pour mon module gratuit et pour le module payant de PrestaShop auquel je ne suis aucunement lié. Mon module a été créé justement car je jugeais la stabilité et la qualité du module officiel largement insuffisant par rapport à mes standards de qualité concernant des transactions bancaires.

La mise à jour 4.1.1 du module TggAtos corrige le problème auquel vous êtes confronté par l'utilisation d'un système de lock sur la génération de commande pour compenser la modification de fonctionnement du système de paiement SIPS en début d'année. Votre solution présente la problématique de ne pas avoir de solution de rattrapage dans le cas où la réponse automatique échoue (problématique que j'ai fréquemment rencontrée avec le système de paiement SIPS) auquel cas la commande n'est pas générée.

Vous pouvez si vous le souhaiter tester et utiliser librement mon module qui est gratuit et libre, ou émettre une réclamation auprès du support de PrestaShop.

@jul7859
Copy link

jul7859 commented Mar 7, 2017

Hello,
Déso de rouvrir le sujet un peu tard, mon ancien module Atos a tjrs les commandes doublons. Ce module qui corrige le problème me fait rêver, mais je n'ai pas les compétences techniques de l'installer :( qqun peut le faire ? (j'ai LCL sherlocks sur module Atos)
Cheers !

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

10 participants