The iOS SDK makes it easy to integrate payment flows into your iOS app.
Additional resources
Requirements
The first step is including the library in your project. You can add the Yuno iOS SDK using CocoaPods or Swift Package Manager.
Option 1: CocoaPods
Add to your Podfile:
pod 'YunoSDK', '~> 2.11.1'
Then run:
Option 2: Swift Package Manager
Add the package dependency:
dependencies: [
.package(url: "https://github.com/yuno-payments/yuno-sdk-ios.git", .upToNextMajor(from: "2.11.1"))
]
Once Step 1 is complete, continue with the full-checkout integration.
Parameters
For the full list of parameters and YunoConfig, see the iOS SDK Common Reference.
| Parameter | Description |
|---|
checkoutSession | Checkout session ID from your backend (Create checkout session API). Required. |
countryCode | ISO country code (e.g. BR). Required. |
language | Language code for the UI. Optional. |
viewController | UIViewController that presents the payment flow. Required for delegate. |
yunoCreatePayment(with:) | Delegate: create payment on your backend with the one-time token. |
yunoPaymentResult(_:) | Delegate: payment finished. Receives Yuno.Result value (e.g., .succeeded, .fail, .processing). See Payment Status reference for status mapping. |
YunoConfig (initialize) | Optional: appearance, saveCardEnabled, keepLoader. See Common Reference. |
full-checkout
Implement the Full iOS SDK: complete payment solution with automatic payment method display and minimal UI customization. See Requirements above.
Step 1: Include the library in your project
Follow the steps in Include the library in your project above.
Step 2: Initialize SDK with the public key
Retrieve your public API keys from the Yuno Dashboard.
To start running the Yuno iOS Full checkout, import and initialize Yuno:
import YunoSDK
Yuno.initialize(
apiKey: "PUBLIC_API_KEY",
config: YunoConfig(),
callback: { (value: Bool) in }
)
The Full checkout enables you to configure the appearance and process through the YunoConfig class. The available options are:
struct YunoConfig {
var appearance: Appearance? = nil
var saveCardEnabled: Bool = false
var keepLoader: Bool = false
}
Options
Customization options:
| customization option | Description |
|---|
appearance | Enables SDK-wide UI customization. Use it to define global visual styles like colors, fonts, and button appearance. For more information, check the SDK customizations page. |
saveCardEnabled | Enables the Save card checkbox on card flows. Check the Save card section for more information. |
keepLoader | Controls loader display behavior. When true, the loader remains visible until manually hidden. |
language | Defines the language to be used in the payment forms. You can set it to one of the available language options: ar (Arabic), en (English), es (Spanish), pt (Portuguese), fil (Filipino), id (Indonesian), ms (Malay), th (Thai), zh-TW (Chinese Traditional), zh-CN (Chinese Simplified), vi (Vietnamese), fr (French), pl (Polish), it (Italian), de (German), ru (Russian), tr (Turkish), nl (Dutch), sv (Swedish), ko (Korean), ja (Japanese). |
Step 3: Create the checkout session
Each payment requires a new checkout_session. Use the Create checkout session endpoint to create one; use that session to initiate the payment.
If your payment flow sends users to an external browser (e.g., for 3DS authentication or bank redirects), set the callback_url when creating your checkout session. See Handle external browser return for details.
Checkout session options
| Parameter | Required | Description |
|---|
amount | Yes | The primary transaction amount object containing currency (ISO 4217 code) and value (numeric amount). |
alternative_amount | No | An alternative currency representation with the same structure as amount. Useful for multi-currency scenarios. |
callback_url | Recommended | URL to redirect users back to your app after external browser flows (3DS, bank redirects). |
customer_id | Yes | The customer ID obtained from the Create customer endpoint. |
Auth vs captureControl auth vs capture by sending payment_method.detail.card.capture in the checkout session: false = authorize only, true = capture immediately.
Step 4: Implement the payment delegate
Create a class that adopts the YunoPaymentDelegate protocol:
Swift 6 Concurrency RequirementsIf you’re using Swift 6, you’ll need to implement the YunoPaymentDelegate protocol with specific concurrency considerations. See the Swift 6 Concurrency guide for detailed implementation options and best practices.
protocol YunoPaymentDelegate: AnyObject {
var checkoutSession: String { get }
var countryCode: String { get }
var language: String? { get }
var viewController: UIViewController? { get }
func yunoCreatePayment(with token: String)
func yunoCreatePayment(with token: String, information: [String: Any])
func yunoPaymentResult(_ result: Yuno.Result)
}
class ViewController: UIViewController, YunoPaymentDelegate {
var checkoutSession: String { "438413b7-4921-41e4-b8f3-28a5a0141638" }
var countryCode: String { "BR" }
var language: String? { "en" }
var viewController: UIViewController? { self }
func yunoCreatePayment(with token: String) {
// Create payment on your backend
}
func yunoCreatePayment(with token: String, information: [String: Any]) {
// Create payment with additional information
}
func yunoPaymentResult(_ result: Yuno.Result) {
// Handle payment result
}
}
Options
| Parameter | Description |
|---|
checkoutSession | The unique identifier for the checkout session. |
countryCode | Country code where the payment is performed. See Country Coverage for supported countries. |
language | Language code for the payment forms (e.g., "en", "es", "pt"). See Supported languages. |
viewController | The UIViewController used to present the payment flow. Required for proper UI presentation. |
yunoCreatePayment(with:) | Called when a one-time token is generated. Create the payment on your backend. |
yunoCreatePayment(with:information:) | Alternative callback that includes additional token information. Use only one version. |
yunoPaymentResult(_:) | Called when the payment process completes. Receives a Yuno.Result enum value. See Payment Status reference for status mapping. |
Important NoteUse either yunoCreatePayment(with:) OR yunoCreatePayment(with:information:) based on your needs—not both. Calling both may cause issues.
Step 5: Mount the SDK with automatic payment method display
Use getPaymentMethodViewAsync() to display all available payment methods automatically. Implement the YunoPaymentFullDelegate protocol:
protocol YunoPaymentFullDelegate: YunoPaymentDelegate {
func yunoDidSelect(paymentMethod: YunoSDK.PaymentMethodSelected)
func yunoDidUnenrollSuccessfully(_ success: Bool)
func yunoUpdatePaymentMethodsViewHeight(_ height: CGFloat)
}
class ViewController: UIViewController, YunoPaymentFullDelegate {
// ... YunoPaymentDelegate implementation ...
func yunoDidSelect(paymentMethod: YunoSDK.PaymentMethodSelected) {
print("Payment method selected: \(paymentMethod.paymentMethodType)")
}
func yunoDidUnenrollSuccessfully(_ success: Bool) {
if success {
print("Payment method removed successfully")
}
}
func yunoUpdatePaymentMethodsViewHeight(_ height: CGFloat) {
// Update container height if needed
}
}
Then call getPaymentMethodViewAsync() to retrieve the payment methods view:
let paymentMethodsView = await Yuno.getPaymentMethodViewAsync(delegate: self)
// Add the view to your UI
// For UIKit:
view.addSubview(paymentMethodsView)
// For SwiftUI:
// Use the returned view in your SwiftUI body
The SDK automatically returns the correct view type:
- UIKit: Returns a
UIView
- SwiftUI: Returns a
some View
ImportantAlways ensure the payment methods view container has proper constraints or layout configuration. The SDK will notify you of height changes through yunoUpdatePaymentMethodsViewHeight(_:) if needed.
Step 6: Start the payment process
After displaying the payment methods, call startPayment():
Yuno.startPayment(showPaymentStatus: true)
Options
| Parameter | Description |
|---|
showPaymentStatus | A boolean that specifies whether the payment status should be displayed within the Yuno interface. When true, the SDK displays default status screens. When false, you handle status display through callbacks. |
Step 7: Get the one-time token (OTT)
After the customer fills out the requested data in Yuno’s payment forms, you will obtain the one-time token, a required parameter to create a payment using the Yuno API.
The one-time token will be shared by Yuno using the yunoCreatePayment function you provided in Step 4 when implementing the delegate. The one-time token will be available in the callback.
A loader can be shown while the one-time token is generated. Use Yuno’s default or implement your own with the required configuration.
Step 8: Create the payment
After receiving the one-time token from Step 7, create the payment using the Create payment endpoint. Use the checkout_session from Step 3 and the one-time token to create the payment.
func yunoCreatePayment(with token: String) {
// Call your backend to create the payment
createPaymentOnBackend(token: token) { result in
switch result {
case .success:
// Payment created successfully
// Call continuePayment() if needed
Yuno.continuePayment()
case .failure(let error):
// Handle error
print("Payment creation failed: \(error)")
}
}
}
In your backend, call the Create Payment endpoint:
POST /v1/payments
{
"payment_method": {
"token": "9ee44ac7-9134-4598-ae28-a26fec03099d"
},
"checkout_session": "438413b7-4921-41e4-b8f3-28a5a0141638"
}
The response from the Create payment endpoint will include the parameter sdk_action_required, which defines if additional actions are required to finish the payment based on the payment type.
Required: Integrate the continuePayment method after the payment is created. Some asynchronous payment methods require additional customer actions. When the API response sets sdk_action_required to true, call Yuno.continuePayment() to display the necessary screens.
Step 9: Continue payment
Yuno requires integrating the SDK’s continuePayment method after the payment is created, as certain asynchronous payment methods require additional customer actions to complete. The response from the Create payment endpoint, from Step 8, will include an sdk_action_required field. If it returns TRUE, you need to call the continuePayment() function to show additional screens that allow the customer to complete the payment. Otherwise, this step is not necessary.
To show your payment status screens, handle status through the yunoPaymentResult(_:) delegate method instead of using the SDK’s default status display.
Step 10: Handle external browser return (Optional)
Deep Links and Mercado Pago Checkout ProThis step is only required if you’re using a payment method that relies on deep links or Mercado Pago Checkout Pro. If your payment methods don’t use deep links, you can skip this step.
Some payment methods take users out of your app to complete the transaction. Once the payment is finished, the user is redirected back using a deep link. Update your AppDelegate to pass the incoming URL to the Yuno SDK:
func application(_ app: UIApplication,
open url: URL,
options: [UIApplication.OpenURLOptionsKey: Any] = [:]) -> Bool {
guard url.scheme == "yunoexample" else { return false }
return Yuno.receiveDeeplink(url)
}
Make sure the url.scheme matches the callback_url you provided when creating the checkout_session.
Step 11: Handle payment result
The SDK returns the payment result through the yunoPaymentResult(_:) delegate method:
func yunoPaymentResult(_ result: Yuno.Result) {
switch result {
case .succeeded:
print("Payment succeeded")
// Navigate to success screen
case .fail:
print("Payment failed")
// Show error message
case .processing:
print("Payment is processing")
// Show processing message
case .reject:
print("Payment was rejected")
// Show rejection message
case .userCancelled:
print("User canceled payment")
// Handle cancellation
case .internalError:
print("Internal error occurred")
// Show error message
}
}
Payment states
| State | Description | Action Required |
|---|
succeeded | Payment completed successfully | No |
fail | Payment failed due to validation, network, or technical issues | Yes - Investigate and retry |
processing | Payment in progress, awaiting approval | No |
reject | Payment rejected (insufficient funds, fraud detection, etc.) | Yes - Inform user and suggest actions |
internalError | Unexpected internal error occurred | Yes - Technical intervention required |
userCancelled | User canceled the payment | No |
Payment status validation
This section explains how the SDK handles payment status when users cancel or leave payment flows, and how the SDK status relates to the backend payment status in these scenarios.
Sync payment methods (Apple Pay)
For synchronous payment methods like Apple Pay, when a user cancels before PSP response:
- SDK Status: Returns
userCancelled (CANCELLED_BY_USER)
- Backend Payment Status: Remains
PENDING until PSP timeout or merchant cancellation
- Important: The SDK will not return
reject or processing in this scenario
This ensures that the backend payment remains in a pending state and can be properly handled by the merchant’s system.
Async payment methods (PIX, QR codes)
For asynchronous payment methods like PIX, when a user closes the QR window:
- SDK Status: Returns
processing, optionally with a sub-status such as CLOSED_BY_USER
- Backend Payment Status: Remains
PENDING and the QR code remains valid until expiry
- Checkout Session Reuse: Re-opening the same checkout session can display the same valid QR code
- No Automatic Cancellation: The PIX payment is not automatically cancelled when the user closes the QR window
This behavior allows users to return to the payment flow and complete the transaction using the same QR code before it expires.
Expired async payments
If a PIX QR code expires naturally:
- Backend Status: Updated to
EXPIRED
- SDK Status: SDK callbacks and polling endpoints return
EXPIRED consistently
This ensures merchants receive accurate status information when a payment method has expired.
Render mode integration
The render mode in the Yuno SDK offers enhanced UI flexibility, enabling developers to integrate payment flows with complete control over the user interface while retaining full SDK functionality. This mode provides SwiftUI views that can be seamlessly incorporated into your existing UI.
Main function: startPaymentRenderFlow
The startPaymentRender function is a feature of the Yuno SDK that allows merchants to integrate the payment process in a more detailed and customizable manner. This function grants full control over when and how payment forms are displayed, facilitating smoother integration with the merchant’s existing application UI.
This function is designed to offer greater control over the payment flow, allowing merchants to:
- Integrate payment forms in a customized manner within their own UI.
- Precisely control when payment data forms are displayed.
- Gain detailed control over the payment confirmation process.
- Provide a more fluid and consistent user experience within the merchant’s application.
Syntax
The syntax section provides the method signature for the startPaymentRender function. This function is central to integrating the payment process within your application, offering a customizable and detailed approach to handling payment forms and flows.
@MainActor static func startPaymentRenderFlow(
paymentMethodSelected: PaymentMethodSelected,
with delegate: YunoPaymentDelegate
) async -> some YunoPaymentRenderFlowProtocol
Parameters
The startPaymentRender function requires specific parameters to operate effectively. These parameters are essential for defining the payment method and handling the payment process responses.
| Parameter | Type | Description |
|---|
paymentMethodSelected | PaymentMethodSelected | The payment method selected by the user. Must include the vaultedToken (if exists) and the paymentMethodType |
delegate | YunoPaymentDelegate | The delegate that will handle payment process responses, including token creation and final result |
Return value
Returns an instance that conforms to YunoPaymentRenderFlowProtocol, which provides methods to handle the payment rendering flow.
YunoPaymentRenderFlowProtocol protocol
The instance returned by startPaymentRender conforms to this protocol which includes the following methods:
func formView(
paymentMethodSelected: PaymentMethodSelected,
with delegate: YunoPaymentDelegate
) async -> AnyView?
- Purpose: Gets the form view to capture payment data
- Behavior:
- If the payment method requires showing a form, returns an
AnyView with the corresponding form
- If the payment method doesn’t need to show any form (e.g., already configured methods), returns
nil
- When to use: Call immediately after creating the payment flow instance
- Purpose: Submits form data for validation
- Behavior: Executes all necessary validations and, if successful, proceeds to generate a new one-time token
- When to use: When the user executes the “pay” action in the merchant’s application
continuePayment()
func continuePayment() async -> AnyView?
- Purpose: Continues the payment process after the one-time token has been generated
- Behavior:
- If it’s necessary to show any additional view (e.g., 3DS authentication), returns an
AnyView
- If no additional view is required, returns
nil
- When to use: After receiving the one-time token through the delegate and creating the payment
Implementation flow
This section outlines the sequence of steps required to implement the payment rendering process using the Yuno SDK.
Step 1: Initial setup
To begin using startPaymentRender, make sure the SDK is properly initialized and you possess a valid checkoutSession. Follow the steps below to set up your environment:
await Yuno.initialize(apiKey: "your_api_key")
Step 2: Create payment flow instance
Create a payment flow instance to manage and render the payment process using the selected method.
let paymentFlow = await Yuno.startPaymentRenderFlow(
paymentMethodSelected: selectedPaymentMethod,
with: self
)
Step 3: Get and display the form
Retrieve and present the payment form to collect user payment information efficiently.
let formView = await paymentFlow.formView(
paymentMethodSelected: selectedPaymentMethod,
with: self
)
if let formView = formView {
VStack {
Text("Payment Information")
formView
Button("Pay") {
paymentFlow.submitForm()
}
}
} else {
paymentFlow.submitForm()
}
Step 4: Handle the one time token
Implement the delegate method to receive the token:
extension MyViewController: YunoPaymentDelegate {
var checkoutSession: String {
return "your_checkout_session"
}
var countryCode: String {
return "CO"
}
var viewController: UIViewController? {
return self
}
func yunoCreatePayment(with token: String, information: [String: Any]) {
createPaymentInBackend(token: token) { [weak self] success in
if success {
Task {
let additionalView = await self?.paymentFlow?.continuePayment()
if let additionalView = additionalView {
self?.showAdditionalView(additionalView)
}
}
}
}
}
func yunoPaymentResult(_ result: Yuno.Result) {
switch result {
case .succeeded:
showSuccessMessage()
case .reject:
showRejectionMessage()
case .fail:
showErrorMessage()
case .processing:
showProcessingMessage()
case .userCancelled:
handleCancellation()
case .internalError:
showInternalErrorMessage()
}
}
}
Complementary features
For styling, themes, form options, and additional configurations, see SDK customizations.
Common reference
For full parameter and customization details, see the iOS SDK Common Reference.