天天看點

C#對接----韻達開發平台--取電子面單結語

引子

最近根據業務的一些需求,是以放棄從快遞鳥對接去電子面單,轉而直接對接韻達開發平台:

http://open.yundasys.com/

,中間踩了一些坑,借此做了一個小案例給大夥,瞅瞅,若有需改進之處,還請指出!!!

廢話不多數:首先咱先對韻達的一些接口參數了解清楚:

當然附上位址:

http://open.yundasys.com/index.php?g=&m=ApiTools&a=exm

還有接口的一些SDK檔案位址,這個就各位觀衆大老爺們自己去看了:

http://open.yundasys.com/index.php?g=&m=ApiTools&a=apps&id=14

解決方案

上代碼走起:基礎參數的模型

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace ConsoleApplication1
{
  //請求參數
    class RequestVO
    {
        /// <summary>
        /// XML資料内容
        /// </summary>
        public string xmldata { get; set; }
        /// <summary>
        /// 合作社群ID,由韻達給大客戶提供
        /// </summary>
        public string partnerid { get; set; }
        /// <summary>
        /// 密碼
        /// </summary>
        public string password { get; set; }
        /// <summary>
        /// 資料請求類型,如request=data;其中data表示下單,詳細請見request字典表
        /// </summary>
        public string request { get; set; }
        /// <summary>
        /// 請求的版本,目前版本為1.0
        /// </summary>
        public string version { get; set; }
    }
}
      

  

主體參數模型

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml.Serialization;
namespace ConsoleApplication2
{
    /// <summary>
    /// 資料體
    /// </summary>
    public class Orders
    {
        [XmlElement("order")]
        public List<Order> order { get; set; }
    }

    /// <summary>
    /// 韻達取号訂單資訊
    /// </summary>
    public class Order
    {
        /// <summary>
        /// 訂單唯一序列号
        /// </summary>
        public string order_serial_no { get; set; }
        /// <summary>
        /// 大客戶系統訂單的訂單号
        /// </summary>
        public string khddh { get; set; }
        /// <summary>
        /// 内部參考号,供大客戶自己使用,可以是客戶的客戶編号
        /// </summary>
        public string nbckh { get; set; }
        /// <summary>
        /// 單号
        /// </summary>
        public string mailno { get; set; }
        /// <summary>
        /// 發件人
        /// </summary>
        [XmlElement("sender")]
        public Sender sender { get; set; }
        /// <summary>
        /// 收件人
        /// </summary>
        [XmlElement("receiver")]
        public Receiver receiver { get; set; }
        /// <summary>
        /// 物品重量
        /// </summary>
        public long weight { get; set; }
        /// <summary>
        /// 尺寸,格式(長,寬,高),機關cm
        /// </summary>
        public string size { get; set; }
        /// <summary>
        /// 貨物金額
        /// </summary>
        public decimal value { get; set; }
        /// <summary>
        /// 商品集合
        /// </summary>
        [XmlElement("items")]
        public Items items { get; set; }
        /// <summary>
        /// 訂單備注
        /// </summary>
        public string remark { get; set; }
        /// <summary>
        /// 可以自定義顯示資訊1
        /// </summary>
        public string cus_area1 { get; set; }
        /// <summary>
        /// 可以自定義顯示資訊2
        /// </summary>
        public string cus_area2 { get; set; }

    }
    public class Sender
    {
        /// <summary>
        /// 姓名
        /// </summary>
        public string name { get; set; }
        /// <summary>
        /// 公司
        /// </summary>
        public string company { get; set; }
        /// <summary>
        /// 嚴格按照國家行政區劃,省市區三級,逗号分隔。示例上海市,上海市,青浦區(cod訂單必填)
        /// </summary>
        public string city { get; set; }
        /// <summary>
        /// 需要将省市區劃資訊加上,例如:上海市,上海市,青浦區盈港東路7766号
        /// </summary>
        public string address { get; set; }
        /// <summary>
        /// 郵編
        /// </summary>
        public string postcode { get; set; }
        /// <summary>
        /// 固定電話
        /// </summary>
        public string phone { get; set; }
        /// <summary>
        /// 行動電話固定電話或行動電話至少填一項
        /// </summary>
        public string mobile { get; set; }

