Full SDK (安卓)


👍

推荐的 SDK

我们建议使用AndroidSeamless SDK,以获得流畅的集成体验。该选项提供了灵活的支付解决方案,预置了用户界面组件和定制选项。

本页为您提供 Android 版 YunoFull SDK 指南,该Full SDK 提供具有可定制用户界面的完整支付解决方案。它提供支付方式管理、欺诈防范和无缝结账流程等高级功能,比我们的Headless SDK专门用于核心支付处理功能)功能更丰富。

要求

在启动 Yuno Android SDK 之前,请确保您的项目符合技术要求。此外,还要确保具备以下先决条件:

  1. 您必须拥有一个激活的 Yuno 帐户
  2. 您需要 Yuno API 凭据 (account_id, public-api-keyprivate-secret-key),您可以从 Yuno 仪表板的开发人员部分.向 Yuno API 提出的请求需要这些凭据来验证。API 用于
  • 创建一个 checkout_session初始化付款流
  • 创建与会话相关的付款
  1. 在创建付款之前,必须先使用创建客户endpoint创建一个客户

第 1 步:在项目中加入程序库

通过 Gradle 在项目中包含 Yuno SDK 文件。然后,添加版本库源代码:

maven { url "https://yunopayments.jfrog.io/artifactory/snapshots-libs-release" }
📘

SDK 版本

访问发行说明Yuno Android SDK 存储库,验证可用的最新 SDK 版本。

然后,在 build.gradle 文件,将 Yuno SDK 依赖关系添加到应用程序中:

dependencies {
    implementation 'com.yuno.payments:android-sdk:{last_version}'
}

权限

Yuno SDK 默认包含 INTERNET 权限,这是提出网络请求的必要条件。

<uses-permission android:name="android.permission.INTERNET" />

步骤 2:使用公钥Initialize SDK

Yuno 面板读取公共 API 密钥。

如果还没有实施自定义应用程序,请创建一个。在 onCreate() 方法,调用initialize 函数 (Yuno.initialize):

class CustomApplication : Application() {
  override fun onCreate() {
    super.onCreate()
    Yuno.initialize(
      this,
      "<your-public-api-key>",
      config: YunoConfig,
    )
  }
}
📘

证书

更多信息,请参阅全权证书页面: https://docs.y.uno/reference/authentication

使用数据类 YunoConfig 来定制 SDK 的行为。在调用 Yuno.initialize().可用的选项有

data classYunoConfig(
    val cardFlow:CardFormType  CardFormType.ONE_STEP,
    val saveCardEnabled: Boolean = false,
    val cardFormDeployed: Boolean = false,
    val language:YunoLanguage? = null,
    val styles:YunoStyles? = null,
    val cardNumberPlaceholder: String? = null, // 可选:卡号字段的自定义占位文本
    val hideCardholderName: Boolean? = null // 可选:设为true隐藏持卡人姓名字段
)

参数

下表介绍了每种可用的自定义功能:

