Geeks With Blogs
The Life and Times of a Dev Yes, we're really that weird

Sometimes as developers we’re spoiled by third parties that do a lot of the heavy lifting for us.  However, sometimes we’re NOT spoiled and we have to get our hands dirty.

Today, I spent much of the day getting my hands dirty.  I’m working on a project that uses a MagTek credit card swiper and all MagTek provides you in terms of dlls is a c++ dll and an ActiveX dll.  What fun is that?  I wanted to avoid com interop (no, I don’t have a good reason) and write a C# class that handled talking with their C++ dlls directly.

This ended up being a good lesson in P/Invoke and how to deal with unsafe (I’m guessing strcat) code in a dll that I don’t control.

1207 lines of code (and comments) later, I have the final result completed.  I’m not going to post the entire post, since it would be WAY to long, but here are the key bits:

Here’s the dll imports you’ll need:

/// <summary>
///   Clears the data buffer
/// </summary>
[DllImport("MTUSCRA.dll")]
private static extern void MTUSCRAClearBuffer();

/// <summary>
///   Opens the MTUSCRA Device
/// </summary>
/// <returns> A uint that is an <see cref="ErrorValuesEnum" /> </returns>
[DllImport("MTUSCRA.dll")]
private static extern uint MTUSCRACloseDevice();

/// <summary>Gets the card data from the reader.</summary>
/// <param name="cardData">The card data structure for holding the card information. </param>
/// <returns>A uint that is an <see cref="ErrorValuesEnum"/> </returns>
[DllImport("MTUSCRA.dll")]
private static extern uint MTUSCRAGetCardData(ref MTMSRDATA cardData);

//// This has been removed because it requires unsafe code.
/////// <summary>Gets the card data delimited by the provided string.</summary>
/////// <param name="data">The string result that will be sent back. </param>
/////// <param name="delimiter">The delimiter for the string </param>
/////// <returns>A uint that is an <see cref="ErrorValuesEnum"/> </returns>
////[DllImport("MTUSCRA.dll")]
////private static extern unsafe uint MTUSCRAGetCardDataStr(byte* data, string delimiter);

/// <summary>Opens the MTUSCRA Device</summary>
/// <param name="deviceName">The name of the device to open </param>
/// <returns>A uint that is an <see cref="ErrorValuesEnum"/> </returns>
[DllImport("MTUSCRA.dll")]
private static extern uint MTUSCRAOpenDevice(string deviceName);

/// <summary>Opens the MTUSCRA Device</summary>
/// <param name="command">The command to send </param>
/// <param name="commandLength">The length of the command sent. </param>
/// <param name="result">The result of the command </param>
/// <param name="resultLength">The length of the result. </param>
/// <returns>A uint that is an <see cref="ErrorValuesEnum"/> </returns>
[DllImport("MTUSCRA.dll")]
private static extern uint MTUSCRASendCommand(string command, uint commandLength, ref string result, ref uint resultLength);

/// <summary>
/// Raised when the card state data changes.
/// </summary>
/// <param name="callBack">The call back for card data state changing.</param>
[DllImport("MTUSCRA.dll")]
private static extern void MTUSCRACardDataStateChangedNotify(CardDataStateChangedCallBack callBack);

/// <summary>
/// Raised when the device state changes
/// </summary>
/// <param name="callBack">The call back for card data state changing.</param>
[DllImport("MTUSCRA.dll")]
private static extern void MTUSCRADeviceStateChangedNotify(DeviceStateChangedCallBack callBack);

/// <summary>
/// Gets the current device state.
/// </summary>
/// <param name="deviceState">The device state</param>
[DllImport("MTUSCRA.dll")]
private static extern void MTUSCRAGetDeviceState(ref uint deviceState);

/// <summary>
/// Gets the current data state.
/// </summary>
/// <param name="dataState">The data state</param>
[DllImport("MTUSCRA.dll")]
private static extern void MTUSCRAGetCardDataState(ref uint dataState);

/// <summary>
/// Gets the cproduct id of the card reader.
/// </summary>
/// <param name="productId">The product id</param>
[DllImport("MTUSCRA.dll")]
private static extern void MTUSCRAGetPID(ref uint productId);

You’ll need a couple of delegates as well:

/// <summary>
///   A delegate for handling the card data state callback.
/// </summary>
/// <param name="dataState"> The data state </param>
private delegate void CardDataStateChangedCallBack(uint dataState);

/// <summary>
///   A delegate for handling the device state callback.
/// </summary>
/// <param name="deviceState"> The device state </param>
private delegate void DeviceStateChangedCallBack(uint deviceState);

And then you’ll want to wire those up like so:

 

