Работа с подписью к данным

Общая информация

Для обеспечения защищённого обмена данными при работе с платёжной платформой ecommpay используется криптографический протокол TLS (Transport Layer Security; протокол защиты транспортного уровня) версии не ниже 1.2, а для подтверждения авторства и целостности передаваемых данных дополнительно применяется цифровая подпись.

Цифровая подпись формируется и проверяется по заданным алгоритмам с использованием одинакового секретного ключа, доступного на двух сторонах: мерчанта и ecommpay. Независимо от интерфейса, используемого при работе с платформой, подпись обязательна к включению в состав всех программных запросов, отправляемых от веб-сервиса к платёжной платформе, а также всех оповещений и ряда ответов, отправляемых от платёжной платформы к веб-сервису. Поэтому перед отправкой любого запроса в платформу необходимо сформировать подпись и включить её в состав этого запроса, а при получении ответов и оповещений от платформы следует проверять целостность данных путём сличения расчётных подписей с полученными. Для этого можно использовать как собственные программные решения, так и SDK от ecommpay (подробнее).

Алгоритмы подписывания данных и проверки их целостности, а также примеры выполнения этих алгоритмов и интерактивные формы для самостоятельной проверки корректной работы с подписью к разным данным при использовании программных интерфейсов ecommpay, представлены далее.

Подписывание данных

Описание алгоритма

В качестве входных данных для подписывания выступают:

  1. Данные, которые требуется подписать.

    Как правило, это заполненное тело запроса, все параметры запроса за исключением подписи или JavaScript-объект configObj с параметрами без включения параметра signature.

  2. Ключ, используемый для подписывания.
    Прим.: Для работы с Data API должны использоваться ключи, получаемые через интерфейс Dashboard в связке с токенами. (Подробнее в разделе Порядок доступа к данным.)

    Для отладки и тестирования могут использоваться произвольные ключи, а для рабочих запросов в платформу — только актуальный секретный ключ.

В качестве выходных данных подписывания в зависимости от реализации алгоритма могут выступать либо подпись, либо подписанные данные — как правило, это итоговый объект или итоговое тело запроса в формате JSON с параметром signature, включённым в его состав.

Далее в описании, примерах и формах для тестирования представлен наиболее показательный вариант реализации алгоритма, актуальный при работе с интерфейсами Payment Page API, Gate API и Data API.

В состав алгоритма в этом случае включаются следующие шаги:

  1. Проверка входных данных на соблюдение заданных требований:

    1. Структура данных для подписывания должна соответствовать формату JSON. При работе с Payment Page также можно использовать JavaScript-объекты.
    2. В составе данных для подписывания не должен присутствовать параметр signature (даже с пустым значением).
    3. Должен быть задан ключ.
  2. Преобразование данных в строку UTF-8 с сортировкой параметров в естественном порядке. В рамках этого шага выполняются следующие действия:

    1. Логические (булевы) значения кодируются следующим образом: false заменяется на 0, а true — на 1. Но это относится только к булевым значениям — в строковых параметрах, даже если они содержат значения false или true, замены на 0 или 1 не используются (например, в параметре recurring: "{type: \"U\",register: true}" замена true на 1 не требуется).
    2. Каждый параметр преобразуется в строку, содержащую полный путь к параметру, название параметра и его значение:
      <родительский_узел_1>:...:<родительский_узел_N>:<название_параметра>:<значение_параметра>

      где родительские узлы — это названия объектов и (или) массивов, в состав которых включена пара «название параметра — значение параметра». Родительские узлы располагаются в порядке их вложения, начиная с самого верхнего уровня. В качестве разделителя при этом используется двоеточие (:), между парами «название параметра — значение параметра» удаляются запятые, а у строковых значений параметров удаляются обрамляющие кавычки.

    3. Параметры с нулевыми, а также пустыми значениями остаются в строке, например запись "payment_description":"" представляется в виде payment_description:. Замены пустых значений на пробелы или null не применяются.
    4. Элементы массивов записываются отдельными строками, с указанием номера каждого элемента, начиная с нуля. Например, массив ["alpha", "beta", "gamma"] представляется в виде трёх строк: 0:alpha, 1:beta и 2:gamma.
    5. Пустые массивы полностью игнорируются и не включаются в набор строк для создания подписи.
    6. Кодировка всех строк приводится к формату UTF-8.
    7. Полученные строки упорядочиваются в естественном порядке и объединяются в одну строку с использованием в качестве разделителя точки с запятой (;).
  3. Получение двоичного кода HMAC с использованием ключа и функции SHA-512. На этом шаге для полученной строки с параметрами вычисляется HMAC (Hash-based Message Authentication Code; код аутентификации сообщений с использованием хеш-функции) с использованием функции хеширования SHA‑512 (Secure Hash Algorithm; безопасный алгоритм хеширования) и применяемого ключа. И этот HMAC представляется в виде необработанных двоичных данных.
  4. Кодирование двоичного кода HMAC с применением алгоритма Base64. На этом шаге полученный двоичный код HMAC кодируется с использованием алгоритма Base64. Получаемая при этом строка является подписью к исходным данным.
  5. Добавление подписи к данным. На этом шаге к исходным данным для подписывания добавляется параметр signature с полученной подписью в качестве его значения.

