VB6银联读卡之旅(二)__55域获取流程及相关注意

银行卡读卡涉及相关APDU命令发送。网上有很多相关博客进行了详细说明,这里就不在赘述。本文主要讲55域获取流程及本人联调时遇到的相关问题。在智能卡读取使用方面本人也属于初学者,其中如有疑问或表述不正确的地方还望谅解。

银联IC卡读卡流程详解--读卡器与卡交互指令 请参考:https://blog.csdn.net/kxd_ysheng/article/details/21178101/

金融tag对照表 请参考:https://blog.csdn.net/juvary/article/details/51487245

常用APDU指令错误码 请参考:https://blog.csdn.net/lonet/article/details/7541265

不多说直接上源码(55域获取部分):

55域获取:

'*************************************************************************************************
'*函数名:  get55Date
'*程序功能:银行卡读卡 55域获取(TYPE A CPU类型)
'*开发人员:Anna
'*异动人员:无
'*入口参数:hexMoney 传入金额(例:¥201.05表示为:000000020105)
'           merchantName 商户名称 (10字节)
'*返回参数:返回55域信息
'           -1101 卡机内无卡
'           -1102 暂不支持此类卡片,请使用借记卡
'           -1103 操作不成功
'           -1104 卡不在允许操作的位置上
'           -1105 复卡位失败
'           -1106 APDU执行失败
'           -1107 暂不支持该卡支付
'*************************************************************************************************
Public Function get55Date(ByVal hexMoney As String, ByVal merchantName As String)
    '冷复位
    Dim CpuType As Byte
    Dim CpuResetData(300) As Byte
    Dim CpuResetDataLen As Long
    
    '定义接受判断标识符
    Dim resDateFlag As String
    '定义接收执行apdu返回数据
    Dim resDate As String
    
    Dim rc As Integer
    If hcom <= 0 Then
        MsgBox ("请先打开串口")
        Exit Function
    End If
    'CPU 卡复位
    rc = CPU_ColdReset(hcom, 0, CpuType, CpuResetData(0), CpuResetDataLen)
    resBool = WriteErrLog("CRT_310--银行卡读卡 55域获取 (TYPE A CPU类型)--", "MC_ReadTrack", rc, "CPU 卡复位", "ComHandle=" & hcom & ",_CPUMode = 0x0,_CPUType = 0x0")
    If (rc >= 0) Then
        Select Case rc
            Case 0
                Dim Strtmp As String
                Strtmp = ""
                For i = 0 To CpuResetDataLen - 1
                    Strtmp = Strtmp + DoubleType(Hex(CpuResetData(i)))
                Next i
                '1. 应用选择
                CPUAPDUCOMMAND = "00A404000E315041592E5359532E4444463031"
                crt310resStr = CPUSendCmd(CPUAPDUCOMMAND, 0)
                resBool = WriteErrLog("CRT_310--银行卡读卡 55域获取 (TYPE A CPU类型)--", "CPUSendCmd", crt310resStr, "APDU 应用选择", "CPUAPDUCOMMAND = " & CPUAPDUCOMMAND)
                '2.通过循环读记录,选择 PSE 关联文件,判断是否是借记卡
                CPUAPDUCOMMAND = "00B2010C00"
                crt310resStr = CPUSendCmd(CPUAPDUCOMMAND, 0)
                resBool = WriteErrLog("CRT_310--银行卡读卡 55域获取 (TYPE A CPU类型)--", "CPUSendCmd", crt310resStr, "APDU 通过循环读记录,选择 PSE 关联文件", "CPUAPDUCOMMAND = " & CPUAPDUCOMMAND)
                    '截取返回值判断是否是储蓄卡
                    resDateFlag = Right$(crt310resStr, 4)
                    'MsgBox ("resDateFlag")
                    'MsgBox (resDateFlag)
                    If (resDateFlag = "9000") Then
                        Dim aidStr As String
                        aidStr = Mid$(crt310resStr, 13, 16)
                        
                        '3.选择文件
                        
                        CPUAPDUCOMMAND = "00A4040008" & aidStr
                        crt310resStr = CPUSendCmd(CPUAPDUCOMMAND, 0)
                        resBool = WriteErrLog("CRT_310--银行卡读卡 55域获取 (TYPE A CPU类型)--", "CPUSendCmd", crt310resStr, "APDU 选择文件", "CPUAPDUCOMMAND = " & CPUAPDUCOMMAND)
                        Dim resIncludeStrPosition As Integer
                        resIncludeStrPosition = InStr(crt310resStr, "9F38")
                        If (resIncludeStrPosition > 0) Then
                            Dim CPUAPDUCOMMAND55 As String
                            
                            
                            '获取截取长度
                            Dim interceptLenStr As String
                            interceptLenStr = Mid$(crt310resStr, resIncludeStrPosition + 4, 2)
                            '获取9F38数据
                            Dim date9F38res As String
                            date9F38res = Mid$(crt310resStr, resIncludeStrPosition + 6, HEXToDEC(interceptLenStr) * 2)
                            '定义获取信息长度
                            Dim date9F38resHex As String
                            Dim date9F38resLen As Integer
                            date9F38resHex = interceptLenStr
                            date9F38resLen = HEXToDEC(date9F38resHex)
                            '定义9F38获取信息返回值
                            Dim date9F7A As String
                            date9F7A = "00"
                            
                            '终端交易属性
                            Dim date9F66 As String
                            date9F66 = "60000000"
                            
                            '授权金额
                            Dim date9F02 As String
                            date9F02 = hexMoney
                            
                            '其他金额
                            Dim date9F03 As String
                            date9F03 = "000000000000"
                            
                            '终端国家代码
                            Dim date9F1A As String
                            date9F1A = "0156"
                            
                            '终端验证结果
                            Dim date95 As String
                            date95 = "0000000000"
                            
                            '交易货币代码
                            Dim date5F2A As String
                            date5F2A = "0156"
                            
                            '交易日期
                            Dim date9A As String
                            date9A = Format(Now, "yymmdd")
                            
                            '交易类型
                            Dim date9C As String
                            date9C = "00"
                            
                            '不可预知数
                            Dim date9F37 As String
                            Dim RandomizeInt As Long
                            RandomizeInt = Rnd * 100000000
                            date9F37 = Trim(RandomizeInt)
                            
                            'SM算法支持指示器
                            Dim dateDF69 As String
                            dateDF69 = "00"
                            
                            '交易时间
                            Dim date9F21 As String
                            date9F21 = Format(Now, "HHmmss")
                            
                            '商户名称
                            Dim date9F4E As String
                            date9F4E = merchantName
                            date9F4E = "0000000000000000000000000000000000000000"
                            
                            CPUAPDUCOMMAND = ""
                            CPUAPDUCOMMAND55 = ""
                            Dim itemLen As Integer
                            itemLen = 0
                            '判断是否包含9F7A
                            If (InStr(date9F38res, "9F7A")) Then
                                CPUAPDUCOMMAND = CPUAPDUCOMMAND + date9F7A
                                itemLen = itemLen + 1
                            End If
                            
                             '判断是否包含9F66
                            If (InStr(date9F38res, "9F66")) Then
                                CPUAPDUCOMMAND = CPUAPDUCOMMAND + date9F66
                                itemLen = itemLen + 4
                            End If
                            
                            '判断是否包含9F02(实际金额/分)
                            If (InStr(date9F38res, "9F02")) Then
                                CPUAPDUCOMMAND = CPUAPDUCOMMAND + date9F02
                               
                                itemLen = itemLen + 6
                            End If
                             
                             '判断是否包含9F03
                            If (InStr(date9F38res, "9F03")) Then
                                CPUAPDUCOMMAND = CPUAPDUCOMMAND + date9F03
                                itemLen = itemLen + 6
                            End If
                            
                             '判断是否包含9F1A
                            If (InStr(date9F38res, "9F1A")) Then
                                CPUAPDUCOMMAND = CPUAPDUCOMMAND + date9F1A
                                itemLen = itemLen + 2
                            End If
                            
                             '判断是否包含95
                            If (InStr(date9F38res, "95")) Then
                                CPUAPDUCOMMAND = CPUAPDUCOMMAND + date95
                                itemLen = itemLen + 5
                            End If
                            
                            '判断是否包含5F2A
                            If (InStr(date9F38res, "5F2A")) Then
                                CPUAPDUCOMMAND = CPUAPDUCOMMAND + date5F2A
                                itemLen = itemLen + 2
                            End If
                            
                            '判断是否包含9A
                            If (InStr(date9F38res, "9A")) Then
                                CPUAPDUCOMMAND = CPUAPDUCOMMAND + date9A
                                itemLen = itemLen + 3
                            End If
                            
                            '判断是否包含9C
                            If (InStr(date9F38res, "9C")) Then
                                CPUAPDUCOMMAND = CPUAPDUCOMMAND + date9C
                                itemLen = itemLen + 1
                            End If
                            
                             '判断是否包含9F37
                            If (InStr(date9F38res, "9F37")) Then
                                CPUAPDUCOMMAND = CPUAPDUCOMMAND + date9F37
                                itemLen = itemLen + 4
                            End If
                            
                            '判断是否包含DF69
                            If (InStr(crt310resStr, "DF69")) Then
                                CPUAPDUCOMMAND = CPUAPDUCOMMAND + "00"
                                itemLen = itemLen + 1
                            End If
                            
                            
                            CPUAPDUCOMMAND = "80A80000" + DecToHex(itemLen + 2) + "83" + DecToHex(itemLen) + CPUAPDUCOMMAND
                            '定义接受55域返回值信息
                            Dim date55ResInfo As String
                            
                            date55ResInfo = CPUSendCmd(CPUAPDUCOMMAND, 0)
                            resBool = WriteErrLog("CRT_310--银行卡读卡 55域获取 (TYPE A CPU类型)--", "CPUSendCmd", date55ResInfo, "APDU 根据9F38返回组合报文发送命令", "CPUAPDUCOMMAND = " & CPUAPDUCOMMAND)
                            
                            If (resDateFlag = "9000") Then
                                '获取82值
                                Dim date82 As String
                                date82 = Mid$(date55ResInfo, 5, 4)
                               
                                '根据 GPO 返回的 AFL
                                Dim gpoDate As String
                                gpoDate = Mid$(date55ResInfo, 9, Len(date55ResInfo) - 12)
                                Dim GPOCPUAPDUCOMMAND As String
                                resBool = WriteErrLog("CRT_310--银行卡读卡 55域获取 (TYPE A CPU类型)--", "截取获取gpoDate", gpoDate, "APDU 读应用数据")
                                
                                resBool = WriteErrLog("CRT_310--银行卡读卡 55域获取 (TYPE A CPU类型)--", "判断Len(gpoDate) Mod 8 = 0结果:", Len(gpoDate) Mod 8 = 0, "APDU 读应用数据")
                                '定义存储5F34数据
                                Dim date5F34 As String
                                date5F34 = ""
                                '定义存储8C数据
                                Dim date8C As String
                                
                                If (Len(gpoDate) Mod 8 = 0) Then
                                    Dim forNum As Integer
                                    forNum = Len(gpoDate) / 8
                                    For i = 1 To forNum
                                        '定义截取命令数据
                                        Dim GPOCPUAPDUCOMMANDDate As String
                                        GPOCPUAPDUCOMMANDDate = Mid$(gpoDate, (i - 1) * 8 + 1, 8)
                                        resBool = WriteErrLog("CRT_310--银行卡读卡 55域获取 (TYPE A CPU类型)--", "定义截取命令数据GPOCPUAPDUCOMMANDDate:", GPOCPUAPDUCOMMANDDate, "APDU 读应用数据")
                                        '计算SFI值
                                        Dim SFIDate As String
                                        SFIDate = Left$(GPOCPUAPDUCOMMANDDate, 2)
                                        resBool = WriteErrLog("CRT_310--银行卡读卡 55域获取 (TYPE A CPU类型)--", "计算SFIDate:", SFIDate, "APDU 读应用数据")
                                        Dim SFIDateRes As String
                                        SFIDateRes = HexForSFI(SFIDate)
                                        resBool = WriteErrLog("CRT_310--银行卡读卡 55域获取 (TYPE A CPU类型)--", "计算SFI值:", SFIDateRes, "APDU 读应用数据")
                                        '截取Record 值
                                        Dim RecordDate As String
                                        Dim RecordDateNum As Integer
                                        RecordDate = Mid$(GPOCPUAPDUCOMMANDDate, 5, 2)
                                        RecordDateNum = HEXToDEC(RecordDate)
                                        For k = 1 To RecordDateNum
                                            '拼接GPO命令
                                            GPOCPUAPDUCOMMAND = "00B2" & DecToHex(k) & SFIDateRes & "00"
                                            resDate = CPUSendCmd(GPOCPUAPDUCOMMAND, 0)
                                            resBool = WriteErrLog("CRT_310--银行卡读卡 55域获取 (TYPE A CPU类型)--", "CPUSendCmd", resDate, "APDU 读应用数据", "GPOCPUAPDUCOMMAND = " & GPOCPUAPDUCOMMAND)
                                            resBool = WriteErrLog("CRT_310--银行卡读卡 55域获取 (TYPE A CPU类型)--", "InStr(resDate, 8C):", InStr(resDate, "8C"), "APDU 截取8C数据")
                                            If (Len(resDate) > 0 And InStr(resDate, "8C") = 5 And InStr(resDate, "8D") > InStr(resDate, "8C")) Then
                                                '获取截取长度
                                                Dim interceptLen8C As String
                                                interceptLen8C = Mid$(resDate, 7, 2)
                                                '获取9F38数据
                                                date8C = Mid$(resDate, 9, HEXToDEC(interceptLen8C) * 2)
                                                resBool = WriteErrLog("CRT_310--银行卡读卡 55域获取 (TYPE A CPU类型)--", "截取8C数据", date8C, "APDU 截取8C数据")
                                            End If
                                            
                                            If (Len(resDate) > 0 And InStr(resDate, "5F34") > 0) Then
                                               '定义获取包含5F34位置
                                                Dim resInclude5F34Position As Integer
                                                resInclude5F34Position = InStr(resDate, "5F34")
                                                If (resInclude5F34Position > 0) Then
                                                    '获取截取长度
                                                    Dim interceptLen5F34 As String
                                                    interceptLen5F34 = Mid$(resDate, resInclude5F34Position + 4, 2)
                                                    '获取9F38数据
                                                    date5F34 = Mid$(resDate, resInclude5F34Position + 6, HEXToDEC(interceptLen5F34) * 2)
                                                    resBool = WriteErrLog("CRT_310--银行卡读卡 55域获取 (TYPE A CPU类型)--", "截取5F34数据", date5F34, "APDU 截取5F34数据")
                                                End If
                                            End If
                                             
                                        Next
                                    Next
                                Else
                                    '命令截取错误
                                End If
                                '组合报文获取55域9F10 9F26 9F27信息
                                'CPUAPDUCOMMAND = "80AE800034" + CPUAPDUCOMMAND55 + date82 + date9F36 组合报文发送如上报文时 部分卡不能获取返回值报错 6A80 数据域参数不正确 将所有包含数据全部发送时 都可以正常返回
                                
                                If (Len(date8C) > 0) Then
                                   
                                    '此次ATC寄存器值
                                    Dim date9F36 As String
                                    date9F36 = ""
                                    CPUAPDUCOMMAND = "80CA9F3600"
                                    resDate = CPUSendCmd(CPUAPDUCOMMAND, 0)
                                    resBool = WriteErrLog("CRT_310--银行卡读卡 55域获取 (TYPE A CPU类型)--", "CPUSendCmd", resDate, "APDU 获取9F36此次ATC寄存器值", "CPUAPDUCOMMAND = " & CPUAPDUCOMMAND)
                                    resDateFlag = Right$(resDate, 4)
                                    
                                    If (resDateFlag = "9000") Then
                                        
                                       date9F36 = Mid$(resDate, 7, 4)
                                    End If
                                    
                                    '判断是否包含9F02(实际金额/分)
                                    If (InStr(date8C, "9F02")) Then
                                        CPUAPDUCOMMAND55 = CPUAPDUCOMMAND55 + date9F02
                                    End If
                                     
                                     '判断是否包含9F03
                                    If (InStr(date8C, "9F03")) Then
                                        CPUAPDUCOMMAND55 = CPUAPDUCOMMAND55 + date9F03
                                    End If
                                    
                                     '判断是否包含9F1A
                                    If (InStr(date8C, "9F1A")) Then
                                        CPUAPDUCOMMAND55 = CPUAPDUCOMMAND55 + date9F1A
                                    End If
                                    
                                     '判断是否包含95
                                    If (InStr(date8C, "95")) Then
                                        CPUAPDUCOMMAND55 = CPUAPDUCOMMAND55 + date95
                                    End If
                                    
                                    '判断是否包含5F2A
                                    If (InStr(date8C, "5F2A")) Then
                                        CPUAPDUCOMMAND55 = CPUAPDUCOMMAND55 + date5F2A
                                    End If
                                    
                                    '判断是否包含9A
                                    If (InStr(date8C, "9A")) Then
                                        CPUAPDUCOMMAND55 = CPUAPDUCOMMAND55 + date9A
                                    End If
                                    
                                    '判断是否包含9C
                                    If (InStr(date8C, "9C")) Then
                                        CPUAPDUCOMMAND55 = CPUAPDUCOMMAND55 + date9C
                                    End If
                                    
                                     '判断是否包含9F37
                                    If (InStr(date8C, "9F37")) Then
                                        CPUAPDUCOMMAND55 = CPUAPDUCOMMAND55 + date9F37
                                    End If
                                    
                                    
                                End If
                                
                                CPUAPDUCOMMAND = "80AE800034" + CPUAPDUCOMMAND55 + date82 + date9F36
                                resDate = CPUSendCmd(CPUAPDUCOMMAND, 0)
                                resBool = WriteErrLog("CRT_310--银行卡读卡 55域获取 (TYPE A CPU类型)--", "CPUSendCmd", resDate, "APDU 发送组合报文获取55域信息", "CPUAPDUCOMMAND = " & CPUAPDUCOMMAND)
                                resDateFlag = Right$(resDate, 4)
                                If (resDateFlag = "9000") Then
                                    Dim date9F26 As String
                                    Dim date9F27 As String
                                    Dim date9F10 As String
                                    date9F27 = Mid$(resDate, 5, 2)
                                    resBool = WriteErrLog("CRT_310--银行卡读卡 55域获取 (TYPE A CPU类型)--", "截取", date9F27, "截取 date9F27")
                                    date9F26 = Mid$(resDate, 11, 16)
                                    resBool = WriteErrLog("CRT_310--银行卡读卡 55域获取 (TYPE A CPU类型)--", "截取", date9F26, "截取 date9F26")
                                    date9F10 = Mid$(resDate, 27, Len(resDate) - 30)
                                    resBool = WriteErrLog("CRT_310--银行卡读卡 55域获取 (TYPE A CPU类型)--", "截取", date9F10, "截取 date9F10")
                                    '封装组合55域数据
                                    Dim str9F33 As String
                                    Dim resDate55 As String
                                    resDate55 = ""
                                    str9F33 = "6040E8"
                                    resDate55 = resDate55 + "9F26" + DecToHex(Len(date9F26) / 2) + date9F26
                                    resDate55 = resDate55 + "9F27" + DecToHex(Len(date9F27) / 2) + date9F27
                                    resDate55 = resDate55 + "9F10" + DecToHex(Len(date9F10) / 2) + date9F10
                                    resDate55 = resDate55 + "9F37" + DecToHex(Len(date9F37) / 2) + date9F37
                                    resDate55 = resDate55 + "9F36" + DecToHex(Len(date9F36) / 2) + date9F36
                                    resDate55 = resDate55 + "95" + DecToHex(Len(date95) / 2) + date95
                                    resDate55 = resDate55 + "9A" + DecToHex(Len(date9A) / 2) + date9A
                                    resDate55 = resDate55 + "9C" + DecToHex(Len(date9C) / 2) + date9C
                                    resDate55 = resDate55 + "9F02" + DecToHex(Len(date9F02) / 2) + date9F02
                                    resDate55 = resDate55 + "5F2A" + DecToHex(Len(date5F2A) / 2) + date5F2A
                                    resDate55 = resDate55 + "82" + DecToHex(Len(date82) / 2) + date82
                                    resDate55 = resDate55 + "9F1A" + DecToHex(Len(date9F1A) / 2) + date9F1A
                                    resDate55 = resDate55 + "9F03" + DecToHex(Len(date9F03) / 2) + date9F03
                                    resDate55 = resDate55 + "9F33" + DecToHex(Len(date9F33) / 2) + date9F33
                                    resBool = WriteErrLog("CRT_310--银行卡读卡 55域获取 (TYPE A CPU类型)--", "55域信息", resDate55, " resDate55结果")
                                    
                                    
                                    get55Date = resDate55 & "|" & date5F34
                                Else
                                    '-1107 暂不支持该卡支付
                                    get55Date = -1107
                                    
                                End If
                                
                                
                            End If
                            
                        End If
                            
                       
                    End If
                    
                '下电
                crt310resStr = CPUDownPower()
            Case 78
                  '-1103 操作不成功
                 get55Date = -1103
            Case 69
                 '-1101 卡机内无卡
                 get55Date = -1101
            Case 87
                 get55Date = -1104
                 
        End Select
    Else
        '-1105 复卡位失败
        get55Date = -1105
    End If