        public string branch { get; set; }
    }
    public class Receiver
    {
        /// <summary>
        /// 姓名
        /// </summary>
        public string name { get; set; }
        /// <summary>
        /// 公司
        /// </summary>
        public string company { get; set; }
        /// <summary>
        /// 嚴格按照國家行政區劃,省市區三級,逗号分隔。示例上海市,上海市,青浦區(cod訂單必填)
        /// </summary>
        public string city { get; set; }
        /// <summary>
        /// 需要将省市區劃資訊加上,例如:上海市,上海市,青浦區盈港東路7766号
        /// </summary>
        public string address { get; set; }
        /// <summary>
        /// 郵編
        /// </summary>
        public string postcode { get; set; }
        /// <summary>
        /// 固定電話
        /// </summary>
        public string phone { get; set; }
        /// <summary>
        /// 行動電話固定電話或行動電話至少填一項
        /// </summary>
        public string mobile { get; set; }
        public string branch { get; set; }
    }
    /// <summary>
    /// 明細集合
    /// </summary>
    public class Items
    {
        [XmlElement("item")]
        public List<Item> item { get; set; }
    }
    /// <summary>
    /// 明細資訊
    /// </summary>
    public class Item
    {
        /// <summary>
        /// 商品名稱
        /// </summary>
        public string name { get; set; }
        /// <summary>
        /// 商品數量
        /// </summary>
        public int number { get; set; }
        /// <summary>
        /// 商品備注
        /// </summary>
        public string remark { get; set; }
    }
}
      

請求方法:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Web;
using System.IO;
using System.Collections.Specialized;
using System.Net;


namespace ConsoleApplication1
{
    /// <summary>
    /// POST送出
    /// </summary>
    class HttpClient
    {
        /// <summary>
        /// 
        /// </summary>
        /// <param name="url"></param>
        /// <param name="parameters"></param>
        /// <returns></returns>
        public static HttpWebResponse post(String url, IDictionary<string, string> parameters)
        {
            HttpWebRequest request = WebRequest.Create(url) as HttpWebRequest;
            request.Method = "POST";
            request.ContentType = "application/x-www-form-urlencoded";

            //如果需要POST資料
            if (!(parameters == null || parameters.Count == 0))
            {
                StringBuilder buffer = new StringBuilder();
                int i = 0;
                foreach (string key in parameters.Keys)
                {
                    if (i > 0)
                    {
                        buffer.AppendFormat("&{0}={1}", key, parameters[key]);
                    }
                    else
                    {
                        buffer.AppendFormat("{0}={1}", key, parameters[key]);
                    }
                    i++;
                }
                byte[] data = Encoding.UTF8.GetBytes(buffer.ToString());
                using (Stream stream = request.GetRequestStream())
                {
                    stream.Write(data, 0, data.Length);
                }
            }
            return request.GetResponse() as HttpWebResponse;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="url"></param>
        /// <param name="data"></param>
        /// <returns></returns>
        public static String post(String url, String postdata)
        {
            try {
                HttpWebRequest request = WebRequest.Create(url) as HttpWebRequest;
                request.Method = "POST";
                request.ContentType = "application/x-www-form-urlencoded";
                byte[] data = Encoding.UTF8.GetBytes(postdata.ToString());
                using (Stream stream = request.GetRequestStream())
                {
                    stream.Write(data, 0, data.Length);
                }
                HttpWebResponse response = request.GetResponse() as HttpWebResponse;
                StreamReader sr = new StreamReader(response.GetResponseStream(), Encoding.UTF8);
                string outMessage = sr.ReadToEnd();
                sr.Close();
                return outMessage;
            } catch (Exception ex) {
                throw ex;
            }
        }


    }
}
      

要求

目前按照SDK的要求:

請求封包說明:     

1. 資料傳輸以HTTP POST方式發送,資料字元集一律采用UTF-8 

2. xmldata首先需要進行base64編碼 

3. validation的效驗方式采用 MD5(xmldata + partnerid + 密碼),這裡的加号為字元串連接配接符号。 

4. 所有參數最終均須在完成資料轉換後進行URL編碼。

請求封包詳細解釋: 

1.假設partnerid為YUNDA;密碼為123456;xmldata内容為

<order></order>      

2.xmldata經過base64編碼以後變成PG9yZGVyPjwvb3JkZXI+

3.那麼要簽名的内容為PG9yZGVyPjwvb3JkZXI+YUNDA123456,經過md5後的内容就為f197e870a12528e38cb483b4e371f4ea

4.然後再對xmldata經過URL編碼,得到字元串PG9yZGVyPjwvb3JkZXI%2B

5.同樣需要對其他字段進行URL編碼,否則可能會影響POST傳遞,具體請參見HTTP POST傳輸協定

6.最終要發送的資料為: partnerid=YUNDA&version=1.0&request=data&xmldata=PG9yZGVyPjwvb3JkZXI%2B&validation=f197e870a12528e38cb483b4e371f4ea

不拉不拉不拉,一大堆,大老爺們自己去看,這些資料轉換的方法我直接貼出:

using System;
using System.Text;
using System.Web;
using System.IO;
using System.Xml.Serialization;

namespace ConsoleApplication1
{
    class DataTransform
    {
        /// <summary>
        /// 組裝主體内容
        /// </summary>
        /// <param name="requestVO"></param>
        /// <returns></returns>
        public static String signData(RequestVO requestVO)
        {
            String xmldata = Convert.ToBase64String(System.Text.Encoding.GetEncoding("UTF-8").GetBytes(requestVO.xmldata));
            string validation = System.Web.Security.FormsAuthentication.HashPasswordForStoringInConfigFile(xmldata + requestVO.partnerid + requestVO.password, "MD5").ToLower();
            string signdata = "partnerid=" + requestVO.partnerid + "&version=" + requestVO.version + "&request=" + requestVO.request + "&xmldata=" + HttpUtility.UrlEncode(xmldata) + "&validation=" + validation;
            return signdata;
        }

