Двухстадийная оплата
При необходимости, Партнеры могут установить возможность дополнительного подтверждения суммы платежа. Это делается в тех случаях, когда стоимость товара, или услуги, может измениться по различным причинам: клиент оплатил за несколько единиц товара, но на складе осталось меньше, или произошла уценка товара, др. Для установки данного функционала, необходимо, в методе prepare_payment
, параметр auto_capture
задать как false
. Тогда, вместо списания средств, производится холдирование и Процессинговый центр (ПЦ) будет ожидать вызова дополнительного метода set_accept
для уточнения суммы списания. Если сумма не меняется, то холдирование переходит в списание и транзакция завершится, а если подтвержденная сумма окажется меньше изначальной суммы, то оставшаяся часть будет возвращена клиенту на его банковскую карту.
Примечание
В случае, если сумма транзакции не будет подтверждена в течение 30 минут (больше информации про отмены, см. в разделе «Отмена платежа»), то транзакция будет автоматически отменена.
Важно!
Callback
с нашей стороны будет отправляться до тех пор, пока мы не получим статус waiting_user_action
в ответе для прекращения отправок, либо статус capture
.
Схемы работ
При подтверждении всей суммы, Humo/Uzcard (ПЦ)
- Клиент выбрал товар/услугу;
- В корзине нажал «Оплатить»;
- Партнер инициирует транзакцию методом
prepare_payment
; - Наш Back-end (BE) отправляет ссылку на наш Front-end (FE) для оплаты;
- Партнер перенаправляет клиента на наш FE;
- Клиент выбирает способ оплаты;
- Наш FE отправляет экранную форму для ввода данных банковской карты;
- Клиент заполняет и отправляет данные банковской карты;
- Наш FE перенаправляет на экранную форму ввода OTP кода;
- Процессинговый центр (ПЦ) отправляет OTP код;
- Клиент отправляет OTP код*;
- После проверок, наш BE отправляет запрос на холдирование средств
set_accept
в ПЦ; - ПЦ подтверждает холдирование или отказывает;
- Мы уведомляем Партнера об успешном/неуспешном холдировании;
- Отправляем запрос подтверждения суммы в виде
callback
; - Партнер подтверждает полную сумму оплаты;
- Мы убеждаемся, что сумма не изменилась;
- Подтверждаем сумму в ПЦ;
- Получаем подтверждение от ПЦ;
- Отправляем ответ на подтверждение суммы;
- Перенаправляем клиента обратно на сайт Партнера.
При частичном подтверждении суммы, Humo/Uzcard (ПЦ)
- Клиент выбрал товар/услугу;
- В корзине нажал «Оплатить»;
- Партнер инициирует транзакцию методом
prepare_payment
; - Наш Back-end (BE) отправляет ссылку на наш Front-end (FE) для оплаты;
- Партнер перенаправляет клиента на наш FE;
- Клиент выбирает способ оплаты;
- Наш FE отправляет экранную форму для ввода данных банковской карты;
- Клиент заполняет и отправляет данные банковской карты;
- Наш FE перенаправляет на экранную форму ввода OTP кода;
- Процессинговый центр (ПЦ) отправляет OTP код;
- Клиент отправляет OTP код*;
- После проверок, наш BE отправляет запрос на холдирование средств
set_accept
в ПЦ; - ПЦ подтверждает холдирование или отказывает;
- Мы уведомляем Партнера об успешном/неуспешном холдировании;
- Отправляем запрос подтверждения суммы в виде
callback
; - Партнер подтверждает часть суммы оплаты;
- Мы получаем сумму меньше первоначальной;
- Проводим коррекцию суммы транзакции;
- Получаем подтверждение от ПЦ;
- Отправляем ответ на подтверждение суммы;
- Перенаправляем клиента обратно на сайт Партнера;
- ПЦ возвращает остаток средств клиенту.
При подтверждении всей суммы, Visa/MC (ПЦ)
- Клиент выбрал товар/услугу;
- В корзине нажал «Оплатить»;
- Партнер инициирует транзакцию методом
prepare_payment
; - Наш Back-end (BE) отправляет ссылку на наш Front-end (FE) для оплаты;
- Партнер перенаправляет клиента на наш FE;
- Клиент выбирает способ оплаты;
- Наш FE отправляет экранную форму для ввода данных банковской карты;
- Клиент заполняет и отправляет данные банковской карты;
- Наш BE отправляет запрос на холдирование средств
set_accept
в ПЦ; - ПЦ отправляет ссылку на форму ввода OTP кода;
- Наш BE перенаправляет на экранную форму ввода OTP кода;
- ПЦ отправляет OTP код;
- Клиент отправляет OTP код;
- ПЦ отправляет нам уведомление о подтверждении холдирования средств;
- Мы уведомляем Партнера об успешном/неуспешном холдировании;
- Отправляем запрос подтверждения суммы в виде
callback
; - Партнер подтверждает полную сумму оплаты;
- Мы убеждаемся, что сумма не изменилась;
- Подтверждаем сумму в ПЦ;
- Получаем подтверждение от ПЦ;
- Отправляем ответ на подтверждение суммы;
- Перенаправляем клиента обратно на сайт Партнера.
При частичном подтверждении суммы, Visa/MC (ПЦ)
- Клиент выбрал товар/услугу;
- В корзине нажал «Оплатить»;
- Партнер инициирует транзакцию методом
prepare_payment
; - Наш Back-end (BE) отправляет ссылку на наш Front-end (FE) для оплаты;
- Партнер перенаправляет клиента на наш FE;
- Клиент выбирает способ оплаты;
- Наш FE отправляет экранную форму для ввода данных банковской карты;
- Клиент заполняет и отправляет данные банковской карты;
- Наш BE отправляет запрос на холдирование средств
set_accept
в ПЦ; - ПЦ отправляет ссылку на форму ввода OTP кода;
- Наш BE перенаправляет на экранную форму ввода OTP кода;
- ПЦ отправляет OTP код;
- Клиент отправляет OTP код;
- ПЦ отправляет нам уведомление о подтверждении холдирования средств;
- Мы уведомляем Партнера об успешном/неуспешном холдировании;
- Отправляем запрос подтверждения суммы в виде
callback
; - Партнер подтверждает часть суммы оплаты;
- Мы получаем сумму меньше первоначальной;
- Проводим коррекцию суммы транзакции;
- Получаем подтверждение от ПЦ;
- Отправляем ответ на подтверждение суммы;
- Перенаправляем клиента обратно на сайт Партнера;
- ПЦ возвращает остаток средств клиенту.
Методы
prepare_payment
- URL:
https://secure.octo.uz/prepare_payment
- Method:
POST
- Content-type:
application/json
Тестовые транзакции
Для проведения тестовой транзакции необходимо при инициации метода prepare_payment
указать в теле запроса параметр test
со значением true
. Этот параметр является необязательным. Если он не указан, будет создана реальная транзакция.
Для проведения тестовой транзакции укажите - test: true
{
"auto_capture": true,
"test": true,
"init_time": "2024-05-02 09:17:00"
}
Пример запроса
Важно!
Одностадийная оплата - auto_capture: true
Двухстадийная оплата - auto_capture: false
{
"octo_shop_id": 123,
"octo_secret": "537da54b-835a-4968-9864-c2ae02c5902e",
"shop_transaction_id": "0000_0000_0000_0000_0010",
"auto_capture": true,
"init_time": "2024-05-02 09:17:00",
"test": false,
"user_data": {
"user_id": "Johnny Depp",
"phone": "998901234567",
"email": "octo@mail.com"
},
"total_sum": 1000.0,
"currency": "UZS",
"description": "TEST_PAYMENT",
"basket": [
{
"position_desc": "Йогурт MANON клубничный",
"count": 2,
"price": 10.0,
"spic": "special_information_for_position"
},
{
"position_desc": "Йогурт MANON банановый",
"count": 1,
"price": 20.0,
"spic": "special_information_for_position"
}
],
"payment_methods": [
{
"method": "bank_card"
},
{
"method": "uzcard"
},
{
"method": "humo"
}
],
"tsp_id": 18,
"return_url": "https://octo.uz" // (URL всегда должен быть полным),
"notify_url": "https://notify-url.uz",
"language": "uz",
"ttl": 15
}
Параметры запроса
Параметр | Тип | Обязательность | Описание |
---|---|---|---|
octo_shop_id | Integer | Да | Уникальный ID магазина (доступен в ЛК магазина). |
octo_secret | String | Да | Персональный секретный ключ магазина, который генерируется в ЛК магазина. Должен содержаться в безопасной недоступной зоне сайта магазина. |
shop_transaction_id | String | Да | Уникальный идентификатор транзакции на стороне магазина. Используется OCTO для предотвращения случайного дублирования транзакций. |
auto_capture | Bool | Да | Если true, то ПС Octo будет автоматически подтверждать списание средств со счета покупателя. Если false, то после авторизации платежа Octo будет ожидать от магазина дополнительного подтверждения завершения транзакции. По умолчанию false |
test | Bool | Да | Тестовый платёж или нет. |
init_time | Datetime | Да | Время создания платежа в формате yyyy-MM-dd HH:mm:ss. |
user_data | Object | Нет | Информация о покупателе, используется для отображения на странице оплаты. |
user_data.user_id | String | Да (если передаётся весь блок user_data) | ID пользователя в БД магазина. |
user_data.phone | String | Да (если передаётся весь блок user_data) | Номер телефона пользователя. |
user_data.email | String | Да (если передаётся весь блок user_data) | Электронная почта пользователя. |
total_sum | Double | Да | Итоговая сумма платежа. |
currency | String | Да | Валюта. Варианты: USD, UZS, RUB. |
description | String | Да | Описание товара. |
basket | Array | Да | Блок детальной информации по корзине. Если присутствует, то будет отображен покупателю при оплате. |
basket.position_desc | String | Да (если передаётся весь блок basket) | Название позиции в чеке. |
basket.count | Int | Да (если передаётся весь блок basket) | Число таких позиций. |
basket.price | Double | Да (если передаётся весь блок basket) | Цена одной позиции. |
basket.spic | String | Нет | Дополнительное поле для уточнения информации о позиции в корзине. |
payment_methods | Array | Нет | Множество доступных покупателю методов оплаты. Если не передается, то будут предложены все доступные методы. |
payment_methods.method | String | Да (если передаётся весь блок payment_methods) | Название одного метода из вариантов: bank_card, uzcard, humo. |
tsp_id | Int | Нет | Идентификатор торгово-сервисного предприятия, обеспечивающего продажу данной услуги или товара. |
return_url | String | Да | URL на который следует перенаправить покупателя после завершения оплаты. URL должен содержать уникальный параметр, идентифицирующий конкретный платеж. |
notify_url | String | Нет | URL на который сервер OCTO будет отправлять нотификации об изменении статуса платежа. Если не установлен, то используется общий URL, который установлен в личном кабинете. |
language | String | Да | Язык платежной формы. По умолчанию - язык браузера или en. Допустимые значения: oz - узбекский (латиница), uz - узбекский (кириллица), en - английский, ru - русский. |
ttl | Int | Нет | Время жизни платежа с момента создания (в минутах). По истечению этого времени провести платеж будет невозможно. |
Пример успешного ответа
{
"error": 0,
"data": {
"shop_transaction_id": "c9211e0f-c6ba-4d97-b8be-fb230ef3985b",
"octo_payment_UUID": "e3f40dc3-4955-412a-853a-2ddd28d3201f",
"status": "created",
"octo_pay_url": "https://pay2.octo.uz/pay/e3f40dc3-4955-412a-853a-2ddd28d3201f?language=uz",
"refunded_sum": 0,
"total_sum": 1000.0
},
"apiMessageForDevelopers": "",
"shop_transaction_id": "c9211e0f-c6ba-4d97-b8be-fb230ef3985b",
"octo_payment_UUID": "e3f40dc3-4955-412a-853a-2ddd28d3201f",
"status": "created",
"octo_pay_url": "https://pay2.octo.uz/pay/e3f40dc3-4955-412a-853a-2ddd28d3201f?language=uz",
"refunded_sum": 0,
"total_sum": 1000.0
}
Параметры успешного ответа
Параметр | Тип | Обязательность | Описание |
---|---|---|---|
error | int | Да (если error=0 ) | Код ошибки (0 — ошибок нет). |
data | object | Да (если error=0 ) | Основной объект с данными о платеже. |
data.shop_transaction_id | string | Да (если error=0 ) | Уникальный идентификатор транзакции на стороне магазина. |
data.octo_payment_UUID | string | Да (если error=0 ) | Уникальный идентификатор платежа в системе Octo. |
data.status | string | Да (если error=0 ) | Статус платежа. |
data.octo_pay_url | string | Да (если error=0 ) | URL для перехода к оплате в системе Octo. |
data.refunded_sum | double | Нет | Сумма, которая была возвращена (если есть возвраты). |
data.total_sum | double | Да (если error=0 ) | Итоговая сумма платежа. |
apiMessageForDevelopers | string | Нет | Сообщение для разработчиков, предоставляемое API (пустое в случае успеха). |
shop_transaction_id | string | Да (если error=0 ) | Дублирует shop_transaction_id из объекта data . |
octo_payment_UUID | string | Да (если error=0 ) | Дублирует octo_payment_UUID из объекта data . |
status | string | Да (если error=0 ) | Дублирует status из объекта data . |
octo_pay_url | string | Да (если error=0 ) | Дублирует octo_pay_url из объекта data . |
refunded_sum | double | Да (если error=0 ) | Дублирует refunded_sum из объекта data . |
total_sum | double | Да (если error=0 ) | Дублирует total_sum из объекта data . |
Пример неуспешного ответа
{
"error": 2,
"errMessage": "Wrong secret",
"data": null,
"errorMessage": "Wrong secret",
"apiMessageForDevelopers": "Поле errorMessage устарело, просим перейти на errMessage для унификации ответов. Так же пожалуйста знайте, что в дальнейшем все поля кроме error и errMessage будут передаваться в data. Для более подробного ознакомление свяжитесь с технической поддержкой сервиса"
}
Параметры неуспешного ответа
Параметр | Тип | Обязательность | Описание |
---|---|---|---|
error | int | Да | Код ошибки (0 указывает на отсутствие ошибок). |
errMessage | string | Да | Сообщение об ошибке (если ошибка произошла). |
data | object | Нет | Основные данные транзакции (при ошибке может быть null ). |
errorMessage | string | Да | Сообщение об ошибке (если ошибка произошла). |
apiMessageForDevelopers | string | Нет | Техническое сообщение (поле для дополнительной информации). |
Важно!
В дальнейшем все поля, кроме error
и errMessage
, будут передаваться в объект data
. Если у вас возникают вопросы по поводу структуры ответов, пожалуйста, свяжитесь с технической поддержкой сервиса Octo.
set_accept
- URL:
https://secure.octo.uz/set_accept
- Method:
POST
- Content-type:
application/json
Важно!
Метод set_accept
должен вызываться после успешной инициации платежа методом prepare_payment
. При возникновении вопросов по интеграции обратитесь в техническую поддержку.
Пример запроса
{
"octo_shop_id": "{{merchant_id}}",
"octo_secret": "{{merchant_secret}}",
"octo_payment_UUID": "{{octo_payment_UUID}}",
"accept_status": "capture", // или "cancel"
"final_amount": 10.00
}
Параметры запроса
Параметр | Тип | Обязательность | Описание |
---|---|---|---|
octo_shop_id | int | Да | Уникальный идентификатор магазина, доступный в личном кабинете магазина. |
octo_secret | string | Да | Персональный секретный ключ магазина, генерируемый в личном кабинете. |
octo_payment_UUID | string | Да | Уникальный идентификатор платежа, созданный системой OCTO. |
accept_status | string | Да | Статус подтверждения транзакции: capture для подтверждения или cancel для отмены. |
final_amount | decimal | Да | Окончательная сумма платежа. |
Пример успешного ответа
{
"error": 0,
"data": {
"shop_transaction_id": "6354c573-040a-490f-8d1f-2bb5c89b6d9d",
"octo_payment_UUID": "6b6b4477-ab8b-49dc-97eb-638b15b9b3e9",
"status": "succeeded",
"octo_pay_url": "https://dev-pay.octo.uz/pay/6b6b4477-ab8b-49dc-97eb-638b15b9b3e9?language=uz",
"transfer_sum": 980.00,
"refunded_sum": 0.00,
"total_sum": 1000.00,
"payed_time": "2024-12-18 16:15:34"
},
"apiMessageForDevelopers": "Поле errorMessage устарело, просим перейти на errMessage для унификации ответов."
}
Параметры успешного ответа
Параметр | Тип | Обязательность | Описание |
---|---|---|---|
error | int | Да | Код ошибки. 0 означает успешный запрос. |
data | object | Да | Объект с детальной информацией о платеже. |
data.shop_transaction_id | string | Да | Уникальный идентификатор транзакции в магазине. |
data.octo_payment_UUID | string | Да | Уникальный идентификатор платежа в системе Octo. |
data.status | string | Да | Статус платежа. Возможные значения: succeeded , failed , pending и др. |
data.octo_pay_url | string | Да | Ссылка для оплаты или просмотра статуса платежа. |
data.transfer_sum | float | Да | Сумма, которая была переведена, с учетом всех вычетов. |
data.refunded_sum | float | Нет | Сумма, которая была возвращена в рамках транзакции. Если возвратов не было, значение 0 . |
data.total_sum | float | Да | Изначально запрошенная сумма платежа. |
data.payed_time | string | Нет | Время успешного завершения платежа в формате YYYY-MM-DD HH:MM:SS . |
apiMessageForDevelopers | string | Нет | Сообщение для разработчиков о статусе API или изменениях. |
Пример неуспешного ответа
{
"error": 2,
"errMessage": "Wrong secret",
"data": null,
"errorMessage": "Wrong secret",
"apiMessageForDevelopers": "Поле errorMessage устарело, просим перейти на errMessage для унификации ответов."
}
Параметры неуспешного ответа
Параметр | Тип | Обязательность | Описание |
---|---|---|---|
error | int | Да | Код ошибки. |
errMessage | string | Да | Сообщение об ошибке. |
data | object | Нет | Основные данные транзакции (при ошибке может быть null ). |
errorMessage | string | Да | Устаревшее поле, сообщение об ошибке (рекомендуется использовать errMessage ). |
apiMessageForDevelopers | string | Нет | Сообщение для разработчиков о статусе API или изменениях. |
callback
- URL:
https://secure.octo.uz/callback
- Method:
POST
- Content-type:
application/json
Callback подтверждения суммы:
{
"octo_secret":"***",
"octo_payment_UUID":"0800a75f-1f50-4da8-9225-ae43028cbad1",
"accept_status":"capture",
"final_amount":437278.66
}
Параметр | Тип | Обязательность | Описание |
---|---|---|---|
octo_secret | String | Да | Персональный секретный ключ магазина, который генерируется в ЛК магазина. Должен содержаться в безопасной недоступной зоне сайта магазина |
octo_payment_UUID | String | Да (еслиerror=0 ) | Уникальный идентификатор платежа в системе Octo |
accept_status | String | Да | Статус подтверждения, обязательно для транзакций со статусом waiting_for_capture Возможные значения: capture – подтверждение платежаcancel – отмена платежа |
final_amount | Decimal | Нет | Подтверждаемая сумма платежа |
Структура ответа callback:
{
"accept_status": "capture",
"final_amount": 1000.00
}
Параметр | Тип | Обязательность | Описание |
---|---|---|---|
accept_status | String | Да | Статус подтверждения, обязательно для транзакций со статусом waiting_for_capture Возможные значения: capture – подтверждение платежаcancel – отмена платежа |
final_amount | Decimal | Нет | Подтверждаемая сумма платежа |
Предупреждение
Octo не хранит секретные ключи магазинов в открытом виде и не использует их для подписи нотификаций. Поэтому, прежде чем изменять статус на основе уведомления от Octo, рекомендуется дополнительно запросить актуальный статус. Такой запрос подписывается и шифруется секретным ключом магазина, что гарантирует его подлинность.