IDTech iOS SDK Guide  1.1.166.045
API reference for VP3300
EMV PIN Callback

The VP8800 has the ability to interface with external PED (PIN Entry Device). For it to be valid for live transactions, the PED must be paired with the VP8800 using shared keys.

When the kernel encounters a PIN CVM, it will send a request for PIN to the protocol. When properly paired, the kernel will pass the correct key (DUKPT or Session), and information what kind of PIN CVM it is, either Online DUKPT, Online Session, or Offline (DUKPT). It is then expected the PED will securely collect the PIN, and pass it back to the kernel in its encrypted form, including the KSN if DUKPT.

If the PED is not paired with the VP3300, it is possible to collect a plaintext offline PIN and pass it back to the kernel. THIS MUST BE USED FOR DEMO PURPOSES ONLY. Collecting, transmitting and processing unprotected PIN data violates PCI and introduces considerable liability to the merchant.

To implement, first make the class a delegate of IDT_VP3300 (IDT_VP3300_Delegate). Then include the delegate protocols to capture PIN request.

// Objective-C
- (void) pinRequest:(EMV_PIN_MODE_Types)mode key:(NSData*)key PAN:(NSData*)PAN startTO:(int)startTO intervalTO:(int)intervalTO language:(NSString*)language;
// Swift
func pinRequest(_ mode: EMV_PIN_MODE_Types, key: Data!, pan PAN: Data!, startTO: Int32, intervalTO: Int32, language: String!)



When pinRequest is called, this indicates the kernel encountered a PIN CVM and would like an external PIN supplied to continue the transaction. If the PED is paired, the delegate will receive all relevant key information. If the PED is not paired, the key information will not be provided.

Once the PIN is collected, it must be sent back to kernel. If the PED is paired, the PIN data will be enciphered, and the KSN must be provided if DUKPT was used. If the PED is not paired, there is no KSN, and the PIN data would be plaintext (example "1234" = NSData* object 0x31323334). The mode passed would be the same mode that was received in the delegate, unless a PIN_CANCEL is desired, then the mode would be EMV_PIN_MODE_CANCEL, and no KSN or PIN data is provided.

// Objective-C
-(RETURN_CODE) emv_callbackResponsePIN:(EMV_PIN_MODE_Types)mode KSN:(NSData*)KSN PIN:(NSData*)PIN;
// Swift
func emv_callbackResponsePIN(_ mode: EMV_PIN_MODE_Types, ksn KSN: Data, pin PIN: Data) -> RETURN_CODE



To enable PIN in the terminal, tag 9F33 must be configured accordingly. This means a kernel configuration must exist where 9F33 allows PIN entry. This kernel has 5 available configurations. Configuration #2 is the default for VP3300 which does not allow PIN entry. Configuration #1 does allow pin entry. So two methods must be executed. First, the kernel needs to be told which configuration to use, then the default tags for that configuration must be loaded.

Here is example code how to change to configuration #1, and load standard default tags for that configuration. This will enable PIN entry callback.

