/// <summary> /// 获取处理选项 /// </summary> /// <param name="card"></param> public void GPO(ICCard card) { StringBuilder body = new StringBuilder(); List <string> gpoList = new List <string>(); if (card.GPOL == null || card.GPOL.Count == 0) { throw new CardReadException("未读取到处理选项列表"); } gpoList = card.GPOL.ToList(); gpoList.ForEach(pdo => body.Append(PublicStaticData.PDOL[pdo])); body.Insert(0, (body.Length / 2).ToString("x2")); body.Insert(0, "83"); body.Insert(0, (body.Length / 2).ToString("x2")); APDUEntity GPO = new APDUEntity("80", "A8", "00", "00", body.ToString()); string result = CardReader.SendAPDU(GPO.ToString()); List <TLVEntity> tlvList = TLVHelper.ToTLVEntityList(result); TLVEntity entity = null; if (tlvList != null && tlvList.Count > 0) { entity = tlvList[0]; } card.AIP = CodeConvert.ToHexString(entity.Value.Take(2).ToArray());//前两位是AIP List <string> afl = new List <string>(); for (int i = 2; i < entity.Value.Length; i = i + 4) { afl.Add(CodeConvert.ToHexString(entity.Value.Take(i + 4).Skip(i).ToArray())); } card.AFL = afl; }
/// <summary> /// 获取应用密文 /// </summary> /// <param name="card">卡片信息</param> /// <returns></returns> public void GENERATEARQC(ICCard card, string transactionType = TransactionType.Pay) { PublicStaticData.TransactionType = TransactionType.Pay; Random random = new Random(); PublicStaticData.RadomData = CodeConvert.ToHexString(new byte[] { (byte)random.Next(256), (byte)random.Next(256), (byte)random.Next(256), (byte)random.Next(256) }); card.RadomData = PublicStaticData.RadomData; StringBuilder cdol1Builder = new StringBuilder(); card.CDOL1.ToList().ForEach(cdo => cdol1Builder.Append(PublicStaticData.CDOL1[cdo])); cdol1Builder.Insert(0, (cdol1Builder.Length / 2).ToString("x2")); APDUEntity entity = new APDUEntity("80", "AE", "80", "00", cdol1Builder.ToString()); string arqc = CardReader.SendAPDU(entity.ToString()); List <TLVEntity> entityList = TLVHelper.ToTLVEntityList(arqc); if (entityList.Count == 0) { throw new CardReadException("获取应用密文(ARQC)失败"); } TLVEntity arqcEntity = entityList[0]; card.CID = arqcEntity.Value[0].ToString("x2"); //密文信息 L:1 card.ATC = CodeConvert.ToHexString(new byte[] { arqcEntity.Value[1], arqcEntity.Value[2] }); //ATC 应用交易计数器 L:2 card.AC = CodeConvert.ToHexString(arqcEntity.Value.Take(11).Skip(3).ToArray()); //AC应用密文 L:8 card.IssBankAppData = CodeConvert.ToHexString(arqcEntity.Value.Skip(11).ToArray()); //发卡行应用数据 }
/// <summary> /// TLV报文打包 /// </summary> /// <param name="buffer">字节数据</param> /// <returns></returns> public static List <TLVEntity> Construct(byte[] buffer) { List <TLVEntity> resultList = new List <TLVEntity>(); int currentIndex = 0; while (currentIndex < buffer.Length) { TLVEntity entity = new TLVEntity(); //1. 根据Tag判断数据是否是嵌套的TLV bool hasSubEntity = HasSubEntity(buffer, currentIndex); #region Tag解析 entity.Tag = GetTag(buffer, currentIndex); currentIndex += entity.Tag.Length; #endregion #region Length解析 entity.Length = GetLength(buffer, currentIndex); currentIndex += entity.Length.Length; #endregion #region Value解析 int valueLength = GetValueLengthByLengthByteValue(entity.Length); entity.Value = buffer.Take(currentIndex + valueLength).Skip(currentIndex).ToArray(); if (hasSubEntity) //判断是否是嵌套结构 { entity.SubTLVEntity = Construct(entity.Value); //嵌套结构递归解析 } currentIndex += entity.Value.Length; #endregion resultList.Add(entity); } return(resultList); }
/// <summary> /// 根据tag获取tlv的值 /// </summary> /// <param name="entities"></param> /// <param name="tag"></param> /// <returns></returns> public static TLVEntity GetValueByTag(List <TLVEntity> entities, string tag) { TLVEntity resultEntity = null; var query = entities.SingleOrDefault(e => CodeConvert.ToHexString(e.Tag).ToUpper() == tag); if (query == null) { foreach (var tlv in entities) { if (tlv.SubTLVEntity != null) { TLVEntity result = GetValueByTag(tlv.SubTLVEntity, tag); if (result != null && result.Length.Length > 0) { return(result); } } } } else { resultEntity = query; } return(resultEntity); }
/// <summary> /// 解析TLV /// </summary> /// <param name="list"> /// <returns></returns> public static byte[] Parse(List <TLVEntity> list) { byte[] buffer = new byte[4096]; int currentIndex = 0; int currentTLVIndex = 0; int valueSize = 0; while (currentTLVIndex < list.Count()) { valueSize = 0; TLVEntity entity = list[currentTLVIndex]; Array.Copy(entity.Tag, 0, buffer, currentIndex, entity.TagSize); //解析Tag currentIndex += entity.TagSize; for (int index = 0; index < entity.LengthSize; index++) { valueSize += entity.Length[index] << (index * 8); //计算Length域的长度 } if (valueSize > 127) { buffer[currentIndex] = Convert.ToByte(0x80 | entity.LengthSize); currentIndex += 1; } Array.Copy(entity.Length, 0, buffer, currentIndex, entity.LengthSize); //解析Length currentIndex += entity.LengthSize; //判断是否包含子嵌套TLV if (entity.SubTLVEntity == null) { Array.Copy(entity.Value, 0, buffer, currentIndex, valueSize); //解析Value currentIndex += valueSize; } else { byte[] tempBuffer = Parse(entity.SubTLVEntity); Array.Copy(tempBuffer, 0, buffer, currentIndex, tempBuffer.Length); //解析子嵌套TLV currentIndex += tempBuffer.Length; } currentTLVIndex++; } byte[] resultBuffer = new byte[currentIndex]; Array.Copy(buffer, 0, resultBuffer, 0, currentIndex); return(resultBuffer); }
/// <summary> /// 发卡行外部认证 /// </summary> /// <param name="data"></param> /// <returns></returns> public bool IssueBankAuthenticate(string data) { //支付成功获取发卡行返回的55域数据 byte[] part55Data = CodeConvert.HexStringToByteArray(data); List <TLVEntity> tlvList = TLVPackage.Construct(part55Data); TLVEntity entity = TLVHelper.GetValueByTag(tlvList, "91");//获取发卡行认证数据 if (entity != null) { APDUEntity apdu = new APDUEntity("00", "82", "00", "00", CodeConvert.ToHexString(entity.Length) + CodeConvert.ToHexString(entity.Value)); string result = CardReader.SendAPDU(apdu.ToString()); return(true);// result.Equals(StatusCode.Success) == result.Equals(StatusCode.Authenticated); } else { return(true); } }