Integration of 1C-Bitrix with the Kaspi Pay payment system (Kazakhstan)

Our company is engaged in the development, support and maintenance of Bitrix and Bitrix24 solutions of any complexity. From simple one-page sites to complex online stores, CRM systems with 1C and telephony integration. The experience of developers is confirmed by certificates from the vendor.
Our competencies:
Development stages
Latest works
  • image_website-b2b-advance_0.png
    B2B ADVANCE company website development
    1175
  • image_bitrix-bitrix-24-1c_fixper_448_0.png
    Website development for FIXPER company
    811
  • image_bitrix-bitrix-24-1c_development_of_an_online_appointment_booking_widget_for_a_medical_center_594_0.webp
    Development based on Bitrix, Bitrix24, 1C for the company Development of an Online Appointment Booking Widget for a Medical Center
    564
  • image_bitrix-bitrix-24-1c_mirsanbel_458_0.webp
    Development based on 1C Enterprise for MIRSANBEL
    747
  • image_crm_dolbimby_434_0.webp
    Website development on CRM Bitrix24 for DOLBIMBY
    655
  • image_crm_technotorgcomplex_453_0.webp
    Development based on Bitrix24 for the company TECHNOTORGKOMPLEKS
    976

1C-Bitrix Integration with Kaspi Pay Payment System (Kazakhstan)

Kaspi Pay is a payment instrument of the Kaspi Bank ecosystem. Widely distributed in Kazakhstan: the customer scans a QR code or enters a phone number, confirms payment in the Kaspi application. For online stores, it is relevant as one of the most conversion-effective payment methods in the Kazakhstani market.

Integration Options

Kaspi provides several methods for online stores:

QR Payment — a QR code with an invoice is generated. The customer scans it through the Kaspi.kz app. Used both on the website and at offline points.

Kaspi Pay by Link — a link leads to a confirmation form in the browser or opens the Kaspi application.

Kaspi eCommerce API — for online stores, direct API integration.

For Bitrix integration, the standard approach is eCommerce API or payment link.

Kaspi eCommerce API

Authorization via Bearer token. Base URL: https://api.kaspi.kz/payment/

$token   = $this->getBusinessValue($payment, 'KASPI_TOKEN');
$orderId = $payment->getOrder()->getId();
$amount  = $payment->getSum();  // in tenge (KZT)

// Create payment
$payload = [
    'device'  => [
        'platformType' => 'WEB',
        'id'           => md5($orderId),
    ],
    'amount' => [
        'value'    => $amount,
        'currency' => 'KZT',
    ],
    'externalId'   => (string)$orderId,
    'description'  => 'Payment for order №' . $orderId,
    'paymentType'  => 'ECOM',
    'customer'     => [
        'phone' => $phone,  // customer phone in format +77XXXXXXXXX
    ],
    'redirectUrl'  => $returnUrl,
    'callbackUrl'  => $callbackUrl,
];

$ch = curl_init('https://api.kaspi.kz/payment/api/v1/payments/create');
curl_setopt($ch, CURLOPT_HTTPHEADER, [
    'Content-Type: application/json',
    'Authorization: Bearer ' . $token,
]);
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($payload));
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$response = json_decode(curl_exec($ch), true);
curl_close($ch);

// $response['data']['paymentLink'] — redirect link
// $response['data']['paymentId']   — payment ID for status check

Handling Notifications

Kaspi sends a POST to callbackUrl when the payment status changes:

$rawBody = file_get_contents('php://input');
$data    = json_decode($rawBody, true);

$paymentId  = $data['data']['paymentId'];
$externalId = $data['data']['externalId'];  // our orderId
$status     = $data['data']['status'];      // 'COMPLETED', 'FAILED', 'EXPIRED'

// Verification via signature header or additional status request
if ($status === 'COMPLETED') {
    // Verify via separate GET request to protect against fake notifications
    $verification = $this->httpGet(
        'https://api.kaspi.kz/payment/api/v1/payments/' . $paymentId,
        [],
        ['Authorization: Bearer ' . $token]
    );

    if ($verification['data']['status'] === 'COMPLETED') {
        $order = \Bitrix\Sale\Order::loadByAccountNumber($externalId);
        // setPaid('Y'), save()
    }
}

http_response_code(200);
echo json_encode(['status' => 'OK']);

Important: always verify the status via an additional GET request to the API. Accepting the status from the callback body without verification is a fraud risk.

QR Code on Order Page

An alternative UX for mobile users — QR code directly on the checkout page:

// Get QR code for payment
$qrResponse = $this->httpPost('https://api.kaspi.kz/payment/api/v1/payments/qr', $payload, $headers);
$qrBase64   = $qrResponse['data']['qrCode'];  // base64 PNG image

echo '<img src="data:image/png;base64,' . $qrBase64 . '" alt="Kaspi Pay QR">';
echo '<p>Scan QR in the Kaspi app</p>';

Additionally — implement polling or WebSocket for automatic status updates on the page without reloading.

Kazakhstani Market Characteristics

  • Currency — tenge (KZT). Amounts without kopecks (whole numbers)
  • Phone numbers in format +77XXXXXXXXX (7 or 8 at the start — clarify the format with Kaspi)
  • Kaspi Pay is popular for payments from 5,000 to 500,000 KZT — main audience
  • Kaspi also provides installment plans (Kaspi Red) — separate integration

Development Timeline

Task Timeline
Payment creation + redirect + callback 2–3 days
QR code on page + polling status +1–2 days
Testing on test environment 0.5–1 day