// Objective-C
//Setting Major Terminal Configuration to 1C
RETURN_CODE rt = [[IDT_VP3300 sharedController] emv_setTerminalMajorConfiguration:1];
if (RETURN_CODE_DO_SUCCESS == rt)
{
//Major Config Set OK
}
else{
//Setting Major Config Failed
return;
}
//Setting Terminal Tags To Allow PIN
NSString* TLVstring = @"5F3601029F1A0208409F3501229F3303E0F8C89F4005F000F0A0019F1E085465726D696E616C9F150212349F160F3030303030303030303030303030309F1C0838373635343332319F4E2231303732312057616C6B65722053742E20437970726573732C204341202C5553412EDF260101DF1008656E667265737A68DF110101DF270100DFEE150101DFEE160100DFEE170105DFEE180180DFEE1E08F0DC3CF0C29E9400DFEE1F0180DFEE1B083030303130353030DFEE20013CDFEE21010ADFEE2203323C3C";
NSData* TLV = [IDTUtility hexToData:TLVstring];
rt = [[IDT_VP3300 sharedController] emv_setTerminalData:[IDTUtility TLVtoDICT:TLV]];
if (RETURN_CODE_DO_SUCCESS == rt)
{
//Terminal Tags Set OK
}
else{
//Setting Terminal Tags Failed
}
// Swift
// Setting Major Terminal Configuration to 1C
let rt = IDT_VP3300.sharedController().emv_setTerminalMajorConfiguration(1)
if RETURN_CODE_DO_SUCCESS == rt {
//Major Config Set OK
} else {
//Setting Major Config Failed
return
}
//Setting Terminal Tags To Allow PIN
let TLVstring = "5F3601029F1A0208409F3501229F3303E0F8C89F4005F000F0A0019F1E085465726D696E616C9F150212349F160F3030303030303030303030303030309F1C0838373635343332319F4E2231303732312057616C6B65722053742E20437970726573732C204341202C5553412EDF260101DF1008656E667265737A68DF110101DF270100DFEE150101DFEE160100DFEE170105DFEE180180DFEE1E08F0DC3CF0C29E9400DFEE1F0180DFEE1B083030303130353030DFEE20013CDFEE21010ADFEE2203323C3C"
let TLV = IDTUtility.hex(toData: TLVstring)
let rt2 = IDT_VP3300.sharedController().emv_setTerminalData(IDTUtility.tlVtoDICT(TLV))
if RETURN_CODE_DO_SUCCESS == rt2 {
//Terminal Tags Set OK
} else {
Setting Terminal Tags Failed
}



Here is example code how to change to configuration #2, and load standard default tags for that configuration. This will disable PIN entry callback.

// Objective-C
//Setting Major Terminal Configuration to 2C
RETURN_CODE rt = [[IDT_VP3300 sharedController] emv_setTerminalMajorConfiguration:2];
if (RETURN_CODE_DO_SUCCESS == rt)
{
//Major Config Set OK
}
else{
//Setting Major Config Failed
return;
}
//Setting Terminal Tags To Allow PIN
NSString* TLVstring = @"5F3601029F1A0208409F3501219F33036028C89F4005F000F0A0019F1E085465726D696E616C9F150212349F160F3030303030303030303030303030309F1C0838373635343332319F4E2231303732312057616C6B65722053742E20437970726573732C204341202C5553412EDF260101DF1008656E667265737A68DF110100DF270100DFEE150101DFEE160100DFEE170105DFEE180180DFEE1E08D0DC20D0C41E1400DFEE1F0180DFEE1B083030303130353030DFEE20013CDFEE21010ADFEE2203323C3C";
NSData* TLV = [IDTUtility hexToData:TLVstring];
rt = [[IDT_VP3300 sharedController] emv_setTerminalData:[IDTUtility TLVtoDICT:TLV]];
if (RETURN_CODE_DO_SUCCESS == rt)
{
//Terminal Tags Set OK
}
else{
//Setting Terminal Tags Failed
}
// Swift
// Setting Major Terminal Configuration to 2C
let rt = IDT_VP3300.sharedController().emv_setTerminalMajorConfiguration(2)
if RETURN_CODE_DO_SUCCESS == rt {
//Major Config Set OK
} else {
//Setting Major Config Failed
return
}
//Setting Terminal Tags To Allow PIN
let TLVstring = "5F3601029F1A0208409F3501219F33036028C89F4005F000F0A0019F1E085465726D696E616C9F150212349F160F3030303030303030303030303030309F1C0838373635343332319F4E2231303732312057616C6B65722053742E20437970726573732C204341202C5553412EDF260101DF1008656E667265737A68DF110100DF270100DFEE150101DFEE160100DFEE170105DFEE180180DFEE1E08D0DC20D0C41E1400DFEE1F0180DFEE1B083030303130353030DFEE20013CDFEE21010ADFEE2203323C3C"
let TLV = IDTUtility.hex(toData: TLVstring)
let rt2 = IDT_VP3300.sharedController().emv_setTerminalData(IDTUtility.tlVtoDICT(TLV))
if RETURN_CODE_DO_SUCCESS == rt2 {
//Terminal Tags Set OK
} else {
Setting Terminal Tags Failed
}