My site code is housed @ https://github.com/CB-Essential-Services/adorable-chestnut/blob/staging-3/src/components/checkout.js

I am running a Netlify -- Gatsby -- StripeCheckout stack.

Issue: I need the submit button in the code below to both submit form data to Netlify Forms and using an 'onClick' event redirectToCheckout to process payment with Stripe.

Checkout.js

import React, { useState } from "react";
import { loadStripe } from "@stripe/stripe-js";

import _ from 'lodash';

function encode(data) {
    return Object.keys(data)
      .map((key) => encodeURIComponent(key) + '=' + encodeURIComponent(data[key]))
      .join('&')
  }

let stripePromise
const getStripe = () => {
  if (!stripePromise) {
    stripePromise = loadStripe("pk_test_RlvibjeKdvwY81acv2YLwvTM00I3UsWXIi")
  }
  return stripePromise
}

const Checkout = () => {
  const [loading, setLoading] = useState(false)

  const redirectToCheckout = async event => {
    event.preventDefault()
    setLoading(true)

    const stripe = await getStripe()
    const { error } = await stripe.redirectToCheckout({
      mode: "subscription",
      lineItems: [{ price: "price_1Gva5YAeKYVunD5viRkFzoR7", quantity: 1 }],
      successUrl: `http://localhost:8000/thanks/`,
      cancelUrl: `http://localhost:8000/404`,
    })

    if (error) {
      console.warn("Error:", error)
      setLoading(false)
    }
  }

  return (    
<form
    name="transfer"
    method="POST"
    content-type= "application/x-www-form-urlencoded"
    data-netlify-honeypot="bot-field"
    data-netlify="true"
    id="transfer"
    className="transfer"
>
    <p className="screen-reader-text">
        <label>Don't fill this out if you're human: <input name="bot-field" /></label>
    </p>
    <p className="form-row">
        <label htmlFor="transfer-name" className="form-label">Name</label>
        <input type="text" name="name" id="transfer-name" className="form-input" />
    </p>
    <p className="form-row">
        <label htmlFor="transfer-email" className="form-label">Email address</label>
        <input type="email" name="email" id="transfer-email" className="form-input" />
    </p>
    <input type="hidden" name="transfer" value="transfer" />
    <p className="form-row form-submit">
        <button type="submit" className="button" 
        disabled={loading}
      onClick={redirectToCheckout}>
          Pay
          </button>
    </p>
</form>
  )
}

export default Checkout

The redirectToCheckout part works fine. Stripe dev support said I should be able to submit form data to Netlify --> initial convo w/Stripe secondary convo w/Stripe

In summary, Stripe dev support said Yes, I could use redirectToCheckout at any point on the frontend. For instance, submit form data to Netlify using AJAX, then while resolving the result redirectToCheckout.

That's a different method than what I'm doing. I have no idea how utilize AJAX!

But they also implied the process is fluid. My way should be fine. I just need to figure out how to POST the data to Netlify.

1

There are 1 answers

3
Ferran Buireu On

You need to expand and redirect your flow-through redirectToCheckout function once all the validations have been done.

Assuming that your redirectToCheckout function is pushing properly your data to Stripe, you only need to pass your data to Netlify and make a simple redirection.

  const redirectToCheckout = async event => {
    event.preventDefault()
    setLoading(true)

   // form validations here. If passed the validation, send data to Stripe and Netlify

    const stripe = await getStripe()
    const { error } = await stripe.redirectToCheckout({
      mode: "subscription",
      lineItems: [{ price: "price_1Gva5YAeKYVunD5viRkFzoR7", quantity: 1 }],
      successUrl: `http://localhost:8000/thanks/`,
      cancelUrl: `http://localhost:8000/404`,
    })


    fetch(`/`, {
      method: `POST`,
      headers: {
        'Content-Type': `application/x-www-form-urlencoded`,
      },
      body: encode({
        'form-name': `transfer`,
        ...data, // here you need to pass your data object
      }),
    })
      .then(() => console.log(`OK`)) // navigate to desired page
      .catch(error => alert(error));
    };

    if (error) {
      console.warn("Error:", error)
      setLoading(false)
    }
  }

There are a lot of things in the snippet above. First of all, make sure to validate your data properly and creating a data object with key-value pairs for all your fields before sending it to your Stripe API or Netlify, you should need to validate your form before.

Then, you only need to create an asynchronous request using fetch (JavaScript built-in) or using axios for example. When dealing with Netlify forms, the data structure is very important and it's mandatory to have exactly the needed information to pass. You can check this article for further details.

Once your promise ended successfully, you only need to change the console.log(`OK`) for a navigate("/your-page").