Подписание запросов
Запросы на формирование заказа и подтверждение оказания услуг должны содержать в заголовках подпись, которая формируется при помощи RSA (OpenSSL) ключа. Для проверки корректности подписания запросов от площадки, нужно предоставить публичный (открытый) ключ с соответствующими документами, сопровождающими этот ключ:
- Акт приёма-передачи Открытого ключа
- Соглашение на использование сервиса
Для рабочего слоя с реализацией подписания через OpenSSL ключ должен соответствовать формату RSA и содержать данные юр. лица, которые представляют площадку (в ключе должен содержаться электронный адрес компании и её наименование или ФИО ИП). Срок действия RSA ключа - от 365 до 1825 дней (не более 5 лет).
Создание приватного ключа
Для каждого слоя нужно генерировать отдельный сформированный приватный ключ и сертификат. Приватную часть никому нельзя передавать.
openssl genrsa -out rsaprivkey.pem 2048
Создание публичного ключа
Формирование публичного сертификата на основе приватного ключа
openssl req -days 1825 -new -x509 -key rsaprivkey.pem -out rsaacert.pem
Параметр days задает нужный срок действия в днях. Его нужно передать сотрудникам банка, отвечающим за сервис
Файл rsaacert.pem содержит публичную часть ключа, которая выглядит так:
-----BEGIN CERTIFICATE-----
MIIDazCCAlOgAwIBAgIUOMamoGWXd5FATOQzf74j2tP6tWAwDQYJKoZIhvcNAQEL
...
-----END CERTIFICATE-----
Подписание запроса
Формируем запрос в виде строки следующего формата:
'{"orderExtId": "string", "orderCommission": "string", "IncomingPayment": {"type": "string", "redirectUrl": "string", "redirectFailUrl": "string", "paymentUrlTtl": 0, "purpose": "string"}, "Services": [{"extId": "string", "price": "string", "Recipient": {"extId": "string", "method": "string", "cardExtId": "string"}, "startDecision": "string"}]}'
Без переносов и табуляций
Ключ и значение разделяются двоеточием и одним пробелом (": ")
Пары ключей и значений разделяются запятой и одним пробелом (", ")
Пример кода на python, который формирует корректную строку
import json
request_payload = {
"orderExtId": "string",
"orderCommission": "string",
"IncomingPayment": {
"type": "string",
"redirectUrl": "string",
"redirectFailUrl": "string",
"paymentUrlTtl": 0,
"purpose": "string"
},
"Services": [
{
"extId": "string",
"price": "string",
"Recipient": {
"extId": "string",
"method": "string",
"cardExtId": "string"
},
"startDecision": "string"
}
]
}
sign_payload = json.dumps(request_payload) # Сообщение для подписи
print(sign_payload)
Пример формирования подписи через командную строку
Помещаем сформированную строку с запросом в файл message
echo -n '{"orderExtId": "string", "orderCommission": "string", "IncomingPayment": {"type": "string", "redirectUrl": "string", "redirectFailUrl": "string", "paymentUrlTtl": 0, "purpose": "string"}, "Services": [{"extId": "string", "price": "string", "Recipient": {"extId": "string", "method": "string", "cardExtId": "string"}, "startDecision": "string"}]}' > message
Подписание сообщения. Используем алгоритм sha256. Это создаст бинарный файл message.sgn, содержащий подпись.
openssl dgst -sha256 -sign ./rsaprivkey.pem -out ./message.sgn ./message
base64 message.sgn
Получаем вывод формата
FZsN/3QUwpcl8JCh8jrO/jFZwXAesQEDTBmD3F2L+sB++OY9XpguZ5vAXFifMku9b1HRsvaEIjnxhDOMAGtC6M8DP8439UIjK3kPiVhq0LzROWQrYqxpdJl53RGff8A95OuDlzVVx3PUWoEGj2FBczEEQKl5rDs+YHjG7hJq6oOLHzNcN5vFYgGk2swn0G+usTx0Fox+JyqgobycZXYNBIGylh64f2mZ1FjoTulzfsrgZilSejapsrfKSCiohg4C4SmUU8bcp/cgYSqGrPLw8oe2o7Ads2c1/omVWodw8RGcDu+m21fhFlAjbVUyhFByvGWGz1dahThQfRgyvGMOQw==
Отправляем запрос.
Указываем идентификатор ключа, которым формировалась подпись в заголовке Sign-Key-Id. Его передаст сотрудник банка при передаче ключа.
Указываем подпись в формате base64 в заголовке Sign-Body
В Sign-Body не должно быть никаких переносов или каких-либо других лишних символов
curl --location '[http://stage-uapi-dcdp.bank24.int/uapi/medusa/v1.0/orders](http://stage-uapi-dcdp.bank24.int/uapi/medusa/v1.0/orders)' \
--header 'Sign-Body: 'FZsN/3QUwpcl8JCh8jrO/jFZwXAesQEDTBmD3F2L+sB++OY9XpguZ5vAXFifMku9b1HRsvaEIjnxhDOMAGtC6M8DP8439UIjK3kPiVhq0LzROWQrYqxpdJl53RGff8A95OuDlzVVx3PUWoEGj2FBczEEQKl5rDs+YHjG7hJq6oOLHzNcN5vFYgGk2swn0G+usTx0Fox+JyqgobycZXYNBIGylh64f2mZ1FjoTulzfsrgZilSejapsrfKSCiohg4C4SmUU8bcp/cgYSqGrPLw8oe2o7Ads2c1/omVWodw8RGcDu+m21fhFlAjbVUyhFByvGWGz1dahThQfRgyvGMOQw\==' \
--header 'Sign-Key-Id: 66019375-5ae8-4618-bf10-919547a269df' \
--header 'Content-Type: application/json' \
--header 'Authorization: ••••••' \
--data-binary @'./message'
Пример формирования подписи через код на python
Для выполнения данного кода необходимо по инструкции выше сформировать приватный ключ rsaprivkey.pem и установить библиотеки pycryptodome и httpx:
pip install pycryptodome
pip install httpx
import base64
import json
import httpx
from Crypto.Hash import SHA256
from Crypto.PublicKey import RSA
from Crypto.PublicKey.RSA import RsaKey
from Crypto.Signature import PKCS1_v1_5
from httpx import BasicAuth
def sign(message: bytes, private_key_: RsaKey) -> bytes:
signer = PKCS1_v1_5.new(private_key_)
data_hash = SHA256.new(message)
return signer.sign(data_hash)
with open('rsaprivkey.pem', 'rb') as key_file:
private_key = RSA.import_key(key_file.read())
request_payload = {
"orderExtId": "string",
"orderCommission": "string",
"IncomingPayment": {
"type": "string",
"redirectUrl": "string",
"redirectFailUrl": "string",
"paymentUrlTtl": 0,
"purpose": "string"
},
"Services": [
{
"extId": "string",
"price": "string",
"Recipient": {
"extId": "string",
"method": "string",
"cardExtId": "string"
},
"startDecision": "string"
}
]
}
sign_payload = json.dumps(request_payload) # body запроса в корректном строковом формате
sign_body = sign(sign_payload.encode('utf-8'), private_key) # Подпись запроса
encoded_sign_body = base64.b64encode(sign_body).decode() # Подпись запроса в base_64
response = httpx.post(
'http://stage-uapi-dcdp.bank24.int/uapi/medusa/v1.0/orders',
json=request_payload,
headers={
'Sign-Key-Id': 'Указать идентификатор ключа',
'Sign-Body': encoded_sign_body,
},
auth=BasicAuth(username='Указать логин', password='Указать пароль'),
)