This guide details how to install the Payrails SDK into your iOS project using CocoaPods.
Prerequisites:
- CocoaPods installed.
- Your Xcode project targets iOS 14.0 or later.
Installation Steps:
-
Add Payrails to your Podfile:
If you don't have aPodfile
in your project's root directory, runpod init
in your terminal from that directory. Then, open thePodfile
and add the following line within your target's dependencies:target 'YourAppTargetName' do use_frameworks! # Ensure you are using frameworks # Add the Payrails Checkout SDK pod 'Payrails/Checkout', '~> 1.0.0' # Or specify the version you need # ... other pods end
Note: Using
~> 1.0.0
will install the latest compatible version within the 1.0.x range. You can remove the version specifier ('Payrails/Checkout'
) to always get the absolute latest version, or specify an exact version. -
Install the Pod:
Close Xcode. Open your terminal, navigate to your project's root directory (where thePodfile
is located), and run:pod install
-
Use the .xcworkspace:
After the installation is complete, always open your project using the.xcworkspace
file generated by CocoaPods, not the.xcodeproj
file.open YourProjectName.xcworkspace
-
Import the Module:
You can now import the Payrails SDK module in your Swift files where needed:
Before you can display any Payrails UI components (like the Card Payment Form or PayPal Button), you need to initialize a Payrails.Session
. This session holds the configuration and state for the user's payment interaction.
Prerequisites:
- SDK Installation: Ensure the Payrails SDK is correctly installed in your project (see Installation Guide).
Payrails.InitData
: You must obtain an instance ofPayrails.InitData
.- This data is crucial and must be fetched from your backend. Your server will typically interact with the Payrails API, providing transaction details (like amount, currency, references, user info), to generate this
InitData
. - The SDK does not handle the network request to fetch this data. You are responsible for implementing this API call. The
InitSettings
and the API call shown in the exampleTestViewController
are illustrative of how you might fetch this data; they are not part of the SDK itself.
- This data is crucial and must be fetched from your backend. Your server will typically interact with the Payrails API, providing transaction details (like amount, currency, references, user info), to generate this
Initialization Steps:
-
Obtain
Payrails.InitData
: Fetch this data from your backend server. Let's assume you have it in a variable namedfetchedInitData
. -
Define
Payrails.Options
(Optional): Configure SDK options, such as the environment (.prod
or.sandbox
).// Example: Configure for the production environment let options = Payrails.Options(env: .prod) // Or for development: // let options = Payrails.Options(env: .dev)
-
Create
Payrails.Configuration
: Combine the fetchedInitData
and any customOptions
.// Assuming 'fetchedInitData' is the Payrails.InitData obtained from your backend let configuration = Payrails.Configuration( initData: fetchedInitData, option: options // Use the options defined above )
-
Call
Payrails.configure
: Use the staticconfigure
function, passing theconfiguration
. This is an asynchronous operation.// This function should be called within an async context (e.g., Task or async function) do { // This asynchronously configures and returns the session let payrailsSession = try await Payrails.configure(with: configuration) // **Important:** Store the 'payrailsSession' instance. // You will need it to create UI components later. self.payrails = payrailsSession // Store it in a property // Proceed to set up UI components (e.g., Card Form, PayPal Button) // Example: self.setupCardPaymentForm() // Example: self.setupPayPalButton() print("✅ Payrails SDK Initialized successfully. Execution ID: \(payrailsSession.executionId ?? "N/A")") } catch { // Handle initialization errors (e.g., invalid data, network issues during internal setup) print("❌ Failed to initialize Payrails SDK: \(error.localizedDescription)") // Update UI to show error state }
-
Store the Session: Keep a reference to the returned
Payrails.Session
object (e.g., in a view controller property likevar payrails: Payrails.Session?
). This object is required to create and manage Payrails UI elements.
After successfully initializing the SDK and storing the payrailsSession
, you can proceed to create and display payment components like Payrails.createCardPaymentForm(...)
or Payrails.createPayPalButton(...)
.
The Payrails SDK provides a pre-built UI component, Payrails.CardPaymentForm
, to securely collect card payment details from the user. It handles input validation, formatting, and interacts with the Payrails system for processing.
Prerequisites:
- A configured
Payrails.Session
must be available. Ensure you have successfully calledPayrails.configure(...)
and stored the resulting session object before attempting to create a card form. See the Initializing the Payrails SDK section.
Use the static factory method Payrails.createCardPaymentForm(...)
to get an instance of the form. This method requires an active Payrails.Session
.
// Ensure you have a valid Payrails.Session stored, e.g., in self.payrails
guard let payrails = self.payrails else {
print("Error: Payrails session not initialized.")
return // Or handle the error appropriately
}
// 1. Create the form instance (examples):
// Simple creation with defaults
let paymentForm = Payrails.createCardPaymentForm()
/* Other creation examples:
// Creation with a custom button title
let paymentFormWithTitle = Payrails.createCardPaymentForm(buttonTitle: "Pay €10.00")
// Creation with custom configuration (styles, text - see configuration section below)
let customConfig = CardFormConfig(...) // Define your config
let paymentFormWithConfig = Payrails.createCardPaymentForm(config: customConfig, buttonTitle: "Complete Payment")
*/
// 2. **Essential Step:** Assign Delegate and Presenter
// (See explanations below)
paymentForm.delegate = self // 'self' is typically your ViewController conforming to PayrailsCardPaymentFormDelegate
paymentForm.presenter = self // 'self' is typically your ViewController conforming to PaymentPresenter
// 3. Add the form to your view hierarchy (See "Adding the Form" section)
// view.addSubview(paymentForm) // Or add to a stack view, etc.
// ... setup constraints ...
Why Delegate and Presenter are Required:
After creating the paymentForm
instance, you must assign objects to its delegate
and presenter
properties. These are crucial for the form to function correctly within your app:
-
delegate
(Type:PayrailsCardPaymentFormDelegate
):- Purpose: To receive feedback and results from the Payrails SDK. Your delegate object gets notified about important events during the payment lifecycle.
- What it tells you:
- When the user clicks the payment button (
onPaymentButtonClicked
). - Whether the payment authorization succeeded (
onAuthorizeSuccess
). - Whether the payment authorization failed (
onAuthorizeFailed
). - When an external challenge like 3D Secure is required (
onThreeDSecureChallenge
).
- When the user clicks the payment button (
- Who implements it: Typically, the View Controller that manages the
CardPaymentForm
. - Details: See the Handling Events (
PayrailsCardPaymentFormDelegate
) section for detailed implementation guidance. - Reference: Refer to Events Glossary to see available events.
-
presenter
(Type:PaymentPresenter
):- Purpose: To allow the Payrails SDK to request UI presentations from your application when needed. Certain payment flows (most notably 3D Secure authentication) require showing new view controllers modally (e.g., a web view loading the bank's challenge page).
- What it allows the SDK to do: Call the
presentPayment(_:)
method on your presenter object, passing the specificUIViewController
that the SDK needs to display. Your implementation of this method handles the actual presentation logic (e.g.,self.present(viewController, animated: true)
). - Who implements it: Typically, the View Controller that manages the
CardPaymentForm
, as it has the capability to present other view controllers within the app's navigation flow. - Details: See the Handling External UI Flows (
PaymentPresenter
) section for detailed implementation guidance.
In summary: The delegate
enables your app to listen to the SDK's status updates and results, while the presenter
empowers the SDK to request necessary UI actions (specifically, view controller presentations) from your app. Both properties must be assigned for the card form to handle the complete payment lifecycle, including potential challenges like 3D Secure.
You can customize the appearance, labels, placeholders, and error messages of the card form by passing a CardFormConfig
object during creation using Payrails.createCardPaymentForm(config: ...)
. If no config is provided, sensible defaults will be used.
The CardFormConfig
struct allows you to specify:
showNameField
(Bool): Set totrue
to include the "Name on Card" input field in the form. Defaults tofalse
.styles
([CardFieldType: CardFormStyle]?): A dictionary where keys areCardFieldType
enum cases (e.g.,.CARD_NUMBER
,.EXPIRATION_DATE
,.CVV
,.CARDHOLDER_NAME
) and values areCardFormStyle
objects. This allows fine-grained control over the visual appearance of each field.translations
(CardTranslations?): An object containing customized text for labels, placeholders, and error messages used within the form.
1. Customizing Styles (CardFormStyle
):
To change the look and feel of the input fields, provide a styles
dictionary within your CardFormConfig
. Each entry maps a specific field type (CardFieldType
) to a CardFormStyle
configuration.
A CardFormStyle
object lets you define the appearance for different states of an input field using nested Style
objects:
baseStyle
: The default appearance when the field is idle.focusStyle
: Appearance when the user taps into the field and it gains focus.completedStyle
: Appearance when the field's input is considered complete (e.g., enough digits entered for a card number). Note: This doesn't guarantee validity.invalidStyle
: Appearance when the input fails validation (e.g., incorrect card number format, expired date).labelStyle
: Style applied to the text label associated with the field (e.g., "Card Number").errorTextStyle
: Style applied to the validation error message text displayed below the field wheninvalidStyle
is active.
Each Style
object allows setting properties like:
borderColor
, borderWidth
, backgroundColor
, textColor
, font
, cornerRadius
, padding
, textAlignment
, etc.
Example:
// Example: Customizing Card Number and CVV fields
// Define a custom style for the card number field
let customPadding = UIEdgeInsets(top: 10, left: 15, bottom: 10, right: 15)
let customCardNumberStyle = CardFormStyle(
baseStyle: Style(borderColor: .systemGray, padding: customPadding, borderWidth: 1.0, cornerRadius: 4),
focusStyle: Style(borderColor: .blue, borderWidth: 2.0, backgroundColor: .systemGray6),
invalidStyle: Style(borderColor: .red, borderWidth: 1.5),
labelStyle: Style(textColor: .darkGray, font: .systemFont(ofSize: 14, weight: .medium))
)
// Define a custom style for the CVV field
let customCvvStyle = CardFormStyle(
baseStyle: Style(cornerRadius: 8, backgroundColor: .systemTeal.withAlphaComponent(0.1)),
labelStyle: Style(textColor: .blue),
invalidStyle: Style(borderColor: .orange, borderWidth: 2)
)
// Create the styles dictionary mapping field types to their custom styles
let customStyles: [CardFieldType: CardFormStyle] = [
.CARD_NUMBER: customCardNumberStyle,
.CVV: customCvvStyle
// Add entries for .EXPIRATION_DATE, .CARDHOLDER_NAME etc. if needed
]
// Create the CardFormConfig incorporating these styles
let cardFormConfig = CardFormConfig(styles: customStyles)
// Pass this config when creating the form
// let paymentForm = Payrails.createCardPaymentForm(config: cardFormConfig)
Merging: Custom styles are intelligently merged over the default styles provided by the SDK. You only need to specify the properties you want to change for each style state (baseStyle
, focusStyle
, etc.). Unspecified properties will retain their default values.
2. Customizing Text (CardTranslations
):
To change the default text displayed in the form (labels, placeholders, error messages), create a CardTranslations
object and assign it to the translations
property of your CardFormConfig
.
The CardTranslations
object structure allows customization of:
placeholders
: ACardTranslations.Placeholders
object. Itsvalues
dictionary mapsCardFieldType
to custom placeholder strings (the grey text shown before input).labels
: ACardTranslations.Labels
object. Itsvalues
dictionary mapsCardFieldType
to custom label strings (the text usually displayed above the field). It also includes properties for other form text likesaveInstrument
,storeInstrument
,paymentInstallments
.error
: ACardTranslations.ErrorMessages
object. Itsvalues
dictionary mapsCardFieldType
to custom validation error message strings shown when input is invalid.
Example:
// Example: Customizing placeholders, labels, and error messages
let customPlaceholders = CardTranslations.Placeholders(
values: [
.CARD_NUMBER: "Enter your 16-digit card number",
.CVV: "3 or 4 digits"
]
)
let customLabels = CardTranslations.Labels(
values: [
.CARD_NUMBER: "Credit/Debit Card Number",
.CVV: "Security Code (CVV)"
],
// You can also customize other labels like:
saveInstrument: "Save this card securely for future payments"
)
let customErrorValues: [CardFieldType: String] = [
.CARD_NUMBER: "Invalid card number provided. Please double-check.",
.EXPIRATION_DATE: "Expiry date must be in MM/YY format and in the future."
]
let customErrors = CardTranslations.ErrorMessages(values: customErrorValues)
// Create the main translations object
let translations = CardTranslations(
placeholders: customPlaceholders,
labels: customLabels,
error: customErrors
)
// Create the CardFormConfig incorporating these translations
// Also showing the 'showNameField' option here for completeness
let cardFormConfig = CardFormConfig(
showNameField: true, // Include the name field
translations: translations
// You can combine styles and translations in the same config:
// styles: customStyles // Assuming customStyles is defined elsewhere
)
// Pass this config when creating the form
// let paymentForm = Payrails.createCardPaymentForm(config: cardFormConfig)
Merging: Similar to styles, custom translations are merged with the default translations provided by the SDK. You only need to provide overrides for the specific text elements you want to change. Untouched elements will use the SDK's default text.
The Payrails SDK offers a ready-to-use UI component, Payrails.PayPalButton
, to seamlessly integrate PayPal as a payment method in your iOS application. This button handles the necessary interactions with the PayPal flow, simplifying the integration process for merchants.
Prerequisites:
- A configured
Payrails.Session
must be available. Ensure you have initialized the Payrails SDK successfully and have a valid session object before creating a PayPal button. Refer to the Initializing the Payrails SDK section for details.
To instantiate a Payrails.PayPalButton
, use the static factory method Payrails.createPayPalButton()
. This method requires an active Payrails.Session
.
// Ensure you have a valid Payrails.Session stored, e.g., in self.payrails
guard let payrails = self.payrails else {
print("Error: Payrails session not initialized.")
return // Handle error appropriately
}
// 1. Create the PayPal Button instance:
let payPalButton = Payrails.createPayPalButton()
// 2. **Crucial Step:** Assign Delegate and Presenter
// (Explanations below)
payPalButton.delegate = self // 'self' is typically your ViewController conforming to PayrailsPayPalButtonDelegate
payPalButton.presenter = self // 'self' is typically your ViewController conforming to PaymentPresenter
// 3. Customize the button (Optional):
payPalButton.setTitle("Pay with PayPal", for: .normal) // Set a custom title
payPalButton.isEnabled = true // Ensure the button is enabled
// 4. Add the button to your view hierarchy (See "Adding the Button" section)
// view.addSubview(payPalButton) // Or add to a stack view, etc.
// ... setup constraints ...
Similar to the Card Payment Form, the Payrails.PayPalButton
requires you to set its delegate and presenter properties for proper functionality. These are essential for handling events and UI presentations during the PayPal payment flow:
-
delegate
(Type:PayrailsPayPalButtonDelegate
):- Purpose: To receive notifications and results from the Payrails SDK specifically related to the PayPal payment process initiated by the button. Your delegate object will be informed about key events in the PayPal payment lifecycle.
- What it tells you:
- When the user taps the PayPal button (
onPaymentButtonClicked
). - Whether the PayPal payment authorization succeeded (
onAuthorizeSuccess
). - Whether the PayPal payment authorization failed (
onAuthorizeFailed
). - If the PayPal payment session expired or was cancelled by the user on the PayPal side (
onPaymentSessionExpired
).
- When the user taps the PayPal button (
- Who implements it: Typically, the View Controller that is managing the
Payrails.PayPalButton
. - Details: See the Handling Events (PayrailsPayPalButtonDelegate) section for detailed implementation guidance.
- Reference: Refer to Events Glossary to see available events.
-
presenter
(Type:PaymentPresenter
):- Purpose: To allow the Payrails SDK to request UI presentations from your application when necessary during the PayPal payment flow. This is how the SDK can present the PayPal payment authorization UI (typically a web view or modal sheet) to the user.
- What it allows the SDK to do: Call the
presentPayment(_:)
method on your presenter object, passing the UIViewController that contains the PayPal authorization UI. Your implementation of this method is responsible for presenting this view controller within your app (e.g., usingself.present(viewController, animated: true)
). - Who implements it: Usually, the View Controller that manages the
Payrails.PayPalButton
, as it is responsible for presenting other view controllers in your app's UI flow. - Details: See the Handling External UI Flows (PaymentPresenter) section for detailed implementation guidance.
In essence: The delegate allows your application to react to PayPal payment events and outcomes, while the presenter empowers the SDK to initiate necessary UI actions (specifically, presenting view controllers for PayPal authorization) within your app's context. Both delegate and presenter must be set for the PayPal button to function correctly and handle the complete PayPal payment flow.
The Payrails.PayPalButton
offers limited customization options directly. You can primarily customize:
- Title: Set the text displayed on the button using the
setTitle(_:for:)
method. For example:payPalButton.setTitle("Checkout with PayPal", for: .normal)
. - Enabled State: Control whether the button is interactive using the
isEnabled
property. Set totrue
to enable user interaction andfalse
to disable it.
For more advanced styling or visual customization, you might need to subclass Payrails.PayPalButton
(if it's designed to be subclassable - check the SDK code) or wrap it within a container view to apply further styling. However, for most common use cases, setting the title and enabled state should be sufficient.
Payrails.PayPalButton
is a UIView subclass, so you can add it to your view hierarchy like any other UIKit view. Common approaches include:
- Adding as a subview directly to your UIViewController's main view:
view.addSubview(payPalButton)
- Adding to a UIStackView: This is often recommended for layout flexibility, especially if you have multiple payment options or form elements. As seen in the TestViewController example, adding to a UIStackView simplifies arrangement and spacing.
- Using Auto Layout constraints: After adding the button to your view hierarchy, you will need to set up Auto Layout constraints to define its position and size within its parent view.
Refer to standard UIKit documentation and tutorials for guidance on adding subviews and setting up Auto Layout constraints.
import UIKit
import Payrails
class MyViewController: UIViewController, PayrailsPayPalButtonDelegate, PaymentPresenter {
private var payPalButton: Payrails.PayPalButton?
private var payrailsSession: Payrails.Session? // Assume this is configured and set
override func viewDidLoad() {
super.viewDidLoad()
setupPayPal()
}
private func setupPayPal() {
guard let payrailsSession = self.payrailsSession else {
print("Error: Payrails session is not available.")
return
}
let button = Payrails.createPayPalButton()
button.delegate = self
button.presenter = self
button.setTitle("Pay with PayPal", for: .normal)
button.isEnabled = true
self.payPalButton = button
view.addSubview(button)
button.translatesAutoresizingMaskIntoConstraints = false
NSLayoutConstraint.activate([
button.centerXAnchor.constraint(equalTo: view.centerXAnchor),
button.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor, constant: 20),
// ... other constraints for width, height, etc. ...
])
}
// MARK: - PayrailsPayPalButtonDelegate Methods
func onPaymentButtonClicked(_ button: Payrails.PayPalButton) {
print("PayPal button tapped!")
// Handle button tap event (optional - delegate methods are called during payment execution)
}
func onAuthorizeSuccess(_ button: Payrails.PayPalButton) {
print("PayPal payment authorized successfully!")
// Payment success handling logic
}
func onAuthorizeFailed(_ button: Payrails.PayPalButton) {
print("PayPal payment authorization failed.")
// Payment failure handling logic
}
func onPaymentSessionExpired(_ button: Payrails.PayPalButton) {
print("PayPal session expired or cancelled by user.")
// Handle session expiration (e.g., user cancellation)
}
// MARK: - PaymentPresenter Method
func presentPayment(_ viewController: UIViewController) {
DispatchQueue.main.async {
self.present(viewController, animated: true)
}
}
var encryptedCardData: String? { // Implementation required by PaymentPresenter - not used for PayPal, can be a stub
get { return nil }
set { }
}
}
This section provides a comprehensive guide to using the Payrails.PayPalButton
in your iOS application. Remember to consult the Handling Events (PayrailsPayPalButtonDelegate) and Handling External UI Flows (PaymentPresenter) sections for details on implementing the delegate and presenter protocols.