Implementation guide
Before starting implementation you should have completed Installation of the MCD SDK.
Main Interface
MeaCardData
is the main interface for interaction with MCD SDK
.
Easy Launch Card View
Easy Launch Card View is fully customisable subclass of the native UIView
that wraps around SDK functionality and exposes API for styling appearance and interacting with a user.
With the Easy Launch Card View, you can omit some of the SDK implementation steps and data management tasks and more rapidly get a visual card-like visual representation of data visible to the user.
Add Interface Builder companion file
Retrieve the McdDesignables.m
companion source file from the framework bundle and copy it into your project, adding it to your target.
Adding the file located within the framework or using a symbolic link does not work, as Xcode / Interface Builder does not to parse files within frameworks.
Add Card View in Interface Builder
Drag and drop an UIView
object into your view and set its class to McdEasyLaunchCardView
.
Card Secret Generation
Secret generator property is used to pass card data from app to card view. Card secret is generated on app backend, see Time-based Secret (TOTP) Generation.
Generating Secret Synchronously
- swift
- objective-c
@IBOutlet var mcdEasyLaunchCardView: McdEasyLaunchCardView!
// ...
override func viewDidLoad() {
// ...
mcdEasyLaunchCardView.secretGenerator = { cardId in
return cardSecret; // cardSecret generated and provided by banking app backend.
}
// ...
}
@property (weak, nonatomic) IBOutlet McdEasyLaunchCardView *mcdEasyLaunchCardView;
// ...
- (void)viewDidLoad
{
// ...
mcdEasyLaunchCardView.secretGenerator = ^(NSString *cardId) {
return cardSecret; // cardSecret generated and provided by banking app backend.
};
// ...
}
Generating Secret Asynchronously
- swift
- objective-c
@IBOutlet var mcdEasyLaunchCardView: McdEasyLaunchCardView!
// ...
override func viewDidLoad() {
// ...
mcdEasyLaunchCardView.secretGeneratorWithCompletion = { cardId, completion in
completion(cardSecret) // cardSecret generated and provided by banking app backend.
}
// ...
}
@property (weak, nonatomic) IBOutlet McdEasyLaunchCardView *mcdEasyLaunchCardView;
// ...
- (void)viewDidLoad
{
// ...
mcdEasyLaunchCardView.secretGeneratorWithCompletion = ^(NSString *cardId, void (^ completion)(NSString *)) {
completion(cardSecret); // cardSecret generated and provided by banking app backend.
};
// ...
}
Default Appearance And Behaviour
By completing the steps above, you have implemented the bare minimum of Easy Launch Custom View and have it with default appearance and behavior.
Default behavior:
tap
- Show card data. If card data is not retrieved, it is retrieved first. The secondclick
hides card data.long press
- Copy card PAN to clipboard, if card data is retrieved.- Menu button on the top-right corner for accessing more actions -
Show / Hide
,Copy PAN
,Copy Name
,Copy Expiry
,Copy CVV
. - Shows toast message when any of card data is copied to clipboard.
- All texts are in English.
- Default colors are used for card background, texts, and loading indicators.
The Easy Launch Custom View takes care of disposing of retrieved data after 60 seconds. Card View also maintains a proper plastic-card-like aspect ratio. It fills maximum available space within given boundaries. The rest of the assigned area is filled with transparent background.
Card View Customization
Use Interface Builder layout attributes and runtime methods to customize McdEasyLaunchCardView
.
Add translations for text values, add cardTapBlock
and cardLongPressBlock
handlers to get action result callbacks.
Card background, fonts, text and loading indicator colors, touch and card data loading events can be customized and handled. For more UI customization details refer to Card Custom Layout.
See MCD SDK iOS API Reference for more details.
Customization with Interface Builder
Configure and change appearance of Easy Launch Card with the Attributes inspector in Interface Builder.
Interface Builder Attributes
Attribute | Format | Default Value | Description |
---|---|---|---|
cardId | NSString | nil | Card Id |
layout | NSString | nil | Custom layout: bundled XIB file name without extension |
fontSize | CGFloat | 10.0 | Font size |
fontName | NSString | nil | Font name |
cardBackground | UIImage | nil | Card background image |
textColor | UIColor | UIColor.white | Text and symbol color |
loadingIndicatorEnabled | BOOL | true | Enable/Disable default loading indicator |
loadingIndicatorColor | UIColor | UIColor.white | Loading indicator color |
defaultMenuEnabled | BOOL | true | Enable/Disable menu on top-right corner |
panCopyMenuTitle | NSString | "Copy card number" | Menu entry text |
holderNameCopyMenuTitle | NSString | "Copy name" | Menu entry text |
validThruCopyMenuTitle | NSString | "Copy expiry" | Menu entry text |
cvvCopyMenuTitle | NSString | "Copy CVV" | Menu entry text |
showCardMenuTitle | NSString | "Show card details" | Menu entry text |
hideCardMenuTitle | NSString | "Hide card details" | Menu entry text |
toastsEnabled | BOOL | true | Enable/Disable info toasts on card data copy |
panCopyInfoText | NSString | "Card number copied" | Toast message text |
holderNameCopyInfoText | NSString | "Name copied" | Toast message text |
validThruCopyInfoText | NSString | "Card expiry copied" | Toast message text |
cvvCopyInfoText | NSString | "CVV copied" | Toast message text |
To use your custom font, add the font file to your app bundle first. Then use this custom font the same way you use any of the iOS system fonts.
Apple documentation: Adding a Custom Font to Your App
Customization with Code
- swift
- objective-c
class MainViewController: UIViewController {
// ...
@IBOutlet var mcdEasyLaunchCardView: McdEasyLaunchCardView!
// ...
override func viewDidLoad() {
// ...
mcdEasyLaunchCardView.textColor = .yellow
mcdEasyLaunchCardView.validThruCopyMenuTitle = "Copy expiry right now!"
mcdEasyLaunchCardView.toastsEnabled = false;
mcdEasyLaunchCardView.cardTapBlock = {
self.mcdEasyLaunchCardView.cardTapBlock = {
self.mcdEasyLaunchCardView.showCardData { error in
if let error = error {
NSLog("%@", error)
} else {
NSLog("Card data is displayed");
}
}
}
}
mcdEasyLaunchCardView.cardLongPressBlock = {
NSLog("Card Long Press");
self.mcdEasyLaunchCardView.textColor = .white
}
// ...
}
}
@property (weak, nonatomic) IBOutlet McdEasyLaunchCardView *mcdEasyLaunchCardView;
// ...
- (void)viewDidLoad
{
// ...
self.mcdEasyLaunchCardView.cardId = cardId;
self.mcdEasyLaunchCardView.textColor = UIColor.yellowColor;
self.mcdEasyLaunchCardView.validThruCopyMenuTitle = @"Copy expiry right now!";
self.mcdEasyLaunchCardView.toastsEnabled = false;
self.mcdEasyLaunchCardView.cardTapBlock = ^{
[self.mcdEasyLaunchCardView.cardTapBlock showCardData:^(NSError *_Nullable error) {
if (!error) {
NSLog(@"Card data is displayed");
} else {
NSLog(@"%@", error);
}
}];
};
self.mcdEasyLaunchCardView.cardLongPressBlock = ^{
NSLog(@"Card Long Press");
self.mcdEasyLaunchCardView.textColor = UIColor.whiteColor;
};
// ...
}
Custom Card Layout
XIB file
created in XCode Interface Builder could be used as template for Card View.
Add custom layout XIB
file to your app bundle, and then set McdEasyLaunchCardView.layout
property the name of the XIB
file without ".xib"
extension.
At run time, custom layout's UILabel elements with following Restoration ID property values used as placeholders for actual card data:
android:tag | Description |
---|---|
pan | PAN |
expiry | Expiry date in MM/YY format |
name | Name embossed on the card |
cvv | CVV |
Card View Custom Layout taking effect at runtime only - it will not be visible in Interface Builder.
Card Data Loading Events
McdEasyLaunchCardView
have handler properties for card data loading events.
- Loading started:
cardDataLoadingStartedBlock
mcdEasyLaunchCardView.cardDataLoadingStartedBlock = ^{
NSLog(@"Card data loading started")
// ...
};
- Loading completed or loading failed:
cardDataLoadingCompletedBlock
mcdEasyLaunchCardView.cardDataLoadingCompletedBlock = ^(NSError *error) {
if (error) {
NSLog(@"Card data loading failed: %@", error);
// Handle loading data error...
} else {
NSLog(@"Card data loaded");
// ...
}
};
- Card data cleared:
cardDataClearedBlock
self.mcdEasyLaunchCardView.cardDataClearedBlock = ^{
NSLog(@"Card data cleared");
// ...
};
Get Card Data Images
Two input parameters are required to retrieve card data images using MeaCardData.getCardDataImages
method:
cardId
- Card ID of the card.secret
- Secret generated on backend, see Time-based Secret (TOTP) Generation.
- swift
- objective-c
import MeaCardData
//...
let cardId: String = "<value>"
let secret: String = "<value>"
MeaCardData.getImages(cardId, secret: generateMeaTotp(cardId), completionHandler: {(data, error) in
if let cardDataImages = data {
// Use retrieved cardDataImages.
} else {
NSLog("Card Data Images request failed, %@", error?.localizedDescription ?? "unknown error" )
// Handle error.
}
})
#import <MeaCardData/MeaCardData.h>
// ...
NSString *cardId = @"<value>";
NSString *secret = @"<value>";
[MeaCardData getCardDataImages:cardId secret:secret completionHandler:^(McdCardDataImages *_Nullable cardDataImages, NSError *_Nullable error) {
if (cardDataImages) {
// Use retrieved cardDataImages
} else {
NSLog(@"Card data request failed: %@", [error localizedDescription]);
}
}];
Card Data Images
PAN, Expiry Date, Emboss Name and CVV can be exported as UIImage
:
- swift
- objective-c
// Default font, black color, size 10dp, default character spacing
UIImage panImage = cardDataImages.getPanImage(UIFont.systemFont(ofSize: 10), color:.black, spacing:0.0)
// Default monospace font, green color, size 8dp, default character spacing
UIImage expiryDateImage = cardDataImages.getExpiryImage(UIFont.monospacedDigitSystemFont(ofSize: 8, weight:.regular), color:.green, spacing: 0.0)
// Default Bold font, red color, size 12dp, negative character spacing - condensed text
UIImage embossNameImage = cardDataImages.getEmbossNameImage(UIFont.systemFont(ofSize: 16, weight: .bold), color:.red, spacing: -0.05)
// Custom font loaded from resources, blue color, size 20dp, positive character spacing - text is expanded
UIImage cvvImage = cardDataImages.getCvvImage((UIFont(name: "CustomFontName", size: 20), color: .blue, spacing: 0.1)
// Default font, black color, size 10dp, default character spacing
UIImage *panImage = [cardDataImages getPanImage:[UIFont systemFontOfSize:10] color:UIColor.blackColor spacing:0.0];
// Default monospace font, green color, size 8dp, default character spacing
UIImage *expiryDateImage = [cardDataImages getExpiryImage:[UIFont monospacedDigitSystemFontOfSize:8 weight:UIFontWeightRegular] color:UIColor.greenColor spacing: 0.0];
// Default Bold font, red color, size 12dp, negative character spacing - condensed text
UIImage *embossNameImage = [cardDataImages getEmbossNameImage:[UIFont systemFontOfSize:16 weight:UIFontWeightBold] color:UIColor.redColor spacing: -0.05];
// Custom font loaded from resources, blue color, size 20dp, positive character spacing - text is expanded
UIImage *cvvImage = [cardDataImages getCvvImage:[UIFont fontWithName:@"CustomFontName" size:20] color: UIColor.blueColor spacing: 0.1];
Copying Card Data to Clipboard
PAN, Expiry Date, Emboss Name and CVV can be copied to clipboard:
- swift
- objective-c
// Copy PAN to clipboard.
cardDataImages.copyPanToClipboard()
// Copy Expiry Date to clipboard.
cardDataImages.copyExpiryToClipboard()
// Copy Emboss Name to clipboard.
cardDataImages.copyEmbossNameToClipboard()
// Copy CVV to clipboard.
cardDataImages.copyCvvToClipboard()
// Copy PAN to clipboard.
[cardDataImages copyPanToClipboard];
// Copy Expiry Date to clipboard.
[cardDataImages copyExpiryToClipboard];
// Copy Emboss Name to clipboard.
[cardDataImages copyEmbossNameToClipboard];
// Copy CVV to clipboard.
[cardDataImages copyCvvToClipboard];
Card Data Cleared Event
MeaCardDataImages.cardDataClearedBlock
sets handler for card data cleared event:
- swift
- objective-c
cardDataImages.cardDataClearedBlock = {
// Handle data cleared event, e.g. clear or hide card data images on the UI.
}
cardDataImages.cardDataClearedBlock = ^{
// Handle data cleared event, e.g. clear or hide card data images on the UI.
};
Card PIN Management
Get Card PIN Image Data
Two input parameters are required to retrieve Card PIN Data:
cardId
- Card ID.secret
- Secret generated on backend, see Time-based Secret (TOTP) Generation.
- swift
- objective-c
import MeaCardData
// ...
let cardId: String = "<value>"
let secret: String = "<value>"
MeaCardData.getCardPinImage(cardId, secret: secret, completionHandler: {(data, error) in
if let carPinImage = data {
// Use retrieved data.
} else {
NSLog("Request failed, %@", error?.localizedDescription ?? "unknown error" )
// Handle error.
}
})
#import <MeaCardData/MeaCardData.h>
// ...
NSString *cardId = @"<value>";
NSString *secret = @"<value>";
[MeaCardData getCardPinImage:cardId secret:secret completionHandler:^(McdCardPinImage *_Nullable cardPinImage, NSError *_Nullable error) {
if (cardPinImage) {
// Use retrieved data.
} else {
NSLog(@"Request failed: %@", [error localizedDescription]);
}
}];;
Card PIN Image
Card PIN can be exported as UIImage
:
- swift
- objective-c
// Default font, black color, size 10dp, default character spacing
UIImage pinImage = cardPinImage.getPinImage(UIFont.systemFont(ofSize: 10), color:.black, spacing:0.0)
// Default font, black color, size 10dp, default character spacing
UIImage *pinImage = [cardPinImage getPinImage:[UIFont systemFontOfSize:10] color:UIColor.blackColor spacing:0.0];
Copying PIN to Clipboard
Card PIN can be copied to clipboard:
- swift
- objective-c
cardPinImage.copyPinToClipboard()
[cardPinImage copyPinToClipboard];
Data Cleared Event
MeaCardPinImage
object provides method to set listener for data cleared event:
- swift
- objective-c
cardPinImage.cardPinClearedBlock = {
// Handle PIN data cleared event, e.g. clear or hide PIN image on the UI.
}
cardPinImage.cardPinClearedBlock = ^{
// Handle PIN data cleared event, e.g. clear or hide PIN image on the UI.
};
Set Card PIN
Four input parameters are required to set Card PIN:
cardId
- Card ID.secret
- Secret generated on backend, see Time-based Secret (TOTP) Generation.oldPin
- Old PIN value.newPin
- New PIN value.
- swift
- objective-c
import MeaCardData
// ...
let cardId: String = "<value>"
let secret: String = "<value>"
let oldPin: String = "<value>"
let newPin: String = "<value>"
MeaCardData.setCardPin(cardId, secret: secret, oldPin:oldPin, newPin:newPin, completionHandler: {(isPinSet, error) in
if error != nil {
NSLog("setCardPin request failed, %@", error?.localizedDescription ?? "unknown error" )
// Handle error.
} else {
// setCardPin request successful.
}
})
#import <MeaCardData/MeaCardData.h>
// ...
NSString *cardId = @"<value>";
NSString *secret = @"<value>";
NSString *oldPin = @"<value>";
NSString *newPin = @"<value>";
[MeaCardData setCardPin:cardId secret:secret oldPin:oldPin newPin:newPin completionHandler:^(McdCardData BOOL isPinSet, NSError *_Nullable error) {
if (error) {
NSLog(@"setCardPin request failed, %@", [error localizedDescription]);
// Handle error.
} else {
// setCardPin request successful.
}
}];
Unblock Card PIN
Two input parameters are required to unblock Card PIN:
cardId
- Card ID.secret
- Secret generated on backend, see Time-based Secret (TOTP) Generation.
- swift
- objective-c
import MeaCardData
// ...
let cardId: String = "<value>"
let secret: String = "<value>"
MeaCardData.unblockCardPin(cardId, secret: secret, completionHandler: {(isPinUnblocked, error) in
if error != nil {
NSLog("unblockCardPin request failed, %@", error?.localizedDescription ?? "unknown error" )
// Handle error.
} else {
// unblockCardPin request successful.
}
})
#import <MeaCardData/MeaCardData.h>
// ...
NSString *cardId = @"<value>";
NSString *secret = @"<value>";
[MeaCardData unblockCardPin:cardId secret:secret completionHandler:^(McdCardData BOOL isPinUnblocked, NSError *_Nullable error) {
if (error) {
NSLog(@"unblockCardPin request failed, %@", [error localizedDescription]);
// Handle error.
} else {
// unblockCardPin request successful.
}
}];
Get Card Data (Deprecated)
This method is deprecated. Use EasyLaunchCardView instead.
The main interface provides getCardData
method to fetch PAN and CVV values of the card.
Two input parameters are required to retrieve card data:
cardId
- Card ID.secret
- Secret generated on backend, see Time-based Secret (TOTP) Generation.
- swift
- objective-c
import MeaCardData
...
let cardId: String = "<value>"
let secret: String = "<value>"
MeaCardData.getCardData(cardId, secret: secret) { (cardData, error) in
if (error != nil) {
print(String(format: "Card data request failed: %@", error!.localizedDescription))
}
else {
let pan = cardData!.pan
let cvv = cardData!.cvv
print(String(format: "Card data fetched successfully, pan: %@, cvv: %@", pan, cvv))
}
}
#import <MeaCardData/MeaCardData.h>
...
NSString *cardId = @"<value>";
NSString *secret = @"<value>";
[MeaCardData getCardData:cardId secret:secret completionHandler:^(McdCardData *_Nullable cardData, NSError *_Nullable error) {
if (error) {
NSLog(@"Card data request failed: %@", [error localizedDescription]);
}
else {
NSString *pan = cardData.pan;
NSString *cvv = cardData.cvv;
NSLog(@"Card data fetched successfully, pan: %@, cvv: %@", pan, cvv);
}
}];
Debugging
Use setDebugLoggingEnabled
method to enable/disable logging to console. Use versionName
and versionCode
methods to check the version of the SDK, when necessary.
- swift
- objective-c
import MeaCardData
...
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
MeaCardData.setDebugLoggingEnabled(true)
print(String(format: "SDK version: %@, code: %@", MeaCardData.versionName(), MeaCardData.versionCode()))
...
return true
}
#import <MeaCardData/MeaCardData.h>
...
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
[MeaCardData setDebugLoggingEnabled:YES];
NSLog(@"SDK version: %@, code: %@", [MeaCardData versionName], [MeaCardData versionCode]);
...
return YES;
}