diff --git a/AfRApay.MateCard/include/Adafruit_PN532.h b/AfRApay.MateCard/include/Adafruit_PN532.h
index c777ce0..c6c2eea 100644
--- a/AfRApay.MateCard/include/Adafruit_PN532.h
+++ b/AfRApay.MateCard/include/Adafruit_PN532.h
@@ -186,6 +186,7 @@ public:
uint16_t timeout = 0); // timeout 0 means no timeout - will block forever.
bool startPassiveTargetIDDetection(uint8_t cardbaudrate);
bool readDetectedPassiveTargetID(uint8_t* uid, uint8_t* uidLength);
+ bool readDetectedPassiveTargetID(uint8_t* uid, uint8_t* uidLength, uint16_t* atqa, uint8_t* sak);
bool readDetectedPassiveTargetIDFeliCa(uint8_t* IDm, uint8_t* IDmLength);
bool inDataExchange(uint8_t* send, uint8_t sendLength, uint8_t* response,
uint8_t* responseLength);
diff --git a/AfRApay.MateCard/src/Adafruit_PN532.cpp b/AfRApay.MateCard/src/Adafruit_PN532.cpp
index e54d8cd..dd22bb3 100644
--- a/AfRApay.MateCard/src/Adafruit_PN532.cpp
+++ b/AfRApay.MateCard/src/Adafruit_PN532.cpp
@@ -631,6 +631,66 @@ bool Adafruit_PN532::startPassiveTargetIDDetection(uint8_t cardbaudrate) {
@returns 1 if everything executed properly, 0 for an error
*/
/**************************************************************************/
+bool Adafruit_PN532::readDetectedPassiveTargetID(uint8_t* uid,
+ uint8_t* uidLength,
+ uint16_t* atqa,
+ uint8_t* sak) {
+ // read data packet
+ readdata(pn532_packetbuffer, 20);
+ // check some basic stuff
+
+ /* ISO14443A card response should be in the following format:
+
+ byte Description
+ ------------- ------------------------------------------
+ b0..6 Frame header and preamble
+ b7 Tags Found
+ b8 Tag Number (only one used in this example)
+ b9..10 SENS_RES
+ b11 SEL_RES
+ b12 NFCID Length
+ b13..NFCIDLen NFCID */
+
+#ifdef PN532CARDDEBUG
+ PN532DEBUGPRINT.print(F("Found "));
+ PN532DEBUGPRINT.print(pn532_packetbuffer[7], DEC);
+ PN532DEBUGPRINT.println(F(" tags"));
+#endif
+ if (pn532_packetbuffer[7] != 1)
+ return 0;
+
+ uint16_t sens_res = pn532_packetbuffer[9];
+ sens_res <<= 8;
+ sens_res |= pn532_packetbuffer[10];
+#ifdef PN532CARDDEBUG
+ PN532DEBUGPRINT.print(F("ATQA: 0x"));
+ PN532DEBUGPRINT.println(sens_res, HEX);
+ PN532DEBUGPRINT.print(F("SAK: 0x"));
+ PN532DEBUGPRINT.println(pn532_packetbuffer[11], HEX);
+#endif
+
+ *atqa = sens_res;
+ *sak = pn532_packetbuffer[11];
+
+ /* Card appears to be Mifare Classic */
+ *uidLength = pn532_packetbuffer[12];
+#ifdef PN532CARDDEBUG
+ PN532DEBUGPRINT.print(F("UID:"));
+#endif
+ for (uint8_t i = 0; i < pn532_packetbuffer[12]; i++) {
+ uid[i] = pn532_packetbuffer[13 + i];
+#ifdef PN532CARDDEBUG
+ PN532DEBUGPRINT.print(F(" 0x"));
+ PN532DEBUGPRINT.print(uid[i], HEX);
+#endif
+ }
+#ifdef PN532CARDDEBUG
+ PN532DEBUGPRINT.println();
+#endif
+
+ return 1;
+}
+
bool Adafruit_PN532::readDetectedPassiveTargetID(uint8_t* uid,
uint8_t* uidLength) {
// read data packet
diff --git a/AfRApay.MateCard/src/readers/pn532.cpp b/AfRApay.MateCard/src/readers/pn532.cpp
index 47cbc29..8e0619f 100644
--- a/AfRApay.MateCard/src/readers/pn532.cpp
+++ b/AfRApay.MateCard/src/readers/pn532.cpp
@@ -65,7 +65,19 @@ bool PN532Reader::isNewCardPresent() {
String PN532Reader::getCardUid() {
if (mode == PN532_MIFARE_ISO14443A) {
Serial.println("Reading NFC-A UID");
- pn532->readDetectedPassiveTargetID(uid, &uidLength);
+
+ uint16_t atqa;
+ uint8_t sak;
+
+ pn532->readDetectedPassiveTargetID(uid, &uidLength, &atqa, &sak);
+ if (uidLength == 4) {
+ if (atqa == 0x2 && sak == 0x18) {
+ Serial.println("4 byte uid with ATQA 0x2 and SAK 0x18, assuming ov-chipkaart");
+ uidLength = 6;
+ uid[4] = 0x02;
+ uid[5] = 0x18;
+ }
+ }
}
else {
Serial.println("Reading FeliCa IDm");
diff --git a/AfRApay.Web/Backend/Database/Tables/Card.cs b/AfRApay.Web/Backend/Database/Tables/Card.cs
index 5e6f54c..81d7f2b 100644
--- a/AfRApay.Web/Backend/Database/Tables/Card.cs
+++ b/AfRApay.Web/Backend/Database/Tables/Card.cs
@@ -17,8 +17,10 @@ public class Card {
NfcTflOyster = 22,
NfcOvChipkaart = 23,
NfcItso = 24,
- FeliCaGeneric = 30,
- FeliCaSuica = 31,
- FeliCaPasmo = 32,
+ NfcContactless = 25,
+ FeliCaGeneric = 30,
+ FeliCaSuica = 31,
+ FeliCaPasmo = 32,
+ FeliCaApplePay = 33,
}
}
diff --git a/AfRApay.Web/Controllers/CardController.cs b/AfRApay.Web/Controllers/CardController.cs
index 7579e22..a369dd2 100644
--- a/AfRApay.Web/Controllers/CardController.cs
+++ b/AfRApay.Web/Controllers/CardController.cs
@@ -121,7 +121,7 @@ public class CardController : Controller {
var db = new DatabaseContext();
if (db.Cards.Any(p => p.Id == card)) {
var user = db.Cards.Include(p => p.User).First(p => p.Id == card).User;
-
+
var dbCard = db.Cards.First(p => p.Id == card);
var newType = GetCardType(reader, card);
@@ -152,14 +152,18 @@ public class CardController : Controller {
public ErrorResponse GetExamples() => new("No active link process");
}
- private Card.CardType GetCardType(string? reader, string cardNumber) {
- //TODO match more specific type based on card number format
-
- return reader switch {
- "rdm6300" => Card.CardType.Rfid125KhzGeneric,
- "pn532-iso14443a" => Card.CardType.NfcGeneric,
- "pn532-felica" => Card.CardType.FeliCaGeneric,
- _ => Card.CardType.Unknown
- };
- }
+ private Card.CardType GetCardType(string? reader, string cardNumber) => reader switch {
+ "rdm6300" => Card.CardType.Rfid125KhzGeneric,
+ "pn532-iso14443a" when cardNumber.Length == 8 => Card.CardType.NfcMifareClassic,
+ "pn532-iso14443a" when cardNumber.Length == 12 && cardNumber.EndsWith("0218") => Card.CardType.NfcOvChipkaart,
+ "pn532-iso14443a" when cardNumber.Length == 14 && cardNumber.EndsWith("5e80") => Card.CardType.NfcTflOyster,
+ "pn532-iso14443a" when cardNumber.Length == 14 && cardNumber.StartsWith("04") && cardNumber.EndsWith("80") => Card.CardType.NfcItso,
+ "pn532-iso14443a" => Card.CardType.NfcGeneric,
+ "pn532-felica" when cardNumber.Length == 16 && cardNumber.StartsWith("0112") => Card.CardType.FeliCaSuica,
+ "pn532-felica" when cardNumber.Length == 16 && cardNumber.StartsWith("0101") => Card.CardType.FeliCaPasmo,
+ "pn532-felica" when cardNumber.Length == 16 && cardNumber.StartsWith("0139") => Card.CardType.FeliCaApplePay,
+ "pn532-felica" => Card.CardType.FeliCaGeneric,
+ _ => Card.CardType.Unknown
+ //"pn532-iso14443a" when [???] => Card.CardType.NfcContactless,
+ };
}
diff --git a/AfRApay.Web/Pages/EditUser.cshtml b/AfRApay.Web/Pages/EditUser.cshtml
index e70fa9a..5666f88 100644
--- a/AfRApay.Web/Pages/EditUser.cshtml
+++ b/AfRApay.Web/Pages/EditUser.cshtml
@@ -42,9 +42,9 @@
-
-
-
+
+
+
@@ -108,12 +108,13 @@
- @if(cardNumber.Length < 12) {
+ @if (cardNumber.Length < 12) {
if (cardType == Card.CardType.Rfid125KhzGeneric) {
- 0000000@cardNumber[^3..]
+
+ 0000000@cardNumber[^3..]
+
}
- else
- {
+ else {
@cardNumber
}
}
@@ -126,10 +127,69 @@
@expDate
-
-
-
-
+ @switch (cardType) {
+ case Card.CardType.Rfid125KhzGeneric:
+
+
+
+ break;
+ case Card.CardType.NfcGeneric:
+
+
+
+ break;
+ case Card.CardType.FeliCaGeneric:
+
+
+
+ break;
+ case Card.CardType.NfcMifareClassic:
+
+
+
+ break;
+ case Card.CardType.NfcTflOyster:
+
+
+
+ break;
+ case Card.CardType.NfcOvChipkaart:
+
+
+
+ break;
+ case Card.CardType.NfcItso:
+
+
+
+ break;
+ case Card.CardType.NfcContactless:
+
+ break;
+ case Card.CardType.FeliCaSuica:
+
+
+
+ break;
+ case Card.CardType.FeliCaPasmo:
+
+
+
+ break;
+ case Card.CardType.FeliCaApplePay:
+
+
+
+
+ break;
+ case Card.CardType.Unknown:
+ break;
+ default:
+ throw new ArgumentOutOfRangeException(nameof(cardType), cardType, null);
+ }
+
@@ -168,6 +228,7 @@
await RenderCard(user.Nickname, card.Id, cardType: card.Type);
await RenderCardModal(user.Nickname, card.Id, cardType: card.Type);
}
+
await RenderCard(user.Nickname, displayType: EditUserModel.CardDisplayType.LinkPlaceholder);
}
diff --git a/AfRApay.Web/wwwroot/css/site.css b/AfRApay.Web/wwwroot/css/site.css
index 61fa075..2923f52 100644
--- a/AfRApay.Web/wwwroot/css/site.css
+++ b/AfRApay.Web/wwwroot/css/site.css
@@ -224,7 +224,7 @@ button.accept-policy {
line-height: 9px;
margin-right: 5px;
}
-.fake-card-wrapper .fake-card .face-card.front .fake-card-logo-bottom {
+.fake-card-wrapper .fake-card .face-card.front .fake-card-logo-bottom-matecard {
position: absolute;
bottom: 33px;
right: 20px;
@@ -234,30 +234,253 @@ button.accept-policy {
align-items: center;
justify-content: center;
}
-.fake-card-wrapper .fake-card .face-card.front .fake-card-logo-top {
+.fake-card-wrapper .fake-card .face-card.front .fake-card-logo-bottom-matecard img {
+ width: 55px;
+}
+.fake-card-wrapper .fake-card .face-card.front .fake-card-logo-bottom-matecard img.fake-card-logo-inner {
+ margin-top: 18px;
+}
+
+.fake-card-wrapper .fake-card .face-card.front .fake-card-logo-top-rfid {
position: absolute;
top: 25px;
right: 20px;
width: 70px;
height: 65px;
border-radius: 10px;
- background-color: white;
display: flex;
align-items: center;
- justify-content: center; overflow: hidden;
+ justify-content: center;
+ overflow: hidden;
}
-.fake-card-wrapper .fake-card .face-card.front .fake-card-logo-top img {
+.fake-card-wrapper .fake-card .face-card.front .fake-card-logo-top-rfid img {
width: 55px;
+ filter: invert(100%);
}
-.fake-card-wrapper .fake-card .face-card.front .fake-card-logo-top img.fake-card-logo-inner {
+.fake-card-wrapper .fake-card .face-card.front .fake-card-logo-top-rfid img.fake-card-logo-inner {
margin-top: 1px;
margin-bottom: 2px;
}
-.fake-card-wrapper .fake-card .face-card.front .fake-card-logo-bottom img {
+.fake-card-wrapper .fake-card .face-card.front .fake-card-logo-top-ovc {
+ position: absolute;
+ top: 25px;
+ right: 20px;
+ width: 70px;
+ height: 65px;
+ border-radius: 10px;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ overflow: hidden;
+}
+.fake-card-wrapper .fake-card .face-card.front .fake-card-logo-top-ovc img {
+ width: 55px;
+ filter: invert(100%);
+}
+.fake-card-wrapper .fake-card .face-card.front .fake-card-logo-top-ovc img.fake-card-logo-inner {
+ margin-top: 1px;
+ margin-bottom: 2px;
+}
+
+.fake-card-wrapper .fake-card .face-card.front .fake-card-logo-top-mifare {
+ position: absolute;
+ top: 25px;
+ right: 20px;
+ width: 100px;
+ height: 65px;
+ border-radius: 10px;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ overflow: hidden;
+}
+.fake-card-wrapper .fake-card .face-card.front .fake-card-logo-top-mifare img {
+ width: 100px;
+ filter: invert(100%);
+}
+.fake-card-wrapper .fake-card .face-card.front .fake-card-logo-top-mifare img.fake-card-logo-inner {
+ margin-top: 1px;
+ margin-bottom: 2px;
+}
+
+.fake-card-wrapper .fake-card .face-card.front .fake-card-logo-top-itso {
+ position: absolute;
+ top: 25px;
+ right: 20px;
+ width: 70px;
+ height: 65px;
+ border-radius: 10px;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ overflow: hidden;
+}
+.fake-card-wrapper .fake-card .face-card.front .fake-card-logo-top-itso img {
+ width: 55px;
+ filter: invert(100%);
+}
+.fake-card-wrapper .fake-card .face-card.front .fake-card-logo-top-itso img.fake-card-logo-inner {
+ margin-top: 1px;
+ margin-bottom: 2px;
+}
+
+.fake-card-wrapper .fake-card .face-card.front .fake-card-logo-top-pasmo {
+ position: absolute;
+ top: 25px;
+ right: 20px;
+ width: 90px;
+ height: 65px;
+ border-radius: 10px;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ overflow: hidden;
+}
+.fake-card-wrapper .fake-card .face-card.front .fake-card-logo-top-pasmo img {
+ width: 75px;
+ filter: invert(100%);
+}
+.fake-card-wrapper .fake-card .face-card.front .fake-card-logo-top-pasmo img.fake-card-logo-inner {
+ margin-top: 1px;
+ margin-bottom: 2px;
+}
+
+.fake-card-wrapper .fake-card .face-card.front .fake-card-logo-top-contactless {
+ position: absolute;
+ top: 25px;
+ right: 20px;
+ width: 60px;
+ height: 65px;
+ border-radius: 10px;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ overflow: hidden;
+}
+.fake-card-wrapper .fake-card .face-card.front .fake-card-logo-top-contactless img {
+ width: 25px;
+ filter: invert(100%);
+}
+.fake-card-wrapper .fake-card .face-card.front .fake-card-logo-top-contactless img.fake-card-logo-inner {
+ margin-top: 1px;
+ margin-bottom: 2px;
+}
+
+.fake-card-wrapper .fake-card .face-card.front .fake-card-logo-top-suica {
+ position: absolute;
+ top: 25px;
+ right: 20px;
+ width: 120px;
+ height: 65px;
+ border-radius: 10px;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ overflow: hidden;
+}
+.fake-card-wrapper .fake-card .face-card.front .fake-card-logo-top-suica img {
+ width: 110px;
+ filter: invert(100%);
+}
+.fake-card-wrapper .fake-card .face-card.front .fake-card-logo-top-suica img.fake-card-logo-inner {
+ margin-top: 1px;
+ margin-bottom: 2px;
+}
+
+.fake-card-wrapper .fake-card .face-card.front .fake-card-logo-top-oyster {
+ position: absolute;
+ top: 25px;
+ right: 20px;
+ width: 120px;
+ height: 65px;
+ border-radius: 10px;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ overflow: hidden;
+}
+.fake-card-wrapper .fake-card .face-card.front .fake-card-logo-top-oyster img {
+ width: 120px;
+ filter: invert(100%);
+}
+.fake-card-wrapper .fake-card .face-card.front .fake-card-logo-top-oyster img.fake-card-logo-inner {
+ margin-top: 1px;
+ margin-bottom: 2px;
+}
+
+.fake-card-wrapper .fake-card .face-card.front .fake-card-logo-top-felica {
+ position: absolute;
+ top: 25px;
+ right: 20px;
+ width: 70px;
+ height: 65px;
+ border-radius: 10px;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ overflow: hidden;
+}
+.fake-card-wrapper .fake-card .face-card.front .fake-card-logo-top-felica img {
+ width: 55px;
+ filter: invert(100%);
+}
+.fake-card-wrapper .fake-card .face-card.front .fake-card-logo-top-felica img.fake-card-logo-inner {
+ margin-top: 1px;
+ margin-bottom: 2px;
+}
+
+.fake-card-wrapper .fake-card .face-card.front .fake-card-logo-top-apay {
+ position: absolute;
+ top: 25px;
+ right: 20px;
+ width: 130px;
+ height: 65px;
+ border-radius: 10px;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ overflow: hidden;
+}
+.fake-card-wrapper .fake-card .face-card.front .fake-card-logo-top-apay img:nth-of-type(1) {
+ width: 55px;
+ margin-right: 15px;
+ filter: invert(100%);
+}
+.fake-card-wrapper .fake-card .face-card.front .fake-card-logo-top-apay img:nth-of-type(2) {
+ width: 50px;
+ filter: invert(100%);
+}
+.fake-card-wrapper .fake-card .face-card.front .fake-card-logo-top-apay img.fake-card-logo-inner {
+ margin-top: 1px;
+ margin-bottom: 2px;
+}
+
+.fake-card-wrapper .fake-card .face-card.front .fake-card-logo-top-nfc {
+ position: absolute;
+ top: 25px;
+ right: 20px;
+ width: 70px;
+ height: 65px;
+ border-radius: 10px;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ overflow: hidden;
+}
+.fake-card-wrapper .fake-card .face-card.front .fake-card-logo-top-nfc img {
+ width: 55px;
+ filter: invert(100%);
+}
+.fake-card-wrapper .fake-card .face-card.front .fake-card-logo-top-nfc img.fake-card-logo-inner {
+ margin-top: 1px;
+ margin-bottom: 2px;
+}
+
+.fake-card-wrapper .fake-card .face-card.front .fake-card-logo-bottom-matecard img {
width: 55px;
}
-.fake-card-wrapper .fake-card .face-card.front .fake-card-logo-bottom img.fake-card-logo-inner {
+.fake-card-wrapper .fake-card .face-card.front .fake-card-logo-bottom-matecard img.fake-card-logo-inner {
margin-top: 18px;
}
diff --git a/AfRApay.Web/wwwroot/img/apay.svg b/AfRApay.Web/wwwroot/img/apay.svg
new file mode 100644
index 0000000..d0fb0c7
--- /dev/null
+++ b/AfRApay.Web/wwwroot/img/apay.svg
@@ -0,0 +1,28 @@
+
+
+
diff --git a/AfRApay.Web/wwwroot/img/contactless.svg b/AfRApay.Web/wwwroot/img/contactless.svg
new file mode 100644
index 0000000..fa42cf4
--- /dev/null
+++ b/AfRApay.Web/wwwroot/img/contactless.svg
@@ -0,0 +1,7 @@
+
+
\ No newline at end of file
diff --git a/AfRApay.Web/wwwroot/img/felica.png b/AfRApay.Web/wwwroot/img/felica.png
new file mode 100644
index 0000000..fc48ff1
Binary files /dev/null and b/AfRApay.Web/wwwroot/img/felica.png differ
diff --git a/AfRApay.Web/wwwroot/img/itso.svg b/AfRApay.Web/wwwroot/img/itso.svg
new file mode 100644
index 0000000..2755337
--- /dev/null
+++ b/AfRApay.Web/wwwroot/img/itso.svg
@@ -0,0 +1,64 @@
+
+
+
+
diff --git a/AfRApay.Web/wwwroot/img/mifare.svg b/AfRApay.Web/wwwroot/img/mifare.svg
new file mode 100644
index 0000000..95db33c
--- /dev/null
+++ b/AfRApay.Web/wwwroot/img/mifare.svg
@@ -0,0 +1,212 @@
+
+
+
+
diff --git a/AfRApay.Web/wwwroot/img/nfc.png b/AfRApay.Web/wwwroot/img/nfc.png
new file mode 100644
index 0000000..33a9ddf
Binary files /dev/null and b/AfRApay.Web/wwwroot/img/nfc.png differ
diff --git a/AfRApay.Web/wwwroot/img/ovc.png b/AfRApay.Web/wwwroot/img/ovc.png
new file mode 100644
index 0000000..fe64100
Binary files /dev/null and b/AfRApay.Web/wwwroot/img/ovc.png differ
diff --git a/AfRApay.Web/wwwroot/img/ovc.svg b/AfRApay.Web/wwwroot/img/ovc.svg
new file mode 100644
index 0000000..25eec6f
--- /dev/null
+++ b/AfRApay.Web/wwwroot/img/ovc.svg
@@ -0,0 +1,46 @@
+
+
+
+
diff --git a/AfRApay.Web/wwwroot/img/oyster.svg b/AfRApay.Web/wwwroot/img/oyster.svg
new file mode 100644
index 0000000..7075703
--- /dev/null
+++ b/AfRApay.Web/wwwroot/img/oyster.svg
@@ -0,0 +1,76 @@
+
+
diff --git a/AfRApay.Web/wwwroot/img/pasmo.svg b/AfRApay.Web/wwwroot/img/pasmo.svg
new file mode 100644
index 0000000..6a22aa6
--- /dev/null
+++ b/AfRApay.Web/wwwroot/img/pasmo.svg
@@ -0,0 +1,43 @@
+
+
+
+
diff --git a/AfRApay.Web/wwwroot/img/rfid.png b/AfRApay.Web/wwwroot/img/rfid.png
new file mode 100644
index 0000000..d9f8b29
Binary files /dev/null and b/AfRApay.Web/wwwroot/img/rfid.png differ
diff --git a/AfRApay.Web/wwwroot/img/suica.svg b/AfRApay.Web/wwwroot/img/suica.svg
new file mode 100644
index 0000000..9af18d3
--- /dev/null
+++ b/AfRApay.Web/wwwroot/img/suica.svg
@@ -0,0 +1,68 @@
+
+