物流包裹一站式查询(TrackingMore)

时间:2022-10-23 14:28:09

连载篇提前看

物流一站式查询之TrackingMore篇

物流一站式查询之顺丰接口篇

物流一站式查询之快递100篇

快递查询接口

目前提供快递查询的接口平台有:

不同接口的区别:

(1)Trackingmore支持380家快递公司,其中有55家为国内的快递,其余325家为国际快递。具体的价格为0.6分钱/单号左右,新注册用户可以免费测试12小时。

(2)快递100属于在国内做得比较早的平台,可以申请每天最多2000次的API调用,但需要给快递100做一个友链。超过2000次收费,每次0.06~0.1元不等。

(3)快递网可以申请每天最多500次的API调用,但同样需要做一个友链。超过部分,每次0.05元。

快递API的应用场景与用途

1. 最常见的应用场景如下:

(1)电商网站:例如B2C、团购、B2B、批发分销站、C2C、本地生活交易等网站。

(2)管理系统:订单处理平台、订货平台、发货平台、分销系统、渠道管理系统、客户管理系统、ERP等。

2. 快递API的用途如下:

(1)让顾客登录网站后,直接在“我的订单”页面内就能看到订单的物流状态。

(2)自动筛选出“已签收”、“疑难件”等状态的单号,减轻物流跟单人员的压力。

(3)改变订单的状态和交易流程,例如单号变为“已签收”,就能让订单变为可以确认退换货等。

(4)评估选择快递公司,根据“已签收”的运单数,可以算出销售人员的业绩,且便于应对货到付款的结算。

(5)邮件、短信提醒用户运单的最新状态,可以安抚用户,也可以利用邮件短信二次营销。

对接示例

这里以Trackingmore为例,不同的接口的对接方式比较类似,都需要注册,并生成自己的API key。以下以Trackingmore的实时查询API为例。

  接口支持的消息接收方式为HTTP POST

  请求方法的编码格式为 utf-8

  请求body部分的参数的数据格式为json 格式

物流包裹一站式查询(TrackingMore)

接口参数

接口请求地址

http://api.trackingmore.com/v2/trackings/realtime

请求头部信息参数

参数名称 类型 说明 是否必须
Content-Type: 
application/json
定义请求头部的数据格式
Trackingmore-Api-Key: 
string Trackingmore 后台获取的API

请求body参数说明

参数说明 类型 说明 是否必须
tracking_number
string 查询快递的快递单号
carrier_code
string trackingmore定义的快递商简码,比如china ems 就是china-ema

carrier_code 参数是trackingmore 自己定义的快递商家的简码,具体的可以在这里查看

还有需要注意的就是body部分这两个参数需要时json数据格式。大概样子就是这样的

1 {
2 "tracking_number": "LK664578623CN",
3 "carrier_code": "china-ems"
4 }

返回参数定义

参数名称 参数类型 参数说明 是否一定要返回该项值
code
数字 返回码 成功返回200,失败有其他队列的错误码
type string 接口类型 成功返回Success
message string 返回信息说明 成功返回Succes,失败返回队列的错误信息
data json 查询到的物流信息 成功返回物流信息,失败返回空

其他的状态响应简码可以在这里看到。

这里把Trackingmore平台状态响应简码简单封装了下,代码如下:

  /// <summary>
