Get charge id associated with Stripe checkout session - stripe-payments

I am using Stripe checkout sessions. I am capturing 'checkout.session.completed' webhook. I need to know charge id associated with the session so I can refund the customer later. I am not finding any reference to charge object in the session object.
How can I get charge object associated with checkout session?
I tried capturing charge object in charge.succeeded webhook, but it doesn't have any reference to the price object customer used to purchase.

A completed Checkout Session will have an associated PaymentIntent, which in turn has a list of Charges associated with it.

Related

Stripe - Get risk score from checkout.session.completed event

I have a webhook for checkout.session.completed. There is no information about risk score in the object I receive. How can I get the risk evaluation information for my customers' payments?
I can see the risk score from Stripe dashboard, but I also need it in my database.
The risk_score field is set on the Charge object associated with the payment. This object is not directly available on the Checkout Session object or events.
In order to retrieve these details, you'd need to make an additional API request in your webhook handler. My recommendation would be to retrieve the associated Payment Intent using the pi_xxx ID from the payment_intent field on your checkout.session.completed event, and expand the latest_charge field. The response will include the full Charge object, including the required outcome.risk_score field.
This will look something like this using the stripe-node library:
const paymentIntent = await stripe.paymentIntents.retrieve('pi_xxx', {
expand: ['latest_charge']
})

Provision subscription in checkout.session.completed for first payment

When I create a checkout session, I include the user_id in the metadata. This allows me to retrieve the user_id when checkout.session.completed event is fired which I will need in order to save the stripe customer id in the database for that user.
Is this the correct approach?
The issue I am having now, is that given this logic whenever the first payment is created I will need to provision the subscription in the checkout.session.completed event, future payments will be handled by invoice.paid event. This is because invoice.paid will can only recognise the user by customer id, which gets populated by checkout.session.completed.
Question:
Is my approach for storing the customer id correct?
How can I provision the subscription from the checkout.session.completed event for the first payment and then future payments are provisioned by invoice.paid?
To provision and monitor a subscription, Stripe recommends listening to three events: checkout.session.completed, invoice.paid, and invoice.payment_failed.
If you need a user_id to provision the subscription, then yes adding it on the Checkout Session metadata makes sense.
When you get the invoice.paid event you can retrieve the associated subscription with the subscription property of the invoice. And then, if needed, you can find the Checkout Session for that subscription with the list checkout sessions endpoint and passing the subscription ID.

Stripe APi paymentIntent and sessions object

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.

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.

Can I attach a Stripe PaymentMethod to a Customer several hours after creating the PaymentMethod?

When a user registers on my site, a pending registration object is created. The user must validate their email for an account object to be created.
I'd like to collect the user's payment information when they register but wait to create the Customer object until they actually validate their email and have an account. Is this possible? And is there a maximum amount of time that can elapse before I attach the PaymentMethod to a customer?
Yes this is definitely possible. The best option here is to create a SetupIntent that will let you collect their payment details securely. Once the SetupIntent is completed successfully you will get a valid PaymentMethod that you can then attach to a new customer in the future without a specific time limit.
You can read more about this in Stripe's docs: https://stripe.com/docs/payments/setup-intents

Resources