iOS Checkout SDK Integration Guide
Posted by Paolo Alcabaza, Elijah Joshua Cayabyab • Wednesday December 07, 2016 09:03 AM

The PayMaya iOS Checkout SDK allows your app to accept payments from your customers using any MasterCard and Visa enabled card (credit, debit, or prepaid).

 


Contents

 

Prerequisites

Overview

Integration

Using Checkout

    Initializing the SDK

    Contructing Checkout Information object

    Constructing Buyer Profile

    Constructing Item List

    Constructing Total Amount

    Executing Checkout

Summary

 

Prerequisites

 

Compatibility

 

Your PayMaya iOS Checkout SDK is compatible with the following:

 

  • Xcode 6 or above
  • iOS 6.0+ target deployment
  • armv7, armv7s, and arm64 devices, and the simulator (not armv6)
  • iPhone and iPad of all sizes and resolutions

 

API Keys

 

To use your PayMaya iOS Checkout SDK, you need to have a different API key for Sandbox and Production environment.

 

  • Sandbox Environment

 

Sandbox credentials are used for testing application integration. All transactions made in this environment are only simulated and will not reflect in production. The following sandbox API key can be used for testing purposes:

 

Public-facing API Key: pk-iaioBC2pbY6d3BVRSebsJxghSHeJDW4n6navI7tYdrN

 

  • Production Environment

 

Upon successful integration testing, you can then request for production credentials. Upon receipt, just change your SDK initialization to use production environment to start accepting live transactions.

 

There are two (2) required fields in HTTP Basic Authentication, the username and password. API keys act as the "username" while passwords are set to blank ("").

 

Redirect URLs

 

Redirect URLs are needed by the Checkout payment page to pass the result of the payment transaction. Redirect URLs are either app URL schemes or web site URLs.

 

  1. Successful transaction redirect URL
  2. Failed transaction redirect URL
  3. Canceled transaction redirect URL

 

Overview

 

Checkout handles the entire purchase process for you. From presenting the input customer's card and billing information to actual purchase transaction execution. You just have to standby for the checkout completion status and respond accordingly. If you're looking for a solution with minimal integration, using Checkout is the best option for you.

iOS Checkout Flow

Figure 1 - Checkout transaction flow

 

  1. Customer proceeds with purchase. Your application provides the transaction details and customer provides card and billing information.
  2. Your app receives the checkout completion status.
  3. If checkout is successful, verify that the payment was received in your server and make the necessary server and app-side changes to reflect the transaction. Otherwise, notify the user of the failed transaction.

 

Method completion status is received either via delegates or completion block. The former requires you to implement a class that conforms to a protocol while the latter requires understanding of blocks. As to which of the two callback options you will implement is entirely up to you. For more information, you can refer to the following references about delegates and blocks.

 

Integration

 

Via CocoaPods

 

If you use CocoaPods, then add these lines to your podfile:

platform :ios, '7.0' 
pod 'PayMayaSDK'

 

If you don't use CocoaPods, then you can clone the SDK:

  1. Clone the SDK (https://github.com/PayMaya/PayMaya-iOS-SDK).
  2. Copy the contents of the Pod directory consisting of header and implementation files to your Xcode project. It is recommended to check "Copy items..." and select "Create groups...".

 

Note: Since the SDK is written in Objective-C, projects written in Swift would need to configure a bridging header to use it. More information about this can be found here.

 

Using Checkout

 

    1. Initialize the Checkout SDK by providing your API key and specifying intended environment either sandbox or production. It is recommended to do this in your app delegate's didFinishLaunchingWithOptions: method. Sample credentials provided below should be updated accordingly.

#import "PayMayaSDK.h"

//..

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
    // ...
    [[PayMayaSDK sharedInstance] setCheckoutAPIKey:@"pk-iaioBC2pbY6d3BVRSebsJxghSHeJDW4n6navI7tYdrN"
                                    forEnvironment:PayMayaEnvironmentSandbox];
    // ...
    return YES;
}

    2. Create a PMSDKCheckoutInformation object with total amount, buyer, items, and request reference number as defined in PMSDKCheckoutInformation.h

