API request signature
Facing insecure integration, you may be requested to implement an asymmetric request signature.
To have a possibility to sign requests, you need to perform the following steps:
- Generate and upload a certificate.
- Calculate a hash and a signature using your private key and pass the generated hash (X-Hash) and the signature value (X-Signature) in the request header.
These steps are described below in details.
Generating and uploading a certificate
-
Generate 2048-bit RSA private key. The way of generation depends on privacy policy in your company. For example, you can do it using OpenSSL:
openssl genrsa -des3 -out private.key 2048 -
Generate public CSR (Certificate Signing Request) using the generated private key:
openssl req -key private.key -new -out public.csr -
Generate a certificate using the generated private key and CSR. The example of generating a certificate for 5 years:
openssl x509 -signkey private.key -in public.csr -req -days 1825 -out public.cer Upload the certificate in the Merchant Portal. For that, go to Certificates > Merchant API, click Add a certificate, then drag-and-drop the generated public certificate.

To use this function in the Merchant Portal, a permission in the bank is required. If the certificates section is not displayed in the menu, contact the support service to upload the certificate.
Calculating a hash and a signature
-
Calculate SHA256 hash of the request body as follows:
- Use request body as a string, for example
{"orderId": "243d940e-bedd-4e95-8e78-b08f459a242f","password": "test-user-password","userName": "test-user"}. - Calculate SHA256 hash from this string, in raw bytes (hex format).
- Convert the raw bytes into base64 encoding.
Hash Base64: MmI1ZmUwZjc2YmUxNGJiY2ZjN2M3NzQ3OGYwYTU4ODUwYzhmNzEyNDg5YjczOTg3NzZlYTg4ODEwNDczYzFmYg== - Use request body as a string, for example
-
Generate a signature for the calculated SHA256 hash (raw hex, not base64) with RSA algorythm using the private key.
In our example we use the following private key with the password 12345:
MIIEvwIBADANBgkqhkiG9w0BAQEFAASCBKkwggSlAgEAAoIBAQC0NQCjnqUmdEK1aisFXGMIihI73zofZycI/EGTJkQ6HOT2e/dG4j1RqHwuE6FEPL8lGG3EddFSiZzjDbIH+bm5m0CpcnFN1ShTxbA8BzM+OGxRHsuHU168HiS3OSIO9IxCKlaYzNgL1IygkjF6xqXLRvAPJ70zb/ymD2Cszfbw3ZNcZnr07QtJF/Jbn/+UJt+1hin9y6ikKZH+laZlMOx6LLGsj3W1PjFyEuzNUmau3iX6I6PdfgVwbB7TRVFuFDfxzBZxtBDympGRxpTGNFHug1NNPA9ekWa+zVlNVbzPrMuf6rF4yvKc8Tv9OkQ7RfGv1YmFCgEjqgnW2puIuufJAgMBAAECggEAdzDzakVdMJEHKly9db9ElXpVUxpzpB+jFvNaIAzYZaOE4W7fABhVvHP3Jra/HJYdS1jcCWxv9eqlRRxi25mV+Six3SGfxX4uPTJtPVb50raZFhKLRcejykMZv8JfP4sKVh0Qx+H9J93+4Zmwdmd7c3dJAo0jPCle7ysOo11bbrXTMwgg/i9Rxfzf5j4HYVTqYGIOL8cwNDE9XzDV7ekYJ147Ro15QnXK315fij2y7HFEJoyXp4BySm2nGNjxBjPn7sd/0Y8IrnYtpAnD7PG6oHRMITAEpZGEGyAi5cxAwTK1p43megM9ZaddSYPGtyrelNW6xm86x5Ulv8Bqhg1gzQKBgQDcAkILsNGV1eazxsv7QEg9Xs7h9VHrmPVTSGx6OjcZNP/VSZCzLT6IiK68c5ywkTe8SuDCLgU6Tcf4YOuno7gRplnLm6KzTatu/WE4qiz+WzrT4/+uspOli5YdTBXWtGXgWWvcnuQ1TTECdFf83na/cPDM5qKfJuoOan3gbMNVowKBgQDRr+MarMxNnoaH/XlY0HURtAUENieoyll72iHLofdlyQPDqoo0G00zjlV11DH/pH8qQ1PsswJDxL6oiY9XkxZ0P2Pd5BnYW8wSUdQ033ReSxc9WHlnTnixPp/YHraAmzZXncM6B8YJWAO5CtLW7Xym58BLUgMMH6FUM0gKiLMrowKBgQCx1alpJb3jrYjTnEdZifZalP4JK3DSTUtPzGTSz6el2m9JCjPKgTHgzwrfDVyEZH1219ehXe2f2Stgm4cgdHfe3GYM7HqxEIEYL/ucAAJqf3enus37eiFaWOA4Qj4M1LjchatoI483fnO1FjHhFjlKOZKLLYoZtyzOBkpFU+T4nQKBgQDNCpYj3ncFK4/X6NfBLk5b2lHRdXdAiWYJQxsq+Z1m7bJ9ogT0wQGz+Wm+B5pApkUnOaEWY1FCnV/mhGUjuJQLZnUsZEGVnOYnv9anQR6Umg8GkL5ec5B3mYpKlnXVunDgKkfeNf3D40n4pwnW23G58ALMZEzQjRl/sYmvq06wywKBgQCer3/ehngsL6xpdmWaWOyZja992F9s7JKb+M5esEltp5utpB9DEGrV1KKnLTWtM99vbxBEm5zeaYimdy1359YxzaDdmDm+w2tV+qjA3u3RgZpjqfw5uiASgL8hT12Rgme4itBC6tuhf3fZEGlQI5cKSJn+fB2XMXw/3S7RfGRT9w==and get the signature:
WR5bDw3XFuf29y9j1IJIM3E96g9d1fgyaWwUVKYIHOhOflKWuT0ei1Myz8aJzP1k2XlztQARK1h4Rj5LHMbZDZMSkkwfdNdr0VoKrfxPv6bJqW/paduYv47wQ5Q6YSqpuLsNjCjy5MMLKtLnuff9Drc18lEQU2RGq7eh8lELUVB6asts+8FOp7PIawfeSGbM+kSKPdH181E3XR0/V+ck1/m6cBouGeZHM7767S6nkbl8b7wx9kCj5z1j0mbvQxU3lPjK1qS+ntkbP4V0oMaDKe8kfnbZK9/LX6tRZFHoDjjMspwy3M72pe+ohn9FkfPg5G39H2L2dVtV/fb5BXlOBQ== Now you should pass the generated hash (
X-Hash) and the signature value (X-Signature) in the request header. The request will look like this:
curl 'https://api.uat.all2pay.net/v1/getOrderStatusExtended.do' \
-H 'X-hash: MmI1ZmUwZjc2YmUxNGJiY2ZjN2M3NzQ3OGYwYTU4ODUwYzhmNzEyNDg5YjczOTg3NzZlYTg4ODEwNDczYzFmYg==' \
-H 'X-signature: WR5bDw3XFuf29y9j1IJIM3E96g9d1fgyaWwUVKYIHOhOflKWuT0ei1Myz8aJzP1k2XlztQARK1h4Rj5LHMbZDZMSkkwfdNdr0VoKrfxPv6bJqW/paduYv47wQ5Q6YSqpuLsNjCjy5MMLKtLnuff9Drc18lEQU2RGq7eh8lELUVB6asts+8FOp7PIawfeSGbM+kSKPdH181E3XR0/V+ck1/m6cBouGeZHM7767S6nkbl8b7wx9kCj5z1j0mbvQxU3lPjK1qS+ntkbP4V0oMaDKe8kfnbZK9/LX6tRZFHoDjjMspwy3M72pe+ohn9FkfPg5G39H2L2dVtV/fb5BXlOBQ==' \
-H 'Content-Type: application/json' \
-d '{"orderId": "243d940e-bedd-4e95-8e78-b08f459a242f","password": "test-user-password","userName": "test-user"}''The request should meet the following requirements:
- All the request parameters are included into the request body (not into the URL).
-
As the request parameters are in JSON format, then the following header should be used:
--header 'content-type: application/json' The request contains correct login and password of the API user.
The
X-Hashheader contains SHA256 hash of the request body (calculated at step 1).The
X-Signatureheader contains the signature for the calculated SHA256 hash with RSA algorythm using the private key (generated at step 2).
Groovy code example
Below is the Groovy code example that generates the hash and signature:
import java.security.Signature;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.Key;
import java.security.KeyFactory;
Base64.Decoder b64d = Base64.getDecoder();
Base64.Encoder b64e = Base64.getEncoder();
//2048 pair
def privKeyBase64 = "MIIEvwIBADANBgkqhkiG9w0BAQEFAASCBKkwggSlAgEAAoIBAQC0NQCjnqUmdEK1aisFXGMIihI73zofZycI/EGTJkQ6HOT2e/dG4j1RqHwuE6FEPL8lGG3EddFSiZzjDbIH+bm5m0CpcnFN1ShTxbA8BzM+OGxRHsuHU168HiS3OSIO9IxCKlaYzNgL1IygkjF6xqXLRvAPJ70zb/ymD2Cszfbw3ZNcZnr07QtJF/Jbn/+UJt+1hin9y6ikKZH+laZlMOx6LLGsj3W1PjFyEuzNUmau3iX6I6PdfgVwbB7TRVFuFDfxzBZxtBDympGRxpTGNFHug1NNPA9ekWa+zVlNVbzPrMuf6rF4yvKc8Tv9OkQ7RfGv1YmFCgEjqgnW2puIuufJAgMBAAECggEAdzDzakVdMJEHKly9db9ElXpVUxpzpB+jFvNaIAzYZaOE4W7fABhVvHP3Jra/HJYdS1jcCWxv9eqlRRxi25mV+Six3SGfxX4uPTJtPVb50raZFhKLRcejykMZv8JfP4sKVh0Qx+H9J93+4Zmwdmd7c3dJAo0jPCle7ysOo11bbrXTMwgg/i9Rxfzf5j4HYVTqYGIOL8cwNDE9XzDV7ekYJ147Ro15QnXK315fij2y7HFEJoyXp4BySm2nGNjxBjPn7sd/0Y8IrnYtpAnD7PG6oHRMITAEpZGEGyAi5cxAwTK1p43megM9ZaddSYPGtyrelNW6xm86x5Ulv8Bqhg1gzQKBgQDcAkILsNGV1eazxsv7QEg9Xs7h9VHrmPVTSGx6OjcZNP/VSZCzLT6IiK68c5ywkTe8SuDCLgU6Tcf4YOuno7gRplnLm6KzTatu/WE4qiz+WzrT4/+uspOli5YdTBXWtGXgWWvcnuQ1TTECdFf83na/cPDM5qKfJuoOan3gbMNVowKBgQDRr+MarMxNnoaH/XlY0HURtAUENieoyll72iHLofdlyQPDqoo0G00zjlV11DH/pH8qQ1PsswJDxL6oiY9XkxZ0P2Pd5BnYW8wSUdQ033ReSxc9WHlnTnixPp/YHraAmzZXncM6B8YJWAO5CtLW7Xym58BLUgMMH6FUM0gKiLMrowKBgQCx1alpJb3jrYjTnEdZifZalP4JK3DSTUtPzGTSz6el2m9JCjPKgTHgzwrfDVyEZH1219ehXe2f2Stgm4cgdHfe3GYM7HqxEIEYL/ucAAJqf3enus37eiFaWOA4Qj4M1LjchatoI483fnO1FjHhFjlKOZKLLYoZtyzOBkpFU+T4nQKBgQDNCpYj3ncFK4/X6NfBLk5b2lHRdXdAiWYJQxsq+Z1m7bJ9ogT0wQGz+Wm+B5pApkUnOaEWY1FCnV/mhGUjuJQLZnUsZEGVnOYnv9anQR6Umg8GkL5ec5B3mYpKlnXVunDgKkfeNf3D40n4pwnW23G58ALMZEzQjRl/sYmvq06wywKBgQCer3/ehngsL6xpdmWaWOyZja992F9s7JKb+M5esEltp5utpB9DEGrV1KKnLTWtM99vbxBEm5zeaYimdy1359YxzaDdmDm+w2tV+qjA3u3RgZpjqfw5uiASgL8hT12Rgme4itBC6tuhf3fZEGlQI5cKSJn+fB2XMXw/3S7RfGRT9w=="
def body = """{"orderId": "243d940e-bedd-4e95-8e78-b08f459a242f","password": "test-user-password","userName": "test-user"}"""
//// HASH /////
KeyFactory keyFactory = KeyFactory.getInstance('RSA');
Signature signatureProvider = Signature.getInstance("SHA256withRSA");
byte[] bodyHash = body.digest('SHA-256')
def bodyHashBase64 = b64e.encodeToString(bodyHash);
println "Hash Hex: " + new String(bodyHash)
println "Hash Base64: $bodyHashBase64"
//// SIGN /////
byte[] byteKey = b64d.decode(privKeyBase64.getBytes());
PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(byteKey)
Key privKey = keyFactory.generatePrivate(keySpec);
signatureProvider.initSign(privKey);
signatureProvider.update(bodyHash);
byte[] signature = signatureProvider.sign();
def signatureBase64 = b64e.encodeToString(signature)
println "Signature: $signatureBase64"Python code example
Same code in Python: generating hash and signature.
import base64
import hashlib
from cryptography.hazmat.primitives import serialization, hashes
from cryptography.hazmat.primitives.asymmetric import padding
from cryptography.hazmat.backends import default_backend
data = """{"orderId": "243d940e-bedd-4e95-8e78-b08f459a242f","password": "test-user-password","userName": "test-user"}"""
priv_key_pem = """
-----BEGIN PRIVATE KEY-----
MIIEvwIBADANBgkqhkiG9w0BAQEFAASCBKkwggSlAgEAAoIBAQC0NQCjnqUmdEK1aisFXGMIihI73zofZycI/EGTJkQ6HOT2e/dG4j1RqHwuE6FEPL8lGG3EddFSiZzjDbIH+bm5m0CpcnFN1ShTxbA8BzM+OGxRHsuHU168HiS3OSIO9IxCKlaYzNgL1IygkjF6xqXLRvAPJ70zb/ymD2Cszfbw3ZNcZnr07QtJF/Jbn/+UJt+1hin9y6ikKZH+laZlMOx6LLGsj3W1PjFyEuzNUmau3iX6I6PdfgVwbB7TRVFuFDfxzBZxtBDympGRxpTGNFHug1NNPA9ekWa+zVlNVbzPrMuf6rF4yvKc8Tv9OkQ7RfGv1YmFCgEjqgnW2puIuufJAgMBAAECggEAdzDzakVdMJEHKly9db9ElXpVUxpzpB+jFvNaIAzYZaOE4W7fABhVvHP3Jra/HJYdS1jcCWxv9eqlRRxi25mV+Six3SGfxX4uPTJtPVb50raZFhKLRcejykMZv8JfP4sKVh0Qx+H9J93+4Zmwdmd7c3dJAo0jPCle7ysOo11bbrXTMwgg/i9Rxfzf5j4HYVTqYGIOL8cwNDE9XzDV7ekYJ147Ro15QnXK315fij2y7HFEJoyXp4BySm2nGNjxBjPn7sd/0Y8IrnYtpAnD7PG6oHRMITAEpZGEGyAi5cxAwTK1p43megM9ZaddSYPGtyrelNW6xm86x5Ulv8Bqhg1gzQKBgQDcAkILsNGV1eazxsv7QEg9Xs7h9VHrmPVTSGx6OjcZNP/VSZCzLT6IiK68c5ywkTe8SuDCLgU6Tcf4YOuno7gRplnLm6KzTatu/WE4qiz+WzrT4/+uspOli5YdTBXWtGXgWWvcnuQ1TTECdFf83na/cPDM5qKfJuoOan3gbMNVowKBgQDRr+MarMxNnoaH/XlY0HURtAUENieoyll72iHLofdlyQPDqoo0G00zjlV11DH/pH8qQ1PsswJDxL6oiY9XkxZ0P2Pd5BnYW8wSUdQ033ReSxc9WHlnTnixPp/YHraAmzZXncM6B8YJWAO5CtLW7Xym58BLUgMMH6FUM0gKiLMrowKBgQCx1alpJb3jrYjTnEdZifZalP4JK3DSTUtPzGTSz6el2m9JCjPKgTHgzwrfDVyEZH1219ehXe2f2Stgm4cgdHfe3GYM7HqxEIEYL/ucAAJqf3enus37eiFaWOA4Qj4M1LjchatoI483fnO1FjHhFjlKOZKLLYoZtyzOBkpFU+T4nQKBgQDNCpYj3ncFK4/X6NfBLk5b2lHRdXdAiWYJQxsq+Z1m7bJ9ogT0wQGz+Wm+B5pApkUnOaEWY1FCnV/mhGUjuJQLZnUsZEGVnOYnv9anQR6Umg8GkL5ec5B3mYpKlnXVunDgKkfeNf3D40n4pwnW23G58ALMZEzQjRl/sYmvq06wywKBgQCer3/ehngsL6xpdmWaWOyZja992F9s7JKb+M5esEltp5utpB9DEGrV1KKnLTWtM99vbxBEm5zeaYimdy1359YxzaDdmDm+w2tV+qjA3u3RgZpjqfw5uiASgL8hT12Rgme4itBC6tuhf3fZEGlQI5cKSJn+fB2XMXw/3S7RfGRT9w==
-----END PRIVATE KEY-----
""".strip()
# HASH Hex
sha256_hash = hashlib.sha256(data.encode('utf-8')).hexdigest()
print(f"Hash Hex: {sha256_hash}")
# HASH Base64
base64_hash = base64.b64encode(sha256_hash.encode('utf-8')).decode('utf-8')
print(f"Hash Base64: {base64_hash}")
# Signature
private_key = serialization.load_pem_private_key(priv_key_pem.encode('utf-8'), password=None, backend=default_backend())
signature = private_key.sign(sha256_hash.encode('utf-8'), padding.PKCS1v15(), hashes.SHA256())
signature_base64 = base64.b64encode(signature).decode('utf-8')
print(f"Signature: {signature_base64}")Note that PEM key format (with BEGIN and END elements) is used in the Python example.