前端转vue
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

MsgPackage.cs 13KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Text;
  5. using System.Text.RegularExpressions;
  6. using Platform.Common;
  7. using Platform.ServiceProxy.ServiceHelper;
  8. using Platform.Common.RunningParameters;
  9. using Platform.Common.LogSystem;
  10. using TellerSystem.ServiceProxy.Ext;
  11. using TellerSystem.ServiceProxy.Ext.ServiceHelper;
  12. using System.Diagnostics;
  13. using TellerSystem.Communication.SocketListener;
  14. using System.IO;
  15. namespace TellerSystem.Communication.Package
  16. {
  17. /// <summary>
  18. /// 交易处理相关操作
  19. /// </summary>
  20. class MsgPackage
  21. {
  22. //报文处理接口对象
  23. public static Dictionary<PackageType, IPackage> PackageList = new Dictionary<PackageType, IPackage>
  24. {
  25. {PackageType.Msg858301,Msg858301.GetInstance()},
  26. {PackageType.Msg858302,Msg858302.GetInstance()},
  27. {PackageType.Msg858304,Msg858304.GetInstance()},
  28. {PackageType.MsgXml01,MsgXml01.GetInstance()}
  29. };
  30. /// <summary>
  31. /// 交易处理
  32. /// </summary>
  33. /// <param name="msg">报文对象</param>
  34. /// <param name="transit">callserver,callagn,calltips</param>
  35. /// <returns></returns>
  36. public static bool Trade(Message msg, PackageType packageType, string transit)
  37. {
  38. //组包后数据
  39. byte[] integrateData;
  40. //交易整体数据
  41. byte[] totalData;
  42. //通讯返回数据
  43. byte[] returnData;
  44. byte[] fileData = new byte[0];
  45. bool retunValue = false;
  46. //根据当前报文类型实例化报文处理对象
  47. if (!PackageList.ContainsKey(packageType))
  48. {
  49. PlatformLogger.TradeErrorInfo("MsgPackage.Trade:不支持的报文类型!-->" + packageType.ToString(), null);
  50. return false;
  51. }
  52. try
  53. {
  54. //根据当前报文类型实例化报文处理对象,
  55. var package = PackageList[packageType];
  56. //GetPackageInstance(transit);
  57. //组包
  58. integrateData = package.Integrate(msg);
  59. //通讯
  60. var fileName = msg.Fd3.Replace(" ", "") + msg.Fd10.Replace(" ", "");
  61. Stopwatch watch = new Stopwatch();
  62. watch.Start();
  63. List<byte[]> list;
  64. if (ServiceSettings.IsRecordPrintData)
  65. {
  66. //登记通讯报文类型
  67. string msgType = msg.IsMainTrade ? packageType.ToString() : string.Empty;
  68. try
  69. {
  70. list = TradeHandle.DoTrade(transit, integrateData, msg.Fd3, fileName, PlatformSettings.Encoding.GetBytes(Message.Cconv(msg.FileData)), null, msg.SerialNumber, msgType);//生僻字转义:文件组包处理
  71. }
  72. catch { list = null; }
  73. //当主交易通讯情况,未返回数据,需要查询记录,尝试进行补偿
  74. if (msg.IsMainTrade && (list == null || list.Count == 0))
  75. {
  76. //考虑到网络波动,需尝试3次
  77. for (int i = 0; i < 3; i++)
  78. {
  79. try
  80. {
  81. var data = PrintManagerHandle.GetPrintExtDataById(msg.SerialNumber);
  82. if (data != null)
  83. {
  84. PlatformLogger.SystemInfo("MsgPackage:主通讯补偿成功!" + msg.SerialNumber);
  85. list = new List<byte[]> { data.Message };
  86. if (data.MsgFile != null && data.MsgFile.Length > 0) list.Add(data.MsgFile);
  87. break;
  88. }
  89. }
  90. catch (Exception ex) { PlatformLogger.SystemErrorInfo("MsgPackage:主通讯补偿失败!" + msg.SerialNumber, ex); }
  91. System.Threading.Thread.Sleep(200);
  92. }
  93. //登记入库
  94. TradeHandle.WriteImportantLog("主通讯触发补偿", msg.SerialNumber, ((list != null && list.Count > 0) ? "成功" : "失败"), "DoTrade", "2", string.Join(",", SocketManager.GetLocalIpAddressList()));
  95. }
  96. }
  97. else
  98. {
  99. list = TradeHandle.DoTrade(transit, integrateData, msg.Fd3, fileName, PlatformSettings.Encoding.GetBytes(Message.Cconv(msg.FileData)), null, msg.SerialNumber);
  100. }
  101. watch.Stop();
  102. if (watch.ElapsedMilliseconds > 2000)
  103. TradeHandle.WriteImportantLog("通讯时间统计", watch.ElapsedMilliseconds.ToString(), msg.Fd16, "DoTrade", "2", string.Join(",", SocketManager.GetLocalIpAddressList()));
  104. //重置主交易标识
  105. msg.IsMainTrade = false;
  106. returnData = list[0];
  107. //处理文件附件
  108. if (list.Count > 1)
  109. {
  110. fileData = list[1];
  111. }
  112. byte fileDataFlag = 0;
  113. if (returnData != null && returnData.Length > 0)
  114. {
  115. if (returnData.Length < 20)
  116. PlatformLogger.SystemErrorInfo(string.Format("MsgPackage:返回报文长度太短,无法获取附件标志!", returnData.Length), new Exception());
  117. fileDataFlag = returnData[20];
  118. }
  119. else
  120. {
  121. //通讯出现异常,需要添加错误码
  122. msg.Fd12 = "COMM";
  123. return false;
  124. }
  125. //重置附件发送标志
  126. msg.FileFlag = false;
  127. totalData = new byte[returnData.Length + fileData.Length];
  128. Array.Copy(returnData, 0, totalData, 0, returnData.Length);
  129. Array.Copy(fileData, 0, totalData, returnData.Length, fileData.Length);
  130. //解包
  131. retunValue = package.Analyze(msg, totalData);
  132. }
  133. catch (Exception ex)
  134. {
  135. //写错误信息
  136. PlatformLogger.SystemErrorInfo("Trade: 函数出错. ", ex);
  137. return false;
  138. }
  139. return retunValue;
  140. }
  141. #region 报文处理相关功能函数
  142. /// <summary>
  143. /// 加密,解密函数
  144. /// 加密:flg=1 解密:flg=0
  145. /// </summary>
  146. /// <param name="myData"></param>
  147. /// <param name="key"></param>
  148. /// <param name="flg"></param>
  149. /// <returns></returns>
  150. public static bool Encrypt(byte[] myData, byte[] key, int flg)
  151. {
  152. //TODO:焦作项目不用做数据加密,暂时写死
  153. if (true) return true;
  154. int klen;
  155. klen = key.Length;
  156. string value;
  157. try
  158. {
  159. for (int i = 0; i < myData.Length; i++)
  160. {
  161. //加密
  162. if (flg == 1)
  163. { //溢出情况
  164. if ((myData[i] + key[i % klen]) > 255)
  165. {
  166. value = Convert.ToString((myData[i]) + key[i % klen], 2);
  167. myData[i] = Convert.ToByte(Convert.ToInt32(value.Substring(value.Length - 8, 8), 2));
  168. }
  169. //正常情况
  170. else
  171. {
  172. myData[i] = Convert.ToByte(myData[i] + key[i % klen]);
  173. }
  174. }
  175. //解密
  176. else
  177. {
  178. //溢出情况
  179. if (myData[i] < key[i % klen])
  180. {
  181. value = Convert.ToString((myData[i]), 2).PadLeft(8, '0');
  182. value = "1" + value;
  183. myData[i] = Convert.ToByte(Convert.ToInt32(value, 2) - key[i % klen]);
  184. }
  185. //正常情况
  186. else
  187. {
  188. myData[i] = Convert.ToByte(myData[i] - key[i % klen]);
  189. }
  190. }
  191. }
  192. }
  193. catch (Exception ex)
  194. {
  195. //写错误信息
  196. PlatformLogger.SystemErrorInfo("加密解密出错!", ex);
  197. throw;
  198. }
  199. return true;
  200. }
  201. /// <summary>
  202. /// 复制对象的属性值
  203. /// </summary>
  204. /// <param name="obj">复制目标对象</param>
  205. /// <param name="source">复制源对象</param>
  206. public static void Clone(Message obj, Message source)
  207. {
  208. System.Reflection.PropertyInfo[] tmp = obj.GetType().GetProperties();
  209. //复制所有的属性
  210. for (int i = 0; i < tmp.Length; i++)
  211. {
  212. tmp[i].SetValue(obj, tmp[i].GetValue(source, null), null);
  213. }
  214. //复制所有的filed
  215. }
  216. /// <summary>
  217. /// 字节数组修复为GDK编码规则
  218. /// </summary>
  219. /// <param name="data"></param>
  220. public static void CheckByte(byte[] data)
  221. {
  222. byte[] tmpData = null;
  223. string tmpStr = string.Empty;
  224. if (data == null || data.Length == 0)
  225. return;
  226. for (int i = 0; i < data.Length; i++)
  227. {
  228. //如果是ascii码字符,直接跳过
  229. if (data[i] < 128)
  230. continue;
  231. //added by liuyong 2010-4-16 start
  232. else
  233. {
  234. if ((i + 1) >= data.Length)
  235. continue;
  236. tmpData = new byte[2];
  237. tmpData[0] = data[i];
  238. tmpData[1] = data[i + 1];
  239. tmpStr = PlatformSettings.Encoding.GetString(tmpData);
  240. //全角字符且不是汉字则不进行转换
  241. if (IsSbc(tmpStr) && !IsChinese(tmpStr))
  242. {
  243. i++;
  244. continue;
  245. }
  246. }
  247. //added by liuyong 2010-4-16 end
  248. if (data[i] >= 0x81 && data[i] <= 0xa0)//GBK/3高位区间 129-160
  249. {
  250. if ((i + 1) >= data.Length)
  251. continue;
  252. if (data[i + 1] < 0x40 || data[i + 1] > 0xfe) //64 254
  253. {
  254. data[i] = 61;
  255. continue;
  256. }
  257. i++;
  258. }
  259. else if (data[i] >= 0xa1 && data[i] <= 0xa9)//GBK/1 高位区间 161-169
  260. {
  261. if ((i + 1) >= data.Length)
  262. continue;
  263. if (data[i + 1] < 0xa1 || data[i + 1] > 0xef) //161 239
  264. {
  265. data[i] = 61;
  266. continue;
  267. }
  268. i++;
  269. }
  270. else if (data[i] >= 0xaa && data[i] <= 0xfe)//GBK/4高位区间 170-254
  271. {
  272. if ((i + 1) >= data.Length)
  273. continue;
  274. if (data[i + 1] < 0x40) //64
  275. {
  276. data[i] = 61;
  277. continue;
  278. }
  279. else if (data[i + 1] > 0xa0) //160
  280. {
  281. //GBK/2高位区间
  282. if ((data[i] >= 0xb0 && data[i] <= 0xf7)) //176-247
  283. {
  284. //低位错误,证明是随机字符,高低位同时修复161 254
  285. if (data[i + 1] < 0xa1 || data[i + 1] > 0xfe)
  286. {
  287. data[i] = 61;
  288. continue;
  289. }
  290. }
  291. }
  292. i++;
  293. }
  294. else //错误乱码直接修复
  295. {
  296. data[i] = 61;
  297. }
  298. }
  299. }
  300. /// <summary>
  301. /// 判断字符串是否是全角字符
  302. /// </summary>
  303. /// <param name="str"></param>
  304. /// <returns></returns>
  305. private static bool IsSbc(string str)
  306. {
  307. bool blRet = false;
  308. if (2 * str.Length == Encoding.Default.GetByteCount(str))
  309. {
  310. blRet = true;
  311. }
  312. else
  313. {
  314. blRet = false;
  315. }
  316. return blRet;
  317. }
  318. /// <summary>
  319. /// 判断是否为中文
  320. /// </summary>
  321. /// <param name="word"></param>
  322. /// <returns></returns>
  323. private static bool IsChinese(string word)
  324. {
  325. Regex rx = null;
  326. if (string.IsNullOrEmpty(word))
  327. return false;
  328. rx = new Regex("^[\u4e00-\u9fa5]$");
  329. if (rx.IsMatch(word))
  330. return true;
  331. else
  332. return false;
  333. }
  334. #endregion
  335. }
  336. }