I've read a lot of documentation on "why" my Stripe payment intents are left in a status of "The Customer has not entered a payment method" and that "We recommend that you explicitly provide the payment_method going forward" however I can't tell how do that (provide the payment_method).
When I initialise the Payment Intent object I have "AutomaticPaymentMethods" enabled. I only have 1 payment method enabled in my Stripe Dashboard (cards).
(Also, I'm using Blazor with JS interop for this - if that is relevant...)
string customerId = await getCustomer(); // fetch existing customer from Stripe API based on current user or create a new one
Stripe.PaymentMethodService pms = new PaymentMethodService();
Stripe.PaymentIntentCreateOptions options = new PaymentIntentCreateOptions
{
Amount = p.UnitAmount,
Currency = p.Currency,
Customer = customerId,
ReceiptEmail = "[email protected]",
Description = "Test Purchase",
StatementDescriptor = "Test Purchase",
AutomaticPaymentMethods = new PaymentIntentAutomaticPaymentMethodsOptions
{
Enabled = true,
},
};
Stripe.PaymentIntentService pis = new Stripe.PaymentIntentService();
Stripe.PaymentIntent pi = pis.Create(options);
return pi;
The Payment Method is null on the resulting Payment Intent object.
It is still null after the payment details have been completed in the "payment-element" on my HTML form.
Is the payment_method something I can set up as the Payment Intent object is created (as I only wish to use "cards" at the moment anyway), or is it something I need to set in the confirm_payment JS call? (Either way, how to I obtain that Payment Method?)
CodePudding user response:
Your code creates a PaymentIntent
server-side for say $10 USD. This represents the "state machine" of an overall payment for the customer. They might never pay, or they might try to pay once and get a decline or a success, or they might get declined, try another card and see a success. Each "payment attempt" is represented in the API as a Charge
object and the corresponding payment method details associated with that are represented as a PaymentMethod
.
Now all of that "payment attempt" happens client-side where you collect payment method details and you use those to "confirm the PaymentIntent".
You mentioned you are using PaymentElement which is Stripe's newer UI library component to collect payment method details and accept a payment client-side. Since you only accept card payments, the PaymentElement would get initialized with your PaymentIntent's client_secret
and render the card form to collect those card details.
What you need to do here is have a button to "pay" and when it's clicked, your Javascript code should call the confirmPayment()
method from Stripe.js. Doing that will use the card details entered by the customer and attempt to confirm the PaymentIntent that is for a specific amount and currency. This payment might succeed, in which case the customer is redirected to your return_url
, or it might be declined in which case the promise completes with error details you can handle to surface an error.
What you need to do here is look into your client-side code, ensure that you call confirmPayment()
as expected and debug the response you get back to help narrow it down.
After the PaymentIntent is confirmed successfully and has status: 'succeeded'
then it will have payment_method: 'pm_123'
that is the id of the PaymentMethod
object associated with the successful confirmation. All the information about that card would be on the successful Charge
object associated with it inside payment_method_details
.