Пример для запроса на оплату через Payment Page

Допустим, что надо подписать запрос на открытие Payment Page при следующих условиях:

  • Используемый ключ — secret
  • Предварительная версия объекта configObj, в котором еще нет значения параметра с подписью, выглядит так:
    {
    "project_id": 12345, 
    "payment_id": "X03936", 
    "payment_amount": 2035, 
    "payment_currency": "USD",
    "payment_description": "Guyliner purchase",
    "customer_first_name": "Jack",
    "customer_id": "user007",
    "customer_last_name": "Sparrow",
    "customer_phone": "02081234567",
    "close_on_missclick": true,
    "signature": "<подпись, которую нужно создать>" 
    }

Задача заключается в том, чтобы вычислить подпись, то есть определить значение параметра signature. Для этого необходимо:

  1. Убедиться, что в теле запроса нет параметра signature, даже с пустым значением. Если такой параметр есть, его нужно удалить:
    {
    "project_id": 12345, 
    "payment_id": "X03936", 
    "payment_amount": 2035, 
    "payment_currency": "USD",
    "payment_description": "Guyliner purchase",
    "customer_first_name": "Jack",
    "customer_id": "user007",
    "customer_last_name": "Sparrow",
    "customer_phone": "02081234567",
    "close_on_missclick": true,
    "signature": "<подпись, которую нужно создать>" 
    }
  2. Преобразовать оставшиеся параметры в строки UTF-8 согласно правилам алгоритма:
    project_id:12345 
    payment_id:X03936
    payment_amount:2035
    payment_currency:USD
    payment_description:Guyliner purchase
    customer_first_name:Jack
    customer_id:user007
    customer_last_name:Sparrow
    customer_phone:02081234567
    close_on_missclick:1
  3. Отсортировать полученные строки в естественном порядке:
    close_on_missclick:1
    customer_first_name:Jack
    customer_id:user007
    customer_last_name:Sparrow
    customer_phone:02081234567
    payment_amount:2035
    payment_currency:USD
    payment_description:Guyliner purchase
    payment_id:X03936
    project_id:12345
    
  4. Объединить отсортированные строки в одну строку с использованием в качестве разделителя точки с запятой:
    close_on_missclick:1;customer_first_name:Jack;customer_id:user007;customer_last_name:Sparrow;customer_phone:02081234567;payment_amount:2035;payment_currency:USD;payment_description:Guyliner purchase;payment_id:X03936;project_id:12345
  5. Вычислить HMAC полученной строки с использованием функции хеширования SHA-512 и используемого ключа, после чего кодировать двоичный код HMAC с применением алгоритма Base64:
    SyA3cx/dmFrwjRcpbnwEK9zaklWKR9buIfTctQob/EHUTutFLpI0zWpSDFEWEwbZt/04i83395RCdEhtUMw83A==
  6. Добавить полученную подпись в объект configObj:
    {
    "project_id": 12345, 
    "payment_id": "X03936", 
    "payment_amount": 2035, 
    "payment_currency": "USD",
    "payment_description": "Guyliner purchase",
    "customer_first_name": "Jack",
    "customer_id": "user007",
    "customer_last_name": "Sparrow",
    "customer_phone": "02081234567",
    "close_on_missclick": true,
    "signature": "SyA3cx/dmFrwjRcpbnwEK9zaklWKR9buIfTctQob/EHUTutFLpI0zWpSDFEWEwbZt/04i83395RCdEhtUMw83A==" 
    }

Далее представлена интерактивная форма для самостоятельной проверки корректной работы с подписью при отправке запросов на открытие Payment Page.

Прим.:

Для корректной работы с параметрами реальных запросов следует учитывать требования к кодированию вложенных объектов, представленные в статье Параметры вызова платёжной формы и в статьях с описанием возможностей платёжной формы. При указании вложенных объектов, не соответствующих таким требованиям, подпись в форме тестирования рассчитывается в соответствии с алгоритмом, но не может использоваться для реальных запросов, поскольку оказывается сформированной на некорректных входных данных.

Пример для запроса на оплату через Gate