定制选项说明
cardFlow这是一项可选配置,用于定义支付和注册卡流程。默认情况下 CardFormType.ONE_STEP 选项。检查 渲染选项 部分获取更多信息。
saveCardEnabled启用卡片流上的保存卡片复选框。更多信息请查看保存卡片部分。
cardFormDeployed此选项仅适用于Full SDK。如果 TRUE系统会显示支付方式列表中的银行卡表格。如果 FALSE,在另一个屏幕上显示正常的卡片形式。
language定义付款表单中使用的语言。您可以将其设置为可用语言选项之一:
  • es (西班牙文)
  • en (英语)
  • pt (葡萄牙语)
  • 菲力
  • id(印尼语)
  • 马来文
  • th(泰语)
  • zh-TW(繁体中文,台湾
  • zh-CN (简体中文,中国
  • vi(越南语)
  • 法文
  • pl (波兰语)
  • it(意大利语)
  • 德文
  • ru(俄文)
  • tr (土耳其语)
  • nl(荷兰语)
  • sv(瑞典语)
  • 韩语
  • ja (日语)
cardNumberPlaceholder此可选字段允许您自定义卡号字段的占位符文本。支持字母数字字符、空格及用于本地化的UTF-8字符。若未提供,SDK将使用默认占位符("卡号")。此自定义操作不会影响卡片格式、遮罩处理、BIN逻辑或验证功能。
hideCardholderName此可选字段允许您在卡片表单中隐藏持卡人姓名字段。当设置为 true持卡人姓名字段未显示。当未指定或设置为 false持卡人姓名字段将显示(默认行为)。隐藏该字段不会影响主卡号、有效期、CVV验证码收集、BIN逻辑或3DS/支付机构验证。当支付机构要求提供持卡人姓名时,商户有责任确保该信息被提交。
styles支持 SDK 范围内的用户界面自定义。使用它可以定义全局可视化样式,如字体家族和按钮外观(颜色、填充、半径、排版)。 YunoStyles 对象。更多信息,请查看 styles 节。

更新您的清单,以使用您的应用程序:

<application android:name=".CustomApplication"></application>

步骤 3:创建结账会话

每次付款都需要一个新的 checkout_session,可以访问特定客户的所有可用付款方式。使用 创建结账会话 endpoint 获取新的 checkout_session.然后使用该会话启动付款。

📘

外部浏览器返回处理

如果您的支付流程将用户发送到外部浏览器(例如,用于 3DS 身份验证或银行重定向),请确保设置 callback_url 创建结账会话时使用。有关处理返回应用程序的分步指南,请参阅 处理外部浏览器返回 (callback_url).

步骤 4:开始结账

致电 startCheckout 方法内的 onCreate() 活动的函数,该函数用于初始化 SDK,以便使用Full SDK 启动新的支付流程:

startCheckout(
 checkoutSession:"checkout_session"、
 countryCode:"country_code_iso"、
 callbackPaymentState: ((String?) -> Unit)?
  merchantSessionId:String? = null
)

参数

使用以下选项配置结账:

参数说明
checkoutSession与付款相关的结账会话的唯一标识符。需要用它来initialize 付款流程,并允许访问客户可用的付款方式。
countryCode执行付款的国家代码。有关支持国家及其代码的完整列表,请参阅国家覆盖范围
callbackPaymentState这是一个返回当前付款流程的函数。如果不需要结果,则无需发送此函数。
merchantSessionId商家用于跟踪付款的标识符。

以下是 callbackPaymentState:

const valSUCCEEDED=SUCCEEDED"
const val PAYMENT_STATE_FAIL = "FAIL" (失败)
const val PAYMENT_STATE_PROCESSING = "PROCESSING" (处理中)
const val PAYMENT_STATE_REJECT = "REJECT" (拒绝)
const val PAYMENT_STATE_INTERNAL_ERROR = "INTERNAL_ERROR" (内部错误)
const val PAYMENT_STATE_STATE_CANCELED_BY_USER = "CANCELED" (取消)

下表提供了有关可能状态的更多信息:

国家说明需要采取的额外行动
SUCCEEDED交易或付款过程成功完成,无任何错误。
FAIL由于数据验证问题、服务器连接故障或技术/网络问题等错误导致交易失败。调查故障原因(验证、网络、服务器)并采取纠正措施。
PROCESSING交易正在进行中,等待批准或核实。
REJECT由于资金不足或涉嫌欺诈活动等原因,交易被拒绝。是的,告知用户被拒绝的原因,如果可能的话提供理由,并建议采取的行动。
INTERNAL_ERROR处理付款过程的系统出现意外内部错误。是。需要技术干预,以审查系统、修复内部问题、重试或通知用户。
CANCELED用户自愿取消交易或放弃付款过程。

付款状态验证

本节说明当用户取消或退出支付流程时,SDK如何处理支付状态,以及在这些场景中SDK状态与后端支付状态之间的关联关系。

同步支付方式(Google Pay)

对于Google Pay等同步支付方式,当用户在收到支付服务提供商(PSP)响应前取消或关闭钱包界面时:

  • SDK状态: 返回 CANCELED (CANCELLED)
  • 后端支付状态:遗骸 PENDING 直至PSP超时或商户取消
  • 重要SDK 将不返回 REJECTPROCESSING 在此情境下

这确保后端支付保持待处理状态,并能由商户系统妥善处理。

异步支付方式(PIX及基于二维码的支付方式)

对于PIX等异步支付方式,当用户在完成支付前关闭二维码窗口(点击X)时:

  • SDK状态: 返回 PROCESSING,可选地带有子状态,例如 CLOSED_BY_USER
  • 后端支付状态:遗骸 PENDING 且二维码在到期前始终有效
  • 结账会话复用:重新打开相同的结账会话可显示相同的有效二维码
  • 不自动取消:当用户关闭二维码窗口时,PIX支付不会自动取消

此功能允许用户在二维码失效前返回支付流程,使用同一二维码完成交易。

已过期的异步支付

如果PIX二维码自然过期:

  • 后端状态更新至 EXPIRED
  • SDK状态SDK 回调和轮询endpoints 点返回 EXPIRED 始终如一地

这确保了当支付方式过期时,商户能够收到准确的状态信息。

第 5 步:在结账中添加 SDK 视图

使用 PaymentMethodListViewComponent 以在使用 Jetpack Compose 实现Full SDK 时显示可用的支付方法。该组件提供回调功能,以便在启用或禁用支付按钮以及成功删除注册的支付方式时通知您的应用程序。

组件签名

@Composable
fun PaymentMethodListViewComponent(
    activity: Activity,
    modifier: Modifier? = null,
    onPaymentSelected: (Boolean) -> Unit,
    onUnEnrollSuccess: (Boolean) -> Unit = {}
)

参数

  • activity: Activity
    • 目前的 Activity 组件的托管位置。需要正确处理付款流。
  • modifier: Modifier? 可选
    • 允许自定义布局和外观(如填充、间距)。默认为 null.
  • onPaymentSelected: (Boolean) -> Unit
    • 每当选择或取消选择付款方式时调用的回调。
      • true → 选择一种方法(启用支付按钮)。
      • false → 未选择任何方法(禁用支付按钮)。
  • onUnEnrollSuccess: (Boolean) -> Unit 可选
    • 成功删除(取消注册)存储的付款方式时调用的回调。
      • true → 表示删除成功。
      • 可用于显示点心栏、刷新列表或更新用户界面状态。

示例

val coroutineScope = rememberCoroutineScope()
val SnackbarHostState = remember { SnackbarHostState() }
var paymentMethodIsSelected by remember { mutableStateOf(false) }

Column(
    modifier = Modifier
        .weight(1f)
        .verticalScroll(rememberScrollState())
) {
    PaymentMethodListViewComponent(
        activity = activity、
       onPaymentSelected = { isSelected ->
            paymentMethodIsSelected = isSelected
        },
       onUnEnrollSuccess = { success ->
            if (success) {
                coroutineScope.launch {
                    snackbarHostState.showSnackbar(
                        message = "您的付款方式已被删除"、
                    )
                }
            }
        },
    )
}

重要

始终用 Column.verticalScroll(rememberScrollState()).如果不这样做,当有多种付款方式可用时,付款方式列表可能无法正常显示或滚动。

第 6 步:启动付款程序

致电 startPayment() 方法启动付款流程:

startPayment(
    showStatusYuno: 布尔值、
   callbackOTT: (String?) -> Unit = this:onTokenUpdated、
   callBackTokenWithInformation:OneTimeTokenModel?) -> Unit = this:onTokenComplete

)

参数

使用以下选项配置付款:

参数说明
showStatusYuno布尔值,用于指定是否在 Yuno 界面中显示付款状态。
callbackOTT必填函数,用于返回完成支付流程所需的更新一次性token (OTT)。完成支付需要该token 。
callBackTokenWithInformation提供一次性token详细信息的函数,用一个 OneTimeTokenModel 对象,从而可以全面处理token 细节。

第 7 步:获取一次性token (OTT)

客户在 Yuno 的支付表单中填写所需的数据后,您将获得一次性token,这是使用 Yuno API 创建支付所需的参数。

一次性token 将由 Yuno 使用 callbackOTT 函数。一次性token 将在 onActivityResult.

📘

装载机配置

在 Yuno 接收客户信息并共享一次性token的同时,可以显示加载器以改善用户体验。Yuno 提供了一个默认加载器,开箱即可使用。不过,商家可以选择实施自己的加载器,并负责进行必要的配置。

步骤 8:创建付款

步骤 7,使用 创建支付endpoint.使用 checkout_session步骤 3 和创建付款的一次性token 。

创建支付endpoint 的响应将包括以下参数 sdk_action_required,根据付款类型定义完成付款是否需要其他操作。

🚧

继续整合付款方式

Yuno 需要 您将整合 continuePayment 因为某些异步支付方法需要额外的客户操作才能完成。API 会通过 sdk_action_required 字段,该字段将返回为 true。返回 yuno.continuePayment() 该功能将向客户显示额外的屏幕,客户可以在屏幕上执行必要的操作来完成支付,而无需您处理每一种情况。

步骤 9:继续付款

Yuno 需要集成 SDK 的 continuePayment 方法,因为某些异步支付方法需要额外的客户操作才能完成。从 创建支付endpoint从步骤 8 开始,将包括 sdk_action_required 字段。如果返回 TRUE您需要调用 continuePayment() 功能,以显示允许客户完成付款的附加屏幕。否则,不需要此步骤。调用 continuePayment 方法:

continuePayment(
   showPaymentStatus:Boolean = true、
   checkoutSession:= null、
   countryCode:String?
   callbackPaymentState: ((String?) -> Unit)? = null
)

要显示付款状态屏幕,请发送 FALSEshowPaymentStatus 参数。然后,通过回调获取付款状态。

渲染模式集成

Yuno SDK 渲染模式提供了高级用户界面灵活性,允许开发人员在保持full SDK 功能的同时,通过对用户界面的完全控制来集成支付流程。该模式返回的片段可与 Jetpack Compose 和传统 XML 视图一起使用。

主要功能 startPaymentRender

"(《世界人权宣言》) startPaymentRender 函数可在呈现模式下初始化支付流程,从而对用户界面的呈现进行细粒度控制。

fun Activity.startPaymentRender(
   checkoutSession:= null、
   countryCode:= null、
    coroutineScope:CoroutineScope、
   paymentSelected: PaymentSelected,
    listener:YunoPaymentRenderListener、
):YunoPaymentFragmentController

参数

参数类型需要说明
checkoutSessionString?没有之前创建的结账会话的 ID
countryCodeString?没有地区配置的国家代码
coroutineScopeCoroutineScope用于异步操作的例行程序范围
paymentSelectedPaymentSelected选择的付款方式
listenerYunoPaymentRenderListener接收事件的监听器实现

实施示例

class PaymentActivity : Activity() {

    private lateinit var fragmentController: YunoPaymentFragmentController

    private fun initializePayment() {
        fragmentController = startPaymentRender(
            checkoutSession = "your_checkout_session_id",
            countryCode = "US",
            coroutineScope = lifecycleScope,
            paymentSelected = PaymentSelected.CARD,
            listener = paymentRenderListener
        )
    }
}

YunoPaymentRenderListener 界面

执行此接口可在支付流程中接收来自 SDK 的所有事件和视图:

class PaymentRenderListener : YunoPaymentRenderListener {

    override fun showView(fragment: Fragment) {
        supportFragmentManager.beginTransaction()
            .replace(R.id.payment_container, fragment)
            .commit()
    }

    override fun returnStatus(resultCode: Int, paymentStatus: String) {
        when (paymentStatus) {
            "SUCCEEDED" -> handleSuccessfulPayment()
            "FAIL" -> handleFailedPayment()
        }
    }

    override fun returnOneTimeToken(oneTimeToken: String, additionalData: OneTimeTokenModel?) {
        createPaymentInBackend(oneTimeToken) { result ->
            when (result) {
                is Success -> fragmentController.continuePayment()
                is Error -> handlePaymentError(result.error)
            }
        }
    }

    override fun loadingListener(isLoading: Boolean) {
        progressBar.visibility = if (isLoading) View.VISIBLE else View.GONE
    }
}

YunoPaymentFragmentController 界面

使用返回的控制器实例控制付款流程:

方法

  • submitForm():当前表格可用时提交
  • continuePayment():后端 OTT 处理后继续支付流程
fragmentController.submitForm()

fragmentControllercontinuePayment()

整合效益

用户界面的灵活性

  • 兼容 Compose 和 XML:与 Jetpack Compose 和传统 XML 视图兼容
  • 完全控制:由您决定每个视图的显示位置和方式
  • 自定义集成:与现有应用程序设计轻松集成

流量控制

  • 自定义提交逻辑:控制何时提交表单
  • 后台集成:先在后台处理 OTT,然后再继续

完整集成示例

class PaymentActivity : ComponentActivity() {

    private lateinit var fragmentController: YunoPaymentFragmentController

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        fragmentController = startPaymentRender(
            checkoutSession = checkoutSessionId,
            countryCode = "US",
            coroutineScope = lifecycleScope,
            paymentSelected = PaymentSelected.CARD,
            listener = object : YunoPaymentRenderListener {
                override fun showView(fragment: Fragment) {
                    supportFragmentManager.beginTransaction()
                        .replace(R.id.payment_fragment_container, fragment)
                        .commit()
                }

                override fun returnOneTimeToken(oneTimeToken: String, additionalData: OneTimeTokenModel?) {
                    processPaymentToken(oneTimeToken) {
                        fragmentController.continuePayment()
                    }
                }

                override fun returnStatus(resultCode: Int, paymentStatus: String) {
                    handlePaymentResult(paymentStatus)
                }

                override fun loadingListener(isLoading: Boolean) {
                    updateLoadingState(isLoading)
                }
            }
        )
    }
}
🚧

