Transaction.start(paymentSelected:). No controller overrides beyond onStatus needed.
Before you start
- Replace the
com.yuno.sdk.*andcom.yuno.presentation.*imports with theircom.yuno.payments.sdk.api.*counterparts (the side-by-side lists them). 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 Lite you had | In the unified API | Session workflow |
|---|---|---|---|
| Your backend | callbackOTT implemented (the headless variant) | Override createPayment | Default (SDK_CHECKOUT) |
| The SDK | No callbackOTT | 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 com.yuno.sdk.Yuno
import com.yuno.sdk.YunoConfig
import com.yuno.sdk.payments.startCheckout
import com.yuno.sdk.payments.startPaymentLite
import com.yuno.presentation.core.components.PaymentSelected
class CheckoutActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
// 1. Initialize once at app startup (usually in Application.onCreate)
Yuno.initialize(
applicationContext,
apiKey = "your-public-api-key",
config = YunoConfig(
saveCardEnabled = true,
keepLoader = false,
styles = customStyles,
),
)
// 2. Set up the checkout launcher and the result callbacks
startCheckout(
checkoutSession = "session-from-backend",
countryCode = "CO",
callbackPaymentState = { state, subState ->
when (state) {
"SUCCEEDED" -> println("Success")
"REJECT" -> println("Rejected")
"FAIL" -> println("Failed")
"PROCESSING" -> println("Processing")
"INTERNAL_ERROR" -> println("Internal error")
"CANCELED_BY_USER" -> println("User cancelled")
}
},
)
}
// 3. Trigger the payment with a pre-selected method
fun pay(paymentSelected: PaymentSelected) {
startPaymentLite(
paymentSelected = paymentSelected,
showPaymentStatus = true,
)
}
}
import com.yuno.payments.sdk.api.SdkPayments
import com.yuno.payments.sdk.api.Transaction
import com.yuno.payments.sdk.api.TransactionConfig
import com.yuno.payments.sdk.api.TransactionController
import com.yuno.payments.sdk.api.models.PaymentMethodSelected
import com.yuno.payments.sdk.api.models.TransactionStatus
class CheckoutActivity : ComponentActivity(), TransactionController {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
// 1. Initialize once at app startup (usually in Application.onCreate)
SdkPayments.initialize(applicationContext, apiKey = "your-public-api-key")
}
// 2. Implement the controller
override fun onStatus(status: TransactionStatus) {
when (status.status) {
"SUCCEEDED" -> println("Success")
"DECLINED" -> println("Declined")
"REJECTED" -> println("Rejected")
"ERROR" -> println("Error")
"PENDING" -> println("Pending")
"INTERNAL_ERROR" -> println("Internal error")
"USER_CANCEL" -> println("User cancelled")
}
}
// 3. Trigger the payment with a pre-selected method
fun pay(paymentSelected: PaymentMethodSelected) {
val config = TransactionConfig(
checkoutSession = "session-from-backend",
countryCode = "CO",
language = "en",
appearance = customAppearance, // optional
controller = this,
showStatusScreen = true,
)
Transaction(config = config)
.start(activity = this, paymentSelected = paymentSelected)
}
}
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
| Lite | Unified | Change | What to do |
|---|---|---|---|
import com.yuno.sdk.* | import com.yuno.payments.sdk.api.* | Renamed | |
Yuno.initialize(context, apiKey, YunoConfig) | SdkPayments.initialize(context, apiKey) | Renamed | YunoConfig is gone: its fields move to TransactionConfig or disappear (next rows). |
YunoConfig.styles | TransactionConfig.appearance | Moved | Pass it per transaction instead of once at startup. |
YunoConfig.language | TransactionConfig.language | Moved | Pass it per transaction instead of once at startup. |
YunoConfig.saveCardEnabled | (removed) | Removed | Delete it: the flag is now controlled server-side via the settings service, the client no longer passes it. |
YunoConfig.keepLoader | (removed) | Removed | The SDK keeps its loader. Override showLoading only if you want your own (see Controller). |
YunoConfig.isDynamicViewEnabled | (removed) | Removed | Delete it: the dynamic view flow is the only flow in the unified API. |
checkoutSession, countryCode arguments of startCheckout | The same fields on TransactionConfig | Moved | The setup call’s arguments become config fields. |
merchantSessionId argument | (removed) | Removed | Reserved: the anti-fraud session ID is now configured server-side and is no longer passed from the client. |
showPaymentStatus argument of startPaymentLite | TransactionConfig.showStatusScreen | Moved | See the note below. |
The SDK result screen is off by default now. Set
showStatusScreen = true to keep it.Controller
| Lite | Unified | Change | What to do |
|---|---|---|---|
Lambdas passed to startCheckout (callbackPaymentState, callbackOTT) | TransactionController | Renamed | Lambdas become an interface: implement TransactionController on whichever class you keep around for the duration of the transaction (your Activity, ViewModel, or a dedicated state holder) and pass it as TransactionConfig.controller. The SDK does not retain it: keep it alive for the whole transaction. |
callbackPaymentState: (state, subState) -> Unit | onStatus(status: TransactionStatus) | Renamed | Still the single outcome callback, once per transaction on the terminal status, also when the SDK shows its result screen, so you can drive your own UI on top. The raw (state, subState) string pair becomes a TransactionStatus object: status and substatus come from the backend, as the backend returns them. The legacy REJECT, FAIL and PROCESSING strings are no longer emitted: handle DECLINED, REJECTED, ERROR and PENDING instead. CANCELED_BY_USER is now USER_CANCEL; subState maps 1-to-1 to substatus. The SDK itself only emits INTERNAL_ERROR and USER_CANCEL. See Status. |
callbackOTT: (String?) -> Unit | createPayment(token: Map<String, Any>) | Renamed | Optional. In Lite this lambda only fired in the headless variant; for the SDK-managed Lite flow you do not need it. If your backend creates the payment, override it: token is the full One-Time Token as a map, not just the token string. Create the payment and return; the SDK then polls the status, runs 3DS if needed and calls onStatus. If the handler throws, the flow stops and onStatus is not called, so show the error yourself. See createPayment and Headless migration. |
| (none) | showLoading(isLoading: Boolean) | New | Optional. Lite had no loader callback: the SDK always showed its own loader. It still does unless you override showLoading; once overridden, the SDK hides its own loader and reports the state to you. See showLoading. |
Entry points
| Lite | Unified | Change | What to do |
|---|---|---|---|
startCheckout(…) + startPaymentLite(paymentSelected, …, showPaymentStatus) | Transaction(config).start(activity, paymentSelected) | Renamed | Build the config, then start. You still pick the method and pass it. The two Activity extension functions become one call on a regular Transaction instance: you do not need an Activity to construct it (you only need an Activity/Context if you want to launch the SDK’s UI). showPaymentStatus moved to the config (see Initialization and config). |
PaymentSelected | PaymentMethodSelected | Renamed | Same role: the value you pass to start. |
Related
- Get Started. Full unified-API walkthrough.
TransactionConfig. Complete field reference.Status. Values and substatus.