skyflow-iOS
Skyflow 的 iOS SDK 可以用于在移动设备上安全收集、标记和显示敏感数据,同时不将前端基础设施暴露给敏感数据。
目录
安装
要求
- iOS 13.0.0 及以上版本
配置
SPM (Swift Package Manager)
- 在 Xcode IDE 中前往“文件”->“Swift 包”->“新建包依赖
- 输入 https://github.com/skyflowapi/skyflow-iOS.git 并按“确定”。
Cocoapods
- 要使用 Cocoapods 将 skyflow-iOS 集成到您的 Xcode 项目中,请在 Podfile 中指定它
#Mentioning the below source will pick the podspec from Skyflow repo #Otherwise you can add cocoapod trunk as the source #source 'https://github.com/skyflowapi/skyflow-iOS-spec.git' pod 'Skyflow'
初始化 skyflow-iOS
使用 initialize()
方法来初始化一个 Skyflow 客户端,如下所示。
//DemoTokenProvider is an implementation of the Skyflow.TokenProvider protocol
let demoTokenProvider = DemoTokenProvider()
let config = Skyflow.Configuration(
vaultID: <VAULT_ID>,
vaultURL: <VAULT_URL>,
tokenProvider: demoTokenProvider,
options: Skyflow.Options(
logLevel: Skyflow.LogLevel, // optional, if not specified default is ERROR
env: Skyflow.Env // optional, if not specified default is PROD
)
)
let skyflowClient = Skyflow.initialize(config)
对于 tokenProvider 参数,传递一个实现 Skyflow.TokenProvider
协议的实例,该协议声明了一个 getBearerToken 方法,用于从您的后端检索 Skyflow 托管令牌。此函数将在 SDK 需要向或从保险库插入或检索数据时调用。
例如,如果消费者 tokenAPI 的响应格式如下
{
"accessToken": string,
"tokenType": string
}
那么,您的 Skyflow.TokenProvider 实现应该如下所示
public class DemoTokenProvider: Skyflow.TokenProvider {
public func getBearerToken(_ apiCallback: Skyflow.Callback) {
if let url = URL(string: <YOUR_TOKEN_ENDPOINT>) {
let session = URLSession(configuration: .default)
let task = session.dataTask(with: url) {data, _, error in
if error != nil {
print(error!)
return
}
if let safeData = data {
do {
let x = try JSONSerialization.jsonObject(with: safeData, options: []) as? [String: String]
if let accessToken = x?["accessToken"] {
apiCallback.onSuccess(accessToken)
}
} catch {
apiCallback.onFailure(error)
}
}
}
task.resume()
}
}
}
注意:您应将访问令牌作为 String
类型的值在 getBearerToken 的成功回调中传递。
对于 logLevel
参数,Skyflow.LogLevel 中有 4 个接受值
-
DEBUG
当传递
Skyflow.LogLevel.DEBUG
时,将打印所有日志级别(DEBUG、INFO、WARN、ERROR)。 -
INFO
当传递
Skyflow.LogLevel.INFO
时,将打印 SDK 流执行过程中发生的每个事件的 INFO 日志以及 WARN 和 ERROR 日志。 -
WARN
当传递
Skyflow.LogLevel.WARN
时,将打印 WARN 和 ERROR 日志。 -
ERROR
当传入
Skyflow.LogLevel.ERROR
时,只有 ERROR 日志会被打印。
注意
:
- 日志级别的排序如下:DEBUG < INFO < WARN < ERROR
- 由于
logLevel
可选,默认情况下 logLevel 将会是ERROR
。
对于 env
参数,在 Skyflow.Env 中有 2 个接受值
-
PROD
-
DEV
在 事件监听器 中,只有当
env
设置为DEV
时,才能在处理器内部访问元素的实际值。
注意
:
- 由于
env
可选,默认情况下 env 将会是PROD
。 - 谨慎使用
env
选项,确保在使用skyflow-iOS
生产环境中,环境设置为PROD
。
客户端安全收集数据
- 将数据插入宝库
- 使用 Skyflow Elements 收集数据
- 在 Collect Elements 上使用验证
- 在 Collect Elements 上的事件监听器
- Collect Elements 的 UI 错误
- 为 Collect Elements 设置和清除值(仅限 DEV 环境)
将数据插入宝库
要将数据插入您的宝库,请使用 skyflowClient.insert()
方法。
insert(records: [String: Any], options: InsertOptions?= InsertOptions() , callback: Skyflow.Callback)
insert()
方法需要一个 records 参数。The records
参数接受一个要插入宝库的记录数组。
插入调用示例
let insertCallback = InsertCallback() //A Custom callback using Skyflow.Callback
skyflowClient.insert(
records: [
"records": [
[
"table": "cards",
"fields": [
"cardNumber": "41111111111",
"cvv": "123",
]
]
]
],
callback: insertCallback
)
Skyflow 会为刚插入的记录返回令牌。
{
"records": [ {
"table": "cards",
"fields": {
"cardNumber": "f37186-e7e2-466f-91e5-48e12c2bcbc1",
"cvv": "1989cb56-63da-4482-a2df-1f74cd0dd1a5"
}
}]
}
options 参数接受一个 Skyflow.InsertOptions 对象。
InsertOptions 包含一个 tokens
布尔值,用于控制在将记录插入宝库后是否接收令牌。
InsertOptions 支持强大的 Upsert 功能,允许您通过指定用作唯一值的唯一列来有条件地插入或更新现有记录。
例如,如果您指定使用 'customer_id' 列来 Upsert,且该 customer_id 已存在,则将更新现有记录。如果 customer_id 不存在,则创建新的记录。
插入调用示例
let records = [
"records" : [
[
"table": "customers", //The table where you are inserting the record.
"fields": [
"name" : "Francis",
"customer_id" : "12345"
]
]
]
]
let upsertOptions = [["table": "customers", "column": "customer_id"]] as [[String : Any]]
let insertOptions = Skyflow.InsertOptions(tokens: false, upsert: upsertOptions)
let insertCallback = InsertCallback() //Custom callback - implementation of Skyflow.Callback
skyflowClient.insert(records: records, options: insertOptions, callback: insertCallback)
使用 Skyflow 元素收集数据
Skyflow Elements 为开发者提供了预构建的表单元素,以安全地收集客户端的敏感数据。这样可以减少您的 PCI 合规范围,因为它不会将前端应用程序暴露给敏感数据。按照以下步骤在您的应用程序中使用 Skyflow Elements 安全地收集数据。
步骤 1:创建容器
首先,如以下所示使用 skyflowClient.container(type: Skyflow.ContainerType)
方法创建用于表单元素的一个 容器
let container = skyflowClient.container(type: Skyflow.ContainerType.COLLECT)
步骤 2:创建收集元素
要创建收集元素,我们必须首先构建一个如以下所示的 Skyflow.CollectElementInput 对象
let collectElementInput = Skyflow.CollectElementInput(
table: String, // optional, the table this data belongs to
column: String, // optional, the column into which this data should be inserted
inputStyles: Skyflow.Styles, // optional styles that should be applied to the form element
labelStyles: Skyflow.Styles, // optional styles that will be applied to the label of the collect element
errorTextStyles: Skyflow.Styles, // optional styles that will be applied to the errorText of the collect element
label: String, // optional label for the form element
placeholder: String, // optional placeholder for the form element
altText: String, // (DEPRECATED) optional that acts as an initial value for the collect element
validations: ValidationSet, // optional set of validations for the input element
type: Skyflow.ElementType, // Skyflow.ElementType enum
)
table
和 column
字段指示元素对应的保险库中的表格和列。 注意:
- 使用点分隔的字符串来指定嵌套在 JSON 字段内的列(例如:
address.street.line1
) - 在调用 invokeConnection() 时,
table
和column
是可选的
inputStyles
参数接受一个 Skyflow.Styles 对象,该对象由多个 Skyflow.Styles
对象组成,这些对象应应用于以下状态下的表单元素
base
:所有其他变体都继承自这些样式complete
:当元素具有有效输入时应用empty
:当元素没有输入时应用focus
:当元素具有焦点时应用invalid
:当元素具有无效输入时应用
每个样式对象接受以下属性,请注意,每个属性都是可选的
let style = Skyflow.Style(
borderColor: UIColor, // optional
cornerRadius: CGFloat, // optional
padding: UIEdgeInsets, // optional
borderWidth: CGFloat, // optional
font: UIFont, // optional
textAlignment: NSTextAlignment, // optional
textColor: UIColor // optional
)
一个示例 Skyflow.Styles 对象
let styles = Skyflow.Styles(
base: style, // optional
complete: style, // optional
empty: style, // optional
focus: style, // optional
invalid: style // optional
)
labelStyles
和 errorTextStyles
字段接受上述 Skyflow.Styles
对象,分别应用于 label
和 errorText
文本视图
适用于 labelStyles
的状态是 base
和 focus
适用于 errorTextStyles
的状态仅是 base
状态,当收集元素出现错误时显示
Skyflow.Style
对象中尊重用于 label
和 errorText
文本视图的参数是
- 填充
- 字体
- 文本颜色
- 文本对齐
Skyflow.Style
对象中的其他参数对于 label
和 errorText
文本视图将被忽略
最后,type
参数接受一个 Skyflow.ElementType,每种类型都会将适当的正则表达式和验证应用于表单元素。目前有 5 种类型
INPUT_FIELD
CARDHOLDER_NAME
CARD_NUMBER
EXPIRATION_DATE
CVV
PIN
EXPIRATION_YEAR
EXPIRATION_MONTH
INPUT_FIELD
类型是一个自定义 UI 元素,没有内置的验证。有关验证的更多信息,请参阅 验证 部分。
除了 CollectElementInput
之外,您还可以在下面描述的 CollectElementOptions
对象中定义其他选项。
Skyflow.CollectElementOptions(
required: Boolean, // Indicates whether the field is marked as required. Defaults to 'false'
enableCardIcon: Boolean, // Indicates whether card icon should be enabled (only for CARD_NUMBER inputs)
format: String, // Format for the element
translation: [Character: String] // Indicates the allowed data type value for format.
)
required
:指示字段是否标记为必填。默认为false
。enableCardIcon
:指示 CARD_NUMBER 元素的图标是否可见。默认为true
。format
:一个表示适用于元素类型的格式模式的字符串值。仅适用于 EXPIRATION_DATE、CARD_NUMBER、EXPIRATION_YEAR 和 INPUT_FIELD 元素。- 对于 INPUT_FIELD 元素,
format
的长度决定了用户输入的预期长度。 - 如果没有指定
translation
,则认为format
值是一个字符串字面量。
- 对于 INPUT_FIELD 元素,
translation
:一个键/值对的字典,其中键是在format
中出现的字符,相应值是该字符可接受的输入的正则表达式。每个键只能出现一次。仅适用于 INPUT_FIELD 元素。
元素类型可接受值
元素类型 | format 和 translation 值 |
示例 |
---|---|---|
EXPIRATION_DATE |
|
|
EXPIRATION_YEAR |
|
|
CARD_NUMBER |
|
|
INPUT_FIELD |
|
具有 format 为 +91 XXXX-XX-XXXX 和 translation 为 [ "X": "[0-9]"] ,用户输入 "1234121234" 显示为 "+91 1234-12-1234"。。 |
INPUT_FIELD 的收集元素选项示例
Skyflow.CollectElementOptions(
required: true,
enableCardIcon: true,
format: "+91 XXXX-XX-XXXX",
translation: [ "X": "[0-9]"]
)
用户输入:"1234121234"
在 INPUT_FIELD 中显示的值:"1234121234"
示例 2
Skyflow.CollectElementOptions(
required: true,
enableCardIcon: true,
format: "AY XX-XXX-XXXX",
translation: [ "X": "[0-9]", "Y": "[A-Z]"]
)
用户输入:"B1234121234"
在 INPUT_FIELD 中显示的值:"B 12-341-2123"
一旦定义了 Skyflow.CollectElementInput
和 Skyflow.CollectElementOptions
对象,可以使用以下方法将它们添加到容器中:create(input: CollectElementInput, options: CollectElementOptions)
。如示,input
参数接收一个上面定义的 Skyflow.CollectElementInput
对象,而 options
参数则接收一个下面描述的 Skyflow.CollectElementOptions
对象
let collectElementInput = Skyflow.CollectElementInput(
table: String, // the table this data belongs to
column: String, // the column into which this data should be inserted
inputStyles: Skyflow.Styles, // optional styles that should be applied to the form element
labelStyles: Skyflow.Styles, // optional styles that will be applied to the label of the collect element
errorTextStyles: Skyflow.Styles, // optional styles that will be applied to the errorText of the collect element
label: String, // optional label for the form element
placeholder: String, // optional placeholder for the form element
altText: String, // (DEPRECATED) optional that acts as an initial value for the collect element
validations: ValidationSet, // optional set of validations for the input element
type: Skyflow.ElementType, // Skyflow.ElementType enum
)
let collectElementOptions = Skyflow.CollectElementOptions(
required: false, // indicates whether the field is marked as required. Defaults to 'false',
enableCardIcon: true, // indicates whether card icon should be enabled (only for CARD_NUMBER inputs)
format: "mm/yy" // Format for the element
)
let element = container?.create(input: collectElementInput, options: collectElementOptions)
第3步:将元素安装到屏幕上
为了指定元素将在屏幕上的渲染位置,创建一个父 UIView(如 UIStackView 等),然后可以以编程方式将其添加为子视图。
let stackView = UIStackView()
stackView.addArrangedSubview(element)
Skyflow 元素是 UIView 的实现,因此可以使用/安装的类似方式。或者,您可以使用 unmount
方法将任何收集元素重置为其初始状态
func clearFieldsOnSubmit(_ elements: [TextField]) {
// resets all elements in the array
for element in elements {
element.unmount()
}
}
第4步:从元素收集数据
在提交表单时,在容器对象上调用 collect(options: Skyflow.CollectOptions? = nil, callback: Skyflow.Callback)
方法。选项参数接收一个如下所示的 Skyflow.CollectOptions
对象
// Non-PCI records
let nonPCIRecords = ["table": "persons", "fields": [["gender": "MALE"]]]
// Upsert
let upsertOptions = [["table": "cards", "column": "cardNumber"]] as [[String : Any]]
// Send the non-PCI records as additionalFields of InsertOptions (optional) and apply upsert using `upsert` field of InsertOptions (optional)
let options = Skyflow.CollectOptions(tokens: true, additionalFields: nonPCIRecords)
//Custom callback - implementation of Skyflow.callback
let insertCallback = InsertCallback()
container?.collect(callback: insertCallback, options: options)
收集使用 Skyflow Elements 的数据
收集调用示例
//Initialize skyflow configuration.
let config = Skyflow.Configuration(vaultID: VAULT_ID, vaultURL: VAULT_URL, tokenProvider: demoTokenProvider)
//Initialize skyflow client.
let skyflowClient = Skyflow.initialize(config)
//Create a CollectContainer.
let container = skyflowClient.container(type: Skyflow.ContainerType.COLLECT)
//Create Skyflow.Styles with individual Skyflow.Style variants.
let baseStyle = Skyflow.Style(borderColor: UIColor.blue)
let baseTextStyle = Skyflow.Style(textColor: UIColor.black)
let completeStyle = Skyflow.Style(borderColor: UIColor.green)
val focusTextStyle = Skyflow.Style(textColor: UIColor.red)
let inputStyles = Skyflow.Styles(base: baseStyle, complete: completeStyle)
let labelStyles = Skyflow.Styles(base: baseTextStyle, focus: focusTextStyle)
let errorTextStyles = Skyflow.Styles(base: baseTextStyle)
// Create a CollectElementInput.
let input = Skyflow.CollectElementInput(
table: "cards",
column: "cardNumber",
inputStyles: inputStyles,
labelStyles: labelStyles,
errorTextStyles: errorTextStyles,
label: "card number",
placeholder: "card number",
type: Skyflow.ElementType.CARD_NUMBER
)
// Create an option to require the element.
let requiredOption = Skyflow.CollectElementOptions(required: true)
// Create a Collect Element from the Collect Container.
let skyflowElement = container?.create(input: input, options: requiredOption)
// Can interact with this object as a normal UIView Object and add to View
// Non-PCI records
let nonPCIRecords = ["table": "persons", "fields": [["gender": "MALE"]]]
//Upsert options
let upsertOptions = [["table": "cards", "column": "cardNumber"]] as [[String : Any]]
// Send the Non-PCI records as additionalFields of CollectOptions (optional) and apply upsert using optional field `upsert` of CollectOptions.
let collectOptions = Skyflow.CollectOptions(tokens: true, additionalFields: nonPCIRecords, upsert: upsertOptions)
//Implement a custom Skyflow.Callback to call on Insertion success/failure.
public class InsertCallback: Skyflow.Callback {
public func onSuccess(_ responseBody: Any) {
print(responseBody)
}
public func onFailure(_ error: Any) {
print(error)
}
}
// Initialize custom Skyflow.Callback.
let insertCallback = InsertCallback()
// Call collect method on CollectContainer.
container?.collect(callback: insertCallback, options: collectOptions)
Skyflow返回您刚刚插入的记录的令牌
{
"records": [ {
"table": "cards",
"fields": {
"cardNumber": "f3907186-e7e2-466f-91e5-48e12c2bcbc1"
}
}, {
"table": "persons",
"fields": {
"gender": "12f670af-6c7d-4837-83fb-30365fbc0b1e",
}
}]
}
验证
Skyflow-iOS提供两种类型的收集元素验证
1. 默认验证
除了类型为INPUT_FIELD
的收集元素之外,以下列出了默认验证集
CARD_NUMBER
:卡号验证,使用校验和算法(Luhn算法),定义的卡类型可用卡号长度CARD_HOLDER_NAME
:姓名应是2个或更多字符,有效字符应匹配模式 -^([a-zA-Z\\ \\,\\.\\-\\']{2,})$
CVV
:卡CVV可以是3-4位数字EXPIRATION_DATE
:任何从当前月份开始的日期。默认情况下,有效的过期日期应采用简短年份格式 -MM/YY
PIN
:可以是4-12位数字
2. 自定义验证
可以在任何元素上添加自定义验证,这些验证将在默认验证通过后进行检查。目前支持以下自定义验证规则
RegexMatchRule
:您可以使用此规则指定任何正则表达式以匹配文本字段的值LengthMatchRule
:您可以使用此规则来设置文本框值的最小和最大允许长度。ElementValueMatchRule
:您可以使用此规则来匹配一个元素的值与另一个值。
以下示例代码展示了自定义验证的使用方法。
/*
Reset Password - A simple example that illustrates custom validations.
The below code shows two input fields with custom validations,
one to enter a password and the second to confirm the same password.
*/
var myRuleset = ValidationSet()
let strongPasswordRule = RegexMatchRule(
regex: "^(?=.*[A-Za-z])(?=.*\\d)[A-Za-z\\d]*$",
error: "At least one letter and one number"
) // This rule enforces a strong password
let lengthRule = LengthMatchRule(
minLength: 8,
maxLength: 16,
error: "Must be between 8 and 16 digits"
) // this rule allows input length between 8 and 16 characters
// for the Password element
myRuleset.add(rule: strongPasswordRule)
myRuleset.add(rule: lengthRule)
let collectElementOptions = CollectElementOptions(required: true)
let passwordInput = CollectElementInput(
inputStyles: styles,
label: "password",
placeholder: "********",
type: .INPUT_FIELD,
validations: myRuleset
)
let password = container?.create(input: passwordInput, options: collectElementOptions)
// For confirm password element - shows error when the passwords don't match
let elementValueMatchRule = ElementValueMatchRule(element: password!, error: "passwords don't match")
let confirmPasswordInput = CollectElementInput(
inputStyles: styles,
label: "Confirm password",
placeholder: "********",
type: .INPUT_FIELD,
validations: ValidationSet(rules: [strongPasswordRule, lengthRule, elementValueMatchRule])
)
let confirmPassword = container?.create(input: confirmPasswordInput, options: collectElementOptions)
// mount elements on screen - errors will be shown if any of the validaitons fail
stackView.addArrangedSubview(password!)
stackView.addArrangedSubview(confirmPassword!)
在收集元素上监听事件
通过监听事件与skyflow元素/iframe进行通信。
element!.on(eventName: Skyflow.EventName) { _ in
// handle function
}
Skyflow.EventName
中有4个事件。
CHANGE
当元素的值发生变化时,将触发更改事件。READY
当元素完全渲染时,将触发就绪事件。FOCUS
当元素获得焦点时,将触发焦点事件。BLUR
当元素失去焦点时,将触发失焦事件。处理器(state: [String: Any]) -> Void
是您提供的回调函数,当事件被触发时,将使用以下所示的状态对象。
let state = [
"elementType": Skyflow.ElementType,
"isEmpty": Bool ,
"isFocused": Bool,
"isValid": Bool,
"value": String
]
注意:
当env
是DEV
时,SkyflowElements的值将仅返回到元素状态对象中,否则为空字符串,即空字符串,但对于除AMEX以外的所有卡片类型,当env
是PROD
时,它将返回前八个数字,对于AMEX它将返回前六个数字,其余数字以掩码格式显示。
使用监听器的示例代码片段
// create skyflow client with loglevel:"DEBUG"
let config = Skyflow.Configuration(
vaultID: VAULT_ID,
vaultURL: VAULT_URL,
tokenProvider: demoTokenProvider,
options: Skyflow.Options(logLevel: Skyflow.LogLevel.DEBUG)
)
let skyflowClient = Skyflow.initialize(config)
let container = skyflowClient.container(type: Skyflow.ContainerType.COLLECT)
// Create a CollectElementInput
let cardNumberInput = Skyflow.CollectElementInput(
table: "cards",
column: "cardNumber",
type: Skyflow.ElementType.CARD_NUMBER,
)
let cardHolderNameInput = Skyflow.CollectElementInput(
table: "cards",
column: "cardHolderName",
type: Skyflow.ElementType.CARDHOLDER_NAME,
)
let cardNumber = container?.create(input: cardNumberInput)
let cardHolderName = container?.create(input: cardHolderNameInput)
// subscribing to CHANGE event, which gets triggered when element changes
cardNumber.on(eventName: Skyflow.EventName.CHANGE) { state in
// Your implementation when Change event occurs
print(state)
}
cardHolderName.on(eventName: Skyflow.EventName.CHANGE) { state in
// Your implementation when Change event occurs
print(state)
}
env
是DEV
时的示例元素状态对象
当[
"elementType": Skyflow.ElementType.CARD_NUMBER,
"isEmpty": false,
"isFocused": true,
"isValid": true,
"value": "4111111111111111"
]
[
"elementType": Skyflow.ElementType.CARDHOLDER_NAME,
"isEmpty": false,
"isFocused": true,
"isValid": true,
"value": "John"
]
PROD
时的示例元素状态对象
当环境为 [
"elementType": Skyflow.ElementType.CARD_NUMBER,
"isEmpty": false,
"isFocused": true,
"isValid": true,
"value": "41111111XXXXXXXX"
]
[
"elementType": Skyflow.ElementType.CARDHOLDER_NAME,
"isEmpty": false,
"isFocused": true,
"isValid": true,
"value": ""
]
收集元素的用户界面错误
帮助在 Skyflow Elements 上通过元素上的 setError
和 resetError
方法显示自定义错误消息。
setError(error: String)
方法用于设置元素的错误文本,当此方法被触发时,元素上当前的所有错误都将被提供的自定义错误消息覆盖。此错误将显示在元素上,直到在同一元素上触发 resetError()
。
resetError()
方法用于清除使用 setError
设置的自定义错误消息。
setError 和 resetError 的示例代码片段
// Create skyflow client with loglevel:"DEBUG"
let config = Skyflow.Configuration(
vaultID: VAULT_ID,
vaultURL: VAULT_URL,
tokenProvider: demoTokenProvider,
options: Skyflow.Options(logLevel: Skyflow.LogLevel.DEBUG)
)
let skyflowClient = Skyflow.initialize(config)
let container = skyflowClient.container(type: Skyflow.ContainerType.COLLECT)
// Create a CollectElementInput
let cardNumberInput = Skyflow.CollectElementInput(
table: "cards",
column: "cardNumber",
type: Skyflow.ElementType.CARD_NUMBER
)
let cardNumber = container.create(input: cardNumberInput)
// Set custom error
cardNumber.setError("custom error")
// Reset custom error
cardNumber.resetError()
仅 (DEV ENV) 设置和清除收集元素的值
setValue(value: String)
方法用于设置元素的值。此方法将覆盖元素中先前存在的任何值。
clearValue()
方法用于重置元素的值。
注意:
这些方法仅适用于开发环境进行测试/开发,绝不能在生产环境中使用。
setValue 和 clearValue 的示例代码片段
// Create skyflow client with env DEV
let config = Skyflow.Configuration(
vaultID: VAULT_ID,
vaultURL: VAULT_URL,
tokenProvider: demoTokenProvider,
options: Skyflow.Options(env: Skyflow.Env.DEV)
)
let skyflowClient = Skyflow.initialize(config)
let container = skyflowClient.container(type: Skyflow.ContainerType.COLLECT)
// Create a CollectElementInput
let cardNumberInput = Skyflow.CollectElementInput(
table: "cards",
column: "cardNumber",
type: Skyflow.ElementType.CARD_NUMBER
)
let cardNumber = container.create(input: cardNumberInput)
// Set a value programatically
cardNumber.setValue("4111111111111111")
// Clear the value
cardNumber.clearValue()
在客户端安全地揭露数据
- 从保险库检索数据
- 使用 Skyflow Elements 揭露数据
- Reveal Elements 的 UI 错误
- 为 Reveal Elements 设置令牌
- 为 Reveal Elements 设置和清除 altText
从保险库检索数据
对于非 PCI 用例,可以使用 SkyflowID 或令牌从保险库检索数据并揭示到移动设备,具体方式如下所述
-
要使用令牌检索记录数据,请使用 使用 Skyflow 令牌
detokenize(records)
方法。记录参数接受一个包含要获取的record
值的令牌的字典对象注意:默认情况下[ "records": [ [ "token": String, "redaction": Skyflow.RedactionType // Optional. Redaction to apply for retrieved data. ] ] ]
redaction
为 RedactionType.PLAIN_TEXT。
以下示例代码调用 detokenize 调用来揭示令牌的掩码值
let getCallback = GetCallback() // Custom callback - implementation of Skyflow.Callback
let records = [
"records": [
[
"token": "45012507-f72b-4f5c-9bf9-86b133bae719",
],
[
"token": "1r434532-6f76-4319-bdd3-96281e051051",
"redaction": Skyflow.RedactionType.MASKED
]
]
] as [String: Any]
skyflowClient.detokenize(records: records, callback: getCallback)
示例响应
{
"records": [
{
"token": "131e70dc-6f76-4319-bdd3-96281e051051",
"value": "1990-01-01"
},
{
"token": "1r434532-6f76-4319-bdd3-96281e051051",
"value": "xxxxxxer",
}
]
}
-
要使用 SkyflowID 进行检索,请使用 使用 Skyflow ID
getById(records)
方法。records 参数接受一个包含要获取的records
的字典对象,如下所示。[ "records": [ [ "ids": ArrayList<String>(), // Array of SkyflowID's of the records to be fetched "table": String, // name of table holding the above skyflow_id's "redaction": Skyflow.RedactionType //redaction to be applied to retrieved data ] ] ]
红色编辑类型
Skyflow.RedactionTypes 中有 4 个接受的值
PLAIN_TEXT
MASKED
REDACTED
DEFAULT
getById 调用示例
let getCallback = GetCallback() // Custom callback - implementation of Skyflow.Callback
let skyflowIDs = ["f8d8a622-b557-4c6b-a12c-c5ebe0b0bfd9", "da26de53-95d5-4bdb-99db-8d8c66a35ff9"]
let record = ["ids": skyflowIDs, "table": "cards", "redaction": Skyflow.RedactionType.PLAIN_TEXT] as [String : Any]
let invalidID = ["invalid skyflow ID"]
let badRecord = ["ids": invalidID, "table": "cards", "redaction": Skyflow.RedactionType.PLAIN_TEXT] as [String : Any]
let records = ["records": [record, badRecord]]
skyflowClient.getById(records: records, callback: getCallback)
示例响应
{
"records": [ {
"fields": {
"card_number": "4111111111111111",
"cvv": "127",
"expiry_date": "11/35",
"fullname": "myname",
"skyflow_id": "f8d8a622-b557-4c6b-a12c-c5ebe0b0bfd9"
},
"table": "cards"
}, {
"fields": {
"card_number": "4111111111111111",
"cvv": "317",
"expiry_date": "10/23",
"fullname": "sam",
"skyflow_id": "da26de53-95d5-4bdb-99db-8d8c66a35ff9"
},
"table": "cards"
}],
"errors": [ {
"error": {
"code": "404",
"description": "No Records Found"
},
"skyflow_ids": ["invalid skyflow id"]
}]
}
使用 Skyflow 元素显示数据
Skyflow 元素可用于在应用程序中安全地显示数据,而不会使您的前端暴露于敏感数据。这对于像卡片发行这类用例来说很棒,在这种情况下,您可能希望在不增加 PCI 网络安全范围的情况下向用户显示卡号。
步骤 1:创建一个容器
首先,使用如下所示的方法 skyflowClient.container(Skyflow.ContainerType.REVEAL)
创建一个容器。
let container = skyflowClient.container(type: Skyflow.ContainerType.REVEAL)
第2步:创建Reveal元素
要创建Reveal元素,我们首先需要构造一个Skyflow.RevealElementInput对象,如下所示
let revealElementInput = Skyflow.RevealElementInput(
token: String, // optional, token of the data being revealed
inputStyles: Skyflow.Styles(), // optional, styles to be applied to the element
labelStyles: Skyflow.Styles(), // optional, styles to be applied to the label of the reveal element
errorTextStyles: Skyflow.Styles(), // optional styles that will be applied to the errorText of the reveal element
label: "cardNumber", // optional, label for the element,
altText: "XXXX XXXX XXXX XXXX", // optional, string that is shown before reveal, will show token if it is not provided
redaction: Skyflow.RedactionType, // optional. Redaction to apply for retrieved data. E.g. RedactionType.MASKED
)
注意
:
token
是可选的,除非在invokeConnection()中使用redaction
默认为RedactionType.PLAIN_TEXT
。
inputStyles
参数接受一个样式对象,如在上一节中描述的数据收集时使用的样式,但对于Reveal元素,只有基本状态可用。
labelStyles
和errorTextStyles
字段接受如上一节中描述的Skyflow.Styles
对象,但对于Reveal元素,只有基本状态可用。
inputStyles
、labelStyles
和errorTextStyles
参数接受如上一节中描述的数据收集时使用的样式对象,但对于Reveal元素,只有一个变体可用,即基本。
inputStyles对象的一个示例
let inputStyles = Skyflow.Styles(base: Skyflow.Style(borderColor: UIColor.green))
labelStyles对象的一个示例
let labelStyles = Skyflow.Styles(base: Skyflow.Style(font: UIFont (name: "GILLSANSCE-ROMAN", size: 12))))
errorTextStyles对象的一个示例
let labelStyles = Skyflow.Styles(base: Skyflow.Style(textColor: UIColor.red))
除了RevealElementInput
之外,你还可以在RevealElementOptions
对象中定义其他选项,如下所述
Skyflow.RevealElementOptions(
format: String, // Format for the element.
translation: [Character: String] // Indicates the allowed data type value for format
)
format
:表示元素应如何显示值的字符串值,包括映射到键translation
的占位符字符。如果未指定translation
,则认为format
值是一个字符串字面量。translation
:键值对的字典,其中键是format
中出现的字符,值是对于该字符可接受的输入的regex模式。每个键只能出现一次。默认为[ "X": "[0-9]"]
。
Reveal元素选项示例
示例1
Skyflow.RevealElementOptions(
format: "(XXX) XXX-XXXX",
translation: [ "X": "[0-9]"]
)
保险库中的值:“1234121234”
元素中显示的值:“(123) 412-1234”
示例 2
Skyflow.RevealElementOptions(
format: "XXXX-XXXXXX-XXXXX",
translation: [ "X": "[0-9]"]
)
保险库中的值:“374200000000004”
元素中显示的值:“3742-000000-00004”
一旦你定义了一个Skyflow.RevealElementInput
对象和一个Skyflow.RevealElementOptions
,你就可以使用容器的create
方法创建元素,如下所示
let element = container.create(input: revealElementInput, options: Skyflow.RevealElementOptions(format: "XXXX-XXXXXX-XXXXX",
translation: ["X": "[0-9]"]
))
第3步:将元素挂载到屏幕
用于揭示数据的元素以与用于收集数据的元素相同的方式挂载到屏幕上。参阅上面的步骤3。
第4步:显示数据
当敏感数据准备检索并显示时,如下所示,在容器上调用reveal()
方法
let revealCallback = RevealCallback() // Custom callback - implementation of Skyflow.Callback
container.reveal(callback: revealCallback)
显示元素UI错误
帮助在 Skyflow Elements 上通过元素上的 setError
和 resetError
方法显示自定义错误消息。
setError(error: String)
方法用于设置元素的错误文本,当此方法被触发时,元素上当前的所有错误都将被提供的自定义错误消息覆盖。此错误将显示在元素上,直到在同一元素上触发 resetError()
。
resetError()
方法用于清除使用 setError
设置的自定义错误消息。
为显示元素设置令牌
setToken(value: String)
方法可以用来设置显示元素的令牌。如果没有设置altText,则设置的令牌也会在UI上显示。如果设置了altText,则UI上将不会发生变化,但元素的令牌将在内部更新。
设置和清除显示元素的altText
setAltText(value: String)
方法可以用来设置显示元素的altText。这将导致无论是否显示令牌或值,altText都会在UI中显示。
clearAltText()
方法可以用来清除altText。这将导致元素显示令牌或元素的实际值。如果元素没有令牌,则元素将显示为空。
使用Skyflow Elements展示数据
使用Skyflow Elements展示数据的端到端示例
// Initialize skyflow configuration
let config = Skyflow.Configuration(vaultID: <VAULT_ID>, vaultURL: <VAULT_URL>, tokenProvider: demoTokenProvider)
// Initialize skyflow client
let skyflowClient = Skyflow.initialize(config)
// Create a Reveal Container
let container = skyflowClient.container(type: Skyflow.ContainerType.REVEAL)
// Create Skyflow.Styles with individual Skyflow.Style variants
let baseStyle = Skyflow.Style(borderColor: UIColor.blue)
let baseTextStyle = Skyflow.Style(textColor: UIColor.BLACK)
let inputStyles = Skyflow.Styles(base: baseStyle)
let labelStyles = Skyflow.Styles(base: baseTextStyle)
let errorTextStyles = Skyflow.Styles(base: baseTextStyle)
// Create Reveal Elements
let cardNumberInput = Skyflow.RevealElementInput(
token: "b63ec4e0-bbad-4e43-96e6-6bd50f483f75",
inputStyles: inputStyles,
labelStyles: labelStyles,
errorTextStyles: errorTextStyles,
label: "cardnumber",
altText: "XXXX XXXX XXXX XXXX",
redaction: SKyflow.RedactionType.MASKED
)
let cardNumberElement = container?.create(input: cardNumberInput)
let cvvInput = Skyflow.RevealElementInput(
token: "89024714-6a26-4256-b9d4-55ad69aa4047",
inputStyles: inputStyles,
labelStyles: labelStyles,
errorTextStyles: errorTextStyles,
label: "cvv",
altText: "XXX"
)
let cvvElement = container?.create(input: cvvInput)
let expiryDateInput = Skyflow.RevealElementInput(
token: "a4b24714-6a26-4256-b9d4-55ad69aa4047",
inputStyles: inputStyles,
labelStyles: labelStyles,
errorTextStyles: errorTextStyles,
label: "expiryDate",
altText: "MM/YYYY"
)
let expiryDateElement = container?.create(input: expiryDateInput)
// Can interact with these objects as a normal UIView Object and add to View
// set error to the element
cvvElement!.setError("custom error")
// reset error to the element
cvvElement!.resetError()
// Implement a custom Skyflow.Callback to be called on Reveal success/failure
public class RevealCallback: Skyflow.Callback {
public func onSuccess(_ responseBody: Any) {
print(responseBody)
}
public func onFailure(_ error: Any) {
print(error)
}
}
// Initialize custom Skyflow.Callback
let revealCallback = RevealCallback()
// Call reveal method on RevealContainer
container?.reveal(callback: revealCallback)
以下响应显示,分配给展示元素的某些令牌成功展示了,而其他令牌失败且未展示。
示例响应
{
"success": [ {
"token": "b63ec4e0-bbad-4e43-96e6-6bd50f483f75"
},
{
"token": "89024714-6a26-4256-b9d4-55ad69aa4047"
}],
"errors": [ {
"id": "a4b24714-6a26-4256-b9d4-55ad69aa4047",
"error": {
"code": 404,
"description": "Tokens not found for a4b24714-6a26-4256-b9d4-55ad69aa4047"
}
}]
}
报告漏洞
如果您在这个项目中发现了一个潜在的安全问题,请通过电子邮件与我们联系[email protected]。请不要创建公开的GitHub问题和拉取请求,因为恶意行为者可能会查看它们。