using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Security.Cryptography;
using System.Text;
using System.Threading.Tasks;
using System.Xml;
using System.Xml.Linq;
using DSWeb.MvcShipping.DAL.MsSysParamSet;
using DSWeb.MvcShipping.Models.MsOpExpress;
using InvokeWebService;
namespace DSWeb.MvcShipping.DAL.MsOpExpressDAL
{
public class SFService
{
//顾客编码
private static string ClientCode = MsSysParamSetDAL.GetData("PARAMNAME='ClientCode'").PARAMVALUE;
//电商加密私钥,校验码,注意保管,不要泄漏
private static string CheckWord = MsSysParamSetDAL.GetData("PARAMNAME='CheckWord'").PARAMVALUE;
//月结卡号
private static string custid = MsSysParamSetDAL.GetData("PARAMNAME='custid'").PARAMVALUE;
//顺丰运单查询接口
private static string OrderUrl = "http://bsp-oisp.sf-express.com/bsp-oisp/sfexpressService";
#region 路由查询
///
/// 路由查询
///
///
///
public static List GetHttpRouteSearch(RouteSearchService model)
{
//返回路由查询XML请求体
var xml = GetRoutexml(model);
//MD5编码
var pass = Convert.ToBase64String(MD5(xml + CheckWord));
var result = GetRouteack(OrderUrl, "xml=" + xml + "&verifyCode=" + pass);
return result;
}
///
/// 路由查询
///
/// URL地址
/// 编码后的请求体
///
private static List GetRouteack(string add, string post)
{
var client = new WebClient();
var sXml = "";
var rutoelist = new List();
try
{
var postData = Encoding.UTF8.GetBytes(post);
client.Headers.Clear();
//采取POST方式必须加的header,如果改为GET方式的话就去掉这句话即可
client.Headers.Add("Content-Type", "application/x-www-form-urlencoded");
sXml = Encoding.UTF8.GetString(client.UploadData(add, "POST", postData));
//判断返回响应体是否是ERR
if (Convert.ToString(GetNodeValue(sXml, "Head")) == "ERR")
{
sXml = XElement.Parse(sXml).Value;
rutoelist.Add(new RouteResponse {failMessage = XElement.Parse(sXml).Value});
}
//将xml字符串转换为XML文档
var xmlDoc = XDocument.Parse(sXml);
//获取 文档中子代元素 RouteResponse 的所有集合
var nodelist = xmlDoc.Descendants("RouteResponse");
if (nodelist != null)
{
//获取源集合中每个元素和子元素的集合
var pieceareas = nodelist.Elements();
foreach (var item in pieceareas)
//循环添加到路由响应容器集合中
rutoelist.Add(new RouteResponse
{
//获取XML mailno 属性值
mailno = GetXmlNodeValue(sXml, "RouteResponse", "mailno"),
Route = new Route
{
opcode = item.Attribute("opcode").Value,
accept_address = item.Attribute("accept_address").Value,
accept_time = item.Attribute("accept_time").Value,
remark = item.Attribute("remark").Value
}
});
}
}
catch (Exception e)
{
client.Dispose();
rutoelist.Add(new RouteResponse {failMessage = XElement.Parse(sXml).Value});
return rutoelist;
}
client.Dispose();
return rutoelist;
}
///
/// 构建路由查询XML请求体
///
/// 路由查询请求模型
///
private static string GetRoutexml(RouteSearchService model)
{
string[] xmls =
{
"",
"" + ClientCode + "",
"",
"",
"",
""
};
var xml = "";
foreach (var s in xmls)
if (xml == "")
xml = s;
else
xml += "\r\n" + s;
return xml;
}
#endregion
#region 下单接口
private static string CreateOrderXML(Order order,cargo cargo)
{
string[] xmls =
{
"",
"" + ClientCode + "",
"",
"",
"",
"",
""
};
var xml = "";
foreach (var s in xmls)
if (xml == "")
xml = s;
else
xml += "\r\n" + s;
return xml;
}
/**
* 获取顺丰下订单接口xml
* @param params
* @return
*/
private static string getOrderServiceRequestXml(Order order)
{
StringBuilder sb = new StringBuilder();
sb.Append("");
sb.Append("" + ClientCode + "");
sb.Append("");
sb.Append(" ");
//货物信息
sb.Append("");
//sb.Append("count=1").Append(">");
sb.Append("");
sb.Append("");
sb.Append("");
sb.Append("");
return sb.ToString();
}
public static MsOpSFPrint CreateOrder(Order order,cargo cargo)
{
order.custid = custid;
//返回路由查询XML请求体
var xml = CreateOrderXML(order,cargo);
//MD5编码
var pass = Convert.ToBase64String(MD5(xml + CheckWord));
var result = CreateOrderAction(OrderUrl, "xml=" + xml + "&verifyCode=" + pass);
return result;
}
///
/// 下单
///
/// URL地址
/// 编码后的请求体
///
private static MsOpSFPrint CreateOrderAction(string add, string post)
{
var client = new WebClient();
var sXml = "";
var orderResult = new MsOpSFPrint();
try
{
//编码,尤其是汉字,事先要看下抓取网页的编码方式
var postData = Encoding.UTF8.GetBytes(post);
client.Headers.Clear();
//采取POST方式必须加的header,如果改为GET方式的话就去掉这句话即可
client.Headers.Add("Content-Type", "application/x-www-form-urlencoded");
sXml = Encoding.UTF8.GetString(client.UploadData(add, "POST", postData));
if (Convert.ToString(GetNodeValue(sXml, "Head")) == "ERR")
{
sXml = XElement.Parse(sXml).Value;
orderResult.mailno = "ERR";
}
//将xml字符串转换为XML文档
var xmlDoc = XDocument.Parse(sXml);
//获取 文档中子代元素 RouteResponse 的所有集合
var nodelist = xmlDoc.Descendants("OrderResponse");
if (nodelist != null)
{
//获取源集合中每个元素和子元素的集合
//var pieceareas = nodelist.Elements();
orderResult.mailno = GetXmlNodeValue(sXml, "OrderResponse", "mailno");
orderResult.origincode = GetXmlNodeValue(sXml, "OrderResponse", "origincode");
orderResult.destcode = GetXmlNodeValue(sXml, "OrderResponse", "destcode");
//orderResult.filter_result = Convert.ToInt16(GetXmlNodeValue(sXml, "OrderResponse", "filter_result"));
orderResult.orderid = GetXmlNodeValue(sXml, "OrderResponse", "orderid");
orderResult.rlsCode = orderResult.proCode = GetXmlNodeValue(sXml, "rls_info", "rls_code");
//orderResult.invoke_result = orderResult.proCode = GetXmlNodeValue(sXml, "rls_info", "invoke_result");
//orderResult.errorDesc = orderResult.proCode = GetXmlNodeValue(sXml, "rls_info", "errorDesc");
orderResult.proCode = GetXmlNodeValue(sXml, "rls_detail", "proCode");
orderResult.destRouteLabel = GetXmlNodeValue(sXml, "rls_detail", "destRouteLabel");
orderResult.destTeamCode = GetXmlNodeValue(sXml, "rls_detail", "destTeamCode");
orderResult.codingMapping = GetXmlNodeValue(sXml, "rls_detail", "codingMapping");
orderResult.codingMappingOut = GetXmlNodeValue(sXml, "rls_detail", "codingMappingOut");
orderResult.twoDimensionCode = GetXmlNodeValue(sXml, "rls_detail", "twoDimensionCode");
orderResult.abFlag = GetXmlNodeValue(sXml, "rls_detail", "abFlag");
}
}
catch (Exception e)
{
client.Dispose();
//rutoelist.Add(new RouteResponse {failMessage = XElement.Parse(sXml).Value});
//return rutoelist;
}
client.Dispose();
return orderResult;
}
#endregion
#region XML处理
///
/// 读取XML资源中的指定节点内容
///
/// XML资源
/// 节点名称
/// 节点内容
public static object GetNodeValue(string source, string nodeName)
{
if (source == null || nodeName == null || source == "" || nodeName == "" ||
source.Length < nodeName.Length * 2) return null;
var start = source.IndexOf("<" + nodeName + ">") + nodeName.Length + 2;
var end = source.IndexOf("" + nodeName + ">");
if (start == -1 || end == -1)
return null;
if (start >= end)
return null;
return source.Substring(start, end - start);
}
///
/// 获取xml任意节点中某个属性值
///
/// xml
/// 节点名称
/// 属性名称
///
public static string GetXmlNodeValue(string strXml, string strNodeName, string strValueName)
{
try
{
var xmlDoc = new XmlDocument();
xmlDoc.LoadXml(strXml);
var xNode = xmlDoc.SelectSingleNode("//" + strNodeName + "");
var strValue = xNode.Attributes[strValueName].Value;
return strValue;
}
catch (Exception ex)
{
//return ex.Message;
return "";
}
}
///
/// 获取MD5
///
///
///
private static byte[] MD5(string str)
{
var result = Encoding.UTF8.GetBytes(str);
MD5 md5 = new MD5CryptoServiceProvider();
var output = md5.ComputeHash(result);
return output;
}
#endregion
#region 路由推送
public static string RoutePushService(RoutePushService model)
{
var xml = GetPushxml(model);
var pass = Convert.ToBase64String(MD5(xml + CheckWord));
var strData = "xml=" + xml + "&verifyCode=" + pass;
var strHeaders = "Content-Type: application/x-www-form-urlencoded\r\n";
var bytePost = Encoding.UTF8.GetBytes(strData);
var byteHeaders = Encoding.UTF8.GetBytes(strHeaders);
var str = GetPushBack(OrderUrl, "xml=" + xml + "&verifyCode=" + pass);
return str;
}
///
/// 构建路由推送XML
///
/// 推送容器
///
private static string GetPushxml(RoutePushService model)
{
string[] xmls =
{
"",
"",
"",
"orderid=‘" + model.orderid + "‘/>",
"",
""
};
var xml = "";
foreach (var s in xmls)
if (xml == "")
xml = s;
else
xml += "\r\n" + s;
return xml;
}
///
/// 推送
///
/// URL
/// 数据
///
private static string GetPushBack(string add, string post)
{
var pusthclient = new WebClient();
var sXml = "";
try
{
var postData = Encoding.UTF8.GetBytes(post);
pusthclient.Headers.Clear();
//采取POST方式必须加的header,如果改为GET方式的话就去掉这句话即可
pusthclient.Headers.Add("Content-Type", "application/x-www-form-urlencoded");
sXml = Encoding.UTF8.GetString(pusthclient.UploadData(add, "POST", postData));
//获取Head是否是ERR,若不是,直接返回OK
if (Convert.ToString(GetNodeValue(sXml, "Head")) == "ERR")
sXml = XElement.Parse(sXml).Value;
else
sXml = "OK";
}
catch (Exception e)
{
sXml = e.Message;
}
pusthclient.Dispose();
return sXml;
}
#endregion
}
///
/// 路由请求实体
///
public class RouteSearchService
{
///
/// 查询号类别 1运单号查询 2 订单号查询
///
public string tracking_type { get; set; }
///
/// 查询号 tracking_type=1 则此值是运单号 tracking_type为1=2 此值是订单号
///
public string tracking_number { get; set; }
///
/// 1 标准路由查询 2定制路由查询
///
public string method_type { get; set; }
///
/// 收件人或寄件人手机号后四位
///
public string check_phoneNo { get; set; }
}
///
/// 路由返回报文实体
///
public class RouteResponse
{
public string mailno { get; set; }
public Route Route { get; set; }
public string failMessage { get; set; }
}
///
/// 路由信息实体
///
public class Route
{
public string accept_time { get; set; }
public string accept_address { get; set; }
public string remark { get; set; }
public string opcode { get; set; }
}
///
/// 下单实体
///
public class Order
{
//客户订单号,必填
public string orderid { get; set; }
//顺丰运单号,条件
public string mailno { get; set; }
//寄件方公司名称,条件
public string j_company { get; set; }
//寄件方联系人,条件
public string j_contact { get; set; }
//寄件方联系电话,条件
public string j_tel { get; set; }
//寄件方手机,否
public string j_mobile { get; set; }
//寄件方所在省份,否
public string j_province { get; set; }
//寄件方所在城市名称,否
public string j_city { get; set; }
//寄件方所在区县,否
public string j_county { get; set; }
//寄件方详细地址,条件
public string j_address { get; set; }
//到件方公司名称,必填
public string d_company { get; set; }
//到件方联系人,必填
public string d_contact { get; set; }
//到件方联系电话,必填
public string d_tel { get; set; }
//到件方手机,否
public string d_mobile { get; set; }
//到件方所在省份,否
public string d_province { get; set; }
//到件方所在城市名称,否
public string d_city { get; set; }
//到件方所在县区,否
public string d_county { get; set; }
//到件方详细地址,是
public string d_address { get; set; }
//月结号,否
public string custid { get; set; }
//付款方式,否
public int pay_method { get; set; }
//快件产品编码,否
public string express_type { get; set; }
//快件包裹数,否
public int parcel_quantity { get; set; }
//客户订单货物总长,否
public decimal cargo_length { get; set; }
//客户订单货物总宽,否
public decimal cargo_width { get; set; }
//客户订单货物高度,否
public decimal cargo_height { get; set; }
//总体积,否
public decimal volume { get; set; }
//订单货物总重量,否
public decimal cargo_total_weight { get; set; }
//要求上门开始时间,否
public DateTime sendstarttime { get; set; }
//是否通过手持端通知顺丰快递员,否
public int is_docall { get; set; }
//是否要求签回单号,否
public string need_return_tracking_no { get; set; }
//顺丰签回运单号,否
public string return_tracking { get; set; }
//温度范围类型,条件
public int temp_range { get; set; }
//业务模板编码,否
public string template { get; set; }
//备注,否
public string remark { get; set; }
//客户自取,否
public int oneself_pickup_flg { get; set; }
//特殊派送类型,否
public string special_delivery_type_code { get; set; }
//特殊派送类型表述,否
public string special_delivery_value { get; set; }
//实名认证流水号,否
public string realname_num { get; set; }
//签回单路由返回,否
public int routelabelForReturn { get; set; }
//路由标签查询服务,否
public int routelabelService { get; set; }
//是否使用国家统一面单号,否
public int is_unified_waybill_no { get; set; }
}
public class cargo
{
//货物名称,必填
public string name { get; set; }
//货物数量,条件
public int count { get; set; }
}
public class OrderResponse
{
//客户订单号,必填
public string orderid { get; set; }
//顺丰运单号,否
public string mailno { get; set; }
//顺丰签回单服务运单号,否
public string return_tracking_no { get; set; }
//原寄地区域代码,否
public string origincode { get; set; }
//目的地区域代码,否
public string destcode { get; set; }
//筛单结果:1:人工确认,2:可收派,3:不可以收派
public int filter_result { get; set; }
//若filter_result为3则为必填,1:收方超范围,2:寄方超范围,3:其他原因
public string remark { get; set; }
//代理单号
public string agentMailno { get; set; }
//地址映射码
public string mapping_mark { get; set; }
//url
public string url { get; set; }
//用于第三方支付的url
public string PaymentLink { get; set; }
public rls_info rls_info { get; set; }
}
///
/// 下单元素响应
///
public class rls_info
{
public string invoke_result { get; set; }
public string rls_code { get; set; }
public string errorDesc { get; set; }
public rls_detail rls_detail { get; set; }
}
public class rls_detail
{
public string waybillNo { get; set; }
//原寄地中转场
public string sourceTransferCode { get; set; }
//原寄地城市代码
public string sourceCityCode { get; set; }
//原寄地网点代码
public string sourceDeptCode { get; set; }
//原寄地单元代码
public string sourceTeamCode { get; set; }
//目的地城市代码
public string deptCityCode { get; set; }
//目的地网点代码
public string deptDeptCode { get; set; }
//目的地代码映射
public string destDeptCodeMapping { get; set; }
//目的地单元代码
public string destTeamCode { get; set; }
//目的地单元区域码映射
public string destTeamCodeMapping { get; set; }
//目的地中转场
public string destTransferCode { get; set; }
//打单时的标签信息
public string destRouteLabel { get; set; }
//产品名称
public string proName { get; set; }
//快件内容
public string cargoTypeCode { get; set; }
//时效代码
public string limitTypeCode { get; set; }
//产品类型
public string expressTypeCode { get; set; }
//入港映射码
public string codingMapping { get; set; }
//出港映射码
public string codingMappingOut { get; set; }
//xb标志
public string xbFlag { get; set; }
//打印标志
public string printFlag { get; set; }
//二维码
public string twoDimensionCode { get; set; }
//时效类型
public string proCode { get; set; }
//打印图标
public string printIcon { get; set; }
//ab标
public string abFlag { get; set; }
//时效类型
public string errMsg { get; set; }
//目的地口岸代码
public string destPortCode { get; set; }
//目的地国别
public string destCountry { get; set; }
//目的地邮编
public string destPostCode { get; set; }
//总价值
public string goodsValueTotal { get; set; }
//币种
public string currencySymbol { get; set; }
//件数
public string goodsNumber { get; set; }
//校验码
public string checkCode { get; set; }
}
///
/// 路由推送模型
///
public class RoutePushService
{
///
/// 路由节点信息编号,每一个id 代表一条不同的路由节点信息
///
public int id { get; set; }
///
/// 顺丰运单号
///
public string mailno { get; set; }
///
/// 客户订单号
///
public string orderid { get; set; }
///
/// 路由节点产生的时间,格式:YYYY-MM-DDHH24:MM:SS
///
public DateTime acceptTime { get; set; }
///
/// 路由节点发生的城市
///
public string acceptAddress { get; set; } = "深圳";
///
/// 路由节点具体描述
///
public string remark { get; set; } = "上门收件";
///
/// 路由节点操作码
///
public string opCode { get; set; } = "50";
}
}