Hogyan készítsünk egy egyszerű fizetési átjáró integrációt Node.js és Stripe segítségével?

Üdvözöljük a digitális gazdaságban, ahol az online fizetés már nem luxus, hanem alapvető elvárás. Akár egy webshopot üzemeltet, akár egy SaaS szolgáltatást fejleszt, vagy csupán egy egyedi terméket szeretne értékesíteni, a megbízható és biztonságos fizetési átjáró integráció elengedhetetlen a sikerhez. Ebben a cikkben bemutatjuk, hogyan hozhat létre egy egyszerű, de robusztus fizetési megoldást a népszerű Node.js futtatókörnyezet és a fejlesztőbarát Stripe platform segítségével.

Nem kell zseniális pénzügyi szakembernek lennie ahhoz, hogy ezt megtegye. A Stripe API-ja hihetetlenül átgondolt és könnyen kezelhető, míg a Node.js aszinkron természete és nagy teljesítménye ideális választássá teszi a szerveroldali fizetési logikához. Készen áll? Vágjunk is bele!

Miért éppen Stripe és Node.js?

Mielőtt a technikai részletekbe merülnénk, tisztázzuk, miért éppen ezt a két technológiát választottuk az integráció alapjául:

  • Stripe: A Stripe az egyik vezető fizetési szolgáltató, amely rendkívül széleskörű funkciókat kínál, a bankkártyás fizetésektől kezdve az előfizetéses modelleken át a piacterek támogatásáig. Legnagyobb előnye a kiválóan dokumentált, fejlesztőbarát API, amely minimalizálja a PCI DSS megfelelőséggel kapcsolatos terheket. A Stripe Elements és a Stripe.js könyvtárak egyszerűvé teszik a kártyaadatok biztonságos gyűjtését a kliens oldalon, anélkül, hogy a szerverünknek valaha is látnia kellene az érzékeny adatokat.
  • Node.js: Egy nyílt forráskódú, szerveroldali JavaScript futtatókörnyezet, amely lehetővé teszi, hogy egyetlen nyelven (JavaScript) írja meg az egész webalkalmazását, a front-endetől a back-endig. Az aszinkron, eseményvezérelt architektúrájának köszönhetően a Node.js kiválóan alkalmas I/O-intenzív feladatokra, mint amilyenek a fizetési tranzakciók is. Az Express.js keretrendszerrel párosítva gyorsan és hatékonyan építhetünk API végpontokat.

Ez a kombináció egy rendkívül hatékony és skálázható megoldást kínál, amellyel magabiztosan kezelheti az online fizetés kihívásait.

Előfeltételek

Mielőtt belevágnánk, győződjön meg róla, hogy az alábbiak rendelkezésre állnak:

  • Node.js és npm: Telepítve a gépén. Ellenőrizheti a verziókat a node -v és npm -v parancsokkal.
  • Stripe Fiók: Regisztráljon egy ingyenes fejlesztői fiókot a stripe.com oldalon.
  • Alapvető Webfejlesztési Ismeretek: HTML, CSS, JavaScript és egy kevés Express.js tapasztalat segít megérteni a kódokat.
  • Internetkapcsolat: Nyilvánvaló, de fontos!

1. Stripe Fiók Beállítása és API Kulcsok Beszerzése

Az első lépés, hogy Stripe fiókjában hozzáférjen az API kulcsokhoz. Ezekre lesz szüksége az alkalmazás és a Stripe közötti kommunikációhoz.

  1. Jelentkezzen be a Stripe irányítópultjára.
  2. A bal oldali menüben keresse meg a „Developers” (Fejlesztők) menüpontot, majd azon belül az „API keys” (API kulcsok) opciót.
  3. Itt két fő kulcsot fog látni:
    • Publishable key (Nyilvános kulcs): Ezt használja majd a front-enden, a böngészőben futó JavaScript kódban. Kezdődik pk_test_... előtaggal teszt módban, és pk_live_... előtaggal éles módban. Ez a kulcs biztonságosan kiadható a kliensnek.
    • Secret key (Titkos kulcs): Ezt kizárólag a szerveroldalon használja (Node.js alkalmazásunkban). Kezdődik sk_test_... előtaggal teszt módban, és sk_live_... előtaggal éles módban. Soha ne tegye közzé ezt a kulcsot a kliens oldalon, és soha ne ossza meg nyilvánosan!
  4. Másolja ki mindkét kulcsot, teszt módra vonatkozóan. Később, amikor élesbe állítja az alkalmazását, átválthat az „Éles adatok megtekintése” opcióra, hogy az éles kulcsokat lássa.

