О насБлогКонтакты
Бизнес и продукт15 августа 2015 г. 5 мин 200Обновлено: 22 июня 2026 г.

Как внедрить онлайн-оплату в Кыргызстане в 2015 году: Элсом, МБанк и VISA эквайринг

AunimedaAunimeda
📋 Содержание

Коротко: В 2015 году в КР работало три реалистичных варианта онлайн-оплаты: Элсом (QIWI-кошелёк, API через HTTP), банковский VISA/Mastercard эквайринг (РСК или МБанк, 3DS), СБЕР KG переводы. PayPal не работал. Stripe не работал. Наличными при доставке оставалось 60% оборота даже у лидеров рынка.


Что реально работало в 2015

Метод Охват Комиссия Сложность интеграции
Элсом (E-wallet) 30% аудитории 1-2% Средняя
Банковская карта (РСК/МБанк) 20% аудитории 2-3% Высокая (договор, 3DS)
Мобильный банкинг перевод 15% 0-0.5% Высокая (ручная сверка)
Наличные при доставке 60% 0% Нулевая

Сумма больше 100% - клиенты выбирали несколько способов.


Интеграция Элсом (2015 API)

<?php
// ElsomPayment.php - интеграция с Элсом API 2015

class ElsomPayment {
    private string $merchantId;
    private string $secretKey;
    private string $apiUrl = 'https://api.elsom.kg/v1/';

    public function __construct(string $merchantId, string $secretKey) {
        $this->merchantId = $merchantId;
        $this->secretKey  = $secretKey;
    }

    /**
     * Создать платёжный запрос
     * Пользователь будет перенаправлен на страницу Элсом для подтверждения
     */
    public function createPayment(int $orderId, float $amount, string $description): array {
        $timestamp = time();
        $params = [
            'merchant_id'  => $this->merchantId,
            'order_id'     => (string)$orderId,
            'amount'       => number_format($amount, 2, '.', ''),
            'currency'     => 'KGS',
            'description'  => $description,
            'callback_url' => 'https://myshop.kg/payment/callback/elsom',
            'success_url'  => 'https://myshop.kg/order/' . $orderId . '/success',
            'fail_url'     => 'https://myshop.kg/order/' . $orderId . '/fail',
            'timestamp'    => $timestamp,
        ];

        // Подпись: HMAC-SHA256 от отсортированных параметров
        ksort($params);
        $signString = implode('|', $params);
        $params['signature'] = hash_hmac('sha256', $signString, $this->secretKey);

        $response = $this->request('POST', 'payments/create', $params);

        return [
            'payment_id'   => $response['payment_id'],
            'redirect_url' => $response['payment_url'],
        ];
    }

    /**
     * Обработка callback от Элсом
     * Вызывается когда пользователь подтверждает оплату
     */
    public function handleCallback(array $postData): bool {
        // Проверяем подпись
        $signature = $postData['signature'] ?? '';
        $data = $postData;
        unset($data['signature']);
        ksort($data);
        
        $expectedSig = hash_hmac('sha256', implode('|', $data), $this->secretKey);
        
        if (!hash_equals($expectedSig, $signature)) {
            error_log('Elsom callback: invalid signature');
            return false;
        }

        return $postData['status'] === 'SUCCESS';
    }

    private function request(string $method, string $endpoint, array $data): array {
        $ch = curl_init($this->apiUrl . $endpoint);
        curl_setopt_array($ch, [
            CURLOPT_RETURNTRANSFER => true,
            CURLOPT_TIMEOUT        => 30,
            CURLOPT_SSL_VERIFYPEER => true,
            CURLOPT_POSTFIELDS     => json_encode($data),
            CURLOPT_HTTPHEADER     => ['Content-Type: application/json'],
        ]);
        $response = curl_exec($ch);
        curl_close($ch);
        return json_decode($response, true);
    }
}

Контроллер оплаты

<?php
// PaymentController.php

class PaymentController {
    private ElsomPayment $elsom;
    private OrderRepository $orders;

    public function initiate(int $orderId): void {
        $order = $this->orders->findOrFail($orderId);

        // Проверить что заказ принадлежит текущему пользователю
        if ($order['user_id'] !== auth()->userId()) {
            http_response_code(403);
            die('Forbidden');
        }

        $paymentMethod = $_POST['method'] ?? 'elsom';

        switch ($paymentMethod) {
            case 'elsom':
                $result = $this->elsom->createPayment(
                    $orderId,
                    $order['total'],
                    'Заказ #' . $orderId . ' на myshop.kg'
                );
                // Сохранить payment_id для последующей сверки
                $this->orders->setPaymentId($orderId, $result['payment_id'], 'elsom');
                header('Location: ' . $result['redirect_url']);
                exit;

            case 'card':
                // Редирект на страницу банка
                $bankUrl = $this->initiateBankPayment($order);
                header('Location: ' . $bankUrl);
                exit;

            case 'cod':
                // Наличные при доставке
                $this->orders->updateStatus($orderId, 'confirmed');
                header('Location: /order/' . $orderId . '/confirmed');
                exit;
        }
    }

