/******************************************************************************
* 文件名称: CardReader.cs
* 文件说明: 读卡的封装,包括社保卡,身份证,电子凭证等等
* 当前版本: V1.0
* 创建日期: 2022-06-20
*
* * 2020-06-20: 增加 CardReader 类
* ***** 2020-06-20: 增加 CardReader 方法,获取URL地址,USER信息,地方版SSCard.dll使用
* ***** 2020-06-20: 增加 CardReader 方法重载,国家版电子凭证使用
* ***** 2020-06-20: 增加 Init 方法,SSCard环境初始化
* ***** 2020-06-20: 增加 ReadCardBas 方法,读社保卡
* ***** 2020-06-20: 增加 VerifyPIN 方法,验证密码
* ***** 2020-06-20: 增加 ChangePIN 方法,修改密码
* ***** 2020-06-20: 增加 ReadSFZ 方法,读身份证
* ***** 2020-06-20: 增加 GetQRBase 方法,读二维码
* ***** 2020-06-20: 增加 NationEcTrans 方法,读电子凭证(国家版)
******************************************************************************/
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using PTMedicalInsurance.Variables;
using System;
using System.Runtime.InteropServices;
using System.Text;
namespace PTMedicalInsurance.CardReaders
{
class CardReader
{
[DllImport("SSCard.dll", EntryPoint = "Init", CharSet = CharSet.Ansi, ExactSpelling = false, CallingConvention = CallingConvention.StdCall)]
static extern int Init(IntPtr pURL, IntPtr pUser);
//[DllImport(DllPath, EntryPoint = "Init", CharSet = CharSet.Ansi, ExactSpelling = false, CallingConvention = CallingConvention.StdCall)]
//static extern int Init(StringBuilder pInitInfo, StringBuilder pErrMsg);
[DllImport("SSCard.dll", EntryPoint = "ReadCardBas", CharSet = CharSet.Ansi, ExactSpelling = false, CallingConvention = CallingConvention.StdCall)]
private static extern int ReadCardBas(IntPtr pOutBuff, int nOutBuffLen, IntPtr pSignBuff, int nSignBuffLen);
const string DllPath = @"SSCard.dll";
private static bool initilaized = false;
private static string URL;
private static string User;
public CardReader()
{
}
public CardReader(string URL, string User)
{
}
public static int Init(string _URL, string _User)
{
URL = _URL;
User = _User;
if (initilaized)
{
Global.writeLog("Init", "检测到已初始化", "");
return 0;
}
string errMsg = "";
int result = -1;
//Global.writeLog_debug(string.Format("读卡初始化:{0},{1}", URL, User));
// 将托管字符串转换为 ANSI 编码的字节数组
byte[] urlBytes = Encoding.ASCII.GetBytes(URL + '\0'); // 添加终止符
byte[] userBytes = Encoding.ASCII.GetBytes(User + '\0'); // 添加终止符
Global.writeLog("Init", URL, User);
// 分配全局非托管内存并复制字符串数据
IntPtr pUrl = Marshal.AllocHGlobal(urlBytes.Length);
IntPtr pUser = Marshal.AllocHGlobal(userBytes.Length);
try
{
// 将托管字节数组复制到非托管内存
Marshal.Copy(urlBytes, 0, pUrl, urlBytes.Length);
Marshal.Copy(userBytes, 0, pUser, userBytes.Length);
result = Init(pUrl, pUser);
if (result == 0)
{
initilaized = true;
}
return result;
}
catch (Exception ex)
{
errMsg = ex.Message;
return result;
}
finally
{
// 显式释放全局非托管内存
if (pUrl != IntPtr.Zero) Marshal.FreeHGlobal(pUrl);
if (pUser != IntPtr.Zero) Marshal.FreeHGlobal(pUser);
Global.writeLog("Init", result.ToString(), errMsg);
}
}
//public int Init()
//{
// string errMsg = "";
// int result = -1;
// try
// {
// StringBuilder sbInitInfo = new StringBuilder();
// StringBuilder sbUSER = new StringBuilder(4096);
// result = Init(sbInitInfo, sbUSER);
// return result;
// }
// catch (Exception ex)
// {
// errMsg = ex.Message;
// return result;
// }
// finally
// {
// Global.writeLog("初始化", "", result.ToString() + ":" + errMsg);
// }
//}
///
/// 读社保卡
///
///
///
public int ReadCardBas(out string basInfo)
{
basInfo = "";
int rtn = -1;
// 分配非托管内存
//IntPtr pOutBuff = Marshal.AllocCoTaskMem(1024);
//IntPtr pSignBuff = Marshal.AllocCoTaskMem(8192);
// 分配全局非托管内存
IntPtr pOutBuff = Marshal.AllocHGlobal(1024);
IntPtr pSignBuff = Marshal.AllocHGlobal(8192);
try
{
rtn = ReadCardBas(pOutBuff, 1024, pSignBuff, 8192);
if (rtn == 0)
{
// 解析返回读卡信息
string outString = Marshal.PtrToStringAnsi(pOutBuff);
string signString = Marshal.PtrToStringAnsi(pSignBuff);
basInfo = outString;
Global.pat.card.BusinessCode = signString;
}
else
{
string outString = Marshal.PtrToStringAnsi(pOutBuff);
basInfo = outString;
}
return rtn;
}
catch (Exception ex)
{
basInfo = "ReadCardBas异常:" + ex.Message;
return rtn;
}
finally
{
Global.writeLog("读社保卡", "", basInfo);
//// 显式释放非托管内存
//Marshal.FreeCoTaskMem(pOutBuff);
//Marshal.FreeCoTaskMem(pSignBuff);
// 显式释放非托管内存
Marshal.FreeHGlobal(pOutBuff);
Marshal.FreeHGlobal(pSignBuff);
}
}
public int ReadCardBas(out string basInfo, out string signInfo)
{
basInfo = ""; signInfo = "";
int rtn = -1;
// 分配全局非托管内存
IntPtr pOutBuff = Marshal.AllocHGlobal(1024);
IntPtr pSignBuff = Marshal.AllocHGlobal(8192);
try
{
rtn = ReadCardBas(pOutBuff, 1024, pSignBuff, 8192);
if (rtn == 0)
{
// 解析返回读卡信息
string outString = Marshal.PtrToStringAnsi(pOutBuff);
string signString = Marshal.PtrToStringAnsi(pSignBuff);
basInfo = outString;
signInfo = signString;
Global.pat.card.BusinessCode = signString;
}
else
{
string outString = Marshal.PtrToStringAnsi(pOutBuff);
string signString = Marshal.PtrToStringAnsi(pSignBuff);
basInfo = outString;
signInfo = signString;
}
return rtn;
}
catch (Exception ex)
{
basInfo = "ReadCardBas异常:" + ex.Message;
return rtn;
}
finally
{
// 显式释放非托管内存
Marshal.FreeHGlobal(pOutBuff);
Marshal.FreeHGlobal(pSignBuff);
Global.writeLog("ReadCardBas", basInfo, signInfo);
}
}
///
/// 读身份证
///
///
///
public int ReadSFZ(out string OutBuff)
{
OutBuff = "";
try
{
SFZReader reader = new SFZReader();
return reader.ReadSFZ(out OutBuff);
}
catch (Exception ex)
{
OutBuff = "ReadSFZ 异常:" + ex.Message;
return -1;
}
}
///
/// 6101
///
///
///
public int ReadEC(out string OutBuff)
{
OutBuff = "";
try
{
ECTokenData eCToken = new ECTokenData();
eCToken.orgId = Global.inf.hospitalNO;
eCToken.operatorId = Global.user.ID;
eCToken.operatorName = Global.user.name;
eCToken.officeId = Global.user.officeID;
eCToken.officeName = Global.user.officeName;
eCToken.businessType = Global.businessType;
//eCToken.outBizNo = bizNo;
//eCToken.extData = "";
string tmp = JsonConvert.SerializeObject(eCToken);
var inData = new { InData = JObject.Parse(tmp) };
JObject joInData = new JObject(
new JProperty("InData", JObject.Parse(tmp))
);
ECReader reader = new ECReader();
return reader.Read(joInData,out OutBuff);
}
catch (Exception ex)
{
OutBuff = "ReadEC 异常:" + ex.Message;
return -1;
}
}
///
/// 6101
///
///
///
public int ECQuery(out string OutBuff)
{
OutBuff = "";
try
{
EcQueryData ecqueryData = new EcQueryData();
ecqueryData.orgId = Global.inf.hospitalNO;
ecqueryData.operatorId = Global.user.ID;
ecqueryData.operatorName = Global.user.name;
ecqueryData.officeId = Global.user.officeID;
ecqueryData.officeName = Global.user.officeName;
ecqueryData.businessType = Global.businessType;
//eCToken.outBizNo = bizNo;
//eCToken.extData = "";
NationECInput nationECInput = new NationECInput();
nationECInput.data = ecqueryData;
nationECInput.orgId = Global.inf.hospitalNO;
nationECInput.transType = "ec.query";
nationECInput.extra = "";
//测试环境电子凭证动态库地址:http://igb.hsa.gdgov.cn/tst_nation_eccode/tst_eccode/localcfc/api/hsecfc/localQrCodeQuery
//正式环境电子凭证动态库地址:http://hosp.gd.hsip.gov.cn/prd_nation_eccode/prd_eccode/localcfc/api/hsecfc/localQrCodeQuery
NationECCodeAPI nationECCodeAPI = new NationECCodeAPI(Global.inf.ecURL);
return nationECCodeAPI.NationEcTrans(nationECInput, out OutBuff);
}
catch (Exception ex)
{
OutBuff = "ECQuery 异常:" + ex.Message;
return -1;
}
}
}
}