{"id":16854392,"url":"https://github.com/tomkp/smartcard","last_synced_at":"2025-12-28T03:26:46.795Z","repository":{"id":6096148,"uuid":"54770992","full_name":"tomkp/smartcard","owner":"tomkp","description":"PCSC smartcard reader library for nodejs","archived":false,"fork":false,"pushed_at":"2023-01-07T04:20:40.000Z","size":406,"stargazers_count":137,"open_issues_count":14,"forks_count":57,"subscribers_count":8,"default_branch":"master","last_synced_at":"2025-03-30T15:09:16.353Z","etag":null,"topics":["card-reader","emv","iso7816","nodejs","pcsc","smartcard"],"latest_commit_sha":null,"homepage":"","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/tomkp.png","metadata":{"files":{"readme":"README.MD","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2016-03-26T08:57:38.000Z","updated_at":"2025-02-10T06:51:22.000Z","dependencies_parsed_at":"2023-01-13T13:50:10.110Z","dependency_job_id":null,"html_url":"https://github.com/tomkp/smartcard","commit_stats":null,"previous_names":[],"tags_count":1,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tomkp%2Fsmartcard","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tomkp%2Fsmartcard/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tomkp%2Fsmartcard/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tomkp%2Fsmartcard/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/tomkp","download_url":"https://codeload.github.com/tomkp/smartcard/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247509238,"owners_count":20950232,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["card-reader","emv","iso7816","nodejs","pcsc","smartcard"],"created_at":"2024-10-13T13:55:12.545Z","updated_at":"2025-12-28T03:26:46.748Z","avatar_url":"https://github.com/tomkp.png","language":"JavaScript","funding_links":[],"categories":["JavaScript"],"sub_categories":[],"readme":"# smartcard\n\n\nSmartcard library.\n\nThis is a simple wrapper around [Santiago Gimeno's](https://www.npmjs.org/~sgimeno) great [pcsclite](https://github.com/santigimeno/node-pcsclite) library.\n\nUsed by [Card Spy](http://card-spy.surge.sh)\n\n## API\n\nThe following objects are defined by the `smartcard` library, each contains its own set of methods and events.\n\n### Class: Devices\nA general object that provides access to all smartcard related devices.\n\n#### Events\nThe `devices` object emits the following events\n\n##### Event: 'device-activated'\nEmitted when a card reader is attached.\nReturns:\n* `Object`\n  * `Device`\n  * `Array`: List of all devices, returned via `devices.listDevices()`\n\n##### Event: 'device-deactivated'\nEmitted when a card reader is detached.\nReturns:\n* `Object`\n  * `Device`\n  * `Array`: List of all devices, returned via `devices.listDevices()`\n\n##### Event: 'error'\nEmitted when an error occurs\nReturns `Object`:\n* _error_ `Error`\n\n#### Methods\nThe following methods are available within the `devices` class.\n\n##### Constructor\nThe constructor for a devices object takes no arguments,\n```javascript\ndevices = new Devices();\n```\n##### `devices.onActivated()`\nReturns `Promise`\n* Resolves with activation _event_\n\n##### `devices.onDeactivated()`\nReturns `Promise`\n* Resolves with deactivation _event_\n\n##### `devices.listDevices()`\nReturns `Object` a list of the different devices attached, each a `device` object\n\n##### `devices.lookup(name)`\n* _name_ `String`: The text name of a device\n\n* Returns `Device`\n\n\n\n### Class: Device\nAn object representing a specific card reader (device).\n\n#### Methods\nThe following methods are available within the `device` class.\n\n##### `device.getName()`\nReturns the name of the attached device.\n\n##### `device.transmit(data, res_len, protocol, cb)`\nSends a command to the connected device\n* _data_ `Buffer`: data to be transmitted\n* _res_len_ `Number`: Maximum length of the expected response, includes the 2 byte response (sw1 and sw2)\n* _protocol_ `Number`: Protocol to be used in the transmission\n* _cb(error,response)_ `Function`: Called when transmit function completes\n  * _error_ `Error`\n  * _output_ `Buffer`\n\n#### Events\nThe `device` object emits the following events\n\n##### Event: 'card-inserted'\nEmitted when a smartcard is inserted into a card reader\n\nReturns `Object`:\n* _device_ `Device`\n* _card_ `Card`\n\n##### Event: 'card-removed'\nEmitted when a smartcard is removed from a card reader\n\nReturns `Object`:\n* _name_ `String`\n* _card_ `Card`\n\n### Class: Card\nAn object representing an attached smart card.\n\n#### Methods\nThe following methods are available within the `card` class.\n\n##### `card.getAtr()`\nReturns `String` containing the atr of the card\n\n##### `card.issueCommand(commandApdu, callback)`\nSends a command to the card\n* _commandApdu_: The command to be sent to the card\n  * `String`\n  * `Buffer`\n  * `Array`\n  * `CommandApdu`\n* _callback(error,response)_: (optional) Function to call upon completion of the command\n  * _error_ `Error`\n  * _response_ `Buffer`\n\nReturns `Promise`\n  * Resolves with _response_ `Buffer`\n  * Rejects with _error_ `Error`\n\nIf no callback is specified, returns a `Promise`\n*\n#### Events\nThe `card` object emits the following events\n\n##### Event: 'command-issued'\nEmitted when a command is sent to the smartcard.\n\nReturns `Object`:\n* _card_ `Card`\n* _command_ `Buffer`\n\n##### Event: 'response-received'\nEmitted when a response is received from the card.\n\nReturns `Object`:\n* _card_ `Card`\n* _command_ `Buffer`\n* _response_ `ResponseApdu`\n\n### Class: CommandApdu\nAn object representing a command to send to a smart card\n\n#### Methods\nThe `CommandApdu` class has the following methods.\n\n##### Constructor `CommandApdu(obj)`\nCreates a new instance and sets the appropriate items\n* _obj_ `Object`\n  * _cla_ `Number`: The class of the command, typically 0\n  * _ins_ `Number`: The instruction\n  * _p1_ `Number`: The value of p1\n  * _p2_ `Number`: The value of p2\n  * _data_ `Array` (optional): The value of data\n  * _le_ `Number` (optional): The value of le\n\nOR\n* _obj_ `Array`: Byte array representing the whole command\n\n##### `CommandApdu.toBuffer()`\nConverts the command to a Buffer\n* Returns `Buffer`\n\n##### `CommandApdu.toString()`\nConverts the command to a hex string\n* Returns `String`\n\n##### `CommandApdu.toByteArray()`\nConverts the command to a byte array\n* Returns `Array`\n\n##### `CommandApdu.setLe(le)`\nUpdates the le value of the command\n* _le_ `Number`: The new le value\n\n### Class: ResponseApdu\nClass representing a response from the card\n\n#### Methods\nThe `ResponseApdu` class has the following methods.\n\n##### Constructor\n\n##### `ResponseApdu.meaning()`\nInterprets the return code and attempts to provide a text translation.\n* Returns `String`\n\n##### `ResponseApdu.getDataOnly()`\nReturns the response data without including the status code\n* Returns `String`\n\n##### `ResponseApdu.getStatusCode()`\nReturns only the status code\n* Returns `String`\n\n##### `ResponseApdu.isOk()`\nCheck if the status code is 9000\n* Returns `Boolean`\n\n##### `ResponseApdu.buffer()`\nReturns the whole buffer, status code and data\n* Returns `Buffer`\n\n##### `ResponseApdu.hasMoreBytesAvailable()`\nReads the status code and looks for a 61 as sw1, meaning more data is available\n* Returns `Boolean`\n\n##### `ResponseApdu.numberOfBytesAvailable()`\nReads sw2 staus code to return number of bytes left, when sw1 is 61. A value of 0 means there are more than 256 bytes remaining.\n* Returns `Number`\n\n##### `ResponseApdu.isWrongLength()`\nChecks status code for 6c as sw1\n* Returns `Boolean`\n\n##### `ResponseApdu.correctLength()`\nIf sw1 is 6c, returns the correct length from sw2. A value of 0 means there are more than 256 bytes remaining.\n* Returns `Number`\n\n### Class: Iso7816Application\nAn object offering general commands to most ISO7816 compliant smart cards.\n\n#### Methods\n\n##### Constructor `Iso7816Application(card)`\nSets up the `Iso7816Application` object\n* _card_ `Card`: The card to communicate with using ISO7816 standards\n\n##### `Iso7816Application.issueCommand(commandApdu)`\nSends the provided command to the card. Automatically retrieve the full response, even if it requires multiple GET_RESPONSE commands\n* _commandApdu_ `CommandApdu`: Command to send to the card\n\nReturns\n* `ResponseApdu` Complete response from card\n\n##### `Iso7816Application.selectFile(bytes, p1, p2)`\nSends the SELECT command to the card, often called selecting an application\n* _bytes_ `Buffer`: The resource locater (AID, etc)\n* _p1_ `Number`: Value to specify as the p1 value\n* _p2_ `Number`: Value to specify as the p2 value\n\nReturns\n* `ResponseApdu` Complete response from card\n\n##### `Iso7816Application.getResponse(length)`\nSends a single GET_RESPONSE command to the card\n* _length_ `Number`: The length of the response expected, maximum is 0xFF\n\nReturns\n* `ResponseApdu` Complete response from card\n\n##### `Iso7816Application.getResponse(sfi,record)`\nSends a READ_RECORD command to the card\n* _sfi_ `Number`: The sfi\n* _record_ `Number`: The record\n\nReturns\n* `ResponseApdu` Complete response from card\n\n##### `Iso7816Application.getData(p1, p2)`\nSends a GET_DATA command to the card\n* _p1_ `Number`: Value to specify as the p1 value\n* _p2_ `Number`: Value to specify as the p2 value\n\nReturns\n* `ResponseApdu` Complete response from card\n\n#### Events\nThe `Iso7816Application` class emits the following events\n\n##### Event: 'application-selected'\nEmitted when a successful reply to a `selectFile()` command is received.\n\nReturns `Object`:\n* _application_ `String`\n\n## Examples\n\n\n### With event emitter\n\n```javascript\n'use strict';\n\nconst smartcard = require('smartcard');\nconst Devices = smartcard.Devices;\nconst devices = new Devices();\n\n\ndevices.on('device-activated', (event =\u003e {\n    console.log(`Device '${event.device}' activated`);\n    event.devices.map((device, index) =\u003e {\n        console.log(`Device #${index + 1}: '${device.name}'`);\n    });\n}));\n```\n\n\n### Using promises\n\n```javascript\n'use strict';\n\nconst smartcard = require('smartcard');\nconst Devices = smartcard.Devices;\nconst devices = new Devices();\n\n\ndevices.onActivated().then(event =\u003e {\n    console.log(`Device '${event.device}' activated`);\n    event.devices.map((device, index) =\u003e {\n        console.log(`Device #${index + 1}: '${device.name}'`);\n    });\n});\n```\n\n\n### Selecting the Payment Systems Environment on an EMV (Chip \u0026 Pin) card\n\n\n```javascript\n'use strict';\n\nconst smartcard = require('smartcard');\nconst Devices = smartcard.Devices;\nconst Iso7816Application = smartcard.Iso7816Application;\n\nconst devices = new Devices();\n\ndevices.on('device-activated', event =\u003e {\n    const currentDevices = event.devices;\n    let device = event.device;\n    console.log(`Device '${device}' activated, devices: ${currentDevices}`);\n    for (let prop in currentDevices) {\n        console.log(\"Devices: \" + currentDevices[prop]);\n    }\n\n    device.on('card-inserted', event =\u003e {\n        let card = event.card;\n        console.log(`Card '${card.getAtr()}' inserted into '${event.device}'`);\n\n        card.on('command-issued', event =\u003e {\n            console.log(`Command '${event.command}' issued to '${event.card}' `);\n        });\n\n        card.on('response-received', event =\u003e {\n            console.log(`Response '${event.response}' received from '${event.card}' in response to '${event.command}'`);\n        });\n\n        const application = new Iso7816Application(card);\n        application.selectFile([0x31, 0x50, 0x41, 0x59, 0x2E, 0x53, 0x59, 0x53, 0x2E, 0x44, 0x44, 0x46, 0x30, 0x31])\n            .then(response =\u003e {\n                console.info(`Select PSE Response: '${response}' '${response.meaning()}'`);\n            }).catch(error =\u003e {\n                console.error('Error:', error, error.stack);\n            });\n\n    });\n    device.on('card-removed', event =\u003e {\n        console.log(`Card removed from '${event.name}' `);\n    });\n\n});\n\ndevices.on('device-deactivated', event =\u003e {\n    console.log(`Device '${event.device}' deactivated, devices: [${event.devices}]`);\n});\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftomkp%2Fsmartcard","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ftomkp%2Fsmartcard","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftomkp%2Fsmartcard/lists"}