Допустим, что надо подписать запрос в Gate при следующих условиях:

  • Используемый ключ — secret
  • Предварительная версия тела запроса, в котором еще нет значения параметра с подписью, выглядит так:
    {
        "general": {
            "project_id": 3254,
            "payment_id": "id_38202316",
           "signature": "<подпись, которую нужно создать>"
        },
        "customer": {
            "id": "585741",
            "email": "johndoe@mycompany.com",
            "first_name": "John",
            "last_name": "Doe",
            "address": "Downing str., 23",
            "identify": {
                "doc_number": "54122312544"
            },
            "ip_address": "111.222.333.444"
        },
        "payment": {
            "amount": 10800,
            "currency": "USD",
            "description": "Computer keyboards"
        },
        "receipt_data": {
            "positions": [
                {
                    "quantity": "10",
                    "amount": "108",
                    "description": "Computer keyboard"
                }
            ]
        },
        "return_url": {
            "success": "https://paymentpage.mycompany.com/complete-redirect?id=success",
            "decline": "https://paymentpage.mycompany.com/complete-redirect?id=decline"
        }
    }

Задача заключается в том, чтобы вычислить подпись, то есть рассчитать значение параметра signature и добавить его в запрос. Для этого необходимо:

  1. Убедиться, что в теле запроса нет параметра signature, даже с пустым значением. Если такой параметр есть, его нужно удалить.
    {
        "general": {
            "project_id": 3254,
            "payment_id": "id_38202316",
           "signature": "<подпись, которую нужно создать>"
        },
        "customer": {
            "id": "585741",
            "email": "johndoe@mycompany.com",
            "first_name": "John",
            "last_name": "Doe",
            "address": "Downing str., 23",
            "identify": {
                "doc_number": "54122312544"
            },
            "ip_address": "111.222.333.444"
        },
        "payment": {
            "amount": 10800,
            "currency": "USD",
            "description": "Computer keyboards"
        },
        "receipt_data": {
            "positions": [
                {
                    "quantity": "10",
                    "amount": "108",
                    "description": "Computer keyboard"
                }
            ]
        },
        "return_url": {
            "success": "https://paymentpage.mycompany.com/complete-redirect?id=success",
            "decline": "https://paymentpage.mycompany.com/complete-redirect?id=decline"
        }
    }
  2. Преобразовать оставшиеся параметры в строки UTF-8 согласно правилам алгоритма:
    general:project_id:3254
    general:payment_id:id_38202316
    customer:id:585741
    customer:email:johndoe@mycompany.com
    customer:first_name:John
    customer:last_name:Doe
    customer:address:Downing str., 23
    customer:identify:doc_number:54122312544
    customer:ip_address:111.222.333.444
    payment:amount:10800
    payment:currency:USD
    payment:description:Computer keyboards
    receipt_data:positions:0:quantity:10
    receipt_data:positions:0:amount:108
    receipt_data:positions:0:description:Computer keyboard
    return_url:success:https://paymentpage.mycompany.com/complete-redirect?id=success
    return_url:decline:https://paymentpage.mycompany.com/complete-redirect?id=decline
  3. Отсортировать полученные строки в естественном порядке:
    customer:address:Downing str., 23
    customer:email:johndoe@mycompany.com
    customer:first_name:John
    customer:id:585741
    customer:identify:doc_number:54122312544
    customer:ip_address:111.222.333.444
    customer:last_name:Doe
    general:payment_id:id_38202316
    general:project_id:3254
    payment:amount:10800
    payment:currency:USD
    payment:description:Computer keyboards
    receipt_data:positions:0:amount:108
    receipt_data:positions:0:description:Computer keyboard
    receipt_data:positions:0:quantity:10
    return_url:decline:https://paymentpage.mycompany.com/complete-redirect?id=decline
    return_url:success:https://paymentpage.mycompany.com/complete-redirect?id=success
    
  4. Объединить отсортированные строки в одну строку с использованием в качестве разделителя точки с запятой:
    customer:address:Downing str., 23;customer:email:johndoe@mycompany.com;customer:first_name:John;customer:id:585741;customer:identify:doc_number:54122312544;customer:ip_address:111.222.333.444;customer:last_name:Doe;general:payment_id:id_38202316;general:project_id:3254;payment:amount:10800;payment:currency:USD;payment:description:Computer keyboards;receipt_data:positions:0:amount:108;receipt_data:positions:0:description:Computer keyboard;receipt_data:positions:0:quantity:10;return_url:decline:https://paymentpage.mycompany.com/complete-redirect?id=decline;return_url:success:https://paymentpage.mycompany.com/complete-redirect?id=success
  5. Вычислить HMAC полученной строки с использованием функции хеширования SHA-512 и используемого ключа, после чего кодировать двоичный код HMAC с применением алгоритма Base64:
    VLLZzVNGevQNhr1b4TEhbC4qqHD17Kyn/M6FPNN93ttyk/amJgD/R6dayTKVvW6/QCRdq4hOf8R2w/xbUa8f2w==
  6. Добавить полученную подпись в тело запроса:
    {
        "general": {
            "project_id": 3254,
            "payment_id": "id_38202316",
           "signature": "VLLZzVNGevQNhr1b4TEhbC4qqHD17Kyn/M6FPNN93ttyk/amJgD/R6dayTKVvW6/QCRdq4hOf8R2w/xbUa8f2w=="
        },
        "customer": {
            "id": "585741",
            "email": "johndoe@mycompany.com",
            "first_name": "John",
            "last_name": "Doe",
            "address": "Downing str., 23",
            "identify": {
                "doc_number": "54122312544"
            },
            "ip_address": "111.222.333.444"
        },
        "payment": {
            "amount": 10800,
            "currency": "USD",
            "description": "Computer keyboards"
        },
        "receipt_data": {
            "positions": [
                {
                    "quantity": "10",
                    "amount": "108",
                    "description": "Computer keyboard"
                }
            ]
        },
        "return_url": {
            "success": "https://paymentpage.mycompany.com/complete-redirect?id=success",
            "decline": "https://paymentpage.mycompany.com/complete-redirect?id=decline"
        }
    }

