开放接口签名算法
一、接口地址
https://您的ECShopX域名/api/openapi
二、系统级参数
| 参数名称 | 是否必要 | 类型 | 描述 |
|---|---|---|---|
| app_key | 是 | string | 应用 key,由接口提供方提前颁发 |
| method | 是 | string | 接口方法名,根据接口提供 |
| version | 是 | number | 版本号,默认 1.0 |
| timestamp | 是 | datetime | 格式为 yyyy-mm-dd hh:mm:ss,允许最大时间误差 10 分钟 |
| sign | 是 | string | API 输入参数签名结果,签名算法参考本页「签名算法」 |
请求方式说明:所有参数使用 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 签名示例
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);
}
}
}