End Function

55域获取使用公用函数:

Public Function HexForSFI(ByVal Dnum As String) As String
  '截取第一个值
  Dim numStr1 As String
  numStr1 = Left$(Dnum, 1)
  Dim numStr1Hex As String
  numStr1Hex = ASCII_to_bin(numStr1)
  resBool = WriteErrLog("CRT_310--银行卡读卡 55域获取 (TYPE A CPU类型)--", "截取第一个值", numStr1Hex, "APDU 读应用数据")
  
  '截取第二个值
  Dim numStr2 As String
  numStr2 = Right$(Dnum, 1)
  Dim numStr2Hex As String
  numStr2Hex = ASCII_to_bin(numStr2)
  resBool = WriteErrLog("CRT_310--银行卡读卡 55域获取 (TYPE A CPU类型)--", "截取第二个值", numStr2Hex, "APDU 读应用数据")
  
  '拼接SFI
  Dim SFIStr As String
  SFIStr = numStr1Hex & Left$(numStr2Hex, 1) & "100"
  resBool = WriteErrLog("CRT_310--银行卡读卡 55域获取 (TYPE A CPU类型)--", "拼接SFI", SFIStr, "APDU 读应用数据")

 
  HexForSFI = BIN_to_HEX(SFIStr)
  
End Function