/// 典型的服务器响应 状态枚举
/// </summary>
public enum TrackMoreServerResponse
{
[Display(Name = "请求已成功 (一些 API 调用可能会相反返回 201)")]
OK = , [Display(Name = "请求成功,已创建了资源")]
Created = , [Display(Name = "请求已成功,但超过了数量限制")]
CreatedFail = , [Display(Name = "身份验证失败或用户没有所请求的操作的权限")]
Unauthorized = , [Display(Name = "无效的 API 密钥。请确保自己的申请API key的账户与调用API的服务器同时在国内或国外。即如果你的服务器在国外,你需要*登录trackingmore网站进而获取API key")]
UnauthorizedAPIInvalid = , [Display(Name = "API 密钥已被删除")]
UnauthorizedAPIDelete = , [Display(Name = "请求不能理解或缺少必需的参数")]
BadRequest = , [Display(Name = "Tracking_number 是必需的")]
BadRequest1 = , [Display(Name = "Tracking_number 的值是无效的")]
BadRequestInvalid = , [Display(Name = "Carrier_code的值是无效的")]
BadRequest3 = , [Display(Name = "跟踪已存在")]
BadRequest4 = , [Display(Name = "跟踪并不存在")]
BadRequest5 = , [Display(Name = "由于过载风险此功能需要自定义激活。与 service@trackingmore.org 联系更多的信息。")]
BadRequest6 = , [Display(Name = "数量限制一次 200")]
BadRequest7 = , [Display(Name = "你的余额不够,所以你不能调用API请求数据")]
BadRequest8 = , [Display(Name = "请求已成功,但响应为空")]
BadRequest9 = , [Display(Name = "无法检测到快递")]
NoContent = , [Display(Name = "付款要求")]
PaymentRequired = , [Display(Name = "访问被拒绝")]
Forbidden = , [Display(Name = "找不到资源")]
NotFound = , [Display(Name = "指定的资源不支持请求的方法")]
MethodNotAllowed = , [Display(Name = "由于冲突,无法完成请求")]
Conflict = , [Display(Name = "超过 API 限制。请求暂停,等待两分钟,然后再试")]
TooManyRequests = , [Display(Name = "内部异常")]
ServerError = , [Display(Name = "服务是临时不可用 (例如预定的平台维护)稍后再试")]
ServiceUnavailable = , }

然后我们可以获取枚举描述值来快速知道返回了什么状态,而不用去官网查状态码的意思。这里也把获取枚举描述值的代码贴出来如下:

  /// <summary>
/// 枚举辅助类
/// </summary>
public static class EnmHelper
{
/// <summary>
/// 获取枚举值的描述
/// </summary>
/// <param name="sourceValue"></param>
/// <returns></returns>
public static string GetEnmName(this Enum sourceValue)
{
DisplayAttribute[] attributes = null;
if (sourceValue != null)
{
FieldInfo field = sourceValue.GetType().GetField(sourceValue.ToString());
if (field != null)
{
attributes =field .GetCustomAttributes(typeof(DisplayAttribute), false) as DisplayAttribute[];
}
}
if (attributes==null|| attributes.Length < ) return sourceValue.ToString();
return attributes[].Name;
} /// <summary>
/// 获取枚举集合列表
/// </summary>
/// <param name="enmType"></param>
/// <returns></returns>
public static List<ModItem> GetEnmList(this Type enmType)
{
List<EnmItem> result = new List<EnmItem>();
Array array= Enum.GetValues(enmType);
foreach (var item in array)
{
DisplayAttribute[] attributes = (DisplayAttribute[])item.GetType().GetField(item.ToString()).GetCustomAttributes(typeof(DisplayAttribute), false);
EnmItem enmItem = new EnmItem();
if (attributes.Length > )
{
enmItem.Name = attributes[].Name;
enmItem.Value = Convert.ToInt32(item).ToString();
enmItem.OrderIndex = attributes[].GetOrder().GetValueOrDefault();
result.Add(enmItem);
}
}
return result.OrderBy(x=>x.OrderIndex).Select(x=>x as ModItem).ToList();
} /// <summary>
/// 把字符串转换为枚举
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="source"></param>
/// <returns></returns>
public static T ConvertToEnm<T>(this string source)
{
return (T) ConvertToEnm(source,typeof(T));
} /// <summary>
/// 把字符串转换为枚举
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="source"></param>
/// <returns></returns>
public static object ConvertToEnm(this string source,Type enmType)
{
ModItem mod = enmType.GetEnmList().FirstOrDefault(x => x.Name == source);
if (mod != null)
{
source = mod.Value;
}
return Enum.Parse(enmType, source);
}
} class EnmItem:ModItem
{
public int OrderIndex { set; get; }
}

一个枚举帮助类,其中ModItem类是自定义的一个类,里面就两个属性,Name、Value。

   public class ModItem
{
public string Name { set; get; } public string Value { set; get; }
}

像一般的调用接口获取物流信息,官网也有提供调用示例,点我去看示例

完整的物流订阅、查询状态有更新触发回调url 示例

现在假设你已经在More平台注册过,并生成创建了一个API Key。

订阅篇

①创建一个接口的访问类(此类官方已提供)

 /// <summary>
