Код который у меня работает! Пользуйтесь на здоровье!
import win32com.client
import base64
import pythoncom
import json
import requests
def signed_data(_data):
# Функция подписывает данные открепленной подписью
# Возращает обратно данные которые подписаны, и открепленную подпись
CADES_BES = 1
CAPICOM_ENCODE_BASE64 = 0
CAPICOM_CURRENT_USER_STORE = 2
CAPICOM_MY_STORE = "My"
CAPICOM_STORE_OPEN_MAXIMUM_ALLOWED = 2
sSerialNumber = "SERIAL_NUMBER" # ID ключа, берется из крипто-про
# Инструменты криптопро -> контейнеры -> Найти нужный ключ (не просроченный, видно при тестировании контейнера) -> Протестировать контейнер -> серийный номер
# Ищем сертификат в хранилище
oCert = None
oStore = win32com.client.Dispatch("CAdESCOM.Store", pythoncom.CoInitialize())
oStore.Open(CAPICOM_CURRENT_USER_STORE, CAPICOM_MY_STORE, CAPICOM_STORE_OPEN_MAXIMUM_ALLOWED)
for val in oStore.Certificates:
if val.SerialNumber.upper() == sSerialNumber.upper():
oCert = val
oStore.Close
if not oCert:
print("Не найден сертификат в хранилище")
return None
oSigner = win32com.client.Dispatch("CAdESCOM.CPSigner", pythoncom.CoInitialize())
oSigner.Certificate = oCert
# Строка JSON БЕЗ ПРОБЕЛОВ
message = _data
message_bytes = message.encode()
base64_bytes = base64.b64encode(message_bytes)
base64_message = base64_bytes.decode()
signedData = win32com.client.Dispatch("CAdESCOM.CadesSignedData", pythoncom.CoInitialize())
signedData.ContentEncoding = 1
signedData.Content = base64_message
sSignedData = signedData.SignCades(oSigner, CADES_BES, True, CAPICOM_ENCODE_BASE64)
# Удаляем из подписи символы переноса строки, иначе не вставить в заголовок запроса
sSignedData = sSignedData.replace('\r', '')
sSignedData = sSignedData.replace('\n', '')
return _data, sSignedData
# token выдается при авторизации по URL <url стенда>/auth/simpleSignIn/{omsConnection}
# Статья есть на хабре.
headers = {"clientToken": "token", "Accept": "application/json", 'Content-type': 'application/json'}
# oms_id - Находим в личном кабинете - управление заказами - устройства - OMS ID:
query_params = {"omsId": "oms_id"}
# Заполнение поля products я пропущу, оно хорошо описано в документации к СУЗ
body = {
"productGroup": "lp",
"attributes": {
"releaseMethodType": "PRODUCTION",
"createMethodType": "SELF_MADE",
},
"products": [],
}
# Переводим словарь в JSON БЕЗ ПРОБЕЛОВ!
json_str = json.dumps(body, separators=(',', ':'))
sData, signed = signed_data(json_str) # получаем подпись
headers["X-Signature"] = signed
# Так же в тело запроса отправляем этот JSON который подписывали без пробелов!
response = requests.post(f"https://suz.sandbox.crptech.ru/api/v3/order", params=query_params, headers=headers, data=sData)
if response.status_code == 200:
response.json()