Skip to content
Stripe Payments Integration Guide — Accept Payments Online

Stripe Payments Integration Guide — Accept Payments Online

DodaTech Updated Jun 7, 2026 7 min read

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
  
Prerequisites: Basic JavaScript and Node.js experience. A Stripe account (free) and basic understanding of HTTP and webhooks.

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/webhooks

Stripe 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_1QqXxY

Common Mistakes

  1. Not verifying webhook signatures: Without signature verification, an attacker can send fake webhook events and grant access without payment. Always use stripe.webhooks.constructEvent.

  2. Trusting the success_url alone: Users can visit /success without paying. Never grant access based on the success URL — always wait for the webhook confirmation.

  3. 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.

  4. Not idempotent webhook handling: Stripe may send the same event multiple times. Use event.id to deduplicate — grant access only once per checkout session.

  5. Forgetting to handle subscription cancellations: When a subscription is canceled or payment fails, Stripe sends customer.subscription.deleted or invoice.payment_failed. Handle these to revoke access.

Practice Questions

  1. 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.

  2. 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.

  3. 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.

  4. 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

Is Stripe free to use?
: Stripe charges 2.9% + $0.30 per successful transaction. No setup fees, no monthly fees for standard processing. Some features (like Invoicing) have additional costs.
Does Stripe support international payments?
: Yes. Stripe supports 135+ currencies and payment methods including Visa, Mastercard, PayPal, Apple Pay, Google Pay, SEPA, Alipay, and more.
How does Stripe handle refunds?
: Full or partial refunds can be issued from the Dashboard or API. The fee percentage is refunded, but the $0.30 fee is not.
Can I use Stripe without a backend?
: Yes, with Stripe Checkout you can create sessions from client-side code using the stripe js library and a limited scope key. However, webhooks still need a server.
What happens if a subscription payment fails?
: Stripe retries the payment automatically based on Smart Retries (up to 3 times over several days). After all retries fail, the subscription is marked as past_due, then eventually canceled.

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

TopicDescription
Node.js
Run your Stripe integration server
API Security
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