美文网首页
Android NFC(二)M1卡电子钱包功能

Android NFC(二)M1卡电子钱包功能

作者: ccDown | 来源:发表于2019-03-15 18:06 被阅读0次

M1任意可写块都可实现电子钱包的功能。本质其实就是按照一定的数据格式来对块值进行初始化、加值、减值。电子钱包的数据结构下图示例:


钱包结构.png

比如要将第5扇区的第0块作为电子钱包的存储位置,就要先将该块的数据格式化为上述形式。

钱包正值的意思是将10进制余额转为16进制数然后按字节逆序排列
钱包反值的意思是将钱包正值取反
地址的意思是当前的块值序号,如20块填14(10进制的20转为16进制的14)

如电子钱包余额为0,该块值数据为:00000000ffffffff0000000014eb14eb
当电子钱包余额为1时,该块值数据为:01000000feffffff0100000018e718e7
当电子钱包余额为100时,该块值数据为:640000009bffffff6400000018e718e7

余额的加值减值都要转换为10进制数然后进行计算之后再重新组装为16进制数据

电子钱包块值初始化:

  /**
 * 初始化块值
 *
 * @param blockIndex
 * @param data
 * @return
 */
public static byte[] m1FormatBlock(int blockIndex, int data) {

    //region 系统的方法
    //construct value block of value zero; "address" byte is set to 0 in this example 

    //byte[] zeroValue = {0, 0, 0, 0, 255, 255, 255, 255, 0, 0, 0, 0, 0, 255, 0, 255 }; 
    //mifare.writeBlock(blockIndex, zeroValue); 

    //end region

    byte[] result = new byte[16];

    //钱包正值
    byte[] temps = new byte[4];
    //钱包反值
    byte[] noTemps = new byte[4];
    
    //4个字节的钱包值  反序排列 如1000 转为16进制00 00 03 e8  反序为 e8 03 00 00
    for (int i = 0; i < 4; i++) {
        int temp = data >> 8 * i;
        temps[i] = (byte) (temp & 0xFF);

        int noTemp = (~data) >> 8 * i;
        noTemps[i] = (byte) (noTemp & 0xFF);
    }

    //钱包1-4字节 正值 
    //钱包5-8字节 反值 
    //钱包9-12字节 正值 
    for (int i = 0; i < 12; i++) {
        if (i<4){
            result[i] = temps[i%4];
        } else if (i < 8){
            result[i] = noTemps[i%4];
        } else if (i < 12){
            result[i] = temps[i%4];
        }
    }

    /**
     *  钱包地址 
     *  12字节 16进制正值 
     *  13字节 16进制反值
     *  14字节 16进制正值 
     *  15字节 16进制反值 
     */
    result[12] = (byte) (blockIndex & 0xFF);
    result[13] = (byte) ~(blockIndex & 0xFF);
    result[14] = (byte) (blockIndex & 0xFF);
    result[15] = (byte) ~(blockIndex & 0xFF);
    return result;
}

电子钱包余额加(将余额转换为十进制数进行加操作计算出结果,然后再将结果转换为16进制倒序写入到卡中):

    /**
 * 加值
 */
private void m1incvalue(int block,int value) {
    // increase the value block by some amount 
    mifare.increment(blockIndex, value); 
    // result is stored in scratch register inside tag; now write result to block 
    mifare.transfer(blockIndex); 
}

电子钱包余额减(将余额转换为十进制数进行减操作计算出结果,然后再将结果转换为16进制倒序写入到卡中):

/**
 * 减值
 */
private void m1decvalue(int block,int value) {
     // decrease the value block by some amount 
    mifare.decrement(blockIndex, value); 
    // result is stored in scratch register inside tag; now write result to block 
    mifare.transfer(blockIndex); 
}

根据块值获取余额(取前4字节数据):

 /**
 * 根据值块获取值数据
 *
 * @param block
 * @return
 */
public static int resolveBlockValue(final byte[] block) {
    byte[] blockValue = new byte[4];
    if (block != null && block.length == 16) {
        //获取前四位值
        System.arraycopy(block, 0, blockValue, 0, blockValue.length);
        //反转数组
        byte[] temp = new byte[4];
        for (int i = 0; i < temp.length; i++) {
            temp[temp.length - 1 - i] = block[i];
        }
        String hex = bytesToHexString(temp);
        return hex2Int(hex);
    }
    return -100;
}

/**
 * 十六进制转int 
 *
 * @param hex
 * @return
 */
public static int hex2Int(String hex) {
    byte[] bytes = hex2Bytes(hex);
    int len = bytes.length;
    int rec = 0;
    for (int i = 0; i < len; i++) {
        int temp = bytes[i] & 0xff;
        int off = (len - 1 - i) * 8;
        rec |= (temp << off);
    }
    return rec;
}

/**
 * 十六进制转Byte
 *
 * @param hexStr
 * @return
 */
public static byte[] hex2Bytes(String hexStr) {
    int len = hexStr.length();
    if (len % 2 != 0) {
        throw new RuntimeException("length error");
    }
    byte[] b = new byte[hexStr.length() / 2];
    int bLen = b.length;
    int j = 0;
    for (int i = 0; i < bLen; i++) {
        char c0 = hexStr.charAt(j++);
        char c1 = hexStr.charAt(j++);
        b[i] = (byte) ((parse(c0) << 4) | parse(c1));
    }
    return b;
}

private static int parse(char c) {
    if (c >= 'a')
        return (c - 'a' + 10) & 0x0f;
    if (c >= 'A')
        return (c - 'A' + 10) & 0x0f;
    return (c - '0') & 0x0f;
}

遇到的问题:
1.构建值块:http://cn.voidcc.com/question/p-tpvgkusm-xv.html
2.加值减值失败:https://stackoverflow.com/questions/11999710/how-to-use-mifareclassic-api-increment-and-decrement-in-android

参考官方文档:
https://www.nxp.com/docs/en/data-sheet/MF1S50YYX_V1.pdf

相关文章

网友评论

      本文标题:Android NFC(二)M1卡电子钱包功能

      本文链接:https://www.haomeiwen.com/subject/cfxrmqtx.html