I have followed this documentation to implement the Stripe Recurring Payments, which is working fine for both non-3d-Secure card and 3d-Secure enabled cards. For initial payments i get the 3d-Secure Payment authentication Modal from Stripe to authenticate payments using 3D-Secure Test cards.
The subscription is created along with invoices that Stripe generates for me. Everything's seems to be OK, BUT for 3D-Secure Enabled (Stripe Testing Cards) the First Payment goes through successfully but the subsequent payments which i have set interval of 1Day (for testing) are "Failed" by Stripe. From what i understand Stripe requires Customer's Authentication again to continue the Subscription.
In this they said
When 3D Secure is encountered, configure your billing settings to send a hosted link to your customer to complete the flow.
That's completely OK, But why they even require the authentication step again if the first payment is succeeded and the subscription is started? I have gone through all the related Docs but found nothing to prevent that.
What if Customer does not check his/her email to come back to my Application to authenticate the payments? OR
Is there anything wrong with the code? By that i mean that Stripe should have saved the Payment Method ie Card Number so it does not require the Customer Authentication on subsequent charges every time the new billing cycle start(monthly/biannually).
I have searched on internet and found and answer saying
You are using stripe.createToken which does not support 3ds authentication. You need to migrate your client side code to stripe.createPaymentMethod which does support it
Is that it? Any response is appreciated
My Payment.js
// set your stripe publishable key
var stripe = Stripe('pk_test_key');
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 cardNumber = elements.create('cardNumber', {
style: style
});
cardNumber.mount('#cardNumber');
var cardExpiry = elements.create('cardExpiry', {
style: style
});
cardExpiry.mount('#cardExpiry');
var cardCvc = elements.create('cardCvc', {
style: style
});
cardCvc.mount('#cardCVC');
var cardholderName = $('#custName').val();
var amount = $('#amount').val();
var cardButton = document.getElementById('makePayment');
cardButton.addEventListener('click', function(ev) {
// alert();
ev.preventDefault();
stripe.createToken(cardNumber).then(function(result) {
if (result.error) {
} else {
//$body.addClass("loading");
fetch('process.php', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
token_id: result.token.id
})
}).then(function(result) {
// Handle server response (see Step 3)
result.json().then(function(json) {
handleServerResponse(json);
//alert();
})
});
}
});
});
function handleServerResponse(response) {
if (response.error) {
// Show error from server on payment form
} else if (response.requires_action) {
// Use Stripe.js to handle required card action
var action = response.next_action;
if (action && action.type == 'redirect_to_url') {
window.location = action.redirect_to_url.url;
}
handleAction(response);
} else {
console.log("3D" + response);
}
}
function handleAction(response) {
var paymentIntentSecret = response.payment_intent_client_secret;
stripe.handleCardPayment(paymentIntentSecret).then(function(result) {
if (result.error) {
// Display error.message in your UI.
} else {
// The payment has succeeded. Display a success message.
alert('Payment succeeded!');
}
});
}
Process.php
<?php
require_once('stripe-php/init.php');
\Stripe\Stripe::setApiKey('sk_test_key');
$json_str = file_get_contents('php://input');
$json_obj = json_decode($json_str);
//print_r($json_obj->token_id);die;
//$intent = null;
try {
if (isset($json_obj->token_id)) {
//Create Customer
$customer = \Stripe\Customer::create([
"email" => "test@gmail.com",
"name" => "Haroon",
"source" => $json_obj->token_id,
]);
//create product
$product = \Stripe\Product::create([
'name' => 'Water',
'type' => 'service',
]);
//create a plan
$plan = \Stripe\Plan::create([
'product' => $product->id,
'nickname' => 'Water',
'interval' => 'day',
'currency' => 'eur',
'amount' => 1200.00,
]);
//add subscription to stripe
$subscription = \Stripe\Subscription::create([
'customer' => $customer->id,
'items' => [[
"plan" => $plan->id],],
'expand' => ['latest_invoice.payment_intent'],
]);
}
$intent = \Stripe\PaymentIntent::retrieve($subscription->latest_invoice->payment_intent->id);
$subscription = \Stripe\Subscription::retrieve($subscription->id);
// $intent->confirm();
// }
generatePaymentResponse($intent,$subscription);
}catch (\Stripe\Error\Base $e) {
# Display error on client
echo json_encode([
'error' => $e->getMessage()
]);
}
function generatePaymentResponse($intent,$subscription) {
if ($intent->status == 'requires_action' && $subscription->status == 'incomplete' &&
$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' && $subscription->status == 'active') {
# The payment didn’t need any additional actions and completed!
# Handle post-payment fulfillment
echo json_encode([
'success' => true
]);
} else if ($intent->status == 'requires_payment_method' && $subscription->status == 'incomplete') {
echo "Subscription failed";
} else {
# Invalid status
http_response_code(500);
echo json_encode(['error' => 'Invalid PaymentIntent status']);
}
}
If you are doing this for already exist card then i have done this just before some day . Refer this document https://stripe.com/docs/payments/3d-secure .
This suggest that you need to create paymentIntent and need to confirm this payment intent . and also in 3ds there are test card 4242 4242 4242 4242 This card does not require any authentication for 3ds . Giving below link for test cards
https://stripe.com/docs/payments/3d-secure/web#three-ds-cards
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.