web-dev-qa-db-fra.com

Comment atténuer un scénario où un utilisateur va payer, mais le prix est modifié au milieu de la demande?

C'est un peu similaire au problème Deux généraux " , mais pas tout à fait. Je pense qu'il y a un nom pour cela, mais je ne m'en souviens tout simplement pas en ce moment.

Je travaille sur le flux de paiement de mon site Web.

Scénario

  1. Alice veut payer Bob pour un service. Bob lui a cité 10 USD.
  2. Alice clique sur Pay.
  3. Alors que la demande d'Alice volait à travers l'éther, Bob édite sa citation. Il veut maintenant US $ 20.
  4. La demande de Bob se termine avant que Alice ait atteint le serveur.
  5. La demande d'Alice atteint le serveur et son paiement est autorisé pour 20 USD au lieu de 10 USD.
  6. Alice est malheureuse.

Bien que les chances de cela soient très faibles dans la pratique, c'est un scénario possible. Parfois, les demandes peuvent accrocher en raison de problèmes de réseau, etc.

Mitigations possibles

Je ne pense pas que ce problème soit résoluble. Mais nous pouvons faire des choses pour l'atténuer.

Ce n'est pas exactement un problème d'idimpoteur, donc je ne pense pas que la réponse soit "jeton d'idempotence".

Option 1

Définissons:

  • t_0 Comme le temps Alice, cliquez sur Payer.
  • t_edit Comme la demande de modification de l'époque Bob réussit
  • t_1 Comme la demande du temps Alice atteint le serveur

Depuis que nous ne pouvons pas savoir t_0 À moins que nous l'envoyions dans le cadre des données de la demande, et ​​parce que nous ne pouvons pas faire confiance à ce que le client envoie, nous ignorerons t_0.

À l'époque, la demande d'Alice arrive sur le serveur, nous vérifions:

if t_1 - t_edit < 1 minute: return "409 Conflict" (ou un autre code)

Cette approche fonctionnerait-elle? 1 minute est un choix arbitraire, et cela ne résout pas entièrement le problème. Si la demande d'Alice prend 1 minute ou plus pour atteindre le serveur, le problème persiste.

Cela doit être un problème extrêmement courant à traiter, non?

64
turnip

Notez que dans la plupart des cas, il y a une étape intermédiaire - chariots de shopping. Vous mettez l'article dans le panier plutôt que de l'acheter. S'il y a un changement de prix au mauvais instant, vous pouvez le voir avant de presse payer. Lorsque vous payez, vous achetez le panier - les articles de cette information ont déjà des prix attachés.

Pour une solution plus complète, vous pouvez rendre les prix en lecture seule. Lorsque Bob a élevé le prix sur les widgets à 20 $, il a vraiment créé un nouveau type de widget qui va 20 $, le widget de 10 $ existe toujours mais ne peut pas être trouvé à moins que vous sachiez l'ID d'article. Alice tente d'acheter la version de 10 $, la transaction passe à 10 $.

0
Loren Pechtel