Інтеграція платіїної системи Stripe на сайт
Stripe — стандарт де-факто для міжнародних платежів. Документація вичерпна, SDK покриває всі основні мови, Stripe CLI спрощує локальну розробку. Працює з картами Visa, Mastercard, Amex, Apple Pay, Google Pay, SEPA, iDEAL та десятками інших методів залежно від регіону.
Важливо: з березня 2022 Stripe призупинив роботу з російськими юридичними особами. Інтеграція актуальна для білоруських, казахстанських, європейських та міжнародних бізнесів.
Установка та конфігурація
composer require stripe/stripe-php
// config/services.php
'stripe' => [
'key' => env('STRIPE_KEY'),
'secret' => env('STRIPE_SECRET'),
'webhook_secret' => env('STRIPE_WEBHOOK_SECRET'),
],
Ключі: pk_test_... / sk_test_... для тестування, pk_live_... / sk_live_... для продакшну.
Payment Intent — сучасний підхід
Stripe рекомендує використовувати Payment Intents API замість застарілого Charges API. Payment Intent описує намір прийняти платіж та керує 3D Secure автоматично.
Сервер — створення Payment Intent:
\Stripe\Stripe::setApiKey(config('services.stripe.secret'));
$paymentIntent = \Stripe\PaymentIntent::create([
'amount' => 1500, // у найменших одиницях (центах, копійках)
'currency' => 'eur',
'metadata' => ['order_id' => $order->id],
'automatic_payment_methods' => ['enabled' => true],
]);
return response()->json([
'clientSecret' => $paymentIntent->client_secret,
]);
Клієнт — Stripe Elements:
import { loadStripe } from '@stripe/stripe-js';
import { Elements, PaymentElement, useStripe, useElements } from '@stripe/react-stripe-js';
const stripePromise = loadStripe(import.meta.env.VITE_STRIPE_KEY);
function CheckoutForm({ clientSecret }: { clientSecret: string }) {
const stripe = useStripe();
const elements = useElements();
const handleSubmit = async (e: React.FormEvent) => {
e.preventDefault();
if (!stripe || !elements) return;
const { error } = await stripe.confirmPayment({
elements,
confirmParams: {
return_url: `${window.location.origin}/payment/complete`,
},
});
if (error) {
console.error(error.message);
}
};
return (
<form onSubmit={handleSubmit}>
<PaymentElement />
<button type="submit">Оплатити</button>
</form>
);
}
export default function Payment({ clientSecret }: { clientSecret: string }) {
return (
<Elements stripe={stripePromise} options={{ clientSecret }}>
<CheckoutForm clientSecret={clientSecret} />
</Elements>
);
}
PaymentElement автоматично показує придатні методи оплати залежно від місцеперебування клієнта та налаштувань Dashboard.
Webhook
Для локальної розробки: stripe listen --forward-to localhost:8000/webhook/stripe
public function handleWebhook(Request $request): Response
{
$payload = $request->getContent();
$sigHeader = $request->header('Stripe-Signature');
try {
$event = \Stripe\Webhook::constructEvent(
$payload,
$sigHeader,
config('services.stripe.webhook_secret')
);
} catch (\Stripe\Exception\SignatureVerificationException $e) {
return response('Invalid signature', 400);
}
match ($event->type) {
'payment_intent.succeeded' => $this->handleSuccess($event->data->object),
'payment_intent.payment_failed' => $this->handleFailed($event->data->object),
default => null,
};
return response('OK', 200);
}
private function handleSuccess(\Stripe\PaymentIntent $intent): void
{
$orderId = $intent->metadata->order_id;
Order::where('id', $orderId)->update([
'status' => 'paid',
'transaction_id' => $intent->id,
]);
}
Повернення
\Stripe\Stripe::setApiKey(config('services.stripe.secret'));
$refund = \Stripe\Refund::create([
'payment_intent' => $paymentIntentId,
'amount' => 750, // частинковий; видалити для повного
]);
Stripe CLI для розробки
# Установка
brew install stripe/stripe-cli/stripe
# Форвардинг вебхуків на локальний сервер
stripe listen --forward-to http://localhost:8000/webhook/stripe
# Відправка тестової подіїї
stripe trigger payment_intent.succeeded
Тестові карти: 4242424242424242 — успіх, 4000000000009995 — недостатньо коштів, 4000002760003184 — потребує 3D Secure.
Checkout Session — альтернатива для простих випадків
Якщо не потібен кастомний UI, Stripe Checkout Session дає готову сторінку оплати:
$session = \Stripe\Checkout\Session::create([
'line_items' => [[
'price_data' => [
'currency' => 'eur',
'unit_amount' => 1500,
'product_data' => ['name' => 'Товар 1'],
],
'quantity' => 1,
]],
'mode' => 'payment',
'success_url' => 'https://example.com/success?session_id={CHECKOUT_SESSION_ID}',
'cancel_url' => 'https://example.com/cancel',
'metadata' => ['order_id' => $order->id],
]);
return redirect($session->url);
Активація Stripe-аккаунту займає 1–2 дні для більшості юрисдикцій. Для білоруських ІП та юрлиць — реєстрація можлива через європейське представництво.







