Stripe TypeError: Cannot read property 'payment_intent' of undefined - node.js

I'm integrating the payment methods to the app with Stripe and Paypal and now working on Stripe integration.
The backend is Node, Sails.js, and the frontend is React.js.
I followed the guide they provided but and tested the payment processing using testing card.
But I got the error, which says TypeError: Cannot read property 'payment_intent' of undefined.
Here is my code.
- Frontend
this.props.stripe.createPaymentMethod({
type: 'card',
card: cardElement,
}).then(({paymentMethod}) => {
// API call
})
- Backend
subscribe = await stripe.subscriptions.create({
customer: customerId,
items: [
{price: plan.stripe.stripeId},
],
expand: ['latest_invoice.payment_intent']
});
Please help me to fix this issue.

In my opinion you don't have to create the PaymentIntent per subscrition.
Here is what Stripe API docs says about paymentIntent.
A PaymentIntent guides you through the process of collecting a payment from your customer. We recommend that you create exactly one PaymentIntent for each order or customer session in your system. You can reference the PaymentIntent later to see the history of payment attempts for a particular session.
So they recommend to create the paymentIntent per transaction and in subscription case, the payment is proceed in background automatically and paymentIntent is also generated in my experience.
But on the other hand in checkout option, you need to create the paymentIntent first before proceeding the payment.
I think you code was not wrong but I think you didn't follow the correct guide from Stripe or used wrong credit card.
Please refer this link:
Stripe API Payment_intents

Related

NodeJs Update default credit card of customer for Stripe subscriptions and payment

I am building an app in which i am using stripe to handle all payments. And in our app we have a common feature where user can update the default card for their subscriptions but it not working as expected. I Have followed the instruction to update the customer payment method as described in the stripe documentation but it's not working as expected i still see the old credit card details as default payment method in stripe dashboard.
Updating the customer:
const customer = await stripe.customers.update(body.customerId, {
invoice_settings: {default_payment_method: body.pId},
});
Attaching payment method to customer and updating subscription:
const paymentMethod = await stripe.paymentMethods.attach(body.pId, {
customer: body.customerId,
});
await stripe.subscriptions.update(subscriptionDetails?.planId as string, {
default_payment_method: paymentMethod.id,
});
But still nothing, i am not sure what i am missing here but i couldn't update the default payment method.
The screenshot you shared refers to the payment methods saved on the Customer. If you wish to set the default payment method on the Customer, it will be under invoice_settings.default_payment_method on Customer API.
Subscription's default payment method is different from Customer's default payment method. With default_payment_method on Subscription API, it will only update the default on the Subscription object, not Customer object like the page you see. You should be able to find Subscription's default payment method at the Subscription page.
Subscription page link will be: https://dashboard.stripe.com/test/subscriptions/sub_xxx where sub_xxx is the Subscription ID.

Generate Stripe Subscription Link

