IDTech iOS Framework Guide  1.1.088
API reference for UniPay
Sample Project Tutorial

Using Xcode 5.0+, we will create a sample project that will interface with the UniPay and will perform the following activities:

  • Report Firmware
  • Report connected/disconnected
  • Turn on/off MSR reader and perform a card capture

Protocol Delegates:

  • Protocol to report unsolicited card swipes
  • Protocol to report device connected
  • Protocol to report device disconnected

Step 1: Create New Project

Create a new Single View Application in Xcode

new_project1.png
new_project2.png

Step 2: Import Frameworks

Import the necessary framework/libraries

Step 3: Design Interface

Design the User Interface by editing the iPhone storyboard file
Open your storyboard and add items to so it contains the following buttons/fields:

  • Add a label to the top that will signify connection/disconnection status.
  • Add a text view to communicate data from the UniPay. Remove the Editable behavior if you don't want the keyboard to pop up if you accidentally select it.
  • Add buttons to execute the following functions:
    • Get Firmware
    • Start Swipe
    • Cancel Swipe
xib_up.png

Step 5: Configure Header File

In the header file, perform the following:

  • Add Import statements to utilize frameworks
  • Amend the view controller interface
  • Create an IBOutlet for the UITextView and link it as a Referencing Outlet to the UITextView on the storyboard
  • Create an IBOutlet for the UILabel and link it as a Referencing Outlet to the UILabel on the storyboard
  • Create the 3 IBAction for the buttons, and link them to the "Touch Up Inside" event on the storyboard buttons
#import <UIKit/UIKit.h>
#import <IDTech/IDTech.h>
@interface ViewController : UIViewController <IDT_UniPay_Delegate>{
IBOutlet UITextView *tv;
IBOutlet UILabel *connectedLabel;
}
-(IBAction) msrON:(id)sender;
-(IBAction) msrOff:(id)sender;
-(IBAction) getFirmware:(id)sender;
@end