/// TrackingMore 每次发送必须带有Key 否则请求无效
/// </summary>
public class TrackingMoreAPI
{
private string ApiKey = ConfigHelper.GetKey("APIKey");
public string getOrderTracesByJson(string requestData, string urlStr, string method)
{
string result = null;
if (method.Equals("post"))
{
string ReqURL = "http://api.trackingmore.com/v2/trackings/post";
string RelUrl = ReqURL + urlStr;
result = sendPost(ReqURL, requestData, "POST");
}
else if (method.Equals("get"))
{
string ReqURL = "http://api.trackingmore.com/v2/trackings/get";
string RelUrl = ReqURL + urlStr;
//Console.WriteLine("RelUrl:" + RelUrl);
result = sendPost(RelUrl, requestData, "GET");
}
else if (method.Equals("batch"))
{
string ReqURL = "http://api.trackingmore.com/v2/trackings/batch";
string RelUrl = ReqURL + urlStr;
//Console.WriteLine("RelUrl:" + RelUrl);
result = sendPost(RelUrl, requestData, "POST");
}
else if (method.Equals("codeNumberGet"))
{ string ReqURL = "http://api.trackingmore.com/v2/trackings";
string RelUrl = ReqURL + urlStr;
//Console.WriteLine("RelUrl:" + RelUrl);
result = sendPost(RelUrl, requestData, "GET");
}
else if (method.Equals("codeNumberPut"))
{ string ReqURL = "http://api.trackingmore.com/v2/trackings";
string RelUrl = ReqURL + urlStr;
//Console.WriteLine("RelUrl:" + RelUrl);
result = sendPost(RelUrl, requestData, "PUT");
}
else if (method.Equals("codeNumberDel"))
{ string ReqURL = "http://api.trackingmore.com/v2/trackings";
string RelUrl = ReqURL + urlStr;
//Console.WriteLine("RelUrl:" + RelUrl);
result = sendPost(RelUrl, requestData, "DELETE");
} else if (method.Equals("realtime"))
{ string ReqURL = "http://api.trackingmore.com/v2/trackings/realtime";
string RelUrl = ReqURL + urlStr;
//Console.WriteLine("RelUrl:" + RelUrl);
result = sendPost(RelUrl, requestData, "POST");
} return result;
}
private string sendPost(string url, string requestData, string method)
{
string result = "";
byte[] byteData = null;
if (requestData != null)
{
byteData = Encoding.GetEncoding("UTF-8").GetBytes(requestData.ToString());
}
try
{
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url);
request.ContentType = "application/x-www-form-urlencoded";
request.Timeout = * ;
request.Method = method;
request.Headers["Trackingmore-Api-Key"] = ApiKey; if (byteData != null)
{
Stream stream = request.GetRequestStream();
stream.Write(byteData, , byteData.Length);
stream.Flush();
stream.Close();
}
HttpWebResponse response = (HttpWebResponse)request.GetResponse();
Stream backStream = response.GetResponseStream();
StreamReader sr = new StreamReader(backStream, Encoding.GetEncoding("UTF-8"));
result = sr.ReadToEnd();
sr.Close();
backStream.Close();
response.Close();
request.Abort();
}
catch (Exception ex)
{
result = ex.Message;
}
return result;
}
}

②创建一个TrackMoreModel模型类用于传输快递单号和快递公司编码

 public class TrackMoreModel
{
/// <summary>
/// 快递单号
/// </summary>
public string tracking_number { get; set; }
/// <summary>
/// 快递公司编码
/// </summary>
public string carrier_code { get; set; } }

③创建一个TrackMore快递信息跟踪类,里面可以包含你需要的一些访问接口的方法,如:创建快递单项目,查询单个物流信息、创建多个物流项目,查询多个物流信息、实时查询物流信息等。这里以创建单个快递单项目为例

/// <summary>
/// 快递跟踪信息
/// </summary>
public class TrackMore
{
/// <summary>
/// 创建快递单号项目
/// </summary>
/// <param name="input"></param>
/// <returns></returns>
public static OperationResult TrackExpressSubscibe(TrackMoreModel model)
{
#region 创建物流跟踪信息
string urlstr = null;
string requestdata = "{\"tracking_number\": \"" + model.tracking_number + "\",\"carrier_code\":\"" + model.carrier_code + "\"}";
string result = new TrackingMoreAPI().getOrderTracesByJson(requestdata, urlstr, "post");
var code = TarckMoreExpressCompany.GetValueFromJson(result, "code");
if ( code!="")
{
string message = EnmHelper.GetEnmName((TrackMoreServerResponse)int.Parse(code));
if (!message.Equals("跟踪已存在"))
{
return new OperationResult(message);
}
}
#endregion
return new OperationResult();
}
}