生命周期管理

确保 CoroutineScope 与活动/片段生命周期挂钩,以防止内存泄漏并确保正确清理。

补充功能

Yuno Android SDK 提供额外的服务和配置,您可以用来改善客户体验。使用SDK 定制功能可更改 SDK 外观以匹配您的品牌或配置加载器:

使用密码匙的点击支付 (CTP)

与其他程序不同的是,当用户使用 CTP 密码完成支付时 一次性Token (OTT)将不会通过通常的回调方法接收。OTT 将通过 深度链接URL 在 Intent 中。您的应用程序必须从 Intent在后台创建付款,然后使用 SDK 继续流程。

⚠️

重要

它是 必不可少的 包含一个 callback_url 在创建CTP Passkey支付的结算会话时。此URL必须与您在AndroidManifest中配置的深度链接方案相匹配。例如:

{
  "callback_url": "myapp://pay/ctp"
}

"(《世界人权宣言》) callback_url 用于在密钥认证流程完成后,将客户重定向回您的应用。

1.AndroidManifest (深度链接)

添加一个 intent-filter 的主要活动 AndroidManifest.xml:

<activity android:name=".CheckoutActivity" android:exported="true">
  <intent-filter>
    <action android:name="android.intent.action.VIEW" />
    <category android:name="android.intent.category.DEFAULT" />
    <category android:name="android.intent.category.BROWSABLE" />
    <!-- Adjust to your actual scheme/host -->
    <data android:scheme="myapp" android:host="pay" android:pathPrefix="/ctp" />
  </intent-filter>
