Проведение платежа по карте через H2H
H2H (Host-to-Host) — способ приёма оплаты без использования платёжной страницы KVELL. Используйте H2H, если хотите реализовать собственную платёжную страницу.
Метод создаёт одностадийный платёж по реквизитам банковской карты. Перед вызовом метода необходимо создать платёжную сессию; результат платежа определяется позднее по статусу транзакции или колбэку.
Работа с карточными данными
Для использования H2H-интеграции мерчант должен иметь действующий документ, подтверждающий соответствие требованиям PCI DSS.
Не сохраняйте и не логируйте card.pan и card.cvv. Значение card.cvv должно
использоваться только для проведения текущего платежа.
Сценарий интеграции
- Создайте платёжную сессию с уникальным
transaction. Для возврата пользователя на сайт мерчанта после 3-D Secure передайте в сессииredirect_url. - Соберите данные браузера пользователя и передайте реквизиты новой карты в
cardлибо данные привязанной карты вcustomer_card. - Сформируйте подпись в зависимости от выбранного варианта карты и отправьте запрос на проведение платежа.
- Получив
200, перенаправьте браузер пользователя по адресуform_url. На этой странице KVELL выполнит необходимые переходы на страницы банка и 3-D Secure, а затем перенаправит пользователя наredirect_urlиз сессии. Еслиredirect_urlне был передан, используется адрес платёжной страницы KVELL по умолчанию. - Определяйте результат платежа по статусу транзакции: используйте колбэк или опрашивайте метод статуса с интервалом 10 минут, пока не получите финальный статус.
URL
Запрос
Заголовки
| Название | Тип | Обязательно | Описание |
|---|---|---|---|
X-Api-Key |
string | Да | Идентификатор магазина. |
X-Signature |
string | Да | Подпись запроса. |
Формирование подписи
Объедините значения без разделителей в указанном порядке, вычислите SHA-256 от строки в кодировке UTF-8 и передайте
полученный hex-хеш в нижнем регистре в заголовке X-Signature.
Если используются реквизиты новой карты в объекте card:
Если используется привязанная карта в объекте customer_card:
secret_key находится в настройках магазина. Пробелы, переносы строк и другие разделители между значениями добавлять
нельзя. Значения должны в точности совпадать с данными в отправляемом JSON.
Тело запроса
| Параметр | Тип | Обязательно | Описание |
|---|---|---|---|
transaction |
string | Да | Уникальный номер транзакции на стороне мерчанта, переданный при создании сессии. |
card |
object | Условно | Реквизиты новой карты. Обязательно, если не передан customer_card. |
customer_card |
object | Условно | Данные привязанной карты. Обязательно, если не передан card. |
customer_key |
string | null | Условно | Идентификатор покупателя в системе мерчанта. Обязателен при bind_card: true. |
browser_info |
object | Да | Данные браузера пользователя. Описание полей приведено ниже. |
customer |
string | null | Нет | Идентификатор плательщика в системе мерчанта. |
bind_card |
boolean | Нет | true — привязать карту в KVELL после успешного платежа. По умолчанию false. |
Выберите один источник карточных данных
Передавайте ровно один объект: card или customer_card. Формула подписи зависит от выбранного объекта.
Объект card
| Параметр | Тип | Обязательно | Описание |
|---|---|---|---|
pan |
string | Да | Номер карты: от 12 до 19 цифр, проходит проверку по алгоритму Луна. |
expire |
string | Да | Срок действия карты в формате YYYY-MM, например 2028-12. |
cvv |
string | Да | Трёхзначный код безопасности карты. |
holder |
string | Да | Имя держателя карты, как указано на карте. |
Объект customer_card
| Параметр | Тип | Обязательно | Описание |
|---|---|---|---|
customer_key |
string | Да | Идентификатор покупателя, которому принадлежит карта. |
token |
string | Да | Токен из метода получения списка привязанных карт. |
cvv |
string | Да | Трёхзначный код безопасности карты. |
Объект browser_info
Данные необходимо получить в браузере пользователя непосредственно перед созданием платежа.
| Параметр | Тип | Обязательно | Описание |
|---|---|---|---|
user_agent |
string | Да | Содержимое HTTP-заголовка User-Agent. Используйте navigator.userAgent. Максимальная длина — 2048 символов. |
accept_header |
string | Нет | Содержимое HTTP-заголовка Accept, полученного от браузера пользователя. Максимальная длина — 2048 символов. По умолчанию application/json, text/plain, */*. |
color_depth |
integer | Да | Глубина цвета экрана в битах на пиксель — значение screen.colorDepth. Допустимые значения: 1, 4, 8, 15, 16, 24, 32, 48; не более 2 цифр. |
ip |
string | Да | Публичный IPv4- или IPv6-адрес браузера пользователя. IPv4 передаётся четырьмя десятичными группами через ., IPv6 — восемью шестнадцатеричными группами через :. |
language |
string | Нет | Язык браузера в формате IETF BCP 47, например ru-RU; не более 8 символов. По умолчанию ru-RU. |
screen_width |
integer | Да | Полная ширина экрана пользователя в пикселях — значение screen.width; не более 6 цифр. |
screen_height |
integer | Да | Полная высота экрана пользователя в пикселях — значение screen.height; не более 6 цифр. |
screen_print |
string | Да | Строка с текущим и доступным разрешением экрана, а также глубиной цвета. Формат показан в примере ниже. |
tz |
integer | Да | Разница между UTC и локальным временем браузера в минутах — значение new Date().getTimezoneOffset(); не более 5 символов с учётом знака. Например, -180 для Москвы. |
time_zone |
string | Да | Название часового пояса из Intl.DateTimeFormat().resolvedOptions().timeZone, например Europe/Moscow. |
java_enabled |
boolean | Да | Признак доступности Java в браузере — результат navigator.javaEnabled(): true или false. |
device_channel |
string | Да | Тип устройства: 01 — мобильное приложение мерчанта, 02 — браузер пользователя, 03 — 3DS Requestor. Для этого H2H-сценария передайте 02. |
Формирование browser_info в браузере
Значения ip и accept_header передайте в функцию со своего backend: получите их из входящего запроса пользователя.
Остальные параметры можно собрать в браузере непосредственно перед созданием платежа.
function collectBrowserInfo(ip, acceptHeader) {
const screen = window.screen;
return {
user_agent: navigator.userAgent,
accept_header: acceptHeader || "application/json, text/plain, */*",
color_depth: screen.colorDepth,
ip,
language: navigator.language || "ru-RU",
screen_width: screen.width,
screen_height: screen.height,
screen_print:
`Current Resolution: ${screen.width}x${screen.height}, ` +
`Available Resolution: ${screen.availWidth}x${screen.availHeight}, ` +
`Color Depth: ${screen.colorDepth}`,
tz: new Date().getTimezoneOffset(),
time_zone: Intl.DateTimeFormat().resolvedOptions().timeZone,
java_enabled:
typeof navigator.javaEnabled === "function"
? navigator.javaEnabled()
: false,
device_channel: "02"
};
}
Пример
{
"transaction": "payment-20260807-0001",
"browser_info": {
"user_agent": "Mozilla/5.0",
"accept_header": "application/json, text/plain, */*",
"color_depth": 24,
"ip": "203.0.113.10",
"language": "ru-RU",
"screen_width": 1920,
"screen_height": 1080,
"screen_print": "Current Resolution: 1920x1080, Available Resolution: 1920x1040, Color Depth: 24",
"tz": -180,
"time_zone": "Europe/Moscow",
"java_enabled": false,
"device_channel": "02"
},
"card": {
"pan": "5100000000000123",
"expire": "2034-12",
"cvv": "123",
"holder": "VASYA PUPKIN"
}
}
curl --request POST \
--url 'https://api.pay.kvell.group/v1/orders/card2account' \
--header 'Content-Type: application/json' \
--header 'X-Api-Key: <api-key>' \
--header 'X-Signature: <signature>' \
--data '{
"transaction": "payment-20260807-0001",
"browser_info": {
"user_agent": "Mozilla/5.0",
"accept_header": "application/json, text/plain, */*",
"color_depth": 24,
"ip": "203.0.113.10",
"language": "ru-RU",
"screen_width": 1920,
"screen_height": 1080,
"screen_print": "Current Resolution: 1920x1080, Available Resolution: 1920x1040, Color Depth: 24",
"tz": -180,
"time_zone": "Europe/Moscow",
"java_enabled": false,
"device_channel": "02"
},
"card": {
"pan": "5100000000000123",
"expire": "2034-12",
"cvv": "123",
"holder": "VASYA PUPKIN"
}
}'
Ответ
Выберите HTTP-код, чтобы посмотреть пример, параметры ответа и рекомендуемые действия.
Если HTTP-ответ не получен
Таймаут и разрыв соединения обрабатывайте так же, как ответ 5XX: результат создания платежа неизвестен. Сначала
запросите статус по исходному transaction и не создавайте новый платёж, пока результат исходного не установлен.
Параметры ответа
| Параметр | Тип | Описание |
|---|---|---|
form_url |
string | URL для продолжения сценария платежа и прохождения 3-D Secure. |
Что делать дальше
- Перенаправьте браузер пользователя по адресу
form_url. - После возврата на
redirect_urlполучите статус транзакции или обработайте колбэк.
{
"errors": [
{
"code": 20007,
"message": "Транзакция совершалась прежде"
}
]
}
Параметры ответа
| Параметр | Тип | Описание |
|---|---|---|
errors |
array | Список ошибок. Коды и рекомендации по обработке приведены в разделе «Ошибки HTTP-ответов». |
errors[].code |
integer | Код ошибки. В примере — 20007. |
errors[].message |
string | Описание причины отклонения запроса. |
Что делать дальше
- При
20007не создавайте дубликат — запросите статус исходногоtransaction. - При
20004повторно создайте сессию с тем жеtransaction, затем повторите запрос платежа. - Для остальных кодов выполните рекомендацию из справочника HTTP-ошибок.
Параметры ответа
| Параметр | Тип | Описание |
|---|---|---|
errors |
array | Список ошибок. Коды и рекомендации по обработке приведены в разделе «Ошибки HTTP-ответов». |
errors[].code |
integer | Код ошибки. Для запрета доступа — 20037. |
errors[].message |
string | Описание причины запрета доступа. |
Что делать дальше
Проверьте статус магазина и обратитесь к менеджеру KVELL. Повторяйте запрос только после восстановления доступа.
Параметры ответа
| Параметр | Тип | Описание |
|---|---|---|
errors |
array | Список ошибок. Коды и рекомендации по обработке приведены в разделе «Ошибки HTTP-ответов». |
errors[].code |
integer | Код ошибки. В примере — 20006. |
errors[].message |
string | Описание причины, по которой ресурс не найден. |
Что делать дальше
Проверьте X-Api-Key и контур Stage/Production. Не повторяйте запрос с теми же данными, пока не исправите причину.
{
"errors": [
{
"code": 20098,
"message": "transaction: Field required"
}
]
}
Параметры ответа
| Параметр | Тип | Описание |
|---|---|---|
errors |
array | Список ошибок валидации. Коды и рекомендации по обработке приведены в разделе «Ошибки HTTP-ответов». |
errors[].code |
integer | Код ошибки валидации. Для ошибки поля — 20098. |
errors[].message |
string | Название поля и причина ошибки валидации. |
{
"errors": [
{
"code": 20000,
"message": "Неизвестная ошибка"
}
]
}
Параметры ответа
| Параметр | Тип | Описание |
|---|---|---|
errors |
array | Список ошибок. Коды и рекомендации по обработке приведены в разделе «Ошибки HTTP-ответов». |
errors[].code |
integer | Код ошибки. Для неизвестной ошибки — 20000. |
errors[].message |
string | Описание технической ошибки. |
5XX, таймаут и разрыв соединения
Во всех этих случаях результат запроса считается неопределённым: платёж мог быть создан, даже если клиент не получил ответ. Оставьте операцию в своей системе в состоянии «обрабатывается» до получения подтверждённого результата от KVELL.
Единый алгоритм обработки
- Не создавайте новый платёж и не меняйте
transaction. - Запросите статус транзакции по исходному
transaction. - Если транзакция найдена, проверяйте её до финального статуса или дождитесь колбэка.
- Если запросы статуса продолжают завершаться технической ошибкой, обратитесь в поддержку и передайте
transaction.
Привязка карты при платеже
Чтобы привязать новую карту к покупателю в KVELL, добавьте в запрос bind_card: true и передайте customer_key.
Оплата привязанной картой
Если карта была привязана ранее, передайте customer_card вместо card и сформируйте подпись по формуле для
привязанной карты.
{
"transaction": "payment-20260807-0002",
"browser_info": {
"user_agent": "Mozilla/5.0",
"accept_header": "application/json, text/plain, */*",
"color_depth": 24,
"ip": "203.0.113.10",
"language": "ru-RU",
"screen_width": 1920,
"screen_height": 1080,
"screen_print": "Current Resolution: 1920x1080, Available Resolution: 1920x1040, Color Depth: 24",
"tz": -180,
"time_zone": "Europe/Moscow",
"java_enabled": false,
"device_channel": "02"
},
"customer_card": {
"customer_key": "customer-42",
"token": "<card-token>",
"cvv": "123"
}
}
Карта станет доступна в методе получения списка карт после успешного завершения платежа
со статусом completed. Привязка действует в рамках магазина из X-Api-Key.