其中GetValueFromJson 方法作用是从json字符串中获取字段值 ,在这里方法也贴一下:

        /// <summary>
/// 从json字符串中获取字段值
/// </summary>
/// <param name="json">json字符串</param>
/// <param name="field">要解析出值的字段</param>
/// <returns></returns>
public static string GetValueFromJson(string json, string field)
{
int start = json.IndexOf(field + "\":");
start += field.Length + ;
int end = json.IndexOf(",", start);
if (end < )
{
end = json.IndexOf("}", start);
}
return json.Substring(start, end - start).Trim('"');
}

OperationResult 类是自定义的业务操作结果类,可以根据项目需要自定义添加,这里我贴三个出来

        /// <summary>
/// 默认操作成功
/// </summary>
public OperationResult()
{
IsSuccess = true;
} /// <summary>
/// 以操作失败信息实例操作结果
/// </summary>
/// <param name="failMessage">操作失败信息</param>
public OperationResult(string failMessage)
{
IsSuccess = false;
FailMessage = failMessage;
} /// <summary>
/// 业务操作是否成功
/// </summary>
public bool IsSuccess
{
set;
get;
}

④有了跟踪物流信息类,那剩下的就是调用了 ,调用比较简单,主要是根绝项目业务 去做一些操作,比如从数据库查询订单,过滤一些条件,快递没有订阅的,排除掉一些订单类型,有些充值啊这些不需要快递,查询到的集合

可以循环去创建物流单项目,调用的代码就一句,

OperationResult result = TrackMore.TrackExpressSubscibe(new TrackMoreModel() { tracking_number =快递单号, carrier_code =快递公司简码) });

然后可以根据返回的结果做一些其他操作

if (result.IsSuccess)
{
//TODO 比如 更新数据库此条订单物流订阅状态,订阅时间等
}
else
{
//TODO 比如 日志记录失败原因
}

回调更新物流信息

上面只是再More物流平台创建了此条物流信息记录,但是我们并不知道当前这个快递状态是如何,也不能每次都去快递平台查询,所以,回调的作用就凸显出来了,物流平台每次只要有物流更新的时候,会访问到你再平台上设定的回调URL。

此时,你只用接收发过来的数据(包括meta请求头状态,data 数据 verifyInfo 签名部分),具体代码如下:

⑴先再More平台设置回调地址

物流包裹一站式查询(TrackingMore)

当然官方也提供了回调测试的 页面 在填回调地址的下面 点击 format of inbound webhooks 即可进入,界面如下图所示:

物流包裹一站式查询(TrackingMore)

⑵设置完了回调地址,那我们就可以进行编码了,首先我们要对返回的数据 进行分析,上面也提到了 Body返回的主体部分是Json格式的,其实这里有一个坑,就是提交那边是form,但是接收是的数据类型是Json的

物流包裹一站式查询(TrackingMore)

物流包裹一站式查询(TrackingMore)

关于这种请求数据类型区别和使用,可以看这篇博客:

ASP.NET MVC学习系列(二)-WebAPI请求

ok,既然是Json格式数据,那我们就把返回的Json格式数据转成实体模型。这里有几种方式推荐,①将官方示例中的json全部复制下来,然后随便百度一个Json转实体,不过我更推荐第二种,② 号称宇宙最强IED 的VS也帮我们实现Json转实体的快捷操作,具体操作方式如下:

物流包裹一站式查询(TrackingMore)

有了模型容器,我们就可以来接收数据了 创建一个和回调URL一样的方法名称UpdateTrack

