Checkout iOS SDK

A comprehensive iOS SDK for integrating payment processing into your iOS applications. This SDK provides a secure, user-friendly checkout experience with support for multiple payment methods, currencies, and customization options.

Table of Contents

Overview

The Checkout iOS SDK allows you to integrate payment processing into your iOS app with just a few lines of code. It handles the complex payment flow, security, and user interface, so you can focus on your app's core functionality.

Github link

What does it do?

  • πŸ’³ Processes payments securely
  • 🌍 Supports multiple currencies and payment methods
  • πŸ“± Handles both card and digital wallet payments
  • πŸ” Manages security and encryption automatically

Features

βœ… Multiple Payment Methods: Credit/Debit cards, Apple Pay, Google Pay, and more

βœ… Multi-Currency Support: Process payments in various currencies

βœ… Localization: Support for English and Arabic languages

βœ… Security: Built-in encryption and security measures

βœ… Card Scanner: Scan card details using device camera

βœ… Real-time Validation: Instant feedback on payment details

Requirements

  • iOS 13.0 or later
  • Xcode 12.0 or later
  • Swift 5.0 or later

Swift Package Manager

  1. Open your project in Xcode
  2. Go to File > Add Package Dependencies
  3. Enter the repository URL: https://github.com/your-repo/Checkout-IOS.git
  4. Click Add Package

Manual Installation

  1. Download the SDK from the releases page
  2. Drag the Checkout-IOS folder into your Xcode project
  3. Make sure to add it to your target

Quick Start

Here's how to get started with the Checkout SDK in just 5 minutes:

1. Import the SDK

import Checkout_IOS

2. Create a Basic Checkout

class ViewController: UIViewController {
    
    override func viewDidLoad() {
        super.viewDidLoad()
        setupCheckoutButton()
    }
    
    func setupCheckoutButton() {
        let checkoutButton = UIButton(type: .system)
        checkoutButton.setTitle("Pay Now", for: .normal)
        checkoutButton.addTarget(self, action: #selector(startCheckout), for: .touchUpInside)
        // Add button to your view and set constraints
    }
    
    @objc func startCheckout() {
        // Minimum required configuration
        let config = [
        "hashString": "",
        "language": "en",
        "themeMode": "light",
        "supportedPaymentMethods": "ALL",
        "paymentType": "ALL",
        "selectedCurrency": "KWD",
        "supportedCurrencies": "ALL",
        "supportedPaymentTypes": [],
        "supportedRegions": [],
        "supportedSchemes": [],
        "supportedCountries": [],
        "gateway": [
            "publicKey": "pk_key",
            "merchantId": ""
        ],
        "customer": [
            "firstName": "Android",
            "lastName": "Test",
            "email": "[email protected]",
            "phone": [
                "countryCode": "965",
                "number": "55567890"
            ]
        ],
        "transaction": [
            "mode": "charge",
            "charge": [
                "saveCard": true,
                "auto": [
                    "type": "VOID",
                    "time": 100
                ],
                "redirect": [
                    "url": "https://demo.staging.tap.company/v2/sdk/checkout"
                ],
                "threeDSecure": true,
                "subscription": [
                    "type": "SCHEDULED",
                    "amount_variability": "FIXED",
                    "txn_count": 0
                ],
                "airline": [
                    "reference": [
                        "booking": ""
                    ]
                ]
            ]
        ],
        "amount": "5",
        "order": [
            "id": "",
            "currency": "KWD",
            "amount": "5",
            "items": [
                [
                    "amount": "5",
                    "currency": "KWD",
                    "name": "Item Title 1",
                    "quantity": 1,
                    "description": "item description 1"
                ]
            ]
        ],
        "cardOptions": [
            "showBrands": true,
            "showLoadingState": false,
            "collectHolderName": true,
            "preLoadCardName": "",
            "cardNameEditable": true,
            "cardFundingSource": "all",
            "saveCardOption": "all",
            "forceLtr": false,
            "alternativeCardInputs": [
                "cardScanner": true,
                "cardNFC": true
            ]
        ],
        "isApplePayAvailableOnClient": true,
    ]
        
        // Start the checkout process
        CheckoutSDK().start(configurations: config, delegate: self)
    }
}

3. Handle the Results

extension ViewController: CheckoutSDKDelegate {
    var controller: UIViewController {
        return self
    }
    
    func onReady() {
        print("Checkout is ready!")
    }
    
    func onSuccess(data: String) {
        print("Payment successful: \(data)")
        // Handle successful payment
    }
    
    func onError(data: String) {
        print("Payment failed: \(data)")
        // Handle payment error
    }
    
    func onClose() {
        print("Checkout was closed")
        // Handle checkout cancellation
    }
}

That's it! You now have a working payment system.

Basic Usage

Understanding the Flow

sequenceDiagram
    participant App as Your App
    participant SDK as Checkout SDK
    participant UI as Payment UI
    participant Server as Payment Server
    
