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
}
}