/// <summary>
/// TrackingMore 回调 同步物流信息
/// </summary>
/// <param name="form"></param>
/// <returns></returns>
public ActionResult UpdateTrack([FromBody]Root dataJson)
{
var code = dataJson.meta.code;//请求状态
var expressNumber = dataJson.data.tracking_number;//快递单号
var status = dataJson.data.status;//物流状态
var trackinfo = dataJson.data.origin_info.trackinfo;//物流信息集合
var expressMessage = ""; //所有物流信息
foreach (var item in dataJson.data.origin_info.trackinfo)
{
expressMessage += item.Date + " " + item.StatusDescription + "<br/>";
}
var track = dataJson.data.origin_info.trackinfo;
var LastExpressMessage = track.Count > ? track[].Date + " " + track[].StatusDescription : "";//最近一条物流信息 //TODO 比如:先根据传过来的快递单号查寻 项目的订单表 确认是否有此订单,再根据数据表中的订单状态
//看是否需要修改一些其他信息,主要就是拿到第一条物流信息和所有的物流信息,也可以再数据表中记录此时这个快递单 回调的时间 和返回的状态 用于后期数据分析
}

注:此方法接受回调使用了FormBody ,快递100平台接收回调是FormCollection即可。

外部调用

所谓外部调用,就是再自己项目中,根据不同单号 借助物流平台查询快递实时信息。物流平台对此操作也有讲解,这里简单提下。

官方给出的效果如下:

物流包裹一站式查询(TrackingMore)

实现步骤

①将下面这句引用代码放在标签开始之前的位置

<script type="text/javascript" src="//cdn.trackingmore.com/plugins/v1/pluginsCss.js?time=20170913"></script><script type="text/javascript" src="//cdn.trackingmore.com/plugins/v1/plugins.min.js"></script>

②将下面代码放在 页面与标签之间的位置

<div style="width:600px;margin-left:0px;text-align:left;">
<form id="trackingmoreId" role="form" action="//track.trackingmore.com" method="get" onsubmit="return false">
<div class="search-box">
<div class="input-box">
<input id="button_express_code" type="hidden" value="" name="button_express_code"><input style="border-color: #428bca;" type="text" autocomplete="off" maxlength="26" placeholder="请输入快递单号" id="button_tracking_number" class="inp-metro" name="button_tracking_number"> <button style="background-color: #428bca" class="button-query" type="submit" onclick="return doTrack()" id="query">查询</button>
</div>
</div>
<input type="hidden" name="lang" value="cn" />
</form>
<div id="TRNum"></div>
</div>
<script type="text/javascript">
function doTrack() {
var num=document.getElementById("button_tracking_number").value;
var expCode=document.getElementById("button_express_code").value;
var width = document.getElementById("query").parentNode.offsetWidth;
TRACKINGMORE.trackMynumber({
TR_ElementId:"TRNum", //必须,指定悬浮位置的元素ID。
TR_Width:width, //可选,指定查询结果宽度,最小宽度为600px,默认撑满容器。
TR_Height:600, //可选,指定查询结果高度,最大高度为800px,默认撑满容器。
TR_ExpressCode:expCode, //可选,指定运输商,默认为自动识别。
TR_Lang:"cn", //可选,指定UI语言,默认根据浏览器自动识别。
TR_Num:num //必须,指定要查询的单号。
});
return false;
}
</script>

温馨提示:不要短时间内频繁调用 More平台会检测当前IP,过短调用会提示I异常 需要输入验证码   最终效果展示如下:

物流包裹一站式查询(TrackingMore)

PS:这种每次点击订单请求快递数据并不是最优的做法。因为上面我们也有提到过快递订阅这个功能,其实,最佳的做法是 订阅之后,快递平台推送到回调地址的最新物流信息,我们可以将这些物流信息保存再对应订单的快递物流字段里面。这样前台取的时候可以先判断

物流信息字段是否为空,如果不为空 就直接取物流信息字段,这样既可以减少网络流量消耗,也可以加快系统反应时间,带来更好的用户体验。如果不喜欢用官方自带的这个显示框,也可以改成Bootstrap的样式框显示,具体做法如下:

 //查看物流(订单id,this,物流信息,快递单号,快递公司简码)
function viewSenderMessage(id, obj, message, number, company) {
debugger;
if (!isNullEmptyUndefined(message)) {
var d = dialog({
title: '物流最新跟踪',
content: "<div style='line-height:20px;'>" + message + "</div>",
okValue: '确定',
ok: true,
});
d.show(obj);
} else if (!isNullEmptyUndefined(number) && !isNullEmptyUndefined(company)) {
// doTrack(number, company);
ajaxGetContent("@Url.Action("ViewExpress")" + "?companyNumber=" + company + "&expressNumber=" + number, function (data) {
var d = dialog({
title: '物流最新跟踪',
content: data,
okValue: '确定',
ok: true,
});
d.show(obj);
});
} else {
var d = dialog({
title: '物流最新跟踪',
content: "无物流跟踪信息",
okValue: '确定',
ok: true,
});
d.show(obj);
}
}

