Skyflow 1.22.1

Skyflow 1.22.1

Skyflow 维护。



Skyflow 1.22.1

  • Skyflow

skyflow-iOS


Skyflow 的 iOS SDK 可以用于在移动设备上安全收集、标记和显示敏感数据,同时不将前端基础设施暴露给敏感数据。

CI GitHub release License

目录

安装

要求

  • iOS 13.0.0 及以上版本

配置


SPM (Swift Package Manager)

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

客户端安全收集数据

将数据插入宝库

要将数据插入您的宝库,请使用 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
)

tablecolumn 字段指示元素对应的保险库中的表格和列。 注意:

  • 使用点分隔的字符串来指定嵌套在 JSON 字段内的列(例如:address.street.line1
  • 在调用 invokeConnection() 时,tablecolumn 是可选的

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
)

labelStyleserrorTextStyles 字段接受上述 Skyflow.Styles 对象,分别应用于 labelerrorText 文本视图

适用于 labelStyles 的状态是 basefocus

适用于 errorTextStyles 的状态仅是 base 状态,当收集元素出现错误时显示

Skyflow.Style 对象中尊重用于 labelerrorText 文本视图的参数是

  • 填充
  • 字体
  • 文本颜色
  • 文本对齐

Skyflow.Style 对象中的其他参数对于 labelerrorText 文本视图将被忽略

最后,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 值是一个字符串字面量。
  • translation:一个键/值对的字典,其中键是在 format 中出现的字符,相应值是该字符可接受的输入的正则表达式。每个键只能出现一次。仅适用于 INPUT_FIELD 元素。

元素类型可接受值

元素类型 formattranslation 示例
EXPIRATION_DATE
  • 格式
    • mm/yy(默认值)
    • mm/yyyy
    • yy/mm
    • yyyy/mm
  • 12/27
  • 12/2027
  • 27/12
  • 2027/12
EXPIRATION_YEAR
  • 格式
    • yyyy(默认值)
    • yy
  • 27
  • 2027
CARD_NUMBER
  • 格式
    • XXXX XXXX XXXX XXXX(默认值)
    • XXXX-XXXX-XXXX-XXXX
  • 1234 5678 9012 3456
  • 1234-5678-9012-3456
INPUT_FIELD
  • 一个与所需输出匹配的字符串,其中包含您选择的占位符字符。
  • translation:键/值对的字典。默认为 [ "X": "[0-9]"]
具有 format+91 XXXX-XX-XXXXtranslation[ "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.CollectElementInputSkyflow.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
]

注意:envDEV时,SkyflowElements的值将仅返回到元素状态对象中,否则为空字符串,即空字符串,但对于除AMEX以外的所有卡片类型,当envPROD时,它将返回前八个数字,对于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)
}
envDEV时的示例元素状态对象
[
    "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 上通过元素上的 setErrorresetError 方法显示自定义错误消息。

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()

在客户端安全地揭露数据

从保险库检索数据

对于非 PCI 用例,可以使用 SkyflowID 或令牌从保险库检索数据并揭示到移动设备,具体方式如下所述

  • 使用 Skyflow 令牌

    要使用令牌检索记录数据,请使用 detokenize(records) 方法。记录参数接受一个包含要获取的 record 值的令牌的字典对象
    [
      "records": [
        [
          "token": String,
          "redaction": Skyflow.RedactionType // Optional. Redaction to apply for retrieved data.     
        ]
      ]
    ]
    注意:默认情况下 redactionRedactionType.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",
    }
   ]
}
  • 使用 Skyflow ID

    要使用 SkyflowID 进行检索,请使用 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
)

注意:

inputStyles参数接受一个样式对象,如在上一节中描述的数据收集时使用的样式,但对于Reveal元素,只有基本状态可用。

labelStyleserrorTextStyles字段接受如上一节中描述的Skyflow.Styles对象,但对于Reveal元素,只有基本状态可用。

inputStyleslabelStyleserrorTextStyles参数接受如上一节中描述的数据收集时使用的样式对象,但对于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 上通过元素上的 setErrorresetError 方法显示自定义错误消息。

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问题和拉取请求,因为恶意行为者可能会查看它们。