- Java 双重比较
- java - 比较器与 Apache BeanComparator
- Objective-C 完成 block 导致额外的方法调用?
- database - RESTful URI 是否应该公开数据库主键?
我需要使用 NFC 从信用卡中获取卡号,然后将其转换为正确的字符串。
这是我目前所拥有的:
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<AccountCallback> mAccountCallback;
public interface AccountCallback
{
void OnAccountRecieved(string account);
}
public LoyaltyCardReader(WeakReference<AccountCallback> accountCallback)
{
mAccountCallback = accountCallback;
}
/**
* Callback when a new tag is discovered by the system.
*
* <p>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 < SELECT_OK_SW.Length && i < statusWord.Length && 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.
*
* <p>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 < 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;
}
我可以提取卡片类型,但结果的其余部分是乱码,如加框问号等。我试图阅读我能找到的有关该主题的所有内容,但我就是不明白! :(
我在 Visual Studio 2015 Enterprise 中使用 Xamarin。
我不记得是从哪里得到的,但大部分代码都取自一个很好的例子,在这个例子中,作者使用了另一部手机作为模拟器。
最佳答案
如果您的卡实际上是万事达卡(或几乎任何 EMV 支付卡),该卡将不会返回其卡号(实际上:主帐号,PAN)以响应应用程序选择 (SELECT) 命令。相反,您需要查询卡中的数据文件并从这些文件中提取号码。
因此,您首先要通过 AID 选择 MasterCard 应用程序:
result = isoDep.Transceive(HexStringToByteArray("00A404007A000000004101000"));
接下来,您通常会发出 GET PROCESSING OPTIONS 命令(请参阅 Unable to identify AFL on a smart card)以发现数据记录的位置。但是,您也可以跳过此步骤,尝试通过暴力方式读取记录。
用蛮力方法读取记录可能看起来像这样:
for (int sfi = 1; sfi < 10; ++sfi ) {
for (int record = 1; record < 10; ++record) {
byte[] cmd = HexStringToByteArray("00B2000400");
cmd[2] = (byte)(record & 0x0FF)
cmd[3] |= (byte)((sfi << 3) & 0x0F8);
result = isoDep.Transceive(cmd);
if ((result != null) && (result.Length >=2)) {
if ((result[result.Length - 2] == (byte)0x90) && (result[result.Length - 1] == (byte)0x00)) {
// file exists and contains data
byte[] data = Arrays.CopyOf(result, result.Length - 2);
// TODO: parse data
}
}
}
}
然后您需要搜索为每条记录返回的数据,以便找到包含 PAN 的数据对象。参见 this answer关于如何解码 TLV 编码数据对象。您可以找到在线 TLV 解析器 here . PAN 通常编码在带有标签 0x5A 的数据对象中(参见 here )。
请注意,您可以通过 NFC 读取的 PAN可能与印在卡上的 PAN 不同。
关于android - 如何通过 NFC 读取信用卡的响应,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38998065/
我正在尝试检查 Entry 中是否存在重复项,并使用内联消息提醒用户该数字存在。 $(document).ready(function(){ $("#con1").blur(function(
我有一个基于类的 View 。我在引导模式上使用 Ajax。为了避免页面刷新,我想使用此类基于 View 返回 JSON 响应而不是 HTTP 响应,但我只看到了如何为基于函数的 View 返回 JS
关闭。这个问题是not reproducible or was caused by typos .它目前不接受答案。 这个问题是由于错别字或无法再重现的问题引起的。虽然类似的问题可能是on-topi
我有一个大型内部企业基于 Web 的应用程序在 IIS6 上运行 ASP.NET 3.5,生成 401 个“未经授权”响应,然后是 200 个“Ok”响应(如 Fiddler 所述)。我知道为什么会发
感谢您研究我的问题。 我有一个node/express服务器,配置了一个server.js文件,它调用urls.js,而urls.js又调用 Controller 来处理http请求,所有这些都配置相
当我使用以下命令时,我得到正确的 JSON 响应: $ curl --data "regno=&dob=&mobile=" https://vitacademics-rel.herokuapp.co
我有一个非常简单的 RESTful 服务,它通过 POST 接收一些表单数据,其目的是在云存储(Amazon S3、Azure Blob 存储等)中简单地保留文本主体(具有唯一 ID)作为一个文件..
UDP 不发送任何 ack,但它会发送任何响应吗? 我已经设置了客户端服务器UDP程序。如果我让客户端向不存在的服务器发送数据,那么客户端会收到任何响应吗? 我的假设是; 客户端 --> 广播服务器地
我有一个电梯项目,其中 有一个扩展 RestHelper 的类,看起来像这样 serve{ "api" / "mystuff" prefix { case a
我们正在寻求覆盖 Kong 错误响应结构并编写自定义消息(即用我们的自定义消息替换“超出 API 速率限制”、“无效的身份验证凭据”等)。 我们要找的错误响应结构(代码是自定义的内部错误代码,与HTT
我正在尝试监听 EKEventStoreChangedNotification 以检查当我的应用程序处于后台时日历是否已更改。 我在 View Controller 的 initWithNibMeth
我了解 javascript,并且正在学习 ASP.NET C# 我想要做什么(完成的是javascript): document.getElementById('divID-1'
是否可以过滤所有 har 对象并仅获取 POST 请求/响应?也许在初始化 BrowserMobProxyServer 期间是这样做的方法?我需要将 har 对象保存到文件中并上传到 har 查看器。
我正在尝试向 Oauth 的 API 发送响应。遗憾的是,Symfony2 文档在解释 $response->headers->set(...); 的所有不同部分方面做得很差。 这是我的 OauthC
我正在尝试测试用例来模拟 api 调用,并使用 python 响应来模拟 api 调用。 下面是我的模拟, with responses.RequestsMock() as rsps: url
在尝试在 Haskell 中进行一些领域驱动设计时,我发现自己遇到了这个问题: data FetchAccessories = FetchAccessories data AccessoriesRes
我正在与 ANT+ USB 棒连接,并用项目 react 器替换我自己天真的“MessageBus”,因为它看起来非常合适。 USB接口(interface)本质上是异步的(单独的输入/输出管道),我
我正在将项目迁移到AFNetworking 2.0。使用AFNetworking 1.0时,我编写了代码来记录控制台中的每个请求/响应。这是代码: -(AFHTTPRequestOperation *
我有以下代码段。 ajaxRequest.onreadystatechange = function(){ if(ajaxRequest.readyState == 4){
我有问题......我在 php 中有一个监听器脚本可以执行以下操作: if ($count != 1) {echo 'no';} else { echo "yes";} 因此它会回显"is"或“
我是一名优秀的程序员,十分优秀!