Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to fix the 3D secure confirm Payment on client side or on server side in Stripe Payment Intent?

I'm integrating Stripe Payment Intent API and it's working well where 3D secure is not required, 3D secure authorization is popping up but I think I'm missing return_url to confirm the payment.

Where do I need to mention return_url for 3D Secure in PaymentIntent?

I've tried multiple times but got stuck on 3D Secure Authorize. It returns an error in the object.

I've mentioned the code of view and controller below.

Thanks in Advance

Client Side Code:


    form.addEventListener('submit', function(event) {
        event.preventDefault();

        $('#card-button').html('<i class="fa fa-circle-o-notch fa-spin" style="font-size:24px"></i>');
        var fname = $('#firstname2').val();
        var lname = $('#lastname2').val();

        var cardholderName = fname + " " + lname;
        var cardButton = document.getElementById('card-button');
        var form_data = $("#payment-form").serialize();

        cardButton.addEventListener('click', function(ev) {
          stripe.createPaymentMethod('card', cardElement, {
            billing_details: {name: cardholderName}
          }).then(function(result) {
            if (result.error) {
             // Show error in payment form
          } else {
             console.log(result);
             // Otherwise send paymentMethod.id to your server (see Step 2)
             fetch('<?php echo base_url(); ?>payment/stripe_test/process_payment', 
             {
               method: 'POST',
               headers: { 'Content-Type': 'application/json' },
               body: JSON.stringify({ payment_method_id: result.paymentMethod.id, customer_detail: form_data})
              }).then(function(result) {
                // Handle server response (see Step 3)
                result.json().then(function(result) {
                console.log("Response" + result);
                handleServerResponse(result);
              });
           });
          }
        });
       });
    }

function handleServerResponse(response) {
          if (response.error) {
            // Show error from server on payment form
          } else if (response.requires_action) {

                var action = response.next_action;
                if (action && action.type === 'redirect_to_url') {
                  window.location = action.redirect_to_url.url;
                }

            // Use Stripe.js to handle required card action
            stripe.handleCardAction(
              response.payment_intent_client_secret
            ).then(function(result) {
              if (result.error) {
                // Show error in payment form
              } else {
                // The card action has been handled
                // The PaymentIntent can be confirmed again on the server
                fetch('<?php echo base_url(); ?>payment/stripe_test/process_payment', {
                  method: 'POST',
                  headers: { 'Content-Type': 'application/json' },
                  body: JSON.stringify({ payment_intent_id: result.paymentIntent.id })
                }).then(function(confirmResult) {
                  return confirmResult.json();
                }).then(handleServerResponse);
              }
            });
          } else {
            // Show success message
            console.log("3D" + response);
          }
        }

CodeIgniter Controller:

//PaymentIntent Function
    function process_payment() {
        require_once (APPPATH."third_party/stripe/init.php");

        $key = "STRIPE_KEY_HERE";

        header('Content-Type: application/json');

        # retrieve json from POST body
        $json_str = file_get_contents('php://input');
        $json_obj = json_decode($json_str);

        $intent = null;
        try {
            if (isset($json_obj->payment_method_id)) {
              # Create the PaymentIntent
                //STRIPE PAYMENT INTENT
                \Stripe\Stripe::setApiKey($key);

                // Create a Customer:
                $customer = \Stripe\Customer::create([
                    'email' => '[email protected]',
                ]);

                // Attach payment method to the customer:

                $customer_detail = $json_obj->customer_detail;

              $intent = \Stripe\PaymentIntent::create([
                'payment_method' => $json_obj->payment_method_id,
                'amount' => 1099,
                'currency' => 'GBP',
                'confirmation_method' => 'manual',
                "customer" => $customer->id,
                'confirm' => true,
              ]);
            }
            if (isset($json_obj->payment_intent_id)) {
              $intent = \Stripe\PaymentIntent::retrieve(
                $json_obj->payment_intent_id
              );
              $intent->confirm();
            }

            $this->generatePaymentResponse($intent);

        } catch (\Stripe\Error\Base $e) {
            # Display error on client
            echo json_encode([
              'error' => $e->getMessage()
            ]);
        }
    }

generatePaymentResponse Function:

function generatePaymentResponse($intent) {
        if ($intent->status == 'requires_source_action' &&
            $intent->next_action->type == 'use_stripe_sdk') {
          # Tell the client to handle the action
          echo json_encode([
            'requires_action' => true,
            'payment_intent_client_secret' => $intent->client_secret
          ]);
        } else if ($intent->status == 'succeeded') {
          # The payment didn’t need any additional actions and completed!
          # Handle post-payment fulfillment
          echo json_encode([
            "success" => true
          ]);
        } else {
          # Invalid status
          http_response_code(500);
          echo json_encode(['error' => 'Invalid PaymentIntent status']);
        }
    }

like image 406
Kamran KB Avatar asked Apr 25 '19 23:04

Kamran KB


People also ask

How do I turn on 3D Secure authentication stripe?

Step 1: The customer enters their card details. Step 2: The customer's bank assesses the request and can complete 3D Secure at this step. Step 3: If required by their bank, the customer completes an additional authentication step.

How do I fix 3D Secure authentication failed?

If you receive a "3D Authentication failed" error, it means that you have not entered the required information successfully. Please double check that Caps Lock is disabled and repeat the process making sure there are no typing errors.


1 Answers

As mentioned in comments, you don't need to specify return_url, because in your case Stripe will use Popup for 3DS confirmation, not redirecting.

You missed two things in your code:
1. In function generatePaymentResponse add condition for $intent->status === 'requires_action'.
2. On Payment Intent confirmation ($intent->confirm();) you missed to set api key (\Stripe\Stripe::setApiKey($key);)

I have tested your code and it works with mentioned modifications.

like image 183
Konstantin Bogomolov Avatar answered Oct 01 '22 11:10

Konstantin Bogomolov