Public Function BIN_to_HEX(ByVal Bin As String) As String
    Dim i As Long
    Dim H As String
    If Len(Bin) Mod 4 <> 0 Then
        Bin = String(4 - Len(Bin) Mod 4, "0") & Bin
    End If
    For i = 1 To Len(Bin) Step 4
        Select Case Mid(Bin, i, 4)
            Case "0000": H = H & "0"
            Case "0001": H = H & "1"
            Case "0010": H = H & "2"
            Case "0011": H = H & "3"
            Case "0100": H = H & "4"
            Case "0101": H = H & "5"
            Case "0110": H = H & "6"
            Case "0111": H = H & "7"
            Case "1000": H = H & "8"
            Case "1001": H = H & "9"
            Case "1010": H = H & "A"
            Case "1011": H = H & "B"
            Case "1100": H = H & "C"
            Case "1101": H = H & "D"
            Case "1110": H = H & "E"
            Case "1111": H = H & "F"
        End Select
    Next i
    'While Left(H, 1) = "0"
   '     H = Right(H, Len(H) - 1)
   ' Wend
        BIN_to_HEX = H
End Function


'*************************************************************************************************
'*函数名:  HEXToDEC
'*程序功能:16进制转10进制值
'*开发人员:Anna
'*异动人员:无
'*入口参数:Hex 16进制字符串
'*返回参数:10进制Integer值
'*************************************************************************************************
Public Function HEXToDEC(ByVal Hex As String) As Integer
   Dim i As Integer
   Dim B As Integer
    
   For i = 1 To Len(Hex)
       Select Case Mid(Hex, Len(Hex) - i + 1, 1)
           Case "0": B = B + 16 ^ (i - 1) * 0
           Case "1": B = B + 16 ^ (i - 1) * 1
           Case "2": B = B + 16 ^ (i - 1) * 2
           Case "3": B = B + 16 ^ (i - 1) * 3
           Case "4": B = B + 16 ^ (i - 1) * 4
           Case "5": B = B + 16 ^ (i - 1) * 5
           Case "6": B = B + 16 ^ (i - 1) * 6
           Case "7": B = B + 16 ^ (i - 1) * 7
           Case "8": B = B + 16 ^ (i - 1) * 8
           Case "9": B = B + 16 ^ (i - 1) * 9
           Case "A": B = B + 16 ^ (i - 1) * 10
           Case "B": B = B + 16 ^ (i - 1) * 11
           Case "C": B = B + 16 ^ (i - 1) * 12
           Case "D": B = B + 16 ^ (i - 1) * 13
           Case "E": B = B + 16 ^ (i - 1) * 14
           Case "F": B = B + 16 ^ (i - 1) * 15
       End Select
   Next i
   HEXToDEC = B