Далее представлена интерактивная форма для самостоятельной проверки корректной работы с подписью при отправке запросов к Gate API.

Пример для запроса на получение данных через Data API

Допустим, что надо подписать запрос в Dashboard при следующих условиях:

  • Используемый ключ — secret
  • Предварительная версия тела запроса, в котором еще нет значения параметра с подписью, выглядит так:
    {
      "token": "WKiarERJ5pcceNerpM9R5TNnyPTQMl",
      "interval": {
        "from": "2020-01-01 14:53:55",
        "to": "2020-01-30 13:53:59"
      },
      "project_id": [
        183
      ],
      "limit": 3,
      "offset": 0,
      "tz": "Asia/Singapore",
     "signature": "<подпись, которую нужно создать>"
    }

Задача заключается в том, чтобы вычислить подпись, то есть рассчитать значение параметра signature и добавить его в запрос. Для этого необходимо:

  1. Убедиться, что в теле запроса нет параметра signature, даже с пустым значением. Если такой параметр есть, его нужно удалить.
    {
      "token": "WKiarERJ5pcceNerpM9R5TNnyPTQMl",
      "interval": {
        "from": "2020-01-01 14:53:55",
        "to": "2020-01-30 13:53:59"
      },
      "project_id": [
        183
      ],
      "limit": 3,
      "offset": 0,
      "tz": "Asia/Singapore",
     "signature": "<подпись, которую нужно создать>"
    }
  2. Преобразовать оставшиеся параметры в строки UTF-8 согласно правилам алгоритма:
    token:WKiarERJ5pcceNerpM9R5TNnyPTQMl
    interval:from:2020-01-01 14:53:55
    interval:to:2020-01-30 13:53:59
    project_id:0:183
    limit:3
    offset:0
    tz:Asia/Singapore
  3. Отсортировать полученные строки в естественном порядке:
    interval:from:2020-01-01 14:53:55
    interval:to:2020-01-30 13:53:59
    limit:3
    offset:0
    project_id:0:183
    token:WKiarERJ5pcceNerpM9R5TNnyPTQMl
    tz:Asia/Singapore
    
  4. Объединить отсортированные строки в одну строку с использованием в качестве разделителя точки с запятой:
    interval:from:2020-01-01 14:53:55;interval:to:2020-01-30 13:53:59;limit:3;offset:0;project_id:0:183;token:WKiarERJ5pcceNerpM9R5TNnyPTQMl;tz:Asia/Singapore
  5. Вычислить HMAC полученной строки с использованием функции хеширования SHA-512 и используемого ключа, после чего кодировать двоичный код HMAC с применением алгоритма Base64:
    Ini3aKje6aZskajTuRS761YOzVqierlVRafZdxIz48wmVnL7yxgy9vDsp7T2/LGPGHJ/DHoKOgP7VqObJALrUA==
  6. Добавить полученную подпись в тело запроса:
    {
      "token": "WKiarERJ5pcceNerpM9R5TNnyPTQMl",
      "interval": {
        "from": "2020-01-01 14:53:55",
        "to": "2020-01-30 13:53:59"
      },
      "project_id": [
        183
      ],
      "limit": 3,
      "offset": 0,
      "tz": "Asia/Singapore",
     "signature": "Ini3aKje6aZskajTuRS761YOzVqierlVRafZdxIz48wmVnL7yxgy9vDsp7T2/LGPGHJ/DHoKOgP7VqObJALrUA=="
    }

Далее представлена интерактивная форма для самостоятельной проверки корректной работы с подписью при отправке запросов к Data API.

Проверка данных

Описание алгоритма

