Настройка сервера для получения уведомлений
Чтобы получать уведомления в режиме реального времени, вам необходимо создать безопасный сервер. Для этого выполните шаги, перечисленные ниже.
Подготовьте сервер
Для получения уведомлений разверните сервер, который будет:
- принимать уведомления в формате POST-запросов от RuStore;
- отвечать на запросы HTTP-кодом
200 ОК
, если уведомление принято; - отвечать на запросы HTTP-кодами ошибок
4xx
или5xx
, если не удалось получить уведомление и необходимо повторить отправку.
Ваш сервер отвечает за отправку ответов на все уведомления, а также анализ и интерпретацию уведомлений.
Добавьте IP-адрес RuStore в белый список
Создайте правило Firewall, разрешающее вашему серверу получать уведомления от IP-адреса RuStore 95.163.133.1:8080
.
Обработку запросов с остальных IP-адресов рекомендуем запретить.
Привяжите домен и выпустите сертификат
Определите URL-адрес для сервера, который будет получать уведомления.
Сервис по отправке уведомлений работает только с теми адресами, которые начинаются на https://
.
Ваш сервер должен поддерживать TLS-соединение сертификатом, который выпущен центром сертификации. Например, Let’s Encrypt. Подходят в том числе сертификаты, выпущенные Национальным удостоверяющим центром Минцифры РФ.
Если ваш сервер развёрнут в публичном облаке, сертификат также можно получить у облачного провайдера.
Настройте расшифровку уведомления
В целях безопасности информация о платежах шифруется с помощью механизма симметричного шифрования AES-256 с параметрами:
AES/GCM/NoPadding
;- длина вектора инициализации (IV) —
12
; - длина тега —
16
.
Подробности об этом алгоритме шифрования вы можете посмотреть, например, тут.
При получении уведомления ваш алгоритм должен расшифровывать строку payload
из body
.
Ключ для расшифровки вы получаете в RuStore Консоль после настройки отправки уведомлений или при обновлении ключа шифрования.
Пример расшифровки уведомления на Java
//длина Initialization vector
private static final int GCM_IV_LENGTH = 12;
//длина тега
private static final int GCM_TAG_LENGTH = 16;
//алгоритм
private static final String CIPHER_ALGORITHM = "AES/GCM/NoPadding";
public String decrypt(
//строка, которая приходит в запросе от RuStore
String encryptedInput,
//ключ, который копируем из консоли
String secretKey
) {
try {
//декодируем входящее ecrypt сообщение
byte[] decoded = Base64.getDecoder().decode(encryptedInput.getBytes(StandardCharsets.UTF_8));
//выделяем вектор из последовательности байт
byte[] ivDecrypt = Arrays.copyOfRange(decoded, 0, GCM_IV_LENGTH);
//инициализируем объект параметров GCM
GCMParameterSpec ivSpec = new GCMParameterSpec(GCM_TAG_LENGTH * Byte.SIZE, ivDecrypt);
//получаем инстанс объекта по алгоритму шифрования
Cipher cipher = Cipher.getInstance(CIPHER_ALGORITHM);
//инициализируем объект шифрования в режиме decrypt, ключом и вектором
cipher.init(Cipher.DECRYPT_MODE, convertStringToSecretKey(secretKey), ivSpec);
//дешифруем набор байт начиная с окончания вектора
byte[] ciphertext = cipher.doFinal(decoded, GCM_IV_LENGTH, decoded.length - GCM_IV_LENGTH);
//возвращаем ответ в формате String UTF_8
return new String(ciphertext, StandardCharsets.UTF_8);
} catch (Exception e) {
//в случае ошибки логируем проблему
logger.warn("Something went wrong with decrypting", e);
throw new RuntimeException(e);
}
}
//десериализуем ключ из текстового формата Base64(UTF_8) в объект SecretKey
private SecretKey convertStringToSecretKey(String secretKey) {
byte[] decodedKey = Base64.getDecoder().decode(secretKey.getBytes(StandardCharsets.UTF_8));
return new SecretKeySpec(decodedKey, 0, decodedKey.length, "AES");
}
Что дальше
Настройте и протестируйте отправку уведомлений в RuStore Консоль, чтобы убедиться в корректности конфигурации сервера.