Stripe is the global standard for SaaS payments.
SassyPack includes a clean Stripe integration layer, allowing you to handle both one-time purchases and recurring plans with minimal setup.
1. Create a Stripe Account
- Go to https://stripe.com
- Complete identity verification
- Navigate to Developers → API keys
- Copy your Publishable Key and Secret Key
Example:
STRIPE_SECRET_KEY=sk_test_51Nxxxxxx
STRIPE_PUBLISHABLE_KEY=pk_test_51Nxxxxxx
2. Add Environment Variables
In your server .env file:
STRIPE_SECRET_KEY=sk_test_51Nxxxxxx
CLIENT_URL=http://localhost:5173
In your client .env file:
REACT_APP_STRIPE_KEY=pk_test_51Nxxxxxx
Restart both frontend and backend servers after saving.
3. Install Dependencies
Backend:
npm install stripe
Frontend:
npm install @stripe/stripe-js @stripe/react-stripe-js
4. Create a Checkout Route in Express
In server/routes/payments.js:
import express from "express";
import Stripe from "stripe";
const router = express.Router();
const stripe = new Stripe(process.env.STRIPE_SECRET_KEY);
router.post("/create-checkout-session", async (req, res) => {
const { priceId } = req.body;
try {
const session = await stripe.checkout.sessions.create({
mode: "subscription",
payment_method_types: ["card"],
line_items: [{ price: priceId, quantity: 1 }],
success_url: `${process.env.CLIENT_URL}/success`,
cancel_url: `${process.env.CLIENT_URL}/cancel`,
});
res.json({ url: session.url });
} catch (error) {
res.status(500).json({ error: error.message });
}
});
export default router;
This route creates a hosted checkout session and returns a redirect URL.
5. Connect Stripe to Your Frontend
In client/src/components/StripeButton.jsx:
import { useState } from "react";
import axios from "axios";
export default function StripeButton({ priceId }) {
const [loading, setLoading] = useState(false);
const handleCheckout = async () => {
setLoading(true);
try {
const res = await axios.post("http://localhost:5000/api/payments/create-checkout-session", { priceId });
window.location.href = res.data.url;
} catch (error) {
alert("Checkout failed");
} finally {
setLoading(false);
}
};
return (
<button onClick={handleCheckout} disabled={loading} className="btn btn-primary w-full">
{loading ? "Loading..." : "Subscribe with Stripe"}
</button>
);
}
Replace priceId with your Stripe product price ID.
6. Create Products and Prices in Stripe
- Go to Products → Add Product
- Add your plan name (e.g., “Pro Plan”)
- Set billing type as Recurring or One-Time
- Save and copy the Price ID (e.g.,
price_1NYZxxxxxx) - Use that ID in your frontend component.
7. Add Success and Cancel Pages
In your client routes:
// Success.jsx
export default function Success() {
return (
<div className="text-center py-20">
<h1 className="text-3xl font-bold mb-4">Payment Successful</h1>
<p>Your subscription is now active.</p>
</div>
);
}
// Cancel.jsx
export default function Cancel() {
return (
<div className="text-center py-20">
<h1 className="text-3xl font-bold mb-4">Payment Canceled</h1>
<p>You can try again anytime.</p>
</div>
);
}
8. Test Your Checkout
Use Stripe test cards for sandbox testing:
Card: 4242 4242 4242 4242
Exp: 12/34
CVC: 123
Click “Subscribe with Stripe” and confirm that the redirect works correctly.
9. Deploy to Production
Once confirmed, replace your test keys with live keys:
STRIPE_SECRET_KEY=sk_live_xxxxxxx
REACT_APP_STRIPE_KEY=pk_live_xxxxxxx
Ensure your success and cancel URLs point to your production domain.
10. Combine Stripe and Paystack
Offer Stripe globally and Paystack regionally.
Detect region via IP or user selection, then display the right payment method dynamically.
Final Notes
Stripe makes your SaaS commercially functional.
With SassyPack’s backend route and React integration ready, you can begin collecting payments immediately without additional setup.