    public function elsomCallback(): void {
        $postData = json_decode(file_get_contents('php://input'), true);

        if (!$this->elsom->handleCallback($postData)) {
            http_response_code(400);
            echo json_encode(['status' => 'error']);
            return;
        }

        $orderId = (int)$postData['order_id'];
        $order   = $this->orders->find($orderId);

        if ($order && $order['status'] === 'pending_payment') {
            $this->orders->updateStatus($orderId, 'paid');
            $this->orders->recordPayment($orderId, [
                'method'         => 'elsom',
                'transaction_id' => $postData['transaction_id'],
                'amount'         => $postData['amount'],
                'paid_at'        => date('Y-m-d H:i:s'),
            ]);
            // Отправить уведомление клиенту и менеджеру
            $this->notifyPaymentReceived($order);
        }

        echo json_encode(['status' => 'ok']);
    }
}

Банковский эквайринг: 3D Secure поток

<?php
// BankPayment.php - VISA/Mastercard через РСК банк

class BankPayment {
    private string $terminalId;
    private string $merchantPassword;
    private string $bankGateway = 'https://pay.rsk.kg/gateway/';

    public function initiate(int $orderId, float $amount, string $returnUrl): string {
        $params = [
            'TerminalID'    => $this->terminalId,
            'Amount'        => (int)($amount * 100),  // В тыйынах (копейках сома)
            'OrderID'       => $orderId,
            'Currency'      => '417',                  // KGS по ISO 4217
            'Merchant_data' => base64_encode(json_encode([
                'order_id' => $orderId,
                'amount'   => $amount,
            ])),
            'returnUrl'     => $returnUrl,
        ];

        $params['Signature'] = $this->sign($params);

        // Форма POST на страницу банка
        $html = '<form method="POST" action="' . $this->bankGateway . 'pay" id="bankForm">';
        foreach ($params as $key => $value) {
            $html .= '<input type="hidden" name="' . htmlspecialchars($key) . '" value="' . htmlspecialchars($value) . '">';
        }
        $html .= '</form><script>document.getElementById("bankForm").submit()</script>';
        return $html;
    }

    public function processReturn(array $data): bool {
        if (!$this->verifySignature($data)) {
            return false;
        }
        return $data['Result'] === '000';  // '000' = успешная оплата
    }

    private function sign(array $params): string {
        $str = $params['TerminalID'] . $params['Amount'] . $params['OrderID'] . $this->merchantPassword;
        return md5($str);
    }
}

База данных платежей

CREATE TABLE payments (
    id             INT AUTO_INCREMENT PRIMARY KEY,
    order_id       INT NOT NULL,
    method         ENUM('elsom','card','cod','mobile_transfer') NOT NULL,
    status         ENUM('pending','completed','failed','refunded') DEFAULT 'pending',
    amount         DECIMAL(10,2) NOT NULL,
    currency       CHAR(3) DEFAULT 'KGS',
    transaction_id VARCHAR(100),   -- ID транзакции в платёжной системе
    raw_response   TEXT,           -- Сохраняем сырой ответ для разбора споров
    paid_at        DATETIME,
    created_at     DATETIME DEFAULT NOW(),
    INDEX idx_order (order_id),
    INDEX idx_transaction (transaction_id)
) ENGINE=InnoDB;

Главная проблема 2015 года: доверие к онлайн-оплате

Технически мы сделали всё правильно. Но 60% клиентов выбирали «наличными курьеру».

Решение, которое сработало у нас: скидка 3% при онлайн-оплате. За три месяца доля онлайн-оплат выросла с 18% до 35%. Люди были готовы платить онлайн - им нужен был весомый повод начать.

К 2018 году это соотношение перевернулось само по себе: молодая аудитория перешла на карты без всяких скидок.

Читайте также

Как создать интернет-магазин с нуля в 2026 годуaunimeda
Бизнес и продукт

Как создать интернет-магазин с нуля в 2026 году

Пошаговое руководство по созданию интернет-магазина: от выбора платформы до первых продаж. Что реально нужно, а что лишнее - на основе опыта запуска магазинов в Кыргызстане и Казахстане.

Как запустить IT-стартап в Кыргызстане: от идеи до первых клиентов в 2026aunimeda
Бизнес и продукт

Как запустить IT-стартап в Кыргызстане: от идеи до первых клиентов в 2026

Пошаговое руководство по запуску IT-стартапа в Кыргызстане: регистрация компании, налоги для IT, поиск разработчиков, первые клиенты и типичные ошибки основателей.

IT аутсорсинг в Кыргызстане: почему бизнес из России и Казахстана выбирает разработчиков из Бишкекаaunimeda
Бизнес и продукт

IT аутсорсинг в Кыргызстане: почему бизнес из России и Казахстана выбирает разработчиков из Бишкека

Разбираем почему IT аутсорсинг в Кыргызстане выгоднее чем в России, Казахстане и Узбекистане: зарплаты, налоги, качество, часовые пояса и реальные риски.

Нужна IT-разработка для вашего бизнеса?

Разрабатываем сайты, мобильные приложения и AI-решения для бизнеса в Кыргызстане. Бесплатная консультация.

Получить консультацию Все статьи