在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群里

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM