zzz

时间:2022-09-05 14:59:58

开放平台(TOP)的API是基于HTTP协议来调用的,开发者(ISV)可以直接使用TOP提供的官方SDK(支持多种语言,包含了请求的封装,签名加密,响应解释,性能优化等)来调用,也可以根据TOP的协议来封装HTTP请求进行调用,以下主要是针对自行封装HTTP请求进行API调用的原理进行详细解说。

调用流程

根据TOP的协议:填充参数 > 生成签名 > 拼装HTTP请求 > 发起HTTP请求> 得到HTTP响应 > 解释json/xml结果,以下是大体的调用过程示意图:

zzz

调用入口

调用API的服务URL地址,开放平台目前提供了4个环境给ISV使用:沙箱测试环境,正式测试环境,正式环境,海外环境。

  • 沙箱测试环境: ISV软件的测试环境,应用创建后即可使用。此环境提供简化版的淘宝网,支持大部分场景的API调用,沙箱环境的权限和流量均无限制,可放开使用。
  • 正式测试环境: ISV软件上线之前的正式模拟环境,应用创建成功后即可使用。此环境主要是针对部分无法在沙箱完成测试的场景使用,限制API调用为5000次/天,授权用户数量为5个,所能调用的API与应用拥有的权限能力一致。
  • 正式环境: ISV软件上线之后使用的环境,此环境的入口与正式测试环境一致,只不过应用上线之后,流量限制会进行打开,具体流量限制与应用所属类目有关,比如服务市场类的应用,限制API调用为100万次/天。
  • 海外环境: 海外环境也属于正式环境的一种,主要是给海外(欧美国家)ISV使用,对于海外的ISV,使用海外环境会比国内环境的性能高一倍。
调用环境 服务地址(HTTP) 服务地址(HTTPS)
沙箱环境 http://gw.api.tbsandbox.com/router/rest https://gw.api.tbsandbox.com/router/rest
正式环境 http://gw.api.taobao.com/router/rest https://eco.taobao.com/router/rest
海外环境 http://api.taobao.com/router/rest https://api.taobao.com/router/rest

公共参数

调用任何一个API都必须传入的参数,目前支持的公共参数有:

参数名称 参数类型 是否必须 参数描述
method String API接口名称。
app_key String TOP分配给应用的AppKey。这里要注意正式环境和沙箱环境的AppKey是不同的(包括AppSecret),使用时要注意区分;进入开放平台控制台“应用管理-概览” 和 “应用管理-沙箱环境管理”可分别查看正式环境及沙箱环境的AppKey、AppSecret
session String 用户登录授权成功后,TOP颁发给应用的授权信息,详细介绍请点击这里。当此API文档的标签上注明:“需要授权”,则此参数必传;“不需要授权”,则此参数不需要传;“可选授权”,则此参数为可选。
timestamp String 时间戳,格式为yyyy-MM-dd HH:mm:ss,时区为GMT+8,例如:2016-01-01 12:00:00。淘宝API服务端允许客户端请求最大时间误差为10分钟。
format String 响应格式。默认为xml格式,可选值:xml,json。
v String API协议版本,可选值:2.0。
partner_id String 合作伙伴身份标识。
target_app_key String 被调用的目标AppKey,仅当被调用的API为第三方ISV提供时有效。
simplify Boolean 是否采用精简JSON返回格式,仅当format=json时有效,默认值为:false。
sign_method String 签名的摘要算法,可选值为:hmac,md5。
sign String API输入参数签名结果,签名算法参照下面的介绍。

业务参数

API调用除了必须包含公共参数外,如果API本身有业务级的参数也必须传入,每个API的业务级参数请考API文档说明。

签名算法

为了防止API调用过程中被黑客恶意篡改,调用任何一个API都需要携带签名,TOP服务端会根据请求参数,对签名进行验证,签名不合法的请求将会被拒绝。TOP目前支持的签名算法有两种:MD5(sign_method=md5),HMAC_MD5(sign_method=hmac),签名大体过程如下:

  • 对所有API请求参数(包括公共参数和业务参数,但除去sign参数和byte[]类型的参数),根据参数名称的ASCII码表的顺序排序。如:foo=1, bar=2, foo_bar=3, foobar=4排序后的顺序是bar=2, foo=1, foo_bar=3, foobar=4。
  • 将排序好的参数名和参数值拼装在一起,根据上面的示例得到的结果为:bar2foo1foo_bar3foobar4。
  • 把拼装好的字符串采用utf-8编码,使用签名算法对编码后的字节流进行摘要。如果使用MD5算法,则需要在拼装的字符串前后加上app的secret后,再进行摘要,如:md5(secret+bar2foo1foo_bar3foobar4+secret);如果使用HMAC_MD5算法,则需要用app的secret初始化摘要算法后,再进行摘要,如:hmac_md5(bar2foo1foo_bar3foobar4)。
  • 将摘要得到的字节流结果使用十六进制表示,如:hex(“helloworld”.getBytes(“utf-8”)) = “68656C6C6F776F726C64”

