Headless SDK (Payment Android)


👍

推荐的 SDK

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

本页提供 Yuno Headless Android SDK 支付指南。

该 SDK 是以下商家的理想选择:

  • 需要对支付用户界面和用户体验进行全面控制
  • 希望建立自定义支付流程
  • 需要先进的集成能力

Headless SDK 包括以下核心功能:

  • 直接使用应用程序接口进行支付处理
  • 为支付方式生成Token
  • 3DS 验证处理
  • 防欺诈数据收集

如果商家希望使用预建用户界面解决方案,可考虑使用我们的 Full SDKLite SDK来代替。

要求

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

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

最新 SDK 版本

请查看发行说明或访问Yuno Android SDK 存储库,以验证当前可用的 SDK 版本。

步骤 1:创建客户

在开始付款前,使用创建客户endpoint创建客户。需要此步骤来

  • 确定付款人的身份
  • 启用保存的付款方式功能(如果已启用)
  • 跟踪付款历史

从该endpoint 返回的客户 ID 将用于创建 checkout_session.

步骤 2:创建结账会话

创建一个新的 checkout_session 使用 创建结账会话 endpoint 来initialize 支付流程。确保

  • 包括上一步获得的客户 ID
  • 存储返回的 checkout_session ID 供以后步骤使用

"(《世界人权宣言》) checkout_session 对每次付款尝试来说都是唯一的,不能重复使用。

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

通过 Gradle 在项目中加入 Yuno SDK。添加版本库源代码:

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

将 Yuno SDK 依赖关系添加到应用程序的 build.gradle 锉刀

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

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

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

步骤 4:使用公钥Initialize headless SDK

导入 Yuno 并提供有效的 PUBLIC_API_KEY来initialize Headless SDK。如果没有 API 凭据,请参阅开发人员(凭据)页面,查看如何从仪表板检索凭据

如果尚未创建自定义应用程序,请创建一个。在 onCreate() 方法,通过调用 Yuno.initialize() 功能:

class CustomApplication : Application() {
  override fun onCreate() {
    super.onCreate()
    Yuno.initialize(
      this,
      PUBLIC_API_KEY,
      config: YunoConfig,
    )
  }
}

步骤 5:开始结账

致电 apiClientPayment 功能,在客户选择付款方式后开始结账流程。该功能需要配置参数,并开始收集您的系统中配置的 3DS 身份验证和反欺诈工具所需的信息。 路由.

下表描述了所需参数:

参数

说明

country_code

  • 该参数用于确定正在配置支付流程的国家。

checkout_session

  • Example: '438413b7-4921-41e4-b8f3-28a5a0141638'

下面的代码块显示了一个参数配置示例:

 val apiClientPayment = Yuno.apiClientPayment(
   country_code = "US"、
  checkoutSession = "74bf4b96-6b35-42a6-8c73-2fe094c34ca9"、
   context = this
)

步骤 6:生成token

收集用户信息后,使用 apiClientPayment.generateToken 函数。由于这是一个异步函数,因此使用 try/catch 块来处理可能出现的任何错误。下面的示例展示了创建一次性token的两种不同情况:

  1. 例 1:创建一个一次性token ,使用银行卡作为支付方式,并包含所有必需的银行卡信息。
  2. 示例 2:使用 vaulted_token 信息。

使用拱顶token好处

当您使用 SDK 的保险库token 时,您在卡路由中配置的提供商的所有欺诈信息都会被收集并附加到一次性token中。如果提供商需要,您还可以添加分期付款信息和安全代码。


apiClientPayment.generateToken(
   collectedData = TokenCollectedData(
 checkoutSession "checkout_session",
       paymentMethod = PaymentMethod (
           type = "CARD",
 vaultedToken  null,
           card = CardData(
               save = true,
               detail = Detail(
                   expirationMonth = 11,
                   expirationYear = 55,
                   number = "4111111111111111",
                   安全码 = "123",
                  持卡人姓名 = "名 姓",
                  类型 = CardType.DEBIT
               ),
              分期付款 = Installment(
                   id = "id",
                  金额 = 12
               )
           ),
           客户 = 客户(
               id = "id",
               商户客户ID = "merchant_customer_id",
               名 = "firstName",
               姓 = "lastName",
               性别 = 性别.NB,
               出生日期 = "DD/MM/YYYY",
 email "[email ]",
               country = "US",
               document = Document(
                   documentType = "PAS",
                   documentNumber = "PAS12312"
               ),
               phone = Phone(
                   number = "321123321123",
                   country_code = "1"
               )
           )
       )
   ),
   context = this
)

