Hello, I am trying to obtain credit card or debit card information with nfc on flutter. I will perform payment transactions with this information, I can handle that part myself, but I am having trouble getting card information, can you help?
Thanks for your help in advance.
nfc_view_model.dart
import 'package:flutter/foundation.dart';
import 'package:flutter/services.dart';
import 'package:get/get.dart';
import 'package:nfc_manager/nfc_manager.dart';
import 'package:nfc_manager/platform_tags.dart';
class NfcViewModel extends GetxController {
RxString message = ''.obs;
Future<void> startNFCReading() async {
try {
final bool isAvailable = await NfcManager.instance.isAvailable();
if (isAvailable) {
message.value = 'NFC is available.';
await NfcManager.instance.startSession(
onDiscovered: (NfcTag tag) async {
try {
if (kDebugMode) {
print('Tag found: ${tag.data}');
}
message.value = 'Tag found: ${tag.data}';
final IsoDep? isoDep = IsoDep.from(tag);
if (isoDep != null) {
// PPSE (Proximity Payment System Environment) seçimi
var ppseCommand = [
0x00,
0xA4,
0x04,
0x00,
0x0E,
0x32,
0x50,
0x41,
0x59,
0x2E,
0x53,
0x59,
0x53,
0x2E,
0x44,
0x44,
0x46,
0x30,
0x31,
0x00
];
var ppseResponse = await isoDep.transceive(
data: Uint8List.fromList(ppseCommand));
if (kDebugMode) {
print('PPSE Response: $ppseResponse');
}
if (ppseResponse.isEmpty) {
message.value = 'PPSE Response is empty.';
await NfcManager.instance.stopSession();
return;
}
// PPSE yanıtını işle ve AID'yi al
var aid = extractAidFromPpseResponse(ppseResponse);
if (aid == null) {
message.value = 'Failed to extract AID from PPSE response.';
await NfcManager.instance.stopSession();
return;
}
// AID seçim komutu
var aidCommand = [
0x00,
0xA4,
0x04,
0x00,
aid.length,
...aid,
0x00
];
var aidResponse = await isoDep.transceive(
data: Uint8List.fromList(aidCommand));
if (kDebugMode) {
print('AID Response: $aidResponse');
}
if (aidResponse.isEmpty) {
message.value = 'AID Response is empty.';
await NfcManager.instance.stopSession();
return;
}
// GET PROCESSING OPTIONS komutu
var gpoCommand = [
0x80,
0xA8,
0x00,
0x00,
0x02,
0x83,
0x00,
0x00
];
var gpoResponse = await isoDep.transceive(
data: Uint8List.fromList(gpoCommand));
if (kDebugMode) {
print('GPO Response: $gpoResponse');
}
if (gpoResponse.isEmpty) {
message.value = 'GPO Response is empty.';
await NfcManager.instance.stopSession();
return;
}
// RECORD okuma komutu
var readRecordCommand = [0x00, 0xB2, 0x01, 0x0C, 0x00];
var readRecordResponse = await isoDep.transceive(
data: Uint8List.fromList(readRecordCommand));
if (kDebugMode) {
print('Read Record Response: $readRecordResponse');
}
if (readRecordResponse.isEmpty) {
message.value = 'Read Record Response is empty.';
await NfcManager.instance.stopSession();
return;
}
// Kart bilgilerini ayıkla
final cardDetails = parseCardDetails(readRecordResponse);
message.value = cardDetails;
await NfcManager.instance.stopSession();
} else {
message.value = 'IsoDep not supported on this tag.';
}
} catch (e) {
message.value = 'Error: $e';
await NfcManager.instance.stopSession(errorMessage: e.toString());
}
},
);
} else {
message.value = 'NFC is not available.';
}
} catch (e) {
message.value = e.toString();
}
}
List<int>? extractAidFromPpseResponse(Uint8List response) {
try {
int index = 0;
while (index < response.length) {
int tag = response[index++];
int length = response[index++];
if (tag == 0x4F) {
// AID tag
return response.sublist(index, index + length);
}
index += length;
}
return null;
} catch (e) {
if (kDebugMode) {
print('Error extracting AID: $e');
}
return null;
}
}
String parseCardDetails(Uint8List response) {
String hexString = response
.map((e) => e.toRadixString(16).padLeft(2, '0'))
.join()
.toUpperCase();
// Yanıtın uzunluğunu kontrol edin
if (hexString.length < 20) {
return 'Error: Insufficient data length. Response length is ${hexString.length}';
}
try {
// Example extraction logic (adjust based on actual card data structure)
final cardNumber =
hexString.substring(0, 16); // Example: first 16 characters
final expiryDate =
hexString.substring(16, 20); // Example: next 4 characters
return 'Card Number: $cardNumber, Expiry Date: $expiryDate';
} catch (e) {
return 'Error parsing card details: $e';
}
}
}
nfc_screen.dart (UI Code)
import 'package:digipos/core/base/view/base_view.dart';
import 'package:digipos/view/payment/nfc/view_model/nfc_view_model.dart';
import 'package:digipos/view/widgets/appbar/custom_appbar_widget.dart';
import 'package:flutter/material.dart';
import 'package:flutter_svg/flutter_svg.dart';
import 'package:get/get.dart';
import '../../../core/base/state/base_state.dart';
import '../../../core/constants/icons.dart';
class NfcScreen extends StatefulWidget {
const NfcScreen({super.key});
@override
State<NfcScreen> createState() => _NfcScreenState();
}
class _NfcScreenState extends BaseState<NfcScreen> {
final NfcViewModel _viewModel = Get.put(NfcViewModel());
@override
void initState() {
super.initState();
_viewModel.startNFCReading();
}
@override
Widget build(BuildContext context) {
return BaseView(
viewModel: _viewModel,
onPageBuilder: (context, dynamic viewModel) => scaffoldBody(),
);
}
Scaffold scaffoldBody() {
return Scaffold(
appBar: const CustomAppBarWidget(appBarType: AppBarType.back),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
SvgPicture.asset(
AppIcons.nfcPay.iconPath,
width: dynamicHeight(0.25),
),
const SizedBox(height: 20),
Obx(
() => Text(
_viewModel.message.value,
textAlign: TextAlign.center,
style: const TextStyle(
fontWeight: FontWeight.bold,
),
),
),
],
),
),
);
}
}