IDTech Windows SDK Guide  1.1.93.0
API reference for Kiosk III
Sample Project Tutorial

Using Visual Studio 2015, we will create a C# sample project that will interface with the Kiosk III and will perform the following activities:

  • Get firmware version
  • Perform CTLS Transaction
  • Connect to either USB or Serial Versions of KioskIII.
  • Show log of all data going to/from Kiosk III

Step 1: Create New Project

Create a new Blank App (Universal Windows) in Visual Studio. In our example, we use project name KioskIII_Simple_Demo_UWP

new_project_uwp.png

On the following popup, choose the target and minimum versions that your application will support. We have chosen the following for our demo application:

versions_uwp.png

Step 2: Import Libraries

Import the Necessary Libraries

Step 3: Add Device Details

Add Device Details to the Application's Manifest

Step 4: Design Interface

Use the Designer to layout buttons/fields
Open your designer and add items so it contains the following buttons/fields:

  • Radio buttons for USB and COM selection. For COM selection, add a text box to specify COM port.
  • Add buttons to execute the following functions:
    • Get Firmware
    • Start ICC Transaction
    • Cancel ICC Transaction
  • Add a text box to communicate data from the Kiosk III.
  • Add a text box for the log of Kiosk III.
  • Add a text box to display the connection status.


KioskIII_app_uwp.png

Step 5: Configure the Project File

In the start of the class file, perform the following:

  • Add Using Statements to Utilize Library
  • Set callback method and initialize KioskIII singleton object in the class initializer. Reference: Initialize Kiosk III
  • Implement the radio button methods Click handlers to set the proper interface for SDK communications
    private void rbUSB_Click(object sender, RoutedEventArgs e)
    {
    if (rbUSB.IsChecked ?? false)
    {
    Task.Run(() => IDT_KioskIII.useUSB());
    return;
    }
    Int32 portNumber = Convert.ToInt32(tbCOMPort.Text);
    bool isSRED = cbSRED.IsChecked ?? false;
    Task.Run(() => IDT_KioskIII.useSerialPort(portNumber, isSRED));
    }

  • Implement the button methods Click handlers for button press code execution
    private void btnGetFirmwareVersion_Click(object sender, RoutedEventArgs e)
    {
    Task.Run(() =>
    {
    string firmwareVersion = "";
    byte[] reData = { };
    RETURN_CODE rt = IDT_KioskIII.SharedController.device_getFirmwareVersion(ref firmwareVersion);
    if (rt == RETURN_CODE.RETURN_CODE_DO_SUCCESS)
    {
    SetOutputText("Firmware Ver: " + firmwareVersion.Replace("\0", "") + "\r\n");
    System.Diagnostics.Debug.WriteLine("Firmware Ver: " + firmwareVersion);
    }
    else
    {
    SetOutputText("Get Firmware Fail Error Code: " + "0x" + String.Format("{0:X}", (ushort)rt) + ": " + IDTechSDK.errorCode.getErrorString(rt) + "\r\n");
    System.Diagnostics.Debug.WriteLine("Get Firmware Fail Error Code: " + "0x" + String.Format("{0:X}", (ushort)rt));
    }
    });
    }
    private void btnStartCTLSTransaction_Click(object sender, RoutedEventArgs e)
    {
    Task.Run(() =>
    {
    byte[] additionalTags = new byte[] { 0x8E, 0x5A };
    RETURN_CODE rt = IDT_KioskIII.SharedController.ctls_startTransaction(1.00, 0, 2, 0, 30, additionalTags);
    if (rt == RETURN_CODE.RETURN_CODE_DO_SUCCESS)
    {
    SetOutputText("Start CTLS Successful\r\n");
    System.Diagnostics.Debug.WriteLine("Start CTLS Successful");
    }
    else
    {
    SetOutputText("Start CTLS failed Error Code: " + "0x" + String.Format("{0:X}", (ushort)rt) + ": " + IDTechSDK.errorCode.getErrorString(rt) + "\r\n");
    System.Diagnostics.Debug.WriteLine("Start CTLS failed Error Code: " + "0x" + String.Format("{0:X}", (ushort)rt));
    }
    });
    }
    private void btnCancelCTLSTransaction_Click(object sender, RoutedEventArgs e)
    {
    Task.Run(() =>
    {
    RETURN_CODE rt = IDT_KioskIII.SharedController.ctls_cancelTransaction();
    if (rt == RETURN_CODE.RETURN_CODE_DO_SUCCESS)
    {
    SetOutputText("Cancel Transaction Successful\r\n");
    System.Diagnostics.Debug.WriteLine("Cancel Transaction Successful");
    }
    else
    {
    SetOutputText("Cancel Transaction failed Error Code: " + "0x" + String.Format("{0:X}", (ushort)rt) + ": " + IDTechSDK.errorCode.getErrorString(rt) + "\r\n");
    System.Diagnostics.Debug.WriteLine("Cancel Transaction failed Error Code: " + "0x" + String.Format("{0:X}", (ushort)rt));
    }
    });
    }

    Note that all the the click handlers' code are ran asynchronously. At least the device command needs to be executed asynchronously or it will block the UI thread. The UWP API that is used by the IDTechSDK_UWP library for communication with HID devices is asynchronous.

