using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Text.RegularExpressions; using Platform.Common; using Platform.ServiceProxy.ServiceHelper; using Platform.Common.RunningParameters; using Platform.Common.LogSystem; using TellerSystem.ServiceProxy.Ext; using TellerSystem.ServiceProxy.Ext.ServiceHelper; using System.Diagnostics; using TellerSystem.Communication.SocketListener; using System.IO; namespace TellerSystem.Communication.Package { /// /// 交易处理相关操作 /// class MsgPackage { //报文处理接口对象 public static Dictionary PackageList = new Dictionary { {PackageType.Msg858301,Msg858301.GetInstance()}, {PackageType.Msg858302,Msg858302.GetInstance()}, {PackageType.Msg858304,Msg858304.GetInstance()}, {PackageType.MsgXml01,MsgXml01.GetInstance()} }; /// /// 交易处理 /// /// 报文对象 /// callserver,callagn,calltips /// public static bool Trade(Message msg, PackageType packageType, string transit) { //组包后数据 byte[] integrateData; //交易整体数据 byte[] totalData; //通讯返回数据 byte[] returnData; byte[] fileData = new byte[0]; bool retunValue = false; //根据当前报文类型实例化报文处理对象 if (!PackageList.ContainsKey(packageType)) { PlatformLogger.TradeErrorInfo("MsgPackage.Trade:不支持的报文类型!-->" + packageType.ToString(), null); return false; } try { //根据当前报文类型实例化报文处理对象, var package = PackageList[packageType]; //GetPackageInstance(transit); //组包 integrateData = package.Integrate(msg); //通讯 var fileName = msg.Fd3.Replace(" ", "") + msg.Fd10.Replace(" ", ""); Stopwatch watch = new Stopwatch(); watch.Start(); List list; if (ServiceSettings.IsRecordPrintData) { //登记通讯报文类型 string msgType = msg.IsMainTrade ? packageType.ToString() : string.Empty; try { list = TradeHandle.DoTrade(transit, integrateData, msg.Fd3, fileName, PlatformSettings.Encoding.GetBytes(Message.Cconv(msg.FileData)), null, msg.SerialNumber, msgType);//生僻字转义:文件组包处理 } catch { list = null; } //当主交易通讯情况,未返回数据,需要查询记录,尝试进行补偿 if (msg.IsMainTrade && (list == null || list.Count == 0)) { //考虑到网络波动,需尝试3次 for (int i = 0; i < 3; i++) { try { var data = PrintManagerHandle.GetPrintExtDataById(msg.SerialNumber); if (data != null) { PlatformLogger.SystemInfo("MsgPackage:主通讯补偿成功!" + msg.SerialNumber); list = new List { data.Message }; if (data.MsgFile != null && data.MsgFile.Length > 0) list.Add(data.MsgFile); break; } } catch (Exception ex) { PlatformLogger.SystemErrorInfo("MsgPackage:主通讯补偿失败!" + msg.SerialNumber, ex); } System.Threading.Thread.Sleep(200); } //登记入库 TradeHandle.WriteImportantLog("主通讯触发补偿", msg.SerialNumber, ((list != null && list.Count > 0) ? "成功" : "失败"), "DoTrade", "2", string.Join(",", SocketManager.GetLocalIpAddressList())); } } else { list = TradeHandle.DoTrade(transit, integrateData, msg.Fd3, fileName, PlatformSettings.Encoding.GetBytes(Message.Cconv(msg.FileData)), null, msg.SerialNumber); } watch.Stop(); if (watch.ElapsedMilliseconds > 2000) TradeHandle.WriteImportantLog("通讯时间统计", watch.ElapsedMilliseconds.ToString(), msg.Fd16, "DoTrade", "2", string.Join(",", SocketManager.GetLocalIpAddressList())); //重置主交易标识 msg.IsMainTrade = false; returnData = list[0]; //处理文件附件 if (list.Count > 1) { fileData = list[1]; } byte fileDataFlag = 0; if (returnData != null && returnData.Length > 0) { if (returnData.Length < 20) PlatformLogger.SystemErrorInfo(string.Format("MsgPackage:返回报文长度太短,无法获取附件标志!", returnData.Length), new Exception()); fileDataFlag = returnData[20]; } else { //通讯出现异常,需要添加错误码 msg.Fd12 = "COMM"; return false; } //重置附件发送标志 msg.FileFlag = false; totalData = new byte[returnData.Length + fileData.Length]; Array.Copy(returnData, 0, totalData, 0, returnData.Length); Array.Copy(fileData, 0, totalData, returnData.Length, fileData.Length); //解包 retunValue = package.Analyze(msg, totalData); } catch (Exception ex) { //写错误信息 PlatformLogger.SystemErrorInfo("Trade: 函数出错. ", ex); return false; } return retunValue; } #region 报文处理相关功能函数 /// /// 加密,解密函数 /// 加密:flg=1 解密:flg=0 /// /// /// /// /// public static bool Encrypt(byte[] myData, byte[] key, int flg) { //TODO:焦作项目不用做数据加密,暂时写死 if (true) return true; int klen; klen = key.Length; string value; try { for (int i = 0; i < myData.Length; i++) { //加密 if (flg == 1) { //溢出情况 if ((myData[i] + key[i % klen]) > 255) { value = Convert.ToString((myData[i]) + key[i % klen], 2); myData[i] = Convert.ToByte(Convert.ToInt32(value.Substring(value.Length - 8, 8), 2)); } //正常情况 else { myData[i] = Convert.ToByte(myData[i] + key[i % klen]); } } //解密 else { //溢出情况 if (myData[i] < key[i % klen]) { value = Convert.ToString((myData[i]), 2).PadLeft(8, '0'); value = "1" + value; myData[i] = Convert.ToByte(Convert.ToInt32(value, 2) - key[i % klen]); } //正常情况 else { myData[i] = Convert.ToByte(myData[i] - key[i % klen]); } } } } catch (Exception ex) { //写错误信息 PlatformLogger.SystemErrorInfo("加密解密出错!", ex); throw; } return true; } /// /// 复制对象的属性值 /// /// 复制目标对象 /// 复制源对象 public static void Clone(Message obj, Message source) { System.Reflection.PropertyInfo[] tmp = obj.GetType().GetProperties(); //复制所有的属性 for (int i = 0; i < tmp.Length; i++) { tmp[i].SetValue(obj, tmp[i].GetValue(source, null), null); } //复制所有的filed } /// /// 字节数组修复为GDK编码规则 /// /// public static void CheckByte(byte[] data) { byte[] tmpData = null; string tmpStr = string.Empty; if (data == null || data.Length == 0) return; for (int i = 0; i < data.Length; i++) { //如果是ascii码字符,直接跳过 if (data[i] < 128) continue; //added by liuyong 2010-4-16 start else { if ((i + 1) >= data.Length) continue; tmpData = new byte[2]; tmpData[0] = data[i]; tmpData[1] = data[i + 1]; tmpStr = PlatformSettings.Encoding.GetString(tmpData); //全角字符且不是汉字则不进行转换 if (IsSbc(tmpStr) && !IsChinese(tmpStr)) { i++; continue; } } //added by liuyong 2010-4-16 end if (data[i] >= 0x81 && data[i] <= 0xa0)//GBK/3高位区间 129-160 { if ((i + 1) >= data.Length) continue; if (data[i + 1] < 0x40 || data[i + 1] > 0xfe) //64 254 { data[i] = 61; continue; } i++; } else if (data[i] >= 0xa1 && data[i] <= 0xa9)//GBK/1 高位区间 161-169 { if ((i + 1) >= data.Length) continue; if (data[i + 1] < 0xa1 || data[i + 1] > 0xef) //161 239 { data[i] = 61; continue; } i++; } else if (data[i] >= 0xaa && data[i] <= 0xfe)//GBK/4高位区间 170-254 { if ((i + 1) >= data.Length) continue; if (data[i + 1] < 0x40) //64 { data[i] = 61; continue; } else if (data[i + 1] > 0xa0) //160 { //GBK/2高位区间 if ((data[i] >= 0xb0 && data[i] <= 0xf7)) //176-247 { //低位错误,证明是随机字符,高低位同时修复161 254 if (data[i + 1] < 0xa1 || data[i + 1] > 0xfe) { data[i] = 61; continue; } } } i++; } else //错误乱码直接修复 { data[i] = 61; } } } /// /// 判断字符串是否是全角字符 /// /// /// private static bool IsSbc(string str) { bool blRet = false; if (2 * str.Length == Encoding.Default.GetByteCount(str)) { blRet = true; } else { blRet = false; } return blRet; } /// /// 判断是否为中文 /// /// /// private static bool IsChinese(string word) { Regex rx = null; if (string.IsNullOrEmpty(word)) return false; rx = new Regex("^[\u4e00-\u9fa5]$"); if (rx.IsMatch(word)) return true; else return false; } #endregion } }