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 objectejs
: view engine for rendering static HTML files compatible with Expressexpress
: provides a HTTP server framework for Node.jsnodemon
: monitors files for changes and restarts the server automaticallystripe
: 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
Code language: CSS (css)
First thing we’ll do is setup the Express server:
const express = require('express');
const app = express();
app.listen(3000, () => console.log('Server is running...'));
Code language: JavaScript (javascript)
Let’s now test the setup with the following command:
nodemon index.js
Code language: CSS (css)
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:
<!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>
Code language: HTML, XML (xml)
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.
success.html
is just a basic file that displays a payment received message:
<!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>
Code language: HTML, XML (xml)
Next modify the index.js
to include ejs
as follows:
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...'));
Code language: JavaScript (javascript)
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.
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");
Code language: JavaScript (javascript)
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:
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();
}
});
});
Code language: JavaScript (javascript)
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:
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...'));
Code language: JavaScript (javascript)
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 option the offical Stripe.js documentation is an excellent resource.