En este tutorial, exploraremos cómo integrar sin problemas la pasarela de pago Stripe en nuestras aplicaciones completas y alojarlas sin esfuerzo en FL0. 🚀
Ya sea una aplicación de comercio electrónico o SaaS, las pasarelas de pago son un componente central de nuestros proyectos. 💳
En esta guía, exploraremos cómo simplificar estas integraciones, centrándonos específicamente en Stripe Checkout para el procesamiento de pagos en línea.
La API amigable para desarrolladores de Stripe garantiza transacciones seguras y eficientes al tiempo que reduce nuestro tiempo de desarrollo.
Solo por ejemplo, hemos tomado el caso de una página de pago de aplicaciones SaaS.
Estaríamos usando NodeJs
para el backend y Postgres como nuestra base de datos. En la interfaz estamos usando ReactJs
con vite
.
Más tarde seguiríamos adelante y alojaríamos sin esfuerzo nuestro proyecto en FL0. ⬆️
Entonces, comencemos con una pizca de humor:
🧑💻 En este tutorial, crearemos una aplicación de demostración simple donde un usuario puede registrarse, seleccionar su plan y pagar con su tarjeta de crédito.
Para esto necesitaríamos crear 2 repositorios separados, uno para nuestro backend
y otro para frontend
.
🗂️ Así es como se verían nuestras dos estructuras de carpetas, solo como referencia:
Ahora, comencemos.
En aras de la eficiencia, en este tutorial aprovecharemos la plantilla " fl0zone/blog-express-pg-sequelize ".
Luego eliminaríamos cualquier archivo o carpeta que no sea importante para nuestro proyecto. 🧑💻
Para una comprensión más completa del tutorial, puede consultar esta publicación de blog.
Nuestra plantilla encapsula una aplicación Node.js
básica y una base de datos PostgreSQL
dockerizada.
Aquí está el archivo docker-compose.yaml
correspondiente a nuestra configuración 🐳:
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:
Ahora seguiríamos adelante e instalaríamos algunos paquetes esenciales 📦
npm install bcrypt cookie-parser cors jsonwebtoken pg-hstore stripe
Ahora, necesitaríamos obtener nuestras claves API de Stripe 🔑. Para ello necesitaríamos crear una nueva cuenta en Stripe.
Aquí estaríamos usando Test Mode
para la demostración.
Aquí está la lista de variables de entorno que necesitaríamos para este proyecto.
.env.example
STRIPE_PUBLISHABLE_KEY= STRIPE_SECRET_KEY= POSTGRES_DB_URI= secretKey= CLIENT_URL=
Comencemos configurando nuestra base de datos ahora. 🐘
Dado que estamos utilizando Sequelize ORM, necesitaremos crear un modelo para nuestros datos de usuario.
Aquí está el código para nuestro modelo 👇
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; };
Ahora, sigamos adelante y creemos nuestras rutas.
POST /login
- Ayuda a iniciar sesión de usuario y almacenar la sesión
POST /signup
- Ayuda a crear una nueva cuenta
POST /create-checkout-session
: genera y devuelve el enlace de la página de pago de la franja
Estas 3 rutas se separan en 2 archivos de la siguiente manera:
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;
🧑💻 Para configurar el perfil de usuario, primero definiremos un middleware para verificar si la dirección de correo electrónico de un nuevo usuario ya existe en la base de datos durante el registro.
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, };
Luego seguiríamos adelante y definiríamos nuestras funciones de inicio de sesión y registro 👇
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, };
Aquí es donde integraremos Stripe Checkout
en nuestra aplicación.
Usaremos la Stripe API
para administrar los pagos y manejar las suscripciones de los usuarios.
El siguiente código crea una nueva sesión de pago de Stripe. 💳
Le proporcionaremos el tipo de método de pago, los datos del producto y la cantidad.
También debemos especificar las URL a las que se redirigirá al usuario tras un pago exitoso o si cancela la transacción.
Y el servidor responderá con la URL de la sesión de Stripe si todo está 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, };
Por último, necesitaríamos agregar todas nuestras rutas a nuestro punto de entrada, que es 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) {} });
Y hemos terminado con el backend ✅
Ahora sigamos adelante e intentemos implementarlo en FL0
. 🔼
🚀 Para implementar nuestro proyecto en FL0, primero enviaremos nuestro repositorio a un nuevo repositorio de GitHub.
Este es el enlace a nuestro repositorio para referencia: https://github.com/dalefl0/stripe-fl0-backend
Ahora nos dirigiríamos a app.fl0.dev para comenzar a implementar.
Aquí necesitaríamos crear un nuevo proyecto, llamémoslo stripe-fl0
por ejemplo.
Ahora necesitaríamos crear una nueva instancia de Postgres. ¡Con Fl0, esto lleva menos de 30 segundos! ⏳
Una vez que tengamos nuestra base de datos configurada, tendríamos que seguir adelante e implementar nuestro backend en el mismo proyecto.
Después de implementar el backend, necesitaríamos importar nuestra cadena de conexión de base de datos como se muestra arriba ☝️
🙌 Ahora tenemos nuestro backend en funcionamiento.
Tiempo para la interfaz de usuario ✨
Para configurar la interfaz, comenzaríamos con template-react-vite . ⚡️
Esto incluye todo lo que necesitamos para poner en marcha nuestro proyecto React-Vite
.
Ahora seguiríamos adelante e instalaríamos algunos paquetes.
npm install @heroicons/react axios react-router-dom npm install postcss tailwindcss autoprefixer --save-dev
Para construir nuestros componentes de la interfaz de usuario rápidamente, usaríamos la ayuda del componente de la sección de precios y el componente de inicio de sesión y registro de la interfaz de usuario de Tailwind .
En aras de la brevedad, solo veremos las funciones importantes de la interfaz.
El proyecto completo se puede encontrar en: https://github.com/dalefl0/stripe-fl0-frontend
Ahora, necesitaríamos agregar una función para manejar los pagos de franjas
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")); }; ...
Esta función llama a la ruta /create-checkout-session
de nuestro backend, recibe un enlace y redirige al usuario a la página de pago. 📄
Además de esto, también debemos conectar nuestras páginas signup
e login
a las rutas respectivas y almacenar los datos del usuario en localstorage
.
Para la interfaz, necesitaríamos volver a crear un nuevo repositorio e implementarlo en el mismo proyecto de manera similar.
Luego, necesitaríamos agregar la variable de entorno VITE_APP_API_BASE_URL
a la implementación de frontend, que debe establecerse en la URL de nuestro backend.
También necesitaríamos establecer la variable de entorno CLIENT_URL
en el backend a la URL alojada de la interfaz.
Una vez hecho, nuestro proyecto FL0 quedaría así 👇
Ahora, sigamos adelante y probemos nuestra aplicación usando este enlace de demostración en vivo: https://stripe-fl0-frontend-q8oo-dev.fl0.io/
¡Gracias por aguantar hasta el final!
En este tutorial, aprendimos a crear páginas de pago integrando Stripe Checkout
fácilmente en nuestras aplicaciones completas. 🎉
También realizamos implementaciones ultrarrápidas de nuestro proyecto utilizando FL0.
Para comenzar a crear sus propias aplicaciones con capacidades de pago, diríjase a fl0.com 🚀