End Function

'*************************************************************************************************
'*函数名:  DecToHex
'*程序功能:10进制转16进制
'*开发人员:Anna
'*异动人员:无
'*入口参数:decInt 10进制Integer值
'*返回参数:16进制字符串
'*************************************************************************************************
Public Function DecToHex(ByVal decInt As Integer) As String
    Dim resHex As String
    If (decInt < 16) Then
        resHex = "0" + Hex(decInt)
    Else
        resHex = Hex(decInt)
    End If
    DecToHex = resHex
End Function


'*************************************************************************************************
'*函数名:  GetTLVData
'*程序功能:获取响应结果TLV对应值
'*开发人员:Anna
'*异动人员:无
'*入口参数:dateStr 主数据串
'           tlvStr   要获取的tab
'*返回参数:tlvStr对应数据
'*************************************************************************************************
Public Function GetTLVData(ByVal dateStr As String, ByVal tlvStr As String) As String
    '定义获取tvl数据
    Dim tvlDate As String
    tvlDate = "-1"
    '定义获取包含tvl位置
    Dim resIncludeStrPosition As Integer
    resIncludeStrPosition = InStr(crt310resStr, tlvStr)
    If (resIncludeStrPosition >= 0) Then
        '获取截取长度
        Dim interceptLenStr As String
        interceptLenStr = Mid$(dateStr, resIncludeStrPosition + 4, 2)
        '获取tvl数据
        tvlDate = Mid$(dateStr, resIncludeStrPosition + 6, HEXToDEC(interceptLenStr) * 2)
        
    End If
    GetTLVData = tvlDate
