Warning: the iOS SDK is still in an alpha stage. Significant API changes may happen before a 1.0 release.
- Overview
- Requirements
- Integrating the SDK
- Customising the app <-> merchant server communication steps
- Customising the card input form
The payment process happens in four steps.
- Card input. The user enters their card details, which are validated for basic errors (length and checksum on the number, length of the verification code, date of expiry in the future).
- API call to the merchant (your) server, requesting EveryPay API credentials.
- EveryPay API call, which saves & validates the card details, and returns an encrypted card token.
- API call to the merchant (your) server with the encrypted card token. The merchant can decrypt the card token with a server-side EveryPay API call, and make a payment immediately or save it for later.
Example implementation is provided for steps 2 and 4, even if they are likely to be replaced in most apps. EPCardInfoViewController can be replaced or modified for step 1 to match your branding.
NB! You have to add following item to your Info.plist file, in order for SDK to work. Otherwise ATS will complain about TLS handshake :
<key>NSAppTransportSecurity</key>
<dict>
<key>NSExceptionDomains</key>
<dict>
<key>3dsecurempi.com</key>
<dict>
<key>NSIncludesSubdomains</key>
<true/>
<key>NSTemporaryExceptionMinimumTLSVersion</key>
<string>TLSv1.0</string>
</dict>
</dict>
</dict>
iOS 8 or later is required for NSURLSession that is used in everyPay SDK.
Add folder sdk to your project and include EPApi.h where needed.
Add 'everyPay-ios' to podfile.
Modify kEveryPayApiLive and kEveryPayApiTesting URLs in Constants.h to your needs.
NSString *const kEveryPayApiTesting = YOUR_TESTING_URL;
NSString *const kEveryPayApiLive = YOUR_LIVE_URL;
Open a EPCardInfoViewController from your viewcontroller:
EPCardInfoViewController *cardInfoViewController = [[EPCardInfoViewController alloc] initWithNibName:NSStringFromClass([EPCardInfoViewController class]) bundle:nil];
[cardInfoViewController setDelegate:self];
[self presentViewController:cardInfoViewController animated:YES completion:nil];
//or if you are using navigationController
[self.navigationController pushViewController:cardInfoViewController animated:YES];
cardInfoViewController.edgesForExtendedLayout = UIRectEdgeNone;
Let your viewcontroller implement EPCardViewControllerDelegate method cardInfoViewController:didEnterInfoForCard:
.
After user has entered all needed data this delegate method will be called with a validated EPCard object.
- (void)cardInfoViewController:(UIViewController *)controller didEnterInfoForCard:(EPCard *)card {
[self dismissViewControllerAnimated:YES completion:nil];
//Or for navigation contoller
[self.navigationController popToViewController:self animated:YES];
[self sendCardInfoToMerchant:card];
}
Call sendCard:withMerchantInfo:withSuccess:andError:
, where merchantinfo
is dictionary containing your EveryPay username, account, ip and security info:
//For non-3Ds
"account_id" = EUR1;
"api_username" = apiuserame;
hmac = 6c893c8642176b401e918ba61a47123456780c1d;
nonce = b58a1ff58cd9817347e206f30fcb82d5;
timestamp = 1440506937;
"user_ip" = "100.100.100.100";
//For 3Ds
"account_id" = EUR3D1;
"api_username" = apiuserame;
hmac = 6c893c8642176b401e918ba61a47123456780c1d;
nonce = b58a1ff58cd9817347e206f30fcb82d5;
timestamp = 1440506937;
"user_ip" = "100.100.100.100";
"payment_state"="waiting_for_3ds_response"
"order_reference" =85928hshjsdhjfkhkjh4;
[self.epApi sendCard:card withMerchantInfo:merchantInfo withSuccess:^(NSDictionary *responseDictionary) {
NSString *paymentState = [responseDictionary objectForKey:kPaymentState];
if([paymentState isEqualToString:kPaymentStateWaiting3DsResponse] && [accountId containsString:@"3D"]){
[self appendProgressLog:@"Done"];
NSString *paymentReference = [responseDictionary objectForKey:kKeyPaymentReference];
NSString *secureCodeOne = [responseDictionary objectForKey:kKeySecureCodeOne];
NSString *hmac = [merchantInfo objectForKey:kKeyHmac];
[self appendProgressLog:@"Starting 3DS authentication..."];
[self startWebViewWithPaymentReference:paymentReference secureCodeOne:secureCodeOne hmac:hmac];
} else if (![paymentState isEqualToString:kFailed]) {
NSString *token = [responseDictionary objectForKey:kKeyEncryptedToken];
[self appendProgressLog:@"Done"];
[self payWithToken:token andMerchantInfo:merchantInfo];
} else {
[self showAlertWithError:[NSError errorWithDomain:@"Unknown account id or payment state" code:1001 userInfo:nil]];
}
} andError:^(NSArray *errors) {
[self showAlertWithError:[errors firstObject]];
}];
Success block will be called with encrypted token if it's non-3Ds payment. For 3Ds payment order_reference and payment_state are returned, failure block will contain array of NSError objects. Both blocks will be called on main thread.
Open a EPAuthenticationWebViewController from your viewcontroller:
EPAuthenticationWebViewController *authenticationWebViewController = [[EPAuthenticationWebViewController alloc] initWithNibName:NSStringFromClass([EPAuthenticationWebViewController class]) bundle:nil];
[authenticationWebViewController setDelegate:self];
[authenticationWebViewController addURLParametersWithPaymentReference:paymentReference secureCodeOne:secureCodeOne hmac:hmac];
[self presentViewController:authenticationWebViewController animated:YES completion:nil];
//or if you are using navigationController
[self.navigationController pushViewController:authenticationWebViewController animated:YES];
NB! you have to call addURLParametersWithPaymentReference:paymentReference secureCodeOne:secureCodeOne hmac:hmac];
in order for webview to navigate to correct URL.
Let your viewcontroller implement EPAuthenticationWebViewControllerDelegate methods
NB! You have to close the EPAuthenticationViewController inside every delegate method. It will not close automatically!
authenticationSucceededWithPaymentReference:
- (void)authenticationSucceededWithPaymentReference:(NSString *)paymentReference {
[self dismissViewControllerAnimated:YES completion:nil];
//Or for navigation contoller
[self.navigationController popToViewController:self animated:YES];
[EPApi encryptedPaymentInstrumentsConfirmedWithPaymentReference:paymentReference hmac:hmac apiVersion:apiVersion withSuccess:^(NSDictionary *dictionary) {
NSString *token = [dictionary objectForKey:kKeyEncryptedToken];
[self payWithToken:token andMerchantInfo:merchantInfo];
} andError:^(NSArray *array) {
// Show error. Getting error like that array[0];
}];
}
authenticationFailedWithErrorCode:
- (void)authenticationFailedWithErrorCode:(NSInteger)errorCode {
[self dismissViewControllerAnimated:YES completion:nil];
//Or for navigation contoller
[self.navigationController popToViewController:self animated:YES];
//Display error here...
}
authenticationCanceled:
- (void)authenticationCanceled {
//Show canceling error here or do nothing...
}
The SDK includes example implementation for the app - merchant API calls, with the minimal required data for a payment. However, most apps using EveryPay will want to replace the communication step between the app and your server - for example to add your own user accounts, save shopping baskets or subscription plans. To provide a replacement, rewrite methods in EPMerchantApi class.
If the EveryPay card input form does not match your requirements, or if you wish to add custom branding beyond the configuration options, then you can create a custom one. There are two requirements for a custom card form:
- It should construct a EPCard. The Card model can also be used to validate the inputs.