2. Projekt Inicializálása és Függőségek Telepítése

Hozzon létre egy új mappát a projektjének, majd inicializálja azt egy Node.js projektté és telepítse a szükséges csomagokat.


mkdir payment-gateway-app
cd payment-gateway-app
npm init -y
npm install express stripe dotenv
  • express: A webes szerverünk létrehozásához.
  • stripe: A Stripe hivatalos Node.js könyvtára az API hívásokhoz.
  • dotenv: Környezeti változók kezelésére, különösen a titkos API kulcs tárolására. Ez biztosítja, hogy a kulcs ne legyen közvetlenül a kódban, ami biztonsági kockázatot jelentene.

Hozzon létre egy .env fájlt a projekt gyökérkönyvtárában, és adja hozzá a Stripe titkos és nyilvános kulcsait:


STRIPE_SECRET_KEY=sk_test_YOUR_SECRET_KEY
STRIPE_PUBLISHABLE_KEY=pk_test_YOUR_PUBLISHABLE_KEY
PORT=3000

Ne felejtse el a .env fájlt hozzáadni a .gitignore fájlhoz, hogy ne kerüljön fel a verziókövető rendszerbe (pl. GitHubra)!

3. Backend (Node.js/Express) Szerver Beállítása

Most hozzuk létre a szerverünk alapjait. Hozzon létre egy server.js fájlt a projekt gyökérkönyvtárában:


// server.js
require('dotenv').config(); // Betölti a .env fájlban lévő környezeti változókat
const express = require('express');
const stripe = require('stripe')(process.env.STRIPE_SECRET_KEY);
const path = require('path');

const app = express();
const PORT = process.env.PORT || 3000;

// Middleware a JSON kérések testének (body) feldolgozásához
app.use(express.json());
// Middleware a URL-kódolt adatok feldolgozásához
app.use(express.urlencoded({ extended: true }));

// Statikus fájlok kiszolgálása a 'public' mappából
app.use(express.static(path.join(__dirname, 'public')));

// Alapértelmezett útvonal az index.html fájlhoz
app.get('/', (req, res) => {
    res.sendFile(path.join(__dirname, 'public', 'index.html'));
});

// Fizetési kérelem kezelése
app.post('/create-payment-intent', async (req, res) => {
    const { amount, currency, paymentMethodId } = req.body;

    try {
        // Létrehozunk egy PaymentIntent objektumot
        const paymentIntent = await stripe.paymentIntents.create({
            amount: amount, // összeget centben/fillérben kell megadni
            currency: currency,
            payment_method: paymentMethodId,
            confirmation_method: 'manual', // Kézzel erősítjük meg a PaymentIntent-et
            confirm: true, // Azonnal megpróbáljuk megerősíteni a PaymentIntent-et
            return_url: 'http://localhost:3000/success', // Visszatérési URL 3D Secure esetén
        });

        // Visszaadjuk a kliensnek a válasz állapotát
        res.json({ clientSecret: paymentIntent.client_secret, status: paymentIntent.status });

    } catch (error) {
        console.error('Hiba történt a PaymentIntent létrehozása során:', error.message);
        res.status(500).json({ error: error.message });
    }
});

// Szerver indítása
app.listen(PORT, () => {
    console.log(`Szerver fut a http://localhost:${PORT} címen`);
});

Néhány fontos pont a fenti kódból:

  • require('dotenv').config();: Betölti a .env fájl tartalmát a process.env objektumba.
  • stripe(process.env.STRIPE_SECRET_KEY);: Inicializálja a Stripe könyvtárat a titkos kulccsal.
  • app.use(express.json()); és app.use(express.urlencoded({ extended: true }));: Ezek az Express middleware-ek szükségesek ahhoz, hogy a bejövő HTTP kérések testét (body) megfelelően tudjuk kezelni, amikor a kliens adatokat küld a szervernek.
  • app.use(express.static(path.join(__dirname, 'public')));: Ez biztosítja, hogy a public mappában lévő statikus fájlokat (HTML, CSS, kliensoldali JavaScript) a szerver kiszolgálja.
  • /create-payment-intent POST végpont: Ez az a pont, ahová a kliens oldali alkalmazás elküldi a fizetési adatokat (a Stripe által generált paymentMethodId-t és az összeget). Itt hozunk létre egy PaymentIntent-et a Stripe API segítségével. A PaymentIntent a Stripe modern megközelítése a fizetések kezelésére, amely sokkal rugalmasabb és jobban kezeli a különböző fizetési módokat és az erős ügyfélhitelesítést (SCA).
  • Az amount paramétert a legkisebb valutaegységben kell megadni (pl. forint esetén fillérben, dollár esetén centben). Ezért ha 1000 Ft-ot szeretnénk, az 100000 lesz.