End Function


Function DoubleType(ByVal Str1 As String) As String   '双字符函数
     If Len(Str1) = 0 Then
          DoubleType = "00"
     Else
          If Len(Str1) = 1 Then
            DoubleType = "0" + Str1
          Else
             If Len(Str1) = 2 Then
                DoubleType = Str1
             End If
          End If
     End If
End Function

Function ASCII_to_bin(ByRef ASCData As String) As String
Dim ASC_BinBuf As String
Dim i As Integer
ASC_BinBuf = ""

For i = 1 To Len(ASCData)
    Select Case Mid$(ASCData, i, 1)
        Case "0"
            ASC_BinBuf = ASC_BinBuf + "0000"
        Case "1"
            ASC_BinBuf = ASC_BinBuf + "0001"
        Case "2"
            ASC_BinBuf = ASC_BinBuf + "0010"
        Case "3"
            ASC_BinBuf = ASC_BinBuf + "0011"
        Case "4"
            ASC_BinBuf = ASC_BinBuf + "0100"
        Case "5"
            ASC_BinBuf = ASC_BinBuf + "0101"
        Case "6"
            ASC_BinBuf = ASC_BinBuf + "0110"
        Case "7"
            ASC_BinBuf = ASC_BinBuf + "0111"
        Case "8"
            ASC_BinBuf = ASC_BinBuf + "1000"
        Case "9"
            ASC_BinBuf = ASC_BinBuf + "1001"
        Case "A"
            ASC_BinBuf = ASC_BinBuf + "1010"
        Case "B"
            ASC_BinBuf = ASC_BinBuf + "1011"
        Case "C"
            ASC_BinBuf = ASC_BinBuf + "1100"
        Case "D"
            ASC_BinBuf = ASC_BinBuf + "1101"
        Case "E"
            ASC_BinBuf = ASC_BinBuf + "1110"
        Case "F"
            ASC_BinBuf = ASC_BinBuf + "1111"
            
    End Select