// SomeViewController.m

(void)checkoutButtonClicked:(id)sender { 
    PMSDKCheckoutInformation *checkoutInformation = [[PMSDKCheckoutInformation alloc] init];  
    
    // Buyer Profile
    PMSDKBuyerProfile *buyerProfile = [[PMSDKBuyerProfile alloc] init]; 
    buyerProfile.firstName = self.firstNameTextField.text; 
    buyerProfile.middleName = self.middleNameTextField.text; 
    buyerProfile.lastName = self.lastNameTextField.text; 

    PMSDKContact *contact = [[PMSDKContact alloc] init]; 
    contact.phone = self.phoneTextField.text; 
    contact.email = self.emailTextField.text;

    PMSDKAddress *address = [[PMSDKAddress alloc] init]; 
    address.primaryAddressLine = self.line1TextField.text; 
    address.secondaryAddressLine = self.line2TextField.text; 
    address.city = self.cityTextField.text; 
    address.state = self.stateTextField.text; 
    address.zipCode = self.zipCodeTextField.text; 
    address.countryCode = self.countryTextField.text; 
    buyerProfile.shippingAddress = address; 
    buyerProfile.billingAddress = address; 
    checkoutInformation.buyer = buyerProfile; 
    
    // Item List
    NSMutableArray *itemsArray = [[NSMutableArray alloc] initWithArray:@[]]; 
    for (NSDictionary *productInfo in self.cartInformation[@"products"]) { 
        PMSDKCheckoutItem *checkoutItem = [[PMSDKCheckoutItem alloc] init]; 
        PMDProduct *product = (PMDProduct *)productInfo[@"product"]; 
        checkoutItem.code = product.code; 
        checkoutItem.name = product.name; 
        checkoutItem.itemDescription = product.itemDescription; 
        checkoutItem.quantity = productInfo[@"quantity"]; 

        PMSDKItemAmount *itemTotalAmount = [[PMSDKItemAmount alloc] init]; 
        itemTotalAmount.value = productInfo[@"totalAmount"]; 
        PMSDKItemAmount *itemAmount = [[PMSDKItemAmount alloc] init]; 
        itemAmount.value = product.amount; 

        checkoutItem.totalAmount = itemTotalAmount; 
        checkoutItem.amount = itemAmount; 
        [itemsArray addObject:checkoutItem]; 
    } 
    checkoutInformation.items = itemsArray; 
    
    // Total Amount
    PMSDKItemAmount *totalAmount = [[PMSDKItemAmount alloc] init]; 
    totalAmount.currency = @"PHP"; 
    totalAmount.value = self.cartInformation[@"total"]; 

    PMSDKItemAmountDetails *totalAmountDetails = [[PMSDKItemAmountDetails alloc] init]; 
    totalAmountDetails.shippingFee = self.cartInformation[@"shippingFee"]; 
    totalAmountDetails.tax = self.cartInformation[@"tax"]; 
    totalAmountDetails.subtotal = self.cartInformation[@"subtotal"]; 
    totalAmount.details = totalAmountDetails; 
    checkoutInformation.totalAmount = totalAmount;

    checkoutInformation.requestReferenceNumber = @"123456789";

    // continued on step 3...

You can also initialize the checkout information object with a dictionary using the defined keys.

    NSDictionary *totalAmount = @{
        @"currency" : @"PHP",
        @"value" : [self.cartInformation[@"total"] stringValue],
        @"details" : @{
            @"shippingFee" : [self.cartInformation[@"shippingFee"] stringValue],
            @"tax" : [self.cartInformation[@"tax"] stringValue],
            @"subtotal" : [self.cartInformation[@"subtotal"] stringValue]
        }
    };
    
    NSDictionary *address = @{
        @"line1" : self.line1TextField.text,
        @"line2" : self.line2TextField.text,
        @"city" : self.cityTextField.text,
        @"state" : self.stateTextField.text,
        @"zipCode" : self.zipCodeTextField.text,
        @"countryCode" : self.countryTextField.text
    };
    
    NSDictionary *buyer = @{
        @"firstName" : self.firstNameTextField.text,
        @"middleName" : self.middleNameTextField.text,
        @"lastName" : self.lastNameTextField.text,
        @"contact" : @{
            @"phone" : self.phoneTextField.text,
            @"email" : self.emailTextField.text
        },
        @"shippingAddress" : address,
        @"billingAddress" : address
    };
    
    NSMutableArray *items = [[NSMutableArray alloc] init];
    for (NSDictionary *productInfo in self.cartInformation[@"products"]) {
        PMDProduct *product = (PMDProduct *)productInfo[@"product"];
        NSDictionary *item = @{
            @"name" : product.name,
            @"code" : product.code,
            @"description" : product.itemDescription,
            @"quantity" : [productInfo[@"quantity"] stringValue],
            @"amount" : @{
                @"value" : [product.amount stringValue]
            },
            @"totalAmount" : @{
                @"value" : [productInfo[@"totalAmount"] stringValue]
            }
        };
        [items addObject:item];
    }
    
    NSDictionary *checkoutDictionary = @{
        @"totalAmount" : totalAmount,
        @"buyer" : buyer,
        @"items" : items,
        @"requestReferenceNumber" : @"123456789"
    };
    
    PMSDKCheckoutInformation *checkoutInformation = [[PMSDKCheckoutInformation alloc] initWithDictionary:checkoutDictionary];
    
    // continued on step 3...

    3. After creation of your checkout information object, you can use this to initiate a checkout transaction. Then, you can get the checkout result via delegate method or completion block.

 

For Sandbox environment, you must only use credit cards from the following link: Credit Cards for Sandbox Testing.

 

    3.a If you opt to use delegation, you must have a class that conforms to PayMayaCheckoutDelegate, call checkout:delegate: method, and implement the required delegate methods.

 

Create a class that conforms to PayMayaCheckoutDelegate protocol

// SomeViewController.h 

@interface SomeViewController : UIViewController 

// ... 

@end

 

Call the checkout:delegate: method to present a view where user can complete the checkout transaction.

    // ...continued from step 2

    [[PayMayaSDK sharedInstance] checkout:checkoutInformation delegate:self];
}

 