В качестве входных данных для проверки целостности выступают:

  1. Подписанные данные, которые требуется проверить. Как правило, это тело оповещения или ответа в формате JSON с параметром signature в его составе.
  2. Ключ, используемый для проверки. Это должен быть ровно тот ключ, который был использован для подписывания проверяемых данных.

В качестве выходных данных при проверке целостности в зависимости от реализации алгоритма могут выступать расчётная подпись и информация о её совпадении с проверяемой подписью, то есть информация о целостности проверяемых данных.

Далее в описании, примерах и формах для тестирования представлен часто используемый и наиболее показательный вариант реализации алгоритма: с телом проверяемого сообщения (оповещения или ответа) в формате JSON на входе и с заключением о целостности этого сообщения на выходе.

В состав алгоритма в этом случае включаются следующие шаги:

Рис. 1. Шаги алгоритма проверки данных
  1. Проверка входных данных на соблюдение заданных требований:
    1. Структура проверяемых данных должна соответствовать формату JSON.
    2. В составе проверяемых данных должен присутствовать параметр signature с подписью.
    3. Должен быть задан проверочный ключ.
  2. Извлечение подписи из проверяемых данных. На этом шаге из проверяемых данных исключается параметр signature, а его значение фиксируется для последующего сличения с расчётной подписью.
  3. Формирование расчётной подписи для проверяемых данных:
    1. Преобразование данных в строку UTF-8 с сортировкой параметров в естественном порядке. В рамках этого шага выполняются следующие действия:
      1. Логические (булевы) значения кодируются следующим образом: false заменяется на 0, а true — на 1. Но это относится только к булевым значениям — в строковых параметрах, даже если они содержат значения false или true, замены на 0 или 1 не используются (например, в параметре recurring: "{type: \"U\",register: true}" замена true на 1 не требуется).
      2. Каждый параметр преобразуется в строку, содержащую полный путь к параметру, название параметра и его значение: <родительский_узел_1>:...:<родительский_узел_N>:<название_параметра>:<значение_параметра>, где родительские узлы — это названия объектов и (или) массивов, в состав которых включена пара «название параметра — значение параметра». Родительские узлы располагаются в порядке их вложения, начиная с самого верхнего уровня. В качестве разделителя при этом используется двоеточие (:), между парами «название параметра — значение параметра» удаляются запятые, а у строковых значений параметров удаляются обрамляющие кавычки.
      3. Параметры с нулевыми, а также пустыми значениями остаются в строке, например запись "payment_description":"" представляется в виде payment_description:. Замены пустых значений на пробелы или null не применяются.
      4. Элементы массивов записываются отдельными строками, с указанием номера каждого элемента, начиная с нуля. Например, массив ["alpha", "beta", "gamma"] представляется в виде трёх строк: 0:alpha, 1:beta и 2:gamma.
      5. Пустые массивы полностью игнорируются и не включаются в набор строк для создания подписи.
      6. Кодировка всех строк приводится к формату UTF-8.
      7. Полученные строки упорядочиваются в естественном порядке и объединяются в одну строку с использованием в качестве разделителя точки с запятой (;).
    2. Получение двоичного кода HMAC с использованием ключа и функции SHA‑512. На этом шаге для полученной строки с параметрами вычисляется HMAC (Hash-based Message Authentication Code; код аутентификации сообщений с использованием хеш-функции) с использованием функции хеширования SHA‑512 (Secure Hash Algorithm; безопасный алгоритм хеширования) и применяемого ключа. И этот HMAC представляется в виде необработанных двоичных данных.
    3. Кодирование двоичного кода HMAC с применением алгоритма Base64. На этом шаге полученный двоичный код HMAC кодируется с использованием алгоритма Base64. Получаемая при этом строка является подписью к исходным данным.
  4. Сопоставление подписей. На этом шаге расчётная подпись сопоставляется с проверяемой. Если подписи совпадают, данные признаются целостными и достоверными. При несовпадении подписей данные не могут считаться достоверными и не должны использоваться в качестве рабочих.

Пример для оповещения