I want to create a payment link for a subscription in the backend and send it to the client without having any frontend site.
const customer = await stripe.customers.create({
metadata: {
author_id: "author_id",
custom_id: "custom_id",
},
....
}
First I created a customer, using my app specific credentials. Then I want to generate a link using this custome id, but I'm kinda confused how to make it work,
Stripe documentation shows something like this,
await stripe.paymentLinks.create({
line_items: [{price: price_id, quantity: 1}],
});
But it creates a completely new product price.
Is there any way to create a link using pre made product price id and customer metadata using Stripe NodeJS backend?
You cannot pass a pre-existing Customer object (cus_xxx) when creating a Payment Link. The default behaviour for Payment Links infer that a new Customer object be created depending on other parameters set on the Payment Link, as noted in the documentation:
The Checkout Session will only create a Customer if it is required for Session confirmation. Currently, only subscription mode Sessions require a Customer.

Stripe Offline Payments

I am trying to do offline payments using stripe, for which I need to authorize SetupIntent for future payments.
I am creating SetupIntent in Node js as below -
const setupIntent = await stripe.setupIntents.create({
customer: customer.id,
payment_method_types: ['card'],
usage: 'off_session',
});
And I am confirming SetupIntent in React as below -
stripe.confirmCardSetup(setupResponse.clientSecret, {
payment_method: {
card: elements.getElement(CardElement),
billing_details: {
name: name,
email: email
},
}
})
.then(async function (result) {
});
As mentioned in stripe documentation, to do offline payments we need to create mandate_data object. But for it payment method is required and confirm should be true.
Since I am attaching payment method to SetupIntent from React frontend, after SetupIntent is created, so, I am unable to use mandate_data.
I have also followed https://stripe.com/docs/payments/save-and-reuse this documentation. But it gives me authentication required error every time for offline payments.
Any pointers please.
In general, cards set up for future offline usage are subject to re-authentication at the discretion of the bank/issuer.
If you're using Indian-issued cards in particular, then it is currently expected that every payment will require authentication. See docs here:
https://support.stripe.com/questions/rbi-regulations-guide-for-direct-payments-users

Add Stripe Credit Card without Payment in SwiftUI

I am struggling to find a solution that isn't UIKit, or one that requires you make a purchase.
My project is trying to integrate Stripe in SwiftUI, using node.js Firebase Functions for backend handling.
I built a STPPaymentCardTextField in UIViewRepresentable. Which allows me to obtain credit card details for the customer via State.
#State var params: STPPaymentMethodCardParams = STPPaymentMethodCardParams()
SwiftUI TextField
StripePaymentCardTextField(cardParams: $params, isValid: $isValid)
Then we can build paymentMethodParms like..
let paymentMethodParams = STPPaymentMethodParams(card: params, billingDetails: billingDetails, metadata: nil)
Now I could easily pass the credit card details to my backend and add the card manually using
Function for adding payment method
const createPaymentMethods = functions.https.onCall(async (data, context) => {
const paymentMethod = await stripe.paymentMethods.create({
customer: '{{CUSTOMER_ID}}',
payment_method: '{{PAYMENT_METHOD_ID}}',
}, {
stripeAccount: '{{CONNECTED_STRIPE_ACCOUNT_ID}}',
});
}
but I am understanding this is bad practice.
I found this post which might be a "duplicate", but is the closest relevant answer. Adding customer's Credit card info in stripe. That user however is using reactjs and wanted to store credit card details in a database, where I only want to pass it to Stripe.
Is there not a way I can send the credit card data to Stripe, get a paymentMethod ID back, and pass that to my backend or something? I have already solved subscriptions, and purchase charging, I just can't get a credit card setup without going through the payment setup process. I want the user to add a credit card manually on creating a new account and/or in settings.
Can you call stripe-ios's createPaymentMethod() function [0]? That is a client-side function your SwiftUI app would call to tokenize the card details from paymentMethodParams into a PaymentMethod object. You can then pass that ID server-side to attach to a Customer.
[0] https://stripe.dev/stripe-ios/docs/Classes/STPAPIClient.html#/c:#CM#Stripe#objc(cs)STPAPIClient(im)createPaymentMethodWithPayment:completion:
To expand on #hmunoz's answer and the way I got this to work is as follows.
Create your user a Stripe account. https://stripe.com/docs/api/customers/create
Log the customers stripe id in your user's Firestore database for easy reference.
Create an "Add card" view to your frontend and call to the add payment method function. https://stripe.com/docs/api/cards/create
Upon checkout as long as the customer's stripe ID is passed in the payment intent it should populate with their saved payment methods.
In summary it is best to keep track of your user that is signed in so that you can do any CRUD needed throughout.

Stripe adding paymentMethod to trial subscription and later validate credit card

I'm working on stripe integration with react node.js
While creating a subscription without trial, I have no issues, and all use-cases are much simple.
But, I'm trying to create free trial without collecting credit card details, later when trial expired, I would like to collect credit card details
Server side: Creating Trial Subscription without payment method:
const subscription = await stripe.subscriptions.create({
customer: customer.id,
items: [{ price: priceId }],
trial_end: expiredAt.unix(),
expand: ['latest_invoice.payment_intent'],
});
ClientSide: Later when trial expired, I would like to collect credit card details(paymentMethod), check if user action is required due to failures or 3ds and update the subscription by updating the customer's default payment_method:
const updateCustomerDefaultPaymentMethod = await stripe.customers.update(
customerId,
{
invoice_settings: {
default_payment_method: req.body.paymentMethodId,
},
}
);
How can I update the subscription to perform paymentIntent or charge the user, and return to client same subscription object with status 'in_complete' same as when creating subscription without trial_period?
Currently when running my code, I keep getting status='active' because the first invoice is in status='paid' with price of '0$'.
In the case of a free trial, creating a subscription won't result in an initial payment, and Stripe will instead create a SetupIntent under the hood for you automatically. This SetupIntent is meant to be used when collecting the customer's payment method. So at any point during the trial, the customer would need to return to your app to enter their credit card details, which you would then save using the SetupIntent:
subscription.pending_setup_intent
Confirm the SetupIntent with the collected card details
Once the payment method is setup and saved to the customer (as the default payment method for invoices) it will be used to pay for the subscription's first invoice when the trial ends. The first payment after a trial is considered an off-session payment (last FAQ), so if that payment fails Stripe will attempt to recollect the payment using the usual smart retries and dunning functionality.
In a nutshell, you need to use the SetupIntent that's created (and attached to the subscription) to save the user's payment information.

Resources