You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Delphi环境下智能卡APDU通信过程开发的技术咨询

Delphi智能卡APDU通信实现指南

所需依赖

  • 直接调用Windows系统自带的WinSCard.dll,Delphi自带WinSCard单元已封装好所有接口,无需额外引入第三方库或DLL

实现步骤

  1. 初始化智能卡资源管理器上下文,枚举当前可用的读卡器列表
  2. 连接指定读卡器上的智能卡,协商使用T0/T1通信协议
  3. 组装SELECT APDU指令,参数完全匹配需求
  4. 调用传输接口发送APDU,接收卡返回的响应数据与状态码
  5. 校验状态码是否为0x9000,确认选卡成功后后续所有APDU都复用当前连接发送
  6. 通信完成后释放连接与上下文资源

核心代码示例

uses
  WinSCard, Windows, SysUtils;

function SelectTargetApplet(const ReaderName: string; out hCard: THandle; out ActiveProto: DWORD): Boolean;
var
  hContext: SCARDCONTEXT;
  dwRet: DWORD;
  bSendBuf: array[0..22] of Byte;
  bRecvBuf: array[0..255] of Byte;
  dwRecvLen: DWORD;
  SW: WORD;
begin
  Result := False;
  hCard := 0;
  ActiveProto := 0;

  // 1. 初始化SCard上下文
  dwRet := SCardEstablishContext(SCARD_SCOPE_USER, nil, nil, @hContext);
  if dwRet <> SCARD_S_SUCCESS then Exit;

  try
    // 2. 连接智能卡
    dwRet := SCardConnect(hContext, PChar(ReaderName), SCARD_SHARE_SHARED,
      SCARD_PROTOCOL_T0 or SCARD_PROTOCOL_T1, hCard, @ActiveProto);
    if dwRet <> SCARD_S_SUCCESS then Exit;

    // 3. 组装选卡APDU指令,完全匹配需求参数
    bSendBuf[0] := $00;  // Class
    bSendBuf[1] := $A4;  // Instruction: SELECT
    bSendBuf[2] := $04;  // P1: 按AID选择
    bSendBuf[3] := $00;  // P2: 匹配第一个符合条件的Applet
    bSendBuf[4] := $10;  // Lc: 后续Data段长度
    // AID数据部分
    bSendBuf[5] := $A0;
    bSendBuf[6] := $00;
    bSendBuf[7] := $00;
    bSendBuf[8] := $07;
    bSendBuf[9] := $48;
    bSendBuf[10] := $46;
    bSendBuf[11] := $4A;
    bSendBuf[12] := $49;
    bSendBuf[13] := $2D;
    bSendBuf[14] := $54;
    bSendBuf[15] := $61;
    bSendBuf[16] := $78;
    bSendBuf[17] := $43;
    bSendBuf[18] := $6F;
    bSendBuf[19] := $72;
    bSendBuf[20] := $65;
    bSendBuf[21] := $00;  // Le: 期望返回的最大数据长度

    // 4. 发送APDU指令
    dwRecvLen := Length(bRecvBuf);
    dwRet := SCardTransmit(hCard, SCARD_PCI_T0, @bSendBuf, Length(bSendBuf),
      nil, @bRecvBuf, @dwRecvLen);
    if dwRet <> SCARD_S_SUCCESS then Exit;

    // 5. 校验返回状态码
    if dwRecvLen >= 2 then
    begin
      SW := (bRecvBuf[dwRecvLen-2] shl 8) or bRecvBuf[dwRecvLen-1];
      Result := (SW = $9000); // 0x9000表示选卡成功
    end;

    // 注意:hCard需保留用于后续业务APDU发送,不要在此处断开连接
  finally
    // 上下文可根据业务需要保留或释放,此处示例直接释放
    SCardReleaseContext(hContext);
  end;
end;

常见返回状态码说明

  • 0x9000:选卡成功,后续可直接发送业务APDU
  • 0x6A82:未找到对应AID的Applet,检查AID是否填写正确
  • 0x6700:APDU长度错误,检查指令组装逻辑是否异常
  • 0x6985:使用条件不满足,通常为卡处于锁定状态

内容的提问来源于stack exchange,提问作者q1werty

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.04 16:30:00