Prečo Stripe — aj pre slovenský e-shop
Na Slovensku sú rozšírené GoPay a Comgate — domáce brány s lokálnou podporou a slovenčinou. Stripe je americká platforma, ale od roku 2022 plne dostupná v SR a ČR vrátane vyúčtovania v EUR a súladu s PSD2. Výber závisí od kontextu projektu.
| Brána | Trh | Laravel integrácia | Transakčný poplatok (SK) |
|---|---|---|---|
| GoPay | SK/CZ/PL | Vlastný PHP SDK, žiadny Cashier | 1,9 % + 0,25 € |
| Comgate | SK/CZ | Vlastný PHP SDK | od 1,49 % |
| Stripe | Globálne + SK/CZ | Laravel Cashier (1. strana) | 1,5 % + 0,25 € (EÚ karty) |
Pre projekty s medzinárodným dosahom, subscription modelom alebo potrebou rýchlej integrácie je Stripe jasná voľba — Laravel Cashier pokrýva 90 % prípadov bez vlastného kódu. Pre čisto slovenský trh s požiadavkou na lokálne platobné metódy (QR platba, bankový prevod) zvážte GoPay alebo Comgate.
Inštalácia Laravel Cashier
Laravel Cashier je oficiálna integrácia Stripe pre Laravel. Obsahuje Eloquent modely, migrácie a helper metódy pre celý platobný životný cyklus. Základy architektúry Laravelu rozoberám v článku Prečo Laravel 12 v roku 2026 stále vyhráva.
composer require laravel/cashier
# Publikovanie migrácií
php artisan vendor:publish --tag="cashier-migrations"
# Spustenie migrácií (pridá stĺpce do users tabuľky + stripe_customers)
php artisan migrate
Cashier rozširuje tabuľku users o stĺpce stripe_id, pm_type, pm_last_four, trial_ends_at. Do modelu User pridáte trait:
// app/Models/User.php
use Laravel\Cashier\Billable;
class User extends Authenticatable
{
use HasFactory, Notifiable, Billable;
// ...
}
Kľúče Stripe nastavte v .env:
STRIPE_KEY=pk_test_51... # Verejný kľúč (frontend)
STRIPE_SECRET=sk_test_... # Tajný kľúč (backend — NIKDY nepublikovať)
STRIPE_WEBHOOK_SECRET=whsec_... # Nastavíte po vytvorení webhooku v Stripe Dashboard
Jednorazová platba cez Checkout Session
Stripe Checkout je hostedovaná platobná stránka od Stripe — nemusíte sa starať o PCI compliance, 3D Secure ani lokalizáciu. Vaša aplikácia zákazníka presmeruje na Stripe, po platbe ho Stripe vráti späť.
// routes/web.php
Route::post('/checkout', [CheckoutController::class, 'create'])->middleware('auth');
Route::get('/checkout/success', [CheckoutController::class, 'success'])->name('checkout.success');
Route::get('/checkout/cancel', fn() => redirect('/')->with('info', 'Platba bola zrušená.'))->name('checkout.cancel');
// app/Http/Controllers/CheckoutController.php
use Laravel\Cashier\Checkout;
class CheckoutController extends Controller
{
public function create(Request $request): RedirectResponse
{
$checkout = $request->user()->checkout([
'price_data' => [
'currency' => 'eur',
'unit_amount' => 4900, // Suma v centoch: 49,00 EUR
'product_data' => [
'name' => 'Konzultácia — 1 hodina',
'description' => 'Online konzultácia k PHP / Laravel projektu',
],
],
'quantity' => 1,
], [
'success_url' => route('checkout.success') . '?session_id={CHECKOUT_SESSION_ID}',
'cancel_url' => route('checkout.cancel'),
'metadata' => ['user_id' => $request->user()->id],
]);
return redirect($checkout->url);
}
public function success(Request $request): View
{
// Overenie session — detaily platby, nie aktivácia (tú riešte vo webhooku!)
$session = \Laravel\Cashier\Cashier::stripe()
->checkout->sessions->retrieve($request->session_id);
return view('checkout.success', compact('session'));
}
}
success(). Zákazník môže success URL navštíviť viackrát, a URL môže otvoriť skôr, ako Stripe pošle webhookový event. Aktiváciu vždy riešte vo webhooku — len tam máte zaručenú jednu spoľahlivú notifikáciu.
Webhooky: spoľahlivé spracovanie výsledkov platby
Webhook je HTTP POST požiadavka, ktorú Stripe pošle na vašu URL vždy, keď nastane udalosť (platba úspešná, predplatné zrušené, platba zlyhala). Je to jediný spoľahlivý spôsob, ako reagovať na výsledok platby.
Registrácia webhook endpointu
// routes/web.php
use App\Http\Controllers\StripeWebhookController;
Route::post('/stripe/webhook', [StripeWebhookController::class, 'handleWebhook'])
->withoutMiddleware(\App\Http\Middleware\VerifyCsrfToken::class)
->name('cashier.webhook');
Kontrolér s overením podpisu
Cashier poskytuje základný WebhookController, ktorý automaticky overuje Stripe-Signature hlavičku — tak sa ubezpečíte, že request naozaj pochádza od Stripe, nie od útočníka.
// app/Http/Controllers/StripeWebhookController.php
use Laravel\Cashier\Http\Controllers\WebhookController as CashierWebhookController;
use Symfony\Component\HttpFoundation\Response;
class StripeWebhookController extends CashierWebhookController
{
// Metóda sa volá automaticky pre event checkout.session.completed
public function handleCheckoutSessionCompleted(array $payload): Response
{
$session = $payload['data']['object'];
$userId = $session['metadata']['user_id'] ?? null;
if (!$userId) {
return $this->successMethod(); // Ignorujeme — nie naša session
}
$user = \App\Models\User::find($userId);
// Aktivácia: uloženie objednávky, sprístupnenie obsahu...
$user?->orders()->create([
'stripe_session_id' => $session['id'],
'amount_eur' => $session['amount_total'] / 100,
'status' => 'paid',
]);
return $this->successMethod(); // Vrátime HTTP 200 — Stripe prestane retyovať
}
// Spracovanie neúspešnej platby
public function handlePaymentIntentPaymentFailed(array $payload): Response
{
$intent = $payload['data']['object'];
// Notifikácia zákazníka, logovanie...
\Log::warning('Stripe platba zlyhala', ['intent_id' => $intent['id']]);
return $this->successMethod();
}
}
WebhookController automaticky overuje Stripe-Signature — ak overenie zlyhá, vráti HTTP 400 a metóda sa vôbec nezavolá. Nastavte STRIPE_WEBHOOK_SECRET podľa hodnoty zo Stripe Dashboardu → Webhooks → Signing secret.
Subscription model: mesačné predplatné
Cashier má na subscriptions špeciálne API — newSubscription(), subscribed(), subscription()->cancel(). Pred použitím vytvorte produkt a cenu v Stripe Dashboard a skopírujte price_xxx ID.
// Vytvorenie predplatného (po potvrdení platby / Checkout Session)
$user->newSubscription('default', 'price_xxxxxxxxxx')
->trialDays(14) // 14-dňová skúšobná doba
->create($paymentMethodId); // $request->payment_method_id z Stripe Elements
// Kontrola aktívneho predplatného
if ($user->subscribed('default')) {
// Prístup k prémiovému obsahu
}
// Overenie konkrétneho plánu
if ($user->subscribedToPrice('price_xxxxxxxxxx', 'default')) {
// Práve tento plán
}
// Zákazník dostane link na Stripe Billing Portal — spravuje platbu sám
$billingPortalUrl = $user->billingPortalUrl(route('dashboard'));
return redirect($billingPortalUrl);
// Zrušenie (na konci obdobia, nie ihneď)
$user->subscription('default')->cancel();
// Obnovenie po zrušení (kým ešte platí)
$user->subscription('default')->resume();
Testovanie cez Stripe CLI
Stripe CLI umožňuje testovať webhooky lokálne — presmeruje Stripe eventy priamo na váš localhost bez potreby verejného servera alebo tunelu.
# Inštalácia (macOS)
brew install stripe/stripe-cli/stripe
# Windows — cez Scoop
scoop install stripe
# Prihlásenie (otvorí prehliadač)
stripe login
# Spustenie — presmeruje webhooky na localhost
stripe listen --forward-to localhost:8000/stripe/webhook
# Výstup: webhook signing secret — skopírujte do .env ako STRIPE_WEBHOOK_SECRET
# > Ready! Your webhook signing secret is whsec_xxxxxxxxxxxx
V druhom terminále si môžete manuálne spustiť testovací event:
# Simulácia úspešného Checkout
stripe trigger checkout.session.completed
# Simulácia zlyhania platby
stripe trigger payment_intent.payment_failed
# Simulácia zrušenia predplatného
stripe trigger customer.subscription.deleted
Testovacie karty
| Číslo karty | Výsledok |
|---|---|
4242 4242 4242 4242 | Úspešná platba |
4000 0025 0000 3155 | Vyžaduje 3D Secure autentifikáciu |
4000 0000 0000 9995 | Platba zamietnutá (insufficient funds) |
4000 0000 0000 0002 | Platba zamietnutá (karta blokovaná) |
Dátum expirácie a CVC môžu byť ľubovoľné — v sandbox móde sa neoverujú. PSČ zadajte 12345.
Produkčný checklist
- Prepnúť kľúče —
STRIPE_KEYaSTRIPE_SECRETzmeňte zpk_test_/sk_test_napk_live_/sk_live_ - Nový webhook endpoint — v Stripe Dashboard vytvorte produkčný endpoint (
https://domena.sk/stripe/webhook) a skopírujte nový signing secret - Idempotency keys — pri opakovaných volaniach Stripe API (napr. retry pri výpadku) použite
Cashier::stripe()->paymentIntents->create($data, ['idempotency_key' => $orderId])— Stripe zaistí, že sa platba nevykoná dvakrát - Logovanie transakcií — každá platba by mala mať záznam v databáze s
stripe_session_id, sumou, stavom a timestamp-om - Webhook retry — Stripe automaticky opakuje webhook volania pri HTTP chybách (5×× odpovede). Vráťte vždy HTTP 200 — aj keď ste udalosť ignorovali. Inak Stripe bude retryovať a vy môžete spracovať event duplicitne
- Idempotentné handlery — každý webhook handler musí bezpečne zvládnuť duplicitné volanie (
stripe_session_idako unique index v DB) - HTTPS povinné — Stripe odmietne webhooky na plain HTTP URL v produkčnom móde
- Kľúče mimo repozitára —
STRIPE_SECRETnikdy dogit commit. Vždy cez.envalebo secret manager
Záver: čo ďalej
Laravel Cashier a Stripe spolu pokrývajú väčšinu platobných scenárov — od jednorazových platieb za konzultáciu po komplexný SaaS subscription model s viacerými plánmi, trial periódami a billing portálom. Pre pokročilejšie prípady Stripe ponúka:
- Stripe Connect — marketplace platby, výplaty tretím stranám (napr. predajca dostane 80 %, platforma 20 %)
- Stripe Radar — strojové učenie na detekciu podvodov
- Stripe Tax — automatický výpočet DPH podľa krajiny zákazníka
- Usage-based billing — účtovanie podľa skutočného využitia cez Cashier
reportUsage()
Platobné brány som integroval na viacerých projektoch — e-commerce, SaaS platforma pre rezervačný systém aj jednorazové platby za digitálny obsah. Kód sa stane predvídateľnejší, ak celý platobný tok (checkout → webhook → aktivácia) navrhujete ako API s jasným životným cyklom. A ak potrebujete spracovávať webhooky asynchrónne bez blokovania, pozrite si Laravel Queues a Jobs.