title: How to read response from a credit card over NFC
body: <p>I need to get the card number from a credit card using NFC and then convert it to a proper string.</p>
  
  <p>Here is what I have so far:</p>
  
  <pre><code>private static readonly string MASTERCARD_AID = "A0000000041010";
  // ISO-DEP command HEADER for selecting an AID.
  // Format: [Class | Instruction | Parameter 1 | Parameter 2]
  private static readonly string SELECT_APDU_HEADER = "00A40400";
  // "OK" status word sent in response to SELECT AID command (0x9000)
  private static readonly byte[] SELECT_OK_SW = { (byte)0x90, (byte)0x00 };
  
  // Weak reference to prevent retain loop. mAccountCallback is responsible for exiting
  // foreground mode before it becomes invalid (e.g. during onPause() or onStop()).
  private WeakReference&lt;AccountCallback&gt; mAccountCallback;
  
  public interface AccountCallback
  {
      void OnAccountRecieved(string account);
  }
  
  public LoyaltyCardReader(WeakReference&lt;AccountCallback&gt; accountCallback)
  {
      mAccountCallback = accountCallback;
  }
  /**
   * Callback when a new tag is discovered by the system.
   *
   * &lt;p&gt;Communication with the card should take place here.
   *
   * @param tag Discovered tag
   */
  public void OnTagDiscovered(Tag tag)
  {
      IsoDep isoDep = IsoDep.Get(tag);
      if (isoDep != null)
      {
          try
          {
              // Connect to the remote NFC device
              isoDep.Connect();
              // Build SELECT AID command for our loyalty card service.
              // This command tells the remote device which service we wish to communicate with.
              byte[] command = BuildSelectApdu(MASTERCARD_AID);
              // Send command to remote device
              byte[] result = isoDep.Transceive(command);
              // If AID is successfully selected, 0x9000 is returned as the status word (last 2
              // bytes of the result) by convention. Everything before the status word is
              // optional payload, which is used here to hold the account number.
              int resultLength = result.Length; //should be 89
              byte[] statusWord = { result[resultLength - 2], result[resultLength - 1] };
              byte[] payload = new byte[resultLength - 2];
              Array.Copy(result, payload, resultLength - 2);
              bool arrayEquals = SELECT_OK_SW.Length == statusWord.Length;
  
              for (int i = 0; i &lt; SELECT_OK_SW.Length &amp;&amp; i &lt; statusWord.Length &amp;&amp; arrayEquals; i++)
              {
                  arrayEquals = (SELECT_OK_SW[i] == statusWord[i]);
                  if (!arrayEquals)
                      break;
              }
              if (arrayEquals)
              {
                  //takes out cardname
                  //int lengthWanted = 58;
                  //byte[] newRes = new byte[resultLength - lengthWanted];
                  //byte[] cardname = new byte[newRes.Length - 15]; 
                  //Array.Copy(payload, newRes, resultLength - lengthWanted);
                  //Array.Copy(payload, 16, cardname, 0, cardname.Length);
  
                  // The remote NFC device will immediately respond with its stored account number
                  string accountNumber = Encoding.UTF8.GetString(payload);
                  //string accountNumber = ByteArrayToHexString(payload);
  
                  // Inform CardReaderFragment of received account number
                  AccountCallback accountCallback;
                  if (mAccountCallback.TryGetTarget(out accountCallback))
                  {
                      accountCallback.OnAccountRecieved(accountNumber);
                  }
              }
          }
          catch (Exception e)
          {
              Console.WriteLine("Hmm: " + e);
              throw e;
              //Toast.MakeText(ctx, "hmmm: " + e, ToastLength.Short).Show();
          }
      }
  }
  
  /**
   * Build APDU for SELECT AID command. This command indicates which service a reader is
   * interested in communicating with. See ISO 7816-4.
   *
   * @param aid Application ID (AID) to select
   * @return APDU for SELECT AID command
   */
  public static byte[] BuildSelectApdu(string aid)
  {
      // Format: [CLASS | INSTRUCTION | PARAMETER 1 | PARAMETER 2 | LENGTH | DATA]
      return HexStringToByteArray(SELECT_APDU_HEADER + (aid.Length / 2).ToString("X2") + aid);
  }
  
  /**
  * Utility class to convert a byte array to a hexadecimal string.
  *
  * @param bytes Bytes to convert
  * @return String, containing hexadecimal representation.
  */
  
  public static string ByteArrayToHexString(byte[] bytes)
  {
      var hex = new StringBuilder(bytes.Length * 2);
      foreach (byte b in bytes)
          hex.AppendFormat("{0:x2}", b);
      return hex.ToString();
  }
  
  /**
   * Utility class to convert a hexadecimal string to a byte string.
   *
   * &lt;p&gt;Behavior with input strings containing non-hexadecimal characters is undefined.
   *
   * @param s String containing hexadecimal characters to convert
   * @return Byte array generated from input
   */
  private static byte[] HexStringToByteArray(string s)
  {
      int len = s.Length;
      if (len % 2 == 1)
      {
          throw new ArgumentException("Hex string must have even number of characters");
      }
      byte[] data = new byte[len / 2]; //Allocate 1 byte per 2 hex characters
      for (int i = 0; i &lt; len; i += 2)
      {
          ushort val, val2;
          // Convert each chatacter into an unsigned integer (base-16)
          try
          {
              val = (ushort)Convert.ToInt32(s[i].ToString() + "0", 16);
              val2 = (ushort)Convert.ToInt32("0" + s[i + 1].ToString(), 16);
          }
          catch (Exception)
          {
              continue;
          }
  
          data[i / 2] = (byte)(val + val2);
      }
      return data;
  }
  </code></pre>
  
  <p>I can extract the card type, but the rest of the result is gibberish, like boxed questionmarks and so on. I have tried to read all I could find on that subject, but I simply don't get it! :(</p>
  
  <p>I am using Xamarin in Visual Studio 2015 Enterprise.</p>
  
  <p>I can't remember where I got it but most of the code is taken from a great example where the author used another phone as emulator.</p>