YunoPaymentRenderFlowProtocol from Yuno.startPaymentRenderFlow(...), asked it for a formView to place wherever you wanted, and called submitForm() from your own button when the user was ready to pay.
In the unified API the same pattern is expressed by overriding showView. The SDK still provides the form view; you receive it together with a TransactionProcess control object that exposes onSubmit().
Before you start
- Replace
import YunoSDKwithimport SdkPayments. Your public API key and the checkout sessions your backend creates do not change (Before you begin). - Decide who creates the payment. The checkout session’s
workflowmust match that decision:
| Who creates the payment | In Render you had | In the unified API | Session workflow |
|---|---|---|---|
| Your backend | yunoCreatePayment implemented | Override createPayment | Default (SDK_CHECKOUT) |
| The SDK | No equivalent: only Seamless let the SDK create the payment | No override | SDK_SEAMLESS |
A default-workflow session with no
createPayment override ends in INTERNAL_ERROR: the backend rejects the SDK’s payment creation. See createPayment.Side-by-side
import SwiftUI
import YunoSDK
// 1. Initialize once at app startup
Yuno.initialize(apiKey: "your-public-api-key")
// 2. Implement the delegate
final class CheckoutModel: YunoPaymentDelegate, ObservableObject {
var checkoutSession: String = "session-from-backend"
var countryCode: String = "CO"
var language: String? = "en"
var viewController: UIViewController?
func yunoPaymentResult(_ result: Yuno.Result) { /* ... */ }
// Called by the SDK during render mode (the only mode where this fires)
func onLoading(isLoading: Bool) { /* show your own loader */ }
}
// 3. Embed the form, render layout yourself, submit from your button
struct CheckoutView: View {
@StateObject var model = CheckoutModel()
let selectedMethod: PaymentMethodSelected
@State var paymentFlow: YunoPaymentRenderFlowProtocol?
@State var formView: AnyView?
var body: some View {
VStack {
Text("Checkout")
// ... your products / shipping / etc.
formView // SDK form embedded here
Button("Pay") {
paymentFlow?.submitForm()
}
}
.task {
paymentFlow = await Yuno.startPaymentRenderFlow(
paymentMethodSelected: selectedMethod,
with: model
)
formView = await paymentFlow?.formView(
paymentMethodSelected: selectedMethod,
with: model
)
}
}
}
import SwiftUI
import SdkPayments
// 1. Initialize once at app startup
SdkPayments.initialize(apiKey: "your-public-api-key")
// 2. Implement the controller. Override showView + showLoading
final class CheckoutModel: SdkPayments.TransactionController, ObservableObject {
@Published var formView: AnyView?
@Published var process: SdkPayments.TransactionProcess?
@Published var isLoading: Bool = false
func showView(view: AnyView?, process: SdkPayments.TransactionProcess, step: SdkPayments.TransactionViewStep) {
// step == .FORM for the data-capture form, .ACTION for a payment code or OTP view. 3DS and redirects are full-screen.
self.formView = view
self.process = process
}
func showLoading(isLoading: Bool) {
self.isLoading = isLoading
}
func onStatus(status: SdkPayments.TransactionStatus) { /* ... */ }
}
// 3. Embed the delivered view, submit via process.onSubmit()
struct CheckoutView: View {
@StateObject var model = CheckoutModel()
let selectedMethod: SdkPayments.PaymentMethodSelected
var body: some View {
VStack {
Text("Checkout")
// ... your products / shipping / etc.
if model.isLoading { ProgressView() }
model.formView
Button("Pay") {
model.process?.onSubmit()
}
}
.task {
let config = SdkPayments.TransactionConfig(
checkoutSession: "session-from-backend",
countryCode: "CO",
controller: model
)
SdkPayments.Transaction(config: config)
.start(paymentSelected: selectedMethod)
}
}
}
What changes
Grouped in the order you edit the code. Renamed: same role, new name. Moved: same value, new owner. Removed: nothing to call. New: no legacy counterpart. The last column is the only thing you have to do beyond the rename.Initialization and config
| Render | Unified | Change | What to do |
|---|---|---|---|
import YunoSDK | import SdkPayments | Renamed | |
Yuno.initialize(apiKey:) | SdkPayments.initialize(apiKey:) | Renamed | The callback: parameter is gone; use the async overload if you need to wait. |
Yuno.Appearance passed in YunoConfig.appearance | SdkPayments.Appearance in SdkPayments.TransactionConfig.appearance | Renamed | Same initializer; drop the Yuno. prefix and pass it per transaction instead of once at startup. |
YunoPaymentDelegate.checkoutSession, .countryCode, .language, .viewController | The same fields on SdkPayments.TransactionConfig | Moved | Delegate properties become config fields. viewController stays iOS-only and optional in SwiftUI. |
Controller
| Render | Unified | Change | What to do |
|---|---|---|---|
YunoPaymentDelegate | SdkPayments.TransactionController | Renamed | Conform the same class and pass it as TransactionConfig.controller. As before, the SDK does not retain it: keep it alive for the whole transaction. |
yunoPaymentResult(_:) | onStatus(status:) | Renamed | Still the single outcome callback, once per transaction, also when the SDK shows its result screen. status and substatus come from the backend; the SDK itself only emits INTERNAL_ERROR and USER_CANCEL. See Status. |
Yuno.Result.message | SdkPayments.TransactionStatus.message | Renamed | Same role. source is now an enum (.sdk / .backend) and code is non-optional. |
yunoCreatePayment(with:) / (with:information:) | createPayment(token:) | Renamed | Optional. One handler replaces both variants; token is the full One-Time Token as a dictionary. Create the payment and return: returning is what used to be continuePayment(). If the handler throws, the flow stops and onStatus is not called, so show the error yourself. See createPayment. |
YunoLoaderDelegate.onLoading(isLoading:) | showLoading(isLoading:) | Renamed | Same semantics. Render was the only legacy mode that actually invoked it, so existing Render integrations almost certainly need to migrate this. Once overridden, the SDK hides its own loader and reports the state to you. See showLoading. |
onInstallmentSelected(_:) with YunoInstallmentSelected | onInstallmentSelected(_:) with SdkPayments.InstallmentSelected | Renamed | Optional. Same trigger and fields; only the payload type changes. It fires when the shopper selects or changes an installment in the SDK’s card form, including the SDK’s default auto-selection, and with nil when the selection no longer applies. See onInstallmentSelected. |
YunoShippingDelegate.onShippingAddressChanged(_:shippingInfo:) | onShippingAddressChanged(_:shippingInfo:) via SdkPayments.ShippingAddressHandling | Moved | Optional. Conform the controller to the protocol; the types drop the Yuno prefix and the completion-based variant is gone. Same async signature and role: real-time shipping updates on the Apple Pay sheet. The protocol inherits from TransactionController, so the SDK picks it up from the controller you pass in the config. See onShippingAddressChanged. |
Views
| Render | Unified | Change | What to do |
|---|---|---|---|
paymentFlow.formView(paymentMethodSelected:with:) | showView(view:process:step:) | Moved | Push, not pull: you no longer fetch the view, the SDK delivers it to your handler when ready. Cache it in your model and render it from there. showView can be called more than once per transaction: step == .FORM for the data-capture form, step == .ACTION for an action view such as a payment code or an OTP. 3DS challenges and redirects never come through showView: the SDK presents them full-screen. See showView. |
paymentFlow.submitForm() | process.onSubmit() | Renamed | Same role. Call it on the TransactionProcess you receive in showView. |
| (none) | SdkPayments.defaultShowView(view:process:step:) | New | Call it from your showView override for the steps you don’t want to embed (for example, embed .FORM and hand .ACTION back to the SDK). |
Entry points
| Render | Unified | Change | What to do |
|---|---|---|---|
Yuno.startPaymentRenderFlow(paymentMethodSelected:with:) | SdkPayments.Transaction(config:).start(paymentSelected:) | Renamed | Build the config, then start: the Transaction is the single entry point and the selection goes to start. Override showView to keep the form inside your layout (see Views). |
paymentFlow.continuePayment() | (removed) | Removed | Delete the call: returning from createPayment resumes the flow. The SDK runs 3DS and redirects itself, full-screen; you no longer render them in your layout. Set autoContinuePayment to false only if you need the SDK to stop right after the payment is created. |
Yuno.receiveDeeplink(_:) | SdkPayments.handleDeeplink(_:) | Renamed | Same role: forward the URL your app receives after an external redirect. See Handle deeplinks. |
Yuno.hideLoader() | (removed) | Removed | Delete the call: the SDK dismisses its own loader. With a showLoading override you receive isLoading: false instead. |
Related
showView. Full reference for the controller andTransactionProcess.showLoading. Loading-state controller.TransactionConfig. Complete field reference.- Migration / Lite. When you don’t need to embed the form yourself.