    App->>SDK: start(configurations, delegate)
    SDK->>UI: Present checkout interface
    UI->>App: onReady()
    
    Note over UI: User enters payment details
    
    UI->>Server: Process payment
    Server->>UI: Payment result
    
    alt Payment Success
        UI->>App: onSuccess(data)
    else Payment Failed
        UI->>App: onError(data)
    end
    
    UI->>App: onClose()

Step-by-Step Integration

Step 1: Configure Your Payment

let configurations = [
    // Required: Amount to charge
    "amount": "25.99",
    
    // Required: Gateway configuration
    "gateway": [
        "publicKey": "pk_test_your_key_here",
        "merchantId": "your_merchant_id"
    ],
    
    // Required: Customer information
    "customer": [
        "firstName": "John",
        "lastName": "Doe",
        "email": "[email protected]",
        "phone": [
            "countryCode": "1",
            "number": "1234567890"
        ]
    ],
    
    // Required: Order details
    "order": [
        "currency": "USD",
        "amount": "25.99",
        "items": [
            [
                "name": "Premium Subscription",
                "amount": "25.99",
                "currency": "USD",
                "quantity": 1,
                "description": "Monthly premium subscription"
            ]
        ]
    ]
]

Step 2: Initialize and Start

let checkoutSDK = CheckoutSDK()
checkoutSDK.start(configurations: configurations, delegate: self)

Step 3: Implement the Delegate

extension YourViewController: CheckoutSDKDelegate {
    // This tells the SDK which view controller to present from
    var controller: UIViewController {
        return self
    }
    
    // Called when the checkout UI is ready
    func onReady() {
        // Optional: Show loading indicator, log analytics, etc.
        print("Checkout interface is ready")
    }
    
    // Called when payment is successful
    func onSuccess(data: String) {
        // Parse the success data and update your UI
        print("Payment completed successfully!")
        
        // Example: Show success message
        showSuccessAlert(message: "Payment successful!")
        
        // Example: Navigate to success screen
        navigateToSuccessScreen()
    }
    
    // Called when payment fails
    func onError(data: String) {
        // Parse the error data and handle accordingly
        print("Payment failed: \(data)")
        
        // Example: Show error message
        showErrorAlert(message: "Payment failed. Please try again.")
    }
    
    // Called when user closes the checkout
    func onClose() {
        // Handle checkout cancellation
        print("User closed the checkout")
    }
}

Configuration

Basic Configuration Options

let configurations = [
    // REQUIRED FIELDS
    "amount": "10.00",                    // Amount to charge
    "gateway": [...],                     // Gateway configuration
    "customer": [...],                    // Customer details
    "order": [...],                       // Order information
    
    // OPTIONAL FIELDS
    "language": "en",                     // "en" or "ar"
    "themeMode": "light",                 // "light", "dark", "light_mono", "dark_colored"
    "supportedPaymentMethods": "ALL",     // "ALL" or specific methods
    "selectedCurrency": "USD",            // Default currency
    "paymentType": "ALL"                  // "ALL", "WEB", "CARD", "DEVICE"
]

Gateway Configuration

"gateway": [
    "publicKey": "pk_test_your_public_key",    // Your public key from the dashboard
    "merchantId": "your_merchant_id"           // Your merchant ID
]

⚠️ Important: Use pk_test_ for testing and pk_live_ for production.

Customer Configuration

"customer": [
    "firstName": "John",
    "lastName": "Doe",
    "email": "[email protected]",
    "phone": [
        "countryCode": "1",               // Country code without +
        "number": "1234567890"            // Phone number
    ]
]

Order Configuration

"order": [
    "id": "order_123",                    // Optional: Your order ID
    "currency": "USD",                    // Currency code (USD, EUR, GBP, etc.)
    "amount": "25.99",                    // Order amount
    "items": [                            // Array of items
        [
            "name": "Product Name",
            "amount": "25.99",
            "currency": "USD",
            "quantity": 1,
            "description": "Product description"
        ]
    ]
]

Callbacks

Understanding what each callback means and how to handle them:

onReady()

func onReady() {
    // The checkout interface has loaded and is ready for user interaction
    // This is a good place to:
    // - Hide loading indicators
    // - Log analytics events
    // - Update UI state
}

onSuccess(data: String)

func onSuccess(data: String) {
    // Payment was processed successfully
    // The 'data' parameter contains payment details in JSON format
    
    // Example of parsing the data:
    if let jsonData = data.data(using: .utf8) {
        do {
            let paymentResult = try JSONSerialization.jsonObject(with: jsonData) as? [String: Any]
            let transactionId = paymentResult?["id"] as? String
            print("Transaction ID: \(transactionId ?? "Unknown")")
        } catch {
            print("Failed to parse payment data")
        }
    }
    
    // Update your app's state
    // - Save transaction details
    // - Update user's account
    // - Show success message
    // - Navigate to confirmation screen
}

onError(data: String)

func onError(data: String) {
    // Payment failed or encountered an error
    // The 'data' parameter contains error details
    
    // Common error handling:
    if data.contains("cancelled") {
        // User cancelled the payment
        print("Payment was cancelled by user")
    } else if data.contains("declined") {
        // Payment was declined
        print("Payment was declined")
        showAlert(title: "Payment Declined", message: "Please check your card details")
    } else {
        // Other errors
        print("Payment error: \(data)")
        showAlert(title: "Error", message: "Something went wrong. Please try again.")
    }
}

onClose()

func onClose() {
    // The checkout interface was closed
    // This is called after onSuccess, onError, or when user manually closes
    
    // Clean up any resources
    // - Remove loading indicators
    // - Reset UI state
    // - Log analytics
}

Advanced Features

Theme Customization

"themeMode": "light"        // Default light theme
"themeMode": "dark"         // Dark theme
"themeMode": "light_mono"   // Light monochrome
"themeMode": "dark_colored" // Dark with colors

Payment Method Selection

// Allow all payment methods
"supportedPaymentMethods": "ALL"

// Specific payment methods
"supportedPaymentMethods": ["VISA", "MASTERCARD", "APPLE_PAY"]

Card Options

"cardOptions": [
    "showBrands": true,                    // Show card brand logos
    "collectHolderName": true,             // Ask for cardholder name
    "cardNameEditable": true,              // Allow editing card name
    "saveCardOption": "all",               // Show save card option
    "alternativeCardInputs": [
        "cardScanner": true,               // Enable card scanning
        "cardNFC": true                    // Enable NFC reading
    ]
]

Multi-language Support

"language": "en"    // English
"language": "ar"    // Arabic

Example App

The following example app demonstrates all SDK features:

https://github.com/Tap-Payments/Checkout-IOS/tree/main/CheckoutExample

Running the Example

