Stripe payment implementation in Node.js
Tags: node, javascript, tutorial
Published: 2021-08-03 06:15:23

In this tutorial we’ll be building a simple “Buy me a coffee” app using Stripe and Node.js. Before beginning you’ll need to create a Stripe account (free) and have Node.js installed. Once complete you’ll have a fully functioning form that allows users to send you payments.

##Setting up the project

Open a new terminal window and run the following commands to setup the project:

```
mkdir stripe-node
cd stripe-node
npm init -y
npm install body-parser ejs express nodemon stripe
```

This will initiate the project using the default options and install the following packages:

- `body-parser` : parse incoming form data and convert into an easy to use object
- `ejs` : view engine for rendering static HTML files compatible with Express
- `express` : provides a HTTP server framework for Node.js
- `nodemon` : monitors files for changes and restarts the server automatically
- `stripe` : allows us to use the Stripe.js library as an ES module.

##Setting up the server

Create a new `index.js` file in the root of the project folder:

```
touch index.js
```

First thing we’ll do is setup the Express server:

```javascript
const express = require('express');
const app = express();
app.listen(3000, () => console.log('Server is running...'));
```

Let’s now test the setup with the following command:

```
nodemon index.js
```

You should see the ‘Server is running…‘ message logged in the terminal.

##Setting up the frontend

The frontend will consist of two HTML pages. First the page with the form to collect the payment details (`index.html`) and a secondary page (`success.html`) that we’ll redirect the user to if the payment was successful. These HTML files will need to live inside a `views` folder so go ahead and create that before proceeding.

`index.html` should contain the following markup:

```html
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1" />
    <title>Buy me a coffee</title>
  </head>
  <body>
    <div class="flex justify-center mt-32">
      <h1>Buy me a coffee</h1>
      <form action="/charge" method="POST">
        <label for="email">Email:</label>
        <input type="email" name="email" placeholder="Email" />
        <label for="amount">$</label>
        <input type="number" name="amount" value="5" />
        <div id="payment-card"></div>
        <div id="payment-errors"></div>
        <button>Submit</button>
      </form>
    </div>
    <script src="https://js.stripe.com/v3/"></script>
    <script src="payment.js"></script>
  </body>
</html>
```

This creates input fields for the user to enter their email and payment amount. The empty `payment-card` element will be populated with a form to enter credit card information from Stripe.js. This needs to be loaded directly and not bundled into our application to be [PCI compliant](https://stripe.com/docs/security/guide#validating-pci-compliance).

`success.html` is just a basic file that displays a payment received message:

```html
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1" />
    <title>Buy me a coffee</title>
  </head>
  <body>
    <h1>Payment Received - Thanks!</h1>
  </body>
</html>
```

Next modify the `index.js` to include `ejs` as follows:

```javascript
const express = require('express');
const app = express();

app.set('view engine', 'ejs');
app.engine('html', require('ejs').renderFile);
app.use(express.static('./views'));

app.listen(3000, () => console.log('Server is running...'));
```

With the server running test this by going to http://localhost:3000/ in the browser.

##Setting up the Stripe functionality

Create a `payment.js` file in the views folder. You’ll need to `replace pk_test_XXXXXXXXXXXXXXXXXXXX` with your publishable key which can be found in the Stripe dashboard [here](https://dashboard.stripe.com/apikeys).

```javascript
const stripe = Stripe("pk_test_XXXXXXXXXXXXXXXXXXXX"); 
const elements = stripe.elements();
const card = elements.create("card", { hidePostalCode: true });
card.mount("#payment-card");
const form = document.querySelector("form");
const errors = document.querySelector("#payment-errors");
```

To complete the `payment.js` setup we’ll add an event listener to the form that creates a token in a hidden input field which is used to encrypt the credit card details when the data is sent to Stripe for processing:

```javascript
form.addEventListener("submit", (event) => {
  event.preventDefault();
  stripe.createToken(card).then((res) => {
    if (res.error) {
      errors.textContent = res.error.message;
    } else {
      const stripeToken = document.createElement("input");
      stripeToken.setAttribute("type", "hidden");
      stripeToken.setAttribute("name", "stripeToken");
      stripeToken.setAttribute("value", res.token.id);
      form.appendChild(stripeToken);
      form.submit();
    }
  });
});
```

To complete the project update `index.js` to create the customer and process the payment. As with the publishable key you’ll need to replace `sk_test_XXXXXXXXXXXXXXXXXXXX` with your secret key found in the Stripe dashboard:

```javascript
const express = require('express');
const app = express();
const bodyParser = require('body-parser');
const stripe = require('stripe')('sk_test_XXXXXXXXXXXXXXXXXXXX');

app.set('view engine', 'ejs');
app.engine('html', require('ejs').renderFile);
app.use(express.static('./views'));

app.use(bodyParser.urlencoded({ extended: true }))
app.post("/charge", (req, res) => {
    try {
      stripe.customers
        .create({          
          email: req.body.email,
          source: req.body.stripeToken
        })
        .then(customer =>
          stripe.charges.create({
            amount: req.body.amount * 100,
            currency: "usd",
            customer: customer.id
          })
        )
        .then(() => res.render("success.html"))        
        .catch(err => console.log(err));
    } catch (err) {
      res.send(err);
    }
  });

app.listen(3000, () => console.log('Server is running...'));
```

For testing purposes you can use “4242424242424242” as the credit card number, any expiry date in the future and any 3 numbers for the CVC. If everything has been setup correctly when you enter this information you’ll be redirected to the successful payment page.

That’s all for this tutorial. Hopefully it has given you an understanding of how to process Stripe payments in a Node.js application. There are many more configurable options available not used in this tutorial. To discover all these options the offical [Stripe.js documentation](https://stripe.com/docs/js) is an excellent resource.