Aliexpress API 授权流程整理

 

前言

我零零总总用了好几个月的时间,写了一个自用的小程序,从 Aliexpress 上抓取订单的小程序。刚开始写的时候,该API还没有开放,而且没有订单相关的功能。我完全是通过模拟用户在网页上的操作来做的:获取网页源码,用正则取数据,然后组装到本地数据库。

期间经历过Ali 的数次微调,每次微调,我都要耗费几个小时做程序上的调整,最大的改动就是Ali 弄个新的 和 老的 订单展示页并存的时候。

最难的部分当数用户登陆部分,一次登陆,需要跨几个域,收集这几个域返回的 Cookie,收集好几个ajax返回的结果. Cookie 的问题,我用同一个 CookieContainer 解决了,但是 ajax 的,我还得老老实实的每个每个的按顺序去请求。

前两天,Ali 搞了一个小飞机,某状态下没有订单,分页居然有 2147483648 页,一看就是溢出了,正当我准备调整程序的时候,他们又神一般的把这个问题修复了。

数月前,我就申请成开发者账户,而且通过了,只是一直没有去研究。通过这次小飞机后,我决定,改用API获取订单数据,不在从网页抓取了。

开始

首先要注册成为开发者:

http://gw.api.alibaba.com/isv/index.htm

注册成功后,会分配给你一个应用的唯一标志:

其中:

Key 即为API 中说的 YOUR_APPKEY

签名串 即为 API 中说的YOUR_APPSECRET

API 说明可以打开如下地址:

http://gw.api.alibaba.com/dev/doc/sys_auth.htm?ns=aliexpress.open

获取授权步骤:

发起授权请求,用户同意授权后,返回 临时授权码,这里称为 Code

该步骤请求如下地址:

http://gw.api.alibaba.com/auth/authorize.htm?client_id=xxx&site=aliexpress&redirect_uri=urn:ietf:wg:oauth:2.0:oob

client_id 要填写 APPKEY

redirect_uri 是同意授权后回调的地址,因为我写的是客户端,不是WEB应用,所以当然没有回调地址,所以就用这个:urn:ietf:wg:oauth:2.0:oob

在请求之前,需要把上面的地址进行签名,把签名的值做为参数:_aop_signature的值,加到上面的地址里,一起请求,签名说明如下:

参数签名(_aop_signature)为所有参数key + value 字符串拼接后排序,把排序结果拼接为字符串data后通过bytesToHexString(HAMC-RSA1(data, appSecret))计算签名。验证签名的方式为对参数执行同样的签名,比较传入的签名结果和计算的结果是否一致,一致为验签通过。

注:只有客户端和WEB端授权流程发起授权请求这一步使用参数签名串组装规则,只用url请求参数作为签名因子;其他签名均需加入urlPath作为额外因子(见API签名串组装规则)。

Ali 给出了签名算法的C#示例:

http://gw.api.alibaba.com/dev/tools/app_signature.html

二,获取授权码

获取到临时码后,需要用 临时授权码 交换 授权码,所有的API都是通过授权码进行操作的

授权码获取地址:

https://gw.api.alibaba.com/openapi/http/1/system.oauth2/getToken/{0}?grant_type=authorization_code&need_refresh_token=true&client_id={1}&client_secret={2}&redirect_uri=urn:ietf:wg:oauth:2.0:oob&code={3}

其中:

{0}处和{1}处填写 APPKEY

{2} 处填写 APPSECRET

{3}处填写上一步获取到的那个临时授权码 Code

need_refresh_token 如果为 false 的话,不会返回用于刷新授权码的刷新码(我叫它刷新码).

返回的结果如下:

{"aliId":"xxx","resource_owner":"xxx","expires_in":"36000","refresh_token":"xxx","access_token":"xxx"}

expires_in 是授权码的过期时间(秒),10个小时 (60 x 60 x 10)。如果过了10小时,就需要刷新授权码。

refresh_token 是后面需要用的刷新码

access_token 即新的授权码

三,刷新授权令牌

授权令牌自生成时间起,会在10小时后过期,这时如果在访问API,返回的是401 未授权。当该状况发生时,需要刷新授权令牌。刷新授权令牌 不需要 重新获取 临时码

请求地址:

https://gw.api.alibaba.com/openapi/param2/1/system.oauth2/getToken/{0}

POST 如下数据:

grant_type 值为固定的 refresh_token

client_id 值为 APPKEY

client_secret 值为APPSECRET

refresh_token 即上一步中获取的令牌中的刷新码(refhreshToken)