  1. Open CheckoutExample.xcodeproj
  2. Add your test API keys in ViewController.swift
  3. Run the app on simulator or device

Key Features Demonstrated

  • Basic Integration: Simple payment flow
  • Configuration Options: All customization options
  • Callback Handling: Proper response handling
  • UI Customization: Theme and language options

Example App Structure

CheckoutExample/
β”œβ”€β”€ ViewController.swift              # Main example implementation
β”œβ”€β”€ CheckoutSettingsViewController.swift  # Configuration options
└── Storyboards/                     # UI layouts

Troubleshooting

Common Issues

1. SDK Not Starting

Problem: Nothing happens when calling start()
Solution:

  • Check that all required fields are provided
  • Verify your public key is correct
  • Ensure the delegate is properly set

2. Payment Fails Immediately

Problem: onError is called immediately
Solution:

  • Verify your API keys are correct
  • Check network connectivity
  • Ensure amount is properly formatted

3. UI Not Displaying Properly

Problem: Checkout interface looks broken
Solution:

  • Check iOS version compatibility
  • Verify theme mode settings
  • Test on different devices

4. Callbacks Not Working

Problem: Delegate methods not being called
Solution:

  • Ensure your class conforms to CheckoutSDKDelegate
  • Check that controller property returns the correct view controller
  • Verify delegate is set before calling start()

Debug Mode

// Enable debug logging (for development only)
CheckoutSDK.debugMode = true

Testing

  • Use test API keys for development
  • Test with different card numbers
  • Verify error handling with invalid data

Architecture

SDK Structure Overview

graph TB
    A[Your App] --> B[CheckoutSDK]
    B --> C[CheckoutViewController]
    C --> D[WebView Payment Interface]
    C --> E[Network Layer]
    C --> F[Security Layer]
    
    B --> G[CheckoutSDKDelegate]
    G --> H[onReady]
    G --> I[onSuccess]
    G --> J[onError]
    G --> K[onClose]
    
    E --> L[Payment Gateway]
    F --> M[Encryption/Security]

API Reference

CheckoutSDK

Methods

func start(configurations: [String: Any], delegate: CheckoutSDKDelegate)

Starts the checkout process with the given configuration.

Parameters:

  • configurations: Dictionary containing payment configuration
  • delegate: Object implementing CheckoutSDKDelegate protocol

CheckoutSDKDelegate

Required protocol for handling checkout events.

Properties

var controller: UIViewController { get }

The view controller that should present the checkout interface.

Methods

func onReady()

Called when the checkout interface is ready for user interaction.

func onSuccess(data: String)

Called when payment is processed successfully.

  • data: JSON string containing payment details
func onError(data: String)

Called when payment fails or encounters an error.

  • data: String containing error information
func onClose()

Called when the checkout interface is closed.

Support

For questions, issues, or feature requests: