In diesem Tutorial erfahren Sie, wie Sie das Stripe-Zahlungsgateway nahtlos in unsere Full-Stack-Anwendungen integrieren und diese mühelos auf FL0 hosten. 🚀
Ob E-Commerce oder SaaS-Anwendung, Payment Gateways sind ein zentraler Bestandteil unserer Projekte. 💳
In diesem Leitfaden untersuchen wir, wie diese Integrationen vereinfacht werden können, und konzentrieren uns dabei insbesondere auf Stripe Checkout für die Online- Zahlungsabwicklung .
Die entwicklerfreundliche API von Stripe sorgt für sichere und effiziente Transaktionen und verkürzt gleichzeitig unsere Entwicklungszeit.
Als Beispiel haben wir den Fall einer Zahlungsseite für SaaS-Anwendungen genommen.
Wir würden NodeJs
für das Backend und Postgres als unsere Datenbank verwenden. Im Frontend verwenden wir ReactJs
mit vite
.
Später würden wir unser Projekt mühelos auf FL0 hosten. ⬆️
Beginnen wir also mit einer Prise Humor:
🧑💻 In diesem Tutorial erstellen wir eine einfache Demoanwendung, bei der sich ein Benutzer anmelden, seinen Plan auswählen und mit seiner Kreditkarte bezahlen kann.
Dazu müssten wir zwei separate Repositorys erstellen, eines für unser backend
und eines für frontend
.
🗂️ So würden unsere beiden Ordnerstrukturen nur als Referenz aussehen:
Jetzt fangen wir an.
Aus Gründen der Effizienz nutzen wir in diesem Tutorial die Vorlage „ fl0zone/blog-express-pg-sequelize “.
Dann würden wir alle Dateien und Ordner entfernen, die für unser Projekt nicht wichtig sind. 🧑💻
Für ein umfassenderes Verständnis des Tutorials können Sie sich diesen Blogbeitrag ansehen.
Unsere Vorlage kapselt eine grundlegende Node.js
Anwendung und eine dockerisierte PostgreSQL
Datenbank.
Hier ist die entsprechende docker-compose.yaml
Datei für unser Setup 🐳:
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:
Jetzt würden wir fortfahren und einige wichtige Pakete installieren 📦
npm install bcrypt cookie-parser cors jsonwebtoken pg-hstore stripe
Jetzt müssten wir unsere Stripe-API-Schlüssel erhalten 🔑. Dazu müssten wir ein neues Konto bei Stripe erstellen.
Hier würden wir Test Mode
für die Demo verwenden.
Hier ist die Liste der Umgebungsvariablen, die wir für dieses Projekt benötigen würden.
.env.example
STRIPE_PUBLISHABLE_KEY= STRIPE_SECRET_KEY= POSTGRES_DB_URI= secretKey= CLIENT_URL=
Beginnen wir jetzt damit, unsere Datenbank einzurichten. 🐘
Da wir das Sequelize ORM verwenden, müssen wir ein Modell für unsere Benutzerdaten erstellen.
Hier ist der Code für unser Modell 👇
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; };
Lassen Sie uns nun fortfahren und unsere Routen erstellen
POST /login
– Hilft beim Anmelden des Benutzers und beim Speichern der Sitzung
POST /signup
– Hilft beim Erstellen eines neuen Kontos
POST /create-checkout-session
– generiert den Link zur Stripe-Checkout-Seite und gibt ihn zurück
Diese 3 Routen sind wie folgt in 2 Dateien unterteilt:
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;
🧑💻 Zum Einrichten des Benutzerprofils definieren wir zunächst eine Middleware, um zu prüfen, ob die E-Mail-Adresse eines neuen Benutzers bei der Anmeldung bereits in der Datenbank vorhanden ist.
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, };
Dann würden wir fortfahren und unsere Anmelde- und Anmeldefunktionen definieren 👇
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, };
Hier werden wir Stripe Checkout
in unsere Anwendung integrieren.
Wir werden die Stripe API
verwenden, um Zahlungen zu verwalten und Benutzerabonnements abzuwickeln.
Der folgende Code erstellt eine neue Stripe-Checkout-Sitzung. 💳
Wir teilen ihm die Art der Zahlungsart, die Produktdaten und die Menge mit.
Wir müssen auch die URLs angeben, zu denen der Benutzer weitergeleitet wird, wenn die Zahlung erfolgreich ist oder die Transaktion abgebrochen wird.
Und wenn alles in Ordnung ist, antwortet der Server mit der URL für die Stripe-Sitzung. ✅
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, };
Zuletzt müssten wir alle unsere Routen zu unserem Einstiegspunkt hinzufügen, der server.js
ist
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) {} });
Und wir sind mit dem Backend fertig ✅
Lassen Sie uns nun fortfahren und versuchen, es auf FL0
bereitzustellen. 🔼
🚀 Um unser Projekt auf FL0 bereitzustellen, beginnen wir damit , unser Repo zunächst in ein neues GitHub-Repository zu übertragen .
Dies ist der Link zu unserem Repository als Referenz: https://github.com/dalefl0/stripe-fl0-backend
Jetzt würden wir zu app.fl0.dev gehen, um mit der Bereitstellung zu beginnen.
Hier müssten wir ein neues Projekt erstellen, nennen wir es beispielsweise stripe-fl0
.
Jetzt müssten wir eine neue Postgres-Instanz erstellen. Bei Fl0 dauert das weniger als 30 Sekunden! ⏳
Nachdem wir unsere Datenbank vollständig eingerichtet haben, müssen wir unser Backend im selben Projekt bereitstellen.
Nachdem das Backend bereitgestellt wurde, müssten wir unsere Datenbankverbindungszeichenfolge wie oben gezeigt importieren ☝️
🙌 Jetzt haben wir unser Backend eingerichtet und laufen.
Zeit für die Benutzeroberfläche ✨
Zum Einrichten des Frontends würden wir mit dem template-react-vite beginnen. ⚡️
Dazu gehört alles, was wir brauchen, um unser React-Vite
-Projekt zum Laufen zu bringen.
Jetzt würden wir fortfahren und ein paar Pakete installieren.
npm install @heroicons/react axios react-router-dom npm install postcss tailwindcss autoprefixer --save-dev
Um unsere UI-Komponenten schnell zu erstellen, würden wir die Preisabschnittskomponente und die Anmelde- und Registrierungskomponente von tailwind UI nutzen.
Der Kürze halber betrachten wir nur die wichtigen Funktionen des Frontends.
Das komplette Projekt finden Sie unter: https://github.com/dalefl0/stripe-fl0-frontend
Jetzt müssten wir eine Funktion hinzufügen, um Stripe-Checkouts zu verarbeiten
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")); }; ...
Diese Funktion ruft /create-checkout-session
Route unseres Backends auf, empfängt einen Link und leitet den Benutzer zur Checkout-Seite weiter. 📄
Darüber hinaus müssen wir auch unsere signup
und login
mit den entsprechenden Routen verbinden und die Benutzerdaten in localstorage
speichern.
Für das Frontend müssten wir erneut ein neues Repository erstellen und es auf ähnliche Weise im selben Projekt bereitstellen.
Anschließend müssten wir der Frontend-Bereitstellung die Umgebungsvariable VITE_APP_API_BASE_URL
hinzufügen, die auf die URL unseres Backends gesetzt werden sollte.
Außerdem müssten wir die Umgebungsvariable CLIENT_URL
im Backend auf die gehostete URL des Frontends setzen.
Sobald wir fertig sind, würde unser FL0-Projekt so aussehen 👇
Jetzt können wir unsere Anwendung über diesen Live-Demo-Link ausprobieren: https://stripe-fl0-frontend-q8oo-dev.fl0.io/
Vielen Dank, dass Sie bis zum Ende durchgehalten haben!
In diesem Tutorial haben wir gelernt, wie man Zahlungsseiten erstellt, indem man Stripe Checkout
einfach in unsere Full-Stack-Anwendungen integriert. 🎉
Wir haben unser Projekt auch mit FL0 rasend schnell bereitgestellt.
Um mit der Entwicklung Ihrer eigenen Anwendungen mit Zahlungsfunktionen zu beginnen, besuchen Sie fl0.com 🚀