        /// <summary>
        /// 内容資料轉換XML
        /// </summary>
        /// <param name="type"></param>
        /// <param name="obj"></param>
        /// <returns></returns>
        public static String obj2Xml(Type type, Object obj)
        {
            XmlSerializer xml = new XmlSerializer(type);
            String xmldata = "";
            using (MemoryStream stream = new MemoryStream())
            {
                try
                {
                    xml.Serialize(stream, obj);
                    xmldata = Encoding.UTF8.GetString(stream.GetBuffer(), 0, (int)stream.Length);
                }
                catch (Exception)
                {
                    throw;
                }
            }
            return xmldata;
        }

        /// <summary>
        /// 内容清洗轉換
        /// </summary>
        /// <param name="xml"></param>
        /// <returns></returns>
        public static string xmlformat(string xml) {
            try {

                System.Xml.XmlDocument doc = new System.Xml.XmlDocument();
                doc.LoadXml(xml);

                System.IO.StringWriter sw = new System.IO.StringWriter();
                using (System.Xml.XmlTextWriter writer = new System.Xml.XmlTextWriter(sw))
                {
                    writer.Indentation = 2;  // the Indentation
                    writer.Formatting = System.Xml.Formatting.Indented;
                    doc.WriteContentTo(writer);
                    writer.Close();
                }
                return sw.ToString();
            } catch (Exception ex) {
                return xml;
            }
            
        }
    }
}
      

哈哈看了這麼多了 咱還沒看到請求電子面單的方法是吧  别急

這個類是我自己整合的在項目裡的,大老爺們先看看有不足之處 指點指點,應該能看明白!哈哈!案例的是winfrom,這個類沒有用上,方法我就不貼出來了,大佬自己去最底下載下傳吧!!!

using Commons.BLL;
using Commons.Model;
using Commons.Settings;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
using System.Text;
using System.Threading.Tasks;
using System.Web;
using System.Xml;
using System.Xml.Serialization;

namespace Commons.Helpers
{
    public class YunDaApiHelper
    {
        SettingService _settingService=new SettingService();
        /// <summary>
        /// 韻達電子面單請求url
        /// </summary>
        private static string _createYunDaUrl;
        /// <summary>
        /// 取消韻達電子面單url
        /// </summary>
        private static string _colseYunDaUrl;

        //韻達ID,密碼
        private static string _partnerid;
        private static string _password;

        //發件人資訊
        public static string FHCompany;
        public static string FHName;
        public static string FHMobile;
        public static string FHProvinceName;
        public static string FHCityName;
        public static string FHExpAreaName;
        public static string FHAddress;

