Creating an iOS Credit Card Reader with Xamarin

Mark Trinder

Simply put, Xamarin enables you to develop apps for the three major mobile platforms using one type-safe mainstream language, C#. Xamarin lets you share ~60% of your code across iOS, Android and Windows “out of the box” as it’s built on the open source .NET runtime, Mono.

If you use patterns such as dependency injection and frameworks such as MVVM, the code sharing percentage can be even higher. The best part about using Xamarin is that you don’t lose any of the native user experience. An app that shares .NET code will still look and feel like it was developed for the OS it is running on – because it was!

Portability

Now they have reached full maturity, Portable Class Libraries (PCLs) have allowed Xamarin to take another evolutionary “code sharing” leap. For those uninitiated, Microsoft licensed and released documented subsets of the .NET framework that target multiple platforms. Using these subsets it is now possible to write code in one library that can target Windows Phone 8, Windows Store Apps, Silverlight, Xamarin.iOS and Xamarin.Android.

Imaging creating a library with SQLiteORM, data access repositories, business domain objects and view-model binding classes. All compiled and runable on the afore mentioned platforms. There is no need to imagine this possibility because it’s a reality and I will show you an example later.

As you are all good coders, I’m sure you’ve realized the most beneficial part of PCLs. Testability! All of the code coverage will be platform independent. Furthermore, since we can run the tests in a standard test runner like nUnit, mocking and faking frameworks are readily accessible, making integration testing a breeze. This is something that I’ve truly missed while developing for Xamarin.iOS, because prior to PCLs, all C# code written for iOS needed to be compiled to byte-code ahead of time (AOT). This meant that certain parts of the .NET reflection namespace had to be omitted and thus the assistance of powerful mocking frameworks were out of the question.

Version 3 => Xamarin.Forms

Using Xamarin last year I wrote code in common class files and shared them by using platform specific library projects. This technique worked OK but it was a little cumbersome having twice (or sometimes three times) the projects necessary just to share the code.
This year I’m using PCLs to create and reuse the same classes across different platforms.

As of two weeks ago Xamarin 3 was released with the next (even more) exciting iteration of code reuse, shared UI. That’s right, Xamarin have created a common user interface abstraction called Xamarin.Forms, wrapping the native iOS, Android and Windows interfaces. This layer of abstraction is portable and easily installed via nuget packages.

Tutorial – iPhone Credit Card Reader

Did someone order an App with the lot?
In this tutorial we will,

  • Use a trial version of Xamarin (30 day Business Edition)
  • Make an iOS application using Xamarin.Forms (PCL)
  • Read a credit card with the device camera, using SQLite.Net to store the card number

This tutorial is repeatable on Windows with Visual Studio, but my platform of choice is a MacBook using Xamarin Studio. The Xamarin Studio IDE is very similar to Visual Studio in layout and functionality.

Don’t forget that since we’ll be creating an iOS application you’ll still need the latest Xcode installed. You can download it from the Apple AppStore.

Visit here to download and install your trial version of Xamarin. The installer will download any necessary dependencies and then setup the SDKs for iOS and Android.

Beginning

Download the source code for this tutorial here and open the solution file, CreditCardReader.sln as we will be following it.

The end result is a solution with three new projects. Since Xamarin.Forms is multi-platform it creates an iOS and Android project, we will only use the iOS project for this tutorial. Right click the CreditCardReader.iOS project and set it as the “Startup Project”. The third project created is the common library or PCL. All common code goes in there, including common UI code!

Projects browser

Nuget Packages

After our app reads the credit card we need to store the result in a database. We’ll use Nuget packages to make sure the PCL and iOS projects are geared up for that. Right click the PCL project and select Add -> Add Packages from the context menu.

nuget sqlite component

Type sqlite.net into the search box and add the SQLite.Net PCL package to the project.
Now do the same for the iOS project except that you need to find and select the one the specifies XamarinIOS Platform.

nuget in Xamarin

Card.io

To achieve credit card reading functionality we use a Xamarin Component. Xamarin Components are libraries that you can download and use to make life easier. Most are free but some do cost money. Xamarin have created a “store” for developers to publish components, with Xamarin themselves contributing to many free ones. The Component for reading credit card numbers was published by Xamarin and is just a C# wrapper around a library developed by PayPal. In order to use the component visit Card.io and sign up to create an app-key. Signing up is free.

Card.io

Double click the Components folder in the iOS project, you will see the card.io component has already been added. You can add more by clicking the Get More Components button.

When you install a Component a new tab will open in Xamarin Studio with details about the Component along with some code snippets to get you going quickly. Access this snippet now by clicking the Details link.

Card.io Tab

The Portable Library

Main View

Inside the PCL, open App.cs and you’ll see the small amount of platform independent code it takes to create the main screen. Depending on which device this code runs on it will create and display native controls. This is the power of Xamarin.Forms.

var label = new Label { Text = "Card No:" };
var cardEntry = new Entry { Placeholder = "" };
var scanButton = new Button { Text = "Scan", TextColor = Color.White, BackgroundColor = Color.FromHex ("77D065") };

// code omitted

return new ContentPage
{
    Content = new StackLayout {
    Spacing = 20, Padding = 50,
    VerticalOptions = LayoutOptions.Center,
    Children = { label, cardEntry, scanButton }
  }
};

