Stripe 3D Secure 订阅失败。

3

我在Stripe的测试环境中遇到了有关3D安全过程和订阅的问题,并且我担心在没有验证或解释这个问题的情况下将该过程推入生产。

我根据文档执行了所有的3D安全和订阅过程。

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

当我禁用试用期来激活订阅时,所有尝试都失败了。

enter image description here

我使用需要3D安全的测试卡:4000 0000 0000 3063

我的代码过程:

<!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: 'jenny.rosen@example.com'
            },
        };
        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>

我得到了源ID src_xxxxx。

然后我将其放入我的PHP脚本中:

<?php

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

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

$sourceId = 'src_xxxxx';

$customer = Stripe\Customer::create([
    'description' => 'test desc',
    'email' => 'test@test.com',
    '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);

在var_dump中,我得到了重定向URL。
我接受3D安全支付,重定向链接执行以下脚本:
<?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 daniel.garcia@example.com"
));


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


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

var_dump($sub->id);

通过Stripe订阅ID,我将立即激活订阅(这会向客户收取费用)。

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

在这里,我使用了generic_decline代码,支付失败了。

我想知道在我的过程中,我是否做错了什么,是否需要等到月底重新为客户充值,或者Stripe测试卡无法用于此流程?

先感谢您的帮助。

4个回答

7
我认为下降的原因是由于测试卡号4000000000003063(https://stripe.com/docs/sources/three-d-secure)仅适用于单次支付,必须完成3D Secure才能成功收取费用。相反,您可以使用信用卡4000000000003055 -“此卡支持3D Secure,但不要求使用”。

这意味着,如果客户使用这张卡片,则只能测试初始付款,而无法测试重复付款,因为您无法再次完成3D Secure流程。

为了在订阅期内继续使用该来源进行付款,您需要使用Stripe默认程序(https://stripe.com/docs/sources/cards)存储原始信用卡来源。


是的,就是这样,Stripe支持团队向我回答了同样的答复。 - Thomas Dupont
对于不需要3D Secure的卡,我们可以创建一个普通订阅。但是如何为需要此功能的卡创建订阅,就像OP所问的那样呢?据我理解,使用3d_secure_source,我们可以重复使用此类卡片,但我尝试进行循环付款时失败了。 - Bogdan Mircea Stanciu

2
使用3D安全卡在stripe上创建订阅有点令人困惑。当我使用卡号“4000000000003063”进行测试时,我能够提前收费,并且能够创建具有试用期的订阅。但是,当试用期结束时,出现了“拒绝卡片”的错误。这种情况让我怀疑我的代码。
如@mygov所提到的,似乎测试卡“... 3063”不适用于重复付款。为了确认这一点,我使用我的实际3D安全卡在live stripe上创建了订阅,在试用期结束时支付成功。
此外,在使用3D安全卡的情况下,需要在创建订阅之前对3D安全源进行收费,但如果有试用期,则不应立即从客户处收取任何费用。我选择收取1美元作为激活费用,然后再创建订阅。
希望它能帮助某些人。

1
在创建3DS源时,您需要将客户和卡一起传递到three_d_secure哈希中。
$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
    ],
];

如果没有成功验证的3DS source,客户端对象将无法与之关联: https://stripe.com/docs/sources/three-d-secure/subscriptions#create-3ds-source


你好,和 $customer->sources->create(['source' => $source->id]); 一样吗?我执行了该调用。 - Thomas Dupont

0

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接