Допустим, что надо проверить подпись оповещения при следующих условиях:

  • Используемый ключ — secret
  • Тело полученного оповещения выглядит так:
    Рис. 2. Тело оповещения
    {
        "customer": {
            "id": "782572"
        },
        "account": {
            "number": "424242******4242",
            "token": "c8175453f68ec7c8fb3f052b8d786c661261efebcb91155327a6c7b8f8e66359",
            "type": "visa",
            "card_holder": "TEST TEST",
            "expiry_month": "01",
            "expiry_year": "2025"
        },
        "project_id": 28051,
        "payment": {
            "id": "5242723",
            "type": "purchase",
            "status": "success",
            "date": "2023-03-10T12:26:17+0000",
            "method": "card",
            "sum": {
                "amount": 5200,
                "currency": "EUR"
            },
            "description": ""
        },
        "operation": {
            "sum_initial": {
                "amount": 5200,
                "currency": "EUR"
            },
            "sum_converted": {
                "amount": 5200,
                "currency": "EUR"
            },
            "code": "0",
            "message": "Success",
            "provider": {
                "id": 6,
                "payment_id": "16784511766816",
                "auth_code": "563253",
                "endpoint_id": 6,
                "date": "2023-03-10T10:26:17+0000"
            },
            "id": 5028800010128225,
            "type": "sale",
            "status": "success",
            "date": "2023-03-10T12:26:17+0000",
            "created_date": "2023-03-10T12:26:15+0000",
            "request_id": "1f6d3ac37444142f5bd27e7491faa360633fd5a2-fc98e73d475fa4cd6ee02fc6340c964f0267b3d8-05028801"
        },
        "signature": "IszjSnH+UqFp88DF0giI/jUTDHOnfPxc83j2VD/jN4loB9wbHwiO5+KvHfdFE4nBPHhhxD6TXbOkGnRINFTTmg=="
    }

Для проверки подписи необходимо:

  1. Удалить из тела оповещения параметр signature вместе с его значением:
    {
        "customer": {
            "id": "782572"
        },
        "account": {
            "number": "424242******4242",
            "token": "c8175453f68ec7c8fb3f052b8d786c661261efebcb91155327a6c7b8f8e66359",
            "type": "visa",
            "card_holder": "TEST TEST",
            "expiry_month": "01",
            "expiry_year": "2025"
        },
        "project_id": 28051,
        "payment": {
            "id": "5242723",
            "type": "purchase",
            "status": "success",
            "date": "2023-03-10T12:26:17+0000",
            "method": "card",
            "sum": {
                "amount": 5200,
                "currency": "EUR"
            },
            "description": ""
        },
        "operation": {
            "sum_initial": {
                "amount": 5200,
                "currency": "EUR"
            },
            "sum_converted": {
                "amount": 5200,
                "currency": "EUR"
            },
            "code": "0",
            "message": "Success",
            "provider": {
                "id": 6,
                "payment_id": "16784511766816",
                "auth_code": "563253",
                "endpoint_id": 6,
                "date": "2023-03-10T10:26:17+0000"
            },
            "id": 5028800010128225,
            "type": "sale",
            "status": "success",
            "date": "2023-03-10T12:26:17+0000",
            "created_date": "2023-03-10T12:26:15+0000",
            "request_id": "1f6d3ac37444142f5bd27e7491faa360633fd5a2-fc98e73d475fa4cd6ee02fc6340c964f0267b3d8-05028801"
        },
        "signature": "IszjSnH+UqFp88DF0giI/jUTDHOnfPxc83j2VD/jN4loB9wbHwiO5+KvHfdFE4nBPHhhxD6TXbOkGnRINFTTmg=="
    }
  2. Преобразовать оставшиеся параметры в строки UTF-8 согласно правилам алгоритма:

    customer:id:782572
    account:number:424242******4242
    account:token:c8175453f68ec7c8fb3f052b8d786c661261efebcb91155327a6c7b8f8e66359
    account:type:visa
    account:card_holder:TEST TEST
    account:expiry_month:01
    account:expiry_year:2025
    project_id:28051
    payment:id:5242723
    payment:type:purchase
    payment:status:success
    payment:date:2023-03-10T12:26:17+0000
    payment:method:card
    payment:sum:amount:5200
    payment:sum:currency:EUR
    payment:description:
    operation:sum_initial:amount:5200
    operation:sum_initial:currency:EUR
    operation:sum_converted:amount:5200
    operation:sum_converted:currency:EUR
    operation:code:0
    operation:message:Success
    operation:provider:id:6
    operation:provider:payment_id:16784511766816
    operation:provider:auth_code:563253
    operation:provider:endpoint_id:6
    operation:provider:date:2023-03-10T10:26:17+0000
    operation:id:5028800010128225
    operation:type:sale
    operation:status:success
    operation:date:2023-03-10T12:26:17+0000
    operation:created_date:2023-03-10T12:26:15+0000
    operation:request_id:1f6d3ac37444142f5bd27e7491faa360633fd5a2-fc98e73d475fa4cd6ee02fc6340c964f0267b3d8-05028801
    
  3. Отсортировать полученные строки в естественном порядке:
    account:card_holder:TEST TEST
    account:expiry_month:01
    account:expiry_year:2025
    account:number:424242******4242
    account:token:c8175453f68ec7c8fb3f052b8d786c661261efebcb91155327a6c7b8f8e66359
    account:type:visa
    customer:id:782572
    operation:code:0
    operation:created_date:2023-03-10T12:26:15+0000
    operation:date:2023-03-10T12:26:17+0000
    operation:id:5028800010128225
    operation:message:Success
    operation:provider:auth_code:563253
    operation:provider:date:2023-03-10T10:26:17+0000
    operation:provider:endpoint_id:6
    operation:provider:id:6
    operation:provider:payment_id:16784511766816
    operation:request_id:1f6d3ac37444142f5bd27e7491faa360633fd5a2-fc98e73d475fa4cd6ee02fc6340c964f0267b3d8-05028801
    operation:status:success
    operation:sum_converted:amount:5200
    operation:sum_converted:currency:EUR
    operation:sum_initial:amount:5200
    operation:sum_initial:currency:EUR
    operation:type:sale
    payment:date:2023-03-10T12:26:17+0000
    payment:description:
    payment:id:5242723
    payment:method:card
    payment:status:success
    payment:sum:amount:5200
    payment:sum:currency:EUR
    payment:type:purchase
    project_id:28051
  4. Объединить отсортированные строки в одну строку с использованием в качестве разделителя точки с запятой:
    account:card_holder:TEST TEST;account:expiry_month:01;account:expiry_year:2025;account:number:424242******4242;account:token:c8175453f68ec7c8fb3f052b8d786c661261efebcb91155327a6c7b8f8e66359;account:type:visa;customer:id:782572;operation:code:0;operation:created_date:2023-03-10T12:26:15+0000;operation:date:2023-03-10T12:26:17+0000;operation:id:5028800010128225;operation:message:Success;operation:provider:auth_code:563253;operation:provider:date:2023-03-10T10:26:17+0000;operation:provider:endpoint_id:6;operation:provider:id:6;operation:provider:payment_id:16784511766816;operation:request_id:1f6d3ac37444142f5bd27e7491faa360633fd5a2-fc98e73d475fa4cd6ee02fc6340c964f0267b3d8-05028801;operation:status:success;operation:sum_converted:amount:5200;operation:sum_converted:currency:EUR;operation:sum_initial:amount:5200;operation:sum_initial:currency:EUR;operation:type:sale;payment:date:2023-03-10T12:26:17+0000;payment:description:;payment:id:5242723;payment:method:card;payment:status:success;payment:sum:amount:5200;payment:sum:currency:EUR;payment:type:purchase;project_id:28051
  5. Вычислить HMAC полученной строки с использованием функции хеширования SHA-512 и используемого ключа, после чего кодировать двоичный код HMAC с применением алгоритма Base64:
    Y0qjN9dDnPTdddkVvXKS1pGp2z8ZpIl60P1CocND3YRxuBNx05ZMnhUaGFt90fPzgwsI/UpLw0q2RR/XTiDQBg==
  6. Сравнить полученную подпись с проверяемой.

    В данном случае подписи не совпадают, а это значит, что такое оповещение недостоверно или ошибочно и должно быть отброшено.

