• 在Asp.Net MVC中利用快递100接口实现订阅物流轨迹功能


    前言

    分享一篇关于在电商系统中同步物流轨迹到本地服务器的文章,当前方案使用了快递100做为数据来源接口,这个接口是收费的,不过提供的功能还是非常强大的,有专门的售后维护团队。也有免费的方案,类似于快递鸟,不过数据出现问题就凉凉了

    正文

    实现思路大概分为三大步:

    第一步:提交订阅信息到快递100的接口

    第二步:快递100收到请求后会对回调地址进行跟踪,将快递信息推送给回调接口

    第三步:回调接口收到Post推送的数据后,进行逻辑处理

    注意:回调的地址建议单独部署一个API项目,不要放在主程序下面;或者在提交订阅时要求对回调进行签名验证。

    下面附上详细代码:

    Subscribe类

    using System;
    using System.Collections.Generic;
    using System.Collections.Specialized;
    using System.Configuration;
    using System.Linq;
    using System.Net;
    using System.Text;
    using System.Threading.Tasks;
    using WoT.Infrastructure.Helper.Xml;
    using WoT.Model.Inventory;
    using WoT.ViewModel.Dtos.Inventory;
    
    namespace WoT.SyscTraceSys
    {
        /// <summary>
        /// 订阅物流轨迹
        /// </summary>
        public class Subscribe
        {
            //拿到授权的Key
            private static string key = ConfigurationManager.AppSettings["SubscribeKey"];
    
            //请求的url
            private static string reqUrl = "http://www.kuaidi100.com/poll";
    
            //回调url
            private static string callbackurl = "http://你的域名/api/kd100/callback";
    
            /// <summary>
            /// 发送订阅指令
            /// </summary>
            /// <param name="invoce">发货单</param>
            /// <param name="shipperCode">快递公司</param>
            /// <returns></returns>
            public static KD100Result SendPost(Invoice invoce, string shipperCode = "SF")
            {
                StringBuilder param = new StringBuilder();
                KD100Result kdResult = new KD100Result();
    
                param.Append("<?xml version='1.0' encoding='UTF-8'?>")
                    .AppendFormat("<orderRequest>")
                    .AppendFormat("<company>{0}</company>", GetCom(shipperCode))
                    .AppendFormat("<number>{0}</number>", invoce.LogisticCode)
                    .AppendFormat("<from></from>")
                    .AppendFormat("<to></to>")
                    .AppendFormat("<key>{0}</key>", key)
                    .AppendFormat("<parameters><callbackurl>{0}</callbackurl><resultv2>1</resultv2></parameters>", callbackurl)
                    .Append("</orderRequest>");
    
                NameValueCollection postvals = new NameValueCollection();
                postvals.Add("schema", "xml");
                postvals.Add("param", param.ToString());
                try
                {
                    using (WebClient wc = new WebClient())
                    {
                        string rlt = System.Text.Encoding.UTF8.GetString(wc.UploadValues(reqUrl, "POST", postvals));
                        kdResult = XmlExpand.DESerializer<KD100Result>(rlt);
                    }
                }
                catch (Exception ex)
                {
                    return new KD100Result() { result = false, returnCode = 0, message = ex.Message };
                }
                return kdResult;
            }
    
            /// <summary>
            /// 获取com
            /// </summary>
            /// <param name="shipperCode"></param>
            /// <returns></returns>
            private static string GetCom(string shipperCode)
            {
                string com = "shunfeng";
                switch (shipperCode)
                {
                    case "EMS":
                        com = "ems";
                        break;
                    case "SF":
                        com = "shunfeng";
                        break;
                    case "STO":
                        com = "shentong";
                        break;
                    case "YD":
                        com = "yunda";
                        break;
                    case "YTO":
                        com = "yuantong";
                        break;
                    case "YZPY":
                        com = "youzhengguonei";
                        break;
                    case "ZJS":
                        com = "zhaijisong";
                        break;
                    case "ZTO":
                        com = "zhongtong";
                        break;
                    case "DBL":
                        com = "debangwuliu";
                        break;
                    case "JD":
                        com = "debangwuliu";
                        break;
                    default:
                        break;
                }
                return com;
            }
        }
    }
    Subscribe
    GetCom()方法是获取获取快递公司的标示编号,我在数据库中只存了快递简称,所以需要通过这种方式获取,如果是存在数据库的就可以直接从数据库获取了。
    DESerializer()方法将xml字符串转化为实体对象,关于实现的详情在前面C#操作Xml树的扩展类一节中有讲到。
    ConfigurationManager.AppSettings["SubscribeKey"];是读取配置文件,获取快递100对商户授权的Key,配置代码如下:
    在appSettings节点下添加

    KD100Result类

        /// <summary>
        /// 快递100返回结果
        /// </summary>
        [Serializable]
        [XmlType("orderResponse")]
        public class KD100Result
        {
            /// <summary>
            /// 
            /// </summary>
            [XmlElement("result")]
            public bool result { get; set; }
    
            /// <summary>
            /// 
            /// </summary>
            [XmlElement("returnCode")]
            public int returnCode { get; set; }
    
            /// <summary>
            /// 
            /// </summary>
            [XmlElement("message")]
            public string message { get; set; }
        }
    

    回调接口Action

            /// <summary>
            /// 
            /// </summary>
            /// <returns></returns>
            [HttpPost]
            [Route("callback")]
            public void callback()
            {
                StringBuilder sb = new StringBuilder();
                DateTime now = DateTime.Now;
                pushResponse push = new pushResponse()
                {
                    Result = false,
                    ReturnCode = 404,
                    Message = "没有拉取到相关数据"
                };
    
                HttpContext context = HttpContext.Current;
                if (!context.Request.RequestType.ToUpper().Equals("POST"))
                {
                    context.Response.Write(string.Format("<?xml version='1.0' encoding='UTF-8'?><pushResponse><result>{0}</result><returnCode>{1}</returnCode><message>{2}</message></pushResponse>", false, 0, "请使用POST提交"));
                    context.Response.End();
                    return;
                }
    
                try
                {
                    sb.Clear();
                    var stream = context.Request.InputStream;
                    string param = ReadStream(stream);
    
                    if (string.IsNullOrEmpty(param))
                    {
                        context.Response.Write(string.Format("<?xml version='1.0' encoding='UTF-8'?><pushResponse><result>{0}</result><returnCode>{1}</returnCode><message>{2}ee</message></pushResponse>", push.Result, push.ReturnCode, push.Message));
                        context.Response.End();
                        return;
                    }
    
                    Dictionary<string, string> dic = new Dictionary<string, string>();
    
                    string[] sp1 = param.Split('&');
                    foreach (string s in sp1)
                    {
                        int splIdx = s.IndexOf('=');
                        string key = s.Substring(0, splIdx);
                        string value = s.Substring(splIdx + 1);
    
                        dic.Add(key.Trim(), value.Trim());
                    }
                    string cbxml = HttpUtility.UrlDecode(dic["param"], Encoding.UTF8);
    
                    using (ILogisticsTraceService _Service = CoreServiceFactory.Used.Build<ILogisticsTraceService>())
                    {
                        push = _Service.PushLogisticsTrace(cbxml);
                    }
    
                    sb.Append("<?xml version='1.0' encoding='UTF-8'?>")
                        .AppendFormat("<pushResponse><result>{0}</result>", push.Result)
                        .AppendFormat("<returnCode>{0}</returnCode>", push.ReturnCode)
                        .AppendFormat("<message>{0}</message>", push.Message)
                        .Append("</pushResponse>");
    
                    stream.Close();
                    context.Response.Write(sb.ToString());
                    context.Response.End();
                }
                catch (Exception)
                {
                    context.Response.Write(string.Format("<?xml version='1.0' encoding='UTF-8'?><pushResponse><result>{0}</result><returnCode>{1}</returnCode><message>{2}</message></pushResponse>", false, 0, "服务器处理错误"));
                }
    
            }
    callback

    有需要源码的朋友可以扫描下方二维码加入QQ群,我会把源码分享在QQ群里

  • 相关阅读:
    子集生成——增量构造法+位向量法+二进制法
    记忆化搜索
    欧拉回路和欧拉通路
    拓扑排序(基于dfs+基于队列)
    HDU 3839 Ancient Messages(DFS)
    【gulp】前端自动化工具---gulp的使用(一)------【巷子】
    【面向对象】用大白话扯扯那"神奇"的面向对象之方法继承(五)------【巷子】
    【面向对象】----【prototype&&__proto__&&实例化对象三者之间的关系】(四)-----【巷子】
    【面向对象】用大白话扯扯那"神奇"的面向对象之属性继承(三)------【巷子】
    【面向对象】用大白话扯扯那"神奇"的面向对象编程思维(二)------【巷子】
  • 原文地址:https://www.cnblogs.com/ydcnblog/p/9318927.html
Copyright © 2020-2023  润新知