设置API身份验证

API 身份验证

要调用 FuturePay API,您需要一个 API 密钥。API 密钥是您的帐户独有的,并且是敏感信息,绝不能公开或在客户端使用。

每个 API 调用都必须包含 API 密钥,该密钥作为 Bearer 令牌在 HTTP 的 Authorization 请求头中传递。

您还必须在 HTTP 请求头中包含以下信息:MerchantId appId curTime

👍

沙盒与实时 API

要开始处理通过真实货币流动进行的付款,必须激活您的帐户,并且您需要使用 api.futurepay.global 主机而不是带有实时凭证的沙盒。

实时 API: https://api.futurepay.global

沙盒 API:https://api.futurepay-develop.com

提供无效的凭证将导致 401 未授权的响应状态代码。

{
    "message": "Unauthorized"
}

签名方法

package com.futurebank.pojo.utils;

import com.fasterxml.jackson.databind.ObjectMapper;

import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.math.BigDecimal;
import java.nio.charset.StandardCharsets;
import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidKeyException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Base64;
import java.util.*;

/**
 * @author ben
 * @date 2024/3/11 12:15
 **/
public class SingUtils {

    public static String getSign(Map<String, Object> params, String authKey) throws Exception {

        Map<String, Object> sortMap = new HashMap<>();
        sortMap.putAll(params);
        sortMap.remove("lineItems");

        // 排序参数并附加认证密钥
        String param = sortAndFormatParams(sortMap) + authKey;
        // 返回SHA-256哈希值
        return sha256(param);
    }

    public static String sha256(String str) {
        String encodeStr = "";
        try {
            MessageDigest digest = MessageDigest.getInstance("SHA-256");
            byte[] encodedhash = digest.digest(str.getBytes(StandardCharsets.UTF_8));
            encodeStr = bytesToHex(encodedhash);
        } catch (NoSuchAlgorithmException e) {
            throw new RuntimeException("algorithm not supported");
        }
        return encodeStr;
    }


    public static String sortAndFormatParams(Map<String, Object> params) throws Exception {
        // 创建排序的 TreeMap
        Map<String, Object> sortedMap = new TreeMap<>(params);
        StringBuilder sb = new StringBuilder();
        ObjectMapper mapper = new ObjectMapper();

        // 遍历排序后的Map
        for (Map.Entry<String, Object> entry : sortedMap.entrySet()) {
            String key = entry.getKey();
            Object value = entry.getValue();

            if (value == null) {
                continue;
            }

            String valueStr;
            if (value instanceof Map) {
                // 对嵌套的Map进行递归排序和格式化
                valueStr = mapper.writeValueAsString(sortAndFormatNestedMap((Map<String, Object>) value));
            } else if (value instanceof List) {
                // 对List进行排序和格式化
                valueStr = mapper.writeValueAsString(sortAndFormatList((List<Object>) value));
            } else {
                valueStr = objectToString(value);
            }

            // 将键值对添加到StringBuilder中
            sb.append(key).append("=").append(valueStr).append("&");
        }

        // 移除最后一个 '&' 字符
        if (sb.length() > 0) {
            sb.setLength(sb.length() - 1);
        }

        return sb.toString();
    }

    // 排序嵌套的Map对象的方法
    private static Map<String, Object> sortAndFormatNestedMap(Map<String, Object> nestedMap) {
        Map<String, Object> sortedNestedMap = new TreeMap<>();
        for (Map.Entry<String, Object> entry : nestedMap.entrySet()) {
            String key = entry.getKey();
            Object value = entry.getValue();

            if (value instanceof Map) {
                // 对嵌套的Map进行递归排序
                sortedNestedMap.put(key, sortAndFormatNestedMap((Map<String, Object>) value));
            } else if (value instanceof List) {
                // 对List进行递归排序
                sortedNestedMap.put(key, sortAndFormatList((List<Object>) value));
            } else {
                sortedNestedMap.put(key, value);
            }
        }
        return sortedNestedMap;
    }

    private static List<Object> sortAndFormatList(List<Object> list) {
        List<Object> sortedList = new ArrayList<>();
        for (Object item : list) {
            if (item instanceof Map) {
                sortedList.add(sortAndFormatNestedMap((Map<String, Object>) item));
            } else if (item instanceof List) {
                sortedList.add(sortAndFormatList((List<Object>) item));
            } else {
                sortedList.add(item);
            }
        }
        return sortedList;
    }

    // 将对象转换为字符串的方法
    private static String objectToString(Object obj) {
        if (obj instanceof BigDecimal) {
            return ((BigDecimal) obj).toPlainString();
        } else if (obj instanceof Double) {
            return obj.toString();
        } else if (obj instanceof Integer) {
            return obj.toString();
        } else if (obj instanceof String) {
            return (String) obj;
        } else {
            return obj.toString();
        }
    }

    // 将字节数组转换为十六进制字符串
    private static String bytesToHex(byte[] hash) {
        StringBuilder hexString = new StringBuilder(2 * hash.length);
        for (byte b : hash) {
            String hex = Integer.toHexString(0xff & b);
            if (hex.length() == 1) {
                hexString.append('0');
            }
            hexString.append(hex);
        }
        return hexString.toString();
    }
}