说明:MD5和HMAC_MD5都是128位长度的摘要算法,用16进制表示,一个十六进制的字符能表示4个位,所以签名后的字符串长度固定为32个十六进制字符。

JAVA签名示例代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
public static String signTopRequest(Map<String, String> params, String secret, String signMethod) throws IOException {
    // 第一步:检查参数是否已经排序
    String[] keys = params.keySet().toArray(new String[0]);
    Arrays.sort(keys);
 
    // 第二步:把所有参数名和参数值串在一起
    StringBuilder query = new StringBuilder();
    if (Constants.SIGN_METHOD_MD5.equals(signMethod)) {
        query.append(secret);
    }
    for (String key : keys) {
        String value = params.get(key);
        if (StringUtils.areNotEmpty(key, value)) {
            query.append(key).append(value);
        }
    }
 
    // 第三步:使用MD5/HMAC加密
    byte[] bytes;
    if (Constants.SIGN_METHOD_HMAC.equals(signMethod)) {
        bytes = encryptHMAC(query.toString(), secret);
    } else {
        query.append(secret);
        bytes = encryptMD5(query.toString());
    }
 
    // 第四步:把二进制转化为大写的十六进制
    return byte2hex(bytes);
}
 
public static byte[] encryptHMAC(String data, String secret) throws IOException {
    byte[] bytes = null;
    try {
        SecretKey secretKey = new SecretKeySpec(secret.getBytes(Constants.CHARSET_UTF8), "HmacMD5");
        Mac mac = Mac.getInstance(secretKey.getAlgorithm());
        mac.init(secretKey);
        bytes = mac.doFinal(data.getBytes(Constants.CHARSET_UTF8));
    } catch (GeneralSecurityException gse) {
        throw new IOException(gse.toString());
    }
    return bytes;
}
 
public static byte[] encryptMD5(String data) throws IOException {
    return encryptMD5(data.getBytes(Constants.CHARSET_UTF8));
}
 
public static String byte2hex(byte[] bytes) {
    StringBuilder sign = new StringBuilder();
    for (int i = 0; i < bytes.length; i++) {
        String hex = Integer.toHexString(bytes[i] & 0xFF);
        if (hex.length() == 1) {
            sign.append("0");
        }
        sign.append(hex.toUpperCase());
    }
    return sign.toString();
}

C#签名示例代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
public static string SignTopRequest(IDictionary<string, string> parameters, string secret, string signMethod)
{
    // 第一步:把字典按Key的字母顺序排序
    IDictionary<string, string> sortedParams = new SortedDictionary<string, string>(parameters, StringComparer.Ordinal);
    IEnumerator<KeyValuePair<string, string>> dem = sortedParams.GetEnumerator();
 
    // 第二步:把所有参数名和参数值串在一起
    StringBuilder query = new StringBuilder();
    if (Constants.SIGN_METHOD_MD5.Equals(signMethod))
    {
        query.Append(secret);
    }
    while (dem.MoveNext())
    {
        string key = dem.Current.Key;
        string value = dem.Current.Value;
        if (!string.IsNullOrEmpty(key) && !string.IsNullOrEmpty(value))
        {
            query.Append(key).Append(value);
        }
    }
 
    // 第三步:使用MD5/HMAC加密
    byte[] bytes;
    if (Constants.SIGN_METHOD_HMAC.Equals(signMethod))
    {
        HMACMD5 hmac = new HMACMD5(Encoding.UTF8.GetBytes(secret));
        bytes = hmac.ComputeHash(Encoding.UTF8.GetBytes(query.ToString()));
    }
    else
    {
        query.Append(secret);
        MD5 md5 = MD5.Create();
        bytes = md5.ComputeHash(Encoding.UTF8.GetBytes(query.ToString()));
    }
 
    // 第四步:把二进制转化为大写的十六进制
    StringBuilder result = new StringBuilder();
    for (int i = 0; i < bytes.Length; i++)
    {
        result.Append(bytes[i].ToString("X2"));
    }
 
    return result.ToString();
}

其他语言签名示例代码请参见TOP官方SDK源代码。

调用示例

taobao.item.seller.get调用为例,具体步骤如下:

1. 设置参数值

