Інтеграція платіїної системи Fondy на сайт
Fondy — український платіжний шлюз, активно використовується в Україні, та має ліцензії для роботи у країнах ЄС. Підтримує карти Visa, Mastercard, Google Pay, Apple Pay, локальні українські методи (Приват24, MONO, Укрбанк). Документація на російській та англійській мовах, REST API стабільний.
Параметри підключення
З особистого кабінету merchant.fondy.eu потрібно отримати:
-
merchant_id— ідентифікатор магазину -
secret_key— для підпису запитів
Тестові транзакції проходять через той же URL, відмінність тільки у тестових даних карт.
Hosted Payment Page — базова інтеграція
Найпоширеніший варіант — перенаправлення на сторінку Fondy:
function buildFondyPayment(int $orderId, int $amountInKopecks, string $currency = 'UAH'): array
{
$merchantId = env('FONDY_MERCHANT_ID');
$secretKey = env('FONDY_SECRET_KEY');
$params = [
'merchant_id' => $merchantId,
'order_id' => $orderId . '_' . time(), // уникальність обов'язкова
'order_desc' => "Заказ #{$orderId}",
'amount' => $amountInKopecks,
'currency' => $currency,
'response_url' => 'https://example.com/payment/return',
'server_callback_url' => 'https://example.com/webhook/fondy',
'lang' => 'ru',
];
// Підпис: SHA1 від конкатенації значень, відсортованих по ключу, через |
ksort($params);
$signString = $secretKey . '|' . implode('|', array_values($params));
$params['signature'] = sha1($signString);
return $params;
}
// Відправляємо POST на https://pay.fondy.eu/api/checkout/redirect/
Форма може відправлятись прямо як HTML POST, або через API з отриманням checkout_url.
API-метод з отриманням URL
$response = Http::post('https://pay.fondy.eu/api/checkout/url/', [
'request' => buildFondyPayment(12345, 150000),
]);
$checkoutUrl = $response->json('response.checkout_url');
return redirect($checkoutUrl);
Перевірка підпису у webhook
public function handleCallback(Request $request): Response
{
$data = $request->all();
// Убираємо signature з даних для перевірки
$received = $data['signature'];
unset($data['signature']);
// Убираємо пусті поля
$data = array_filter($data, fn($v) => $v !== '' && $v !== null);
ksort($data);
$expected = sha1(env('FONDY_SECRET_KEY') . '|' . implode('|', array_values($data)));
if (!hash_equals($expected, $received)) {
return response('Bad signature', 403);
}
if ($data['order_status'] === 'approved') {
// order_id містить суфікс часу, відділяємо вихідний ID
$orderId = (int) explode('_', $data['order_id'])[0];
Order::where('id', $orderId)->update([
'status' => 'paid',
'transaction_id' => $data['payment_id'],
]);
}
// Fondy очікує HTTP 200 з тілом {"response":"accept"}
return response()->json(['response' => 'accept']);
}
Статуси order_status: approved, declined, expired, processing, reversed (повернення).
Вбудована форма (Checkout JS)
Для вбудування форми прямо на сторінку без переходу на Fondy:
<script src="https://pay.fondy.eu/static_common/v1/checkout/ipsp.js"></script>
$ipsp.get('checkout').config({
merchantId: FONDY_MERCHANT_ID,
amount: 1500,
currency: 'UAH',
orderId: 'order-12345',
orderDesc: 'Тестовий заказ',
signature: serverGeneratedSignature,
lang: 'ru',
fields: false, // використовувати нативні поля Fondy
fee: false,
theme: {
preset: 'silver',
},
});
Signature для JS-віджета генерується на сервері та передається на клієнт. Ніколи не генерувати на стороні браузера — секретний ключ не можна передавати у фронтенд.
Повернення
$params = [
'merchant_id' => env('FONDY_MERCHANT_ID'),
'order_id' => $originalOrderId,
'amount' => 75000, // частинковий повернення
'currency' => 'UAH',
'comment' => 'Customer request',
];
ksort($params);
$params['signature'] = sha1(env('FONDY_SECRET_KEY') . '|' . implode('|', array_values($params)));
Http::post('https://pay.fondy.eu/api/reverse/order/', ['request' => $params]);
Нюанси
Уникальність order_id у Fondy — обов'язкова вимога. Якщо один і той же order_id використаний повторно, транзакція відхиляється. Поширена практика — додавати timestamp або UUID до внутрішнього ID замовлення. Зберігати маппінг fondy_order_id → local_order_id потрібно до створення транзакції.
Термін підтвердження аккаунту у боевом режимі — 2–5 робочих днів.







