Finix English
    • Finix API documentation
    • Introduction
    • Request Signing
    • Signature Verification
    • India
      • PayIn
        • Create payment
        • Fetch payment status
        • Payment webhook (async notification)
      • PayOut
        • Initiate payout
        • Fetch payout status
        • Payout webhook (async notification)
    • Egypt
      • PayIn
        • Create payment
        • Fetch payment status
        • Payment webhook (async notification)
      • PayOut
        • Initiate payout
        • Fetch payout status
        • Payout webhook (async notification)
    • Nigeria
      • PayIn
        • Create payment
        • Fetch payment status
        • Payment webhook (async notification)
      • PayOut
        • Initiate payout
        • Fetch payout status
        • Payout webhook (async notification)
        • Bank code
    • Indonesia
      • PayIn
        • Create payment
        • Fetch payment status
        • Payment webhook (async notification)
      • PayOut
        • Initiate payout
        • Fetch payout status
        • Payout webhook (async notification)
        • Bank code
    • Account Balance
      POST
    • USDT Exchange Rate
      POST

    Request Signing

    RSA-SHA512 API request signing#

    I. Purpose#

    To protect API integrity and authenticity, the platform uses RSA asymmetric cryptography with an SHA512 digest (SHA512withRSA). This verifies the caller, prevents tampering, and mitigates replay attacks.

    II. When signing is required#

    Signing applies to all API requests between the merchant and Finix.

    III. Structure and rules#

    Every request must include a Signature header computed as described below.
    1
    Signing algorithms
    Digest: SHA512 (512-bit Secure Hash Algorithm)
    Encryption: RSA (sign with the merchant private key)
    Full algorithm name: SHA512withRSA
    2
    Signing procedure
    Step 1: Hash the request body (Body Hash)
    Compute the digest of the raw JSON request body using the SHA512 hash algorithm.
    For GET requests, treat the body as an empty string "" and skip hashing.
    Example body:
    {"merchantRef":"0954f567-ea8f-49b4-920f-c49174aa2c1f","amount":100,"currency":"INR","method":"NATIVE","name":"LuciaLesch","phone":"82445415208","email":"quinten31@yahoo.com","redirectUrl":"https://www.redirect.com/"}
    
    Example lowercase hex SHA512 output:
    bfcd0c58c547c1d5960c73a6cf130cf5ae3f96d115392bdc678a36dab1ea08bdaf271b73db17650536a0a78d04d771557f9c5d71596e36547fb2089deb780784
    
    Step 2: Build the string to sign
    Concatenate as follows:
    stringToSign = requestPathUri + sha512Hex + timestamp
    Example:
    /v1/api/payment/initiatebfcd0c58c547c1d5960c73a6cf130cf5ae3f96d115392bdc678a36dab1ea08bdaf271b73db17650536a0a78d04d771557f9c5d71596e36547fb2089deb7807841699447297
    
    3
    Sign with private key
    Sign stringToSign with the merchant RSA private key using SHA512withRSA.
    Base64-encode the signature bytes to produce the final Signature header value.

    IV. Security notes#

    The merchant signs with its private key; Finix verifies with the merchant public key.
    For Finix-to-merchant responses, Finix signs with its private key and the merchant verifies with Finix’s public key.
    Together this ensures data integrity, authenticates the caller, and binds requests to a time window to reduce replay risk.

    V. Important notes#

    Signing is case-sensitive; the string to sign must match byte-for-byte.
    Keep JSON payloads in a stable serialized form; field order changes alter the hash.
    Timestamp must be the current Unix time in seconds.
    The Base64 signature uses the standard alphabet (decoder may be case-insensitive).

    VI. Code samples#

    Java
    Python
    PHP
    C#(.NET Core)
    Go
    import java.io.*;
    import java.net.HttpURLConnection;
    import java.net.URL;
    import java.nio.charset.StandardCharsets;
    import java.security.*;
    import java.security.spec.*;
    import java.util.Base64;
    
    public class RSASignature {
    
        public static void main(String[] args) throws Exception {
            // Request parameters
            String body = "{\"amount\":\"100\",\"method\":\"NATIVE\",\"phone\":\"82445415208\",\"name\":\"LuciaLesch\",\"merchantRef\":\"T1699447296\",\"email\":\"quinten31@yahoo.com\"}";
            String uri = "/v1/api/payment/initiate";
            String timestamp = String.valueOf(System.currentTimeMillis() / 1000);
            String merchantId = "FINIX_MERCHANT_ID";
    
            // Load private key
            String privateKeyPem = "-----BEGIN PRIVATE KEY-----\n" + YOUR_PRIVATE_KEY_CONTENT_HERE + "\n-----END PRIVATE KEY-----";
            PrivateKey privateKey = getPrivateKeyFromPem(privateKeyPem);
    
            // Generate signature
            String bodyHash = sha512Hex(body);
            String stringToSign = uri + bodyHash + timestamp;
            String signatureBase64 = sign(stringToSign, privateKey);
    
            // Print signature (debug)
            System.out.println("Signature: " + signatureBase64);
    
            // Send HTTP POST
            String apiUrl = "https://secure-staging.finixpayment.com" + uri;
            String response = sendHttpPost(apiUrl, body, merchantId, signatureBase64, timestamp);
    
            System.out.println("Response: " + response);
        }
    
        // Compute SHA-512 hex
        private static String sha512Hex(String data) throws Exception {
            MessageDigest md = MessageDigest.getInstance("SHA-512");
            byte[] digest = md.digest(data.getBytes(StandardCharsets.UTF_8));
            StringBuilder sb = new StringBuilder();
            for (byte b : digest) sb.append(String.format("%02x", b));
            return sb.toString();
        }
    
        // Sign (SHA512withRSA)
        private static String sign(String data, PrivateKey privateKey) throws Exception {
            Signature signature = Signature.getInstance("SHA512withRSA");
            signature.initSign(privateKey);
            signature.update(data.getBytes(StandardCharsets.UTF_8));
            byte[] signed = signature.sign();
            return Base64.getEncoder().encodeToString(signed);
        }
    
        // Read PKCS#8 private key
        private static PrivateKey getPrivateKeyFromPem(String pem) throws Exception {
            pem = pem.replace("-----BEGIN PRIVATE KEY-----", "")
                     .replace("-----END PRIVATE KEY-----", "")
                     .replaceAll("\\s+", "");
            byte[] keyBytes = Base64.getDecoder().decode(pem);
            PKCS8EncodedKeySpec spec = new PKCS8EncodedKeySpec(keyBytes);
            return KeyFactory.getInstance("RSA").generatePrivate(spec);
        }
    
        // Send HTTP POST request
        private static String sendHttpPost(String urlStr, String jsonBody, String merchantId, String signature, String timestamp) throws IOException {
            URL url = new URL(urlStr);
            HttpURLConnection conn = (HttpURLConnection) url.openConnection();
    
            conn.setRequestMethod("POST");
            conn.setRequestProperty("Content-Type", "application/json");
            conn.setRequestProperty("MerchantID", merchantId);
            conn.setRequestProperty("Signature", signature);
            conn.setRequestProperty("Timestamp", timestamp);
            conn.setDoOutput(true);
    
            try (OutputStream os = conn.getOutputStream()) {
                byte[] input = jsonBody.getBytes(StandardCharsets.UTF_8);
                os.write(input, 0, input.length);
            }
    
            int responseCode = conn.getResponseCode();
            InputStream is = (responseCode >= 200 && responseCode < 300) ? conn.getInputStream() : conn.getErrorStream();
    
            try (BufferedReader br = new BufferedReader(new InputStreamReader(is, StandardCharsets.UTF_8))) {
                StringBuilder response = new StringBuilder();
                String line;
                while ((line = br.readLine()) != null) response.append(line);
                return response.toString();
            }
        }
    }
    Modified at 2026-04-07 17:05:02
    Previous
    Introduction
    Next
    Signature Verification
    Built with