按照逻辑,如果物流信息为空 此时我们就需要从Action ViewExpress中获取单个快递信息。ViewExpress代码如下:

 public ActionResult ViewExpress(string expressNumber, string companyNumber)
{
string urlstr = null;
string requestdata = "carrier_code=" + companyNumber + "&tracking_number=" + expressNumber;
//此处是获取单个物流信息 采用get请求,method传入codeNumberGet
string result = new TrackingMoreAPI().getOrderTracesByJson(requestdata, urlstr, "codeNumberGet");
if (!result.Contains("code")) return Content("暂无物流信息,请稍后重试");
var code = TarckMoreExpressCompany.GetValueFromJson(result, "code");
if (code != "")
{
message = EnmHelper.GetEnmName((TrackMoreServerResponse)int.Parse(code));
//这里多加一层判断 4031表示请求成功,但是响应为空,意思就是 TrackMore平台上还没有这个快递单数据,所以要再次调之前创建物流项目这个接口
if (code == "")
{
OperationResult resMessage = TrackMore.TrackExpressSubscibe(new TrackMoreModel() { carrier_code = companyNumber, tracking_number = expressNumber });
if (resMessage.IsSuccess)
{
return ViewExpress(expressNumber, companyNumber);
}
else
{
message = resMessage.FailMessage;
}
}
}
else
{
Root root = JsonConvert.DeserializeObject<Root>(result);
if (root.Data.origin_info.trackinfo.Count == ) message = "暂无物流信息,请稍后重试";
          //此处将返回的物流信息以 时间+空格+物流消息 格式循环输出
foreach (var item in root.Data.origin_info.trackinfo)
{
message += item.Date + " " + item.StatusDescription + "\r\n <br/>";
}
}
        return Content(message);
}

获取单个物流信息采用的是get请求,所以再发送http请求的时候不能再用post 的流方式,需要多加一个get请求的,代码如下:

     public string HttpGet(string Url, string postDataStr, string method)
{
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(Url + (postDataStr == "" ? "" : "?") + postDataStr);
request.Method = "GET";
request.ContentType = "application/x-www-form-urlencoded";
request.Timeout = * ;
request.Method = method;
request.Headers["Trackingmore-Api-Key"] = ApiKey;
HttpWebResponse response = (HttpWebResponse)request.GetResponse();
Stream myResponseStream = response.GetResponseStream();
StreamReader myStreamReader = new StreamReader(myResponseStream, Encoding.GetEncoding("utf-8"));
string retString = myStreamReader.ReadToEnd();
myStreamReader.Close();
myResponseStream.Close();
return retString;
}

最终效果展示

物流包裹一站式查询(TrackingMore)

注:顺丰即日取消了对外第三方接口,故不能通过第三方物流平台获取到顺丰的物流信息,需要和顺丰开放平台(目前据顺丰IT人员透露,此平台已无人维护,已物流服务已转至顺丰官方的企业服务平台)对接 才能查到最新顺丰的物流信息

顺丰的接口对接请转场至下文《物流一站式查询之顺丰接口篇》