Далее представлена интерактивная форма для самостоятельной проверки корректной работы с подписанными данными.

Пример для ответа с информацией об операциях

Допустим, что надо проверить подпись ответа при следующих условиях:

  • Используемый ключ — secret
  • Тело полученного ответа выглядит так:
    Рис. 3. Тело ответа
    {
      "operations": [
        {
          "project_id": "183",
          "operation_id": "9048253065548",
          "payment_id": "EP834a-40521580376090593",
          "operation_type": "cancel",
          "operation_status": "success",
          "account_number": "431422******0056",
          "customer_ip": "192.0.0.255",
          "payment_method_name": "visa",
          "payment_method_type": "visa",
          "payment_description": null,
          "operation_created_at": "2020-01-30T12:29:03+03:00",
          "operation_completed_at": "2020-01-30T12:29:04+03:00",
          "provider_date": null,
          "shipment_date": "",
          "mid": "3416123",
          "sum_initial": {
            "amount": 2000,
            "currency": "EUR"
          },
          "sum_converted": {
            "amount": 2000,
            "currency": "EUR"
          },
          "provider_name": "Dashboard Provider Card",
          "fee_currency": null,
          "fee_amount": 0,
          "arn": null,
          "rrn": null
        }
      ],
      "signature": "EksxDdDygDQ30JKsfK6QSvubpNRSj3wtLI5FzWDJuNY0nEhLXt65Y77dtKMJRcd39NegA7YK1eojA2EB1hIbnQ=="
    }