this.CardDataStateChanged = new CardDataStateChangedCallBack(this.OnCardDataStateChanged);
this.DeviceStateChanged = new DeviceStateChangedCallBack(this.OnDeviceStateChanged);

MTUSCRACardDataStateChangedNotify(this.CardDataStateChanged);
MTUSCRADeviceStateChangedNotify(this.DeviceStateChanged);

And finally, you’ll want the Struct that you’ll need to use to get the card data:

[StructLayout(LayoutKind.Sequential)]
public struct MTMSRDATA
{
    /// <summary>The default data size for tracks.</summary>
    private const int DEF_MSR_DATA_LEN = 256;

    /// <summary>The card data.</summary>
    [MarshalAs(UnmanagedType.ByValTStr, SizeConst = DEF_MSR_DATA_LEN * 3)]
    public string m_szCardData;

    /// <summary>masked card data.</summary>
    [MarshalAs(UnmanagedType.ByValTStr, SizeConst = DEF_MSR_DATA_LEN * 3)]
    public string m_szCardDataMasked;

    /// <summary>Track 1 Data.</summary>
    [MarshalAs(UnmanagedType.ByValTStr, SizeConst = DEF_MSR_DATA_LEN)]
    public string m_szTrack1Data;

    /// <summary>Track 2 data.</summary>
    [MarshalAs(UnmanagedType.ByValTStr, SizeConst = DEF_MSR_DATA_LEN)]
    public string m_szTrack2Data;

    /// <summary>Track 3 data.</summary>
    [MarshalAs(UnmanagedType.ByValTStr, SizeConst = DEF_MSR_DATA_LEN)]
    public string m_szTrack3Data;

    /// <summary>Masked track 1 data.</summary>
    [MarshalAs(UnmanagedType.ByValTStr, SizeConst = DEF_MSR_DATA_LEN)]
    public string m_szTrack1DataMasked;

    /// <summary>masked track 2 data.</summary>
    [MarshalAs(UnmanagedType.ByValTStr, SizeConst = DEF_MSR_DATA_LEN)]
    public string m_szTrack2DataMasked;

    /// <summary>masked track 3 data.</summary>
    [MarshalAs(UnmanagedType.ByValTStr, SizeConst = DEF_MSR_DATA_LEN)]
    public string m_szTrack3DataMasked;

    /// <summary>MagnePrint data.</summary>
    [MarshalAs(UnmanagedType.ByValTStr, SizeConst = DEF_MSR_DATA_LEN)]
    public string m_szMagnePrintData;

    /// <summary>Card encode type.</summary>
    [MarshalAs(UnmanagedType.ByValTStr, SizeConst = DEF_MSR_DATA_LEN)]
    public string m_szCardEncodeType;

    /// <summary>MagnePrint Status.</summary>
    [MarshalAs(UnmanagedType.ByValTStr, SizeConst = DEF_MSR_DATA_LEN)]
    public string m_szMagnePrintStatus;

    /// <summary>DUKPT Session ID.</summary>
    [MarshalAs(UnmanagedType.ByValTStr, SizeConst = DEF_MSR_DATA_LEN)]
    public string m_szDUKPTSessionID;

    /// <summary>Device Serial Number.</summary>
    [MarshalAs(UnmanagedType.ByValTStr, SizeConst = DEF_MSR_DATA_LEN)]
    public string m_szDeviceSerialNumber;

    /// <summary>DUKPT Key Serial Number.</summary>
    [MarshalAs(UnmanagedType.ByValTStr, SizeConst = DEF_MSR_DATA_LEN)]
    public string m_szDUKPTKSN;

    /// <summary>First Name from Track 1.</summary>
    [MarshalAs(UnmanagedType.ByValTStr, SizeConst = DEF_MSR_DATA_LEN)]
    public string m_szFirstName;

    /// <summary>Last Name from Track 1.</summary>
    [MarshalAs(UnmanagedType.ByValTStr, SizeConst = DEF_MSR_DATA_LEN)]
    public string m_szLastName;

    /// <summary>PAN from Track 2.</summary>
    [MarshalAs(UnmanagedType.ByValTStr, SizeConst = DEF_MSR_DATA_LEN)]
    public string m_szPAN;

    /// <summary>The Expiration Month.</summary>
    [MarshalAs(UnmanagedType.ByValTStr, SizeConst = DEF_MSR_DATA_LEN)]
    public string m_szMonth;

    /// <summary>The Expiration Year.</summary>
    [MarshalAs(UnmanagedType.ByValTStr, SizeConst = DEF_MSR_DATA_LEN)]
    public string m_szYear;

    /// <summary>Reader product ID.</summary>
    public uint m_dwReaderID;

    /// <summary>MagnePrint length.</summary>
    public uint m_dwMagnePrintLength;

