payment intent is null in a subscription checkout session - stripe-payments

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.

Related

Stripe create Subscription with payment method in one go instead of two

for my subscription based product I want to have a possibility to subscribe and enter payment details at once with stripe and struggle with that with the api.
In https://stripe.com/docs/billing/subscriptions/build-subscriptions?ui=elements I see an option to create a subscription with payment_behavior='default incomplete' and then enter the details to confirm the payment intent. So far so good. However if I create the subscription like that even before the customer confirms payment details stripe already generates an invoice which is not really what I want before final confirmation by customer.
Options I see:
create setupintent, have this filled by customer via elements and then have the customer subscribe. Technically works nicely but for a sales and customer perspective is not good as it has two steps thus probably reduces conversion.
create the subscription in the background before final subscription confirmation by customer and use the clientsecret of it to pass back to browser and then have customer enter his payment data and submit that and finish the setup of subscription and payment info. Technically works - however I realize that when I create the subscription to get the clientsecret to pass to elements before the customer enters his payment data and confirms the subscription the subscription is not only created but an invoice too - which would be really, i.e. an invoice created before customers really confirms the contract
create setupintent and submit it via elements and in metadata of it add the info of product that customers wants so that when the paymentmethod gets created and I get webhook event I do the booking of the product given in metainfo. May however mean the customer gets to success page but the webhook has not notified yet and thus the customer is not really subscrubed at the point in time but gets a success message he is
same as 3 except do not pass info via metadata but via successUrl parameters which refers to and endpoint at my backend which upon being called after setupintent was setup will do the subscription and then redirect to my frontend which shows success page. That seems like a error prone workaround however.
Create a workflow which is a 2 step sign up and asks for paymentinfo, sets that up and then brings customer to a final confirmation page where the submit triggers subscription creation. Seems a bit complicated from a user flow, but so far probably the best option?
Any better options?
Cheers
Tom
ps: Interestingly enough on discord stripe support told me #2 is the way to go - find it hard to believe ...
As far as I know, there isn't a workaround for this unfortunately. It is just how Subscriptions API is designed by Stripe. You can learn more about that here where they talk about "how subscriptions work".

Adyen session needs to be created after order creation

I am working on a store where we need to integrate Adyen React drop-in components.
I have followed and integrated the guide from here: https://docs.adyen.com/online-payments/web-drop-in
So the workflow that we need to implement is the following:
User adds products to cart
User checkouts and is redirected to checkout page
User adds billing details as well as payment details (card details)
After validation of data, user clicks "Pay"
Order is created
If payment was OK, then order is moved to confirmed status
Else, if payment was refused, order is moved to awaiting payment status.
But right now the integration with Adyen forces us to the following steps:
User adds products to cart
User checks out and is redirected to checkout page
User adds billing details
Adyen session is initiated (with 'reference' to an order ID which is not created at this time), so that the payment details can be filled with user data
User adds payment details
....rest
When creating an Adyen SESSION, it is mandatory to provide a reference, and this reference will be the link between an order and a payment. From the above workflows, you can see that we are forced to have an order ID as soon as the user fills payment data and we don't want that.
We want to create the order only at the end of transaction.
Is it possible to achieve this?
I have tried following the React and NodeJS guides available on git repository but they are just generating a random UUID for every payment
Unfortunately it is not possible to modify the payment reference after creating the session.
The only way around would be to re-create a new session (using the OrderId) but still before performing the payment.

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 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.

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.

Resources