Stripe i Płatności w Next.js
Stripe Checkout, Subscriptions, Webhooks, Stripe Connect, Paddle (MoR), Przelewy24 i BLIK dla rynku polskiego.
6 rozwiązań płatności — porównanie
Stripe, Paddle, Lemon Squeezy, Przelewy24, Tpay i PayU — model, VAT, rynek i opłaty transakcyjne.
| Rozwiązanie | Model | VAT | Rynek | Fee | Kiedy |
|---|---|---|---|---|---|
| Stripe | Payment Processor | Twoja odpowiedzialność | Globalny | 1.4% + 0.25 EUR (EU cards) | Globalne SaaS, marketplace, custom |
| Paddle | Merchant of Record | Paddle obsługuje | Globalny | 5% + $0.50 | SaaS globalny, zero VAT hassle |
| Lemon Squeezy | Merchant of Record | LS obsługuje | Globalny | 5% + $0.50 | Creators, software, open-source |
| Przelewy24 | Payment Aggregator | Twoja odpowiedzialność | Polska | ~1.6% | Rynek PL, BLIK, przelewy |
| Tpay | Payment Aggregator | Twoja odpowiedzialność | Polska/CE | ~1.5-2% | PL market, BLIK, banki |
| PayU | Payment Aggregator | Twoja odpowiedzialność | Polska + CE | ~1.5-2% | PL i Europa Środkowa |
Często zadawane pytania
Co to jest Stripe i jak zintegrować płatności w Next.js?
Stripe: wiodący payment processor dla deweloperów (2010). API-first. 135+ walut. Obsługuje karty, BLIK, przelewy, Apple Pay, Google Pay. PCI DSS Level 1 — Stripe obsługuje compliance. Modele płatności: Checkout (hosted page), Payment Intents (custom form), Subscriptions, Connect (marketplace). Instalacja: npm install stripe @stripe/stripe-js @stripe/react-stripe-js. Klucze: STRIPE_SECRET_KEY (server), NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY (client). Stripe Checkout (najprostrze): Server — stripe.checkout.sessions.create({mode: 'payment', line_items: [{price: priceId, quantity: 1}], success_url, cancel_url}). Client — redirect do session.url. Checkout handles: card input, 3DS, Apple Pay. Webhooks — potwierdzenie płatności. Payment Intents (custom UI): Server — stripe.paymentIntents.create({amount: 2000, currency: 'pln', automatic_payment_methods: {enabled: true}}). Zwróć clientSecret. Client — Elements provider, PaymentElement, stripe.confirmPayment. Stripe.js: const stripe = await loadStripe(publishableKey). const {error} = await stripe.confirmPayment({elements, confirmParams: {return_url: successUrl}}). Test cards: 4242 4242 4242 4242 — success. 4000 0025 0000 3155 — 3DS required. Polskie płatności: BLIK (automatycznie przez Checkout). Przelewy24 (P24). iDEAL. SEPA Direct Debit.
Stripe Subscriptions — plany, trial periods i Customer Portal?
Subscription model: Customer -> Subscription -> Plan (Price) -> Product. Price: monthly ($9.99/month) lub yearly ($99/year). Interval: month, year, week, day. Trial: trial_period_days: 14. Tworzenie subscription: stripe.customers.create({email, name}). stripe.subscriptions.create({customer: customerId, items: [{price: priceId}], trial_period_days: 14, payment_behavior: 'default_incomplete'}). Proration: przy upgrade/downgrade automatyczna. proration_behavior: 'create_prorations'. Billing portal: stripe.billingPortal.sessions.create({customer: customerId, return_url: dashboardUrl}). Klient zarządza: zmiana planu, anulowanie, update payment method. Subscription webhooks: customer.subscription.updated — zmiana statusu. customer.subscription.deleted — anulowanie. invoice.payment_succeeded — opłata przebiegła. invoice.payment_failed — nieudana płatność. customer.subscription.trial_will_end — 3 dni przed końcem trial. Obsługa failed payment: dunning — Stripe smart retries. Smart Retries automatycznie. Email notification. Grace period. Pausing subscriptions: stripe.subscriptions.update(id, {pause_collection: {behavior: 'mark_uncollectible'}}). Metered billing: usage-based pricing. stripe.subscriptionItems.createUsageRecord(itemId, {quantity: units, action: 'increment'}). Coupon i promo codes: stripe.coupons.create({percent_off: 20, duration: 'once'}). stripe.promotionCodes.create({coupon: couponId, code: 'WELCOME20'}). Free tier + upgrade: separate product bez price. Webhook upgrades po akcji.
Stripe Webhooks — bezpieczna obsługa zdarzeń płatności?
Webhooks: Stripe -> Twój serwer przy każdym zdarzeniu. Asynchroniczne. Retry przy niepowodzeniu (5 razy, exponential backoff). Endpoint (Next.js Route Handler): export async function POST(req: Request) {const body = await req.text(). const signature = req.headers.get('stripe-signature'). let event: Stripe.Event. try {event = stripe.webhooks.constructEvent(body, signature, process.env.STRIPE_WEBHOOK_SECRET)} catch (err) {return new Response('Webhook Error', {status: 400})}. switch (event.type) {case 'checkout.session.completed': handleCheckout(event.data.object). case 'customer.subscription.deleted': handleCancellation(event.data.object)}}. Raw body ważny: nie parsuj JSON przed weryfikacją. bodyParser: false (Express). Stripe CLI dla lokalnego testowania: stripe listen --forward-to localhost:3000/api/webhooks. stripe trigger payment_intent.succeeded. Webhook secret: stripe webhooks endpoint webhook_secret -> STRIPE_WEBHOOK_SECRET. Idempotency: sprawdź czy event już przetworzony. Zapisz event.id do DB. Sprawdź przed przetworzeniem. Retry safe. Zdarzenia do obsłużenia: checkout.session.completed — aktywuj dostęp. payment_intent.payment_failed — notify user. customer.subscription.updated — sync plan. invoice.upcoming — remind o płatności. charge.dispute.created — chargeback alert. Stripe metadata: attach userId, planId do session. Dostępne w webhook event. Reconnect Stripe customer z własnym user: customers.search lub metadata lookup.
Stripe Connect — marketplace i płatności dla wielu sprzedawców?
Stripe Connect: płatności dla platform i marketplace. Express (quick onboarding), Standard (separate Stripe accounts), Custom (white-label, pełna kontrola). Modele: Direct charges — klient płaci sprzedawcy (platforma bierze fee). Destination charges — klient płaci platformie, platforma przekazuje do sprzedawcy. Separate charges and transfers — pełna kontrola. Onboarding sprzedawców: stripe.accounts.create({type: 'express', country: 'PL', email: sellerEmail}). accountLinks.create({account: accountId, refresh_url, return_url, type: 'account_onboarding'}). Przekieruj sprzedawcę do url. Webhook: account.updated, account.application.authorized. Opłata platformy: application_fee_amount: 200 (2 PLN). stripe: {account: connectedAccountId} jako transfer_data. PaymentIntent z transfer_data: transfer_data: {destination: connectedAccountId}. Wypłaty (payouts): automatyczne lub manualne. stripe.payouts.create({amount, currency}, {stripeAccount: connectedAccountId}). Lemon Squeezy i Paddle: alternatywy dla SaaS. Merchant of Record (MoR) — obsługują VAT/podatki za Ciebie. Prostsze dla twórców oprogramowania. Lemon Squeezy API + webhooks podobne do Stripe. Polar.sh: open-source. Dla open-source projektów, creators. Tips, subscriptions. Kiedy Stripe Connect: marketplace z wieloma sprzedawcami. Freelance platformy. Creator economy. Usługi połączone.
Alternatywy Stripe — Paddle, Lemon Squeezy, Przelewy24 i PayU dla rynku PL?
Paddle (Merchant of Record): zajmuje się VAT w 200+ krajach. Idealny dla SaaS sprzedającego globalnie. Integracja: Paddle.js overlay checkout. paddle_checkout_open(). Webhooks: payment.succeeded, subscription.cancelled. Droższy niż Stripe (5% + $0.50). Lemon Squeezy (MoR): open-source friendly. Subscriptions, one-time. License keys dla software. API + webhooks. Polskie płatności: Przelewy24 (P24): najpoularniejszy polski agregator. Integracja direktna lub przez Stripe (Stripe obsluguje P24). Akceptuje BLIK, przelewy bankowe, karty. Tpay: polski operator. BLIK, karty, przelewy. API REST. SDK PHP/JavaScript. PayU: obecny w PL i innych krajach CE. Checkout Page lub Rest API. Klarna: BNPL (Buy Now Pay Later). Dostępna przez Stripe (stripe.klarna). Podnosisz konwersję dla drogich produktów. Revolut Business: nowy player. Payment links i API. Przydatny dla małych biznesów. Porównanie Stripe vs Paddle vs P24: Stripe — globalny, najlepsza DX, ale VAT musisz samemu. Paddle — MoR, VAT handled, droższy. P24 — PL rynek, BLIK, tańszy fee (~1.6%). Wybór dla polskiego projektu: jeśli globalnie + DX -> Stripe. Jeśli globalnie + VAT-free -> Paddle. Jeśli głównie PL -> P24 lub Tpay. Jeśli SaaS digital products -> Lemon Squeezy. Zwroty: stripe.refunds.create({payment_intent: id, amount: 500}). Częściowe lub pełne.
Powiązane artykuły
Skontaktuj się z nami
Porozmawiajmy o Twoim projekcie. Bezpłatna wycena w ciągu 24 godzin.
Wyślij zapytanie
Telefon
+48 790 814 814
Pon-Pt: 9:00 - 18:00
adam@fotz.pl
Odpowiadamy w ciągu 24h
Adres
Plac Wolności 16
61-739 Poznań
Godziny pracy
Wolisz porozmawiać?
Zadzwoń teraz i porozmawiaj z naszym specjalistą o Twoim projekcie.
Zadzwoń teraz