nursit / bank

module de paiement bancaire multi prestataires & stockage des transactions pour SPIP
21 stars 22 forks source link

Peut-on corriger une transaction après coup, qui n'aurait pas reçu la bonne notification ? (pas de vads_payment_certificate ni vads_subscription)) #74

Closed rastapopougros closed 3 years ago

rastapopougros commented 3 years ago

Cas découvert cette semaine (avec Payzen en l'occurrence) : une personne a bien réussi son virement SEPA comme il faut, elle a été prélevée sur son compte, et il y a même un prélèvement récurrent annuel bien programmé à l'infini. Donc elle sera de nouveau prélevée dans un an comme il faut à priori.

Cependant, après quelques notifications en erreur (ça arrive, problème de connexion ou autre), une notification a bien fonctionnée, mais ne contenait pas le champ "vads_payement_certificate" attendu par Bank ! Du coup ça a changé la transaction pour "erreur", avec le détail "pas de vads_payement_certificate" (ce qui veut bien dire qu'il y a eu une notif captée, c'est pas juste resté en attente à l'infini). Il n'y avait pas non plus de vads_subscription qui rempli abo_uid.

Comment faire désormais ? L'abonnement interne à SPIP (du plugin Abonnements) n'a pas été généré en cascade du coup puisque la commande liée n'a pas été mise en "payée". Ça on peut le changer à la main dans l'interface, ok.

Sauf qu'il s'agit d'un virement récurrent : dans ce cas il y a un vads_subscription/abo_ui qui est gardé en mémoire pour que l'année prochaine, on puisse continuer de faire le lien avec la même commande. Qui n'a donc pas été rempli non plus là.

Bon je n'ai pas beaucoup d'espoir hein, j'explique tout ça à tout hasard, mais sûrement que la réponse sera : "c'est comme ça, dans le lot ya des notifs qui ne seront pas bonnes et c'est au logiciel de commerce de savoir se démerder ensuite" (mais justement on peut pas éditer les transactions à la main).

rastapopougros commented 3 years ago

Erreur enregistrée ici : https://github.com/nursit/bank/blob/master/presta/payzen/inc/payzen.php#L491 (où on est bien dans "traiter la réponse", donc quand on a bien reçu une réponse)

Cerdic commented 3 years ago

C'est visiblement un cas particulier pas prévu, ou un bug, ou un changement de signature sur les notifications

Normalement tu as un log de l'URL complète avec tous les arguments de la notifications dans un des logs, ça se passe ici https://github.com/nursit/bank/blob/master/action/bank_response.php#L62

Donc la procédure c'est :

Quand on rejoue l'URL, si le bug a été fixé, on revalide la transaction et on repasse dans toutes les étapes prévues

rastapopougros commented 3 years ago

Je ne suis pas sûr d'avoir compris ce que tu appelles "récupérer l'URL" mais depuis l'interface de Payzen on peut "relancer la notification" de tel paiement, en clic droit. Quand je l'ai fait hier midi, dans le SPIP j'ai donc effectivement ce log (qui correspond à la même erreur reçu en mars quand ya eu la vraie commande donc) :

2021-06-22 13:33:09 194.50.38.6 (pid 11847) :Pub:ERREUR: call_response : transaction 16447 refusee ou annulee pour : 00 (pas de vads_payment_certifica
te) 
vads_amount=5000
vads_auth_mode=MARK
vads_auth_number=
vads_auth_result=
vads_capture_delay=2
vads_card_brand=SDD
vads_card_number=
vads_payment_certificate=
vads_ctx_mode=PRODUCTION
vads_currency=978
vads_effective_amount=5000
vads_effective_currency=978
vads_site_id=123456789
vads_trans_date=20210323180522
vads_trans_id=687227
vads_trans_uuid=xxxxxxxxxxxxxxxxxxxxxxxxxxx086406
vads_validation_mode=0
vads_version=V2
vads_warranty_result=NO
vads_payment_src=EC
vads_order_id=16447
vads_cust_email=MACHINE@hotmail.fr
vads_cust_title=Mme
vads_cust_name=MACHINE
vads_cust_first_name=MA
vads_cust_last_name=CHINE
vads_contrib=SPIP 3.2.9 + Bankv3.6.2\(https://github.com/nursit/bank\)
vads_sequence_number=1
vads_acquirer_network=SEPA
vads_contract_used=FR76XXXXXXXXXXXXXXXX
vads_trans_status=CAPTURED
vads_expiry_month=3
vads_expiry_year=2024
vads_pays_ip=FR
vads_presentation_date=20210325180853
vads_effective_creation_date=20210323180600
vads_identifier=xxxxxxxxxxxxxxxxxxxxxxxxxffe5a4
vads_occurrence_type=RECURRENT_INITIAL
vads_subscription=20210323C9Wjry
vads_operation_type=DEBIT
vads_result=00
vads_extra_result=
vads_card_country=FR
vads_language=fr
vads_hash=HASHSUPERLONG
vads_url_check_src=BO
vads_sub_amount=5000
vads_sub_currency=978
vads_sub_desc=RRULE:FREQ=YEARLY\;
vads_sub_effect_date=20220323
vads_sub_init_amount_number=0
vads_threeds_enrolled=
vads_threeds_auth_type=
vads_threeds_eci=
vads_threeds_xid=
vads_threeds_cavvAlgorithm=
vads_threeds_status=
vads_threeds_sign_valid=
vads_threeds_error_code=4
vads_threeds_exit_status=4
vads_threeds_cavv=
signature=f1cf44eb5b4e82fd6742b077c73d5d92fff34948

"vads_payment_certificate" est effectivement vide donc. Par contre il y a bien un "vads_certificate", mais peut-être que dès lors que l'autre est vide, ça n'a pas pu enregistrer et passer dans tous les pipelines qu'il faut de quand ça se passe bien.

Cerdic commented 3 years ago

Ici donc le vads_card_number est vide pour une raison inconnue, et donc le paiement semble invalide du point de vue du plugin (et le message d'erreur mériterait d'être plus clair dans ce cas particulier)

Je te propose de tester le patch

    // si c'est un SEPA, on a pas encore la transaction et le numero d'autorisation car il y a un delai avant presentation
    // (paiement dans le futur)
    if ($is_sepa AND !$transaction){
-       list($transaction, $authorisation_id) = explode("_", $response['vads_card_number']);
+       if (!empty($response['vads_card_number'])) {
+           list($transaction, $authorisation_id) = explode("_", $response['vads_card_number']);
+       }
+       elseif (!empty($response['vads_identifier']) and !empty($response['vads_trans_uuid'])) {
+           $transaction = $response['vads_trans_uuid'];
+           $authorisation_id = $response['vads_identifier'];
+       }
+       if (!$transaction or !$authorisation_id) {
+           $erreur = "SEPA sans reference de paiement (vads_card_number ou vads_identifier + vads_trans_uuid)";
+       }
rastapopougros commented 3 years ago

Alors avec ton patch, en ayant mis le max log à 8, j'ai dans payzen.log : call_response : id_transaction 16447, reglee en ayant relancé la notif depuis le backoffice payzen.

Donc en théorie ça ne fait plus d'erreur !… mais par contre dans l'admin de SPIP ça n'a pas changé le statut de la transaction, qui est toujours marqué "echec[00]" avec le message d'erreur d'origine.

Est-ce que ça ne met en "réglé" que quand c'était en "commande" ? Ou bien ça sait mettre en "réglé" aussi même après des échecs ?

Cerdic commented 3 years ago

Ça semble pas possible selon le code : quand on a le log 'réglée' https://github.com/nursit/bank/blob/master/presta/payzen/inc/payzen.php#L630 on a fait le update sur la ligne avant, et le set est mis avec le statut=ok et le reglee=oui en même temps. https://github.com/nursit/bank/blob/master/presta/payzen/inc/payzen.php#L534

Donc je dirai qu'il faut regarder la ligne SQL pour voir ce qu'il y a dedans et dérouler le code pour voir dans quel scénario on a pu passer vu les données que tu as pour ton hit de paiement

(et la réponse courte est 'oui, une notif de paiement qui conclut un paiement réussi alors que la première fois on avait enregistré un echec, ça marche complètement' et c'est une feature que j'ai utilisé plein de fois - à chaque fois que je me suis retrouvé dans ce genre de cas, des données envoyées qui ne correspondent pas à ce qui est attendu, soit parce que la spec était pas claire, soit parce que j'ai surinterprété sur la base des données de test et de ce que j'ai vu en prod, mais qui ne couvrait pas tous les cas)

rastapopougros commented 3 years ago

Non mea culpa c'était juste un problème de cache, pourtant j'avais bien rechargé (et dans l'admin c'est pas censé garder) mais donc ça a bien tout changé, et même avec la facture générée et tout. Nickel !

Donc le patch peut être ajouté, en master et en V4 stable à priori

Cerdic commented 3 years ago

Corrigé par 8b64710dfba21f87593fe68c366f2b5965ac8dba et 06bbbfaf6fc4412cf7ecddb132a14156d1ed985b

rastapopougros commented 3 years ago

Merci !