刷新授权令牌 得到的结果 和用 临时授权码 得到的 授权令牌 大致一致,但是少了刷新码,因为刷新码的有效期为半年。

其它说明

令牌的刷新码(refreshToken),在API文档中,说是半年有效期,但是在令牌中并没有关于刷新码的过期时间信息。

授权令牌的有效期为10分钟,也就是说即使你退出了应用,重新打开,只要你能复现这个授权令牌,在10分钟内,是不需要重新授权,重新获取授权码的。

所以,在用临时码或刷新码获取到授权码后,应该把相关信息存起来,以便下次使用,因为从本文最上面的图片中可以看到,API 每日最大的调用次数为 1W 次。

业务逻辑和结构逻辑分离

不知道我这样说有没有什么不妥。

API的每个方法调用都需要有授权令牌。但是如果在这些方法里都加上相关的 是否以授权,是否有授权令牌 的判断代码,相信连你自己都觉得不妥。

这里,我管API方法的调用叫业务逻辑,判断是否授权等叫结构逻辑。

做过MVC的一定知道,ActionFilter 很好用,可以将和业务无关的逻辑分离出来,但是C# 并没有原生的类似ActoinFilter 的东西。查了一下,有个叫PostSharp 的东西,但是这个东西不免费。

我之前用过EntLib ,对里面的 PIAB (策略注入 Policy Injecton) 了解一点点,但是仅局限于用配置文件做。因为这里的目的很明确:判断是否有授权,用配置文件做我觉得不妥。搜了一把,很多牛人都写过相关的文章,就是用 PolicyInjection.Create 和 PolicyInjection.Wrap 方法,并结合 ICallHandler 接口,及 HandlerAttribute 来做。

  1. 1 [AttributeUsage(AttributeTargets.Class | AttributeTargets.Method)]
  2. 2 public class NeedAuthAttribute : HandlerAttribute {
  3. 3
  4. 4
  5. 5 public override ICallHandler CreateHandler(Microsoft.Practices.Unity.IUnityContainer container) {
  6. 6 return new NeedAuthHandler();
  7. 7 }
  8. 8 }
  1. 1 public class NeedAuthHandler : ICallHandler {
  2. 2 public IMethodReturn Invoke(IMethodInvocation input, GetNextHandlerDelegate getNext) {
  3. 3 var opts = input.Target as APIOpts;
  4. 4 if(opts.AuthToken == null)
  5. 5 opts.Auth( opts.User , opts.Pwd);
  6. 6 if(opts.AuthToken.HasExpiressed)
  7. 7 opts.RefreshAccessToken();
  8. 8 return getNext()(input, getNext);
  9. 9 }
  10. 10
  11. 11
  12. 12 public int Order {
  13. 13 get;
  14. 14 set;
  15. 15 }
  16. 16 }
  1.  

使用起来很简单,就是在需要做授权判断的方法上加上相关的 Attribute

  1. 1 [NeedAuth]
  2. 2 public OrderDetail FindOrderById(string orderNo) {
  3. 3 var url = this.GetApiUrl(OrderFindOrderByID)
  4. 4 .SetUrlKeyValue("orderId", orderNo);
  5. 5 var rh = new RequestHelper(this.CookieContainer);
  6. 6 var ctx = rh.Get(url);
  7. 7 return JsonConvert.DeserializeObject<OrderDetail>(ctx);
  8. 8 }

不过,上面的还不够,还需要在获取实例的时候:

  1. 1 private static APIOpts GetAPIOpts(string user, string pwd) {
  2. 2 var opts = AuthDataPersistence.Load(user);
  3. 3 if(opts == null)
  4. 4 opts = PolicyInjection.Create<APIOpts>(user, pwd);
  5. 5 else
  6. 6 opts = PolicyInjection.Wrap<APIOpts>(opts);
  7. 7 return opts;
  8. 8 }

好了,现在只需要在需要有授权的API方法上加上 NeedAuth 特性就行了,如果没有授权,就会自动去授权,如果需刷新授权码,就会自动刷新授权码,代码看起来清爽多了。

 
 

