├── .gitignore
├── LICENSE
├── README.md
├── plugin.xml
├── src
├── android
│ ├── libs
│ │ └── square.jar
│ └── src
│ │ └── com
│ │ └── alignace
│ │ └── cordova
│ │ └── plugin
│ │ └── card
│ │ └── reader
│ │ ├── CardRaderPlugin.java
│ │ └── CardResult.java
└── ios
│ ├── libs
│ └── libiMagRead.a
│ └── src
│ ├── CardRaderPlugin.h
│ ├── CardRaderPlugin.m
│ └── iMagRead.h
└── www
└── CardRaderPlugin.js
/.gitignore:
--------------------------------------------------------------------------------
1 | # Built application files
2 | *.apk
3 | *.ap_
4 |
5 | # Files for the Dalvik VM
6 | *.dex
7 |
8 | # Java class files
9 | *.class
10 |
11 | # Generated files
12 | bin/
13 | gen/
14 |
15 | # Gradle files
16 | .gradle/
17 | build/
18 | /*/build/
19 |
20 | # Local configuration file (sdk path, etc)
21 | local.properties
22 |
23 | # Proguard folder generated by Eclipse
24 | proguard/
25 |
26 | # Log Files
27 | *.log
28 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2015 Alignace LLC
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
23 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # card-reader-phonegap
2 | Cordova plugin for 3.5mm Headphone Jack Mini Magnetic Mobile Card Reader
3 |
4 |
5 | # Getting started
6 |
7 | Install the Plugin and use the following method "cardReaderStart" to start the card reader:
8 |
9 | ```javascript
10 | function cardReaderStart(cardReadSuccess, cardReadFailure){
11 | console.log("Card reader started!");
12 | window.plugins.CardRaderPlugin.start(cardReadSuccess, cardReadFailure);
13 | }
14 |
15 | // If OS is Android
16 | function cardReadSuccess(response){
17 | console.log("Card number:" + response[0].card_number);
18 |
19 | if(typeof response[0].expiry_month != 'undefined' && response[0].expiry_month!=null){
20 | console.log("Expiry month:" + response[0].expiry_month);
21 | }
22 |
23 | if(typeof response[0].expiry_year != 'undefined' && response[0].expiry_year!=null){
24 | console.log("Expiry month:" + response[0].expiry_year);
25 | }
26 | }
27 |
28 | //If OS is iOS
29 | function cardReadSuccess(response){
30 | console.log("Card number:" + response['card_number']);
31 |
32 | if(typeof response[0].expiry_month != 'undefined' && response[0].expiry_month!=null){
33 | console.log("Expiry month:" + response['expiry_month']);
34 | }
35 |
36 | if(typeof response[0].expiry_year != 'undefined' && response[0].expiry_year!=null){
37 | console.log("Expiry month:" + response['expiry_year']);
38 | }
39 | }
40 |
41 | function cardReadFailure(){
42 | console.log('Please try again!');
43 | }
44 |
45 | ```
46 |
47 | To stop the card reading use following code:
48 |
49 | ```javascript
50 | function cardReaderStop(){
51 | console.log("Trying to stop CardReader!");
52 | window.plugins.CardRaderPlugin.stop(function(){
53 | console.log("Card reader stopped!");
54 | }, function(){
55 | console.log("Card reader stop failed!");
56 | });
57 | }
58 |
59 | ```
60 |
--------------------------------------------------------------------------------
/plugin.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 | CardRaderPlugin
7 | Cordova plugin for 3.5mm Headphone Jack Mini Magnetic
8 | Mobile Card Reader
9 |
10 | Magnetic Mobile Card Reader, credit card
11 | Ayajahmed Shaikh
12 | MIT
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
29 |
32 |
33 |
34 |
35 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
--------------------------------------------------------------------------------
/src/android/libs/square.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/alignace/card-reader-phonegap/5d1c2c39bf1ae66b210ccbabee5cb9a28a2e85ce/src/android/libs/square.jar
--------------------------------------------------------------------------------
/src/android/src/com/alignace/cordova/plugin/card/reader/CardRaderPlugin.java:
--------------------------------------------------------------------------------
1 | package com.alignace.cordova.plugin.card.reader;
2 |
3 | import org.apache.cordova.CallbackContext;
4 | import org.apache.cordova.CordovaPlugin;
5 | import org.json.JSONArray;
6 | import org.json.JSONObject;
7 |
8 | import android.util.Log;
9 |
10 | import com.square.MagRead;
11 | import com.square.MagReadListener;
12 |
13 | public class CardRaderPlugin extends CordovaPlugin {
14 |
15 | public static final String TAG = "CardRaderPlugin";
16 | public static final String START = "start";
17 | public static final String STOP = "stop";
18 |
19 | CallbackContext callbackContext;
20 | private MagRead read = null;
21 |
22 | public static JSONArray mCreditcardNumber = null;
23 |
24 | @Override
25 | public boolean execute(String action, JSONArray data,
26 | final CallbackContext callbackContext) {
27 | boolean result = true;
28 | this.callbackContext = callbackContext;
29 |
30 | Log.v(TAG, "execute: action=" + action);
31 |
32 | if (START.equals(action)) {
33 | Log.v(TAG, "Start listening");
34 | read = new MagRead();
35 | read.addListener(new MagReadListener() {
36 |
37 | @Override
38 | public void updateBytes(String bytes) {
39 | try {
40 | Log.v(TAG, "UpdateBytes received" + bytes);
41 | CardResult scanResult = getCardDetails(bytes);
42 | if (scanResult != null) {
43 | JSONObject j = new JSONObject();
44 | j.put("card_number", scanResult.getCardNumber());
45 | j.put("expiry_month", scanResult.getExpiryMonth());
46 | j.put("expiry_year", scanResult.getExpiryYear());
47 | mCreditcardNumber.put(j);
48 | callbackContext.success(mCreditcardNumber);
49 | }else{
50 | Log.e(TAG, "Error reading Card");
51 | }
52 | } catch (Exception e) {
53 | Log.e(TAG, "Error reading Card: " + e.getMessage());
54 | callbackContext.error(e.getMessage());
55 | }
56 | }
57 |
58 | @Override
59 | public void updateBits(String bits) {
60 | Log.v(TAG, "UpdateBits received" + bits);
61 |
62 | }
63 | });
64 | read.start();
65 | } else if (STOP.equals(action)) {
66 | if (read != null) {
67 | read.stop();
68 | }
69 |
70 | callbackContext.success();
71 | } else {
72 | result = false;
73 | }
74 |
75 | return result;
76 |
77 | }
78 |
79 | private CardResult getCardDetails(String bytes) {
80 | CardResult result = null;
81 | try {
82 | StringBuffer cardNumber = new StringBuffer();
83 | int i = 0;
84 |
85 | // Find Card Number
86 | for (i = 1; i < bytes.length(); i++) {
87 | if (bytes.charAt(i) != '=') {
88 | cardNumber.append(bytes.charAt(i));
89 | } else {
90 | i++;
91 | break;
92 | }
93 | }
94 |
95 | // Find expiry Year
96 | StringBuffer expiryYear = new StringBuffer();
97 | expiryYear.append(bytes.charAt(i));
98 | expiryYear.append(bytes.charAt(++i));
99 |
100 | // Find expiry Month
101 | StringBuffer expiryMonth = new StringBuffer();
102 | expiryMonth.append(bytes.charAt(++i));
103 | expiryMonth.append(bytes.charAt(++i));
104 |
105 | result.setCardNumber(cardNumber.toString());
106 | result.setExpiryMonth(Integer.parseInt(expiryMonth.toString()));
107 | result.setExpiryYear(Integer.parseInt(expiryYear.toString()));
108 | } catch (Exception e) {
109 | throw new RuntimeException("Please try again!");
110 | }
111 |
112 | return result;
113 |
114 | }
115 |
116 | }
117 |
--------------------------------------------------------------------------------
/src/android/src/com/alignace/cordova/plugin/card/reader/CardResult.java:
--------------------------------------------------------------------------------
1 | package com.alignace.cordova.plugin.card.reader;
2 |
3 | public class CardResult {
4 |
5 | String cardNumber;
6 | int expiryMonth, expiryYear;
7 |
8 | public String getCardNumber() {
9 | return cardNumber;
10 | }
11 |
12 | public void setCardNumber(String cardNumber) {
13 | this.cardNumber = cardNumber;
14 | }
15 |
16 | public int getExpiryMonth() {
17 | return expiryMonth;
18 | }
19 |
20 | public void setExpiryMonth(int expiryMonth) {
21 | this.expiryMonth = expiryMonth;
22 | }
23 |
24 | public int getExpiryYear() {
25 | return expiryYear;
26 | }
27 |
28 | public void setExpiryYear(int expiryYear) {
29 | this.expiryYear = expiryYear;
30 | }
31 |
32 | public String toString() {
33 | return "Card Number=" + this.cardNumber + " \nExpiry Month="
34 | + this.expiryMonth + " \nExpiry year=" + this.expiryYear;
35 | }
36 |
37 | }
38 |
--------------------------------------------------------------------------------
/src/ios/libs/libiMagRead.a:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/alignace/card-reader-phonegap/5d1c2c39bf1ae66b210ccbabee5cb9a28a2e85ce/src/ios/libs/libiMagRead.a
--------------------------------------------------------------------------------
/src/ios/src/CardRaderPlugin.h:
--------------------------------------------------------------------------------
1 | #import
2 | #import "iMagRead.h"
3 |
4 | @interface ViewController : UIViewController{iMagRead * _reader;}
5 |
6 | @interface CardRaderPlugin : CDVPlugin {
7 | NSString* callbackID;
8 | }
9 |
10 | - (void)execute:(CDVInvokedUrlCommand *) command;
11 | - (void)start:(CDVInvokedUrlCommand *)command;
12 | - (void)stop:(CDVInvokedUrlCommand *)command;
13 |
14 | @end
15 |
--------------------------------------------------------------------------------
/src/ios/src/CardRaderPlugin.m:
--------------------------------------------------------------------------------
1 | #import "CardRaderPlugin.h"
2 |
3 | #pragma mark -
4 |
5 | @interface CardRaderPlugin ()
6 |
7 | @property (nonatomic, copy, readwrite) NSString *callbackID;
8 |
9 | - (void)sendSuccessTo:(NSString *)callbackId withObject:(id)objwithObject;
10 | - (void)sendFailureTo:(NSString *)callbackId;
11 |
12 | @end
13 |
14 | #pragma mark -
15 |
16 | @implementation CardRaderPlugin
17 |
18 |
19 | - (void)execute:(CDVInvokedUrlCommand *)command {
20 | [super viewDidLoad];
21 | _reader = [[iMagRead alloc]init];
22 | [self start:command];
23 | [self stop:command];
24 | }
25 |
26 | - (void)start:(CDVInvokedUrlCommand *)command {
27 | self.scanCallbackId = command.callbackId;
28 | NSDictionary* options = [command.arguments objectAtIndex:0];
29 | NSString * CARREAD_MSG_ByteUpdate = @"CARREAD_MSG_ByteUpdate";
30 | NSString * CARREAD_MSG_BitUpdate = @"CARREAD_MSG_BitUpdate";
31 | NSString * CARREAD_MSG_Err = @"CARREAD_MSG_Err";
32 |
33 | [_reader Start];
34 |
35 | [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(UpdateBytes:) name:CARREAD_MSG_ByteUpdate object:nil];
36 |
37 | [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(UpdateBits:) name:CARREAD_MSG_BitUpdate object:nil];
38 |
39 | [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(UpdateError:) name:CARREAD_MSG_Err object:nil];
40 |
41 | NSMutableDictionary *response = [NSMutableDictionary dictionaryWithObjectsAndKeys:
42 | info.cardNumber, @"card_number",
43 | info.redactedCardNumber, @"redacted_card_number",
44 | [CardIOCreditCardInfo displayStringForCardType:info.cardType
45 | usingLanguageOrLocale:self.paymentViewController.languageOrLocale],
46 | @"card_type",
47 | nil];
48 | if(info.expiryMonth > 0 && info.expiryYear > 0) {
49 | [response setObject:[NSNumber numberWithUnsignedInteger:info.expiryMonth] forKey:@"expiry_month"];
50 | [response setObject:[NSNumber numberWithUnsignedInteger:info.expiryYear] forKey:@"expiry_year"];
51 | }
52 |
53 | [self sendSuccessTo:self.scanCallbackId withObject:response];
54 | }
55 |
56 | - (void)stop:(CDVInvokedUrlCommand *)command {
57 | [_reader Stop];
58 | [self sendSuccessTo:command.callbackId withObject:[NSNumber numberWithBool:TRUE]];
59 | }
60 |
61 | - (void) UpdateBytes:(NSNotification*)aNotification{
62 | NSString* str = [aNotification object];
63 | [self performSelectorOnMainThread:@selector(updateBytCtl:) withObject:str waitUntilDone:YES];
64 | }
65 |
66 | - (void) UpdateBits:(NSNotification*)aNotification{
67 | NSString* str = [aNotification object];
68 | [self performSelectorOnMainThread:@selector(updateBitCtl:) withObject:str waitUntilDone:YES];
69 | }
70 |
71 | - (void) UpdateError:(NSNotification*)aNotification{
72 | NSString* str = [aNotification object];
73 | [self performSelectorOnMainThread:@selector(updateErrorState:) withObject:str waitUntilDone:YES];
74 | }
75 |
76 | - (void) updateErrorState:(NSString*) text{
77 | static bool chang_color =false;
78 | if (chang_color) {
79 | [_errLable setTextColor:[UIColor blueColor]];
80 | chang_color=false;
81 | } else{
82 | [_errLable setTextColor:[UIColor blackColor]];
83 | chang_color=true;
84 | }
85 | if ([text isEqualToString:@"Sucess"]) {
86 | [_errLable setBackgroundColor:[UIColor greenColor]];
87 | } else
88 | {
89 | [_errLable setBackgroundColor:[UIColor redColor]];
90 | }
91 |
92 | [_errLable setText:text];
93 | }
94 |
95 |
96 | #pragma mark - Cordova callback helpers
97 |
98 | - (void)sendSuccessTo:(NSString *)callbackId withObject:(id)obj {
99 | CDVPluginResult *result = nil;
100 |
101 | if([obj isKindOfClass:[NSString class]]) {
102 | result = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsString:obj];
103 | } else if([obj isKindOfClass:[NSDictionary class]]) {
104 | result = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsDictionary:obj];
105 | } else if ([obj isKindOfClass:[NSNumber class]]) {
106 | // all the numbers we return are bools
107 | result = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsInt:[obj intValue]];
108 | } else if(!obj) {
109 | result = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK];
110 | } else {
111 | NSLog(@"Success callback wrapper not yet implemented for class %@", [obj class]);
112 | }
113 |
114 | NSString *responseJavascript = [result toSuccessCallbackString:callbackId];
115 | if(responseJavascript) {
116 | [self writeJavascript:responseJavascript];
117 | }
118 | }
119 |
120 | - (void)sendFailureTo:(NSString *)callbackId {
121 | CDVPluginResult *result = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK];
122 | NSString *responseJavascript = [result toErrorCallbackString:callbackId];
123 | if(responseJavascript) {
124 | [self writeJavascript:responseJavascript];
125 | }
126 | }
127 |
128 | @end
129 |
--------------------------------------------------------------------------------
/src/ios/src/iMagRead.h:
--------------------------------------------------------------------------------
1 | //
2 | // iMagRead.h
3 | // iMagRead
4 | //
5 | // Created by wwq on 13-6-10.
6 | // Copyright (c) 2013年 QunHua. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | extern NSString * CARREAD_MSG_ByteUpdate ; //通知应用更新
12 | extern NSString * CARREAD_MSG_BitUpdate ; //通知应用更新
13 | extern NSString * CARREAD_MSG_Err ;
14 |
15 |
16 | //请将下面的3行放到 m 文件中,并打开注释
17 | //NSString * CARREAD_MSG_ByteUpdate = @"CARREAD_MSG_ByteUpdate";
18 | //NSString * CARREAD_MSG_BitUpdate = @"CARREAD_MSG_BitUpdate";
19 | //NSString * CARREAD_MSG_Err = @"CARREAD_MSG_Err";
20 |
21 |
22 | @interface iMagRead : NSObject
23 |
24 | -(void) Start;
25 | -(void) Stop;
26 | @end
27 |
28 |
--------------------------------------------------------------------------------
/www/CardRaderPlugin.js:
--------------------------------------------------------------------------------
1 | cordova.define("com.alignace.cordova.plugin.card.reader.CardRaderPlugin", function(require, exports, module) { /**
2 | * CardRaderPlugin.js
3 | * Cordova plugin for 3.5mm Headphone Jack Mini Magnetic Mobile Card Reader
4 | * @Copyright 2015 Alignace LLC. http://www.alignace.com
5 | * @author Ayajahmed Shaikh
6 | * @Since 21 April, 2015
7 | */
8 |
9 | var CardRaderPlugin = function() {
10 |
11 | };
12 |
13 | CardRaderPlugin.prototype.start = function(successCallback, errorCallback) {
14 |
15 | if (errorCallback == null) { errorCallback = function() {}}
16 |
17 | if (typeof errorCallback != "function") {
18 | console.log("Start failure: failure parameter not a function");
19 | return
20 | }
21 |
22 | if (typeof successCallback != "function") {
23 | console.log("Start failure failure: success callback parameter must be a function");
24 | return
25 | }
26 | cordova.exec(successCallback, errorCallback, "CardRaderPlugin", "start", []);
27 | };
28 |
29 | CardRaderPlugin.prototype.stop = function(successCallback, errorCallback) {
30 |
31 | if (errorCallback == null) { errorCallback = function() {}}
32 |
33 | if (typeof errorCallback != "function") {
34 | console.log("Stop failure: failure parameter not a function");
35 | return
36 | }
37 |
38 | if (typeof successCallback != "function") {
39 | console.log("Stop failure failure: success callback parameter must be a function");
40 | return
41 | }
42 | cordova.exec(successCallback, errorCallback, "CardRaderPlugin", "stop", []);
43 | };
44 |
45 | //-------------------------------------------------------------------
46 | if(!window.plugins) {
47 | window.plugins = {};
48 | }
49 | if (!window.plugins.CardRaderPlugin) {
50 | window.plugins.CardRaderPlugin = new CardRaderPlugin();
51 | }
52 |
53 | if (typeof module != 'undefined' && module.exports) {
54 | module.exports = CardRaderPlugin;
55 | }
56 |
57 |
58 | //EOF
59 | });
60 |
--------------------------------------------------------------------------------