在我们的业务中不可避免要与第三方的系统进行交互,调用他们提供的API来获取相应的数据,那么对于这样的情况该怎样进行处理呢?下面就结合自己对接跨越速运接口来获取一个发运单完整的物流信息为例来说明如何在Asp.Net Core中通过代码实现。当然在他们的官方网站上面会给出具体的API调用方式以及参数格式,作为调用方只需要根据相应规则来进行编码即可,下面以我们查询某一个具体的发运单的物流信息为例来进行说明。

  下面以一个查询路由详细信息为例来进行说明。当前接口主要包括:1 概述。 2 系统参数。 3  业务参数。 4 业务参数。5 返回结果。6 响应数据格式。7 调用示例(Java语言)。这里主要是来说明如何使用C#语言来进行调用,其它语言的思路其实也是一样的。

  一 构造HttpClient对象

  这里建议使用IHttpClientFactory这个接口来创建httpClient而不是直接new一个对象,至于具体原因网上有很多原因,具体理由也是IHttpClientFactory创建的HttpClient对象能够在使用完得到更好的释放资源的效果。在Asp.Net Core中直接在构造函数中注入IHttpClientFactory接口,然后采用CreateClient方法来创建对象。  

 public LogisticsService(IHttpClientFactory httpClientFactory) {
_httpClient = httpClientFactory.CreateClient(PartsConsts.DcsPartClientName);
}

  这个CreateClient方法中需要传一个标识你现在使用的HttpClient的名称。

  二 获取参数Token

  按照他们的API规范中说的,在Headers中需要进行Token传递的,这个称之为请求票据,没有这个是无法进行验证的,首先我们需要定义一个用于请求Token的数据结构,同时还需要根据他们的规范来定义一个接收Token的数据结构。

  A   请求Token的数据结构  

public class LogisticsUser {
public string appkey { get; set; } public string appsecret { get; set; }
}

  B 接收Token的数据结构

public class CodeMsg {
public int Code { get; set; }
public string Msg { get; set; }
public bool Success { get; set; }
} public class TokenResult : CodeMsg {
public TokenData Data { get; set; }
} public class TokenData {
public string Refresh_token { get; set; } public int Expire_time { get; set; } public string Token { get; set; }
}

  C 同步请求方法

 /// <summary>
/// 同步请求post(键值对形式)
/// </summary>
/// <param name="url"></param>
/// <param name="postdate"></param>
/// <param name="formData"></param>
/// <param name="charset"></param>
/// <param name="mediaType"></param>
/// <returns></returns>
public async Task<string> HttpPostAsync(string url, string postdate = null, List<KeyValuePair<string, string>> formData = null,
string charset = "UTF-8", string mediaType = "application/json") { HttpContent content = new StringContent(postdate);
content.Headers.ContentType = new MediaTypeHeaderValue(mediaType) {
CharSet = charset
};
foreach (var data in formData) {
content.Headers.Add(data.Key, data.Value);
}
var response = await _httpClient.PostAsync(url, content); var result = await response.Content.ReadAsStringAsync(); return result;
}

  这个方法是一个常规的异步请求方法,这里使用HttpContent作为数据载体,将一些重要的系统参数添加到Headers里面,将业务参数传递到StringContent的构造函数中去,最后调用PostAsync异步方法发送Post请求,请求完了通过返回的Response来获取返回的数据,通过这种方式来获取完整的数据结构。这里特别需要注意如果第一次请求Token失败则可以再次请求重新刷新Token,最后将获取的Json类型Token反序列化为我们定义的TokenResult结构,这样我们就能够正常获取到Token数据了。

  三 获取发运单数据

  我们之前所有的工作都是为了能够获取到最终的业务数据,那么这里我们也是一样,首先要定义请求和接收数据的数据结构,首先是请求的数据结构。

 public class LogisticsInputModel {
[JsonProperty("customerCode")]
public string CustomerCode { get; set; } [JsonProperty("waybillNumbers")]
public string[] WaybillNumbers { get; set; }
}

  这里面CustomerCode是我们用户编码,这个是唯一的,这是跨越速运官方给予的用户凭证,第二个WaybillNumbers 就是我们需要查询的发运单的集合,这里的接口支持一次性查询多个发运单数据,所以接口使用string[ ]数组类型。

  下面来说一下根据官方定义来定义查询物流信息的接口定义。

    /// <summary>
