Stripe APi paymentIntent and sessions object - stripe-payments

I am having trouble finding out the difference between payment Intent and a session.
Assuming I a customer logs into a page and goes to domain.com/register how can I create session and check if customer has already visited page by using customer email address to get the customer object?
What are the difference between paymentIntent and session and how do they help? I see that session is created on Checkout but not when accepting one time payments.
Current I create a payment intent and it works find but my 'url' has no session

PaymentIntents
A PaymentIntent is an API object in Stripe's API that create encapsulates a lifecycle of a one-time payment.
You typically create your own form on your webpage when using PaymentIntents, create a PaymentIntent using the Stripe API, then confirm it using the cardElement from Stripe Elements (the frontend UI elements for collecting card details).
Checkout
Checkout is a full page "hosted UI" that creates its own PaymentIntent and provides all the UI that a customer needs to enter their card details and takes a payment. It also supports many other payment methods automatically without you having to manually add support for each one.
So a CheckoutSession under the hood uses a Subscription or a PaymentIntent object, depending on whether it was used in subscription or payment mode.

Related

Stripe Elements update subscriber payment method

How to enable users to update their subscription's payment method using Stripe Elements?
I couldn't find any reference to this neither in the docs nor on Stackoverflow.
This is how I'm currently setting the default payment method when the user first subscribes to our service.
Create a Stripe subscription object
Render the React CardElement component.
On submit, I call the browser's side Stripe library with stripe.confirmCardPayment(cardElement)
This then triggers a invoice.payment_succeeded webhook event.
In the webhook event, I get the payment intent ID which I use to retrieve the payment intent object which has the ID of the payment_method attached to it.
I then update Stripe's subscription object to use the successful payment_method's ID as the default payment method.
Is there a way to update the subscription's payment method without making a payment_intent first? Link to docs would be appreciated.
Thank you
You can use SetupIntents to save a customer’s card without an initial payment : https://stripe.com/docs/payments/save-and-reuse-cards-only [until step 4]
Listen for the setup_intent.succeeded webhook event to know when the SetupIntent is successful since the customer could close the browser window or quit the app before the stripe.confirmPayment callback executes.
Update the Subscription to use the resulting PaymentMethod ID as the default payment method.
Alternatively, you could also make use of the Customer Portal to allow customers to update their payment method for a subscription : https://stripe.com/docs/billing/subscriptions/customer-portal

Stripe -- after confirmCardPayment, how to attach the new card to the customer?

I am using a setupIntent to save a card to a customer for future use. I pass the client_secret from the setupIntent to the confirmCardSetup in js.
Later, I create a paymentIntent with that card. If it is declined and the status is requires_payment_method then I email the customer and give them a form to enter a new card, and subit that using confirmCardPayment in js. This works well and the charge succeeds (or becomes requires_capture).
How do I then attach that new payment method to the customer? If I do nothing, then their old saved card is still their primary payment method.
I only want to keep one card on file for each customer. I know I can detach the old card and then attach the new one, but then it will not have been done using a setupIntent, which is apparently more appropriate if I'm going to be charging the card in the future off session.
You can also save a card for future use during a payment using setup_future_usage=off_session by following this guide. The payment method will be automatically attached to the customer provided on the Payment Intent.
Your existing flow can be used, you'd just extend it by:
Prior to confirming the Payment Intent again with the new payment details, update it to set the setup_future_usage option.
After the payment succeeds, detach the old payment method like you mentioned and, if needed, update your internal reference to the payment method to use for that customer to be the new payment method id from the Payment Intent.

payment intent is null in a subscription checkout session

