Интерфейс оплаты
Об интерфейсе оплаты
Внимание! Если вы используете CMS систему или любые другие торговые платформы, рекомендуем ознакомиться с готовыми решениями в разделе виджеты и модули.
Интерфейс Robokassa, предлагает перейти к оплате, нажав одну кнопку. Предварительно магазин должен сохранить у себя передаваемую информацию (номер счёта, сумма, дата формирования и дополнительные параметры, если они используются).
Покупатель отправляется для оплаты в платёжный интерфейс Robokassa, выбирает способ оплаты и совершает платёж. После чего средства перечисляются на ваш баланс в системе Robokassa, а на указанный вами ResultURL мы пришлём уведомление об оплате.
URL для запросов HTTP GET/POST
https://auth.robokassa.kz/Merchant/Index.aspx
Готовый виджет для оплаты на сайте
Вы можете выбрать готовый виджет и кастомизировать его под ваши нужды в конструкторе или в личном кабинете в разделе "Платежный виджет"
В конструкторе выберите нужный виджет способа перехода к оплате, отредактируйте его внешний вид, проставте сумму оплаты и при необходимости дополнительные поля. Затем сгенерируемый готовый код скопируйте к себе на сайт.
По каждому магазину передается четыре параметра:
• Кнопка перехода на оплату;
• Форма с произвольной суммой оплаты;
• Ссылка перехода на оплату;
• Оплата с помощью QR-кода;
Пример кода виджета, для самостоятельной установки
Приведённые примеры предполагают, что в технических настройках магазина выбран алгоритм расчёта хэша MD5.
Кнопка
Минимальный вариант — это кнопка, которая сразу ведёт пользователя на страницу Robokassa.
<?php
$merchantLogin = "demo";
$password1 = "password_1";
$invId = 12;
$outSum = "990.00";
$description = "Оплата заказа №12";
$signature = md5("$merchantLogin:$outSum:$invId:$password1");
?>
<form action="https://auth.robokassa.kz/Merchant/Index.aspx" method="POST">
<input type="hidden" name="MerchantLogin" value="<?= $merchantLogin ?>" />
<input type="hidden" name="OutSum" value="<?= $outSum ?>" />
<input type="hidden" name="InvId" value="<?= $invId ?>" />
<input type="hidden" name="Description" value="<?= $description ?>" />
<input type="hidden" name="SignatureValue" value="<?= $signature ?>" />
<input type="hidden" name="IsTest" value="1" />
<button type="submit">Оплатить через Robokassa</button>
</form>
Форма с произвольной суммой
Если покупатель должен сам ввести сумму (например, при пополнении счёта), используйте промежуточную форму. Скрипт ниже принимает сумму от пользователя, рассчитывает подпись и автоматически отправляет данные на страницу оплаты.
<?php
$merchant_login = "demo";
$password_1 = "password_1";
$invid = 0;
$description = "Техническая документация по ROBOKASSA";
$default_sum = "10";
$signature_value = md5("$merchant_login::$invid:$password_1");
print "<html><script language=JavaScript ".
"src='https://auth.robokassa.kz/Merchant/PaymentForm/FormFLS.js?".
"MerchantLogin=$merchant_login&DefaultSum=$default_sum&InvoiceID=$invid".
"&Description=$description&SignatureValue=$signature_value'></script></html>";
?>
С применением всех параметров
Расширенный пример позволяет передать дополнительные настройки: язык интерфейса, способ оплаты, email покупателя и данные чека.
<?php
// регистрационная информация (Идентификатор магазина, пароль №1)
$merchant_login = "demo";
$password_1 = "password_1";
// номер заказа
$invid = 12345;
// описание заказа
$description = "Техническая документация по ROBOKASSA";
// сумма заказа
$out_sum = "8.96";
// товарная номенклатура в url encode
$receipt = "%7B%22items%22%3A%5B%7B%22name%22%3A%22product%22%2C%22quantity%22%3A1%2C%22sum%22%3A8.96%2C%22tax%22%3A%22none%22%7D%5D%7D";
// предлагаемый способ оплаты
$incurrlabel = "BankCard";
// язык интерфейса
$culture = "ru";
// email покупателя
$Email = "test@test.kz";
// срок оплаты, до которого необходимо совершить платеж
$ExpirationDate = "2029-01-16T12:00";
// пользовательский параметр
$Shp_item = "digital";
// generate signature
$signature_value = md5("$merchant_login:$out_sum:$invid:$receipt:$password_1:Shp_item=$Shp_item");
// форма оплаты товара
print
"<html>".
"<form action='https://auth.robokassa.kz/Merchant/Index.aspx' method='POST'>".
"<input type='hidden' name='MerchantLogin' value='$merchant_login'>".
"<input type='hidden' name='OutSum' value='$out_sum'>".
"<input type='hidden' name='InvId' value='$invid'>".
"<input type='hidden' name='Description' value='$description'>".
"<input type='hidden' name='SignatureValue' value='$signature_value'>".
"<input type='hidden' name='Shp_item' value='$Shp_item'>".
"<input type='hidden' name='IncCurrLabel' value='$incurrlabel'>".
"<input type='hidden' name='Culture' value='$culture'>".
"<input type='hidden' name='Email' value='$Email'>".
"<input type='hidden' name='ExpirationDate' value='$ExpirationDate'>".
"<input type='hidden' name='Receipt' value='$receipt'>".
"<input type='submit' value='Оплатить'>".
"</form>".
"</html>";
?>
Скачать примеры
Описание параметров
Обязательные параметры
| Параметр | Значение |
|---|---|
MerchantLogin | Логин магазина, указанный в технических настройках. |
OutSum | Сумма к оплате в тенге. Формат — число через точку, например 123.45. |
SignatureValue | Контрольная сумма запроса. Строится из строки MerchantLogin:OutSum:[InvId]:[Receipt]:Пароль#1:[Shp_*] с использованием настроенного метода хэширования. Подробнее — в разделе «Сборка подписи». |
Необязательные параметры
| Параметр | Значение |
|---|---|
InvId | Номер счёта в магазине. Параметр необязательный, но мы настоятельно рекомендуем его использовать. Значение должно быть уникальным для каждой оплаты. Допустимые значения: от 1 до 2147483647. Если значение пустое, равно 0 или параметр не указан, при создании операции оплаты ему автоматически будет присвоено уникальное значение. |
Description | Название товара или услуги (до 100 символов, без спецсимволов). |
Email | Почта покупателя. Используется для чеков и уведомлений. |
IncCurrLabel | Предлагаемый способ оплаты. Например, BankCard для банковских карт. Подробности см. в разделе «XML-интерфейсы». |
Culture | Язык интерфейса (ru или en). |
Encoding | Кодировка передаваемых данных (по умолчанию UTF-8). |
IsTest | Включение тестового режима (1 — тест, 0 — основной). |
ExpirationDate | Крайний срок оплаты в формате ISO 8601 (YYYY-MM-DDThh:mm). |
Receipt | Фискальные данные в формате JSON (закодированы в UTF-8 и затем в URL). Подробности см. в разделе «Фискализация». |
StepByStep | Признак холда (true), при котором оплата проводится в два этапа. Подробности см. в разделе «Холдирование и предавторизация». |
PaymentMethods | Предлагаемые способы оплаты. В отличие от IncCurrLabel позволяет передать сразу несколько способов оплаты.Для этого укажите несколько параметров PaymentMethods с разными значениями.При использовании Iframe-версии платёжной страницы способ реализации описан в соответствующем разделе. |
ResultUrl2 | Дополнительный серверный callback. Для холдирования укажите ResultUrl2, чтобы получить уведомление Result2, и учитывайте его в подписи вместе с StepByStep. Подробности см. в разделе «Дополнительное оповещение об оплате на ResultUrl2». |
SuccessUrl2 | Дополнительный адрес возврата при успешной оплате. Подробности см. в разделе «Дополнительная переадресация (ReturnURL: SuccessUrl2)». |
SuccessUrl2Method | Метод запроса к SuccessUrl2 (GET или POST). |
FailUrl2 | Дополнительный адрес возврата при ошибке. Подробности см. в разделе «Дополнительная переадресация (ReturnURL: FailUrl2)». |
FailUrl2Method | Метод запроса к FailUrl2 (GET или POST). |
Token | Токен сохранённой карты. Подробности см. в разделе «Оплата по сохранённой карте». |
Recurring | Флаг периодического платежа (true). Подробности см. в разделе «Периодические платежи». |
Shp | Дополнительные пользовательские параметры. Подробности см. в разделе «Дополнительные пользовательские параметры». |
Сборка подписи SignatureValue
SignatureValue подтверждает, что запрос на платёж сформирован вашим магазином. Строка для подписи собирается последовательно и всегда разделяется двоеточиями без пробелов:
MerchantLogin:OutSum:<InvId или пустой слот>:<модификаторы в строгом порядке>:Пароль#1:<Shp_параметры>
Основные правила
- Если
InvIdне передаётся, оставьте пустой слот (OutSum::...). - Если
Receiptпередаётся, добавьте его послеInvIdи доПароль#1. Пароль#1из личного кабинета всегда указывается перед пользовательскими параметрами.- Дополнительные параметры
Shp_*добавляются после пароля, сортируются по названию ключа и присоединяются в формате:Shp_key=value.
Состав строки
- Обязательные элементы —
MerchantLogin,OutSum,Пароль#1. - Опциональный элемент — InvId (оставляйте слот пустым, если параметр не используется).
- Модификаторы добавляются только при наличии и строго в следующем порядке:
Receipt— фискальные данные в минимизированном JSON UTF-8.StepByStep— признак поэтапной оплаты.ResultUrl2— дополнительный серверный callback.SuccessUrl2— альтернативный success-редирект.SuccessUrl2Method— метод запроса кSuccessUrl2(GETилиPOST).Token— токен сохранённой карты для CoF-платежей.
После формирования строки вычислите хеш — по умолчанию используется MD5, при необходимости можно переключиться на SHA-256.
Дополнительные пользовательские параметры
Параметры, начинающиеся с префикса Shp_, позволяют передать в Robokassa собственные данные — идентификатор пользователя, тип товара или любые другие служебные значения.
- Добавляйте только латинские буквы, цифры и подчёркивания после префикса
Shp_. - Перед отправкой запроса отсортируйте параметры
Shp_*по названию и включите их в строку подписи в формате:Shp_key=value. - Переданные значения будут возвращены в ResultURL, SuccessURL, FailURL и других уведомлениях без изменений.
Используйте пользовательские параметры, чтобы связать оплату с внутренними сущностями магазина или передать дополнительные признаки заказа.
Типовые ошибки интерфейса оплаты
25— магазин не активирован. Ошибка появляется, если магазин работает в боевом режиме без активации или в настройках сайта указан некорректный идентификатор магазина. Проверьте значение идентификатора в разделе «Мои магазины» → «Технические настройки» и обновите его в вашем коде.26— магазин не найден. Убедитесь, что идентификатор магазина указан без опечаток и совпадает с данными в личном кабинете.29— неверный параметрSignatureValue. Проверьте скрипт, который формирует подпись, и убедитесь, что используются корректные значенияMerchantLoginиMerchantPass1. Если добавляете пользовательские параметрыShp_*, включайте их в формулу подсчёта, передавайте в алфавитном порядке и сохраняйте одинаковый регистр имени параметра в запросе и подписи.30— неверный параметр счёта. Проверьте обязательные и необязательные параметры, которые вы передаёте при инициализации оплаты.31— неверная сумма платежа. При переадресации на платёжную страницу сумма должна быть передана и быть больше нуля.33— время, отведённое на оплату счёта, истекло. Ознакомьтесь с лимитами по способам оплаты и оформляйте платёж заново.34— услуга рекуррентных платежей не разрешена магазину. Подключите услугу через менеджеров Robokassa.35— неверные параметры для инициализации рекуррентного платежа. Сверьтесь с документацией по рекуррентным платежам и проверьте настройки на сайте.40— повторная оплата счёта с тем же номером невозможна. Для каждого платежа передавайте уникальныйInvId. Значения, использованные в тестовом режиме (IsTest=1), не логируются и не вызывают эту ошибку.41— ошибка на старте операции. Повторите инициализацию платежа, при повторной неудаче обратитесь в поддержку.51— срок оплаты счёта истек. Актуально для счетов, выставленных через личный кабинет или JSON Web Token.52— попытка повторной оплаты уже оплаченного счёта. Актуально для счетов, выставленных через личный кабинет или JSON Web Token.53— счёт не найден. Проверьте ссылку на счёт или его существование (для личного кабинета и JSON Web Token).64— функционал холдирования средств запрещён для магазина. Подключите услугу перед использованием холда.65— некорректные параметры для холдирования. Уточните передаваемые значения для операций с холдом.20,21,22,23,24,27,28,32,36,37,43,500— внутренние ошибки сервиса. Сообщите в поддержку Robokassa через раздел «Поддержка» в личном кабинете.
Если вы используете тестовую среду Robokassa (IsTest=1 или соответствующая настройка в модуле), применяйте только тестовую пару технических паролей из вкладки «Технические настройки» в карточке магазина. Использование боевых паролей в тестовом окружении приводит к ошибке 29.
Рекомендации для разработчиков мобильных приложений
Если платёжная форма открывается во встроенном браузере мобильного приложения, используйте android.webkit.WebView на Android и WKWebView на iOS. Устаревший компонент UIWebView не поддерживается.
Deep links в мобильном WebView
При выборе банка платёжная страница может перейти по deep link для запуска банковского приложения. Встроенный WebView не открывает нестандартные URL-схемы автоматически. Например, Android WebView может показать ошибку net::ERR_UNKNOWN_URL_SCHEME.
Обрабатывайте такие переходы в мобильном приложении:
- Оставляйте обычные ссылки с протоколами
httpиhttpsвнутри WebView. - Перехватывайте ссылки с другими схемами и передавайте их системному механизму запуска приложений.
- После перехвата отменяйте загрузку ссылки внутри WebView.
- Сообщайте пользователю, если банковское приложение не установлено или ссылку невозможно открыть.
Ссылки https://qr.nspk.ru/... обрабатывайте как внешние, несмотря на протокол https.
Если WebView может открывать сторонние страницы, разрешайте запуск внешних приложений только для доверенных адресов и схем.
Android
Переопределите shouldOverrideUrlLoading. Для ссылок формата intent://... используйте Intent.parseUri, для остальных внешних ссылок — Intent.ACTION_VIEW.
import android.content.ActivityNotFoundException
import android.content.Intent
import android.webkit.WebResourceRequest
import android.webkit.WebView
import android.widget.Toast
import java.net.URISyntaxException
override fun shouldOverrideUrlLoading(
view: WebView,
request: WebResourceRequest,
): Boolean {
val uri = request.url
val scheme = uri.scheme?.lowercase()
val isWebUrl = scheme == "http" || scheme == "https"
val isSbpUrl = uri.host.equals("qr.nspk.ru", ignoreCase = true)
if (isWebUrl && !isSbpUrl) {
return false
}
return try {
val intent = if (scheme == "intent") {
Intent.parseUri(uri.toString(), Intent.URI_INTENT_SCHEME).apply {
addCategory(Intent.CATEGORY_BROWSABLE)
component = null
selector = null
}
} else {
Intent(Intent.ACTION_VIEW, uri)
}
view.context.startActivity(intent)
true
} catch (error: ActivityNotFoundException) {
Toast.makeText(
view.context,
"Не удалось открыть приложение банка",
Toast.LENGTH_LONG,
).show()
true
} catch (error: URISyntaxException) {
true
} catch (error: SecurityException) {
true
}
}
Возвращайте true после перехвата, чтобы WebView не пытался загрузить deep link.
iOS
Реализуйте метод WKNavigationDelegate, отмените переход внутри WKWebView и откройте deep link через UIApplication.
import UIKit
import WebKit
func webView(
_ webView: WKWebView,
decidePolicyFor navigationAction: WKNavigationAction,
decisionHandler: @escaping (WKNavigationActionPolicy) -> Void
) {
guard let url = navigationAction.request.url else {
decisionHandler(.cancel)
return
}
let scheme = url.scheme?.lowercased()
let isWebUrl = scheme == "http" || scheme == "https"
let isSbpUrl = url.host?.lowercased() == "qr.nspk.ru"
guard !isWebUrl || isSbpUrl else {
decisionHandler(.allow)
return
}
decisionHandler(.cancel)
UIApplication.shared.open(url, options: [:]) { opened in
if !opened {
// Покажите пользователю сообщение о том, что приложение банка недоступно.
}
}
}
Вызывайте decisionHandler ровно один раз для каждого перехода. Проверяйте результат в completion handler метода open, чтобы обработать отсутствие подходящего приложения.