1.前言
分享一个的我最近完成的开放平台设计
2.简介
开放平台(以下简API) 是为供应商和分销商(以下简称开发人员)开放的API 接口,开发人员可以通过调用搜物API接口,快速的实现和搜物网的数据交换。搜物API支持Json 格式和XML数据格式进行数据交换,搜物API 根据你传入的数据格式返回对应的数据,如你传入的是是XML搜物API将返回Xml 格式数据如是Json 则返回Json格式数据
3.总体架构
如上图所示,这里采用了分层来的思想开发本系统
l HelperLogic 助手类
l CahceLogic 缓存部分静态数据,
l DataLogic 数据库业务层
l OrderLogic 订单逻辑层
l ProductLogic 产品逻辑层
l purviewLogic 鉴权逻辑层
l LogisticsLogic 物流模板逻辑层
4.业务逻辑处理
5.签名算法
- 把请求中的参数 除了Signature 外 按照参数名称进行正向排序
- 把所有参数名和参数值串在一起(不能有空格)
- 把后台设置的key值串接到“第二步”得到的字符串尾部(不能有空格)
- 采用MD5算法对“第三步”得到的字符串进行加密,生成Signature的值
/// <summary> /// 获取签名字符串 /// </summary> /// <param name="parameters">所有字符型的请求参数</param> /// <param name="secret">签名密钥(即搜物APIKey)</param> /// <returns>签名</returns> public static string GetSignatureStr(IDictionary<string, string> parameters, string secret) { parameters.Remove("Signature"); // 第一步:把字典按Key的字母顺序排序 IDictionary<string, string> sortedParams = new SortedDictionary<string, string>(parameters); IEnumerator<KeyValuePair<string, string>> dem = sortedParams.GetEnumerator(); // 第二步:把所有参数名和参数值串在一起 StringBuilder query = new StringBuilder(); while (dem.MoveNext()) { string key = dem.Current.Key; string value = dem.Current.Value; if (!string.IsNullOrEmpty(key) && !string.IsNullOrEmpty(value)) { query.Append(key + "=" + value + "&"); } } query.Append("key=" + secret); // 第三步:使用MD5加密 MD5 md5 = MD5.Create(); byte[] bytes = md5.ComputeHash(Encoding.UTF8.GetBytes(query.ToString())); // 第四步:把二进制转化为大写的十六进制 StringBuilder result = new StringBuilder(); for (int i = 0; i < bytes.Length; i++) { string hex = bytes[i].ToString("X"); if (hex.Length == 1) { result.Append("0"); } result.Append(hex); } return result.ToString(); }
6.安全性考虑
1.权限接口控制
2.异常访问
1.在30分钟内,10次签名出错,认为账号异常
2.访问过于频繁
3.手动添加黑名单
3.用户可追溯性
我们主要实现2点功能 1. 记录用户的访问操作,比如访问那些接口,上传了那些数据, 2.对于重要的数据的可追溯性,如商品价格,库存等 3. 记录每个请求耗时多久 为了实现以上3点功能,我们在这里引入log4net 做为日志系统,减少开发工作量
7.POST 数据和返回数据格式参考
[XmlRoot(ElementName = "DataPost")] public class DataPostCommon { /// <summary> /// 方法名 /// </summary> [XmlElement(ElementName = "MethodsName")] public string MethodsName { get; set; } /// <summary> /// ApiGuid /// </summary> [XmlElement(ElementName = "ApiGuid")] public string ApiGuid { get; set; } /// <summary> /// 数据签名 /// </summary> [XmlElement(ElementName = "Signature")] public string Signature { get; set; } } [XmlRoot(ElementName = "DataPost")] /// <summary> /// 用户Post 数据格式 /// </summary> public class DataPost<T> : DataPostCommon { [XmlElement(ElementName = "Parameters")] public T Parameters { get; set; } }
/// <summary> /// 服务返回 /// </summary> [XmlRoot(ElementName = "SeverReturn")] public class SeverReturn<T> { public SeverReturn() { ErrNo = ErrorNo.IsSuccess; } /// <summary> /// 错误代码 /// </summary> [XmlElement(ElementName = "ErrNo")] public int ErrNo { get; set; } /// <summary> /// 错误描述 /// </summary> [XmlElement(ElementName = "ErrorDesc")] public string ErrorDesc { get; set; } [XmlElement(ElementName = "RunResults")] public T RunResults { get; set; } } }