Stripe Payments Integration Guide — Accept Payments Online
Stripe is a payment processing platform that lets you accept payments online with a few lines of code — handling everything from credit card processing to subscription billing, fraud detection, and global compliance.
What You’ll Learn
- Setting up a Stripe account and understanding test mode
- Creating products and prices in the Stripe Dashboard
- Building a Checkout Session for one-time and recurring payments
- Handling webhook events for payment confirmation
- Using the Stripe CLI for local testing
- Going live with production payments
Why Stripe Matters
Payment processing involves PCI compliance, card network rules, fraud detection, tax calculation, and global currency conversion — all of which are complex and error-prone. Stripe abstracts this complexity behind a single API, handling PCI compliance Level 1 (the highest tier) so you never touch raw card data. DodaZIP uses Stripe for its subscription plans because the Checkout Session handles everything from payment confirmation to receipt emails without exposing DodaZIP to sensitive card information.
flowchart LR
A[JavaScript & Node.js Basics] --> B[Stripe]
B --> C[Products & Prices]
B --> D[Checkout Session]
B --> E[Webhooks]
B --> F[Subscriptions]
C --> G[Payment Link]
D --> H[Stripe Checkout UI]
E --> I[Backend Confirmation]
style B fill:#6772e5,color:#fff
Core Concepts
Stripe Account and Test Mode
# Install Stripe CLI for local development
# macOS: brew install stripe/stripe-cli/stripe
# Linux: see docs
# Login and link your account
stripe login
# Forward webhooks to local server
stripe listen --forward-to localhost:3000/api/webhooksStripe gives you test mode keys — start with sk_test_ and pk_test_. Everything in test mode uses fake card numbers (4242 4242 4242 4242 always succeeds). Switch to live keys only when ready to accept real payments.
Products and Prices
const stripe = require("stripe")(process.env.STRIPE_SECRET_KEY);
// Create a product (the item being sold)
const product = await stripe.products.create({
name: "Premium Plan",
description: "Full access to all features",
});
// Create a price (how much and how often)
const price = await stripe.prices.create({
product: product.id,
unit_amount: 1999, // $19.99 in cents
currency: "usd",
recurring: { interval: "month" }, // Omit for one-time
});
console.log(`Price ID: ${price.id}`);
// pi_1QqXxY...
Output: A product and a recurring price of $19.99/month. The price.id is used to create Checkout Sessions. Always store price IDs, not amounts, in your code.
Checkout Session
// Server-side endpoint to create a checkout session
app.post("/api/create-checkout-session", async (req, res) => {
const session = await stripe.checkout.sessions.create({
line_items: [
{
price: "price_1QqXxY...", // Price ID from above
quantity: 1,
},
],
mode: "subscription", // or "payment" for one-time
success_url: "https://example.com/success?session_id={CHECKOUT_SESSION_ID}",
cancel_url: "https://example.com/cancel",
customer_email: req.body.email,
});
res.json({ url: session.url });
});
// Client-side redirect
// window.location.href = session.url;
Output: Stripe returns a URL to a hosted Checkout page. The user enters their card details on Stripe’s PCI-compliant page — you never handle card numbers. After payment, Stripe redirects to your success_url.
Webhooks — Getting Payment Confirmation
Your frontend redirects after payment, but server-side confirmation needs webhooks:
// Handle Stripe webhook events
app.post("/api/webhooks", express.raw({ type: "application/json" }), async (req, res) => {
const sig = req.headers["stripe-signature"];
let event;
try {
event = stripe.webhooks.constructEvent(
req.body,
sig,
process.env.STRIPE_WEBHOOK_SECRET
);
} catch (err) {
console.error("Webhook signature verification failed");
return res.status(400).send(`Webhook Error: ${err.message}`);
}
// Handle specific events
switch (event.type) {
case "checkout.session.completed":
const session = event.data.object;
await grantAccess(session.customer_email);
console.log(`Payment completed for ${session.customer_email}`);
break;
case "customer.subscription.updated":
case "invoice.payment_succeeded":
// Handle recurring billing events
break;
case "customer.subscription.deleted":
await revokeAccess(event.data.object.customer_email);
break;
}
res.json({ received: true });
});Output: When Stripe confirms a payment, it sends a POST to your webhook endpoint with the event data. Always verify the signature — without it, anyone could fake payment confirmations. Return 200 quickly; Stripe retries if you don’t respond.
Stripe CLI Testing
# Trigger test events
stripe trigger checkout.session.completed
# Or create a test checkout session
stripe checkout --price price_1QqXxYCommon Mistakes
Not verifying webhook signatures: Without signature verification, an attacker can send fake webhook events and grant access without payment. Always use
stripe.webhooks.constructEvent.Trusting the success_url alone: Users can visit
/successwithout paying. Never grant access based on the success URL — always wait for the webhook confirmation.Storing price amounts instead of price IDs: If you hardcode $19.99 and later change the price, your old customers are affected. Store the Stripe Price ID and let Stripe manage the amount.
Not idempotent webhook handling: Stripe may send the same event multiple times. Use
event.idto deduplicate — grant access only once per checkout session.Forgetting to handle subscription cancellations: When a subscription is canceled or payment fails, Stripe sends
customer.subscription.deletedorinvoice.payment_failed. Handle these to revoke access.
Practice Questions
Why should you use Stripe Checkout instead of building your own payment form? Answer: Stripe Checkout is PCI-compliant and handles card data on Stripe’s servers. Building your own form requires PCI SAQ compliance and exposes you to card data liability.
What’s the difference between test mode and live mode? Answer: Test mode uses fake card numbers and doesn’t process real payments. Live mode charges real cards. Each mode has separate API keys.
How do webhooks differ from the success_url? Answer: The success_url is a client-side redirect that can be visited without payment. Webhooks are server-side HTTP callbacks from Stripe that are reliably delivered and can be verified.
What is the purpose of idempotency in webhooks? Answer: Stripe may deliver the same event multiple times. Idempotent handling ensures you only process each event once — preventing duplicate access grants or charges.
Challenge
Build a subscription SaaS: create Stripe products for Basic ($9.99/mo) and Pro ($29.99/mo), implement a Checkout Session endpoint, set up webhook handling for checkout.session.completed, invoice.payment_succeeded, and customer.subscription.deleted, test everything with the Stripe CLI, and write a script to list all active subscriptions.
FAQ
Try It Yourself
# 1. Create a Stripe account and get test keys
# 2. Create a product and price in the Dashboard
# 3. Install Stripe CLI and forward webhooks
npm install stripe
# 4. Create a checkout session and open the URL
node -e "
const stripe = require('stripe')('sk_test_...');
stripe.checkout.sessions.create({
line_items: [{price: 'price_id', quantity: 1}],
mode: 'payment',
success_url: 'https://example.com/success',
cancel_url: 'https://example.com/cancel',
}).then(s => console.log(s.url));
"Copy the URL to your browser and pay with 4242 4242 4242 4242, any future date, any CVC.
What’s Next
| Topic | Description |
|---|---|
| Run your Stripe integration server | |
| Secure your payment endpoints |
Related topics: JavaScript, Node.js, REST API, Webhooks
What’s Next
Congratulations on completing this Stripe tutorial! Here’s where to go from here:
- Practice daily — Consistency is more important than long study sessions
- Build a project — Apply what you learned by building something real
- Explore related topics — Check out other tutorials in the same category
- Join the community — Discuss with other learners and share your progress
Remember: every expert was once a beginner. Keep coding!
Built by the developers of Doda Browser, DodaZIP, and Durga Antivirus Pro.
Built by the developers of DodaTech
Doda Browser, DodaZIP & Durga Antivirus Pro