Next i

ASCII_to_bin = ASC_BinBuf

End Function

55域获取注意说明:

(1)获取55域信息有固定的流程,按照网上前辈博客中所写流程基本上没有问题都能获取到55域信息。但是需注意的是,获取55域发送apdu命令一般最为最后命令发送,获取9F36应用交易计数器(ATC)请放在发送获取55域apdu命令之前,经本人测试,若流程不对会导致获取55的信息中9F26数据不正确。

(2)对于根据GPO返回的AFL,读文件时,这里指出两点个人理解:

应用初始化

请求命令报文:80A800000B83099F02065F2A02

         卡片返回:80167C0008010100100101011003060018010100200101009000

0801010010010101100306001801010020010100为AFL,AFL(应用文件定位器),每个AFL包括4个字节
           字节1:bit8-bit4:SFI(短文件标识符)
                        bit3-bit1:000
           字节2:文件中要读的第1个记录的记录号(不能为0)
           字节3:文件中要读的最后一个记录的记录号(大于或等于字节2)
           字节4:从字节2的记录好开始,用于静态数据记录的个数(从0开始,不大于(字节3)-(字节2)+1)

           根据GPO返回的AFL,读文件。读文件号格式为:SFI左移3位,右边补100。
比如上面的08 十六进制就是 0000 1000 bit8-bit4才是SFI,所以真实的是:0000 0001 ,读取文件的时候,右补0100(表明读取指定记录) ,得到0000 1100,就是0x0c。同理,02文件就是:0x14

