Collect and Send Data
Collect and Send Data
With the VGS Collect SDK, you can tokenize data via the Vault API or securely send it to your server using the VGS Proxy.
Send Data to Your Server via VGS Proxy
Using the sendData(_:)
method, sensitive data from VGSTextField
will be collected, stored in your organization's Vault, and sent to the Upstream URL specified in the Inbound Route.
/**
Send data from VGSTextFields to your organization vault.
- Parameters:
- path: Inbound rout path for your organization vault.
- method: HTTPMethod, default is `.post`.
- routeId: id of VGS Proxy Route, default is `nil`.
- extraData: Any data you want to send together with data from VGSTextFields , default is `nil`.
- requestOptions: `VGSCollectRequestOptions` object, holds additional request options. Default options are `.nestedJSON`.
- completion: response completion block, returns `VGSResponse`.
- Note:
Errors can be returned in the `NSURLErrorDomain` and `VGSCollectSDKErrorDomain`.
*/
public func sendData(path: String,
method: HTTPMethod = .post,
routeId: String? = nil,
extraData: [String: Any]? = nil,
requestOptions: VGSCollectRequestOptions = VGSCollectRequestOptions(),
completion block: @escaping (VGSResponse) -> Void)
/**
Asynchronously send data from VGSTextFields to your organization vault.
*/
public func sendData(path: String,
method: HTTPMethod = .post,
routeId: String? = nil,
extraData: [String: Any]? = nil,
requestOptions: VGSCollectRequestOptions = VGSCollectRequestOptions()) async throws -> VGSResponse
/**
Send data from VGSTextFields to your organization vault using the Combine framework.
*/
public func sendDataPublisher(path: String,
method: HTTPMethod = .post,
routeId: String? = nil,
extraData: [String: Any]? = nil,
requestOptions: VGSCollectRequestOptions = VGSCollectRequestOptions()) -> Future<VGSResponse, Never>
The send data request returns VGSResponse.failure(_:)
in the following cases:
• The response status code is invalid (i.e., not in the range [200..<300]).
• The request is not possible due to iOS system conditions (e.g., no internet connection).
• The data being sent is invalid according to VGSConfiguration
.\
Errors can be returned in the NSURLErrorDomain
and VGSCollectSDKErrorDomain
.
For more details, check the SDK Reference Docs.
• Data will be collected from all text fields that registered to current
VGSCollect
instance and send to your organization vault id. • By defaultaliases
are not a part of response data forsendData(_:)
request. It's your responsibility to configure a response for the client after the data goes through the Inbound Proxy to your backend. However, if you testsendData(_:)
request with our echo server, you will get a response with the same body as in the request, where the raw data will be redacted to aliases.
Code example
Send data to your organization vault:
func sendData(_ sender: UIButton) {
/// extra information can be sent together with all sensitive data from VGSTextFields
var extraData = [String: Any]()
extraData["cardHolderName"] = "Joe Business"
/// send data to your Vault
vgsCollect.sendData(path: "/post", method: .post, extraData: extraData) { [weak self](../../response) in
switch response {
case .success(let code, let data, let response):
// parse data
case .failure(let code, let data, let response, let error):
// handle failed request
switch code {
// handle error codes
}
}
}
}
Asynchronously send data from VGSTextFields to your organization vault:
func sendData() async {
do {
let response = try await vgsCollect.sendData(path: "/post", method: .post)
switch respose {
case .success(let code, let data, let response):
// parse data
case .failure(let code, let data, let response, let error):
// handle failed request
switch code {
// handle error codes
}
}
} catch {
// handle error
}
}
Send data from VGSTextFields to your organization vault using the Combine framework:
vgsCollect.sendDataPublisher(path: "/post", method: .post)
.sink { completion in
switch completion {
case .finished:
// handle finished
case .failure(let error):
// handle error
}
} receiveValue: { response in
// parse data
}
.store(in: &cancellables)
• If you need to send files data, check VGSFilePickerController.
Sending custom data
To send additional custom data, include it in the extraData parameter of the sendData(_:
)` request.
Code example
// ...
/// extra information can be sent together with all sensitive data from VGSTextFields
var extraData = [String: Any]()
extraData["cardHolderName"] = "Joe Business"
/// send data to your Vault
vgsCollect.sendData(path: "/post", extraData: extraData) { [weak self](../../response) in
switch response {
// ...
}
}
Setting Custom API Headers
To include custom headers in your sendData(_:)
request, assign them to:
var customHeaders: [String: String]?
Code example
// ...
/// set custom headers
vgsCollect.customHeaders = [
"custom header": "custom data"
]
VGSResponse
Represents the result of a VGS SDK request.
Declaration
@frozen enum VGSResponse
/// Success response case
case success(_ code:Int, _ data:Data?, _ response: URLResponse?)
/// Failed response case
case failure(_ code:Int, _ data:Data?, _ response: URLResponse?, _ error:Error?)
See SDK Reference Docs for more information.
Advanced Settings
Setting Custom JSON Structure
Use dot (.) notation in the VGSConfiguration.fieldName
to define nested JSON structures. Each dot (.) in a fiealdName will create a new level of nesting.
Code example
/// Define field names
let userId = "userId"
let cardNumberFieldKey = "card_data.card_number"
let cardCVCFieldKey = "card_data.cvc"
/// Example of transformed JSON structure on sendData(_:)
{
"userId": "id12345",
“card_data: {
“card_number”: 411111111111111”,
“cvc”: “123”
}”
}
• If there are two fieldNames with equal names - they will be overwritten. • If object structure and field name in extraData are same as defined in VGSConfiguration fieldName, value in extraData will be overwritten by data collected from VGSCollect elements with same name on sendData(_:).
Dot (.) notation does not apply to extraData keys. You must format extraData as desired before passing it to sendData(_:)
.
Nested JSON with array
Use [index] notation in fieldName888 to represent arrays. Only one key with an array index is supported per level. Multi-dimensional arrays are not supported.
Field Mapping Policies:
nestedJSON - map fieldnames with dot notation to nested JSON. Arrays are not supported. Is default policy.
flatJSON - map fieldNames to JSON. Flat JSON format uses fieldname as a single
key
and does not produce any nested JSON or array.nestedJSONWithArrayOverwrite - map fieldnames with dot notation to nested JSON and arrays. Replace
extraData
the array with the VGS Collect array.nestedJSONWithArrayMerge - map fieldnames with dot notation to nested JSON and arrays. Merge VGS Collect and
extraData
array.
Specify fieldName
mapping policy with VGSCollectRequestOptions
on sendData(_:)
.
/// Define field names
let cardNumberFieldKey = "card_data[0].number"
let cardCVCFieldKey = "card_data[1].cvc"
let vgsCollect = VGSCollect(id: "<VAULT_ID>", environment: .sandbox, dataRegion: "eu-1")
var options = VGSCollectRequestOptions()
options.fieldNameMappingPolicy = .nestedJSONArrayOvewrite
// Or
options.fieldNameMappingPolicy = .nestedJSONArrayMerge
vgsCollect.sendData(path: "/post", requestOptions: options) { requestResult in }
Example of transformed JSON structure on sendData(_:)
{
"card_data" :
[
{ "number" : "411111111111111"},
{"cvc": "123"}
]
}
Check more examples how to customize JSON structure.
If you need to change the output value format, you can read more about available functionality in VGSConfiguration section.
Tokenize data
VGS offers two Vault API versions for data tokenization:
• Vault API v1: Uses tokenizeData(_:)
. Learn more.
• Vault API v2: Uses createAliases(_:)
and requires Authorization. Learn more.
Each API version requires an appropriate Upstream URL specified in your Vault's Route configuration.\
• Vault API v2 is our newest Vault API and is recommended for integrations. • If you already use API v1 you can find migration guide to API v2 below.
Makes a tokenization request to Vault API v2 with data from VGSTextFields:
public func createAliases(routeId: String? = nil, completion block: @escaping (VGSTokenizationResponse) -> Void)
Asynchronously makes a tokenization request with data from VGSTextFields:
public func createAliases(routeId: String? = nil) async throws -> VGSTokenizationResponse
Makes a tokenization request with data from VGSTextFields using the Combine framework:
public func createAliasesDataPublisher(routeId: String? = nil) -> Future<VGSTokenizationResponse, Never>
VGSTokenizationResponse
An object you use to handle SDK tokenization request completion.
Declaration
@frozen public enum VGSTokenizationResponse {
/**
Success response case
- Parameters:
- code: response status code.
- body: response **JsonData** object.
- response: URLResponse object represents a URL load response.
*/
case success(_ code: Int, _ body: JsonData?, _ response: URLResponse?)
/**
Failed response case
- Parameters:
- code: response status code.
- data: response **Data** object.
- response: `URLResponse` object represents a URL load response.
- error: `Error` object.
*/
case failure(_ code: Int, _ data: Data?, _ response: URLResponse?, _ error: Error?)
}
Code example
Send tokenization request with data from VGSTextFields to your organization vault:
You should set authToken into VGSCollect customHeaders before calling the createAliases(:) function:
vgsCollect.customHeaders = ["Authorization": "Bearer (authToken)"]
vgsCollect.createAliases{ [weak self](response) in
switch response {
case .success(_, let resultBody, _):
let response = (String(data: try! JSONSerialization.data(withJSONObject: resultBody!, options: .prettyPrinted), encoding: .utf8)!)
print(response)
return
case .failure(let code, _, _, let error):
switch code {
case 400..<499:
// Wrong request. This also can happend when your Routs not setup yet or your <vaultId> is wrong
case VGSErrorType.inputDataIsNotValid.rawValue:
if let error = error as? VGSError {
self?.consoleLabel.text = "Error: Input data is not valid. Details:
(error)"
}
default:
self?.consoleLabel.text = "Error: Something went wrong. Code: (code)"
}
print("Submit request error: (code), (String(describing: error))")
return
}
}
Send tokenization request with data from VGSTextFields to your organization vault using the async/await:
do {
let response = try await vgsCollect.createAliases()
switch respose {
case .success(let code, let data, let response):
// parse data
case .failure(let code, let data, let response, let error):
// handle failed request
switch code {
// handle error codes
}
}
} catch {
// handle error
}
Send toa kenization request with data from VGSTextFields to your organization's vault using the Combine framework:
vgsCollect.createAliasesDataPublisher()
.sink { completion in
switch completion {
case .finished:
// handle finished
case .failure(let error):
// handle error
}
} receiveValue: { response in
// parse data
}
.store(in: &cancellables)
Data will be collected from all
VGSTextFields
registered to currentVGSCollect
instance. - Only data fromVGSTextFields
configured with one of available tokenization configurations will be tokenized and stored in your's organization vault. - Data fromVGSTextFields
configured with other configuration types will be returned as raw value along with tokenized data inVGSTokenizationResponse
. - Data from fields with type.cvc
and.cardNumber
will not be included toVGSTokenizationResponse
if tokenization configurations not set for appropriate fields.
RouteId
The route identifier specifies how data should be routed in your organization's vault. You should follow the next rules when setting routeId
:
You should set specific
routeId
when you use multiple routes in your organization's vault.RouteId should be a valid UUID string; you will receive an error in
VGSTokenizationResponse
in case if it's not valid.If you have only one Inbound Route in your organization's vault, you can leave
routeId
as nil.
Migrating from Vault API v1 to v2
Migration from Vault API v1 to API v2 will require you to implement the next steps:
Update your organization's Vault Route with a new Upstream Host: use
https://<your-vault-id>.sandbox.vault-api.verygoodvault.com
for sandbox orhttps://<your-vault-id>.live.vault-api.verygoodvault.com
for a live environment.Receive Tokenization authToken from your backend and set it in VGSCollect headers:
vgsCollect.customHeaders = ["Authorization": "Bearer \(authToken)"]
.Use
-createAliases(:)
function instead of-tokenize(:)
creating aliases.
For more details about available attributes and functionality, check VGSCollectSDK Reference docs
Last updated