公共参数:

  • method = “taobao.item.seller.get”
  • app_key = “12345678”
  • session = “test”
  • timestamp = “2016-01-01 12:00:00”
  • format = “json”
  • v = “2.0”
  • sign_method = “md5”

业务参数:

  • fields = “num_iid,title,nick,price,num”
  • num_iid = 11223344

2. 按ASCII顺序排序

  • app_key = “12345678”
  • fields = “num_iid,title,nick,price,num”
  • format = “json”
  • method = “taobao.item.seller.get”
  • num_iid = 11223344
  • session = “test”
  • sign_method = “md5”
  • timestamp = “2016-01-01 12:00:00”
  • v = “2.0”

3. 拼接参数名与参数值

1
app_key12345678fieldsnum_iid,title,nick,price,numformatjsonmethodtaobao.item.seller.getnum_iid11223344sessiontestsign_methodmd5timestamp2016-01-01 12:00:00v2.0

4. 生成签名
假设app的secret为helloworld,则签名结果为:hex(md5(helloworld+按顺序拼接好的参数名与参数值+helloworld)) = “66987CB115214E59E6EC978214934FB8”

5. 组装HTTP请求
将所有参数名和参数值采用utf-8进行URL编码(参数顺序可随意,但必须要包括签名参数),然后通过GET或POST(含byte[]类型参数)发起请求,如:

1
http://gw.api.taobao.com/router/rest?method=taobao.item.seller.get&app_key=12345678&session=test&timestamp=2016-01-01+12%3A00%3A00&format=json&v=2.0&sign_method=md5&fields=num_iid%2Ctitle%2Cnick%2Cprice%2Cnum&num_iid=11223344&sign=66987CB115214E59E6EC978214934FB8

注意事项

  • 所有的请求和响应数据编码皆为utf-8格式,URL里的所有参数名和参数值请做URL编码。如果请求的Content-Type是application/x-www-form-urlencoded,则HTTP

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

  • 参数名与参数值拼装起来的URL长度小于1024个字符时,可以用GET发起请求;参数类型含byte[]类型或拼装好的请求URL过长时,必须用POST发起请求。所有API都可以用POST发起请求。
  • 如需需要在沙箱环境测试,请在应用控制台的沙箱管理页面获取沙箱环境对应的app_key(一般为正式环境的app_key前面加上“10”)和app_secret,对应的session值也用沙箱帐号登录授权获得,沙箱环境授权和正式环境授权类似,详细可参考用户授权介绍
  • 生成签名(sign)仅对未使用TOP官方SDK进行API调用时需要操作,如使用了TOP官方SDK,该步骤SDK会自动完成。

FAQ

接口调用报签名错误“ Invalid signature”

zzz的更多相关文章

  1. Org-mode五分钟教程ZZZ - Kaka Abel的日志 - 网易博客

    Org-mode五分钟教程ZZZ - Kaka Abel的日志 - 网易博客 Org-mode五分钟教程ZZZ  

  2. jquery cdn&sol;&sol;&sol;&sol;&sol;&sol;&sol;&sol;&sol;&sol;&sol;&sol;&sol;&sol;&sol;&sol;&sol;zzz

    jquery-2.1.1 注:jquery-2.0以上版本不再支持IE 6/7/8)百度引用地址 (推荐目前最稳定的,不会出现延时打不开情况) 百度压缩版引用地址:<script src=&qu ...

  3. 关于nodejs能同时接受多少个请求的问题?&sol;&sol;&sol;&sol;zzz

    关于nodejs能同时接受多少个请求的问题? 最近学习node,看了很多教程,都在赞扬nodejs的异步I/O,异步I/O的特点就是,每接收一个请求,使用异步调用处理请求,不用等待结果,可以继续运行其 ...

  4. 箭头函数 Arrow Functions&sol;&sol;&sol;&sol;&sol;&sol;&sol;&sol;&sol;&sol;&sol;&sol;&sol;&sol;&sol;&sol;&sol;&sol;&sol;&sol;&sol;zzz

    箭头符号在JavaScript诞生时就已经存在,当初第一个JavaScript教程曾建议在HTML注释内包裹行内脚本,这样可以避免不支持JS的浏览器误将JS代码显示为文本.你会写这样的代码: < ...

  5. 创建 MIME 类型&sol;&sol;&sol;&sol;&sol;&sol;&sol;&sol;&sol;&sol;&sol;&sol;zzz

    用 Apache 创建 MIME 类型 在 Apache 里, MIME 类型和文件扩展名之间的映射是被存放在配置文件 "apache根目录/conf/mime.types" 里的 ...

  6. HTML5的Server-Sent Events介绍&sol;&sol;&sol;&sol;&sol;&sol;&sol;&sol;&sol;&sol;&sol;&sol;&sol;&sol;&sol;&sol;zzz

    HTML5有一个Server-Sent Events(SSE)功能,允许服务端推送数据到客户端.(通常叫数据推送).我们来看下,传统的WEB应用程序通信时的简单时序图: 现在Web App中,大都有A ...

  7. Linux Ubuntu 16&period;04 初次安装使用总结zzz

    装了两天的ubuntu系统终于算是勉强能用了,来来回回装了有三四次,期间出了各种各样的毛病.但是还是被我的Google大法给治好了.为了装这个系统,算是耗了两天的时间,啥事情都没干,干耗在这上面了.所 ...

  8. 三位数流水码的生成(000&&num;183&semi;&&num;183&semi;&&num;183&semi;&&num;183&semi;&&num;183&semi;009&&num;183&semi;&&num;183&semi;00A&&num;183&semi;&&num;183&semi;&&num;183&semi;&&num;183&semi;00Z&&num;183&semi;&&num;183&semi;&&num;183&semi;&&num;183&semi;ZZZ)

    //规格代码的生成 private String getCode (String code) { char[] chars=code.toCharArray(); if (chars[2]==57){ ...

  9. Tony的口胡呼呼&lpar;。-ω-&rpar;zzz

    三分 给定平面内 \(n <= 2000\) 个节点, 求平面内一点使得到所有点的欧几里得距离和最小 确定 \(y\) 轴时 \(x\) 轴满足单峰函数 \(x\) 轴同理 三分套三分即可 深度 ...

