Payum / PayumBundle

Payum offers everything you need to work with payments. From simplest use cases to very advanced ones.
https://payum.gitbook.io/payum
MIT License
569 stars 142 forks source link

Token not invalidated when using a ReplyInterface #529

Open Prometee opened 3 years ago

Prometee commented 3 years ago

Writing some Behat tests for a Stripe gateway, I found that each generated capture tokens were never been invalidated.

Reading the documentation of payum/payum about capture.php and how payum/payum-bundle is handling a capture : https://github.com/Payum/PayumBundle/blob/master/Controller/CaptureController.php#L42-L44 It appears that if a gateway is using a ReplyInterface then the invalidation of the capture token is not made.

Is it a mistake or something wanted ?

pierredup commented 3 years ago

That is expected behavior. When a gateway uses the ReplyInterface, it means there is some additional action that needs to happen (E.G display a credit card form, redirect to the payment gateway etc).

If the token is invalidated, when the user returns from the payment gateway, the token won't be valid anymore and the payment won't be able to complete. So in the case where you use a ReplyInterface, then the invalidation must happen in the done script (or in the case of Symfony, it can be invalidated in your done action)

Prometee commented 3 years ago

The fact is, when you generate a capture token you will generate two tokens, one will be used for the capture phase and the other one during the done phase.

  1. prepare phase
    • create a capture token : it will create two tokens
      • the first one will be used for the capture phase
      • the other one is designed to be used during the done phase
  2. capture phase
    • consume the capture token
    • display or redirect (ReplyInterface)
    • no invalidation
  3. done phase
    • consume the second token
    • invalidation of the second token

What if the done phase could be able to invalidate the orphan capture token, because this remaining token will contains an invalidated target_url pointing to the freshly invalidated token hash. And this capture token will stay into the database or the filesystem forever right ?

Let me know if I'm clear enough @pierredup 😉

pierredup commented 3 years ago

I just double-checked in both a Symfony application, and standard setup, and in both cases, the tokens get removed as expected. I tested with Stripe, and Paypal REST.

In the case with stripe, after completing the payment, the capture page loads again, but this time it finalizes the payment and doesn't throw any exception that causes a redirect. In this case, the capture token is invalidated. Then the page redirects to the done action, where the second token gets invalidated.

@Prometee Do you have any custom actions that execute? Can you perhaps share some details of what your controller action looks like?

Prometee commented 3 years ago

@pierredup the old payum/stripe is using the target_url of the capture token which is a capture url, that is to say the capture phase will be executed a second time after entering the credit card info. During the second capture there will be no ReplyInterface involve and the token will be invalidated.

I made a completely different gateway here : flux-se/payum-stripe using Stripe Checkout Session instead of legacy Stripe Charge. You will found that I'm using the after url instead of the target url to avoid repeating a capture action : https://github.com/FLUX-SE/PayumStripe/blob/master/src/Action/StripeCheckoutSession/CaptureAction.php#L20

Prometee commented 3 years ago

@pierredup am I wrong using the capture token after_url or all gateways should use the target_url instead, making the capture phase twice ?