Home » Php » php – How to fix the 3D secure confirm Payment on client side or on server side in Stripe Payment Intent?

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

Posted by: admin July 12, 2020 Leave a comment

Questions:

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']);
        }
    }

How to&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.