2. Interfaces

Inside the Interfaces.cs file we declare a couple of contracts that will be used by the iOS project to create concrete classes. Not everything is platform independent and that certainly applies with the Card.io component library. So we need to create an interface that the PCL can refer to and call at runtime without needing to know anything about the implementation at compile time. You’ll see these being used later.

3. Database

CardNumberDatabase.cs has our quick and simple code for storing the incoming credit cards in a SQLite database. The CreditCard class holds the card number with a unique id. We can create CreditCard objects and save them directly into the database using the ORM facility built into SQLite.Net.

public class CreditCard
{
    public CreditCard ()
    {
        Id = Guid.NewGuid ().ToString ();
    }

    [PrimaryKey]
    public string Id { get; set; }
    public string Number { get; set; }
}

The CardNumberDatabase class represents the singleton object that creates a table for us and saves the CreditCard objects. Every time we start the app and create the database object, the CreateTable<> method (in the constructor) will check if it needs to create the table, or (if exists) modify the table columns based on the public properties in the CreditCard class.

public class CardNumberDatabase : SQLiteConnection
{
    public CardNumberDatabase (string path) : base (DependencyService.Get<ISQLitePlatform>(), path, false, null)
    {
        CreateTable<CreditCard> ();
    }

    public int AddCardNumber (string number)
    {
        return Insert (new CreditCard { Number = number });
    }
}

4. Saving The Number

Back in App.cs everything comes together with the click of a button.

    var database = new CardNumberDatabase (DBPath);

    // code omitted

            scanButton.Clicked += (sender, e) => {
            var platformCardReader = DependencyService.Get<ICardReader>();
            if (platformCardReader != null)
            {
                platformCardReader.CardFound = delegate (string cardNo) {
                    cardEntry.Text = cardNo;

                    // db save
                    var success = database.AddCardNumber (cardNo) == 1;

                    var alerter = DependencyService.Get<IAlert>();
                    if (alerter != null)
                    {
                        alerter.Show ("Database", success ? "Card Number Saved!" : "Failed!");
                    }
                };

                platformCardReader.ReadCard();
            }
        };

Using the Xamarin.Forms DependencyService we can find the runtime specific implementation of the ICardReader interface and get it to make the Card.io component do its thing. Success or failure will be reported using the runtime specific implementation of the IAlert interface.

Notice that as we enter the GetMainPage method we create a local database object. This object is keep alive by virtue of the fact that it is being used in the anonymous button click delegate. Closures are cool.

iOS Application

1. Setup

Inside the AppDelegate.cs file we need to add one line of code to make sure the SQLite engine knows where to create the database file in the local device file system. Setting this static property on the PCL App class does the trick.

App.DBPath = Path.Combine (Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments), "cards.db");

Concrete Classes

The bulk of the iOS specific work goes into making the concrete classes for the PCL to invoke at runtime.

The IAlert interface (MyAlert.cs) is very simple. We just need to create and show an iOS UIAlertView object.

public class MyAlert : IAlert
{
    #region IAlert implementation

    public void Show (string title, string message)
    {
        var alert = new UIAlertView (title, message, null, "OK", null);
        alert.Show ();
    }

    #endregion
}

The ICardReader (MyCardReader.cs) implementation is bit more work, but not much. Here we need to use the Card.io Component to get the job done. Remember when we installed the Component we got a code snippet to help us get going? Well, the bulk of that snippet is being used here.

When our class method ReadCard is invoked (by the PCL) we create the Card.io specific delegate and controller objects and then present them to the user.

RootViewController is the base controller/view for any iOS application. So here, once we grab its reference, it can do the work of showing the card reader UI.

OnScanCompleted is the event that is fired once the the “reading” of the credit card is done. After some null checks we call our class Action property CardFound, passing the credit card number back to the PCL where it is saved in the database.

You can add your own App Token into this file if you wish.

public class MyCardReader : ICardReader
{
    #region ICardReader implementation

    public Action<string> CardFound { get; set; }

    public void ReadCard ()
    {
        var appcontroller = UIApplication.SharedApplication.KeyWindow.RootViewController;

        var paymentDelegate = new PaymentViewControllerDelegate();
        var paymentViewController = new PaymentViewController(paymentDelegate);

        paymentViewController.CollectCVV = false;
        paymentViewController.CollectExpiry = false;
        paymentViewController.MaskManualEntryDigits = true;
        paymentViewController.AppToken = "e63c673c88c44b179dcbaa9f7a1f76af";

        paymentDelegate.OnScanCompleted += (viewController, cardInfo) => {
            if (cardInfo != null)
            {
                if (CardFound != null)
                {
                    CardFound(cardInfo.CardNumber);
                }
            }

            appcontroller.DismissViewController (true, null);
        };

        appcontroller.PresentViewController(paymentViewController, true, null);
    }

    #endregion
}

Ready…Set…Run

You should be able to get the app running, but here’s a video of it in action:

Here are some screen shots of the app.

App Main Screen

Card reader screenshot

Credit Card

Free book: Jump Start HTML5 Basics

Grab a free copy of one our latest ebooks! Packed with hints and tips on HTML5's most powerful new features.

  • http://www.anthonydamota.me/blog Anthony

    I never heard about Xamarin before. I’ll take a look into this one.

    Thanks for this Mark !