Step 6: Configure Callback

The callback is used to receive important SDK data (messages, log info and transaction results). Reference: Implement the Callback Function

private void MessageCallBack(IDTechSDK.IDT_DEVICE_Types type, DeviceState state, byte[] data, IDTTransactionData cardData, EMV_Callback emvCallback, RETURN_CODE transactionResultCode)
{
switch (state)
{
case DeviceState.ToConnect:
//A connection attempt is starting for IDT_DEVICE_TYPES type
SetOutputText("Callback:ToConnect\n");
break;
case DeviceState.DefaultDeviceTypeChange:
//The SDK is changing the default device to IDT_DEVICE_TYPES type
SetOutputText("Callback:DefaultDeviceTypeChange\n");
break;
case DeviceState.Connected:
//A connection has been made to IDT_DEVICE_TYPES type
SetOutputText("Callback:Connected\n");
connectionStatus.Text = "Kiosk III connected.";
connectionStatus.Background = new SolidColorBrush(Windows.UI.Colors.Green);
break;
case DeviceState.Disconnected:
//A disconnection has occured with IDT_DEVICE_TYPES type
SetOutputText("Callback:Disconnected\n");
connectionStatus.Text = "Kiosk III not connected.";
connectionStatus.Background = new SolidColorBrush(Windows.UI.Colors.Red);
break;
case DeviceState.ConnectionFailed:
//A connection attempt has failed for IDT_DEVICE_TYPES type
SetOutputText("Callback:ConnectionFailed\n");
break;
case DeviceState.TransactionData:
//Transaction data is beign returned in IDTTransactionData cardData
SetOutputText("Callback:TransactionData\n");
displayCardData(cardData);
break;
case DeviceState.DataReceived:
//Low-level data received for IDT_DEVICE_TYPES type
SetOutputTextLog(GetTimestamp() + " IN: " + Common.getHexStringFromBytes(data));
break;
case DeviceState.DataSent:
//Low-level data sent for IDT_DEVICE_TYPES type
SetOutputTextLog(GetTimestamp() + " OUT: " + Common.getHexStringFromBytes(data));
break;
case DeviceState.CommandTimeout:
SetOutputText("Callback:CommandTimeout\n");
//Command timeout has occurred for IDT_DEVICE_TYPES type
break;
case DeviceState.ToSwipe:
//Awaiting a swipe for IDT_DEVICE_TYPES type
SetOutputText("Callback:ToSwipe\n");
break;
case DeviceState.MSRDecodeError:
//Awaiting a swipe for IDT_DEVICE_TYPES type
SetOutputText("Callback:MSRDecodeError\n");
break;
case DeviceState.ToTap:
//Awaiting a contactless tap for IDT_DEVICE_TYPES type
SetOutputText("Callback:ToTap\n");
break;
case DeviceState.SwipeTimeout:
//Waiting for swipe timed out
SetOutputText("Callback:SwipeTimeout\n");
break;
case DeviceState.TransactionCancelled:
//Transaction has been cancelled
SetOutputText("Callback:TransactionCancelled\n");
break;
case DeviceState.DeviceTimeout:
//Waiting for EMV transaction to complete timed out
SetOutputText("Callback:DeviceTimeout\n");
break;
case DeviceState.TransactionFailed:
//Transaction failed to complete
SetOutputText("Callback:TransactionFailed\n");
break;
case DeviceState.EMVCallback:
//Callback during EMV transaction retrieved from EMV_Callback emvCallback
SetOutputText("Callback:EMVCallback\n");
break;
default:
break;
}
}
public static String GetTimestamp()
{
DateTime value = DateTime.Now;
return value.ToString("HH:mm:ss.fff");
}
private void displayCardData(IDTTransactionData cardData)
{
string text = "";
if (cardData.Event == EVENT_TRANSACTION_DATA_Types.EVENT_TRANSACTION_PIN_DATA)
{
SetOutputText("PIN Data received:\r\nKSN: " + cardData.pin_KSN + "\r\nPINBLOCK: " + cardData.pin_pinblock + "\r\n");
return;
}
if (cardData.Event == EVENT_TRANSACTION_DATA_Types.EVENT_TRANSACTION_DATA_CARD_DATA)
{
SetOutputText("Data received: (Length [" + cardData.msr_rawData.Length.ToString() + "])\n" + string.Concat(cardData.msr_rawData.ToArray().Select(b => b.ToString("X2")).ToArray()) + "\r\n");
System.Diagnostics.Debug.WriteLine("Data received: (Length [" + cardData.msr_rawData.Length.ToString() + "])\n" + string.Concat(cardData.msr_rawData.ToArray().Select(b => b.ToString("X2")).ToArray()));
}
if (cardData.device_RSN != null && cardData.device_RSN.Length > 0)
text += "Serial Number: " + cardData.device_RSN + "\r\n";
if (cardData.msr_track1Length > 0)
text += "Track 1: " + cardData.msr_track1 + "\r\n";
if (cardData.msr_encTrack1 != null)
text += "Track 1 Encrypted: " + Common.getHexStringFromBytes(cardData.msr_encTrack1) + "\r\n";
if (cardData.msr_hashTrack1 != null)
text += "Track 1 Hash: " + Common.getHexStringFromBytes(cardData.msr_hashTrack1) + "\r\n";
if (cardData.msr_track2Length > 0)
text += "Track 2: " + cardData.msr_track2 + "\r\n";
if (cardData.msr_encTrack2 != null)
text += "Track 2 Encrypted: " + Common.getHexStringFromBytes(cardData.msr_encTrack2) + "\r\n";
if (cardData.msr_hashTrack2 != null)
text += "Track 2 Hash: " + Common.getHexStringFromBytes(cardData.msr_hashTrack2) + "\r\n";
if (cardData.msr_track3Length > 0)
text += "Track 3: " + cardData.msr_track3 + "\r\n";
if (cardData.msr_encTrack3 != null)
text += "Track 3 Encrypted: " + Common.getHexStringFromBytes(cardData.msr_encTrack3) + "\r\n";
if (cardData.msr_hashTrack3 != null)
text += "Track 3 Hash: " + Common.getHexStringFromBytes(cardData.msr_hashTrack3) + "\r\n";
if (cardData.msr_KSN != null)
text += "KSN: " + Common.getHexStringFromBytes(cardData.msr_KSN) + "\r\n";
if (cardData.emv_clearingRecord != null)
{
if (cardData.emv_clearingRecord.Length > 0)
{
text += "\r\nCTLS Clearing Record: \r\n";
text += Common.getHexStringFromBytes(cardData.emv_clearingRecord) + "\r\n";
Dictionary<string, string> dict = Common.processTLVUnencrypted(cardData.emv_clearingRecord);
foreach (KeyValuePair<string, string> kvp in dict) text += kvp.Key + ": " + kvp.Value + "\r\n";
text += "\r\n\r\n";
}
}
if (cardData.emv_unencryptedTags != null)
{
if (cardData.emv_unencryptedTags.Length > 0)
{
text += "\r\n======================== \r\n";
text += "\r\nUnencrypted Tags: \r\n";
text += Common.getHexStringFromBytes(cardData.emv_unencryptedTags) + "\r\n\r\n";
text += tlvToValues(cardData.emv_unencryptedTags);
text += "\r\n======================== \r\n";
}
}
if (cardData.emv_encryptedTags != null)
{
if (cardData.emv_encryptedTags.Length > 0)
{
text += "\r\n======================== \r\n";
text += "\r\nEncrypted Tags: \r\n";
text += Common.getHexStringFromBytes(cardData.emv_encryptedTags) + "\r\n\r\n";
text += tlvToValues(cardData.emv_encryptedTags);
text += "\r\n======================== \r\n";
}
}
if (cardData.emv_maskedTags != null)
{
if (cardData.emv_maskedTags.Length > 0)
{
text += "\r\n======================== \r\n";
text += "\r\nMasked Tags: \r\n";
text += Common.getHexStringFromBytes(cardData.emv_maskedTags) + "\r\n\r\n";
text += tlvToValues(cardData.emv_maskedTags);
text += "\r\n======================== \r\n";
}
}
text += "ICC Present: ";
text += (cardData.iccPresent == 1 ? "TRUE" : "FALSE") + "\r\n";
text += "is CTLS: ";
text += (cardData.isCTLS == 1 ? "TRUE" : "FALSE") + "\r\n";
if (cardData.Event == EVENT_TRANSACTION_DATA_Types.EVENT_TRANSACTION_DATA_EMV_DATA)
{
if (cardData.isCTLS == 2) text += "Capture Encrypt Type: " + ((cardData.emv_encryptionMode == EMV_ENCRYPTION_MODE.EMV_ENCRYPTION_MODE_TDES) ? "TDES" : "AES") + "\r\n";
switch (cardData.emv_resultCode)
{
case EMV_RESULT_CODE.EMV_RESULT_CODE_APPROVED:
text += ("EMV RESULT: " + "EMV_RESULT_CODE_APPROVED" + "\r\n");
break;
case EMV_RESULT_CODE.EMV_RESULT_CODE_APPROVED_OFFLINE:
text += ("EMV RESULT: " + "EMV_RESULT_CODE_APPROVED_OFFLINE" + "\r\n");
break;
case EMV_RESULT_CODE.EMV_RESULT_CODE_DECLINED_OFFLINE:
text += ("EMV RESULT: " + "EMV_RESULT_CODE_DECLINED_OFFLINE" + "\r\n");
break;
case EMV_RESULT_CODE.EMV_RESULT_CODE_DECLINED:
text += ("EMV RESULT: " + "EMV_RESULT_CODE_DECLINED" + "\r\n");
break;
case EMV_RESULT_CODE.EMV_RESULT_CODE_GO_ONLINE:
text += ("EMV RESULT: " + "EMV_RESULT_CODE_GO_ONLINE" + "\r\n");
break;
case EMV_RESULT_CODE.EMV_RESULT_CODE_CALL_YOUR_BANK:
text += ("EMV RESULT: " + "EMV_RESULT_CODE_CALL_YOUR_BANK" + "\r\n");
break;
case EMV_RESULT_CODE.EMV_RESULT_CODE_NOT_ACCEPTED:
text += ("EMV RESULT: " + "EMV_RESULT_CODE_NOT_ACCEPTED" + "\r\n");
break;
case EMV_RESULT_CODE.EMV_RESULT_CODE_FALLBACK_TO_MSR:
text += ("EMV RESULT: " + "EMV_RESULT_CODE_FALLBACK_TO_MSR" + "\r\n");
break;
case EMV_RESULT_CODE.EMV_RESULT_CODE_TIMEOUT:
text += ("EMV RESULT: " + "EMV_RESULT_CODE_TIMEOUT" + "\r\n");
break;
case EMV_RESULT_CODE.EMV_RESULT_CODE_AUTHENTICATE_TRANSACTION:
text += ("EMV RESULT: " + "EMV_RESULT_CODE_AUTHENTICATE_TRANSACTION" + "\r\n");
break;
case EMV_RESULT_CODE.EMV_RESULT_CODE_SWIPE_NON_ICC:
text += ("EMV RESULT: " + "EMV_RESULT_CODE_SWIPE_NON_ICC" + "\r\n");
break;
case EMV_RESULT_CODE.EMV_RESULT_CODE_CTLS_TWO_CARDS:
text += ("EMV RESULT: " + "EMV_RESULT_CODE_CTLS_TWO_CARDS" + "\r\n");
break;
case EMV_RESULT_CODE.EMV_RESULT_CODE_CTLS_TERMINATE:
text += ("EMV RESULT: " + "EMV_RESULT_CODE_CTLS_TERMINATE" + "\r\n");
break;
case EMV_RESULT_CODE.EMV_RESULT_CODE_CTLS_TERMINATE_TRY_ANOTHER:
text += ("EMV RESULT: " + "EMV_RESULT_CODE_CTLS_TERMINATE_TRY_ANOTHER" + "\r\n");
break;
}
}
SetOutputText(text);
}
private string tlvToValues(byte[] tlv)
{
string text = "";
Dictionary<string, string> dict = Common.processTLVUnencrypted(tlv);
foreach (KeyValuePair<string, string> kvp in dict) text += kvp.Key + ": " + kvp.Value + "\r\n";
return text;
}
delegate void SetTextCallback(string text);
private async void SetOutputText(string text)
{
await Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, () =>
{
tbOutput.Text = text + "\r\n" + tbOutput.Text;
});
}
private void SetOutputTextLog(string text)
{
logOutput.Text = text + "\r\n" + logOutput.Text;
}