Xamarin

Making your first mobile payment with Payleven and Xamarin

Posted on .

Welcome in the second part of article about Binding Objective-C Payleven libraries in Xamarin iOS. In previous article we have created binding library using Payleven Framework from iOS. Today we will focus on using it in our PaylevenSample app and making first payment. Before we start I must admit that Payleven is currently not providing any test account, so if you wish to run project you must get one here: Payleven Registration. After registration you will be able to get API key for your app. For app tests you need Payleven device paired with your bluetooth.

Full source code for the Payleven sample application is available on my GitHub account

Step 1

Let’s open our project PaylevenSample. Now update information property list file (Info.plist) with set of keys:

  • NSAppTransportSecurity Domains with value:
payleven.com
  • Privacy – Location Usage Description (you can use default text)
  • NSLocation – WhenInUse Usage Description (you can use default text)
  • Supported external accessory protocols with value:
com.adyen.bt1
  • Requred background modes with values:
location, external-accessory, bluetooth-central, bluetooth-peripheral and remote-notification

The whole code should look like:

<key>UISupportedExternalAccessoryProtocols</key>
  <array>
    <string>com.adyen.bt1</string>
  </array>
<key>NSLocationUsageDescription</key>
  <string>Your location is needed for making payments.</string>
<key>NSLocationWhenInUseUsageDescription</key>
  <string>Your location is needed for making payments.</string>
<key>NSAppTransportSecurity</key>
  <dict>
    <key>NSExceptionDomains</key>
      <dict>
        <key>payleven.com</key>
          <dict>
            <key>NSExceptionRequiresForwardSecrecy</key>
              <false/>
            <key>NSIncludesSubdomains</key>
              <true/>
          </dict>
       </dict>
  </dict>
<key>UIBackgroundModes</key>
  <array>
    <string>location</string>
    <string>external-accessory</string>
    <string>bluetooth-central</string>
    <string>bluetooth-peripheral</string>
    <string>remote-notification</string>
  </array>

Step 2

Create a class PaylevenManager, which will derive from the PLVPaymentTaskDelegate. Then create PLVPayleven instance inside.

namespace PaylevenSample
{
    public class PaylevenManager: PLVPaymentTaskDelegate
    {
        private PLVPayleven Payleven { get; set; }
        private PLVPaymentTask PaymentTask { get; set; }
        private CLLocationCoordinate2D LocationCoordinate { get; set; }
        private Action<PLVPaylevenStatus> StatusAction { get; set; }
        private NSString Currency { get; set; }

        private const string ApiKey = ""; // TODO: Add your Api key
        ...
    }
}

Then add method to provide login functionality. To do this we need to call method LoginWithUsername from PLVPayleven object with user name, password and API key. As you can see in our LogInAndPay method we are checking if user is not logged in and handle errors that may return from API.

#region Login & Logout
public void LogInAndPay(NSString userName, NSString userPassword, string amount)
{
    if (Payleven.LoginState == PLVPaylevenLoginState.PLVPaylevenLoginStateLoggedIn)
    {
        // Payleven: prepare device and make payment
        PrepareDeviceAndPay (amount);
    }
    else
    {
        // Payleven: login user
        Payleven.LoginWithUsername(userName, userPassword, new NSString (ApiKey), (errorHandler) =>
            {
                if (errorHandler == null)
                {
                    // Payleven: login successful
                    PrepareDeviceAndPay(amount);
                }
                else
                {
                    // Payleven: login failed
                    StatusAction.Invoke(PLVPaylevenStatus.PLVPaylevenStatusLoginError);
                }
            });
    }
}

public void LogOut()
{
    Payleven.LogoutWithCompletionHandler((errorHandler) =>
        {
            // TODO: check if there is error
        });
}

Step 3

In this step we will board the device. Paired device should be visible in PLVDevice table from PLVPayleven object. Let’s add method PrepareDeviceAndPay that will check if table with devices is not empty, otherwise we must tell user to check if physical device is turn on and paired with our iPhone/iPad. Before we make a payment our device should be ready for use. Firstly we need to call a method PrepareWithCompletionHandler and then see if flag Ready is set to true. If device is not ready we should check if completion handler didn’t return any error message.

