skip to Main Content

So i’ve been able to successfully create a new stripe customer, subscription and pass the rest of my logic when my card is a non 3DS card but i’ve issues implementing the logic for a 3DS, for the 3DS, i’m trying to redirected the users to they bank for authentication by a modal or iframe and redirect them back to my site after successful authentication but instead i don’t see any authentication page for 3DS cards but a new customer and subscription is created in stripe dashboard and payment status is "incomplete"

if($_SERVER['REQUEST_METHOD'] == "POST"){
    set_value($_POST);
    
    $token = (isset($_POST['stripeToken'])) ? $_POST['stripeToken'] : null;
    $crad_number = (isset($_POST['crad_number'])) ? $_POST['crad_number'] : null;
    $month = (isset($_POST['month'])) ? $_POST['month'] : null;
    $year = (isset($_POST['year'])) ? $_POST['year'] : null;
    $cvv = (isset($_POST['cvv'])) ? $_POST['cvv'] : null;
    
    // Validation
    $errors = array();
    if(empty($token)){
        $errors[] = 'Token is required';
    }
    if(empty($crad_number)){
        $errors[] = 'Crad Number is required';
    }
    if(empty($month)){
        $errors[] = 'MONTH name is required';
    }
    if(empty($year)){
        $errors[] = 'YEAR is required';
    }
    if(empty($cvv)){
        $errors[] = 'CVV is required';
    }
    if(empty($errors)){
            
        try{
            
             $stripe = new StripeStripeClient('sk_test key');
            // Create Customer In Stripe
            
            $customer = StripeCustomer::create(array(
                "email" => $email,
                "name" => $membernamedata,
                'source'  => $token,
            ));

            $finalamount = $amount*100;
            
            $paydesc = "Members Directory";

            // Create the subscription with the found product ID
             $subscription = $stripe->subscriptions->create([
                'customer' => $customer,
                'items' => [['price' => $product_id]],
                "currency" => $_currency,
                "description" => $paydesc,
                //'amount' => $finalamount, 
                'expand' => ['latest_invoice.payment_intent'],
            ]);

                    
            // Check if 3DS authentication is required
            if ($subscription->latest_invoice->payment_intent->status === 'requires_action' &&
                $subscription->latest_invoice->payment_intent->next_action->type === 'redirect_to_url'
            ) {
                // Redirect the customer to the 3DS authentication page
                $redirectUrl = $subscription->latest_invoice->payment_intent->next_action->redirect_to_url->url;
                header('Location: ' . $redirectUrl); 
                exit(); 
            } else {

i’m expecting a modal or iframe to display for users to confirm authentication

2

Answers


  1. Chosen as BEST ANSWER

    i was able to solve my problem

    first the root cause was in my check 3DS logic

    // Check if 3DS authentication is required
                if ($subscription->latest_invoice->payment_intent->status === 'requires_action' &&
                    $subscription->latest_invoice->payment_intent->next_action->type === 'redirect_to_url'
                )
    

    The $subscription->latest_invoice->payment_intent->next_action->type === 'redirect_to_url' output was 'use_stripe_sdk'

    hence the error.

    now in other to change the 'use_stripe_sdk' to 'redirect_to _url', i reconfirmed the paymentIntent and updated the subscription info

    then passed the new output which is now 'redirect_to_url' to the rest of the logic

    updated code below

    if($_SERVER['REQUEST_METHOD'] == "POST"){
        set_value($_POST);
        
        $token = (isset($_POST['stripeToken'])) ? $_POST['stripeToken'] : null;
        $crad_number = (isset($_POST['crad_number'])) ? $_POST['crad_number'] : null;
        $month = (isset($_POST['month'])) ? $_POST['month'] : null;
        $year = (isset($_POST['year'])) ? $_POST['year'] : null;
        $cvv = (isset($_POST['cvv'])) ? $_POST['cvv'] : null;
        
        // Validation
        $errors = array();
        if(empty($token)){
            $errors[] = 'Token is required';
        }
        if(empty($crad_number)){
            $errors[] = 'Crad Number is required';
        }
        if(empty($month)){
            $errors[] = 'MONTH name is required';
        }
        if(empty($year)){
            $errors[] = 'YEAR is required';
        }
        if(empty($cvv)){
            $errors[] = 'CVV is required';
        }
        if(empty($errors)){
                
            try{
                
                 $stripe = new StripeStripeClient('sk_test_key');
                // Create Customer In Stripe
                
                $customer = StripeCustomer::create(array(
                    "email" => $email,
                    "name" => $membernamedata,
                    'source'  => $token,
                ));
    
                $finalamount = $amount*100;
                
                $paydesc = "Members Directory";
    
                // Create the subscription with the found product ID
                 $subscription = $stripe->subscriptions->create([
                    'customer' => $customer,
                    'items' => [['price' => $product_id]],
                    "currency" => $_currency,
                    "description" => $paydesc,
                    //'amount' => $finalamount,
                    'expand' => ['latest_invoice.payment_intent'],
                ]);
    
               
                    // Conditional Payment Intent Confirmation (for 3DS cases)
                if ($subscription->latest_invoice->payment_intent->status === 'requires_action') {
                    $paymentIntent = $stripe->paymentIntents->confirm(
                        $subscription->latest_invoice->payment_intent->id, 
                        ['return_url' => "https://example.com"] 
                    );
            
                    // Update $subscription with the latest information
                    $subscription = $stripe->subscriptions->retrieve($subscription->id, ['expand' => ['latest_invoice.payment_intent']]);
                }
    
    
                        
                // Check if 3DS authentication is required
                if ($subscription->latest_invoice->payment_intent->status === 'requires_action' &&
                    $subscription->latest_invoice->payment_intent->next_action->type === 'redirect_to_url'
                ) {
                    // Redirect the customer to the 3DS authentication page
                    $redirectUrl = $subscription->latest_invoice->payment_intent->next_action->redirect_to_url->url; 
                    
    
                        // Perform the redirect
                        header("HTTP/1.1 303 See Other");
                        header("Location: " . $redirectUrl);
                        exit(); 
                    
                    
                } 
    
    
    

    thanks!


  2. If you have a PaymentIntent with status of requires_action, then the next step is to:

    Once the customer finishes the 3DS flow, the PaymentIntent will be status: succeeded and the Subscription will be status: active.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search