Для проверки подписи необходимо:

  1. Удалить из тела ответа параметр signature вместе с его значением:
    {
      "operations": [
        {
          "project_id": "183",
          "operation_id": "9048253065548",
          "payment_id": "EP834a-40521580376090593",
          "operation_type": "cancel",
          "operation_status": "success",
          "account_number": "431422******0056",
          "customer_ip": "192.0.0.255",
          "payment_method_name": "visa",
          "payment_method_type": "visa",
          "payment_description": null,
          "operation_created_at": "2020-01-30T12:29:03+03:00",
          "operation_completed_at": "2020-01-30T12:29:04+03:00",
          "provider_date": null,
          "shipment_date": "",
          "mid": "3416123",
          "sum_initial": {
            "amount": 2000,
            "currency": "EUR"
          },
          "sum_converted": {
            "amount": 2000,
            "currency": "EUR"
          },
          "provider_name": "Dashboard Provider Card",
          "fee_currency": null,
          "fee_amount": 0,
          "arn": null,
          "rrn": null
        }
      ],
      "signature": "EksxDdDygDQ30JKsfK6QSvubpNRSj3wtLI5FzWDJuNY0nEhLXt65Y77dtKMJRcd39NegA7YK1eojA2EB1hIbnQ=="
    }
  2. Преобразовать оставшиеся параметры в строки UTF-8 согласно правилам алгоритма:

    operations:0:project_id:183
    operations:0:operation_id:9048253065548
    operations:0:payment_id:EP834a-40521580376090593
    operations:0:operation_type:cancel
    operations:0:operation_status:success
    operations:0:account_number:431422******0056
    operations:0:customer_ip:192.0.0.255
    operations:0:payment_method_name:visa
    operations:0:payment_method_type:visa
    operations:0:payment_description:
    operations:0:operation_created_at:2020-01-30T12:29:03+03:00
    operations:0:operation_completed_at:2020-01-30T12:29:04+03:00
    operations:0:provider_date:
    operations:0:shipment_date:
    operations:0:mid:3416123
    operations:0:sum_initial:amount:2000
    operations:0:sum_initial:currency:EUR
    operations:0:sum_converted:currency:EUR
    operations:0:sum_converted:amount:2000
    operations:0:provider_name:Dashboard Provider Card
    operations:0:fee_currency:
    operations:0:fee_amount:0
    operations:0:arn:
    operations:0:rrn:
  3. Отсортировать полученные строки в естественном порядке:
    operations:0:account_number:431422******0056
    operations:0:arn:
    operations:0:customer_ip:192.0.0.255
    operations:0:fee_amount:0
    operations:0:fee_currency:
    operations:0:mid:3416123
    operations:0:operation_completed_at:2020-01-30T12:29:04+03:00
    operations:0:operation_created_at:2020-01-30T12:29:03+03:00
    operations:0:operation_id:9048253065548
    operations:0:operation_status:success
    operations:0:operation_type:cancel
    operations:0:payment_description:
    operations:0:payment_id:EP834a-40521580376090593
    operations:0:payment_method_name:visa
    operations:0:payment_method_type:visa
    operations:0:project_id:183
    operations:0:provider_date:
    operations:0:provider_name:Dashboard Provider Card
    operations:0:rrn:
    operations:0:shipment_date:
    operations:0:sum_converted:amount:2000
    operations:0:sum_converted:currency:EUR
    operations:0:sum_initial:amount:2000
    operations:0:sum_initial:currency:EUR
    
  4. Объединить отсортированные строки в одну строку с использованием в качестве разделителя точки с запятой:
    operations:0:account_number:431422******0056;operations:0:arn:;operations:0:customer_ip:192.0.0.255;operations:0:fee_amount:0;operations:0:fee_currency:;operations:0:mid:3416123;operations:0:operation_completed_at:2020-01-30T12:29:04+03:00;operations:0:operation_created_at:2020-01-30T12:29:03+03:00;operations:0:operation_id:9048253065548;operations:0:operation_status:success;operations:0:operation_type:cancel;operations:0:payment_description:;operations:0:payment_id:EP834a-40521580376090593;operations:0:payment_method_name:visa;operations:0:payment_method_type:visa;operations:0:project_id:183;operations:0:provider_date:;operations:0:provider_name:Dashboard Provider Card;operations:0:rrn:;operations:0:shipment_date:;operations:0:sum_converted:amount:2000;operations:0:sum_converted:currency:EUR;operations:0:sum_initial:amount:2000;operations:0:sum_initial:currency:EUR
  5. Вычислить HMAC полученной строки с использованием функции хеширования SHA-512 и используемого ключа, после чего кодировать двоичный код HMAC с применением алгоритма Base64:
    orpqWm+Vu7unNcob7h+jHuk+H4/M9rnX7qFZD657nECok8oKD7IkdwGye3Ag10A5zBg1Ck2DrZnvtaptNjaIkw==
  6. Сравнить полученную подпись с проверяемой.

    В данном случае подписи не совпадают, а это значит, что такой ответ недостоверен или ошибочен и должен быть отброшен.

Далее представлена интерактивная форма для самостоятельной проверки корректной работы с подписанными данными.