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

How to process 3D Secure Payments? #161

Open
marbuser opened this issue Nov 11, 2019 · 7 comments
Open

How to process 3D Secure Payments? #161

marbuser opened this issue Nov 11, 2019 · 7 comments

Comments

@marbuser
Copy link

So I'm initialising my payment like so;

        $response = $gateway->purchase([
            'amount' => money_format('%i', ($amount / 100)),
            'currency' => 'USD',
            'token' => $payment_token,
            'description' => "Test Product",
            'confirm' => true,
            'returnUrl' => 'http://mysite.test/me/transactions,
        ])->send();

This works perfectly fine for cards that don't have 3D Secure, and triggers my Webhook perfectly. However, as soon as I use a Stripe test card with 3D secure, after clicking 'Complete' on Stripe's test page, it sends a URL back like so;
http://mysite.test/me/transactions?payment_intent=pi_0000000000000000&payment_intent_client_secret=pi_000000000000000_secret_0000000000000000&source_type=card

I'm not entirely sure what to do with this. Since I'm developing my application as a REST API with an SPA frontend, I'm not really sure what to do with this URL and the payment remains as The customer has not completed the payment. in the Stripe dashboard, and my Webhook is never triggered.

Hopefully someone here can help as I can't really find any sort of information about how to deal with this.

@jannejava
Copy link

The basic idea is that you will get a URL that you have to follow to an external site. When it's completed you will be redirected back to your app, so you have to leave your app even if it's a SPA.

So when you get the response from $gateway->purchase() you have to check for $response->isRedirect() and $response->getRedirectUrl().

I wrote a quick blog-post about this.

@domis86
Copy link

domis86 commented Nov 11, 2019

To do it without leaving the SPA you can do as is described in this issue: #152 (comment)

@marbuser
Copy link
Author

@jannejava Thanks for the blog post, but I'm hoping to use a more Webhook based approach than manual confirmation.

@domis86
Yeah I was testing this approach yesterday. I got it working, but 1 thing I really dislike about it is the "Manual Confirmation" part of it. Is there anyway I can use it in conjunction with a webhook so that as soon as they complete 3DSecure, it confirms the payment intent and triggers the webhook?

Thanks!

@jannejava
Copy link

@marbuser Someone has to correct me if I am wrong but this tripped me up: the Omnipay/Stripe is built around the manual flow. If you want the async/webhooks, you have to use Stripe's own PHP SDK. In my project, the manual flow did work much better.

@kpinkowski
Copy link

@marbuser How did you ended up implementing this?

@laoneo
Copy link
Contributor

laoneo commented Nov 22, 2019

I'v just spent the last couple of days to implement this without the Stripe SDK and just with Omnipay and Stripe.js.
First you need to create the payment method with Stripe.js and then authorize. When the response has the status 'requires_capture', then do capture on the gateway. Otherwise you probably have to do the redirect to the banks web site with extra authentication.
On the next callback you should have then a payment_intent parameter in the url. Then do the confirm on the gateway and when the status is again requires_capture on the response, do the capture.

That's how it worked for me to finally get the balance transaction. So you got two times a callback and depending on the url parameters you have to figure out what to do. Not sure if this is the best way, but at least it works now.

@domis86
Copy link

domis86 commented Nov 22, 2019

@marbuser

Yeah I was testing this approach yesterday. I got it working, but 1 thing I really dislike about it is the "Manual Confirmation" part of it. Is there anyway I can use it in conjunction with a webhook so that as soon as they complete 3DSecure, it confirms the payment intent and triggers the webhook?

Ok so i think you my want to do like this:

  1. See this line https://github.com/thephpleague/omnipay-stripe/blob/master/src/Message/PaymentIntents/AuthorizeRequest.php#L346
$data['confirmation_method'] = 'manual';

^ it always sets this paramater value to 'manual' - see full description in Stripe docs: https://stripe.com/docs/api/payment_intents/create#create_payment_intent-confirmation_method . For what you want to do you should use 'automatic' instead

  1. To change this parameter, without creating own custom class that extends \Omnipay\Stripe\Message\PaymentIntents\AuthorizeRequest , you can do like i described in gateway->authorize without return_url to allow "next_action": {"type": "use_stripe_sdk"} #152 (comment) but you need to add this line:
$data['confirmation_method'] = 'automatic';

before the line with thats sends custom $data - so before:

/** @var \Omnipay\Stripe\Message\PaymentIntents\Response $paymentResponse */
$paymentResponse = $paymentIntentAuthorizeRequest->sendData($data);

This will cause that PaymentIntent will be automatically confirmed after customer finishes "3D Secure 2" authentication on client side (or if such authentication is not needed) - similar as is described in "Step 4" here: https://stripe.com/docs/payments/accept-a-payment#web-submit-payment .
In that guide they say to use this javascripts method : https://stripe.com/docs/stripe-js/reference#stripe-confirm-card-payment

Then of course you need to implement your "Webhook endpoint" on your server etc. For that you need to use Stripe PHP SDK (as @jannejava mentioned above #161 (comment) ) or you can build some simpler custom solution basing on "webhook related code" from that Stripe PHP SDK repository.
See more in docs:

https://stripe.com/docs/webhooks
https://stripe.com/docs/webhooks/build
https://stripe.com/docs/payments/accept-a-payment#web-fulfillment

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

5 participants