• 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      ------地址要是挂了,各位直接联系我哈!

    好了!各位大老爷觉着这篇文章要是不错就点个赞咯

     
  • 相关阅读:
    live2d 快速实现好看的看板娘特效
    JQuery 日期转换日期方法封装
    SQL Server 之 DateTime的常用方法
    C# 之DateDiff 时间差扩展方法
    SQL Server 之如何查询某数据库下的触发器和语句
    Css 设置固定表格头部,内容可滚动
    jquery 点击tr选中checkbox,解决checkbox的默认点击事件被阻止的问题
    VS切换代码自动补全模式
    C#实现软键盘的几个关键技术介绍
    C# 模拟软件键盘输入,使Winfrom窗体不获取鼠标焦点方法
  • 原文地址:https://www.cnblogs.com/Agui520/p/9177794.html
Copyright © 2020-2023  润新知