Implement the required delegate methods to be called upon checkout completion. The required delegate methods are checkoutDidFinishWithResult: and checkoutDidFailWithError:. The former is called when checkout finished with a valid status while the latter is called when an error is encountered before successful completion.

// SomeViewController.h 

#pragma mark - PayMayaCheckoutDelegate methods

@implementation SomeViewController : UIViewController 

// ... 

- (void)checkoutDidFinishWithResult:(PMSDKCheckoutResult *)result
{
    if (result.status == PMSDKCheckoutStatusUnknown) {
        // handle unknown status
    }
    else if (result.status == PMSDKCheckoutStatusCanceled) {
        // handle canceled status
    }
    else if (result.status == PMSDKCheckoutStatusFailed) {
        // handle failed status
    }
    else if (result.status == PMSDKCheckoutStatusSuccess) {
        // handle success status
    }
}

- (void)checkoutDidFailWithError:(NSError *)error
{
    // handle error
}

@end 

    3.b If you prefer to use blocks, use the checkout:result: method and handle the result accordingly on the completion block.

    // ...continued from step 2

    [[PayMayaSDK sharedInstance] checkout:checkoutInformation result:^(PMSDKCheckoutResult* result, NSError *error) {
        if (error) {
            // handle error
        }
        else {
            if (result.status == PMSDKCheckoutStatusUnknown) {
                // handle unknown status
            }
            else if (result.status == PMSDKCheckoutStatusCanceled) {
                // handle canceled status
            }
            else if (result.status == PMSDKCheckoutStatusFailed) {
                // handle failed status
            }
            else if (result.status == PMSDKCheckoutStatusSuccess) {
                // handle success status
            }
        }
    }];
}

 

Summary

 

  • These docs in the SDK include an overview of usage, step-by-step integration instructions, and sample code.
  • A sample app is included in the SDK.
  • Header files are documented. Refer to them as needed for more information about any given property or parameter.
  • Documentation in appledoc format is available here.
  • Checkout API Documentation and Payments API Documentation are currently available which covers error codes and server-side integration instructions.