How to correctly pass email and name to created customers in Stripe?

My current code is: server (Node js)

app.post("/create-payment-intent", async (req, res) => {
    const { email, name } = req.body;
    const customer = await stripe.customers.create({
        email: email,
        name: name
    });
    const paymentIntent = await stripe.paymentIntents.create({
      customer: customer.id,
      setup_future_usage: "off_session",
      amount: 2499,
      currency: "usd",
      automatic_payment_methods: { enabled: true }
    });
    await stripe.customers.update(customer.id, {
      email: email,
      name: name
    });
    res.send({ clientSecret: paymentIntent.client_secret });
});

client

<body>
    
    <form id="payment-form">
        
        <div id="payment-element"></div>
        <input type="email" id="email" placeholder="Enter email address" required/>
        <input type="text" id="name" placeholder="Full Name" required/>
        <button class="str" id="submit">
            <div class="spinner hidden" id="spinner"></div>
            <span id="button-text">Submit</span>
        </button>
        <div id="payment-message" class="hidden"></div>
    </form>

<script>
document.addEventListener('DOMContentLoaded', async () => {
    ...
    const {clientSecret} = await fetch("/create-payment-intent", {
        method: "POST",
        headers: {
            'Content-Type': 'application/json'
        },
    }).then((r) => r.json())

    const appearance = { theme: 'flat' };
    const elements = stripe.elements({ clientSecret, appearance });
    const paymentElement = elements.create('payment')
    paymentElement.mount('#payment-element')

    const form = document.getElementById("payment-form")
    form.addEventListener('submit', async (e) => {
        e.preventDefault();

        const email = document.getElementById("email").value;
        const name = document.getElementById("name").value;
    
        await fetch("/create-payment-intent", {
            method: "POST",
            headers: {
                'Content-Type': 'application/json'
            },
            body: JSON.stringify({ email: email, name: name })
        }).then((r) => r.json())

        const {error} = await stripe.confirmPayment({
            elements,
            confirmParams: {
                return_url: (endpoint)
            }
        })
        if(error) {
        const message = document.getElementById("payment-message")
        message.innerText = error.message;
        }
    })
})
</script>
</body>

So the problem is if I remove the first payment intent - payment form load will fail.

If I remove the second - then I do not get email and name, but payment will be successful and redirect to the thank you page.

If I use both at the same time -then I see created customer with email and name but second payment will attach and it will tell me on Dashboard that customer did not enter payment detail, but customer did (at first payment) (I understand stripe attach that I gave inside submit).

I’m use Payment Element

I want to achieve the next solution - customer load website, enter email, name and payment details (in my case card or can use apple/google Pay) press button “buy” and will redirect to thank you page. Then I can see on Stripe Dashboard at the customer section - this customer with email and name that customer entered and also saved payment details for future charges if needed.

Note: I’m not a software engineer and all my code I wrote alone by watching youtube lessons, stipe github page(with examples) and code AI platforms. I understand the logic that I need but I don’t have enough skills and unfortunately even the chat GPT can’t help me resolve this problem. The solution I guess is inside the submit event I need to pass only email and name without creating a payment intent but i can’t figure out how to make that.

This topic was automatically closed 182 days after the last reply. New replies are no longer allowed.