Lite SDK (Enrollment iOS)
本指南将指导您将 Yuno 用于注册的 Lite iOS SDK 集成到您的项目中。
要求
在实施 Yuno iOS SDK 之前,请确保满足这些要求:
- 在项目中添加CocoaPods或Swift 包管理器。
- 使用 iOS 14.0 或以上版本。
第 1 步:在项目中加入程序库
您可以使用 CocoaPods 或 Swift 软件包管理器添加该库。
CocoaPods
使用 CocoaPods 将 Yuno SDK 添加到您的 iOS 项目中。如果您没有 Podfile,请按照CocoaPods 指南创建一个。然后在 Podfile 中添加以下一行:
pod "YunoSDK","~> 1.1.22然后运行安装程序:
吊舱安装
Swift 软件包管理器
使用 Swift 包管理器添加 Yuno SDK。添加 YunoSDK 作为您 Package.swift 文件中的依赖项:
依赖项:[
.package(url:"https://github.com/yuno-payments/yuno-sdk-ios.git", .upToNextMajor(from: "1.1.17"))
]步骤 2:注册新的付款方式
呼叫前
Yuno.enrollPayment(),确保您已经用以下命令初始化了 SDKYuno.initialize().
Yuno 的 iOS SDK 为支付方法提供了注册功能。要显示注册流程,请实现委托并调用注册方法:
protocol YunoEnrollmentDelegate: AnyObject {
var customerSession: String { get }
var countryCode: String { get }
var language: String? { get }
var viewController: UIViewController? { get }
func yunoEnrollmentResult(_ result: Yuno.Result)
}
class ViewController: YunoEnrollmentDelegate {
func startEnrollment() {
Yuno.enrollPayment(with: self, showPaymentStatus: Bool)
}
}
Yuno.enrollPayment() 全屏显示 UIViewController 使用 viewController 在您的 delegate.这仅适用于 UIKit。在 SwiftUI 中,将一个 UIViewController 并通过 viewController 财产该 delegate 必须暴露一个可见控制器,以便 SDK 展示用户界面。
参数
| 参数 | 说明 |
|---|---|
customerSession | 指当前付款的客户会话。 |
countryCode | 该参数决定了正在配置支付流程的国家。支持国家及其国家代码的完整列表可在 "国家覆盖范围"页面查看。 |
language | 定义付款表单中使用的语言。您可以将其设置为可用语言选项之一:
|
viewController | 该属性表示 UIViewController 用于显示注册流程。尽管为了实现向后兼容性,该属性仍然是可选的,但您必须提供一个可见控制器,以便 SDK 能正确显示其用户界面。 |
yunoEnrollmentResult(\_ result: Yuno.Result) | 注册过程完成后,该方法将被调用,并将注册结果作为类型为 Yuno.Result. |
"(《世界人权宣言》) showPaymentStatus 参数决定是否显示付款状态。通过 true 显示付款状态,而通过 false 藏起来。
参数
"(《世界人权宣言》) enrollPayment 方法参数说明如下:
| 参数 | 类型 | 说明 |
|---|---|---|
delegate | YunoEnrollmentDelegate | 处理注册回调的委托对象。 |
showPaymentStatus | Bool | 布尔标志,用于确定是否在付款注册过程中显示状态视图。 |
方法 enrollPayment 启动支付注册流程。应在用户交互(如按下按钮)时调用该方法。该方法利用提供的 delegate 管理注册事件,并根据参数 showPaymentStatus决定是否显示有关注册状态的视觉反馈。
步骤 3:注册情况
深度链接注册此功能只有在注册了可执行深度链接的付款方式时才会使用。如果没有注册执行深度链接的付款方式,可以忽略步骤 3。
如果您使用的支付方法需要返回应用程序的深度链接,请使用以下代码块中描述的方法在您的 AppDelegate.......。 url.scheme 应与 callback_url 时使用的 customer_session.
func application(_ app: UIApplication, open url: URL, options: [UIApplication.OpenURLOptionsKey : Any] = [:]) -> Bool {
guard url.scheme == "yunoexample" else { return false }
return Yuno.receiveDeeplink(url, showStatusView: true)
}
Swift 6 并发要求如果使用 Swift 6,则需要执行
YunoPaymentDelegate协议的具体并发考虑因素。Swift 6 引入了更严格的线程安全要求,这将影响您实现委托的方式。请参见 实施YunoPaymentDelegate使用 Swift 6 并发 部分,了解详细的实施方案和最佳做法。
理解 Yuno.Result
Yuno.Result注册过程结束后,SDK 会调用:
func yunoEnrollmentResult(_ result:Yuno.Result)这一结果可能反映了入学的不同最终状态。这 Yuno.Result 枚举包括
枚举结果 {
成功
失败
拒绝
处理中
internalError
userCancell
}您可以使用开关来处理每种结果情况:
func yunoEnrollmentResult(_ result: Yuno.Result) {
switch result {
case .success:
print("Enrollment successful")
case .fail:
print("Enrollment failed")
case .processing:
print("Enrollment still processing")
case .reject:
print("Enrollment rejected")
case .userCancell:
print("User canceled")
case .internalError:
print("Internal error")
}
}
Yuno.Result不包括tokens 或错误信息。您只会得到一个高级状态,以帮助您指导用户体验。
渲染模式集成(报名)
渲染模式为注册提供了更大的用户界面灵活性,让您可以在使用 SDK 验证和逻辑的同时,将注册流程集成到自己的视图中。
主要功能 startEnrollmentRenderFlow
startEnrollmentRenderFlow@MainActor static func startEnrollmentRenderFlow(
with delegate:YunoEnrollmentDelegate
) async -> 某 YunoEnrollmentRenderFlowProtocolYunoEnrollmentRenderFlowProtocol
func formView(
with delegate: YunoEnrollmentDelegate
) async -> AnyView?
func submitForm()
var needSubmit: Bool { get }- formView:返回一个
AnyView如果需要 UI,则与注册表(卡/APM)一起提交;如果不需要 UI,则与注册表(卡/APM)一起提交nil. - 提交表格:触发验证,并在适用时继续注册。
- needSubmit:表示是否应显示提交按钮。
实施流程
步骤 1:创建注册流程实例
let enrollmentFlow = awaitYuno.startEnrollmentRenderFlow(with: self)步骤 2:获取并显示表单
let formView = await enrollmentFlow.formView(with: self)
if let formView = formView {
VStack {
Text("Enroll Payment Method")
formView
if enrollmentFlow.needSubmit {
Button("Enroll") {
enrollmentFlow.submitForm()
}
}
}
}步骤 3:处理注册结果
extension MyViewController: YunoEnrollmentDelegate {
var customerSession: String { "your_customer_session" }
var countryCode: String { "CO" }
var language: String? { "es" }
var viewController: UIViewController? { self }
func yunoEnrollmentResult(_ result: Yuno.Result) {
// Handle enrollment result
}
}补充功能
Yuno iOS SDK 提供额外的服务和配置,可用于改善客户体验。
渲染选项
在提交注册时,您还可以选择其中一种卡片形式的渲染选项。您有以下选项:
ONE_STEPSTEP_BY_STEP
要更改渲染选项,请设置 cardFormType 等于其中一个可用选项。下文介绍了每种选项。
装载机
通过 SDK 配置选项控制加载器的使用。
SDK 定制
使用SDK 定制功能更改 SDK 外观,使其与您的品牌相匹配。
演示应用程序除提供的代码示例外,您还可以访问Yuno 存储库,获取 Yuno iOS SDK 的完整实现。
实施 YunoPaymentDelegate 使用 Swift 6 并发
YunoPaymentDelegate 使用 Swift 6 并发Swift 6 引入了更严格的并发性要求,这会影响您如何实现 YunoPaymentDelegate 协议。本节将解释这些挑战,并针对不同的实施方案提供解决方案。
了解 Swift 6 中的并发性并发性是指应用程序同时管理多个任务的能力。在 Swift 6 中,并发规则变得更加严格,以增强应用程序的稳定性并防止崩溃。这意味着您的代码结构必须更加严谨,以确保线程安全和适当的任务管理。
问题
在 Swift 6 中,继承自 Sendable 要求其所有实现都是线程安全的。当在标记为 @MainActor.
线程安全意味着你的代码可以被多个线程安全调用,而不会导致崩溃或意外行为。 @MainActor 确保代码在主线程(UI 线程)上运行。
我们的设计决定
我们不会将协议标记为 @MainActor 因为
- 这将迫使所有实现
MainActor兼容的 - 这将降低不使用以下功能的商家的灵活性
MainActor - 每种执行方式都有不同的并发需求
商家的责任
商家有责任根据自己的实施情况处理并发问题。以下是三种不同的方法,您可以根据自己的具体需求加以使用。
方案 1:不可变属性
这种方法使用不可变属性,可自动保证线程安全,是简单配置的理想选择。它最适用于具有固定配置值且在运行时不会改变的简单应用程序。
@MainActor
class MyViewController: UIViewController, YunoPaymentDelegate {
private let _countryCode = "CO"
private let _language = "EN"
nonisolated var countryCode: String { _countryCode }
nonisolated var language: String? { _language }
nonisolated var checkoutSession: String { _checkoutSession }
nonisolated func yunoPaymentResult(_ result: Yuno.Result) {
Task { @MainActor in
// Handle result
}
}
}方案 2:可变属性 MainActor.assumeIsolated
MainActor.assumeIsolated这种方法最适用于配置值可能在运行时发生变化的应用程序(如用户偏好设置),通过使用 MainActor.assumeIsolated.
@MainActor
class MyViewController: UIViewController, YunoPaymentDelegate {
@Published var configLanguage: String = "EN"
@Published var configCountryCode: String = "CO"
nonisolated var language: String? {
MainActor.assumeIsolated { configLanguage }
}
nonisolated var countryCode: String {
MainActor.assumeIsolated { configCountryCode }
}
}方案 3:对于非 MainActor 班级
MainActor 班级这种方法适用于不需要 MainActor 隔离,因此最适合不与用户界面交互的后台服务或实用程序类。
class MyService: YunoPaymentDelegate {
let countryCode: String
let language: String?
let checkoutSession: String
let viewController: UIViewController?
init(countryCode: String, language: String?, checkoutSession: String, viewController: UIViewController?) {
self.countryCode = countryCode
self.language = language
self.checkoutSession = checkoutSession
self.viewController = viewController
}
func yunoPaymentResult(_ result: Yuno.Result) {
// Handle result
}
}⚠️ 重要考虑因素
在委托中实现并发时,请牢记以下要点:
MainActor.assumeIsolated:仅在保证从MainActor.这是一种安全机制,它告诉 Swift "相信我,我知道这是在主线程上运行的"。nonisolated:表示可以从任何线程访问,因此必须是线程安全的。当您的属性或方法不依赖于用户界面状态时,请使用此属性或方法。viewController:仍为@MainActor因为它应始终由主线程访问。用户界面组件必须始终在主线程上运行,以防止崩溃。
2 个月前已更新