Storyboard Source Code

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="6250" systemVersion="14A389" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" initialViewController="vXZ-lx-hvc">
<dependencies>
<deployment identifier="iOS"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="6244"/>
<capability name="Alignment constraints with different attributes" minToolsVersion="5.1"/>
<capability name="Constraints to layout margins" minToolsVersion="6.0"/>
</dependencies>
<scenes>
<!--View Controller-->
<scene sceneID="ufC-wZ-h7g">
<objects>
<viewController id="vXZ-lx-hvc" customClass="ViewController" sceneMemberID="viewController">
<layoutGuides>
<viewControllerLayoutGuide type="top" id="jyV-Pf-zRb"/>
<viewControllerLayoutGuide type="bottom" id="2fi-mo-0CV"/>
</layoutGuides>
<view key="view" contentMode="scaleToFill" id="kh9-bI-dsS">
<rect key="frame" x="0.0" y="0.0" width="600" height="600"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
<subviews>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="UNIPAY DISCONNECTED" textAlignment="center" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="i1O-SW-UeA">
<rect key="frame" x="0.0" y="-21" width="42" height="21"/>
<color key="backgroundColor" white="0.0" alpha="1" colorSpace="calibratedWhite"/>
<fontDescription key="fontDescription" type="system" pointSize="13"/>
<color key="textColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
<nil key="highlightedColor"/>
</label>
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="g4D-Lo-gdS">
<rect key="frame" x="-23" y="-15" width="46" height="30"/>
<constraints>
<constraint firstAttribute="height" constant="30" id="L4N-Q3-gDw"/>
</constraints>
<state key="normal" title="Get Firmware">
<color key="titleShadowColor" white="0.5" alpha="1" colorSpace="calibratedWhite"/>
</state>
<variation key="default">
<mask key="constraints">
<exclude reference="L4N-Q3-gDw"/>
</mask>
</variation>
<variation key="widthClass=compact">
<mask key="constraints">
<include reference="L4N-Q3-gDw"/>
</mask>
</variation>
<connections>
<action selector="getFirmware:" destination="vXZ-lx-hvc" eventType="touchUpInside" id="LRv-H3-uBz"/>
</connections>
</button>
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="qJM-Uo-OAl">
<rect key="frame" x="-23" y="-15" width="46" height="30"/>
<constraints>
<constraint firstAttribute="height" constant="30" id="mjm-6i-7SI"/>
</constraints>
<state key="normal" title="Start Swipe">
<color key="titleShadowColor" white="0.5" alpha="1" colorSpace="calibratedWhite"/>
</state>
<variation key="default">
<mask key="constraints">
<exclude reference="mjm-6i-7SI"/>
</mask>
</variation>
<variation key="widthClass=compact">
<mask key="constraints">
<include reference="mjm-6i-7SI"/>
</mask>
</variation>
<connections>
<action selector="msrON:" destination="vXZ-lx-hvc" eventType="touchUpInside" id="6sg-MT-Toy"/>
</connections>
</button>
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="e9C-sp-2x2">
<rect key="frame" x="-23" y="-15" width="46" height="30"/>
<constraints>
<constraint firstAttribute="height" constant="30" id="GEC-7y-53r"/>
</constraints>
<state key="normal" title="Cancel Swipe">
<color key="titleShadowColor" white="0.5" alpha="1" colorSpace="calibratedWhite"/>
</state>
<variation key="default">
<mask key="constraints">
<exclude reference="GEC-7y-53r"/>
</mask>
</variation>
<variation key="widthClass=compact">
<mask key="constraints">
<include reference="GEC-7y-53r"/>
</mask>
</variation>
<connections>
<action selector="msrOff:" destination="vXZ-lx-hvc" eventType="touchUpInside" id="kCd-Zc-dgc"/>
</connections>
</button>
<textView clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="scaleToFill" editable="NO" translatesAutoresizingMaskIntoConstraints="NO" id="cOU-wT-aWM">
<rect key="frame" x="0.0" y="0.0" width="240" height="128"/>
<color key="backgroundColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
<fontDescription key="fontDescription" type="system" pointSize="14"/>
<textInputTraits key="textInputTraits" autocapitalizationType="sentences"/>
</textView>
</subviews>
<color key="backgroundColor" red="0.7662318441" green="0.94110946179999999" blue="0.96664826770000001" alpha="1" colorSpace="calibratedRGB"/>
<constraints>
<constraint firstItem="g4D-Lo-gdS" firstAttribute="top" secondItem="i1O-SW-UeA" secondAttribute="bottom" constant="8" id="4JI-80-Dtl"/>
<constraint firstItem="e9C-sp-2x2" firstAttribute="leading" secondItem="kh9-bI-dsS" secondAttribute="leadingMargin" id="4ql-n9-Mob"/>
<constraint firstItem="cOU-wT-aWM" firstAttribute="leading" secondItem="kh9-bI-dsS" secondAttribute="leadingMargin" id="DkE-hg-tZJ"/>
<constraint firstItem="qJM-Uo-OAl" firstAttribute="trailing" secondItem="kh9-bI-dsS" secondAttribute="trailingMargin" id="Gei-Yo-Nnl"/>
<constraint firstItem="qJM-Uo-OAl" firstAttribute="leading" secondItem="kh9-bI-dsS" secondAttribute="leadingMargin" id="MiH-76-1tD"/>
<constraint firstItem="g4D-Lo-gdS" firstAttribute="trailing" secondItem="kh9-bI-dsS" secondAttribute="trailingMargin" id="atl-BT-IkW"/>
<constraint firstItem="cOU-wT-aWM" firstAttribute="top" secondItem="e9C-sp-2x2" secondAttribute="bottom" constant="122" id="bUd-oq-RSO"/>
<constraint firstItem="e9C-sp-2x2" firstAttribute="trailing" secondItem="kh9-bI-dsS" secondAttribute="trailingMargin" id="dsT-QT-3pX"/>
<constraint firstItem="i1O-SW-UeA" firstAttribute="leading" secondItem="kh9-bI-dsS" secondAttribute="leadingMargin" id="fvJ-Jb-F4D"/>
<constraint firstItem="g4D-Lo-gdS" firstAttribute="leading" secondItem="kh9-bI-dsS" secondAttribute="leadingMargin" id="i8i-vS-GHG"/>
<constraint firstItem="cOU-wT-aWM" firstAttribute="trailing" secondItem="kh9-bI-dsS" secondAttribute="trailingMargin" id="kTP-Pr-rCR"/>
<constraint firstItem="e9C-sp-2x2" firstAttribute="top" secondItem="qJM-Uo-OAl" secondAttribute="bottom" constant="8" id="lOc-pC-2TS"/>
<constraint firstItem="qJM-Uo-OAl" firstAttribute="top" secondItem="g4D-Lo-gdS" secondAttribute="bottom" constant="8" id="o1P-I3-vHp"/>
<constraint firstItem="i1O-SW-UeA" firstAttribute="top" secondItem="jyV-Pf-zRb" secondAttribute="bottom" id="tmv-so-RdM"/>
<constraint firstItem="2fi-mo-0CV" firstAttribute="top" secondItem="cOU-wT-aWM" secondAttribute="bottom" constant="20" id="wPc-2Y-bol"/>
<constraint firstItem="i1O-SW-UeA" firstAttribute="trailing" secondItem="kh9-bI-dsS" secondAttribute="trailingMargin" id="zKQ-gV-BB6"/>
</constraints>
<variation key="default">
<mask key="subviews">
<exclude reference="i1O-SW-UeA"/>
<exclude reference="g4D-Lo-gdS"/>
<exclude reference="qJM-Uo-OAl"/>
<exclude reference="e9C-sp-2x2"/>
<exclude reference="cOU-wT-aWM"/>
</mask>
<mask key="constraints">
<exclude reference="fvJ-Jb-F4D"/>
<exclude reference="tmv-so-RdM"/>
<exclude reference="zKQ-gV-BB6"/>
<exclude reference="4JI-80-Dtl"/>
<exclude reference="atl-BT-IkW"/>
<exclude reference="i8i-vS-GHG"/>
<exclude reference="Gei-Yo-Nnl"/>
<exclude reference="MiH-76-1tD"/>
<exclude reference="o1P-I3-vHp"/>
<exclude reference="4ql-n9-Mob"/>
<exclude reference="dsT-QT-3pX"/>
<exclude reference="lOc-pC-2TS"/>
<exclude reference="DkE-hg-tZJ"/>
<exclude reference="bUd-oq-RSO"/>
<exclude reference="kTP-Pr-rCR"/>
<exclude reference="wPc-2Y-bol"/>
</mask>
</variation>
<variation key="widthClass=compact">
<mask key="subviews">
<include reference="i1O-SW-UeA"/>
<include reference="g4D-Lo-gdS"/>
<include reference="qJM-Uo-OAl"/>
<include reference="e9C-sp-2x2"/>
<include reference="cOU-wT-aWM"/>
</mask>
<mask key="constraints">
<include reference="fvJ-Jb-F4D"/>
<include reference="tmv-so-RdM"/>
<include reference="zKQ-gV-BB6"/>
<include reference="4JI-80-Dtl"/>
<include reference="atl-BT-IkW"/>
<include reference="i8i-vS-GHG"/>
<include reference="Gei-Yo-Nnl"/>
<include reference="MiH-76-1tD"/>
<include reference="o1P-I3-vHp"/>
<include reference="4ql-n9-Mob"/>
<include reference="dsT-QT-3pX"/>
<include reference="lOc-pC-2TS"/>
<include reference="DkE-hg-tZJ"/>
<include reference="bUd-oq-RSO"/>
<include reference="kTP-Pr-rCR"/>
<include reference="wPc-2Y-bol"/>
</mask>
</variation>
</view>
<connections>
<outlet property="connectedLabel" destination="i1O-SW-UeA" id="aq7-Us-Fcj"/>
<outlet property="tv" destination="cOU-wT-aWM" id="5kv-jl-7Yp"/>
</connections>
</viewController>
<placeholder placeholderIdentifier="IBFirstResponder" id="x5A-6p-PRh" sceneMemberID="firstResponder"/>
</objects>
<point key="canvasLocation" x="205.5" y="385"/>
</scene>
</scenes>
</document>