/// 跨越速运查询物流信息接口
/// </summary>
public class LogisticInfoModel {
public string Code { get; set; } public string Msg { get; set; } public bool? Success { get; set; } public DataInfo Data { get; set; } public string TraceId { get; set; }
} public class DataInfo {
public string ResultCount { get; set; } public IList<EsWayBillInfo> EsWayBill { get; set; }
} public class EsWayBillInfo {
public EsWayBillInfo() {
ExteriorRouteList = new List<ExteriorRoute>();
} public string WaybillNumber { get; set; } public string ProductCode { get; set; } public string ReceiveDate { get; set; } public string Receiver { get; set; } public string ExpectedDate { get; set; } public string MailingTime { get; set; } public string ServiceMode { get; set; } public string MailingAddress { get; set; } public string ReceivingAddress { get; set; } public string Addressee { get; set; } public string Sender { get; set; } public string TotalFreightAmount { get; set; } public string Count { get; set; } public string FreightWeight { get; set; } public decimal? Size { get; set; } public IList<ExteriorRoute> ExteriorRouteList { get; set; }
} public class ExteriorRoute {
public int Id { get; set; } public string RouteStep { get; set; } public string RouteDescription { get; set; } public string UploadDate { get; set; }
}

  有了输入请求参数,当然也需要能够接受最终数据的数据接口,这些数据结构首先都要定义好,而且必须和官方保持一致,否则就无法进行反序列化操作。

  有了这些准备工作我们来看看最核心的获取业务数据的过程,我们会在稍后来对其中的一些代码进行说明。

public async Task<IList<EsWayBillInfo>> GetLogisticsInformationAsync(LogisticsInputModel input) {
var parameter = new List<KeyValuePair<string, string>>();
var nowDate = (DateTime.Now.ToUniversalTime() - new DateTime(, , )).TotalMilliseconds.ToString(CultureInfo.InvariantCulture);
var jsonParam = JsonConvert.SerializeObject(input);
var logisticsUser = new LogisticsUser() {
appkey = Appkey,
appsecret = Appsecret
};
parameter.Add(new KeyValuePair<string, string>("X-from", "openapi_ap")); var tokenResult = await HttpPostAsync(TokenUrl, JsonConvert.SerializeObject(logisticsUser), parameter);
var codeMsg = JsonConvert.DeserializeObject<TokenResult>(tokenResult); //Token失效,调用刷新Token接口,返回新Token
if (codeMsg.Data.Expire_time <= ) {
var tokenRefreshResult = await HttpPostAsync(RefreshTokenUrl,
"{\"refresh_token\": \"" + codeMsg.Data.Refresh_token + "\"}", parameter);
codeMsg = JsonConvert.DeserializeObject<TokenResult>(tokenRefreshResult);
} parameter.Clear();
parameter.Add(new KeyValuePair<string, string>("appkey", Appkey));
parameter.Add(new KeyValuePair<string, string>("format", Format));
parameter.Add(new KeyValuePair<string, string>("timestamp", nowDate));
parameter.Add(new KeyValuePair<string, string>("method", QueryRoute));
parameter.Add(new KeyValuePair<string, string>("sign", MD5Hash(Sign + nowDate + jsonParam).ToUpper()));
parameter.Add(new KeyValuePair<string, string>("token", codeMsg.Data.Token));
var result = await HttpPostAsync(RestUrl, jsonParam, parameter);
return JsonConvert.DeserializeObject<LogisticInfoModel>(result)?.Data?.EsWayBill;
}

  这里有一些需要说明的部分,首先获取nowDate的时候是获取UTC时间,其次获取sign的时候需要对内容进行MD5加密的过程。Asp.Net Core中的MD5加密比较简单,采用下面的方式即可。

/// <summary>
/// netcore下的实现MD5加密
/// </summary>
/// <param name="input">加密内容</param>
/// <returns></returns>
private string MD5Hash(string input) {
using (var md5 = MD5.Create()) {
var result = md5.ComputeHash(Encoding.ASCII.GetBytes(input));
var strResult = BitConverter.ToString(result);
return strResult.Replace("-", "");
}
}

  这里使用Using包裹便于进行非托管对象的释放,这里需要注意,还有一些常用的const变量定义为局部变量即可,有了这些就能够创建一个完整的根据发运单号来获取完整的物流数据的第三方API对接过程了。

private const string Appkey = "";
private const string Format = "json";
private const string Appsecret = "XXXE034XXX355889DC68BB40BEDXXX0";
private const string QueryRoute = "open.api.openCommon.queryRoute";
private const string Sign = "XXXE034545E355889DC68BB40BEDXXX";
private const string TokenUrl = "https://open.ky-express.com/security/token";
private const string RefreshTokenUrl = "https://open.ky-express.com/security/token/refresh";
private const string RestUrl = "https://open.ky-express.com/router/rest";

  最后我们来看看通过整个调用过程获取物流信息并在系统中进行展示的效果。

  图一 获取发运单对应物流信息

  

