You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
DS7/DSWeb/Areas/MvcShipping/DAL/MsOpExpress/MsOpSFService.cs

855 lines
27 KiB
C#

2 years ago
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 路由查询
/// <summary>
/// 路由查询
/// </summary>
/// <param name="model"></param>
/// <returns></returns>
public static List<RouteResponse> 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;
}
/// <summary>
/// 路由查询
/// </summary>
/// <param name="add">URL地址</param>
/// <param name="post">编码后的请求体</param>
/// <returns></returns>
private static List<RouteResponse> GetRouteack(string add, string post)
{
var client = new WebClient();
var sXml = "";
var rutoelist = new List<RouteResponse>();
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;
}
/// <summary>
/// 构建路由查询XML请求体
/// </summary>
/// <param name="model">路由查询请求模型</param>
/// <returns></returns>
private static string GetRoutexml(RouteSearchService model)
{
string[] xmls =
{
"<Request service='RouteService' lang='zh-CN'>",
"<Head>" + ClientCode + "</Head>",
"<Body>",
"<RouteRequest",
"tracking_type='" + model.tracking_type + "'",
"method_type='" + model.method_type + "'",
//"check_phoneNo='" + model.check_phoneNo + "'",
"tracking_number='" + model.tracking_number + "'/>",
"</Body>",
"</Request>"
};
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 =
{
"<Request service='OrderService' lang='zh-CN'>",
"<Head>" + ClientCode + "</Head>",
"<Body>",
"<Order",
"orderid='" + order.orderid + "'",
"j_company='" + order.j_company + "'",
"j_contact='" + order.j_contact + "'",
"j_tel='" + order.j_tel + "'",
"j_province='" + order.j_province + "'",
"j_city='" + order.j_city + "'",
"j_county='" + order.j_county + "'",
"j_address='" + order.j_address+ "'",
"d_province='" + order.d_province + "'",
"d_city='" + order.d_city + "'",
"d_county='" + order.d_county + "'",
"d_company='" + order.d_company + "'",
"d_contact='" + order.d_contact + "'",
"d_tel='" + order.d_tel + "'",
"d_address='" + order.d_address + "'/>",
"<Cargo name='" + cargo.name + "'></Cargo>",
"</Body>",
"</Request>"
};
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("<Request service='OrderService' lang='zh-CN'>");
sb.Append("<Head>" + ClientCode + "</Head>");
sb.Append("<Body>");
sb.Append("<Order").Append(" ");
sb.Append("orderid='" + order.orderid.ToString().Trim() + "" + "'").Append(" ");
//返回顺丰运单号
// sb.Append("is_gen_bill_no='1'").Append(" ");
//寄件方信息
sb.Append("j_company='" + order.j_company + "'").Append(" ");
sb.Append("j_contact='" + order.j_contact + "'").Append(" ");
sb.Append("j_tel='" + order.j_tel + "'").Append(" ");
sb.Append("j_address='" + order.j_province + order.j_city + order.j_county + order.j_address + "'").Append(" ");
//收件方信息
sb.Append("d_company='" + order.d_company + "'").Append(" ");
sb.Append("d_contact='" + order.d_contact.ToString().Trim() + "'").Append(" ");
sb.Append("d_tel='" + order.d_tel.ToString().Trim() + "'").Append(" ");
sb.Append("d_address='" + order.d_address.ToString().Trim() + "'").Append(" ");
sb.Append(" > ");
//货物信息
sb.Append("<Cargo").Append(" ");
sb.Append("name='手机'").Append(">");
//sb.Append("count=1").Append(">");
sb.Append("</Cargo>");
sb.Append("</Order>");
sb.Append("</Body>");
sb.Append("</Request>");
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;
}
/// <summary>
/// 下单
/// </summary>
/// <param name="add">URL地址</param>
/// <param name="post">编码后的请求体</param>
/// <returns></returns>
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处理
/// <summary>
/// 读取XML资源中的指定节点内容
/// </summary>
/// <param name="source">XML资源</param>
/// <param name="nodeName">节点名称</param>
/// <returns>节点内容</returns>
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);
}
/// <summary>
/// 获取xml任意节点中某个属性值
/// </summary>
/// <param name="strXml">xml</param>
/// <param name="strNodeName">节点名称</param>
/// <param name="strValueName">属性名称</param>
/// <returns></returns>
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 "";
}
}
/// <summary>
/// 获取MD5
/// </summary>
/// <param name="str"></param>
/// <returns></returns>
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;
}
/// <summary>
/// 构建路由推送XML
/// </summary>
/// <param name="model">推送容器</param>
/// <returns></returns>
private static string GetPushxml(RoutePushService model)
{
string[] xmls =
{
"<Request service=RouteService lang=zh-CN>",
"<Body>",
"<WaybillRoute",
"id=" + model.id + "",
"mailno=" + model.mailno + "",
"acceptTime=" + model.acceptTime.ToString("yyyy-MM-dd HH:mm:ss") + "",
"acceptAddress=" + model.acceptAddress + "",
"remark=" + model.remark + "",
"opCode=50/>",
"orderid=" + model.orderid + "/>",
"</Body>",
"</Request>"
};
var xml = "";
foreach (var s in xmls)
if (xml == "")
xml = s;
else
xml += "\r\n" + s;
return xml;
}
/// <summary>
/// 推送
/// </summary>
/// <param name="add">URL</param>
/// <param name="post">数据</param>
/// <returns></returns>
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
}
/// <summary>
/// 路由请求实体
/// </summary>
public class RouteSearchService
{
/// <summary>
/// 查询号类别 1运单号查询 2 订单号查询
/// </summary>
public string tracking_type { get; set; }
/// <summary>
/// 查询号 tracking_type=1 则此值是运单号 tracking_type为1=2 此值是订单号
/// </summary>
public string tracking_number { get; set; }
/// <summary>
/// 1 标准路由查询 2定制路由查询
/// </summary>
public string method_type { get; set; }
/// <summary>
/// 收件人或寄件人手机号后四位
/// </summary>
public string check_phoneNo { get; set; }
}
/// <summary>
/// 路由返回报文实体
/// </summary>
public class RouteResponse
{
public string mailno { get; set; }
public Route Route { get; set; }
public string failMessage { get; set; }
}
/// <summary>
/// 路由信息实体
/// </summary>
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; }
}
/// <summary>
/// 下单实体
/// </summary>
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; }
}
/// <summary>
/// 下单元素响应
/// </summary>
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; }
}
/// <summary>
/// 路由推送模型
/// </summary>
public class RoutePushService
{
/// <summary>
/// 路由节点信息编号每一个id 代表一条不同的路由节点信息
/// </summary>
public int id { get; set; }
/// <summary>
/// 顺丰运单号
/// </summary>
public string mailno { get; set; }
/// <summary>
/// 客户订单号
/// </summary>
public string orderid { get; set; }
/// <summary>
/// 路由节点产生的时间格式YYYY-MM-DDHH24:MM:SS
/// </summary>
public DateTime acceptTime { get; set; }
/// <summary>
/// 路由节点发生的城市
/// </summary>
public string acceptAddress { get; set; } = "深圳";
/// <summary>
/// 路由节点具体描述
/// </summary>
public string remark { get; set; } = "上门收件";
/// <summary>
/// 路由节点操作码
/// </summary>
public string opCode { get; set; } = "50";
}
}