Finix
    Finix
    • Finix API Documentation
    • Introduction
    • Signature
    • Signature Verification
    • India
      • Payment
        • Initiate
        • Fetch
        • Webhook
      • Payout
        • Initiate
        • Fetch
        • Webhook
    • Nigeria
      • Payment
        • Initiate
        • Fetch
        • Webhook
      • Payout
        • Initiate
        • Fetch
        • Webhook
        • Bank Code
    • Balance
      POST
    • USDT Rate
      POST

    Signature

    RSA-SHA512 API Signature Mechanism#

    1. Purpose of the Signature#

    To ensure the security and integrity of API calls, the platform adopts an RSA asymmetric encryption mechanism combined with the SHA512 hashing algorithm (SHA512withRSA). This mechanism is used to verify the identity of the requester, prevent data tampering, and protect against replay attacks.

    2. Signature Usage Scenarios#

    The signature is applied to all API interactions between the merchant and Finix.

    3. Signature Structure and Rules#

    When making an API request, the client must include the Signature field in the request header to validate the legitimacy of the request.
    1
    Signature Algorithm
    Hash Algorithm:SHA512 (Secure Hash Algorithm, 512-bit)
    Encryption Algorithm:RSA (signed using the merchant's private key)
    Full Signature Algorithm Name:SHA512withRSA
    2
    Signature Process
    Step 1: Calculate the Request Body Hash (Body Hash)
    Apply the SHA512 hash algorithm to the raw JSON string of the request BODY
    If the request method is GET, the body is considered an empty string "", and hashing is skipped
    Example content:
    {"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/"}
    
    SHA512 hash result example (lowercase hexadecimal):
    bfcd0c58c547c1d5960c73a6cf130cf5ae3f96d115392bdc678a36dab1ea08bdaf271b73db17650536a0a78d04d771557f9c5d71596e36547fb2089deb780784
    
    Step 2: Construct the Original Signature String
    Concatenate the signature string in the following format:
    Signature String = Request URI + SHA512 Hash + Timestamp
    For example:
    /v1/api/payment/initiatebfcd0c58c547c1d5960c73a6cf130cf5ae3f96d115392bdc678a36dab1ea08bdaf271b73db17650536a0a78d04d771557f9c5d71596e36547fb2089deb7807841699447297
    
    3
    Private Key Signing
    Use the merchant's RSA private key to sign the above signature string with SHA512withRSA
    Encode the signature result using Base64 to obtain the final signature string

    4. Security Description#

    Merchants sign using their private key, and the platform verifies using the merchant’s public key
    When the platform responds, it signs using its private key, and the merchant verifies using the platform's public key
    The overall mechanism ensures data integrity, request authenticity, and timeliness (prevents replay attacks)

    5. Notes#

    Signature generation is case-sensitive (all fields in the original string must match exactly)
    The JSON content should retain its original structure, as field order affects the hash
    Timestamp must be the current Unix timestamp (in seconds)
    The signature result is case-insensitive, and must be in standard Base64 format

    6. Code Examples#

    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 (for debugging)
            System.out.println("Signature: " + signatureBase64);
    
            // Send HTTP POST request
            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 string
        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 with 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 private key (PKCS#8 format)
        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();
            }
        }
    }
    
    Previous
    Introduction
    Next
    Signature Verification
    Built with