08 01 01 00

也就是说发送命令报文为:00B2 01 0C 00

其中,00B2 读取IC卡固定命令 0C 为08计算结果 ;00 一般固定为00即可, 01 一般为字节3 如果字节3为03 则发送命令报文可有三个

00B2010C 00  , 00B2020C00, 00B2030C00

(3)在获取55域9F26信息,即生成应用密文,

网上博客说可根据读取的“卡片风险管理数据对象列表1(CDOL1)”生成该命令。

即如果8C卡片风险管理数据对象列表1(CDOL1)返回为:

8C : 9F02069F03069F1A0295055F2A029A039C019F37049F21039F4E14 

则请求命令报文:80AE40002E00000000000900000000000001560000800000015610041000B84FBA072019024C4E00000000000000000000000000000000000000

80AE4000          固定命令

2E                       数据长度

000000000009   9F02

000000000000   9F03

0156                   9F1A

0000800000       95

0156                   5F2A

100410               9A

00                       9C

B84FBA07         9F37

201902              9F21

4C4E00000000000000000000000000000000000000   9F4E

上述命令本人未做尝试,本人使用

"80AE800034" + 8C包含数据(除去9F21 和9F4E)+ date82 + date9F36,

即如果date82 82为7C00, date9F36为0001,

请求命令报文为:80AE800034 + 00000000000900000000000001560000800000015610041000B84FBA07 +7C00 + 0001,即80AE80003400000000000900000000000001560000800000015610041000B84FBA077C000001,经测试联调测试成功

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

丨Anna丨

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值