Overview
The Telr Mobile Payment SDK for iOS is a comprehensive payment solution that enables merchants to accept payments seamlessly within their iOS applications. Built with SwiftUI and following modern iOS development patterns, it provides a clean, secure, and customizable payment experience.
Key Features
- Multiple Payment Methods: Credit/Debit Cards, Apple Pay
- 3D Secure Support: Built-in 3DS authentication flow
- Saved Cards: Tokenization and card management
- Modern UI: SwiftUI-based interface with iOS design guidelines
- Internationalization: Multi-language support (English, Arabic)
- Security: PCI DSS compliant with tokenization
- Accessibility: Full accessibility support for inclusive design
Requirements
- iOS 15.1+
- Swift 6.0+
- Xcode 15.0+
- CocoaPods 1.11+ (if using CocoaPods)
- Your backend must return two URLs taken directly from the createOrder API response:
- tokenUrl — value of _links.auth.href
- orderUrl — value of _links.self.href
Installation
CocoaPods (Recommended)
-
Install CocoaPods (if not already installed):
sudo gem install cocoapods
-
Create or update your Podfile:
platform :ios, '15.1' use_frameworks! inhibit_all_warnings! target 'YourAppTarget' do pod 'TelrSDK', '~> 0.0.20' end
-
Install the SDK:
pod install
-
Open the workspace:
open YourApp.xcworkspace
-
Import the SDK in your Swift files:
import MobilePaymentSDK
CocoaPods Troubleshooting
If you encounter build issues with newer Xcode versions, add this to your Podfile:
post_install do |installer|
installer.pods_project.targets.each do |t|
t.build_configurations.each do |config|
config.build_settings['ENABLE_USER_SCRIPT_SANDBOXING'] = 'NO'
end
end
installer.aggregate_targets.each do |t|
t.user_project.native_targets.each do |nt|
nt.build_configurations.each do |config|
config.build_settings['ENABLE_USER_SCRIPT_SANDBOXING'] = 'NO'
end
end
end
end
Swift Package Manager
Via Xcode (Recommended)
- In Xcode, go to File > Add Package Dependencies
- Enter the repository URL:
https://github.com/Telr-PG/telr-sdk-ios
- Select version rule (e.g., "Up to Next Major") and pick release (e.g., 0.0.20)
- Add the product
MobilePaymentSDK
to your target
Via Package.swift
// swift-tools-version: 6.0
import PackageDescription
let package = Package(
name: "YourApp",
platforms: [
.iOS(.v15)
],
dependencies: [
.package(url: "https://github.com/Telr-PG/telr-sdk-ios.git", .upToNextMajor(from: "0.0.20"))
],
targets: [
.target(
name: "YourApp",
dependencies: [
.product(name: "MobilePaymentSDK", package: "telr-sdk-ios")
]
)
]
)
Carthage
-
Add to Cartfile:
binary "https://raw.githubusercontent.com/Telr-PG/telr-sdk-ios/main/MobilePaymentSDK.json" ~> 0.0.20
-
Update dependencies:
carthage update --use-xcframeworks --platform iOS
-
Add to Xcode:
- Drag
Carthage/Build/MobilePaymentSDK.xcframework
into your project - Set to "Embed & Sign" in Frameworks, Libraries, and Embedded Content
- Drag
Manual Installation
-
Download the framework:
- Download
MobilePaymentSDK.xcframework.zip
from Releases - Unzip to get
MobilePaymentSDK.xcframework
- Download
-
Add to Xcode:
- Drag the framework into your project navigator
- Check "Copy items if needed" and select your target
- Set to "Embed & Sign" in project settings
Quick Start
Basic Implementation
import SwiftUI
import MobilePaymentSDK
struct PaymentView: View {
@State private var showPayment = false
private let paymentSDK = PaymentSDK()
var body: some View {
VStack {
Button("Pay Now") {
showPayment = true
}
}
.fullScreenCover(isPresented: $showPayment) {
paymentSDK.paymentView(
tokenURL: "https://api.telr.com/token",
orderURL: "https://api.telr.com/order/123",
onFinish: { response in
if response.success {
print("Payment successful: \(response.message)")
} else {
print("Payment failed: \(response.message)")
}
showPayment = false
}
)
}
}
}
UIKit Integration
import UIKit
import MobilePaymentSDK
class PaymentViewController: UIViewController {
private let paymentSDK = PaymentSDK()
func showPayment() {
let paymentView = paymentSDK.paymentView(
tokenURL: "https://api.telr.com/token",
orderURL: "https://api.telr.com/order/123",
onFinish: { response in
DispatchQueue.main.async {
if response.success {
self.showAlert(title: "Success", message: response.message)
} else {
self.showAlert(title: "Error", message: response.message)
}
}
}
)
let hostingController = UIHostingController(rootView: paymentView)
present(hostingController, animated: true)
}
private func showAlert(title: String, message: String) {
let alert = UIAlertController(title: title, message: message, preferredStyle: .alert)
alert.addAction(UIAlertAction(title: "OK", style: .default))
present(alert, animated: true)
}
}
Configuration
Basic Configuration
let configuration = PaymentSDKConfiguration(
maxRetries: 1,
debugLoggingEnabled: false,
preferredLanguageCode: "en"
)
let paymentSDK = PaymentSDK(configuration: configuration)
Builder Pattern Configuration
let configuration = PaymentSDKConfiguration.builder()
.withMaxRetries(1)
.withDebugLoggingEnabled(true) // Enable for development
.withPreferredLanguageCode("ar") // Arabic support
.build()
let paymentSDK = PaymentSDK(configuration: configuration)
Configuration Options
Parameter | Type | Default | Description |
---|---|---|---|
maxRetries | Int | 1 | Maximum retry attempts for failed requests |
debugLoggingEnabled | Bool | false | Enable debug logging (development only) |
preferredLanguageCode | String? | nil | Override language ("en", "ar") |
Runtime Configuration Updates
// Update configuration at runtime
let newConfig = PaymentSDKConfiguration.builder()
.withPreferredLanguageCode("ar")
.build()
paymentSDK.updateConfiguration(newConfig)
Note: Views already created with paymentView
will not automatically pick up configuration changes. Create a new view after updating configuration if you need the new config applied.
Payment Methods
Supported Payment Methods
The SDK supports the following payment methods:
-
Credit/Debit Cards
- Visa, Mastercard, American Express
- 3D Secure authentication
- Card tokenization for future payments
-
Apple Pay
- Native Apple Pay integration
- Touch ID/Face ID authentication
- Secure element processing
Card Payment Features
New Card Payment
- Real-time card validation
- BIN lookup for card scheme detection
- CVV and expiry validation
- Cardholder name validation
Saved Cards
- Tokenized card storage
- Quick payment with saved cards
- Card management (view/delete)
3D Secure Authentication
- Automatic 3DS challenge handling
- WebView-based authentication flow
- Seamless user experience
Apple Pay Integration
Apple Pay is automatically available when:
- Device supports Apple Pay
- User has cards in Wallet
- Merchant has Apple Pay enabled
The SDK handles Apple Pay availability detection and presents the option when appropriate.
Error Handling
SDK Response Format
All payment operations return a standardized response:
public struct SDKPaymentResponse {
public let success: Bool
public let message: String
public let errorCode: String?
}
Common Error Scenarios
Network Errors
.onFinish { response in
if !response.success {
switch response.errorCode {
case "NETWORK_ERROR":
// Handle network connectivity issues
break
case "TIMEOUT":
// Handle request timeout
break
case "SERVER_ERROR":
// Handle server-side errors
break
default:
// Handle other errors
break
}
}
}
Payment Failures
.onFinish { response in
if !response.success {
// Payment failed
print("Payment failed: \(response.message)")
print("Error code: \(response.errorCode ?? "Unknown")")
// Show user-friendly error message
showErrorAlert(message: response.message)
} else {
// Payment successful
print("Payment successful: \(response.message)")
showSuccessAlert(message: response.message)
}
}
Error Codes Reference
Error Code | Description | Action Required |
---|---|---|
NETWORK_ERROR | Network connectivity issue | Check internet connection |
TIMEOUT | Request timeout | Retry payment |
SERVER_ERROR | Server-side error | Contact support |
INVALID_TOKEN | Authentication failed | Refresh token |
PAYMENT_DECLINED | Card declined | Try different payment method |
3DS_FAILED | 3D Secure authentication failed | Retry payment |
USER_CANCELLED | User cancelled payment | No action required |
Internationalization
Supported Languages
- English (Base) - Default
- Arabic (
ar
) - RTL support
Language Configuration
Automatic Language Detection
By default, the SDK follows the host app's preferred language:
let paymentSDK = PaymentSDK() // Uses system language
Manual Language Override
let configuration = PaymentSDKConfiguration.builder()
.withPreferredLanguageCode("ar") // Force Arabic
.build()
let paymentSDK = PaymentSDK(configuration: configuration)
RTL Support
The SDK fully supports right-to-left (RTL) languages:
- Automatic layout direction detection
- Proper text alignment
- Icon and image mirroring
- Form field positioning
Troubleshooting
Common Issues
1. "No such module 'MobilePaymentSDK'"
Causes:
- Framework not properly linked
- Wrong import statement
- Build configuration issue
Solutions:
- Ensure framework is added to "Frameworks, Libraries, and Embedded Content"
- Check that you're importing
MobilePaymentSDK
(notTelrSDK
) - Clean build folder and rebuild
2. "Image not found" at Runtime
Causes:
- Framework not embedded
- Architecture mismatch
Solutions:
- Set framework to "Embed & Sign" in project settings
- Ensure you're using the correct XCFramework for your target architecture
3. CocoaPods Build Errors
Causes:
- Script sandboxing enabled
- Derived data corruption
- Pod cache issues
Solutions:
# Clean derived data
rm -rf ~/Library/Developer/Xcode/DerivedData/*
# Clean pod cache
pod cache clean --all
# Reinstall pods
pod deintegrate
pod install
4. Carthage Framework Issues
Causes:
- Not using XCFrameworks
- Framework not properly embedded
Solutions:
# Ensure XCFrameworks are used
carthage update --use-xcframeworks --platform iOS
# Verify framework is embedded
# Check project settings > Frameworks, Libraries, and Embedded Content
5. Payment Not Processing
Causes:
- Invalid URLs
- Network connectivity
- Server configuration
Solutions:
- Verify token and order URLs are correct
- Check network connectivity
- Enable debug logging to see detailed error messages
- Verify server endpoints are accessible
Debug Logging
Enable debug logging for development:
let configuration = PaymentSDKConfiguration.builder()
.withDebugLoggingEnabled(true)
.build()
let paymentSDK = PaymentSDK(configuration: configuration)
Debug logs will show:
- Network requests and responses
- Error details
- SDK internal state
- Validation results
Performance Optimization
Memory Management
- The SDK automatically manages memory for payment views
- Views are released when payment completes or is cancelled
- No manual cleanup required
Network Optimization
- Requests are automatically retried on failure
- Timeout intervals are configurable
API Reference
PaymentSDK
Main SDK class for payment processing.
public class PaymentSDK {
public init(configuration: PaymentSDKConfiguration = PaymentSDKConfiguration())
public func updateConfiguration(_ configuration: PaymentSDKConfiguration)
@MainActor
public func paymentView(
tokenURL: String,
orderURL: String,
onFinish: @escaping (SDKPaymentResponse) -> Void
) -> some View
}
PaymentSDKConfiguration
Configuration class for SDK customization.
public struct PaymentSDKConfiguration {
public let maxRetries: Int
public let debugLoggingEnabled: Bool
public let preferredLanguageCode: String?
public static func builder() -> Builder
public init(builder configure: (input Builder) -> Void)
}
SDKPaymentResponse
Response object for payment operations.
public struct SDKPaymentResponse {
public let success: Bool
public let message: String
public let errorCode: String?
public static func success(message: String) -> SDKPaymentResponse
public static func failure(message: String, errorCode: String?) -> SDKPaymentResponse
}
Order Model
Order information structure.
public struct Order {
public let ref: String
public let amount: Amount
public let status: OrderStatus
public let allowedPaymentMethods: [PaymentMethod]?
public let _links: OrderLinks?
public let payments: [PaymentResponse]?
}
Amount Model
Payment amount structure.
public struct Amount {
public let value: String
public let currency: String?
}
PaymentMethod
Supported payment method entry returned with an order.
public struct PaymentMethod {
public let schemes: [String] // e.g. ["VISA", "MASTERCARD"]
public let type: PaymentMethodType // .card, .applePay
}
PaymentMethodType
Type of payment method available for the order.
public enum PaymentMethodType: String {
case card = "CARD"
case applePay = "APPLE_PAY"
}
OrderStatus
High-level status of the order.
public enum OrderStatus: String {
case pending = "PENDING"
case authorised = "AUTHORISED"
case paid = "PAID"
case cancelled = "CANCELLED"
case declined = "DECLINED"
}
OrderLinks (SDK-internal)
Links to operations/endpoints associated with the order (card, Apple Pay, 3DS, etc.). These are used internally by the SDK.