Integrating a payment module into your NestJS application can enable seamless transactions for your users. In this guide, we will walk you through integrating Stripe into your NestJS application.
1. Set Up Your NestJS Application
Start by setting up your NestJS project. If you haven’t done so already, install the NestJS CLI and create a new application:
npm i -g @nestjs/cli
nest new my-app
Navigate to the newly created project directory:
cd my-app
2. Install Stripe and Necessary Packages
To integrate Stripe, we need to install the Stripe package and other necessary dependencies:
npm install stripe @nestjs/config
- Stripe: The official Stripe package for Node.js.
- @nestjs/config: For managing configuration within NestJS.
3. Configure Stripe API Keys
Once you have the necessary dependencies, you need to configure your API keys. Go to the Stripe Dashboard to get your test and live API keys.
Create a .env
file in the root of your project to store your Stripe keys:
STRIPE_SECRET_KEY=your_stripe_secret_key_here
STRIPE_WEBHOOK_SECRET=your_stripe_webhook_secret_here
4. Webhooks in Stripe
What is a Webhook?
A Webhook in Stripe is a way for Stripe to notify your application about events that happen in your Stripe account. It’s a mechanism that allows you to receive real-time updates from Stripe about specific events, such as successful payments, subscription renewals, disputes, etc.
What is a Webhook Used For?
Real-time Notifications: A webhook allows Stripe to notify your application when certain events occur, like a successful payment or an updated payment status.
Handling Payment Success or Failure: For example, when a payment is completed, Stripe will send an event to your webhook endpoint to notify you. This helps you update the user interface or take appropriate actions (like sending a confirmation email or updating the order status).
Security: Webhooks ensure that you are notified about changes on Stripe’s side, so you can securely handle sensitive payment-related actions in your backend.
Asynchronous Processing: Some actions, like payment authorization, may take time to process. Webhooks ensure that once the payment status is finalized, you are notified even if the user has already left the site or made the payment via a different method (like mobile wallets).
Why Are Webhooks Important?
- Real-time Updates: They allow your system to react to events immediately as they happen, even if the user is not actively interacting with your application.
- Accuracy: Webhooks ensure that your system is always synchronized with Stripe, particularly when payments or subscription statuses change.
- Scalability: You can rely on Stripe to notify your system about key events, removing the need to frequently poll Stripe for updates.
In short, webhooks are essential for handling payments and related actions in a scalable, real-time, and secure manner in your Stripe integration.
5. Set Up Stripe Service
Now, let’s create a service to handle Stripe payment requests, including the webhook verification.
Create a Stripe Service
nest generate service stripe
In stripe.service.ts
, configure the Stripe service and implement the webhook handling logic:
import { Injectable, Logger } from '@nestjs/common';
import Stripe from 'stripe';
import { ConfigService } from '@nestjs/config';
@Injectable()
export class StripeService {
private stripe: Stripe;
private readonly logger = new Logger(StripeService.name);
constructor(private configService: ConfigService) {
const secretKey = this.configService.get('STRIPE_SECRET_KEY');
this.stripe = new Stripe(secretKey, {
apiVersion: '2022-08-01',
});
}
async createPaymentIntent(amount: number) {
return this.stripe.paymentIntents.create({
amount,
currency: 'usd',
});
}
async handleWebhook(payload: any, sig: string) {
const webhookSecret = this.configService.get('STRIPE_WEBHOOK_SECRET');
try {
const event = this.stripe.webhooks.constructEvent(payload, sig, webhookSecret);
switch (event.type) {
case 'payment_intent.succeeded':
this.logger.log('Payment Intent was successful!', event.data.object);
break;
case 'payment_intent.failed':
this.logger.log('Payment Intent failed!', event.data.object);
break;
// Handle other events
default:
this.logger.warn(`Unhandled event type: ${event.type}`);
}
} catch (err) {
this.logger.error('Error verifying webhook signature', err);
throw new Error('Webhook verification failed');
}
}
}
Explanation:
- Stripe Initialization: We initialize Stripe using the secret key from the environment configuration.
-
Payment Intent Creation: The
createPaymentIntent
function will generate a new payment intent that we can use for payment processing. -
Webhook Handling: The
handleWebhook
function listens for Stripe events likepayment_intent.succeeded
orpayment_intent.failed
and handles them accordingly. The event's authenticity is verified using the webhook secret.
6. Create a Payment Controller
To handle payment requests, create a controller:
nest generate controller stripe
In stripe.controller.ts
, create an endpoint to trigger payment and another to receive webhooks from Stripe:
import { Controller, Post, Body, Headers } from '@nestjs/common';
import { StripeService } from './stripe.service';
@Controller('payments')
export class StripeController {
constructor(private readonly stripeService: StripeService) {}
@Post('create-payment-intent')
async createPaymentIntent(@Body() body: { amount: number }) {
return this.stripeService.createPaymentIntent(body.amount);
}
@Post('webhook')
async handleWebhook(@Body() payload: any, @Headers() headers: any) {
const sig = headers['stripe-signature'];
return this.stripeService.handleWebhook(payload, sig);
}
}
7. Testing the Payment Module
To test the payment functionality, run the NestJS server:
npm run start
You can now send a POST request to the /payments/create-payment-intent
endpoint with a JSON body containing the amount (in cents):
{
"amount": 5000
}
This will create a payment intent for $50. You can use tools like Postman or cURL to test the API.
8. Frontend Integration
Once the backend is set up, you can use Stripe's Stripe.js and Elements to handle the frontend payment forms. Refer to Stripe’s official documentation for more details on integrating Stripe on the client side.
Conclusion
In this tutorial, we successfully integrated Stripe’s payment system into a NestJS application. This setup is a starting point, and you can customize it further based on your business needs. With this setup, you now have a simple, secure way to handle payments in your NestJS applications.
Happy coding!
Top comments (0)