community-cordova-plugin-nfc 1.6.2 → 1.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/plugin.xml +1 -1
- package/src/ios/NfcPlugin.h +3 -0
- package/src/ios/NfcPlugin.m +92 -2
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "community-cordova-plugin-nfc",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.7.0",
|
|
4
4
|
"description": "Community Cordova NFC Plugin - Read and write NDEF messages, advanced tag analysis, raw memory access",
|
|
5
5
|
"main": "./types/index.d.ts",
|
|
6
6
|
"types": "./types/index.d.ts",
|
package/plugin.xml
CHANGED
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
xmlns="http://apache.org/cordova/ns/plugins/1.0"
|
|
8
8
|
xmlns:android="http://schemas.android.com/apk/res/android"
|
|
9
9
|
id="community-cordova-plugin-nfc"
|
|
10
|
-
version="1.
|
|
10
|
+
version="1.7.0">
|
|
11
11
|
|
|
12
12
|
<name>NFC</name>
|
|
13
13
|
<description>Community Cordova NFC Plugin - Read and write NDEF messages, advanced tag analysis, raw memory access</description>
|
package/src/ios/NfcPlugin.h
CHANGED
|
@@ -32,6 +32,9 @@
|
|
|
32
32
|
- (void)enabled:(CDVInvokedUrlCommand *)command;
|
|
33
33
|
- (void)writeTag:(CDVInvokedUrlCommand *)command;
|
|
34
34
|
|
|
35
|
+
// ISO 7816 APDU exchange (added v1.7.0) - mirrors Android nfc.transceive
|
|
36
|
+
- (void)transceive:(CDVInvokedUrlCommand *)command;
|
|
37
|
+
|
|
35
38
|
// Internal implementation
|
|
36
39
|
- (void)channel:(CDVInvokedUrlCommand *)command;
|
|
37
40
|
|
package/src/ios/NfcPlugin.m
CHANGED
|
@@ -12,6 +12,9 @@
|
|
|
12
12
|
NSString* channelCallbackId;
|
|
13
13
|
id<NFCNDEFTag> connectedTag API_AVAILABLE(ios(13.0));
|
|
14
14
|
NFCNDEFStatus connectedTagStatus API_AVAILABLE(ios(13.0));
|
|
15
|
+
// Held when an ISO 7816 tag is connected and keepSessionOpen=YES so that
|
|
16
|
+
// subsequent JS calls to nfc.transceive() can exchange APDUs. (v1.7.0)
|
|
17
|
+
id<NFCISO7816Tag> connectedISO7816Tag API_AVAILABLE(ios(13.0));
|
|
15
18
|
}
|
|
16
19
|
@property (nonatomic, assign) BOOL writeMode;
|
|
17
20
|
@property (nonatomic, assign) BOOL shouldUseTagReaderSession;
|
|
@@ -154,6 +157,9 @@
|
|
|
154
157
|
}
|
|
155
158
|
connectedTag = NULL;
|
|
156
159
|
connectedTagStatus = NFCNDEFStatusNotSupported;
|
|
160
|
+
if (@available(iOS 13.0, *)) {
|
|
161
|
+
connectedISO7816Tag = NULL;
|
|
162
|
+
}
|
|
157
163
|
CDVPluginResult *pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK];
|
|
158
164
|
[self.commandDelegate sendPluginResult:pluginResult callbackId:command.callbackId];
|
|
159
165
|
}
|
|
@@ -199,6 +205,73 @@
|
|
|
199
205
|
[self.commandDelegate sendPluginResult:pluginResult callbackId:command.callbackId];
|
|
200
206
|
}
|
|
201
207
|
|
|
208
|
+
// nfc.transceive(buffer) — added v1.7.0 to match Android IsoDep.transceive.
|
|
209
|
+
// Requires an ISO 7816-compatible tag detected via scanTag({keepSessionOpen:true}).
|
|
210
|
+
// Resolves with an ArrayBuffer containing the APDU response data with sw1/sw2
|
|
211
|
+
// appended (Android IsoDep semantics).
|
|
212
|
+
- (void)transceive:(CDVInvokedUrlCommand *)command {
|
|
213
|
+
NSLog(@"transceive");
|
|
214
|
+
|
|
215
|
+
if (@available(iOS 13.0, *)) {
|
|
216
|
+
if (self.nfcSession == nil || !self.nfcSession.isReady) {
|
|
217
|
+
CDVPluginResult *pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR messageAsString:@"No active NFC session. Call nfc.scanTag({keepSessionOpen:true}) first."];
|
|
218
|
+
[self.commandDelegate sendPluginResult:pluginResult callbackId:command.callbackId];
|
|
219
|
+
return;
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
if (connectedISO7816Tag == nil) {
|
|
223
|
+
CDVPluginResult *pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR messageAsString:@"No ISO 7816 tag connected. Only ISO 7816-compatible tags support transceive on iOS."];
|
|
224
|
+
[self.commandDelegate sendPluginResult:pluginResult callbackId:command.callbackId];
|
|
225
|
+
return;
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
// Cordova-iOS converts a JS ArrayBuffer argument into an NSData.
|
|
229
|
+
id arg = [command argumentAtIndex:0];
|
|
230
|
+
NSData *apduData = nil;
|
|
231
|
+
if ([arg isKindOfClass:[NSData class]]) {
|
|
232
|
+
apduData = (NSData *)arg;
|
|
233
|
+
} else if ([arg isKindOfClass:[NSArray class]]) {
|
|
234
|
+
// Fallback if a uint8 array was sent instead of an ArrayBuffer.
|
|
235
|
+
apduData = [self uint8ArrayToNSData:(NSArray *)arg];
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
if (apduData == nil || apduData.length < 4) {
|
|
239
|
+
CDVPluginResult *pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR messageAsString:@"Invalid APDU: expected at least 4 bytes (CLA INS P1 P2)."];
|
|
240
|
+
[self.commandDelegate sendPluginResult:pluginResult callbackId:command.callbackId];
|
|
241
|
+
return;
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
NFCISO7816APDU *apdu = [[NFCISO7816APDU alloc] initWithData:apduData];
|
|
245
|
+
if (apdu == nil) {
|
|
246
|
+
CDVPluginResult *pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR messageAsString:@"Invalid APDU encoding."];
|
|
247
|
+
[self.commandDelegate sendPluginResult:pluginResult callbackId:command.callbackId];
|
|
248
|
+
return;
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
NSString *callbackId = [command.callbackId copy];
|
|
252
|
+
|
|
253
|
+
[connectedISO7816Tag sendCommandAPDU:apdu completionHandler:^(NSData * _Nonnull responseData, uint8_t sw1, uint8_t sw2, NSError * _Nullable error) {
|
|
254
|
+
if (error) {
|
|
255
|
+
NSLog(@"transceive error: %@", error);
|
|
256
|
+
CDVPluginResult *pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR messageAsString:error.localizedDescription];
|
|
257
|
+
[self.commandDelegate sendPluginResult:pluginResult callbackId:callbackId];
|
|
258
|
+
return;
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
// Match Android IsoDep.transceive: response data with sw1/sw2 appended.
|
|
262
|
+
NSMutableData *full = [NSMutableData dataWithData:responseData ?: [NSData data]];
|
|
263
|
+
[full appendBytes:&sw1 length:1];
|
|
264
|
+
[full appendBytes:&sw2 length:1];
|
|
265
|
+
|
|
266
|
+
CDVPluginResult *pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsArrayBuffer:full];
|
|
267
|
+
[self.commandDelegate sendPluginResult:pluginResult callbackId:callbackId];
|
|
268
|
+
}];
|
|
269
|
+
} else {
|
|
270
|
+
CDVPluginResult *pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR messageAsString:@"transceive requires iOS 13 or later."];
|
|
271
|
+
[self.commandDelegate sendPluginResult:pluginResult callbackId:command.callbackId];
|
|
272
|
+
}
|
|
273
|
+
}
|
|
274
|
+
|
|
202
275
|
#pragma mark - NFCNDEFReaderSessionDelegate
|
|
203
276
|
|
|
204
277
|
// iOS 11 & 12
|
|
@@ -274,7 +347,7 @@
|
|
|
274
347
|
id<NFCTag> tag = [tags firstObject];
|
|
275
348
|
NSMutableDictionary *tagMetaData = [self getTagInfo:tag];
|
|
276
349
|
id<NFCNDEFTag> ndefTag = (id<NFCNDEFTag>)tag;
|
|
277
|
-
|
|
350
|
+
|
|
278
351
|
[session connectToTag:tag completionHandler:^(NSError * _Nullable error) {
|
|
279
352
|
if (error) {
|
|
280
353
|
NSLog(@"%@", error);
|
|
@@ -282,6 +355,17 @@
|
|
|
282
355
|
return;
|
|
283
356
|
}
|
|
284
357
|
|
|
358
|
+
// ISO 7816 + keepSessionOpen path (v1.7.0): hold the tag for subsequent
|
|
359
|
+
// nfc.transceive() APDU exchanges. Skip the NDEF path entirely since
|
|
360
|
+
// ISO 7816 tags (gov ID, banking, health) are typically non-NDEF and
|
|
361
|
+
// processNDEFTag would close the session on NFCNDEFStatusNotSupported.
|
|
362
|
+
if (tag.type == NFCTagTypeISO7816Compatible && self.keepSessionOpen) {
|
|
363
|
+
self->connectedISO7816Tag = [tag asNFCISO7816Tag];
|
|
364
|
+
session.alertMessage = [self localizeString:@"NFCTagRead" defaultValue:@"Tag successfully read."];
|
|
365
|
+
[self fireTagEvent:tagMetaData];
|
|
366
|
+
return;
|
|
367
|
+
}
|
|
368
|
+
|
|
285
369
|
[self processNDEFTag:session tag:ndefTag metaData:tagMetaData];
|
|
286
370
|
}];
|
|
287
371
|
}
|
|
@@ -494,6 +578,9 @@
|
|
|
494
578
|
sessionCallbackId = NULL;
|
|
495
579
|
connectedTag = NULL;
|
|
496
580
|
connectedTagStatus = NFCNDEFStatusNotSupported;
|
|
581
|
+
if (@available(iOS 13.0, *)) {
|
|
582
|
+
connectedISO7816Tag = NULL;
|
|
583
|
+
}
|
|
497
584
|
[session invalidateSession];
|
|
498
585
|
}
|
|
499
586
|
|
|
@@ -504,7 +591,10 @@
|
|
|
504
591
|
sessionCallbackId = NULL;
|
|
505
592
|
connectedTag = NULL;
|
|
506
593
|
connectedTagStatus = NFCNDEFStatusNotSupported;
|
|
507
|
-
|
|
594
|
+
if (@available(iOS 13.0, *)) {
|
|
595
|
+
connectedISO7816Tag = NULL;
|
|
596
|
+
}
|
|
597
|
+
|
|
508
598
|
if (@available(iOS 13.0, *)) {
|
|
509
599
|
[session invalidateSessionWithErrorMessage:errorMessage];
|
|
510
600
|
} else {
|