Аутентификация
Регистрация в системе¶
Регистрация в системе происходит через админ панель, доступ до которой вам выдаёт наш специалист. После входа в админку, вам необходимо сгенерировать пару RSA ключей (публичный и приватный). Для этого вам нужно:
- Создать кассу, перейдя во вкладку "Кассы"
- Обратиться к прикреплённому к вам специалисту для того, чтобы мы настроили вашу новую кассу и провели верификацию
- После того, как касса будет настроена и верифицирована, вам необходимо сгенерировать ключи
- Перейти во вкладку "API", найти созданную кассу и нажать на "Сгенерировать ключ"
- В открывшейся модалке будет указано название кассы, URL вашего продукта и вам будет необходимо нажать на "Сгенерировать ключ"
- Скопировать и сохранить значения из полей
UUIDиPrivate keyUUID- идентификатор вашей кассы. Он будет необходим при взаимодействии с нашим API;Private key- приватный RSA ключ в PEM формате. Ключ будет вам необходим для создания цифровой подписи при взаимодействии с нашим API. Важная оговорка, данный ключ мы генерируем на клиентской стороне, т.е. в браузере. Мы не сохраняем данный ключ у себя, поэтому это безопасно. Мы сохраняем лишь публичный ключ, т.к. он нам необходим для проверки цифровой подписи в ваших запросах;
- Передать отделу разработки/devops оба секрета (
uuidиprivate key)
Аутентификация в API¶
HH использует следующие заголовки для аутентификации:
x-access-timestamp: timestamp запросаx-access-merchant-id: идентификатор кассы. Получен при создании кассы и генерации ключей для неё. В примере кода ниже, этот заголовок указывается в переменнойproject_idx-access-signature: конкатенация тела http запроса в Base64Url и timestamp'а, подписанная цифровой подписью от полученной строки, предварительно захешированные sha256:sha256(base64url(body) + str(timestamp))x-access-token: Base64Url закодированный public key из RSA-SHA256 пары
Примеры кода¶
Пример кода на Python3
import base64
import json
import time
import requests
from Crypto.Hash import SHA256
from Crypto.PublicKey import RSA
from Crypto.Signature.pkcs1_15 import PKCS115_SigScheme
url = "https://api.hh-processing.com/api/v1/payment/p2p/payin"
# Идентификатор кассы. Получен при создании кассы и генерации ключей для неё
project_id = "57aff4db-b45d-42bf-bc5f-b7a499a01782"
# Путь до файла с приватным ключом, который вы получили в амдинке
private_key_path = "./private.pem"
payload = {
"general": {
"project_id": project_id
}
}
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
with open(private_key_path, 'rb') as f:
private_key = RSA.importKey(f.read())
public_key = private_key.public_key().export_key()
api_key = base64.urlsafe_b64encode(public_key).decode('utf-8')
timestamp = int(time.time())
if payload:
dumped = json.dumps(payload, separators=(",", ":"))
else:
dumped = "{}"
joined_result = normalize_message(payload)
message = "{}{}".format(
base64.urlsafe_b64encode(joined_result.encode()).decode("utf-8"),
str(timestamp),
).encode('utf-8')
# Create the signature
signer = PKCS115_SigScheme(private_key)
signature = signer.sign(SHA256.new(message))
base64_sign = base64.urlsafe_b64encode(signature).decode('ascii')
# Prepare the request
headers = {
'content-type': 'application/json',
'x-access-token': api_key,
'x-access-signature': base64_sign,
'x-access-merchant-id': project_id,
'x-access-timestamp': str(timestamp),
}
if payload:
response = requests.post(
url,
headers=headers,
data=dumped,
)
else:
response = requests.get(
url,
headers=headers,
)
# Print the response status
print(response.status_code)