随机推荐

  1. Avast&excl;:小型网站最易遭受的3种黑客攻击

    avast是捷克研发的杀毒软件,从网站上找到一篇avast关于网站安全的文章,觉得颇有意思,因此想到翻译过来与大家共享.有不对之处还望大家批评指正. 一个拥有上万访问者的小型网站管理员发来一份信,向我 ...

  2. 多线程同步循环打印和Guarded suspension 模式

     * 迅雷笔试题: * 有三个线程ID分别是A.B.C,请有多线编程实现,在屏幕上循环打印10次ABCABC…  由于线程执行的不确定性,要保证这样有序的输出,必须控制好多线程的同步. 线程同步有两种 ...

  3. 当启动tomcat时出现tomcat setting should be set in tomcat preference page

    转自:https://blog.csdn.net/withyou_wy/article/details/53081800 出现此状况证明你的tomcat在配置的时候没有配置成功,通过以下两个步骤即可以 ...

  4. jsp连接数据库的乱码问题 servlet请求参数编码处理get post

    1.在所有需要读取数据的地方用下面的方式.同时jsp必须统一编码,如我都是UTF-8 String userName= new String(request.getParameter("us ...

  5. sql先分组,再算百分比

    --先分组,再算百分比 SELECT  a.CooperationIntention ,         a.OrganizationID ,         COUNT(*) 数量 , CONVER ...

  6. ProtoBuffer使用笔记

    ProtoBuffer是由谷歌研发的对象序列化和反序列化的开源工具,ProtoBuffer和Xml类似,都是数据描述工具,后者使用更为广泛,前者Google内部使用且具有更高的效率.该工具安装和使用都 ...

  7. &lbrack;置顶&rsqb; hdu 4418 高斯消元解方程求期望

    题意:  一个人在一条线段来回走(遇到线段端点就转变方向),现在他从起点出发,并有一个初始方向, 每次都可以走1, 2, 3 ..... m步,都有对应着一个概率.问你他走到终点的概率 思路: 方向问 ...

  8. JAVA数据类型能串门不?

    JAVA这几种数据类型,能否串门?入了人家门,就得按人家规矩来,入乡随俗哦,难免发生有自觉的 还有不情愿被动的. 自动类型转换 自动类型转换:容量小的数据类型可以自动转换为容量大的数据类型.在图中,黑 ...

  9. Kali 安装VMtools(最新)

    老方法安装的VMtools不能进行主宿切换,下面是kali最新版安装VMtools的方法 一.换国内源&更新源 参考 Kali 2017更新源 二.安装VMtools apt-get inst ...

  10. Matlab实现图像分割 分类: 图像处理 2014-06-14 21&colon;31 662人阅读 评论&lpar;1&rpar; 收藏

    下面使用极小值点阈值选取方法,编写MATLAB程序实现图像分割的功能. 极小值点阈值选取法即从原图像的直方图的包络线中选取出极小值点, 并以极小值点为阈值将图像转为二值图像 clear all; cl ...