Asp.Net Core 调用第三方Open API查询物流数据的更多相关文章

  1. 从头编写 asp.net core 2.0 web api 基础框架 (1)

    工具: 1.Visual Studio 2017 V15.3.5+ 2.Postman (Chrome的App) 3.Chrome (最好是) 关于.net core或者.net core 2.0的相 ...

  2. 【转载】从头编写 asp.net core 2.0 web api 基础框架 (1)

    工具: 1.Visual Studio 2017 V15.3.5+ 2.Postman (Chrome的App) 3.Chrome (最好是) 关于.net core或者.net core 2.0的相 ...

  3. 从头编写 asp.net core 2.0 web api 基础框架 (3)

    第一部分:http://www.cnblogs.com/cgzl/p/7637250.html 第二部分:http://www.cnblogs.com/cgzl/p/7640077.html 之前我介 ...

  4. 【转载】从头编写 asp.net core 2.0 web api 基础框架 (3)

    Github源码地址:https://github.com/solenovex/Building-asp.net-core-2-web-api-starter-template-from-scratc ...

  5. 使用 ASP.NET Core MVC 创建 Web API(五)

    使用 ASP.NET Core MVC 创建 Web API 使用 ASP.NET Core MVC 创建 Web API(一) 使用 ASP.NET Core MVC 创建 Web API(二) 使 ...

  6. 使用 ASP.NET Core MVC 创建 Web API(三)

    使用 ASP.NET Core MVC 创建 Web API 使用 ASP.NET Core MVC 创建 Web API(一) 使用 ASP.NET Core MVC 创建 Web API(二) 十 ...

  7. 从零开始学习 asp.net core 2.1 web api 后端api基础框架(二)-创建项目

    原文:从零开始学习 asp.net core 2.1 web api 后端api基础框架(二)-创建项目 版权声明:本文为博主原创文章,未经博主允许不得转载. https://blog.csdn.ne ...

  8. 【ASP.NET Core学习】Web API

    这里介绍在ASP.NET Core中使用Web API创建 RESTful 服务,本文使用VSCode + NET Core3.0 创建简单Rest API 格式化输出 JSON Patch请求 Op ...

  9. 使用 ASP.NET Core MVC 创建 Web API(一)

    从今天开始来学习如何在 ASP.NET Core 中构建 Web API 以及每项功能的最佳适用场景.关于此次示例的数据库创建请参考<学习ASP.NET Core Razor 编程系列一> ...

随机推荐

  1. Linux----添加zabbix-agent

    1.zabbxi-agent安装及配置 1.1 获取官方zabbix源 [root@localhost ~]# rpm -ivh http://repo.zabbix.com/zabbix/3.4/r ...

  2. [spring-boot] pom文件 spring-boot-starter-parent

    <?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://mave ...

  3. firewalld 实现nat 转发外网转发到内网 实现访问外网端口到内网

    第0步骤:  开启转发生效 [root@node178.oldboy.com ~]# cat /proc/sys/net/ipv4/ip_forward1 [root@node178.oldboy.c ...

  4. Linux下java进程CPU占用率高分析方法(二)

    1. 通过 top 命令查看当前系统CPU使用情况,定位CPU使用率超过100%的进程ID:2. 通过 ps aux | grep PID 命令进一步确定具体的线程信息:3. 通过 ps -mp pi ...

  5. Jupyter Notebook in a virtual environment (virtualenv)

    $ python -m venv projectname $ source projectname/bin/activate (venv) $ pip install ipykernel (venv) ...

  6. springboot mybatis的pagehelper分页

    maven repositary里,分页组件常用的有两个 com.github.pagehelper » pagehelper-spring-boot-starter  com.github.page ...

  7. 时序数据库技术体系 – 初识InfluxDB(原理)

    原贴地址:http://hbasefly.com/2017/12/08/influxdb-1/?qytefg=c4ft23 在上篇文章<时序数据库体系技术 – 时序数据存储模型设计>中笔者 ...

  8. 004-行为型-08-状态模式(State)

    一.概述 允许一个对象在其内部状态改变时,改变它的行为 在状态模式中,我们创建表示各种状态的对象和一个行为随着状态对象改变而改变的 context 对象. 注意事项:在行为受状态约束的时候使用状态模式 ...

  9. 【NANO】引脚说明

    http://bbs.eeworld.com.cn/forum.php?mod=viewthread&tid=489650&page=1

  10. html的输出&,空格,大小于号

    最近定做安装程序,因为这次定做名字里有&符号,用微软的txt文本打开配置文件,在配置文件里修改了名称,名称在文本里显示正常,但是定做出来后,发现&符号变成了_下划线,在本来的& ...