物流包裹一站式查询(TrackingMore)的更多相关文章

  1. 物流一站式查询之TrackingMore篇

    连载篇提前看 物流一站式查询之TrackingMore篇 物流一站式查询之顺丰接口篇 物流一站式查询之快递100篇 快递查询接口 目前提供快递查询的接口平台有: Trackingmore 快递100 ...

  2. 物流一站式单号查询之快递鸟API接口(附Demo源码)

    连载篇提前看 物流一站式单号查询之快递鸟API接口 物流一站式查询之TrackingMore篇 物流一站式查询之顺丰接口篇 物流一站式查询之快递100 前情提要 前三篇中,我们已经从注册.申请接口.调 ...

  3. 快递查询API接口集成,有需要的可以直接用

    适用于涉及经常发货.寄快递的人群.企业.电商网站.微信公众号平台等对接使用.支持国内外三百多家快递及物流公司的快递单号一站式查询. 使用说明: 1.KuadidiAPI.php 不需要修改改任何东西 ...

  4. 物流跟踪API-快递单订阅

    上一篇文章我们讲解了轨迹查询的接口,通过快递鸟接口可以实现实时查询物流轨迹,这次给大家推荐订阅服务功能. 为了更好的理解订阅服务,我们来做个对比, 即时查询是主动查询物流轨迹,需要我们主动调用接口才能 ...

  5. 常用免费快递查询API对接案例

    现在许多电商公司和ERP都会寻找比较适用的集成快递查询接口,减少对接难度,现在整理一下常用的免费快递查询接口,并附上调用案例,如果有觉得不对的地方,望能够一起沟通探讨! 一.快递查询接口 目前有提供免 ...

  6. JAVA 快递查询接口API调用-快递鸟接口

    import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import ...

  7. 快递查询API接口对接方法

    各类接口 快递查询API有即时查询和订阅查询两种,即时是请求即返回数据,订阅则是订阅快递单号到接口,有物流轨迹更新则全量返回数据.目前常用的有快递鸟.快递100.快递网等. 快递鸟即时API可以查询3 ...

  8. &period;Net程序员学用Oracle系列&lpar;14&rpar;:子查询、集合查询

    1.子查询 1.1.子查询简介 1.2.WITH 子查询 2.集合查询 2.1.UNION 和 UNION ALL 2.2.MINUS 2.3.INTERSECT 2.4.集合运算与 ORDER BY ...

  9. 调用第三方物流公司API即时查询物流信息

    主要是利用快递鸟提供的物流服务,通过对接快递鸟的API,调用即时查询接口,获取物流信息. 这里采用java语言,调用快递鸟的接口为例.步骤如下: 1.首先,得去快递鸟的官方网站注册一个账号并进行实名认 ...

随机推荐

  1. GIT远程仓库地址变更

    将VS2013的解决方案添加到GIT源代码管理后会增加.gitattributes和.gitignore 2个文件以及.git目录 设置远程地址的文件在.git目录下的config文件中 直接修改上图 ...

  2. TSwitch 中文简繁显示支持(XE6 Android)

    说明: XE6 的 TSwitch 做了很多改进,包含多语显示处理,但 XE6 似乎只认定一种中文语系「zh」,它无法处理「zh_TW」.「zh_CN」.「zh_HK」.「zh_SG」等语系,不过可以 ...

  3. 【Codeforces 707A】Brain&&num;39&semi;s Photos 水题

    黑白灰都是#Black&White #include <cstdio> int n,m; int main() { scanf("%d%d",&n,&a ...

  4. Hadoop离线项目介绍(不包括程序)

    一:项目场景 1.需求分析 根据用户行为数据进行程序的处理,得到结果保存到关系型数据库中 需要收集用户(系统使用者)在不同客户端上产生的用户行为数据,最终保存到hdfs上 需要明确收集字段的相关信息, ...

  5. ThinkPHP框架概述

    框架概述 1.什么是框架 框架,即framework.其实就是某种应用的半成品,就是一组组件,供你选用完成你自己的系统. 2.框架的应用场景 ① 代码重用 ② 合理分工 ③ 解决团队协作开发问题 3. ...

  6. L2-012&period; 关于堆的判断

    L2-012. 关于堆的判断 题目链接:https://www.patest.cn/contests/gplt/L2-012 终于ac了,简直要哭.题目还是很简单的,不过很多坑: 1.寻找x下标时,有 ...

  7. js压缩上传图片

    初学有不当之处,请多多指点, <body> <div class="cc"> <input type="file" id=&quo ...

  8. Python之find命令中的位置的算法

    find("s",a,b)    #s表示的是一个子序列,a表示的是检索的起始位置,b表示的是检索的终止位置,ab可有可无 test = "abcdefgh" ...

  9. python读取wav文件并播放&lbrack;pyaudio&sol;wave&rsqb;

    #!/usr/bin/python # encoding:utf-8 import pyaudio import wave CHUNK = 1024 # 从目录中读取语音 wf = wave.open ...

  10. C&num;正则表达式语法教程

    C#语法之正则 本文提供全流程,中文翻译. Chinar 坚持将简单的生活方式,带给世人!(拥有更好的阅读体验 -- 高分辨率用户请根据需求调整网页缩放比例) Chinar -- 心分享.心创新!助力 ...