Finix
    Finix
    • Finix API 文档
    • 介绍
    • 签名
    • 验签
    • 印度
      • 收款
        • 创建收款
        • 查询收款状态
        • 收款异步通知
      • 代付
        • 创建代付
        • 查询代付状态
        • 代付异步通知
    • 尼日利亚
      • 收款
        • 创建收款
        • 查询收款状态
        • 收款异步通知
      • 代付
        • 创建代付
        • 查询代付状态
        • 代付异步通知
        • 银行编号
    • 印度尼西亚
      • 收款
        • 创建收款
        • 查询收款状态
        • 收款异步通知
      • 代付
        • 创建代付
        • 查询代付状态
        • 代付异步通知
        • 银行编号
    • 账户余额
      POST
    • USDT汇率
      POST

    签名

    RSA-SHA512 接口签名机制说明#

    一、签名目的#

    为确保接口调用的安全性与完整性,平台采用 RSA 非对称加密结合 SHA512 摘要算法的签名机制(SHA512withRSA)。该机制用于验证请求方身份、防止数据篡改和防止重放攻击。

    二、签名使用场景#

    签名应用于商户与Finix之间的所有API接口交互

    三、签名结构与规则#

    在进行接口调用时,客户端需在请求 Header 中携带签名字段 Signature,用于标识当前请求的合法性。
    1
    签名算法
    摘要算法:SHA512(Secure Hash Algorithm 512 位)
    加密算法:RSA(使用商户私钥进行签名)
    签名算法全称:SHA512withRSA
    2
    签名过程
    步骤一:计算请求体摘要(Body Hash)
    对接口请求的 BODY 原始 JSON 字符串 使用 SHA512 哈希算法计算摘要。
    若请求方式为 GET,则视为 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/"}
    
    计算 SHA512 后结果示例(小写十六进制):
    bfcd0c58c547c1d5960c73a6cf130cf5ae3f96d115392bdc678a36dab1ea08bdaf271b73db17650536a0a78d04d771557f9c5d71596e36547fb2089deb780784
    
    步骤二:构造签名原文字符串
    拼接签名字符串,格式如下:
    签名原文 = 请求路径URI + SHA512摘要 + 时间戳(Timestamp)
    例如:
    /v1/api/payment/initiatebfcd0c58c547c1d5960c73a6cf130cf5ae3f96d115392bdc678a36dab1ea08bdaf271b73db17650536a0a78d04d771557f9c5d71596e36547fb2089deb7807841699447297
    
    3
    私钥签名
    使用商户的 RSA 私钥,对上述签名原文进行 SHA512withRSA 签名。
    签名结果进行 Base64 编码,得到最终签名字符串。

    四、安全性说明#

    商户使用其 私钥签名,平台使用商户提供的 公钥验签。
    平台响应时,反向使用平台私钥签名,商户使用平台公钥验签。
    整体机制保证数据不可篡改、请求身份可验证,并具备时效性(避免重放攻击)。

    五、注意事项#

    签名时区分大小写(签名原文中的字段需严格一致)
    JSON 内容应保持原始结构,避免字段顺序改变影响摘要
    Timestamp 应为当前 Unix 时间戳(单位秒)
    签名结果不区分大小写,统一使用 Base64 标准格式

    六、代码示例#

    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 {
            // 请求参数
            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";
    
            // 加载私钥
            String privateKeyPem = "-----BEGIN PRIVATE KEY-----\n" + YOUR_PRIVATE_KEY_CONTENT_HERE + "\n-----END PRIVATE KEY-----";
            PrivateKey privateKey = getPrivateKeyFromPem(privateKeyPem);
    
            // 生成签名
            String bodyHash = sha512Hex(body);
            String stringToSign = uri + bodyHash + timestamp;
            String signatureBase64 = sign(stringToSign, privateKey);
    
            // 打印签名(调试用)
            System.out.println("Signature: " + signatureBase64);
    
            // 发起 HTTP POST 请求
            String apiUrl = "https://secure-staging.finixpayment.com" + uri;
            String response = sendHttpPost(apiUrl, body, merchantId, signatureBase64, timestamp);
    
            System.out.println("Response: " + response);
        }
    
        // 计算 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();
        }
    
        // 生成签名(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);
        }
    
        // 读取私钥(PKCS#8 格式)
        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);
        }
    
        // 发送 HTTP POST 请求
        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
    介绍
    Next
    验签
    Built with