4. Frontend (HTML/JavaScript) – Bankkártya Adatok Gyűjtése

Most hozzuk létre a felhasználói felületet, ahol a felhasználók megadhatják a kártyaadataikat. A Stripe Elements és a Stripe.js segítségével a bankkártya adatok gyűjtése biztonságos és PCI-kompatibilis.

Hozzon létre egy public mappát a projekt gyökérkönyvtárában, és azon belül egy index.html fájlt:


<!-- public/index.html -->
<!DOCTYPE html>
<html lang="hu">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Egyszerű Stripe Fizetési Átjáró</title>
    <!-- Stripe.js CDN -->
    <script src="https://js.stripe.com/v3/"></script>
    <style>
        body { font-family: Arial, sans-serif; display: flex; justify-content: center; align-items: center; min-height: 100vh; background-color: #f4f7f6; margin: 0; }
        .container { background-color: #ffffff; padding: 40px; border-radius: 8px; box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1); width: 100%; max-width: 450px; }
        h1 { text-align: center; color: #333; margin-bottom: 30px; }
        label { display: block; margin-bottom: 8px; color: #555; font-weight: bold; }
        input[type="number"], input[type="text"] { width: calc(100% - 20px); padding: 12px 10px; margin-bottom: 20px; border: 1px solid #ddd; border-radius: 4px; box-sizing: border-box; font-size: 16px; }
        #card-element { border: 1px solid #ddd; padding: 12px; border-radius: 4px; margin-bottom: 20px; background-color: #f9f9f9; }
        button { background-color: #6772e5; color: white; padding: 14px 20px; border: none; border-radius: 4px; cursor: pointer; width: 100%; font-size: 18px; transition: background-color 0.3s ease; }
        button:hover { background-color: #5469d4; }
        #payment-status { margin-top: 20px; text-align: center; font-weight: bold; }
        .success { color: green; }
        .error { color: red; }
    </style>
</head>
<body>
    <div class="container">
        <h1>Fizetés</h1>
        <form id="payment-form">
            <label for="amount">Összeg (HUF):</label>
            <input type="number" id="amount" value="1000" min="1" required>

            <label for="description">Leírás:</label>
            <input type="text" id="description" value="Teszt termék" required>

            <label for="card-element">Bankkártya adatok:</label>
            <div id="card-element">
                <!-- A Stripe Elements ide fogja beilleszteni a kártya adatgyűjtő mezőket -->
            </div>

            <button type="submit" id="submit-button">Fizetés</button>
            <div id="payment-status"></div>
        </form>
    </div>

    <script>
        // Inicializáljuk a Stripe-ot a nyilvános kulccsal
        const stripe = Stripe('pk_test_YOUR_PUBLISHABLE_KEY'); // HASZNÁLJA A SAJÁT NYILVÁNOS KULCSÁT!
        const elements = stripe.elements();

        // Létrehozunk egy 'card' elemet
        const card = elements.create('card');
        // Felszereljük az elemet a HTML DOM-ra
        card.mount('#card-element');

        const form = document.getElementById('payment-form');
        const submitButton = document.getElementById('submit-button');
        const paymentStatus = document.getElementById('payment-status');

        form.addEventListener('submit', async (event) => {
            event.preventDefault(); // Megakadályozza az alapértelmezett űrlapküldést
            submitButton.disabled = true; // Letiltja a gombot, hogy elkerülje a dupla küldést
            paymentStatus.textContent = 'Feldolgozás...';
            paymentStatus.className = '';

            try {
                // Létrehozzuk a PaymentMethod-et a Stripe.js segítségével
                const { paymentMethod, error } = await stripe.createPaymentMethod({
                    type: 'card',
                    card: card,
                });

                if (error) {
                    // Hiba történt a PaymentMethod létrehozása során
                    paymentStatus.textContent = error.message;
                    paymentStatus.className = 'error';
                    submitButton.disabled = false;
                    return;
                }

                // Elküldjük a paymentMethod.id-t a backendre
                const amountInput = document.getElementById('amount');
                const amountInHUF = parseInt(amountInput.value) * 100; // Átváltás fillérre/cent-re
                const currency = 'huf'; // VAGY 'eur', 'usd' stb.

                const response = await fetch('/create-payment-intent', {
                    method: 'POST',
                    headers: { 'Content-Type': 'application/json' },
                    body: JSON.stringify({
                        amount: amountInHUF,
                        currency: currency,
                        paymentMethodId: paymentMethod.id,
                    }),
                });

                const data = await response.json();

                if (data.error) {
                    paymentStatus.textContent = `Hiba: ${data.error}`;
                    paymentStatus.className = 'error';
                } else if (data.clientSecret) {
                    // Ha szükséges 3D Secure hitelesítés, akkor megerősítjük a fizetést a kliens oldalon
                    const { paymentIntent, error: confirmError } = await stripe.confirmCardPayment(data.clientSecret);

                    if (confirmError) {
                        paymentStatus.textContent = `Fizetés megerősítési hiba: ${confirmError.message}`;
                        paymentStatus.className = 'error';
                    } else if (paymentIntent.status === 'succeeded') {
                        paymentStatus.textContent = 'Sikeres fizetés!';
                        paymentStatus.className = 'success';
                        // Itt lehetne átirányítani egy köszönő oldalra vagy frissíteni az UI-t
                    } else if (paymentIntent.status === 'requires_action') {
                        // További lépések szükségesek (pl. banki hitelesítés) - ezt a confirmCardPayment már kezeli
                        paymentStatus.textContent = 'Fizetés megerősítésre vár.';
                        paymentStatus.className = 'error'; // Ideiglenesen hiba jellegű, amíg nincs sikeres státusz
                    } else {
                        paymentStatus.textContent = `Fizetés státusz: ${paymentIntent.status}`;
                        paymentStatus.className = 'error';
                    }
                } else {
                    paymentStatus.textContent = `Ismeretlen válasz a szervertől.`;
                    paymentStatus.className = 'error';
                }

            } catch (networkError) {
                console.error('Hálózati hiba:', networkError);
                paymentStatus.textContent = `Hálózati hiba: ${networkError.message}`;
                paymentStatus.className = 'error';
            } finally {
                submitButton.disabled = false; // Visszaállítja a gombot
            }
        });
    </script>
</body>
</html>

Fontos: A Stripe('pk_test_YOUR_PUBLISHABLE_KEY') sorban cserélje ki a placeholder értéket a saját Stripe nyilvános kulcsára! Ezt a .env fájlból is beolvashatná, de kliensoldalon nem ajánlott közvetlenül a process.env-hez hozzáférni, helyette a szerverről adhatná át egy globális változóban vagy egy inicializáló végponton keresztül.

A fenti kódban:

  • Behúztuk a Stripe.js könyvtárat a CDN-ről.
  • Inicializáltuk a Stripe-ot a nyilvános kulcsunkkal.
  • Létrehoztunk egy card elemet a stripe.elements() segítségével, amely biztonságosan gyűjti be a kártyaadatait. Ez az elem automatikusan formázza és validálja a bevitelt, és nem küldi el az érzékeny adatokat a mi szerverünknek, hanem közvetlenül a Stripe-nak.
  • Az űrlap elküldésekor a stripe.createPaymentMethod() funkcióval létrehozunk egy PaymentMethod azonosítót a Stripe-nál. Ez az azonosító biztonságosan továbbítható a szerverünknek, és tartalmazza a kártya tokenjét anélkül, hogy valaha is látnánk a teljes kártyaszámot.
  • Ezt a paymentMethod.id-t és az összeget elküldjük a Node.js backend /create-payment-intent végpontjára.
  • A válaszban kapott clientSecret kulcsot (ha van) felhasználjuk a stripe.confirmCardPayment() funkcióval a fizetés véglegesítéséhez, ami kezeli a 3D Secure hitelesítéseket is.

5. Tesztelés

Indítsa el a Node.js szerverét:


node server.js

Ezután nyissa meg a böngészőjében a http://localhost:3000 címet. Meg kell jelennie a fizetési űrlapnak.

A teszteléshez használhatja a Stripe által biztosított tesztkártya számokat. Néhány példa:

  • Sikeres fizetés: 4242 4242 4242 4242 (bármilyen jövőbeli lejárati dátummal és CVV kóddal)
  • 3D Secure hitelesítést igénylő kártya: Ugyanez a kártyaszám, de a fizetéskor felugrik egy teszt hitelesítési ablak.

A Stripe irányítópultján a „Developers” (Fejlesztők) menüpont alatt, az „Events” (Események) és „Logs” (Naplók) részeken nyomon követheti a tranzakciókat és a hibákat. Ez segít a hibakeresésben is.

6. Hibakezelés és Biztonsági Megfontolások

A fenti kód egy egyszerű példa, de egy éles rendszerben számos további dolgot kell figyelembe venni:

  • Robusztus hibakezelés: A hálózati hibák, Stripe API hibák és egyéb váratlan helyzetek kezelése elengedhetetlen. Használjon try...catch blokkokat, és adjon értelmes visszajelzéseket a felhasználónak.
  • Adatvalidálás: Mindig validálja a bejövő adatokat (összeg, valuta stb.) a szerveroldalon is, mielőtt elküldi azokat a Stripe-nak. Ne bízzon meg csak a kliensoldali validációban.
  • Webhooks: Komplexebb alkalmazásoknál, ahol aszinkron események (pl. sikertelen fizetés, visszatérítés, csalásgyanú) kezelése szükséges, a Stripe webhooks használata elengedhetetlen. Ezek lehetővé teszik, hogy a Stripe értesítse az alkalmazását a tranzakciók állapotváltozásairól.
  • HTTPS: Éles környezetben mindenképpen használjon HTTPS-t a szerver és a kliens közötti kommunikációhoz. Ez titkosítja az adatforgalmat, beleértve a PaymentMethod ID-t is. A Stripe Elements csak HTTPS alatt működik biztonságosan.
  • Környezeti változók: Soha ne hard-code-olja (beírja közvetlenül a kódba) az érzékeny adatokat, mint például az API kulcsokat. Használjon környezeti változókat (pl. dotenv) és tárolja ezeket biztonságosan.
  • Naplózás: Alkalmazzon megfelelő naplózást a szerveroldalon, hogy nyomon követhesse a fizetési tranzakciókat és könnyen felderíthesse a problémákat.

Összefoglalás és Következő Lépések

Gratulálunk! Elkészítette és sikeresen integrált egy egyszerű fizetési átjárót a Node.js és Stripe segítségével. Megtanulta, hogyan kell beállítani a Stripe fiókot, hogyan kell kezelni az API kulcsokat, hogyan kell szerveroldali logikát építeni Express.js-szel, és hogyan kell biztonságosan gyűjteni a kártyaadatokat a Stripe.js és Stripe Elements segítségével.

Ez az alap egy nagyon jó kiindulópont a további fejlesztésekhez. Íme néhány ötlet a következő lépésekhez:

  • Dinamikus termékkatalógus: Integrálja a fizetési átjárót egy valódi termékkatalógussal, ahol a felhasználók kiválaszthatják a termékeket és azok ára dinamikusan jelenik meg.
  • Felhasználói azonosítás: Integráljon felhasználói bejelentkezést, és mentse el a felhasználók PaymentMethod-jeit a Stripe-nál a könnyebb jövőbeli vásárlások érdekében.
  • Előfizetések: Fedezze fel a Stripe Billing funkcióit, ha előfizetéses szolgáltatást szeretne nyújtani.
  • Visszatérítések és tranzakciókezelés: Implementáljon admin felületet a tranzakciók megtekintéséhez, visszatérítések indításához és a vitatott tranzakciók kezeléséhez.
  • Jobb felhasználói felület: Fejlessze tovább a front-endet egy professzionálisabb és felhasználóbarátabb dizájnnal.

A Node.js és Stripe kombinációja rendkívül erőteljes eszköz a kezében az online fizetés elfogadására. Ne habozzon tovább, kezdje el a fejlesztést, és hozza létre saját egyedi fizetési megoldásait!

Leave a Reply

Az e-mail címet nem tesszük közzé. A kötelező mezőket * karakterrel jelöltük