到目前为止很好 - 我已经使用Stripe的设置订阅的指南使其工作。但是,需要3D Secure身份验证的卡尚未工作,这是必须的。
因此,我进一步阅读并使用了PaymentIntent(API文档)。但是,当前行为如下:
- 我创建了一个PaymentIntent,并将公钥传递给前端
- 客户输入凭据并提交
- 3D安全验证正确进行,向我返回payment_method_id
- 在服务器端,我再次检索PaymentIntent。它的状态为
succeeded
,并且付款已在我的Stripe Dashboard上收到。 - 然后,我创建客户对象(使用从PaymentIntent获取的付款方式),然后使用该客户创建订阅
- 订阅的状态为
incomplete
,似乎订阅尝试再次向客户收费,但由于第二次需要进行3D Secure验证而失败。
所以我的实际问题是:如何创建一个订阅,使其以某种方式注意到客户已经使用我的PaymentIntent和我传递给它的PaymentMethod进行了支付?
一些代码
创建PaymentIntent并将其传递给前端
\Stripe\Stripe::setApiKey(env('STRIPE_SECRET_KEY'));
$intent = \Stripe\PaymentIntent::create([
'amount' => '1990',
'currency' => 'chf',
]);
$request->session()->put('stripePaymentIntentId',$intent->id);
return view('payment.checkout')->with('intentClientSecret',$intent->client_secret);
点击“购买”时的前端结账
// I have stripe elements (the card input field) ready and working
// using the variable "card". The Stripe instance is saved in "stripe".
// Using "confirmCardPayment", the 3DS authentication is performed successfully.
stripe.confirmCardPayment(intentClientSecret,{
payment_method: {card: mycard},
setup_future_usage: 'off_session'
}).then(function(result) {
$('#card-errors').text(result.error ? result.error.message : '');
if (!result.error) {
submitMyFormToBackend(result.paymentIntent.payment_method);
}
else {
unlockPaymentForm();
}
});
提交后的后端
// Get the PaymentMethod id from the frontend that was submitted
$payment_method_id = $request->get('stripePaymentMethodId');
// Get the PaymentIntent id which we created in the beginning
$payment_intent_id = $request->session()->get('stripePaymentIntentId');
\Stripe\Stripe::setApiKey(env('STRIPE_SECRET_KEY'));
// Get the Laravel User
$user = auth()->user();
// Firstly load Payment Intent to have this failing first if anything is not right
$intent = \Stripe\PaymentIntent::retrieve($payment_intent_id);
if ($intent instanceof \Stripe\PaymentIntent) {
// PaymentIntent loaded successfully.
if ($intent->status == 'succeeded') {
// The intent succeeded and at this point I believe the money
// has already been transferred to my account, so it's paid.
// Setting up the user with the paymentMethod given from the frontend (from
// the 3DS confirmation).
$customer = \Stripe\Customer::create([
'payment_method' => $payment_method_id,
'email' => $user->email,
'invoice_settings' => [
'default_payment_method' => $payment_method_id,
],
]);
$stripeSub = \Stripe\Subscription::create([
'customer' => $customer->id,
'items' => [
[
'plan' => env('STRIPE_PLAN_ID'),
]
],
'collection_method' => 'charge_automatically',
'off_session' => false,
]);
// If the state of the subscription would be "active" or "trialing", we would be fine
// (depends on the trial settings on the plan), but both would be ok.
if (in_array($stripeSub->status,['active','trialing'])) {
return "SUCCESS";
}
// HOWEVER the state that I get here is "incomplete", thus it's an error.
else {
return "ERROR";
}
}
}
4000 0084 0000 1629
(请参见 https://stripe.com/docs/testing#regulatory-cards),当我调用stripe.confirmCardSetup
时,它返回了一个错误,所以对我来说这很好。 - Florian Müller