    /// <summary>MagnePrint Status.</summary>
    public uint m_dwMagnePrintStatus;

    /// <summary>Track 1 data length.</summary>
    public uint m_dwTrack1Length;

    /// <summary>Track 2 length.</summary>
    public uint m_dwTrack2Length;

    /// <summary>Track 3 length.</summary>
    public uint m_dwTrack3Length;

    /// <summary>Track 1 length masked.</summary>
    public uint m_dwTrack1LengthMasked;

    /// <summary>Track 2 length masked.</summary>
    public uint m_dwTrack2LengthMasked;

    /// <summary>Track 3 length masked.</summary>
    public uint m_dwTrack3LengthMasked;

    /// <summary>Card encode type.</summary>
    public uint m_dwCardEncodeType;

    /// <summary>Track 1 decode status.</summary>
    public uint m_dwTrack1DcdStatus;

    /// <summary>Track 2 decode status.</summary>
    public uint m_dwTrack2DcdStatus;

    /// <summary>The m_dw track 3 dcd status.</summary>
    public uint m_dwTrack3DcdStatus;

    /// <summary>Card swipe status.</summary>
    public uint m_dwCardSwipeStatus;
}

Hopefully, this will help you get started and will save you some time.  I know it would have saved me quite a bit!

Good luck!

Technorati Tags: ,,
Posted on Wednesday, July 11, 2012 5:25 PM | Back to top


Comments on this post: Reading Credit Card Data from a MagTek Card Swipe Device

# re: Reading Credit Card Data from a MagTek Card Swipe Device
Requesting Gravatar...
Thank you very much for this code, you saved me a ton of time. We have been getting killed by the ActiveX control that keeps doing this
http://stackoverflow.com/questions/2878525/getting-reportavoncomrelease-exception-when-using-3rd-party-com
to us.
Left by Darrel Miller on Apr 11, 2013 10:45 AM

# re: Reading Credit Card Data from a MagTek Card Swipe Device
Requesting Gravatar...
Hi,

Can you please share the source code of this article? i really need this badly and it would be great if you can help me by sharing the source code.

Thanks,

Mrunal
Left by Mrunal on Apr 25, 2013 6:44 AM

# re: Reading Credit Card Data from a MagTek Card Swipe Device
Requesting Gravatar...
Hi,

I appreciated if you can share the source code of this article?I am looking for some solution or dll since one month. I had tried Magtek ocx card swipe also but there I didn't found any solution. Please help me.

Thanks
Surendar yadav
Left by surendar yadav on Jul 01, 2013 11:22 AM

# re: Reading Credit Card Data from a MagTek Card Swipe Device
Requesting Gravatar...
Sorry, this is a bit over my head...but I really would like to understand how you implemented this solution. Can you provide more context or the source code...I see the guts here but truthfully I have no idea how to put it to use. Obviously I have a learning curve, but I think if I saw all of it, I could understand it and apply it to our application.

Thanks in advance,
Marguerite
Left by mmcfadden on Sep 24, 2013 10:00 AM

# re: Reading Credit Card Data from a MagTek Card Swipe Device
Requesting Gravatar...
Thanks for a very helpful article. Your article helped me integrate a MagTek reader into an existing Net application.
I know this article is a few years old now, but I was wondering if you were able to send any commands to the reader using the above code. I am trying to send commands to the reader to get info like serial # or model #. Any code examples you had would be very helpful.
Thanks.
Left by Brian on Dec 12, 2014 11:45 AM

# re: Reading Credit Card Data from a MagTek Card Swipe Device
Requesting Gravatar...
You know after all these years this is still the best example I have seen. Thank you sir you are a god!
Left by Brandon on Feb 25, 2015 1:39 PM

# re: Reading Credit Card Data from a MagTek Card Swipe Device
Requesting Gravatar...
It will be very helpful if you can send the Source code
Left by Chandu on Apr 07, 2015 10:18 PM

# re: Reading Credit Card Data from a MagTek Card Swipe Device
Requesting Gravatar...
madarchod share the code atleast
Left by sammm on Sep 27, 2016 3:15 PM

# hotstar app
Requesting Gravatar...
Left by hotstar apk on Sep 13, 2017 4:55 AM

# re: Reading Credit Card Data from a MagTek Card Swipe Device
Requesting Gravatar...
Thanks a lot.

You can enjoy these best Hookup Apps for free.

Left by Amazingtop10 on Sep 23, 2017 2:01 PM

# re: Reading Credit Card Data from a MagTek Card Swipe Device
Requesting Gravatar...
Thank you for posting such a great article! I found your website perfect for my needs
official website
Left by nisha on May 04, 2018 3:02 AM

Your comment:
 (will show your gravatar)


Copyright © Robert May | Powered by: GeeksWithBlogs.net