</activity>

调整 scheme, hostpathPrefix 以匹配应用程序的配置。

2.处理意图

在您的活动中,在以下两个方面处理 Intent onCreate()onNewIntent():

class CheckoutActivity : AppCompatActivity() {
    
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        initYuno()
        startCheckout()
        // Initialize your SDK / UI
        handleDeeplink(intent)
    }

    override fun onNewIntent(intent: Intent) {
        super.onNewIntent(intent)
        setIntent(intent)
        handleDeeplink(intent)
    }

    private fun handleDeeplink(intent: Intent?) {
        val uri = intent?.data ?: return

        when {
            // Cancellation or error
            uri.getBooleanQueryParameter("has_error", false) -> {
                val message = uri.getQueryParameter("message") ?: "Operation canceled"
                showError(message)
            }

            // Success: OTT received in URL
            uri.getQueryParameter("one_time_token") != null -> {
                val ott = extractOtt(uri) ?: return
                val checkoutSession = extractCheckoutSession(uri)

                // 1) Send the OTT to your backend to create the payment
                createPaymentOnBackend(ott) { success ->
                    if (success && checkoutSession != null) {
                        // 2) Then continue the flow in the SDK
                        continuePayment(
                            checkoutSession = checkoutSession,
                            countryCode = currentCountry
                        ) { result ->
                            // Handle payment state
                        }
                    }
                }
            }
        }
    }
    
    private fun extractOtt(uri: Uri): String? =
        uri.getQueryParameter("one_time_token")

    private fun extractCheckoutSession(uri: Uri): String? =
        uri.getQueryParameter("checkout_session")
            ?: uri.getQueryParameter("checkoutSession")
}

