Dans ce didacticiel, nous allons explorer comment intégrer de manière transparente la passerelle de paiement Stripe dans nos applications complètes et les héberger sans effort sur FL0. 🚀
Qu'il s'agisse d'une application e-commerce ou d'une application SaaS, les passerelles de paiement sont au cœur de nos projets. 💳
Dans ce guide, nous explorerons comment simplifier ces intégrations, en nous concentrant spécifiquement sur Stripe Checkout pour le traitement des paiements en ligne.
L'API conviviale pour les développeurs de Stripe garantit des transactions sécurisées et efficaces tout en réduisant notre temps de développement.
A titre d'exemple, nous avons pris le cas d'une page de paiement d'applications SaaS.
Nous utiliserions NodeJs
pour le backend et Postgres comme base de données. Sur le frontend, nous utilisons ReactJs
avec vite
.
Plus tard, nous irions de l'avant et hébergerions sans effort notre projet sur FL0. ⬆️
Alors, commençons par une pincée d'humour :
🧑💻 Dans ce didacticiel, nous allons créer une application de démonstration simple où un utilisateur peut s'inscrire, sélectionner son forfait et payer avec sa carte de crédit.
Pour cela, nous aurions besoin de créer 2 référentiels séparés, un pour notre backend
et un autre pour frontend
.
🗂️ Voici à quoi ressembleraient nos deux structures de dossiers, juste pour référence :
Maintenant, commençons.
Par souci d'efficacité, dans ce tutoriel, nous utiliserons le modèle " fl0zone/blog-express-pg-sequelize ".
Ensuite, nous supprimerions tous les fichiers ou dossiers non importants pour notre projet. 🧑💻
Pour une compréhension plus complète du didacticiel, vous pouvez vous référer à cet article de blog.
Notre modèle encapsule une application Node.js
de base et une base de données PostgreSQL
dockerisée.
Voici le fichier docker-compose.yaml
correspondant à notre configuration 🐳 :
version: "3" services: app: build: context: . target: development env_file: .env volumes: - ./src:/usr/src/app/src ports: - 8081:80 depends_on: - db db: image: postgres:14 restart: always environment: POSTGRES_USER: admin POSTGRES_PASSWORD: admin POSTGRES_DB: my-startup-db volumes: - postgres-data:/var/lib/postgresql/data ports: - 5432:5432 volumes: postgres-data:
Maintenant, nous allions de l'avant et installions quelques packages essentiels 📦
npm install bcrypt cookie-parser cors jsonwebtoken pg-hstore stripe
Maintenant, nous aurions besoin d'obtenir nos clés API Stripe 🔑. Pour cela, nous aurions besoin de créer un nouveau compte sur Stripe.
Ici, nous utiliserions Test Mode
pour la démonstration.
Voici la liste des variables d'environnement dont nous aurions besoin pour ce projet.
.env.example
STRIPE_PUBLISHABLE_KEY= STRIPE_SECRET_KEY= POSTGRES_DB_URI= secretKey= CLIENT_URL=
Commençons par configurer notre base de données maintenant. 🐘
Puisque nous utilisons l'ORM Sequelize, nous devrons créer un modèle pour nos données utilisateur.
Voici le code de notre modèle 👇
models/userModel.js
module.exports = (sequelize, DataTypes) => { const User = sequelize.define( "user", { email: { type: DataTypes.STRING, unique: true, isEmail: true, //checks for email format allowNull: false, }, password: { type: DataTypes.STRING, allowNull: false, }, tier: { type: DataTypes.STRING, allowNull: true, }, }, { timestamps: true } ); return User; };
Maintenant, allons-y et créons nos itinéraires
POST /login
- Aide à se connecter à l'utilisateur et à stocker la session
POST /signup
- Aide à créer un nouveau compte
POST /create-checkout-session
- Génère et renvoie le lien de la page de paiement Stripe
Ces 3 routes sont séparées en 2 fichiers comme suit :
routes/userRoutes.js
const express = require("express"); const userController = require("../controllers/userController"); const { signup, login } = userController; const userAuth = require("../middleware/userAuth"); const router = express.Router(); router.post("/signup", userAuth.saveUser, signup); router.post("/login", login); module.exports = router;
routes/stripeRoute.js
const express = require("express"); const { updatePlan } = require("../controllers/stripeController"); const router = express.Router(); router.post("/create-checkout-session", updatePlan); module.exports = router;
🧑💻 Pour configurer le profil utilisateur, nous allons d'abord définir un middleware pour vérifier si l'adresse e-mail d'un nouvel utilisateur existe déjà dans la base de données lors de l'inscription.
middleware/userAuth.js
//importing modules const express = require("express"); const db = require("../models"); const User = db.users; const saveUser = async (req, res, next) => { console.log("here"); try { const checkEmail = await User.findOne({ where: { email: req.body.email, }, }); if (checkEmail) { return res.json(409).send("Authentication failed"); } next(); } catch (error) { console.log(error); } }; module.exports = { saveUser, };
Ensuite, nous définirions nos fonctions de connexion et d'inscription 👇
controllers/userController.js
const bcrypt = require("bcrypt"); const db = require("../models"); const jwt = require("jsonwebtoken"); const User = db.users; const signup = async (req, res) => { try { const { email, password } = req.body; console.log(email); const data = { email, password: await bcrypt.hash(password, 10), }; //saving the user const user = await User.create(data); if (user) { let token = jwt.sign({ id: user.id }, process.env.secretKey, { expiresIn: 1 * 24 * 60 * 60 * 1000, }); res.cookie("jwt", token, { maxAge: 1 * 24 * 60 * 60, httpOnly: true }); console.log("user", JSON.stringify(user, null, 2)); console.log(token); return res.status(201).send(user); } else { return res.status(409).send("Details are not correct"); } } catch (error) { console.log(error); } }; // Login Authentication const login = async (req, res) => { try { const { email, password } = req.body; const user = await User.findOne({ where: { email: email, }, }); if (user) { const isSame = await bcrypt.compare(password, user.password); if (isSame) { let token = jwt.sign({ id: user.id }, process.env.secretKey, { expiresIn: 1 * 24 * 60 * 60 * 1000, }); res.cookie("jwt", token, { maxAge: 1 * 24 * 60 * 60, httpOnly: true }); //send user data return res.status(201).send(user); } else { return res.status(401).send("Authentication failed"); } } else { return res.status(401).send("Authentication failed"); } } catch (error) { console.log(error); } }; module.exports = { signup, login, };
C'est là que nous allons intégrer Stripe Checkout
dans notre application.
Nous utiliserons l' Stripe API
pour gérer les paiements et gérer les abonnements des utilisateurs.
Le code suivant crée une nouvelle session de paiement Stripe. 💳
Nous lui fournirons le type de mode de paiement, les données du produit et la quantité.
Nous devons également spécifier les URL vers lesquelles l'utilisateur sera redirigé en cas de paiement réussi ou s'il annule la transaction.
Et, le serveur répondra avec l'URL de la session Stripe si tout va bien. ✅
controllers/stripeController.js
const db = require("../models"); const Stripe = require("stripe"); const User = db.users; require("dotenv").config(); const stripe = Stripe(process.env.STRIPE_SECRET_KEY); const updatePlan = async (req, res) => { try { const { email, product } = req.body; const session = await stripe.checkout.sessions.create({ payment_method_types: ["card"], line_items: [ { price_data: { currency: "usd", product_data: { name: product.name, }, unit_amount: product.price * 100, }, quantity: product.quantity, }, ], mode: "payment", success_url: `${process.env.CLIENT_URL}/success`, cancel_url: `${process.env.CLIENT_URL}/`, }); //find a user by their email const user = await User.findOne({ where: { email: email, }, }); if (user) { await user.update({ tier: product.name }); return res.send({ url: session.url }); } else { return res.status(401).send("User not found"); } } catch (error) { console.log(error); } }; module.exports = { updatePlan, };
Enfin, nous aurions besoin d'ajouter toutes nos routes à notre point d'entrée, qui est server.js
server.js
const cors = require("cors"); const express = require("express"); require("dotenv").config(); const cookieParser = require("cookie-parser"); const db = require("./models"); const userRoutes = require("./routes/userRoutes"); const PORT = process.env.PORT || 8080; const stripeRoute = require("./routes/stripeRoute"); const app = express(); // Middlewares app.use(express.json()); app.use(express.urlencoded({ extended: true })); app.use(cookieParser()); app.use(cors()); // Routes app.use("/api/v1/users", userRoutes); app.use("/api/v1/stripe", stripeRoute); app.listen(PORT, () => { console.log("Server started at port 8080"); try { db.sequelize.sync({ force: true }).then(() => { console.log("db has been re sync"); }); } catch (error) {} });
Et nous en avons fini avec le backend ✅
Maintenant, allons-y et essayons de le déployer sur FL0
. 🔼
🚀 Pour déployer notre projet sur FL0, nous commencerons par pousser notre référentiel vers un nouveau référentiel GitHub.
Voici le lien vers notre référentiel pour référence : https://github.com/dalefl0/stripe-fl0-backend
Nous allons maintenant nous diriger vers app.fl0.dev pour commencer le déploiement.
Ici, nous aurions besoin de créer un nouveau projet, nommons-le stripe-fl0
par exemple.
Nous aurions maintenant besoin de créer une nouvelle instance Postgres. Avec Fl0, cela prend moins de 30 secondes ! ⏳
Une fois notre base de données configurée, nous devrons continuer et déployer notre backend dans le même projet.
Une fois le backend déployé, nous aurions besoin d'importer notre chaîne de connexion à la base de données comme indiqué ci-dessus ☝️
🙌 Maintenant, nous avons notre backend opérationnel.
C'est l'heure de l'UI ✨
Pour configurer le frontend, nous commencerions avec le template-react-vite . ⚡️
Cela inclut tout ce dont nous avons besoin pour que notre projet React-Vite
soit opérationnel.
Nous allons maintenant installer quelques packages.
npm install @heroicons/react axios react-router-dom npm install postcss tailwindcss autoprefixer --save-dev
Pour créer rapidement nos composants d'interface utilisateur, nous prendrions l'aide du composant de section de tarification et du composant de connexion et d'enregistrement de tailwind UI .
Par souci de brièveté, nous n'examinerons que les fonctions importantes de l'interface.
Le projet complet peut être trouvé sur : https://github.com/dalefl0/stripe-fl0-frontend
Maintenant, nous aurions besoin d'ajouter une fonction pour gérer les paiements par bande
src/components/PricingPlans.jsx
... const handleCheckout = (product) => { axios .post( `https://stripe-fl0-backend-dev.fl0.io/api/v1/stripe/create-checkout-session`, { email, product, } ) .then((res) => { if (res.data.url) { setTier(product.name); localStorage.setItem("tier", product.name); window.location.href = res.data.url; } }) .catch((err) => navigate("/cancel")); }; ...
Cette fonction appelle la route /create-checkout-session
de notre backend, reçoit un lien et redirige l'utilisateur vers la page de paiement. 📄
En dehors de cela, nous devons également connecter nos pages signup
et login
aux itinéraires respectifs et stocker les données utilisateur dans localstorage
.
Pour le frontend, nous aurions besoin de créer à nouveau un nouveau référentiel et de le déployer dans le même projet de la même manière.
Nous aurions alors besoin d'ajouter la variable d'environnement VITE_APP_API_BASE_URL
au déploiement du frontend qui devrait être définie sur l'URL de notre backend.
Nous aurions également besoin de définir la variable d'environnement CLIENT_URL
dans le backend sur l'URL hébergée du frontend.
Une fois terminé, notre projet FL0 ressemblerait à ceci 👇
Maintenant, allons-y et essayons notre application en utilisant ce lien de démonstration en direct : https://stripe-fl0-frontend-q8oo-dev.fl0.io/
Merci d'être resté jusqu'au bout !
Dans ce tutoriel, nous avons appris à créer des pages de paiement en intégrant facilement Stripe Checkout
dans nos applications full-stack. 🎉
Nous avons également effectué des déploiements ultra-rapides de notre projet en utilisant FL0.
Pour commencer à créer vos propres applications avec des capacités de paiement, rendez-vous sur fl0.com 🚀