Search code examples
c#smartcardsmartcard-readercardreader

number value to byte[6] array card reader


What's the best way to convert a number to a byte[6] in C#?

I'm using MagTek Card reader and trying to display desired amount on device screen, it should be 6-byte array. The amount needs to be used and authorized, EMV Tag 9F02, format n12.

Function:

 int requestSmartCard(int cardType, int comfirmationTime, int pinEnteringTime, int beepTones, int option, byte [] amount, int transactionType, byte[] cashback, byte [] reserved);

And the description for amount param is: - amount The amount to be used and authorized, EMV Tag 9F02, format n12. It should be a 6-byte array.

EDIT:

This is example code from their example in C#:

          byte []amount = new byte[6];
          amount[3] = 1;
          byte []cashBack = new byte[6];

          PrintMsg(String.format("start a emv transaction"));
          byte reserved[]  = new byte[26];

          byte cardType = 2;
          byte confirmWaitTime = 20;
          byte pinWaitTime = 20;
          byte tone = 1;
          byte option = 0;
          byte transType = 4;
          retCode = m_MTSCRA.requestSmartCard(cardType, confirmWaitTime, pinWaitTime, tone, option, amount, transType, cashBack, reserved);

and then on device's screen amount of 100.00 $ is shown.

EDIT: I changed the question form float to byte[6] to number to byte[6].


Solution

  • The method should be something like:

    public static byte[] NumberToByteArray(float f, int decimals)
    {
        // A string in the format 0000000000.00 for example
        string format = new string('0', 12 - decimals) + "." + new string('0', decimals);
    
        // We format the number f, removing the decimal separator
        string str = f.ToString(format, CultureInfo.InvariantCulture).Replace(".", string.Empty);
    
        if (str.Length != 12)
        {
            throw new ArgumentException("f");
        }
    
        var bytes = new byte[6];
    
        for (int i = 0; i < 6; i++)
        {
            // For each group of two digits, the first one is shifted by
            // 4 binary places
            int digit1 = str[i * 2] - '0';
            bytes[i] = (byte)(digit1 << 4);
    
            // And the second digit is "added" with the logical | (or)
            int digit2 = str[(i * 2) + 1] - '0';
            bytes[i] |= (byte)digit2;
        }
    
        return bytes;
    }
    

    Note (1) that it isn't an optimized method. I could have multiplied by 10^decimals instead, but I don't want to do useless multiplications.

    Note (2) you shouldn't really use float. float has a precision of 6 or 7 digits (when you are lucky), while that format can store 12 digits. Use double or even better decimal. You can replace float with decimal and it will work correctly.

    Note (3) you need the number of decimal places you want to use. 2 for Euro or Dollars, but for other currencies it could be different.

    Note (4) this is a problem of conversion from a number to a BCD. It can be made without going through a string. Too lazy to do it (and I don't want to do multiplications on float)