public void PrepareDeviceAndPay(string paymentAmount)
{
    if (Payleven.Devices == null || Payleven.Devices.Count() == 0)
    {
        // Payleven: devices list is empty");
        StatusAction.Invoke(PLVPaylevenStatus.PLVPaylevenStatusDeviceNotFound);
        return;
}

var device = Payleven.Devices.FirstOrDefault ();

device.PrepareWithCompletionHandler((completionHandler) =>
    {
        if (device.Ready)
        {
            // Payleven: making payment, device is ready
            Pay(device, paymentAmount);
        }
        else
        {
            // Payleven: device is not ready, check error code
            StatusAction.Invoke(PLVPaylevenStatus.PLVPaylevenStatusDeviceIsNotReady);
        }
    });
}

Step 4

After checking if we are logged in and our device is ready to use we can add method which will begin payment process. This method will initialize payment request and then execute it with special task. For payment request create object PLVPaymentRequest with random id of our payment, payment amount, local currency and our location coordinates. Location coordinates are very important and should be taken from user’s current location because of security purposes. Furthermore I’ve created two methods that will help us with random id and conversion amount to decimal.

public static class PaymentHelper
{
    private const string randomAlphabet = ""; // TODO: Add random alphabet chars

    public static NSString GetRandomNSString()
    {
        string alphabet = randomAlphabet;
        var alphabetLength = alphabet.Length;
        nint stringLength = 20;
        NSMutableString mstring = new NSMutableString(stringLength);

        for (var index = 0; index < stringLength; index++)
        {
            int randomIndex = new Random().Next(1, alphabetLength);
            mstring.Append(new NSString(alphabet[randomIndex].ToString()));
        }

        return mstring;
    }

    public static NSDecimalNumber LocaleAmount(string amount)
    {
        NSLocale locale = NSLocale.CurrentLocale;
        return new NSDecimalNumber(amount, locale);
    }
}

If our payment request is ready let’s create new object with by using method PaymentTaskWithRequest from PLVPayleven. It requires in parameters previous request, device and current instance of class. Calling start method on our payment task will begin payment process on chip device.

public void Pay(PLVDevice device, string paymentAmount)
{
    if (device == null)
    {
        // Payleven: device not found
        StatusAction.Invoke(PLVPaylevenStatus.PLVPaylevenStatusDeviceNotFound);
        return;
    }

    if (!LocationCoordinate.IsValid())
    {
        // Payleven: coordinates are not valid
        StatusAction.Invoke(PLVPaylevenStatus.PLVPaylevenStatusCoordsIsNotValid);
        return;
    }

    var paymentRequest = new PLVPaymentRequest(PaymentHelper.GetRandomNSString(), PaymentHelper.LocaleAmount(paymentAmount),
        Currency, LocationCoordinate);

    var paymentTask = Payleven.PaymentTaskWithRequest(paymentRequest, device, this);

    if (paymentTask == null)
    {
        // Payleven: error with creating payment
        StatusAction.Invoke(PLVPaylevenStatus.PLVPaylevenStatusError);
        return;
    }
    else
        // Payleven: payment has started!
        paymentTask.Start();
}

Step 5

Before we compile our app let’s open iOS Build (in PaylevenSample project). Then fill field additional options with gcc_flags arguments:

-gcc_flags "-L${ProjectDir}/PaylevenLib/ -lPaylevenSDK -IAdyenToolkit -force_load ${ProjectDir}/PaylevenLib/libPaylevenSDK.a -force_load ${ProjectDir}/PaylevenLib/libAdyenToolkit.a”

 

Xamarin Payleven - GCC Flags

Now our application is ready for payments. As you can see binding projects makes it easy to load third-party Objective-C libraries, however it requires some work at the beginning. For me it was a great time to show you how to Accept Chip & PIN payments without leaving app.

The best tips for using Xamarin, Mobile and Web technologies directly to your inbox