Qut Pay Сайт Кабинет Білім базасы Нұсқаулықтар API құжаттамасы ҚАЗРУС
Басты бет → Білім базасы → Анықтамалық

Laravel сайтына Kaspi QR қосу

Жаңартылды: 2026-10-25 · Markdown нұсқасы

Қысқаша

Laravel-де Qut Pay арқылы Kaspi QR интеграциясы — екі маршрут. Біріншісі X-API-Key тақырыбымен POST https://api.qut.kz/api/v1/invoices сұрауымен счёт жасап, redirect()->away($inv['payUrl']) жасайды. Екіншісі — routes/api.php ішіндегі POST /qutpay/webhook (CSRF-сіз): X-Webhook-Signature қолтаңбасын шикі дене $request->getContent() бойынша тексереді, тапсырысты externalOrderId бойынша табады, оны бір рет төленді деп белгілеп, 200 қайтарады. Кілт пен құпия .env-те тұрады, алғашқы сынақ — qp_test_… кілтімен sandbox-та.

Дайындық

  1. https://qut.kz/app кабинетінде API кілтін жасаңыз (sandbox үшін qp_test_…, нақты режим үшін qp_live_…) және Интеграциялар бөлімінде https://site.kz/api/qutpay/webhook webhook адресін қосыңыз; құпия бір рет көрсетіледі — webhook баптау.
  2. .env ішінде: QUTPAY_API_KEY=… және QUTPAY_WEBHOOK_SECRET=…; config/services.php ішінде: 'qutpay' => ['key' => env('QUTPAY_API_KEY'), 'webhook_secret' => env('QUTPAY_WEBHOOK_SECRET')]. Кілт Blade-шаблондарға, JS-ке және репозиторийге түспеуі керек.
  3. PHP SDK жүктеп алыңыз (https://api.qut.kz/downloads/qutpay-sdk-php.zip) — бір файл src/QutPay.php, PHP 7.4+, тәуелділіктер жоқ. SDK-сыз да бәрі Http::withHeaders(['X-API-Key' => …])->post(…) арқылы істеледі.
  4. Тапсырыстар кестесіне qutpay_invoice_id және paid_at өрістерін қосыңыз.

Код: төлем контроллері мен webhook

// routes/web.php:  Route::post('/orders/{order}/pay', [PayController::class, 'pay']);
// routes/api.php:  Route::post('/qutpay/webhook', [PayController::class, 'webhook']);  // api тобы, CSRF жоқ

class PayController extends Controller
{
    public function pay(Order $order)
    {
        $qp  = new \QutPay\Client(config('services.qutpay.key'));
        $inv = $qp->createInvoice([
            'amount'          => $order->total,
            'description'     => "Тапсырыс №{$order->id}",
            'externalOrderId' => (string) $order->id,
            'successUrl'      => route('orders.show', $order),
            'idempotencyKey'  => "order-{$order->id}",   // қайта басу екінші счёт жасамайды
        ]);
        $order->update(['qutpay_invoice_id' => $inv['id']]);

        return redirect()->away($inv['payUrl']);         // QR мен «Kaspi-де төлеу» батырмасы бар бет
    }

    public function webhook(Request $request)
    {
        $raw = $request->getContent();                   // шикі дене, $request->all() ЕМЕС
        if (!\QutPay\Webhook::verify(config('services.qutpay.webhook_secret'), $raw, $request->headers->all())) {
            return response()->noContent(401);
        }
        $e = json_decode($raw, true);
        if (($e['event'] ?? '') === 'invoice.paid') {
            $inv = $e['invoice'];
            DB::transaction(function () use ($inv) {
                $order = Order::whereKey($inv['externalOrderId'])->lockForUpdate()->first();
                if ($order && $order->paid_at === null && (float) $inv['amount'] === (float) $order->total) {
                    $order->update(['paid_at' => now(), 'qutpay_invoice_id' => $inv['id']]);
                }
            });
        }
        return response()->noContent(200);                // 8 секунд ішінде, әйтпесе қайталанады
    }
}

SDK-сыз қолтаңба былай есептеледі: hash_equals('sha256=' . hash_hmac('sha256', $request->header('X-Webhook-Timestamp') . '.' . $raw, $secret), $request->header('X-Webhook-Signature', '')), қосымша X-Webhook-Timestamp 5 минуттан ескі болса қабылдамау.

Неге назар аудару керек

ЖағдайНеге маңызды
Webhook маршруты routes/api.php ішіндеweb тобында CSRF іске қосылып, Laravel 419 қайтарады; біз жеткізуді сәтсіз деп санап, ~2 сағат ішінде 11 ретке дейін қайталаймыз. Маршрут бәрібір web-те болса, оны VerifyCsrfToken ерекшеліктеріне қосыңыз
$request->all() емес, $request->getContent()HMAC байттар бойынша есептеледі; қайта жиналған JSON ешқашан сәйкес келмейді — қолтаңба сәйкес келмейді
ИдемпотенттілікБір оқиға екі рет келуі мүмкін; жол блокировкасы астындағы paid_at === null тексеруі қайталауды зиянсыз етеді — идемпотенттілік
«Рахмет» бетіsuccessUrl-ге оралу — төлемнің дәлелі емес; «төленді» деп базадағы paid_at немесе $qp->getInvoice($id, true) бойынша көрсетіңіз

SDK қателері ->status және ->errorCode өрістері бар \QutPay\ApiException түрінде келеді (invalid_amount, tariff_limit_reached, kaspi_session_expired …) — қателер каталогы.

Sandbox-та тексеру

  1. qp_test_… кілтімен /orders/1/pay ашыңыз — төлем бетіне бағытталасыз.
  2. Төлемді имитациялаңыз: $qp->simulateInvoice($id, 'paid') немесе {"status":"paid"} денесімен POST /api/v1/invoices/{id}/simulate — webhook қолтаңбасымен нағыз күйінде кетеді — sandbox.
  3. Тапсырыста paid_at пайда болғанына, ал қайталанған жеткізу (кабинеттегі тексеру батырмасы немесе сұрауды қайталау) ештеңе өзгертпейтініне көз жеткізіңіз.
  4. Кассирді қосқан соң qp_live_… кілтіне ауысыңыз — іске қосу алдындағы тексеру тізімі.

Сұрақ-жауап

SDK-сыз, тек Http::post арқылы бола ма? Иә: Http::withHeaders(['X-API-Key' => config('services.qutpay.key'), 'Idempotency-Key' => "order-{$order->id}"])->post('https://api.qut.kz/api/v1/invoices', [...])->json() — өрістер сол: amount, externalOrderId, description, successUrl, failUrl, metadata — счёттың барлық өрістері.

Локалда webhook жетпейді. Нақты режимде адрес нағыз домендегі https болуы керек; sandbox-та http және туннель адрестері жарайды. Жеткізу журналы — кабинетте, Интеграциялар бөлімінде.

Webhook болса, polling керек пе? Төлемді күту бетінде 5–10 секунд сайын өз серверіңізден сұрауға болады, ал ол — GET /invoices/{id}; бұл сатып алушыға ыңғайлылық, ақиқат көзі webhook болып қалады — webhook пе, сұрау ма.

Байланысты мақалалар

PHP SDKQut Pay-дің PHP клиентін жобаға қосу, счёт жасау, қайтару және webhook қолтаңбасын тексеру. Таза PHP пен Laravel мысалдары, raw body-ны дұрыс алу және ApiException арқылы қате өңдеу.Webhook қолтаңбасы сәйкес келмейдіҚолтаңба HMAC-SHA256(secret, timestamp + "." + rawBody) арқылы есептеледі. Ең жиі қате — денені JSON-ға айналдырып, қайта жолға түрлендіру. Raw body алудың Express, Laravel, Django мысалдары.Webhook баптауКабинетте webhook адресін қосу, оқиғаларды таңдау, құпияны сақтау, тақырыптар мен дене пішімі, 11 рет қайталау кестесі, журналды оқу, адресті сынау және қайта бағыттау ережесі.Sandbox-та төлемді симуляциялауsimulate эндпоинті арқылы sandbox счётының күйін өзгерту: paid, failed, expired. Kaspi шақырылмайды, webhook нағыз төлемдегідей келеді. Сынау циклі және автоматты тест жазу.Идемпоттылық: қайталаудан қорғануIdempotency-Key тақырыбы қалай жұмыс істейді, кілтті қалай құру керек, externalOrderId-дің рөлі неде, webhook өңдеуде және қайтаруда қайталанудан қалай сақтану керек.Счёт жасау: барлық өрістерPOST /api/v1/invoices эндпоинтінің толық анықтамасы — әр өрістің типі мен шектеуі, жауаптағы барлық өріс, curl мен Node мысалдары, qr мен phone айырмашылығы және жиі кездесетін қателер.

Сұрағыңыз қалды ма? WhatsApp +77788813333 · kazprose@gmail.com
Кабинеттен де жазуға болады: Қолдау.

Qut Pay — тәуелсіз сервис, «Kaspi Bank» АҚ-мен аффилирленбеген. Kaspi және Kaspi Pay — құқық иесінің тауар белгілері.