Step 6: Configure Method File

In the header file, perform the following:

  • set delegate and initialize IDT_UniPay singleton object in the viewDidLoad method. Reference: Call the Singleton instance of the IDT_UniPay framework object
    - (void)viewDidLoad
    {
    [super viewDidLoad];
    // Do any additional setup after loading the view, typically from a nib.
    [[IDT_UniPay sharedController] setDelegate:self];
    }
  • Implement protocol delegate IDT_UniPayDelegate::deviceDisconnected() and IDT_UniPayDelegate::deviceConnected() to monitor connect/disconnect events and modify our connection label upon change. Reference: Implement optional delegate protocols
    -(void)deviceConnected{
    connectedLabel.text = @"UNIPAY CONNECTED";
    }
    -(void)deviceDisconnected{
    connectedLabel.text = @"UNIPAY DISCONNECTED";
    }
  • Implement protocol delegate plugStatusChanged:() to automatically connect to UniPay when a device is inserted
    - (void) plugStatusChange:(BOOL)deviceInserted{
    if (deviceInserted) {
    [self appendMessageToResults: @"device Attached."];
    [self appendMessageToResults: @"Start Connect Task..."];
    [[IDT_UniPay sharedController] device_connectToAudioReader];
    }
    else{
    [self appendMessageToResults: @"device removed."];
    }
    }
  • Implement protocol delegate swipeMSRData:() to receive unsolicited card swipe data. Reference: Implement optional delegate protocols
    -(void) appendMessageToResults:(NSString*) message{
    [tv setText:[NSString stringWithFormat:@"%@\n%@", tv.text, message]];
    [tv scrollRangeToVisible:NSMakeRange([tv.text length], 0)];
    }
    - (void) swipeMSRData:(IDTMSRData*)cardData{
    NSLog(@"--MSR event Received, Type: %d, data: %@", cardData.event, cardData.encTrack1);
    switch (cardData.event) {
    case EVENT_MSR_CARD_DATA:
    {
    switch (cardData.captureEncodeType) {
    case CAPTURE_ENCODE_TYPE_ISOABA:
    [self appendMessageToResults:[NSString stringWithFormat:@"Encryption Type: %@", @"ISO/ABA"]];
    break;
    case CAPTURE_ENCODE_TYPE_AAMVA:
    [self appendMessageToResults:[NSString stringWithFormat:@"Encryption Type: %@", @"AA/MVA"]];
    break;
    case CAPTURE_ENCODE_TYPE_Other:
    [self appendMessageToResults:[NSString stringWithFormat:@"Encryption Type: %@", @"Other"]];
    break;
    case CAPTURE_ENCODE_TYPE_Raw:
    [self appendMessageToResults:[NSString stringWithFormat:@"Encryption Type: %@", @"Raw"]];
    break;
    default:
    [self appendMessageToResults:[NSString stringWithFormat:@"Encryption Type: %@", @"UNKNOWN"]];
    break;
    }
    [self appendMessageToResults:[NSString stringWithFormat:@"Full card data: %@", cardData.cardData]];
    [self appendMessageToResults:[NSString stringWithFormat:@"Track 1: %@", cardData.track1]];
    [self appendMessageToResults:[NSString stringWithFormat:@"Track 2: %@", cardData.track2]];
    [self appendMessageToResults:[NSString stringWithFormat:@"Track 3: %@", cardData.track3]];
    [self appendMessageToResults:[NSString stringWithFormat:@"Length Track 1: %i", cardData.track1Length]];
    [self appendMessageToResults:[NSString stringWithFormat:@"Length Track 2: %i", cardData.track2Length]];
    [self appendMessageToResults:[NSString stringWithFormat:@"Length Track 3: %i", cardData.track3Length]];
    [self appendMessageToResults:[NSString stringWithFormat:@"Encoded Track 1: %@", cardData.encTrack1.description]];
    [self appendMessageToResults:[NSString stringWithFormat:@"Encoded Track 2: %@", cardData.encTrack2.description]];
    [self appendMessageToResults:[NSString stringWithFormat:@"Encoded Track 3: %@", cardData.encTrack3.description]];
    [self appendMessageToResults:[NSString stringWithFormat:@"Hash Track 1: %@", cardData.hashTrack1.description]];
    [self appendMessageToResults:[NSString stringWithFormat:@"Hash Track 2: %@", cardData.hashTrack2.description]];
    [self appendMessageToResults:[NSString stringWithFormat:@"Hash Track 3: %@", cardData.hashTrack3.description]];
    [self appendMessageToResults:[NSString stringWithFormat:@"KSN: %@", cardData.KSN.description]];
    [self appendMessageToResults:[NSString stringWithFormat:@"\nSessionID: %@", cardData.sessionID.description]];
    [self appendMessageToResults:[NSString stringWithFormat:@"\nReader Serial Number: %@", cardData.RSN]];
    [self appendMessageToResults:[NSString stringWithFormat:@"\nRead Status: %2X", cardData.readStatus]];
    NSLog(@"Track 1: %@", cardData.track1);
    NSLog(@"Track 2: %@", cardData.track2);
    NSLog(@"Track 3: %@", cardData.track3);
    NSLog(@"Encoded Track 1: %@", cardData.encTrack1.description);
    NSLog(@"Encoded Track 2: %@", cardData.encTrack2.description);
    NSLog(@"Encoded Track 3: %@", cardData.encTrack3.description);
    NSLog(@"Hash Track 1: %@", cardData.hashTrack1.description);
    NSLog(@"Hash Track 2: %@", cardData.hashTrack2.description);
    NSLog(@"Hash Track 3: %@", cardData.hashTrack3.description);
    NSLog(@"SessionID: %@", cardData.sessionID.description);
    NSLog(@"nReader Serial Number: %@", cardData.RSN);
    NSLog(@"Read Status: %2X", cardData.readStatus);
    NSLog(@"KSN: %@", cardData.KSN.description);
    return;
    }
    break;
    case EVENT_MSR_CANCEL_KEY:
    {
    [self appendMessageToResults:[NSString stringWithFormat:@"(Event) MSR Cancel Key received: %@", cardData.encTrack1]];
    return;
    }
    break;
    case EVENT_MSR_BACKSPACE_KEY:
    {
    [self appendMessageToResults:[NSString stringWithFormat:@"(Event) MSR Backspace Key received: %@", cardData.encTrack1]];
    return;
    }
    break;
    case EVENT_MSR_ENTER_KEY:
    {
    [self appendMessageToResults:[NSString stringWithFormat:@"(Event) MSR Enter Key received: %@", cardData.encTrack1]];
    return;
    }
    break;
    case EVENT_MSR_UNKNOWN:
    {
    [self appendMessageToResults:[NSString stringWithFormat:@"(Event) MSR unknown event, data: %@", cardData.encTrack1]];
    return;
    }
    break;
    default:
    break;
    }
    }
  • Implement the button press methods
    -(IBAction) msrON:(id)sender{
    RETURN_CODE rt = [[IDT_UniPay sharedController] msr_startMSRSwipe:0];
    if(RETURN_CODE_DO_SUCCESS == rt){
    [self appendMessageToResults:@"EnableMSR: OK."];
    }else
    {
    [self appendMessageToResults: @"Enable MSR Failure" ];
    }
    }
    -(IBAction) msrOff:(id)sender{
    RETURN_CODE rt = [[IDT_UniPay sharedController] msr_cancelMSRSwipe];
    if(RETURN_CODE_DO_SUCCESS == rt){
    [self appendMessageToResults:@"DisableMSR: OK."];
    }else
    {
    [self appendMessageToResults: @"Disable MSR Error" ];
    }
    }
    -(IBAction) getFirmware:(id)sender{
    NSString *result;
    RETURN_CODE rt = [[IDT_UniPay sharedController] device_getFirmwareVersion:&result];
    if (RETURN_CODE_DO_SUCCESS == rt)
    {
    [self appendMessageToResults: [NSString stringWithFormat:@"Get FM info: %@", result]];
    }
    else{
    [self appendMessageToResults: @"Get Firmware Error" ];
    }
    }