        public YunDaApiHelper()
        {//_createYunDaUrl = "http://orderdev.yundasys.com:10110/cus_order/order_interface/interface_receive_order__mailno.php";//測試
            //_colseYunDaUrl = "http://orderdev.yundasys.com:10110/cus_order/order_interface/interface_cancel_order.php";//測試
            var settings = _settingService.LoadSetting<KdniaoSettings>();
            _createYunDaUrl = settings.CreateYunDaUrl;
            _colseYunDaUrl = settings.ColseYunDaUrl;
            FHCompany = settings.FHCompany;
            FHName = settings.FHName;
            FHMobile = settings.FHMobile;
            FHProvinceName = settings.FHProvinceName;
            FHCityName = settings.FHCityName;
            FHExpAreaName = settings.FHExpAreaName;
            FHAddress = settings.FHAddress;
            _partnerid = settings.YdPartnerId;
            _password = settings.YdPassword;
        }

        /// <summary>
        /// 申請韻達電子面單
        /// </summary>
        /// <param name="order"></param>
        /// <returns></returns>
        public YunDaResult CreateYunDaNo(Order order)
        {
            var model = new YDOrderModel();
            var send = new YDSender
            {
                name = FHName,//發貨人名稱
                company = FHCompany,//發貨人公司
                mobile = FHMobile,//發貨人行動電話或手機
                address = FHAddress,//發貨人位址,需要将省市區劃資訊加上,例如:上海市,上海市,青浦區盈港東路7766号
                postcode = "510000", //郵編
                city = FHProvinceName + FHCityName + FHExpAreaName,//嚴格按照國家行政區劃,省市區三級,逗号分隔。示例上海市,上海市,青浦區(cod訂單必填)
                phone = "",//固話
                branch = ""
            };
            order.sender = send;
            model.order = order;
            try
            {
                var xml = Obj2Xml(typeof (YDOrderModel), model);
                var requestVo = new YunDaRequestModel
                {
                    xmldata = xml,
                    partnerid = _partnerid,
                    password = _password,
                    version = "1.0",
                    request = "data"
                };
                var data = SignData(requestVo);
                var result = Post(_createYunDaUrl, data);
                var msgBody = new XmlDocument();
                msgBody.LoadXml(result);
                var status = GetXmlValue(msgBody, "status");
                var dto = new YunDaResult
                {
                    status = Convert.ToInt32(status),
                    order_serial_no = GetXmlValue(msgBody, "order_serial_no"),
                    msg = GetXmlValue(msgBody, "msg"),
                    mail_no = GetXmlValue(msgBody, "mail_no")
                };
                return dto;

            }
            catch (Exception ex)
            {
                var dto = new YunDaResult
                {
                    status = (int) CustomBoolean.False,
                    msg = ex.ToString()
                };
                return dto;
            }
        }

        /// <summary>
        /// 取消韻達電子面單
        /// </summary>
        /// <param name="xml"></param>
        /// <returns></returns>
        public YunDaResult ColseYunDaNo(string xml)
        {
            var requestVo = new YunDaRequestModel
            {
                xmldata = Xmlformat(xml),
                partnerid = _partnerid,
                password = _password,
                version = "1.0",
                request = "cancel_order"
            };
            try
            {
                var data = SignData(requestVo);
                var result = Post(_colseYunDaUrl, data);
                var msgBody = new XmlDocument();
                msgBody.LoadXml(result);
                var dto = new YunDaResult
                {
                    status = Convert.ToInt32(GetXmlValue(msgBody, "status")),
                    order_serial_no = GetXmlValue(msgBody, "order_serial_no"),
                    msg = GetXmlValue(msgBody, "msg")
                };
                return dto;
            }
            catch (Exception ex)
            {
                var dto = new YunDaResult
                {
                    status = (int) CustomBoolean.False,
                    msg = ex.ToString()
                };
                return dto;
            }
        }







        #region 組裝資料以及轉化xml資料
        /// <summary>
        /// 組裝主體内容
        /// </summary>
        /// <param name="requestVo"></param>
        /// <returns></returns>
        public static string SignData(YunDaRequestModel requestVo)
        {
            var xmldata = Convert.ToBase64String(System.Text.Encoding.GetEncoding("UTF-8").GetBytes(requestVo.xmldata));
            var validation = System.Web.Security.FormsAuthentication.HashPasswordForStoringInConfigFile(xmldata + requestVo.partnerid + requestVo.password, "MD5").ToLower();
            var signdata = "partnerid=" + requestVo.partnerid + "&version=" + requestVo.version + "&request=" + requestVo.request + "&xmldata=" + HttpUtility.UrlEncode(xmldata) + "&validation=" + validation;
            return signdata;
        }

