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

Payments which aren't redirected still need to be captured on SCA. #157

Open
jeremyquinton opened this issue Sep 17, 2019 · 4 comments
Open

Comments

@jeremyquinton
Copy link

jeremyquinton commented Sep 17, 2019

I'm using the latest stripe API and version 3.1 of this library.

Short version (tested on a live transaction as well as test transaction)

  1. Send authorise using paymentIntents Gateway.
  2. Response is not a redirect but returns isSuccessful().
  3. The payment_intent in the stripe dashboard is set to Payment authorised, but not yet captured.

The documentation states
If you don't set the confirm parameter to true, you will have to manually confirm the payment intent as shown below.

This is in misleading because if you are not redirected and have set confirm to true you have to use the below code to confirm the payment.

The code below in the $response->isSuccessful() does not work if you are not redirected it only works if you are redirected.

if ($response->isSuccessful()) {
    $paymentIntent = $gateway->fetchPaymentIntent($intentData);
    $response = $paymentIntent->send();
    if ($response->requiresConfirmation()) {
       $response = $this->gateway->confirm($intentData)->send();
    }

} else if($response->isRedirect()) {
    $response->redirect();
} else {
    // The payment has failed. Use $response->getMessage() to figure out why and return to step (1).
}

If I use the test card number below (recommended by Stripe to kick in SCA flow)
4000 0000 0000 3063
isRedirect() is true and then I can use the code below to confirm the transaction

$paymentIntent = $gateway->fetchPaymentIntent($intentData);
$response = $paymentIntent->send();
if ($response->requiresConfirmation()) {
   $response = $this->gateway->confirm($intentData)->send();
}

If I use 4242 4242 4242 4242 in test or a real card number in live mode
$response->isSuccessful() is set true however calling the code below does not work.

$paymentIntent = $gateway->fetchPaymentIntent($intentData);
$response = $paymentIntent->send();
if ($response->requiresConfirmation()) {
    $response = $this->gateway->confirm($intentData)->send();
}

I had to use capture instead .

$paymentIntent = $gateway->fetchPaymentIntent($intentData);
$response = $paymentIntent->send();
if ($response->requiresConfirmation()) {
   $response = $this->gateway->confirm($intentData)->send();
} else {
   $response = $this->gateway->capture($intentData)->send();
}

This feels like an odd fringe case that is not handled by the new library. If you aren't redirected you have to use capture instead of confirm.

I will see if I can write test case and code to handle this fringe case.

@domis86
Copy link

domis86 commented Sep 18, 2019

@jeremyquinton please see: https://stripe.com/docs/api/payment_intents/create#create_payment_intent-capture_method

capture_method

optional

One of: "automatic" (default) or "manual".
When the capture method is automatic, Stripe automatically captures funds when the customer authorizes the payment.

Change capture_method to manual if you wish to separate authorization and capture for payment methods that support this.

and here: https://github.com/thephpleague/omnipay-stripe/blob/master/src/Message/PaymentIntents/AuthorizeRequest.php#L347

$data['capture_method'] = 'manual';

If you want to automatically capture PaymentIntent then you should use Omnipay PurchaseRequest instead of AuthorizeRequest - see: https://github.com/thephpleague/omnipay-stripe/blob/master/src/Message/PaymentIntents/PurchaseRequest.php#L36

$data['capture_method'] = 'automatic';

I too was confused by this - thats why i did workaround as discussed here: #152 (comment)
I think Omnipay Stripe documentation should be more clear on this aspect (capture_method and AuthorizeRequest vs PurchaseRequest i mean).

@jeremyquinton
Copy link
Author

jeremyquinton commented Sep 18, 2019

@domis86 thanks for your feedback.

Changing the AuthoriseRequest to PurchaseRequest made no difference to me.

I did the following which works for now.

$response = $paymentIntentGateway->authorize($transaction_data)->send();

if ($response->isSuccessful()) {
    $response = $paymentIntentGateway->capture($intentData)->send();
} elseif ($response->isRedirect()) {
    //redirect user
}

//On return from redirect. 

$paymentIntent = $paymentIntentGateway->fetchPaymentIntent($intentData);
$response = $paymentIntent->send();

if ($response->requiresConfirmation()) {
    $confirmResponse = $paymentIntentGateway->confirm($intentData)->send();
    if ($confirmResponse->isSuccessful()) {
        $response = $paymentIntentGateway->capture($intentData)->send();
    }
} else {
    $response = $paymentIntentGateway->capture($intentData)->send();
}

@ujwaldhakal
Copy link

@jeremyquinton are you using omnipay-common to use stripe or directly ? I found using omnipay stripe you really cant use intentGateway ?

@amit4106udale
Copy link

@domis86 @jeremyquinton - Can you please help how this is implemented? How the payment methods are set? and how to redirect it to 3D secure stripe? Omnipay stripe is having paymentIntents but unable to use it as @ujwaldhakal said.

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

4 participants