Click Below to subscribe

How to Integrate Stripe Payment Gateway In Node.js 2022

Stripe is the most popular and secure payment gateway. In this article, we will integrate stripe(server-side) with our node.js(express) project step by step.

1. Let's create a new express project using express generator.

npm install -g express-generator
express node-stripe --view=hbs //node-stripe is project name

2. Install stripe npm package.

npm install --save stripe

3. Create a new folder config. inside this folder create a file stripe.js 

config/stripe.js 

module.exports = { 
    secretKey: process.env.STRIPE_SECRET_KEY,   // Secret KEY: https://dashboard.stripe.com/account/apikeys 
}

4. Create a .env file and add the stripe secret key environment variable.

STRIPE_SECRET_KEY=       // your secret key

5. Install dotenv npm package.

npm i dotenv

After Installation import dotenv in app.js

require('dotenv').config();

Stripe API Keys - https://dashboard.stripe.com/account/apikeys

Note:- For sandbox keys click on test mode option on the stripe dashboard.

Stripe API

Stripe API provides a bunch of methods to simplify the integration process. stripe payment is divided into two steps.

(a). Tokenization:- In this step stripe collects sensitive card or bank account details and returns a token.

const stripe = require('stripe')('sk_test_0CaAJrFqtvoLO3pfWUayDGgK');

const token = await stripe.tokens.create({
    card: {
        number: '4242424242424242',
        exp_month: 2,
        exp_year: 2023,
        cvc: '314',
    }
});

Ref:- Stripe API Reference - Create a card token

(b). Charge:- In this step stripe will charge the amount using the token created during tokenization

const stripe = require('stripe')('sk_test_0CaAJrFqtvoLO3pfWUayDGgK');
 
const charge = await stripe.charges.create({
    amount: 2000,
    currency: 'usd',
    source: 'tok_amex',
    description: 'My First Test Charge'
});

Note:- amount should be passed in the smallest currency unit. In the above example, 2000 is 20USD. description is optional.

you can also pass extra data in form of key-value pair in metadata field.

Ref:-Stripe API Reference - Create a charge

So let's continue with the integration...

6. We need to create a payment form. 

views/index.hbs

<main>
    <div class="row">
        <aside class="col-sm-6 offset-3">
            <article class="card">
                <div class="card-body p-5">
                    <ul class="nav bg-light nav-pills rounded nav-fill mb-3" role="tablist">
                        <li class="nav-item">
                            <a class="nav-link active" data-toggle="pill" href="#nav-tab-card">
                            <i class="fa fa-credit-card"></i> Credit Card</a>
                        </li>
                    </ul>
                    <div class="tab-content">
                        <div class="tab-pane fade show active" id="nav-tab-card"> 
                            {{#each message}}
                                <p class="alert alert-{{@key}}">{{ this.[0] }}</p>
                            {{/each}}
                            <form role="form" method="POST" id="paymentForm" action="/payment"> 
                                <div class="form-group">
                                    <label for="username">Full name (on the card)</label>
                                    <input type="text" class="form-control" name="fullName" placeholder="Full Name">
                                </div>
                                <div class="form-group">
                                    <label for="cardNumber">Card number</label>
                                    <div class="input-group">
                                        <input type="text" class="form-control" name="cardNumber" placeholder="Card Number">
                                        <div class="input-group-append">
                                            <span class="input-group-text text-muted">
                                            <i class="fab fa-cc-visa fa-lg pr-1"></i>
                                            <i class="fab fa-cc-amex fa-lg pr-1"></i>
                                            <i class="fab fa-cc-mastercard fa-lg"></i>
                                            </span>
                                        </div>
                                    </div>
                                </div>
                                <div class="row">
                                    <div class="col-sm-8">
                                        <div class="form-group">
                                            <label><span class="hidden-xs">Expiration</span> </label>
                                            <div class="input-group">
                                                <select class="form-control" name="month">
                                                    <option value="">MM</option>
                                                    {{#each months}}
                                                        <option value="{{inc @index}}">{{this}}</option>
                                                    {{/each}}
                                                </select>
                                                <select class="form-control" name="year">
                                                    <option value="">YYYY</option>
                                                    {{#each years}}
                                                        <option value="{{this}}">{{this}}</option>
                                                    {{/each}}
                                                </select>
                                            </div>
                                        </div>
                                    </div>
                                    <div class="col-sm-4">
                                        <div class="form-group">
                                            <label data-toggle="tooltip" title=""
                                                data-original-title="3 digits code on back side of the card">CVV <i
                                                class="fa fa-question-circle"></i></label>
                                            <input type="number" class="form-control" placeholder="CVV" name="cvv">
                                        </div>
                                    </div>
                                </div>
                                <button class="subscribe btn btn-primary btn-block" type="submit"> Confirm </button>
                            </form>
                        </div>
                    </div>
                </div>
            </article>
        </aside>
    </div>
</main>

Note:- please checkout github repo - https://github.com/ultimateakash/node-stripe

7. Create a new folder controllers. inside this folder create a file payment.controller.js

controllers/payment.controller.js

const Moment = require('moment');
const MomentRange = require('moment-range');
const moment = MomentRange.extendMoment(Moment);

const config = require('../config/stripe');
const stripe = require('stripe')(config.secretKey);

exports.index = (req, res) => {
    const fromDate = moment();
    const toDate = moment().add(10, 'years');
    const range = moment().range(fromDate, toDate);

    const years = Array.from(range.by('year')).map(m => m.year());
    const months = moment.monthsShort();

    return res.render('index', { months, years, message: req.flash() });
}

exports.payment = async (req, res) => {
    const token = await createToken(req.body);
    if (token.error) {
        req.flash('danger', token.error)
        return res.redirect('/');
    }
    if (!token.id) {
        req.flash('danger', 'Payment failed.');
        return res.redirect('/');
    }

    const charge = await createCharge(token.id, 2000);
    if (charge && charge.status == 'succeeded') { 
        req.flash('success', 'Payment completed.');
    } else {
        req.flash('danger', 'Payment failed.');
    }
    return res.redirect('/');
}

const createToken = async (cardData) => {
    let token = {};
    try {
        token = await stripe.tokens.create({
            card: {
                number: cardData.cardNumber,
                exp_month: cardData.month,
                exp_year: cardData.year,
                cvc: cardData.cvv
            }
        });
    } catch (error) {
        switch (error.type) {
            case 'StripeCardError':
                token.error = error.message;
                break;
            default:
                token.error = error.message;
                break;
        }
    }
    return token;
}

const createCharge = async (tokenId, amount) => {
    let charge = {};
    try {
        charge = await stripe.charges.create({
            amount: amount,
            currency: 'usd',
            source: tokenId,
            description: 'My first payment'
        });
    } catch (error) {
        charge.error = error.message;
    }
    return charge;
}

Note:-  You can store charge.id as a transaction id and later you can fetch the charge data using this id.

Ref:- Stripe API Reference - Retrieve a charge

  

8.  Create routes.

routes/index.js

const express = require('express');
const router = express.Router();
const { validate } = require('../middleware/validator');
const paymentController = require('../controllers/payment.controller');
 
 
router.get('/',                              paymentController.index);
router.post('/payment', validate('payment'), paymentController.payment);

module.exports = router;

9. Finally start the project.

npm start

10. Open http://localhost:3000 and test the integration.

For Testing:-

Card Number: 4242424242424242

Month/Year: Any future date

CVV: Any 3 digits

Ref:- Testing Cards | Stripe

If you facing any issues. please post a comment. I will be happy to help you,
Thanks

Leave Your Comment