apiClientPayment.generateToken(
   collectedData = TokenCollectedData(
 checkoutSession "checkout_session",
       paymentMethod = PaymentMethod(
           type = "CARD",
 vaultedToken "a1c7c5d1-b260-4dc6-909a-8368704233cf",
           card = CardData(
               save = true,
               detail = Detail(
                   expirationMonth = 11,
                   expirationYear = 55,
                   number = "4111111111111111",
                   securityCode = "123",
                   holderName = "Firstname Lastname",
                   type = CardType.DEBIT
               ),
               installment = Installment(
                   id = "id",
                   value = 12
               )
           ),
           customer = Customer(
               id = "id",
               merchantCustomerId = "merchant_customer_id",
               firstName = "firstName",
               lastName = "lastName",
               lastName = "lastName",
               性别 = 性别.男,
               出生日期 = "DD/MM/YYYY",
 email "[email ]",
               国家 = "CO",
               证件 = 证件(
                   证件类型 = "护照",
                   证件号 = "PAS12312"
               ),
               phone = Phone(
                   number = "321123321123",
 countryCode "57"
               )
           )
       )
   ),
   context = this
)

"(《世界人权宣言》) apiClientPayment.generateToken 函数返回一个 Observable 类型,它是 LiveData.您可以观察到作为普通 LiveData 类型如下 SingleLiveEvent<Map<String, Any?>>这是一个 LiveData 只发出一次。响应类型为 Map 包含整个响应。下面的代码块展示了调用 apiClientPayment.generateToken 功能。

[token":"9ee44ac7-9134-4598-ae28-a26fec03099d",
     "类型":"卡"、
     客户["billing_address":空、
                  "first_name": null、
                  性别"",
                  "电话": nil、
                  "浏览器信息["color_depth": null、
                                   语言"en"、
                                   "accept_header":"*/*",
                                   "browser_time_difference": null、
                                   "accept_content": null、
                                   "accept_browser": null、
                                   "java_enabled": null、
                                   "user_agent":"YunoSDK_Example/1 CFNetwork/1406.0.4 Darwin/22.6.0"、
                                   "screen_height":"844.0",
                                   "屏幕宽度"390.0",
                                   "javascript_enabled": null]、
                  "document": null、
                  "last_name":空
                  "设备指纹": null、
                 email":空]、
     "国家":"US"、
     "vaulted_token": null、
     "分期付款":["利率":"",
                     "id":"cca80084-961b-4212-9c34-54f03f4f10ae",
                     "值": 24、
                     "金额": null]、
     "卡数据":空]
[token":"9ee44ac7-9134-4598-ae28-a26fec03099d",
     "类型":"卡"、
     客户["billing_address":空、
                  "first_name": null、
                  性别"",
                  "电话": nil、
                  "浏览器信息["color_depth": null、
                                   语言"en"、
                                   "accept_header":"*/*",
                                   "browser_time_difference": null、
                                   "accept_content": null、
                                   "accept_browser": null、
                                   "java_enabled": null、
                                   "user_agent":"YunoSDK_Example/1 CFNetwork/1406.0.4 Darwin/22.6.0"、
                                   "screen_height":"844.0",
                                   "屏幕宽度"390.0",
                                   "javascript_enabled": null]、
                  "document": null、
                  "last_name":空
                  "设备指纹": null、
                 email":空]、
     "国家":"BR"、
     "vaulted_token":"a1c7c5d1-b260-4dc6-909a-8368704233cf",
     "分期付款":["利率":"",
                     "id":"cca80084-961b-4212-9c34-54f03f4f10ae",
                     "值": 24、
                     "金额": null]、
     "卡数据":空]

endpoint 响应提供 sdk_action_required 参数,该参数定义了是否有必要采取额外行动。

下面的代码块显示了一个观察响应的示例:

