Server setup
To receive real-time notifications, you need to create a secure server. To do this, follow the steps below.
Prepare the server
To receive notifications, deploy a server that will:
- receive POST request notifications from RuStore;
- respond with HTTP status code
200 OKif the notification is accepted; - respond with HTTP error codes
4xxor5xxif the notification could not be received and the delivery must be retried.
Your server is responsible for sending responses to all notifications, as well as analyzing and interpreting the notifications.
Add the RuStore IP address to the allowlist
Create a firewall rule allowing your server to receive notifications from the RuStore IP address 95.163.133.0/30.
We recommend blocking requests from all other IP addresses.
Bind a domain and issue a certificate
Define the server URL that will receive notifications.
The notification delivery service works only with addresses that start with https://.
Your server must support a TLS connection with a certificate issued by a certificate authority. For example, Let’s Encrypt. Certificates issued by the National Certification Authority of the Ministry of Digital Development of the Russian Federation are also supported.
If your server is deployed in a public cloud, you can also obtain a certificate from the cloud provider.
Configure notification decryption
For security reasons, payment information is encrypted using AES-256 symmetric encryption with the following parameters:
AES/GCM/NoPadding;- initialization vector (IV) length —
12; - tag length —
16.
You can find more details about this encryption algorithm, for example, here.
When receiving a notification, your algorithm must decrypt the payload string from the request body.
You receive the decryption key in RuStore Console after configuring notification sending or when updating the encryption key.
Example of decrypting a notification in Java
//Initialization vector length
private static final int GCM_IV_LENGTH = 12;
//tag length
private static final int GCM_TAG_LENGTH = 16;
//algorithm
private static final String CIPHER_ALGORITHM = "AES/GCM/NoPadding";
public String decrypt(
//the string received in the request from RuStore
String encryptedInput,
//the key copied from the console
String secretKey
) {
try {
//decode the incoming encrypted message
byte[] decoded = Base64.getDecoder().decode(encryptedInput.getBytes(StandardCharsets.UTF_8));
//extract the vector from the byte sequence
byte[] ivDecrypt = Arrays.copyOfRange(decoded, 0, GCM_IV_LENGTH);
//initialize the GCM parameter spec
GCMParameterSpec ivSpec = new GCMParameterSpec(GCM_TAG_LENGTH * Byte.SIZE, ivDecrypt);
//get a cipher instance for the encryption algorithm
Cipher cipher = Cipher.getInstance(CIPHER_ALGORITHM);
//initialize the cipher in decrypt mode with the key and vector
cipher.init(Cipher.DECRYPT_MODE, convertStringToSecretKey(secretKey), ivSpec);
//decrypt the byte array starting after the vector ends
byte[] ciphertext = cipher.doFinal(decoded, GCM_IV_LENGTH, decoded.length - GCM_IV_LENGTH);
//return the response as a UTF_8 String
return new String(ciphertext, StandardCharsets.UTF_8);
} catch (Exception e) {
//log the issue in case of an error
logger.warn("Something went wrong with decrypting", e);
throw new RuntimeException(e);
}
}
//deserialize the key from Base64(UTF_8) text format into a SecretKey object
private SecretKey convertStringToSecretKey(String secretKey) {
byte[] decodedKey = Base64.getDecoder().decode(secretKey.getBytes(StandardCharsets.UTF_8));
return new SecretKeySpec(decodedKey, 0, decodedKey.length, "AES");
}
What’s next
Configure and test notification sending in RuStore Console to make sure the server configuration is correct.