Aliexpress API 授权流程整理的更多相关文章

  1. Aliexpress API 授权流程整理(转载)

    前言 我零零总总用了好几个月的时间,写了一个自用的小程序,从 Aliexpress 上抓取订单的小程序.刚开始写的时候,该API还没有开放,而且没有订单相关的功能.我完全是通过模拟用户在网页上的操作来 ...

  2. 高德地图API(流程法)整理分析

    [高德地图API(流程法)分析]: 前言:公司现在的网约车项目,使用的是高德地图,因为地图导航这一块的功能占比量比较大,为了方便大家对高德地图API的了解和学习使用,使用流程图把高德API分析整理了下 ...

  3. Aliexpress API 测试工具

    Aliexpress API 测试工具 上回简单说了 Aliexpress API 的认证流程, 这回在奉送一个小工具, API 测试工具. 点我下载 做这一行,和做程序员的生活完全不搭调, 格格不入 ...

  4. spring cloud+dotnet core搭建微服务架构:Api授权认证(六)

    前言 这篇文章拖太久了,因为最近实在太忙了,加上这篇文章也非常长,所以花了不少时间,给大家说句抱歉.好,进入正题.目前的项目基本都是前后端分离了,前端分Web,Ios,Android...,后端也基本 ...

  5. 基于SPA的网页授权流程(微信OAuth2)

    先说传统MVC网站的网页授权流程. 1.用户发起了某个需要登录执行的操作 2.收集AppId等信息重定向到微信服务器 3.微信服务器回调到网站某个Controller的Action 4.在此Actio ...

  6. spring cloud+.net core搭建微服务架构:Api授权认证(六)

    前言 这篇文章拖太久了,因为最近实在太忙了,加上这篇文章也非常长,所以花了不少时间,给大家说句抱歉.好,进入正题.目前的项目基本都是前后端分离了,前端分Web,Ios,Android...,后端也基本 ...

  7. shiro框架学习-2-springboot整合shiro及Shiro认证授权流程

    1. 添加依赖 <dependency> <groupId>org.springframework.boot</groupId> <artifactId> ...

  8. 【认证与授权】Spring Security的授权流程

    上一篇我们简单的分析了一下认证流程,通过程序的启动加载了各类的配置信息.接下来我们一起来看一下授权流程,争取完成和前面简单的web基于sessin的认证方式一致.由于在授权过程中,我们预先会给用于设置 ...

  9. 基于 Aliexpress API 的小程序 : 批量 Copy 产品到不同的店铺

    第一个基于 Aliexpress API 的小程序 : 批量 Copy 产品到不同的店铺 还没来得及用 API 重写软件, 先写个小程序来缓解一下手工压力: 批量Copy 产品到不同的店铺. 开网店 ...

随机推荐

  1. ftk学习记录(button一片)

    [ 声明:版权所有所有.欢迎转载,请勿用于商业用途.  联系信箱:feixiaoxing @163.com] 前面,我们说到了label,这里能够看一下label执行的效果是怎么样的. waterma ...

  2. dojo的TabContainer添加ContentPane假设closable,怎么不闭幕后予以销毁ContentPane

    其主要思想是新的TabContainer的扩展类,重载其closeChild属性,使得其在关闭子容器时.不调用该子容器的destroyRecursive方法. define([ "dojo/ ...

  3. gpu显存(全局内存)在使用时数据对齐的问题

    全局存储器,即普通的显存,整个网格中的随意线程都能读写全局存储器的任何位置. 存取延时为400-600 clock cycles  很easy成为性能瓶颈. 訪问显存时,读取和存储必须对齐,宽度为4B ...

  4. final、finally、finalize差异

    final.finally.finalize差异 1.final修饰符 它代表了一类是完美的类,它不能被继承,因此.一个类不能既被标记为final类别.同一时间被标记为abstract. 将变量或者函 ...

  5. 使用QT来制作串口终端

    为什么要使用QT,因为它是跨平台的. 我现在使用的环境是Win7 64bit,使用VS的编译器来编译QT工程. 安装这套环境简单说一下:先到QT官网下载qt-windows-opensource-5. ...

  6. leetcode第五题--Longest Palindromic Substring

    Problem:Given a string S, find the longest palindromic substring in S. You may assume that the maxim ...

  7. Floodlight 启动过程分析

      1. 在Main中先是载入模块,启动REST服务,而后构建一个实现了IFloodlightProviderService接口的实例(即Controller)并执行: 2. 接下来进入Control ...

  8. [WebGL入门]十六,绘制多个模型

    注意:文章翻译http://wgld.org/.原作者杉本雅広(doxas),文章中假设有我的额外说明,我会加上[lufy:],另外.鄙人webgl研究还不够深入.一些专业词语.假设翻译有误.欢迎大家 ...

  9. iscroll4实现轮播图效果

    相信很多人和我一样,在使用iscroll的是时候只知道可以手动滑动,不知道iscroll的轮播怎么实现一下就是我做的一个轮播效果,亲测有效: 1.html,当然可以动态添加下面的小圆点 <div ...

  10. javascript图片延迟加载(转载)

    <!DOCTYPE HTML><html><head><meta http-equiv="Content-Type" content=&q ...