3.创建付款(后台)

从深层链接中提取OTT后,使用创建付款 endpoint在后台创建付款。

收到来自后台的成功响应(付款已创建)后,在 SDK 中继续流程,调用 continuePayment().

4.辅助功能

创建辅助函数,从 Intent URI 中提取参数:

private fun extractOtt(uri: Uri):=
    uri.getQueryParameter("one_time_token")

private fun extractCheckoutSession(uri: Uri):= uri.getQueryParameter("one_time_token")
    uri.getQueryParameter("checkout_session")
        uri.getQueryParameter(checkoutSession")
💡

提示

在 QA 环境中,记录完整的 URL 以验证参数名称。

5.快速测试

您可以使用这些示例深层链接 URL 测试 CTP 密钥流:

  • 成功: myapp://pay/ctp?one_time_token=OTT_123&checkout_session=CHK_456
  • 错误: myapp://pay/ctp?has_error=true&message=User%20canceled
  • 继续: myapp://pay/ctp

6.核对表

使用此核对表可确保正确集成 CTP 密钥:

  • callback_url 在创建结账会话时包含(必须与深度链接方案匹配)
  • intent-filter 配置正确(方案/主机/路径)
  • handleDeeplinkonCreate()onNewIntent()
  • ✅ 同时提取 one_time_tokencheckout_session 参数
  • ✅ 使用以下功能在后台创建付款 OTT ➜ 呼叫 continuePayment(...)
  • ✅ 手柄 has_errormessage 错误情景参数
⚠️

重要

OTT 将 通过 callbackOTT 功能用于 CTP 密码支付。您必须从 Intent URI 参数中提取token 。

styles

随着 styles 自定义选项,您可以通过一个 YunoStyles 对象。通过自定义按钮外观和排版,您可以在整个 SDK 中应用一致的品牌。

data classYunoStyles(
    val buttonStyles:YunoButtonStyles? = null、
    val fontFamily:= null
)
参数说明
buttonStyles自定义 SDK 中显示的主要按钮。
fontFamily设置所有 SDK 文本元素使用的字体系列。

"(《世界人权宣言》) YunoButtonStyles 对象可让您定义按钮外观的特定设置:

data class YunoButtonStyles(
    val backgroundColor: Color? = null、
    val contentColor: Color? = null、
    val cornerRadius:= null
    val elevation:= null、
    val padding:= null、
    val fontFamily:= null、
    val fontSize:TextUnit? = null、
    val fontStyle:FontStyle?
)

要使用 styles 自定义选项,使用 YunoConfig 数据类,详见步骤 2。

装载机

通过 keepLoader 参数中的 YunoConfig 数据类,该类已在上文 SDK 配置部分内嵌记录。

为未来付款保存银行卡

您可以使用复选框来保存或注册卡片。 cardSaveEnable: true.以下示例显示了两种卡片表单渲染的复选框:

渲染选项

您可以选择两种卡片表单渲染选项。下面的截图显示了 cardFormType ONE_STEPSTEP_BY_STEP:

SDK 定制

您可以更改 SDK 的外观,使其与您的品牌相匹配。有关详细信息,请参阅SDK 自定义页面。

📘

演示应用程序

除提供的代码示例外,您还可以访问Yuno 存储库,获取 Yuno Android SDK 的完整实现。