apiClientPayment.generateToken(data, context).observe(context) { response ->
   valtoken = response[token"] as String?
   val error = response["error"] as String?
}

第 7 步:创建付款

生成一次性token后,通过调用 创建支付endpoint.包括在 步骤 6payment_method.token 参数。以下代码块显示了创建付款请求的示例:

{
  "merchant_order_id": "0000022",
  "country": "US",
  "account_id": "<Your account_id>",
  "description": "Test",
  "amount": {
    "currency": "USD",
    "value": 500
  },
  "customer_payer": {
    "id": "cfae0941-7234-427a-a739-ef4fce966c79"
  },
  "checkout": {
    "session": "<checkout session>"
  },
  "workflow": "SDK_CHECKOUT",
  "payment_method": {
    "type":"CARD",
    "token": "2cd31999-e44e-4de3-bbe4-179981ff4295"
  }
}

endpoint 响应包括 sdk_action_required 参数,该参数表示是否需要其他操作来完成付款:

  • 对于同步支付方法,支付会立即完成。在这种情况下 sdk_action_requiredfalse 在 API 响应中,支付流程结束
  • 用于需要额外 SDK 交互的支付流程、 sdk_action_requiredtrue.出现这种情况时,请转到 步骤 8 下一步行动

步骤 8:获取 3DS 挑战 URL(如需要)

当支付需要 3DS 身份验证时,可能需要额外的挑战来验证客户的身份。有关此过程的更多详情,请参阅3D 安全页面。如果需要 3DS 验证挑战,创建支付endpoint 响应将包括以下内容:

  • A THREE_D_SECURE 交易类型
  • 状态等于 PENDING 和子状态等于 WAITING_ADDITIONAL_STEP
  • sdk_action_required = true

致电 getThreeDSecureChallenge 功能,并提供 checkoutSession 用于创建付款以获取 3DS 挑战 URL。获得 URL 后,重定向客户以完成挑战。以下代码块展示了如何使用 getThreeDSecureChallenge 功能:

fun ApiClientPayment.getThreeDSecureChallenge(
   context: Context,
   checkoutSession: String? = null,
): SingleLiveEvent<ThreeDSecureChallengeResponse>

"(《世界人权宣言》) getThreeDSecureChallenge 函数返回 ThreeDSecureChallengeResponse 数据类,具体代码如下:

data class ThreeDSecureChallengeResponse(
   val type:String、
   val data:String、
)

"(《世界人权宣言》) type 能返回 ERRORURL,定义函数是否返回了挑战的有效 URL:

  • 如果 type = URL, data 将包含客户完成 3DS 挑战所需的 URL。
  • 如果 type = ERROR, data 将包含错误信息,告知问题的根源。

下面的代码块举例说明了如何观察来自 ThreeDSecureChallengeResponse:

apiClientPayment.getThreeDSecureChallenge(this)?.observe(this) {
   if (it.type == "URL") {
   } else 
}

当响应类型为 "URL "时,您可以在首选视图(WebView、自定义标签页或浏览器)中加载 3DS 挑战 URL。如果响应类型不是 "URL",则表示发生了错误,您应通过向用户显示错误消息来适当处理。

要完成 3DS 挑战,请将客户重定向到由 getThreeDSecureChallenge(context).成功完成后,客户将自动跳转到 callback_url 时指定的 checkout_session 使用 创建结账会话 endpoint。下面的示例展示了如何在 WebView 中加载 3DS 挑战 URL:

val webView = WebView(this)
webViewContainer.addView(
   webView,
   ConstraintLayout.LayoutParams(
       ConstraintLayout.LayoutParams.MATCH_PARENT,
       ConstraintLayout.LayoutParams.MATCH_PARENT
   )
)
webView.settings.javaScriptEnabled = true
webView.addJavascriptInterface(
   object {
       @JavascriptInterface
       fun messageFromWeb(data: String?) {
       }
   },
   "Android"
)
webView.loadUrl(url)

JavaScript 界面必须使用 messageFromWeb(data : String?) 并以 Android.这样就可以捕捉挑战事件,并确定它们何时完成。

完成Headless SDK 支付流程:

  1. 使用Yuno Webhooks接收相关通知:

    • 3DS 挑战赛的结果
    • 最终付款状态
  2. 可选择使用 "按 ID 检索付款"endpoint检索付款详情。

有关完整的支付实施指南,请参阅Headless SDK (支付)

补充功能

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

装载机

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

SDK 定制

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

📘

访问演示应用程序

除了提供的代码示例,您还可以查看Yuno 存储库,以完成 Yuno Android SDK 的实施。