Adyen session needs to be created after order creation - node.js

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.

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

How can I display Stripe PaymentElement form without creating Payment Intent first?

I'm building a platform for selling video courses using React and Next.js.
My goal is to create a payment form that unauthenticated users can use. I want it to work the way it works on Gumroad - a user opens a modal where they can enter their email, their credit card info, and click "Pay" (see the image). When the user submits this form, I want to create an account for them behind the scenes and process the payment at the same time, and then redirect them to the already purchased course, with them being already logged in to their account. That way the UX is much nicer, and conversions are higher - I don't have to require users to create an account before purchasing the course, to them it all looks like one step.
The problem is that to handle payments, I'm using <PaymentElement />. In order to display this form on my website, I am required to create a Payment Intent first. In order to create a Payment Intent, I have to pass it stripeCustomerId (so that I could save the payment method the user has used), as well as userId (so that, in my webhooks, after the payment succeeds, I could add the course to the list of the courses the user has purchased). And that means that in order for me to display the checkout form, the user has to already have an account and be authenticated.
Can you give me some advice? What can I do, is there a solution or a workaround to this?
What I need is:
Show the user a form where they can enter their email address and credit card info.
When the user clicks "pay", create an account for them (which has userId and stripeCustomerId).
After that, use this information to process the payment.
You can update the Payment Intent's customer after the Payment Intent is created and/or confirmed. That means the flow would look something like this:
Create a Payment Intent
Display the payment page with the Payment Element
When payment successfully completes create a Customer and update the Payment Intent's customer with the Customer ID
Normally, to add a new card information, we should follow that order
Create a new customer on Stripe (using email, first name, lastname, phone, zipcode, etc)
Create a setup intent, get a client secret
Confirm card setup with the client secret (when adding card info)
The payment process comes after with that card info. You can make that new card as default if you want.
Create a guest user first
Create a payment intent using guest user credentials
Display Stripe form on the client
Whenever the user submits the form on the client, update the payment intent with the customer id first then confirm the payment.

How to save card details (payment method) in Stripe using backend?

The docs only covers the case where the payment method is created by the frontend (JS). But there is a risk that the user leaves the website before the frontend sends the information to the backend that the card has been added (and its ID).
In order to make a payment, I need ID of the payment method. I don't want to query Stripe's API for user cards IDs every time before making a payment, so I want to save the payment method ID in my local database. I also want to allow the user to define more payment methods and choose the default one.
Is there a reason you are using the non-recommended workflow you linked to? The most up-to-date version can be found here
Have you checked out using webhook listeners? I use them to create/update my local records.
In the workflow you reference, 3 webhook events potentially fire. First the setup_intent.created event is triggered when your server code generates the SetupIntent and its client_secret. Then, when the user fills out whatever Payment or Card element you instantiate and your frontend code calls the stripe.confirmCardSetup() (or stripe.confirmSetup() in the case of a PaymentElement), both the setup_intent.succeeded and payment_method.attached events will fire.
This last one will POST the payment_method object that was just attached to your customer back to your system. This object will have both the Payment Method ID as well as the associated Customer ID. You can use these to update your local records to map payment methods to customers in your server and avoid unnecessary API calls.

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.

How to automatically capture an authorized order in PAYPAL API using nodejs?

(Unfortunately, after a long research I could not find the answer for my question in stackoverflow).
I am currently integrating the PAYPAL REST API V2 in an e-commerce application and in principle it works fine, but not the way it is supposed to.
According to the documentation I am using the following steps:
Create order with user data and purchase details in the backend (nodejs)
Upon successful order creation, the front-end receives the approve_url and capture_url
The user is redirected to the approve_url and login with its credentials, and in case it is successful, the user is redirected to the predefined return_url (which is defined in the step 1)
If the user agrees with the order, the capture_url is manually called at the end of the checkout and the corresponding amount is transferred.
Since the data returned by the order is not persistent (url is being redirected), I am saving the order id and the capture_link in the local storage, which I don't think it is correct. Therefore, I have two questions:
Upon successful approval of the purchase, is it possible to redirect the user directly to capture?
If not, how can I get the order_id details in the return_url?
Thanks in advance
I figured out that the order Id was being appended to the return_url automatically. The misleading thing was that it was named token instead of order. With the order already approved by the user, I was able to complete the transaction without having to redirect the user again to the front-end.

Resources