This project enables an iOS API to communicate with the payleven Classic (Chip & PIN) and Plus (NFC) card reader to accept debit and credit card payments. Learn more about the card readers on one of payleven's country websites. From version 1.1.0 onwards, the payleven Point Pay SDK provides an API to process full and partial refunds. Additionally, the SDK issues a receipt image of both sale and refund payments that contain the bare minimum of receipt details. If you have any questions or require further assistance, please contact [email protected].
The SDK is a static library, which supports other platforms like Xamarin and is fully compatible with the i386, x86_64, armv7, arm64 architectures.
Note:
The product has been renamed to payleven Point Pay SDK from mPOS SDK. Any references within the documentation or classes are relevant to payleven Point Pay SDK.
Drag the following files into your Xcode project.
PaylevenSDK.framework
AdyenToolkit.framework
AdyenToolkit.bundle
Open the Build Phases of your target and add the following frameworks to the Link Binary With Libraries section:
CoreData.framework
CoreLocation.framework
ExternalAccessory.framework
SystemConfiguration.framework
libsqlite3.0.dylib
AVFoundation.framework
AudioToolbox.framework
Open the Build Settings of your target and add -ObjC
flag to Other Linker Flags
Import PaylevenSDK into your files:
#import <PaylevenSDK/PaylevenSDK.h>
Open the Info.plist and add the following entries:
CFBundleDisplayName
with the display name for your app.UISupportedExternalAccessoryProtocols
with an array of just one value com.adyen.bt1
.NSLocationWhenInUseUsageDescription
or NSLocationAlwaysUsageDescription
,
for iOS 7: NSLocationUsageDescription
with the location usage description message for the users. <dict>
<key>NSExceptionDomains</key>
<dict>
<key>payleven.de</key>
<dict>
<key>NSExceptionRequiresForwardSecrecy</key>
<false/>
<key>NSIncludesSubdomains</key>
<true/>
</dict>
</dict>
</dict>
Before submitting your iOS app to iTunes, Apple requires registration of all iOS apps that communicate with approved MFi devices. This registration process officially associates your app with the payleven card reader and can be performed by payleven. Once your app (bundle ID) has been registered, future app versions will not require additional registrations. Please contact [email protected] for help with your submission.
To fetch connected devices, start or refund a payment you must be logged into payleven SDK. Use the API key received from payleven, together with your payleven merchant account (email address & password) to authenticate your app. Hint: Check out our Sample Demo to see how you can easily observe the Login State using Key-Value Observing.
- (void)loginWithUserName:(NSString *)username password:(NSString *)password {
__weak typeof(self) weakSelf = self;
[self.manager.payleven loginWithUsername:username password:password APIKey:self.manager.APIKey completionHandler:^(NSError *error) {
__strong typeof(weakSelf)strongSelf = weakSelf;
if([strongSelf.delegate conformsToProtocol:@protocol(PSLoginDelegate)]) {
if(error) {
[strongSelf.delegate loginDidFailWithError:error];
} else {
[strongSelf.delegate loginViewControllerDidFinish:(PSLoginViewController *)strongSelf.delegate];
}
}
}];
}
Before proceeding with the integration and testing, make sure you have paired the card reader in the bluetooth settings on your iOS device.
Once a PLVPayleven
instance is created, you need to select the card reader to process payments. Please remember to select a device every time you start a new session.
//You probably want to visualize the devices in a UITableView
NSArray * pairedDevices = self.manager.payleven.devices;
//Get the selected device from the list
PLVDevice *device = self.sortedDevices[indexPath.row];
NSString * deviceName = device.name;
After a device is selected it needs to be prepared to accept payments. We will run all required preparations and security checks for you. All you have to do is outlined below. Also, before triggering a new payment you should always check that your PLVDevice object returns ready == true.
dispatch_time_t dispatchTime = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2.00 * NSEC_PER_SEC));
__weak typeof(self)weakSelf = self;
dispatch_after(dispatchTime, dispatch_get_main_queue(), ^{
__strong typeof(weakSelf)strongSelf = weakSelf;
[device prepareWithCompletionHandler:^(NSError *error) {
if (device.ready) {
[strongSelf didSuccessfullyPrepareDevice:device controller:strongSelf];
} else {
[strongSelf didFailConfiguringDeviceWithError:error controller:strongSelf];
}
}];
});
Initialize the actual payment request. For security purposes, you must provide the user's current location in the PaymentRequest. The identifier parameter allows you to reference this particular payment for a potential refund in the future. We strongly advise you to save this value in your Backend.
//Here we are using an arbitrary location. In your app you must provide the user's current location
CLLocationCoordinate2D coordinate = CLLocationCoordinate2DMake(52.5243700, 13.4105300);
NSLocale* locale = [NSLocale currentLocale];
NSDecimalNumber* amount = [NSDecimalNumber decimalNumberWithString:@"1.00" locale:locale];
PLVPaymentRequest* request = [[PLVPaymentRequest alloc] initWithIdentifier:@"anArbitraryUniqueIdentifier"
amount:amount
currency:@"EUR"
coordinate:coordinate];
//Hint: the corresponding delegate is PLVPaymentTaskDelegate
self.paymentTask = [self.manager.payleven paymentTaskWithRequest:request device:self.device delegate:self]
if (self.paymentTask == nil) {
//Could not create Payment
} else {
[self.paymentTask start];
}
Implement PLVPaymentTaskDelegate's methods to respond to payment events such as the request of a payer's signature.
- (void)paymentTask:(PLVPaymentTask *)paymentTask
needsSignatureWithCompletionHandler:(void (^)(BOOL, CGImageRef))completionHandler {
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:@"Main" bundle:nil];
UINavigationController *navigationController
= [storyboard instantiateViewControllerWithIdentifier:@"SignatureConfirmationNavigationController"];
SignatureConfirmationViewController *signatureConfirmationViewController
= (SignatureConfirmationViewController *)navigationController.topViewController;
//Get Payer's signature and return using completionBlock (See our Sample App for full implementation)
UIImage * signature = ...
completionHandler(true, signature.CGImage);
}
Optionally, you can offer a more comprehensive user experience by implementing progressDidChange method as shown below.
-(void)paymentTask:(PLVPaymentTask *)paymentTask progressDidChange:(PLVPaymentProgressState)progressState
{
NSString *progressStateDescriptor;
switch (progressState) {
case PLVPaymentProgressStateNone:
progressStateDescriptor = @"None";
break;
case PLVPaymentProgressStateStarted:
progressStateDescriptor = @"Started";
break;
case PLVPaymentProgressStateRequestInsertCard:
progressStateDescriptor = @"Please insert card";
break;
case PLVPaymentProgressStateRequestPresentCard:
progressStateDescriptor = @"Please present card";
break;
case PLVPaymentProgressStateCardInserted:
progressStateDescriptor = @"Card inserted";
break;
case PLVPaymentProgressStateRequestEnterPin:
progressStateDescriptor = @"Please enter Pin";
break;
case PLVPaymentProgressStatePinEntered:
progressStateDescriptor = @"Pin entered";
break;
case PLVPaymentProgressStateContactlessBeepFailed:
progressStateDescriptor = @"Contactless Tap failed";
break;
case PLVPaymentProgressStateContactlessBeepOk:
progressStateDescriptor = @"Contactless Tap Ok";
break;
case PLVPaymentProgressStateRequestSwipeCard:
progressStateDescriptor = @"Please swipe card";
break;
default:
break;
}
//Display progressStateDescriptor to your user
}
Note:
A successful tap of the card to be charged for a contactless (NFC) transaction is indicated by all four (green) LEDs lighting up on the payleven plus reader and a confirmation on the card reader display is followed by a short beep of your mobile device. Please ensure the volume of the mobile device is turned-on for audio confirmation.
The delegate's paymentTaskDidFinish: and paymentTask:didFailWithError: are called when the payment task finishes. You need to implement both and present the outcome of the payment to the user.
- (void)paymentTaskDidFinish:(PLVPaymentTask *)paymentTask {
//Check paymentTask's result and inform the user
self.paymentTask = nil;
}
- (void)paymentTask:(PLVPaymentTask *)paymentTask didFailWithError:(NSError *)error {
//Error handling
self.paymentTask = nil;
}
You can refund a payment conducted via the Point Pay SDK partially or in full. First, you create a PLVRefundRequest. It is used to create or generate the request for refunds that will later be executed by the PLVRefundTask instance. For a refund you need
PLVRefundRequest *request = [[PLVRefundRequest alloc]initWithIdentifier:refundIdentifier
paymentIdentifier:originalPaymentId
amount:amount
currency:@"EUR"
refundDescription:@"Customer request"];
- (PLVRefundTask *)refundTaskWithRequest:(PLVRefundRequest *)request
completionHandler:(void (^)(PLVRefundResult *result, NSError *error))completionHandler;
Once you have initialised PLVRefundRequest sucessfully you can trigger the refund as outlined below.
- (void)performRefundTask {
NSDecimalNumber *amount = [PSPriceDecimal decimalForIntWithMantissa:self.currentAmount.intValue];
NSString *refundIdentifier = self.manager.randomString;
PLVRefundRequest *request = [[PLVRefundRequest alloc]initWithIdentifier:refundIdentifier
paymentIdentifier:self.externalIdTextField.text
amount:amount
currency:self.manager.currency
refundDescription:nil];
__weak typeof(self)weakSelf = self;
__strong typeof(weakSelf)strongSelf = weakSelf;
self.refundTask = [self.manager.payleven refundTaskWithRequest:request completionHandler:^(PLVRefundResult *result, NSError *error) {
if(error){
//Inform user about error
} else {
//Inform user about success
}
}];
[self.refundTask start];
}
Additionally, the SDK issues a receipt image of sale and refund payments that contains the bare minimum of receipt details. Please keep in mind to extend the image with the merchants name, address and a respective receipt ID. In case you wish to create your own receipt by using a set of raw payment data, please contact [email protected].
self.receiptGenerator = paymentTask.result.receiptGenerator;
CGFloat scale = [UIScreen mainScreen].scale;
[self.receiptGenerator generateReceiptWithWidth:(384.0 * scale)
fontSize:(16.0 * scale)
lineSpacing:(8.0 * scale)
padding:(20.0 * scale)
completionHandler:
^(CGImageRef receipt) {
CGFloat scale = [UIScreen mainScreen].scale;
UIImage *image = [UIImage imageWithCGImage:receipt scale:scale orientation:UIImageOrientationUp];
self.receiptGenerator = nil;
}];
The Point Pay SDK includes a sample app illustrating how the SDK can be integrated.
Note:
- The location is hardcoded and needs to be changed according to user's current position.
- The Bundle ID of the sample app has been registered already and is uniquely associated to the API key used in the project. In case you change the API key to the one you have obtained from payleven during the developer registration, please remember to change also the Bundle ID to the one you have registered.
The sample integration exemplifies the following:
#import <PaylevenSDK/PLVPaymentProgressViewController.h>
- (void)viewWillAppear:(BOOL)animated {
[super viewWillAppear:YES];
//Init
self.paymentProgressViewController = [[PLVPaymentProgressViewController alloc]init];
[self addChildViewController:self.paymentProgressViewController];
//Set size
self.paymentProgressViewController.view.frame = self.paymentProgressContainerView.bounds;
//Add
[self.paymentProgressContainerView addSubview:self.paymentProgressViewController.view];
[self.paymentProgressViewController didMoveToParentViewController:self];
}
-(void)paymentTask:(PLVPaymentTask *)paymentTask progressDidChange:(PLVPaymentProgressState)progressState
{
if (self.paymentProgressViewController) {
[self.paymentProgressViewController animateWithPaymentProgressState:progressState];
}
}