        /// <summary>
        /// 内容資料轉換XML
        /// </summary>
        /// <param name="type"></param>
        /// <param name="obj"></param>
        /// <returns></returns>
        public static string Obj2Xml(Type type, object obj)
        {
            var xml = new XmlSerializer(type);
            var xmldata = "";
            using (var stream = new MemoryStream())
            {
                try
                {
                    xml.Serialize(stream, obj);
                    xmldata = Encoding.UTF8.GetString(stream.GetBuffer(), 0, (int)stream.Length);
                }
                catch (Exception)
                {
                    throw;
                }
            }
            return xmldata;
        }

        /// <summary>
        /// 内容清洗轉換
        /// </summary>
        /// <param name="xml"></param>
        /// <returns></returns>
        public static string Xmlformat(string xml)
        {
            try
            {
                var doc = new System.Xml.XmlDocument();
                doc.LoadXml(xml);
                var sw = new System.IO.StringWriter();
                using (var writer = new System.Xml.XmlTextWriter(sw))
                {
                    writer.Indentation = 2;  // the Indentation
                    writer.Formatting = System.Xml.Formatting.Indented;
                    doc.WriteContentTo(writer);
                    writer.Close();
                }
                return sw.ToString();
            }
            catch (Exception ex)
            {
                return xml;
            }

        }
        #endregion

        #region Post資料請求
        public static HttpWebResponse Post(string url, IDictionary<string, string> parameters)
        {
            var request = WebRequest.Create(url) as HttpWebRequest;
            request.Method = "POST";
            request.ContentType = "application/x-www-form-urlencoded";

            //如果需要POST資料
            if (!(parameters == null || parameters.Count == 0))
            {
                var buffer = new StringBuilder();
                var i = 0;
                foreach (var key in parameters.Keys)
                {
                    buffer.AppendFormat(i > 0 ? "&{0}={1}" : "{0}={1}", key, parameters[key]);
                    i++;
                }
                var data = Encoding.UTF8.GetBytes(buffer.ToString());
                using (var stream = request.GetRequestStream())
                {
                    stream.Write(data, 0, data.Length);
                }
            }
            return request.GetResponse() as HttpWebResponse;
        }

        public static string Post(string url, string postdata)
        {
            try
            {
                var request = WebRequest.Create(url) as HttpWebRequest;
                request.Method = "POST";
                request.ContentType = "application/x-www-form-urlencoded";
                var data = Encoding.UTF8.GetBytes(postdata.ToString());
                using (Stream stream = request.GetRequestStream())
                {
                    stream.Write(data, 0, data.Length);
                }
                var response = request.GetResponse() as HttpWebResponse;
                var sr = new StreamReader(response.GetResponseStream(), Encoding.UTF8);
                var outMessage = sr.ReadToEnd();
                sr.Close();
                return outMessage;
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }
        #endregion

        #region MyRegion
        /// <summary>
        /// XML讀取對應的值
        /// </summary>
        /// <param name="msgBody">xml</param>
        /// <param name="nodeName">節點名稱</param>
        /// <returns>傳回節點值</returns>
        public static string GetXmlValue(XmlDocument msgBody, string nodeName)
        {
            var fromUserName = msgBody.GetElementsByTagName(nodeName).Item(0);
            return fromUserName?.InnerText;
        }
        #endregion
    }
}      
SettingService   這個是系統配置參數,應該沒毛病哈哈!
so,下邊咱來看看案例的界面

      

賬号:韻達的客戶号

密碼:是韻達二維碼VIP用戶端的《接口聯調密碼》

結語

案例很簡單,但是有包含蠻多東東的,各位大佬隻要是搞通一個,那估摸着就都沒問題了!

連結:https://pan.baidu.com/s/1T3X8-TLorn5R8nZfpKkqOg 密碼:m645      ------位址要是挂了,各位直接聯系我哈!

好了!各位大老爺覺着這篇文章要是不錯就點個贊咯

繼續閱讀