I was following the stripe docs to create a Subscription.
BOTH LIVE AND SECRET KEYS ARE SET CORRECTLY, at least i Think
On my server when user registers:
import Stripe from 'stripe';
const stripe = new Stripe('sk_test_xxx...',
{
apiVersion: '2020-08-27'
}
);
export const createUser = async (
req: Request,
res: Response,
_next: NextFunction
) => {
// User logic
const customer = await stripe.customers.create({
email: req.body.email
});
user.stripeCustomerId = customer.id;
await user.save();
const subscription = await stripe.subscriptions.create({
customer: customer.id,
items: [
{
price: price_id
}
],
payment_behavior: 'default_incomplete',
expand: [ 'latest_invoice.payment_intent' ]
});
// Sending the payment_intent, ... back to the frontend
responseToSend = {
user: user,
payment: {
subscriptionId: subscription.id,
clientSecret:
subscription!.latest_invoice.payment_intent.client_secret
}
};
}
On the frontend (React):
const stripePromise = loadStripe(
'pk_test_xxx...'
);
...
<Elements stripe={stripePromise} options={options}>
<RegFormStripe />
</Elements>
Which shows payment element: Code in RegFormStripe:
import React, { useState, useEffect } from 'react';
import {
PaymentElement,
useStripe,
useElements
} from '@stripe/react-stripe-js';
const RegFormStripe = () => {
const stripe = useStripe();
const elements = useElements();
const [ errorMessage, setErrorMessage ] = useState(null);
const handleSubmit = async (event) => {
// We don't want to let default form submission happen here,
// which would refresh the page.
event.preventDefault();
if (!stripe || !elements) {
// Stripe.js has not yet loaded.
// Make sure to disable form submission until Stripe.js has loaded.
return;
}
const { error } = await stripe.confirmSetup({
//`Elements` instance that was used to create the Payment Element
elements,
confirmParams: {
return_url: 'http://localhost/payment-status'
}
});
console.log(error);
if (error) {
// This point will only be reached if there is an immediate error when
// confirming the payment. Show error to your customer (e.g., payment
// details incomplete)
setErrorMessage(error.message);
} else {
// Your customer will be redirected to your `return_url`. For some payment
// methods like iDEAL, your customer will be redirected to an intermediate
// site first to authorize the payment, then redirected to the `return_url`.
}
};
return (
<form onSubmit={handleSubmit}>
<PaymentElement />
<button disabled={!stripe}>Submit</button>
{/* Show error message to your customers */}
{errorMessage && <div>{errorMessage}</div>}
</form>
);
};
export default RegFormStripe;
Entering card details results in: No such setupintent: 'pi_xxxx' I googled for similar errors, they all said that the problem was in the API keys. So i tried generating new ones, replacing them, triple checked that they are correct. They might be initialized wrongly, but the content of API keys should definitely be correct.