I am integrating stripe using php by following this tutorial:
https://phppot.com/php/manage-recurring-payments-using-stripe-billing-in-php/
(my website has some subscription plans and redirects to the stripe checkout form ) . however, for the last step, I decided not to use webhooks, I chose to store the info like in this tutorial https://www.codexworld.com/stripe-checkout-payment-gateway-integration-php/ (I know it is not for subscription but I just use the success.php code from this tutorial to collect the customer info and payment intent details).
I tested it, gone throught the stripe checkout form , and on success I printed the checkout session object and noticed that the payment_intent field of that object is empty ! so i cannot load the payment intent object and get its info although the payment is successfully made and it is showing on the dashboard . any idea why ??
EDIT :
According to the documenttaion of a checkout session (https://stripe.com/docs/api/checkout/sessions/object), the payment_intent field stores the ID of the PaymentIntent for Checkout Sessions in payment mode. In my case I have a subscription mode not a payment one. however,if I still want to get the $intent->status , can I use the payment_status field of the session object $checkout_session->payment_status?
And if subcription payments really don't have paymentintents , then why did the payment appear in the payments section on the dashboard?
Based on the mode you passed in, either one of payment_intent, subscription or setup_intent will be populated, the rest will be null.
When a Subscription is made, your user is invoiced so it is considered a payment and will appear in the Payments dashboard. You can retrieve the Subscription and access the latest_invoice field to obtain the Invoice object. The Invoice object contains the payment_intent field. This is likely what you're looking for.
Using webhook would simplify the process, since you could listen to invoice.payment_suceeded to retrieve the PaymentIntent ID.

Stripe - Create subscriptions with a customer with PaymentMethod instead of Source (Token)

I'm integrating Stripe Subscriptions in our workflow, but when creating a subscription with a Customer created with a paymentMethod instead of source I receive the error This customer has no attached payment source.
If I call in the browser createToken() and attach it to the customer in the source field it works.
We integrated one-time payments using the new docs with SCA that use createPaymentMethod() and not createToken(), so our customers are saved with paymentMethod, not source, like explained here:
https://stripe.com/docs/payments/cards/saving-cards-after-payment#save-payment-method
curl https://api.stripe.com/v1/customers \
-u sk_test_secret_token \
-d payment_method="{{PAYMENT_METHOD_ID}}"
Furthermore, in the migration guide it says to replace createToken() with createPaymentMethod().
In Scenario 2: Charging customers off-session for their initial payment, I saw the following:
To create subscriptions and charge customers off-session for their
initial payment, you need to:
1) Use CreatePaymentMethod to collect payment information
2) Create a customer using the ID of the PaymentMethod you created
3) Create the subscription
4) Set up error handling using handleCardSetup for authentication failures and handleCardPayment for authorization failures
I followed those steps. I don't create a SetupIntent (just like I don't create it in one-time payments and it works in these cases), and receive the error I said before when trying to create subscriptions.
Is it possible to create subscriptions with a customer with paymentMethod instead of source?
(We reuse cards using the customers created with paymentMethod for one-time payments, so it would be very important to be able to reuse the same customer/card for subscriptions, without the need for the user input data in stripe elements or anything of the sort, because it would break our flow for reusing cards)
I was able to solve it by including the payment method in the field default_payment_method.
This field is described as follows:
ID of the default payment method for the subscription. It must belong
to the customer associated with the subscription. If not set, invoices
will use the default payment method in the customer’s invoice
settings.
So I assumed that it would use the payment method I associated with the customer when not defined. It seems it is not happening, tough, so I needed to pass it explicitly (is it a Stripe bug? or creating the customer with paymentMethod doesn't make it the default payment method in the customer’s invoice settings? I will contact Stripe to make sure).
Update (2019-09-23)
I contacted Stripe asking if this was a bug and they replied:
[...] With that being said though, this wouldn't be a bug on our end, rather
expected behavior.
If you're wanting for the Payment Method that you're adding to the
customer object to be used on subscriptions, or invoices, by default
without specifying the default_payment_method when creating the
subscription then you would want to attach the Payment Method and
specify the invoice_settings.default_payment_method parameter when
updating the customer. This information can be found within our API
reference here:
https://stripe.com/docs/api/payment_methods/attach
The parameter to use when updating this can be found on the customer
object itself, here:
https://stripe.com/docs/api/customers/update#update_customer-invoice_settings-default_payment_method
This can also be specified upon customer creation, which can be seen
here:
https://stripe.com/docs/api/customers/create#create_customer-invoice_settings-default_payment_method
Specifying this parameter would indicate that the card being added
would be the default for subscriptions, as well as invoices, so that
the default_payment_method wouldn't need to be specified upon the
subscription, or invoice, creation.

Stripe: Is there an element that creates a customer without a charge?

Does Stripe have an element that would capture a customers card details but not process any payment?
In my case, I have a form that a client fills out but payment is not processed at that time as the final charges will always change based on what the client needs are. Payment would be processed at a later date.
I did see that WordPress / gravity forms have a module that does this but I would rather not have to create a WordPress site.
You can use Stripe.js with Elements (https://stripe.com/docs/stripe-js) or Stripe Checkout (https://stripe.com/docs/checkout) to collect your customer's card details securely.
Both Stripe.js and Checkout allow you to tokenize a user's credit card details. You can then use those that token/source on your backend to create a new Customer with that token [0] or update an existing Customer.
The Stripe recipe's page actually has an example of using Stripe Checkout to update a user's card details (https://stripe.com/docs/recipes/updating-customer-cards#using-the-token-to-update-the-customers-card).
[0] https://stripe.com/docs/api/customers/create?lang=node#create_customer-source
Hope that helps!
UPDATE: adding that the new version of Stripe Checkout is a hosted page that allows collecting card details for future use via its Setup Mode: https://stripe.com/docs/payments/checkout/setup#retrieve-setupintent

Resources