⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ic_card.c

📁 金融IC卡读写器函数
💻 C
📖 第 1 页 / 共 3 页
字号:
/********************************************************************* *   Designed by xiaohuiyang 2005.06.08    E-mail: yxh2001@21cn.com
  *  *********************************************************************/#include <string.h>#include <stdio.h>#include <stdlib.h>#include "ic_card.h"#include "tl.h"                 //Include Transport Layerchar m_chErrMsg[20];int ICOpenCom(){	if(TL_Open(2, 9600) != NO_ERR)	{		return -1;	}	return 0;}int ICCloseCom(){	TL_Close();	return 0;}int ICPowerOn(){	unsigned char recvbuf[256];	unsigned char cmd[] = "\x12";	unsigned char recvlen = 0;	memset(recvbuf, 0x00, sizeof(recvbuf));	SendCmd(cmd, 1, recvbuf, &recvlen);	if(recvbuf[1] == 0x3B)		return 0;	return -1;}int ICPowerDown(){	unsigned char recvbuf[256];	unsigned char cmd[] = "\x11";	unsigned char recvlen = 0;	memset(recvbuf, 0x00, sizeof(recvbuf));	SendCmd(cmd, 1, recvbuf, &recvlen);	return 0;}int ReadAccount(stMACDATA *pst/*char *account*/){	return PbocSelectPboc(pst/*account*/);}/*=============================================================================//函数名称: SendICCommand//输入参数: char *ICSendbuf  : 发送字符串//输出参数: char *ICRecvbuf :  接收字符串//       char *ICSW      : 判断符       //返    回: 0--成功;   <0: 失败//功    能: 发送ic卡命令//开发人员: yangxh//修改记录: 1. 第一次编写.===============================================================================*/short SendICCommand(char *ICSendbuf, char *ICRecvbuf, char *ICSW){	int  ret,datalen;	char chLen[3];	ret=SendICC(ICSendbuf, 0, ICRecvbuf, ICSW);	memset(chLen, 0x00, 3);	if(strncmp(ICSW,"61",2)==0)	{		memcpy(chLen,&ICSW[2],2);		sscanf(chLen,"%02X",&datalen);		datalen = datalen&0XFF;		memset(ICSW, '\0', 5);		ret =  PbocGetResponse(ICRecvbuf, datalen, ICSW);	}	return ret;}/*=============================================================================//函数名称: PbocGetResponse//输入参数: char *ICSendbuf      : 发送字符串//       unsigned int datalen : 发送字符串长度//输出参数: char *SW      : 判断符       //返    回: 0--成功;   <0: 失败//功    能: 发送ic卡响应命令//开发人员: yangxh//修改记录: 1. 第一次编写.===============================================================================*/short PbocGetResponse(char *ICRecvbuf, unsigned int datalen, char *SW){	int    ret;	char   chSend1[128], chLen[3];	stAPDU apdu;	if( datalen<0 || datalen>256 )		return 102;               //102代表数据长度错	memset( &apdu, '\0', sizeof(stAPDU) );	strcpy(apdu.cla,"00");	strcpy(apdu.ins,"C0");	strcpy(apdu.p1,"00");	strcpy(apdu.p2,"00");	sprintf(apdu.p3, "%02X", datalen);	memset( chSend1, '\0', 128);	sprintf(chSend1,"%s%s%s%s%s%s",apdu.cla,apdu.ins,apdu.p1,apdu.p2,apdu.p3,apdu.data);	ret = SendICCommand(chSend1,ICRecvbuf,SW);	if( ret )		return ret;	ret =CheckSW(SW);	if( ret )		return ret;	memset(chLen,'\0',3);	if(strncmp(SW,"6C",2)==0 || strncmp(SW,"61",2)==0)	{		memcpy(chLen,&SW[2],2);		sscanf(chLen,"%02X",&datalen);		datalen = datalen&0XFF;		return PbocGetResponse(ICRecvbuf, datalen,SW);	}	return 0;}/*=============================================================================//函数名称: CheckSW//输入参数: char *pSW      : 判断字符串//输出参数:无//返    回: 0--成功;   <0: 失败//功    能: 检查ic卡响应//开发人员: yangxh//修改记录: 1. 第一次编写.===============================================================================*/short CheckSW(char *pSW){	unsigned int nSW;	memset(m_chErrMsg,'\0',20);	if((strncmp(pSW, "9000", 4)==0 || strncmp(pSW, "61", 2)==0 || strncmp(pSW, "6C", 2)==0 ))	{		return 0;	}  	sscanf(pSW, "%04X", &nSW);	GetICSWErrMsg(nSW);	return nSW;}/*=============================================================================//函数名称: GetICSWErrMsg//输入参数: unsigned int SW : 错误标志//输出参数:无//返    回: 0--成功;   <0: 失败//功    能: 获取错误信息//开发人员: yangxh//修改记录: 1. 第一次编写.===============================================================================*/void GetICSWErrMsg(unsigned int SW){	memset(m_chErrMsg,'\0',20);	if( SW==0X6700 )		strcpy(m_chErrMsg,"Lc错误!");	else if( SW==0X6901 )		strcpy(m_chErrMsg,"命令不接受!");	else if( SW==0X6982 )		strcpy(m_chErrMsg,"不满足安全状态!");	else if( SW==0X6985 )		strcpy(m_chErrMsg,"使用条件不满足!");	else if( SW==0X6A81 )		strcpy(m_chErrMsg,"不支持此功能!");	else if( SW==0X6A82 )		strcpy(m_chErrMsg,"文件未找到!");	else if( SW==0X6A86 )		strcpy(m_chErrMsg,"参数P1, P2错误!");	else if( SW==0X6D00 )		strcpy(m_chErrMsg,"INS错误!");	else if( SW==0X6E00 )		strcpy(m_chErrMsg,"CLA错误!");	else if( SW==0X9302 )		strcpy(m_chErrMsg,"MAC无效!");	else if( SW==0X9303 )		strcpy(m_chErrMsg,"应用已经永久锁定!");	else if( SW==0X9401 )		strcpy(m_chErrMsg,"金额不足!");	else if( SW==0X9403 )		strcpy(m_chErrMsg,"密钥索引不支持!");	else if( SW==0X9406 )		strcpy(m_chErrMsg,"所需的MAC不可用!");	else		strcpy(m_chErrMsg,"系统出错");}/****************************************************************//* Description : Sends Command to the reader and displays       *//*               answer or error code .                         *//* Input :                                                      *//*               unsigned char *pszCmd -> Command               *//*               unsigned char  ucLgcmd -> Command Length       *//* Output :      None                                           *//* Returns :     Error Code                                     *//* Global Variables : None                                      *//****************************************************************/short int SendCmd( unsigned char *pszCmd, unsigned char ucLgcmd, unsigned char *szRep, unsigned char *ucLgRep){//   unsigned char szRep[ 256 ], ucLgRep ;   short int siRet;//#ifdef MMI   unsigned char ucIndice ;   printf( "\n->" );   /*Display Command*/   for ( ucIndice = 0 ; ucIndice < ucLgcmd ; ucIndice++ )      printf( " %02Xh", pszCmd[ ucIndice ] ) ;//#endif   /*Send the command and retrieves the answer*/   siRet = TL_SendReceive( ucLgcmd, pszCmd, ucLgRep, szRep );   /*If no error occured then display answer*/   if ( siRet == NO_ERR )	{//#ifdef MMI      printf( "\n<-" );      for ( ucIndice = 0 ; ucIndice < *ucLgRep ; ucIndice++ )         printf( " %02Xh", szRep[ ucIndice ] ) ;      printf( "\n" );//#endif			}	else	{      /*dispay error code value*///#ifdef MMI      printf( "\nError occured : %X\n", siRet );//#endif      /*Close port*/      TL_Close() ;      /*Leave application*/      exit( -1 ) ;	}   return ( siRet ) ;}/*=============================================================================//函数名称: SendICC//输入参数: char *ICSendbuf : 发送字符串//       int sendlen    : 发送长度//输出参数:char *ICRecvbuf : 接收字符串//      char *ICSW      :  接收标志//返    回: 0--成功;   <0: 失败//功    能: 发送IC卡指令//开发人员: yangxh//修改记录: 1. 第一次编写.===============================================================================*/int SendICC(char *ICSendbuf, int sendlen, char *ICRecvbuf, char *ICSW){	unsigned char ucLgRep;	SendCmd((unsigned char *)ICSendbuf, sendlen, (unsigned char *)ICRecvbuf, &ucLgRep) ;	return 0;}/*=============================================================================//函数名称: PbocICSelect//输入参数: char *file_id : 文件名称//       int filelen    :文件长度//输出参数:unsigned char *recvbuf : 接收字符串//返    回: 0--成功;   <0: 失败//功    能: 文件选择//开发人员: yangxh//修改记录: 1. 第一次编写.===============================================================================*/int PbocICSelect(char *file_id, int filelen, unsigned char *recvbuf){	unsigned char  recvlen = 0;	unsigned char SendCommand[128];	int sendlen;	short  ret;//	int i;	memset((char *)SendCommand, 0x00, sizeof(SendCommand));	sprintf((char *)SendCommand, "%c%c%c%c%c%c", 0x14, 0x00, 0xA4, 0x04, 0x00, filelen);	memcpy(SendCommand+6, file_id, filelen);	sendlen = filelen + 6;	ret = SendCmd(SendCommand, sendlen, recvbuf, &recvlen);/*	printf("Pboc IC select:[");	for(i = 0; i < recvlen; i++)	{		printf("%02X ", recvbuf[i]);	} 	printf("]\n");*/	if(recvbuf[1] == 0x61)	{		sprintf((char *)SendCommand, "%c%c%c%c%c%c", 0x13, 0x00, 0xC0, 0x00, 0x00, recvbuf[2]);	   SendCmd(SendCommand, 6, recvbuf, &recvlen);	}	return 0;}/*=============================================================================//函数名称: PbocSelectPboc//输入参数: 无//输出参数:无//返    回: 0--成功;   <0: 失败//功    能: 金融应用选择//开发人员: yangxh//修改记录: 1. 第一次编写.===============================================================================*/int PbocSelectPboc(stMACDATA *pst/*char *Account*/){	short  ret;	short  sfi;	char   *ptr, tmpfilename[256];	char   chPSE[50];	unsigned char   recvbuf[256];//	unsigned char  datalen;//	char cardno[21];	memset(tmpfilename, 0x00, sizeof(tmpfilename));	memset(recvbuf,'\0',256);	memset(chPSE, '\0', 50);	memcpy(tmpfilename, "1PAY.SYS.DDF01", 14);	strcpy(chPSE, tmpfilename);	PbocICSelect("1PAY.SYS.DDF01", strlen(tmpfilename), recvbuf);//	if( ret )//		return ret;	printf("strstr\n");	ptr = strstr((char *)(recvbuf+1), "\x88\x01");	if(ptr == NULL)		return -1;	ptr += 2;	sfi = ptr[0] & 0XFF;	memset(recvbuf, 0x00, sizeof(recvbuf));/*	for(i = 1; ; i++)	{		printf("Send Read Record\n");		ret = PbocReadRecord(0x14, ABS_RECORD, sfi, i, 0, (char *)recvbuf);		if( ret )			return ret;		printf("start strstr find data ...\n");		ptr = strstr((char *)(recvbuf+1),"\x4F");		if(ptr == NULL)			return -1;		if(strncmp(ptr+2, chPSE, 14) != 0 )			break;	}	printf("come here\n");	datalen = ptr[1] & 0XFF;	memset(tmpfilename, 0x00, sizeof(tmpfilename));	memcpy(tmpfilename, ptr+2, datalen);*/	ret = PbocICSelect("\xD1\x56\x00\x00\x01\x45\x44\x2F\x45\x50\x00\x00\x00\x00\x00\x00", 16, recvbuf);	if( ret )		return ret;	//Unpackage Receive Data//	memset(cardno, 0x00, sizeof(cardno));	GetInfo((char *)recvbuf, pst);	//	ret = PbocReadBinary(0x14, 21, 0, 30, (char *)recvbuf);	return 0;}/*=============================================================================//函数名称: PbocReadRecord//输入参数: char head : 发送头标志//       short readmode: 读取模式//       short sfi://       short recno:    记录数//       short reclen:   接收长度//输出参数:char *recvbuf:    接收数据//返    回: 0--成功;   <0: 失败//功    能: 读记录//开发人员: yangxh//修改记录: 1. 第一次编写.===============================================================================*/short PbocReadRecord(char head, short readmode, short sfi, short recno, short reclen, char *recvbuf){	unsigned char  recvlen = 0;	unsigned char  datalen;	int sendlen;	unsigned char SendCommand[128];	short  ret, p2;	p2 = ( sfi << 3 ) | readmode;	memset((char *)SendCommand, 0x00, sizeof(SendCommand));	sprintf((char *)SendCommand, "%c%c%c%c%c%c", head, 0x00, 0xB2, recno, p2, reclen);	sendlen = 6;	printf("Send Read Record\n");	ret = SendCmd(SendCommand, sendlen, (unsigned char *)recvbuf, &recvlen);	if(recvbuf[1] == 0x6C || recvbuf[1] == 0x61)	{		datalen = recvbuf[2] & 0XFF;		return PbocReadRecord(0x13, readmode, sfi, recno, datalen, recvbuf);	}	return 0;}/*=============================================================================//函数名称: PbocReadBinary//输入参数: char head : 发送头标志//       short sfi://       short offset:   偏移量//       short readlen:  接收长度//输出参数:char *recvbuf:    接收数据//返    回: 0--成功;   <0: 失败//功    能: 读二进制文件//开发人员: yangxh//修改记录: 1. 第一次编写.===============================================================================*/short PbocReadBinary(char head, short sfi, short offset, short readlen, char *recvbuf){	short  datalen, ret, p1;	int    sendlen;	unsigned char  recvlen = 0;	unsigned char SendCommand[128];	if( sfi > 30 || (sfi<21 && sfi!=0 ) )		return FALSE;	if( sfi!=0 )		p1 = 0x80 | sfi;	else		p1 = sfi;	memset((char *)SendCommand, 0x00, sizeof(SendCommand));	sprintf((char *)SendCommand, "%c%c%c%c%c%c", head, 0x00, 0xB0, p1, offset, readlen);	sendlen = 6;	printf("Send ReadBinary\n");	ret = SendCmd(SendCommand, sendlen, (unsigned char *)recvbuf, &recvlen);	if(recvbuf[1] == 0x6C || recvbuf[1] == 0x61)	{		datalen = recvbuf[2] & 0XFF;		return PbocReadBinary(0x13, sfi, offset, datalen, recvbuf);	}	return 0;}/*=============================================================================//函数名称: GetInfo//输入参数: char *recvbuf: 接收数据//输出参数:char *cardno : 卡号//返    回: 0--成功;   <0: 失败//功    能: 获取返回信息//开发人员: yangxh//修改记录: 1. 第一次编写.===============================================================================*/int GetInfo(char *recvbuf, stMACDATA *pst/*char *cardno*/){	int  i;	char startday[10], endday[10];	char temp[50];	char *ptr;	memset(temp, 0x00, sizeof(temp));	memset(startday, 0x00, sizeof(startday));	memset(endday, 0x00, sizeof(endday));	if(recvbuf[0] != 0x00)		return -1;	if(recvbuf[1] != 0x6f)              // FCI 模板		return -2;	printf("FCI:[%02X]\n", recvbuf[2]);	if(recvbuf[3] != 0x84)              // DF 名		return -3;	memcpy(temp, recvbuf+5, recvbuf[4]);	printf("DF name:\n");	for(i = 0; i < recvbuf[4]; i++)	{		printf("%02X ", temp[i]);	}	printf("\n");	ptr = recvbuf + recvbuf[4] + 5;	if(ptr[0] != 0xa5)                  // FCI 专用数据		return -4;//	printf("FCI Special Data:[%02X]\n", ptr[1]);//	ptr = strstr(ptr, "\x9f\x08");      // 应用版本号//	printf("Version NO:[%02x%02x]\n", ptr[2], ptr[3]);//	ptr += 4;	ptr = strstr(ptr, "\x9f\x0c");      // 应用版本号	if(ptr != NULL)// 发送方自定义数据 FCI	{		printf("Sender self define fci:[%02x]\n", ptr[2]);	}	else		return -5;	ptr += 3;	printf("Author card flag:");        // 发卡方标识符	memcpy(pst->bank_id, ptr, 8);	for(i = 0; i < 8; i++)	{		printf("%02x ", ptr[i]);	}	printf("\n");	ptr += 8;	printf("use type:[%02x]\n", ptr[0]); // 应用类型标识	printf("version:[%02X]\n", ptr[1]);  // 发卡方应用版本号	memset(temp, 0x00, sizeof(temp));	memcpy(temp, ptr+2, 10);             // 应用序列号	memcpy(pst->card_no, ptr+2, 10);/*	for(i = 0; i < 10; i++)	{		printf("%02X", temp[i]);		sprintf(cardno+i*2, "%02X", temp[i]);	}	for(i = 0; i < 20; i++)	{		if(cardno[i] == 'F')		{			cardno[i] = '\0';			break;		}	}	printf("card no:[%s]\n", cardno);*/	memset(temp, 0x00, sizeof(temp));	memcpy(temp, ptr+12, 4);              // 应用启用日期	for(i = 0; i < 4; i++)	{

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -