Thomas Dupont
Thomas Dupont

Reputation: 427

Stripe 3d secure subscription failed

I have an issue with the test environnement of Stripe about the 3 d secure process and Subscription. And I'm afraid to push the process to production without validation or explanation of the problem.

I performed all of the 3d secure and Subscription process according to the documentation.

https://stripe.com/docs/sources/three-d-secure/subscriptions

When I would activate the subscription by disabling the trial period, all what I tried failed.

enter image description here

I'm using the test card with 3d secure required : 4000 0000 0000 3063

My code process :

<!DOCTYPE html>
<html lang="fr">
<head>
    <meta charset="UTF-8">
    <title>Source test Stripe</title>
    <script src="https://js.stripe.com/v3/"></script>
    <style>
        .StripeElement {
            background-color: white;
            height: 40px;
            padding: 10px 12px;
            border-radius: 4px;
            border: 1px solid transparent;
            box-shadow: 0 1px 3px 0 #e6ebf1;
            -webkit-transition: box-shadow 150ms ease;
            transition: box-shadow 150ms ease;
        }

        .StripeElement--focus {
            box-shadow: 0 1px 3px 0 #cfd7df;
        }

        .StripeElement--invalid {
            border-color: #fa755a;
        }

        .StripeElement--webkit-autofill {
            background-color: #fefde5 !important;
        }
    </style>

</head>
<body>
<h1>create source</h1>

<form action="javascript:charge()" method="post" id="payment-form">
    <div class="form-row">
        <label for="card-element">
            Credit or debit card
        </label>
        <div id="card-element">
        </div>
        <div id="card-errors" role="alert"></div>
    </div>
    <button>Submit Payment</button>
</form>

</body>
<script>
    var stripe = Stripe('pk_test_xxxx');
    var elements = stripe.elements();
    var style = {
        base: {
            color: '#32325d',
            lineHeight: '18px',
            fontFamily: '"Helvetica Neue", Helvetica, sans-serif',
            fontSmoothing: 'antialiased',
            fontSize: '16px',
            '::placeholder': {
                color: '#aab7c4'
            }
        },
        invalid: {
            color: '#fa755a',
            iconColor: '#fa755a'
        }
    };
    var card = elements.create('card', {style: style});
    card.mount('#card-element');

    card.addEventListener('change', function(event) {
        var displayError = document.getElementById('card-errors');
        if (event.error) {
            displayError.textContent = event.error.message;
        } else {
            displayError.textContent = '';
        }
    });

    var form = document.getElementById('payment-form');
    form.addEventListener('submit', function(event) {
        event.preventDefault();

        var ownerInfo = {
            owner: {
                name: 'Jenny Rosen',
                address: {
                    line1: 'Nollendorfstraße 27',
                    city: 'Berlin',
                    postal_code: '10777',
                    country: 'DE',
                },
                email: '[email protected]'
            },
        };
        stripe.createSource(card, ownerInfo).then(function(result) {
            if (result.error) {
                var errorElement = document.getElementById('card-errors');
                errorElement.textContent = result.error.message;
            } else {
                console.log(result.source.id)
            }
        });
    });

    function charge() {
    }
</script>
</html>

I got the source id src_xxxxx

And I put in my php script:

<?php

require_once('stripe-php/init.php');

Stripe\Stripe::setApiKey(
    'sk_test_xxxxx'
);

$sourceId = 'src_xxxxx';

$customer = Stripe\Customer::create([
    'description' => 'test desc',
    'email' => '[email protected]',
    'source' => $sourceId,
]);


$param = [
    "amount" => 2995,
    "currency" => 'eur',
    "type" => "three_d_secure",
    'three_d_secure' => [
        'card' => $sourceId
    ],
    "redirect" => [
        "return_url" => "http://localhost:8080/stripeProcess2.php?customerId=".$customer->id
    ],
];

$source = Stripe\Source::create($param);

$customer->sources->create(['source' => $source->id]);

var_dump($source->redirect);

In the var_dump, I got the redirection url

I accept the 3d secure payment and the redirect link execute this following script:

<?php
require_once('stripe-php/init.php');

Stripe\Stripe::setApiKey(
    'sk_test_xxxx'
);

$source = $_GET['source'];
$customerId = $_GET['customerId'];

$charges = \Stripe\Charge::create(array(
    "amount" => 2995,
    "currency" => "eur",
    'source' => $source,
    'customer' => $customerId,
    "description" => "Charge for [email protected]"
));


$params = [
    'items' => [
        [
            "plan" => "annual-basic",
        ]
    ],
    'customer' => $customerId,
    'trial_end' => strtotime('+1 day')
];


$sub = \Stripe\Subscription::create($params);

var_dump($sub->id);

And with The subscription Stripe id, I would activate the subscription immediately (This charge the customer)

$subscription = \Stripe\Subscription::retrieve("sub_C7eVRi9WLynMdh");
$subscription->trial_end = "now";
$subscription->save();

And Here, I got the failed payment with generic_decline code.

I want to know if in my process, I performed something wrong, if I need to wait the month end to recharge customer or if the Stripe test card is not available to be used for this process?

Thanks in advance

Upvotes: 3

Views: 8320

Answers (4)

Kate
Kate

Reputation: 23

If you have an old stripe account the Radar payment rules for 3d secure are switched OFF by default.

Simply ENABLE the Stripe radar rules and the 4000000000003063 card will start showing 3d secure modal:

https://dashboard.stripe.com/test/settings/radar/rules

Upvotes: 0

pgcan
pgcan

Reputation: 1219

Creating subscription on stripe using 3D secure card is little confusing. When I tested with card "4000000000003063", I was able to charge upfront as well as able to create subscription with trial period. But when I end the trial period it failed with error "Card is declined". This situation made me doubt my code.

As mentioned by @mygov, it seems that the test card "...3063" is not made for re-occurring payments. To confirm this I created subscription on live stripe using my actual 3D secure card and payment was successful on ending the trial period.

Adding to above, in case of 3D secure card, it is required to charge the 3d secure source before creating subscription, but if there is a trial period then nothing should be charged immediately from customers, I choose to charge 1USD as an activation fee and then create subscription.

Hope it help someone.

Upvotes: 2

mygov
mygov

Reputation: 150

I think the reason for the decline is because the test card 4000000000003063 (https://stripe.com/docs/sources/three-d-secure) are only for single payments and 3D Secure must be completed for a charge to be successful. (Use credit card 4000000000003055 - "3D Secure is supported but not required on this card" instead.)

This means if this card is attached to a customer, you are only able to test the initial payment but not the recurring payments because you can not complete the 3D Secure procedure again.

You need to store the original credit card source with the stripe default procedure (https://stripe.com/docs/sources/cards) to use this source again for your ongoing subscription payments.

Upvotes: 7

postmoderngres
postmoderngres

Reputation: 386

When creating the 3DS source, you need to pass in the customer, along with the card, in the three_d_secure hash.

$param = [
    "amount" => 2995,
    "currency" => 'eur',
    "type" => "three_d_secure",
    'three_d_secure' => [
        'card' => $sourceId,
        'customer' => $customer->id
    ],
    "redirect" => [
        "return_url" => "http://localhost:8080/stripeProcess2.php?
customerId=".$customer->id
    ],
];

Without that the customer object isn't linked to the successfully authenticated 3DS source: https://stripe.com/docs/sources/three-d-secure/subscriptions#create-3ds-source

Upvotes: 1

Related Questions