Банковские переводы в Узбекистане¶
| Название | Код | Описание |
|---|---|---|
| Тип интеграции | H2C |
Платеж на форме оплаты HighHelp |
| Валюта | UZS |
Узбекский сум |
| Страна | UZ |
Республика Узбекистан |
| Депозиты | ✅ | Доступные методы для оплаты: - payin-p2p-card |
| Выплаты | ❌ | Выплаты не доступны |
Оплата¶
Создание заявки¶
POST https://api.hh-processing.com/api/v1/widget/payin
Параметры, которые необходимо отправить в теле запроса при создании p2p заявки.
general** - информация по заявкеproject_id** - идентификатор кассы, полученный от HH в процессе интеграции.
(string) (<= 32 символа)payment_id** - идентификатор платежа, уникальный в рамках кассы мерчанта. Можно использовать любые буквы, цифры и символы в кодировке UTF-8.
(string) (<= 255 символа)merchant_callback_url- динамический URL для получения колбэков информативного характера, таких как: изменение промежуточных статусов заявки, реквизиты для оплаты p2p заявки и т.д. Колбэки по финальным статусам заявок приходят на URL адреса указанные вmerchant_success_callback_urlи вmerchant_decline_callback_url
(string<https-url>) (<= 2048 символа)merchant_success_callback_url- динамический URL для получения колбека при успешном завершении операции/транзакции.
(string<https-url>) (<= 2048 символа)merchant_decline_callback_url- динамический URL для получения колбека, если операция/транзакция не завершилась успешно
(string<https-url>) (<= 2048 символа)redirect_url- cсылка для редиректа пользователя с формы оплаты после завершения платежа
(string<https-url>) (<= 2048 символа)
payment** - информация по платежуamount** - сумма, которую намеревается оплатить пользователь. Сумму необходимо указывать в дробных единицах. Подробнее об этом можно прочитать в разделе "Коды валют"
(integer) (1 <= X <= 10000000000000)currency** - код валюты в которой оплачивает пользователь в формате "ISO-4217 alpha-3". Подробнее о кодах валют в разделе "Коды валют"
(string) (regex: ^[A-Z]{3}$)lifetime- время жизни заявки в секундах. Максимальное время жизни - 10 мин. Если время не указано, то устанавливается значение по умолчанию - 10 мин.
(integer) (300 <= X <= 600)description- описание платежа или комментарий. Данные будут отображены в личном кабинете мерчанта.
(string) (<= 255 символа)extra_param- дополнительный параметр, используемый для индивидуальной маршрутизации заявки. Настраивается совместно с администратором.
(string) (regex: ^[A-Za-z0-9_-]{1,16}$)widget_method- метод платежной страницы, который будет пред-выбран в виджете. Подробнее о методах платежной страницы можно прочитать в разделе "Поддерживаемые методы платежной страницы"
(string) (<= 32 символа)payment_system- платежная система, реквизит которой необходимо получить. Если параметр не указан, то будет выдан реквизит случайной платежной системы. Доступные значения:humo,uzcard
(string) (<= 32 символа)
sender- информация о карте/телефоне/банке пользователя, с которого производится оплатаbank_symbol- банк с которого клиент будет оплачивать заявку. Cписок банков см. в разделах "Поддерживаемые банки для предвыбора при оплате по клику" и "Поддерживаемые банки для предвыбора при транграничном переводе". Если желаемого банка нет в списке или нет нужды в предвыборе банка, то поле можно оставить незаполненным.
(string) (<= 32 символа)
customer** - информация об отправителеid** - уникальный идентификатор пользователя (отправителя) в проекте мерчанта
(string) (<= 255 символа)ip_address** - ip адрес отправителя
(string<ip-address>) (<= 255 символа)country** - код страны пользователя в формате "ISO 3166-1 alpha-2". Список поддерживаемых стран можете увидеть в разделе "Коды стран".
(string) (regex: ^[A-Z]{2}$)language- код языка в формате "ISO 639-1", который будет предвыбран на платежной странице. Если язык не указан, то будет выбран язык по умолчанию для страны. Список поддерживаемых языков можете увидеть в разделе "Коды языков".
(string) (regex: ^[a-z]{2}$)customer_type- тип пользователя.ftd- первичный трафик,trust- вторичный трафик;
(string) (regex: ^(ftd|trust)$)email- имейл адрес отправителя
(string<email>) (<= 255 символа)
Поля помеченные
**являются обязательными
Пример запроса:
curl https://api.hh-processing.com/api/v1/widget/payin \
-X POST \
-H 'x-access-timestamp: 1706182847' \
-H 'x-access-merchant-id: 8b03432e-385b-4670-8d06-064591096795' \
-H 'x-access-signature: fe99035f86fa436181717b302b95bacff1' \
-H 'x-access-token: fe99035f86fa436181717b302b95bacff1' \
-H 'content-type: application/json' \
-d '{
"general": {
"project_id": "57aff4db-b45d-42bf-bc5f-b7a499a01782",
"payment_id": "UZS-HUMO-123456",
"merchant_callback_url": "https://your-callback-domain.com/internal",
"merchant_success_callback_url": "https://your-callback-domain.com/sucess",
"merchant_decline_callback_url": "https://your-callback-domain.com/decline",
"redirect_url": "https://your-web-site-url.com/order/page"
},
"payment": {
"amount": 1500000,
"currency": "UZS",
"lifetime": 300,
"description": "Comment about the payment",
"extra_param": "example",
"widget_method": "payin-p2p-card",
"payment_system": "humo"
},
"sender": {
"bank_symbol": "sberbank"
},
"customer": {
"id": "random-customer-id",
"ip_address": "1.1.1.1",
"country": "UZ",
"language": "uz",
"customer_type": "ftd",
"email": "[email protected]"
}
}'
Пример ответа:
{
"status": "processing",
"sub_status": "requisites",
"status_description": null,
"request_id": "16a10539-fcb3-4ff5-a3e2-86625a2dc3d3",
"project_id": "57aff4db-b45d-42bf-bc5f-b7a499a01782",
"payment_id": "UZS-HUMO-123456",
"integration": {
"form_url": "https://ppage.hh-processing.com/widget/24a9249ae10e15232c123409b625daf7e0ea627c",
"redirect_url": "https://your-web-site-url.com/order/page"
}
}
Параметры ответа:
status** - статус обработки оплаты. Список статусов можно посмотреть в разделе "Статусы оплат"
(string) (<= 32 символа)sub_status- под-статус обработки платежа. Используется только для определенных статусов оплат. Список под-статусов можно посмотреть в разделе "Статусы оплат"
(string) (<= 32 символа)status_description- дополнительная информация по статусу. Используется в случае, если оплата не прошла, либо произошла ошибка
(string) (<= 1024 символа)request_id** - идентификатор платежа, который генерируется в нашей платежной системе
(string) (<= 32 символа)project_id** - идентификатор кассы, полученный от HH в процессе интеграции
(string) (<= 32 символа)payment_id** - идентификатор платежа, уникальный в рамках кассы мерчанта
(string) (<= 255 символа)integration- дополнительная мета информация по платежуform_url** - ссылка на платежную страницу, на которую можно пере-адресовать пользователя. На платежной странице отображаются реквизиты для оплаты, платёжная инструкция и другая информация необходимая для платежа.
(string<https-url>) (<= 255 символа)redirect_url- cсылка для редиректа пользователя с формы оплаты после завершения платежа
(string<https-url>) (<= 2048 символа)
Поля помеченные
**являются обязательными
Информация о заявке¶
POST https://api.hh-processing.com/api/v1/widget/payin/info
Параметры, которые необходимо отправить в теле запроса для получения статуса p2p заявки.
general** - информация по заявкеproject_id** - идентификатор кассы, полученный от HH в процессе интеграции.
(string) (<= 32 символа)payment_id** - идентификатор платежа.
(string) (<= 255 символа)
Поля помеченные
**являются обязательными
Пример запроса:
curl https://api.hh-processing.com/api/v1/widget/payin/info \
-X POST \
-H 'x-access-timestamp: 1706182847' \
-H 'x-access-merchant-id: 8b03432e-385b-4670-8d06-064591096795' \
-H 'x-access-signature: fe99035f86fa436181717b302b95bacff1' \
-H 'x-access-token: fe99035f86fa436181717b302b95bacff1' \
-H 'content-type: application/json' \
-d '{
"general": {
"project_id": "57aff4db-b45d-42bf-bc5f-b7a499a01782",
"payment_id": "UZS-HUMO-123456"
}
}'
Пример ответа:
{
"status": "processing",
"sub_status": "awaiting_confirm",
"status_description": null,
"request_id": "16a10539-fcb3-4ff5-a3e2-86625a2dc3d3",
"project_id": "57aff4db-b45d-42bf-bc5f-b7a499a01782",
"payment_id": "UZS-HUMO-123456",
"payment_info": {
"amount": 10000,
"old_amount": 10000,
"initial_amount": 3000,
"currency": "UZS",
"lifetime": 300,
"expiration_date": 1721647251,
"method": "card-p2p",
"widget_method": "payin-p2p-card",
"payment_system": "humo",
"type": "payin"
},
"integration": {
"form_url": "https://ppage.hh-processing.com/widget/24a9249ae10e15232c123409b625daf7e0ea627c",
"redirect_url": "https://your-web-site-url.com/order/page"
}
}
Параметры ответа:
status** - статус обработки оплаты. Список статусов можно посмотреть в разделе "Статусы оплат"
(string) (<= 32 символа)sub_status- под-статус обработки платежа. Используется только для определенных статусов оплат. Список под-статусов можно посмотреть в разделе "Статусы оплат"
(string) (<= 32 символа)status_description- дополнительная информация по статусу. Используется в случае, если оплата не прошла, либо произошла ошибка
(string) (<= 1024 символа)request_id** - идентификатор платежа, который генерируется в нашей платежной системе
(string) (<= 32 символа)project_id** - идентификатор кассы, полученный от HH в процессе интеграции
(string) (<= 32 символа)payment_id** - идентификатор платежа, уникальный в рамках кассы мерчанта
(string) (<= 255 символа)payment_info** - информация по оплатеamount** - сумма заявки. Сумма указывается в дробных единицах. Подробнее об этом можно прочитать в разделе "Коды валют";
(integer) (1 <= X <= 10000000000000)old_amount** - сумма заявки до апелляции. Сумма может измениться, если заявка была создана на одну сумму, но пользователь перевёл другую сумму. В таком случае, в полеamountуказывается фактическая сумма, полученная от пользователя (необходимо связаться с тех. поддержкой HH и решить апелляцию по заявке). А в полеold_amountуказывается сумма, на которую был создана заявка изначально. Если сумма не менялась, то значения данных полей будут равны;
(integer) (1 <= X <= 10000000000000)initial_amount** - сумма, указанная при создании заявки. Значение данного поля остаётся неизменным
(integer) (1 <= X <= 10000000000000) ""currency** - код валюты, в которой оплачивает пользователь в формате "ISO-4217 alpha-3". Подробнее о кодах валют в разделе "Коды валют"
(string) (regex: ^[A-Z]{3}$)lifetime- время жизни заявки в секундах. Максимальное время жизни - 10 мин. Если время не указано, то устанавливается значение по умолчанию - 10 мин.
(integer) (300 <= X <= 600)expiration_date- время до которого заявка действительна, значение указывается в "Unix Timestamp (UTC)";.
(integer) (X <= 2^32)method- метод оплаты, который был выбран при создании платежа. Подробнее о методах оплаты можно прочитать в разделе "Поддерживаемые платежные методы"
(string) (<= 32 символа)widget_method- метод платежной страницы, который был выбран для оплаты в виджете. Подробнее о методах платежной страницы можно прочитать в разделе "Поддерживаемые методы платежной страницы"
(string) (<= 32 символа)payment_system- платежная система.
(string) (<= 32 символа)type- тип оплаты, который был выбран при создании платежа. Подробнее о методах оплаты можно прочитать в разделе "Поддерживаемые типы платежей"
(string) (<= 32 символа)
integration- дополнительная мета информация по платежуform_url** - ссылка на платежную страницу, на которую можно пере-адресовать пользователя. На платежной странице отображаются реквизиты для оплаты, платёжная инструкция и другая информация необходимая для платежа.
(string<https-url>) (<= 255 символа)redirect_url- cсылка для редиректа пользователя с формы оплаты после завершения платежа
(string<https-url>) (<= 2048 символа)
Статусы оплат¶
| Статус | Под-статус | Описание | Состояние платежа |
|---|---|---|---|
| error | Платеж не был осуществлен из-за ошибки, возникшей при проверке запроса | Промежуточное состояние | |
| processing | new | Проверка запроса перед непосредственной его обработкой | Промежуточное состояние |
| requisites | Подбор реквизитов, на которые клиенту будет необходимо перечислить указанную в запросе сумму | Промежуточное состояние | |
| awaiting_confirm | Ожидание подтверждения оплаты от клиента, т.к. реквизиты ему уже были предоставлены | Промежуточное состояние | |
| paid | Клиент подтвердил, что он отправил сумму на выданные реквизиты | Промежуточное состояние | |
| dispute | no_payment | Клиент не произвёл оплату по заявке, за время её жизни (lifetime) | Промежуточное состояние |
| different_amount | Клиент отправил неверную сумму | Промежуточное состояние | |
| confirm_timeout | Время жизни заявки истекло, но клиент подтвердил оплату предоставив чек | Промежуточное состояние | |
| decline | Платеж отклонен | Финальное состояние | |
| success | Платеж проведен | Финальное состояние |
Оповещения (callback):¶
Важно, чтобы в вашей системе была реализована логика проверки оповещений на дубликаты. Мы рекомендуем собирать ключ идемпотентности вам самостоятельно по следующему принципу:
{project_id}:{payment_id}:{status}:{sub_status}.
Если вы получается повторные опощения, то система должна их игнорировать, чтобы исключить задвойки.Каждое оповещение подписывается нашей цифровой подписью. Получить текущий публичный ключ для валидации подписи можно в нашей админке. Важно помнить, что ключи для каждой из касс разные.
Алгоритм валидации цифр. подписи ровно-противоположен её созданию при отправке запросов на наш API. Ниже будет пример кода для валидации оповещений
У p2p платежей есть 3 типа оповещений:
- Информативные - оповещения по промежуточным статусам заявок. Оповещение отправляется, если у заявки меняется статус. URL для отправки оповещений указывается при создании заявки в параметре
merchant_callback_url - Успешные - оповещения по успешным заявкам. Оповещение отравляется, если заявка завершена успешно. URL для отправки оповещений указывается при создании заявки в параметре
merchant_success_callback_url - Неуспешные - оповещения по неуспешным заявкам. Оповещение отправляется, если в процессе обработки заявки возникла ошибка, либо время жизни заявки истекло. URL для отправки оповещений указывается при создании заявки в параметре
merchant_decline_callback_url
Информативные оповещения¶
Пример оповещения со статусом processing:awaiting_confirm.
{
"project_id": "57aff4db-b45d-42bf-bc5f-b7a499a01782",
"general": {
"request_id": "16a10539-fcb3-4ff5-a3e2-86625a2dc3d3",
"payment_id": "UZS-HUMO-123456"
},
"status": {
"status": "processing",
"sub_status": "awaiting_confirm",
"status_description": null
},
"payment_info": {
"amount": 7000,
"old_amount": 7000,
"initial_amount": 3000,
"currency": "UZS",
"lifetime": 300,
"expiration_date": 1721647251,
"updated_date": 1721647251,
"created_date": 1721647251,
"method": "card-p2p",
"widget_method": "payin-p2p-card",
"payment_system": "humo",
"type": "payin"
},
"recipient_requisites": {
"pan_hidden": "2202****6980",
"card_holder_hidden": "Ко****ов",
"bank_name": "NBU",
"bank_country": "UZ",
"currency": "UZS"
},
"integration": {
"form_url": "https://ppage.hh-processing.com/widget/24a9249ae10e15232c123409b625daf7e0ea627c",
"redirect_url": "https://your-web-site-url.com/order/page"
}
}
"Замыленные" реквизиты отправляются в колбэках, но только для статусов:
processing:awaiting_confirmиprocessing:paid.
В случае, если статус заявки другой, то реквизиты не будут отправлены. Пример:"recipient_requisites": null.
Успешные оповещения¶
Данное оповещение отправляется в том случае, если заявка приняла успешное финальное состояние - статус success. Пример оповещения показан ниже.
{
"project_id": "57aff4db-b45d-42bf-bc5f-b7a499a01782",
"general": {
"request_id": "16a10539-fcb3-4ff5-a3e2-86625a2dc3d3",
"payment_id": "UZS-HUMO-123456"
},
"status": {
"status": "success",
"sub_status": null,
"status_description": null
},
"payment_info": {
"amount": 7000,
"old_amount": 5000,
"initial_amount": 3000,
"currency": "UZS",
"lifetime": 300,
"expiration_date": 1721647251,
"updated_date": 1721647251,
"created_date": 1721647251,
"method": "card-p2p",
"widget_method": "payin-p2p-card",
"payment_system": "humo",
"type": "payin"
}
}
Неуспешные оповещения¶
Данное оповещение отправляется в том случае, если заявка приняла неуспешное финальное состояние - статус decline. Пример оповещения показан ниже.
{
"project_id": "57aff4db-b45d-42bf-bc5f-b7a499a01782",
"general": {
"request_id": "16a10539-fcb3-4ff5-a3e2-86625a2dc3d3",
"payment_id": "UZS-HUMO-123456"
},
"status": {
"status": "decline",
"sub_status": null,
"status_description": "Declined by anti-fraud"
},
"payment_info": {
"amount": 7000,
"old_amount": 7000,
"initial_amount": 3000,
"currency": "UZS",
"lifetime": 300,
"expiration_date": 1721647251,
"updated_date": 1721647251,
"created_date": 1721647251,
"method": null,
"widget_method": null,
"payment_system": null,
"type": "payin"
}
}
Примеры кода¶
Пример кода Python3, для принятия оповещений и проверки их цифровой подписи
import json
import base64
from Crypto.Hash import SHA256
from Crypto.PublicKey import RSA
from Crypto.Signature.pkcs1_15 import PKCS115_SigScheme
from fastapi import FastAPI, Request, Response
from uvicorn import run
app = FastAPI()
pub_key_file_path = "./public.pem"
with open(pub_key_file_path, "rb") as f:
encoded_pub_key = base64.urlsafe_b64encode(
RSA.importKey(f.read()).export_key(),
).decode('utf-8')
def parse_json(prefix, obj, _result):
if isinstance(obj, dict):
for key, value in obj.items():
new_prefix = f"{prefix}:{key}" if prefix else key
parse_json(new_prefix, value, _result)
elif isinstance(obj, list):
for index, item in enumerate(obj):
new_prefix = f"{prefix}:{index}"
parse_json(new_prefix, item, _result)
else:
_result.append(f"{prefix}:{obj or 'None'}")
def normalize_message(_payload):
_result = []
parse_json('', _payload, _result)
_result.sort()
_joined_result = ";".join(_result)
return _joined_result
@app.route("/callback", methods=["POST", "GET"])
async def validate_request(
request: Request,
):
_headers = request.headers
body = await request.body()
if not body:
payload = {}
else:
payload = json.loads(body.decode("utf-8"))
joined_result = normalize_message(payload).encode("utf-8")
message = "{}{}".format(
base64.urlsafe_b64encode(joined_result).decode("utf-8"),
str(
_headers.get("x-access-timestamp"),
),
)
if _headers.get("x-access-token") != encoded_pub_key:
raise ValueError("Invalid public key")
signature = _headers.get("x-access-signature")
pub_key = base64.urlsafe_b64decode(
encoded_pub_key.encode("utf-8"),
)
pub_key_rsa = RSA.importKey(pub_key)
hash_of_received = SHA256.new(message.encode("utf-8"))
verifier = PKCS115_SigScheme(pub_key_rsa)
try:
base64_bytes = signature.encode("ascii")
signature_bytes = base64.urlsafe_b64decode(base64_bytes)
verifier.verify(hash_of_received, signature_bytes)
except ValueError:
raise ValueError("Invalid signature")
return Response(status_code=200)
if __name__ == '__main__':
run(app, host="0.0.0.0", port=8080)