Skip to content

开放接口签名算法 ​

一、接口地址

https://您的ECShopX域名/api/openapi

二、系统级参数

参数名称是否必要类型描述
app_key是string应用 key,由接口提供方提前颁发
method是string接口方法名,根据接口提供
version是number版本号,默认 1.0
timestamp是datetime格式为 yyyy-mm-dd hh:mm:ss,允许最大时间误差 10 分钟
sign是stringAPI 输入参数签名结果,签名算法参考本页「签名算法」

请求方式说明:所有参数使用 POST 提交,业务参数与系统级参数一并上传。

三、业务参数

业务参数请参考具体api

四、签名算法

签名算法说明:

1 将所有请求参数(key,value 为一组),对数据结构按照key的升序,重新排序

a 需要对null值进行过滤

b 需要将boolean型进行转换为1和0

2 将排序后参数组合为新的字符串 (keyvaluekeyvalue 中间无分割符)

3 将生成好的字符串前后加上“私钥”,形成新的字符串

4 将生成好的字符串进行MD5加密,得到加密后的字符串

5 再统一为大写字符串,得到最终的签名字符串

注意:从“系统级参数”开始到“业务级参数”全部作为请求参数。 sign可以不算入,如果放进去,开始sign = null ,也会被过滤掉的。其中的app_key、token可以对应后台菜单“开发接口配置”中的app_key对应其中“销售中心开发设置”,token对应“SECRET”

五、调用示例

设置请求参数公共参数:

method = "order.get"
app_key = "test001"
access_token = "token001"
timestamp = "2020-07-20 12:00:00"
version = "1.0"

业务参数:

order_id = "11223344"

按 ASCII 顺序排序:

access_token = "token001"
app_key = "test001"
method = "order.get"
order_id = "11223344"
timestamp = "2020-07-20 12:00:00"
version = "1.0"

拼接参数名与参数值(假设 secret = "aaaa",由接口服务提供方颁发),拼接的字符串为:

aaaaccess_tokentoken001app_keytest001methodorder.getorder_id11223344timestamp2020-07-20 12:00:00version1.0aaaa

对上述字符串做 MD5 并转大写,即得到签名字符串。

六、注意事项

所有的请求和响应数据编码皆为utf-8格式,URL里的所有参数名和参数值请做URL编码。

POST 请求时 如果请求的Content-Type是application/x-www-form-urlencoded,则HTTP Body体里的所有参数值也做URL编码;

如果是multipart/form-data格式,每个表单字段的参数值无需编码,但每个表单字段的charset部分需要指定为utf-8。

七、Java 签名示例

java
import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
import java.util.Map;
import java.util.TreeMap;
import java.util.stream.Collectors;

public final class OpenapiSignUtil {

    private OpenapiSignUtil() {}

    public static String sign(Map<String, ?> params, String secret) {
        TreeMap<String, String> sorted = new TreeMap<>();
        params.forEach((key, value) -> {
            if (value == null) {
                return;
            }
            if (value instanceof Boolean b) {
                sorted.put(key, b ? "1" : "0");
            } else {
                sorted.put(key, String.valueOf(value));
            }
        });
        String body = sorted.entrySet().stream()
                .map(e -> e.getKey() + e.getValue())
                .collect(Collectors.joining());
        return md5Upper(secret + body + secret);
    }

    private static String md5Upper(String input) {
        try {
            MessageDigest md = MessageDigest.getInstance("MD5");
            byte[] digest = md.digest(input.getBytes(StandardCharsets.UTF_8));
            StringBuilder sb = new StringBuilder();
            for (byte b : digest) {
                sb.append(String.format("%02x", b));
            }
            return sb.toString().toUpperCase();
        } catch (Exception e) {
            throw new IllegalStateException(e);
        }
    }
}