Visa Alias Directory Service

Simplify the push payment experience. Link and resolve an Alias to a payment credential.

How to Use Batch Processing

Overview

Alias Directory Service allows participants to submit requests for bulk operations (i.e. Create Alias) using its Batch Processing Service. Using this service, participants can implement use cases such as directory migration, mass Alias creation during go-live phase, and mass deletion. 

Step 1

Client
Create a one-time encryption key

Step 2

Visa
Return encryption key details

Step 3

Client
Create batch file

Step 4

Client
Submit batch process request

Step 5

Visa
Return a batch process ID

Step 6

Client
Check on the batch process status

Step 7

Client
When status is completed, decode and decompress results file

Available Endpoints

Endpoint

Overview

Details

Generate Key

POST /batchKeys

Create one-time encryption key.

The one-time key provided in the response is composed of three objects:

  1. Key unique ID

  2. AES-GCM encryption key

  3. AES encryption Initialization Vector

A new key must be generated each time the Participant submits a new Batch request. Once the key is used, it will be deactivated.

Create Batch Request

POST /batches

 

Submit a batch request and receive a batch request ID, which can be used to retrieve information about the batch request status.

The operation field indicates which operation will be executed (i.e. CREATE_ALIAS).

The data field contains the data to use for the batch operation (e.g., aliasValue, aliasType, profile, paymentCredentials).

The data field value must be a compressed, encrypted and base64 encoded file.

Alias Directory will process the batch request offline. The status of the batch operation can be retrieved with Get Batch Status.

Get Batch Status

GET /batches/{batchId}

Retrieve the status of a specific batch request.

This endpoint provides the status of a batch request and indicates whether the batch request was completed.

Get Batch Results

GET /batches/{batchId}/result

Retrieve an output file with the results of the batch request.

This endpoint retrieves a file using the batch ID. The file will indicate the result of each request in the batch request.

The data field value will be returned as a compressed and base64 encoded file.

Note: For more details about individual endpoints and its parameters, refer to the API Specifications section.

Available Batch Operations

Operation

Description

CREATE_ALIAS

Create multiple Aliases within Alias Directory. The fields, field format, business validations, and constraints for this batch operation are identical to the Create Alias API.

DELETE_ALIAS

Delete multiple Aliases using the Alias IDs within Alias Directory. Business validations and constraints for this batch operation are identical to the Delete Alias API.

UPDATE_BANK_PAYMENT_CREDENTIAL

Specific fields for multiple Payment Credentials. The following fields can be updated:

  • Bank Code

  • Bank Code Type

  • Branch Code

  • Bank Name

Creating a Batch Processing Input File

Participants must create Batch Processing input files in order to submit Batch processing requests. These files will contain the necessary information for Alias Directory platform to complete the request.

Below are the instructions to create a Batch Processing input file with the correct format:

1. Generate One Time Key

Use the Generate Key API to request a new AES one-time key pair.

Upon successful call, the API will respond with the below fields, which will be used to encrypt the data for the batch request.

{ 

  "keyId": "6e23fd10-2a5e-4447-9f1e-e135d6c2afd2", 

  "encryptionKey": "96ae5a8917f1750769874d296c9b4d0eb6f5a46445ae62e0a44d9ee5054d4c51", 

  "encryptionInitVector": "351a6cb61fd2d666ab92e6ea" 

}

		

       

2. Generate Plain Data

The source data is a plain file formatted in semicolon separated values. Each row within the file is meant to be a single request for the API selected and must follow the structure:

<recordId>;<requestBody>;<pathParams>

where:

  • recordId. Required. A 36 character long unique identifier for this particular request
  • requestBody. Optional. JSON formatted string with the data and format required for the operation (CREATE_ALIAS, UPDATE_BANK_PAYMENT_CREDENTIAL).
  • pathParams. Optional. JSON formatted string with the parameters required for the operation  (DELETE_ALIAS).

 

Example #1 - Creating Aliases

The following example contains information to create 2 aliases. Please note that the Create Alias operation has a request body but no path parameters.

8baf6fa6-1a4d-44d8-8ad3-049cb06e06f0;{"aliasType": "PHONE","aliasValue": "608-504-9509","externalId": "42b8d475-6797-40e8-ba13-c7baaea4252e","profile": {"firstName": "Deloise","middleName": "Middle","lastName": "Hahn","preferredName": "Deloise Middle Hahn","dateOfBirth": "1993-05-15","contactInfo": [{"value": "1231234321","type": "PHONE"}]},"consent": {"presenter": "Client A","intermediaries": ["Client B"],"validFromDateTime": "2021-05-15T10:00:00Z","expiryDateTime": "2022-05-15T10:00:00Z","version": "1.0"},"paymentCredentials": [{"type": "BANK","preferredFor": [{"type": "RECEIVE","date": "1980-02-01T20:00:00Z"}],"externalId": "2368c141-ee10-405c-88d4-3cb09b8de607","bankName": "Bank A","accountName": "Test A","accountNumber": "4111111145551140","accountNumberType": "DEFAULT","accountType": "CHECKING","countryCode": "USA","BIC": "12345678","bankCode": "173","bankCodeType": "ABA","branchCode": "123456","currencyCode": "USD"}]}; 
ca3b332b-0fc7-4ac0-99f4-86afe9d5cd87;{"aliasType": "PHONE","aliasValue": "1-950-769-0773","externalId": "26216ee1-2ad8-46f2-a8a8-254101113fe4","profile": {"firstName": "Hollis","middleName": "Middle","lastName": "Tremblay","preferredName": "Hollis Middle Tremblay","dateOfBirth": "1993-05-15","contactInfo": [{"value": "1231234321","type": "PHONE"}]},"consent": {"presenter": "Client A","intermediaries": ["Client B"],"validFromDateTime": "2021-05-15T10:00:00Z","expiryDateTime": "2022-05-15T10:00:00Z","version": "1.0"},"paymentCredentials": [{"type": "BANK","preferredFor": [{"type": "RECEIVE","date": "1980-02-01T20:00:00Z"}],"externalId": "41307f76-c8cb-41b6-af51-d30f71203b34","bankName": "Bank A","accountName": "Test B","accountNumber": "4111111145551140","accountNumberType": "DEFAULT","accountType": "CHECKING","countryCode": "USA","BIC": "12345678","bankCode": "173","bankCodeType": "ABA","branchCode": "123456","currencyCode": "USD"}]};
		

       

Example #2 - Deleting Aliases

This next example is to delete 2 aliases. Please note the Delete Alias operation has no request body, but has path parameters.

520cdec6-473b-4052-8d41-278c1d10dba4;;{"id": "12c1f328-6025-47d2-9303-21f5b48591d2"}
5e841c2d-3318-41b6-bc85-ca4069c230e5;;{"id": "be3ec8ac-91a0-478f-9be6-782373d0d052"}
		

       

3. Prepare file to be submitted

Once the plain file has been built, it must be compressed, encrypted and encoded before uploading to the API.

This preparation consists of 3 steps:

  • File compression: First, the plain file must be compressed using ZStandard algorithm.
  • File encryption: Then, the compressed file must be encrypted with AES-GCM encryption, using the one-time key pair obtained from the Generate Key endpoint.
  • File encoding: Finally, the resulting file should be encoded in Base64.

Finally, the encoded file can be submitted as text in the data field in Create Batch request.

Below is an example of achieving this using Java.

Preparing the file using Java

Prerequisites:

  • Java version 8 or newer
  • Library zstd-jni, a java binding for native Zstd library.
  • Library Apache Commons Codec, a library with implementations of commons encoders/decoders.

Both of the libraries are publicly available. If you are using a project management tool (e.g., maven), you can get them by including in the pom.xml file the following dependencies:

<dependency>
    <groupId>commons-codec</groupId>
    <artifactId>commons-codec</artifactId>
    <version>1.15</version>
</dependency>
<dependency>
    <groupId>com.github.luben</groupId>
    <artifactId>zstd-jni</artifactId>
    <version>1.5.4-2</version>
</dependency>
		

       

Key Steps for File Submission

Step 1 - Compress the plain file, a helper method similar to this can be used:

static void compress(Path inputFile, Path outputFile) throws Exception {
    try (ZstdOutputStream zos = new ZstdOutputStream(Files.newOutputStream(outputFile))) {
        Files.copy(inputFile, zos);
    }
}
		

The method just copies the input file to an output file stream, compressing it on the fly. The ZstdOutputStream class is from library zstd-jni, and the Files class is from java.nio package.

Step 2 - For the file encryption task, the following snippet uses classes from javax.crypto and java.security packages to encrypt with specified algorithm and mode:

static void encrypt(Path inputFile, Path outputFile, byte[] key, byte[] iv) throws Exception {
    byte[] inputBytes = Files.readAllBytes(inputFile);

    Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding");
    SecretKeySpec secretKeySpec = new SecretKeySpec(key, "AES");
    AlgorithmParameterSpec algorithmParamSpec = new GCMParameterSpec(iv.length * 8, iv);
    cipher.init(Cipher.ENCRYPT_MODE, secretKeySpec, algorithmParamSpec);
    byte[] encryptedBytes = cipher.doFinal(inputBytes);
    Files.write(outputFile, encryptedBytes);
}
		

       

Step 3 - And for the file encoding, using helper class for Base64 output stream, we can do something similar to the compress step:

static void encode(Path inputFile, Path outputFile) throws Exception {
    try (Base64OutputStream bos = new Base64OutputStream(Files.newOutputStream(outputFile), true, 0, null)) {
        Files.copy(inputFile, bos);
    }
}
		

       

Step 4 - Finally, to put it all together, we can prepare our batch file by combining the 3 methods created above:

public static void main(String[] args) throws Exception {
    Path plain = Paths.get("./0-file.txt");
    Path compressed = Paths.get("./1-file.zstd");
    Path encrypted = Paths.get("./2-file.enc");
    Path encoded = Paths.get("./3-file.b64");

    compress(plain, compressed);
    encrypt(compressed, encrypted, Hex.decodeHex("<encryptionKey>"), Hex.decodeHex("<encriptionInitVector>"));
    encode(encrypted, encoded);
}
		

encriptionKey and encriptionInitVector are the values returned by the Generate Key API.

Please note that the values are returned encoded in hexadecimal format, which needs to be decoded into binary format (Hence the Hex.decodeHex(...) call).

 

After completion of the 3 steps, the content on the last file is the data to submit to the Create Batch Request API call.

Please reach out to your Visa representative for a sample tool to assist with the encryption process.

4. Create Batch Request

Below is a sample payload for the Create Batch Request API. 

{
  "keyId": "6e23fd10-2a5e-4447-9f1e-e135d6c2afd2",
  "data": " uAAFdrWJCFtahR28FM8xW30Uipawio4t7XsNhg7LJG+X6E9ezwxrGh/99DD+8PCdUzynVo7",
  "operation": "CREATE_ALIAS"
}
		

 Where:

  • keyId: Is the id of the previously generated one-time key.
  • data: Is the UTF-8 encoded string generated in previous section .
  • operation: The batch operation. Refer to documentation for more details.

 

Upon successful api call, the response will look similar to:

{
  "id": "<batch process uuid>"
}
		

The returned value is the batchId, the ID of the batch process to be used later to query batch status and download the results file.

Reading Batch Processing Result File

After the batch process request is completed, the results file can be downloaded. This result file contains the status and response for each individual request sent in the batch request input file.

There are 2 endpoints in the Batch API used to:

  1. Obtain the status of a batch request

  2. Download the results

1. Get Batch Status

Use the Get Batch Status API to obtain the status of a given batch request by using the batch id returned in the Create Batch Request API. See below for a sample Get Batch Status response.

{
  "id": "a1863b0f-f5ba-4ecd-bac5-60a671aa755e",
  "operation": "CREATE_ALIAS",
  "status": "COMPLETED",
  "submittedDateTime": "2022-12-14T23:05:06.142178Z",
  "finishedDateTime": "2022-12-14T23:10:05.423006Z"
}
		

       

2. Get Batch Results

{
  "data": "KLUv/WCTAKUIAIaVPyBAjdq/lftDnOGV0msFgeN50xuyqDGTUCfl6Jgty1B6XTcANwA1AGlPV+rho55CzFjTj+J4wolYEMrlHSTN0nBAIA5GwcNgScyVVBg1VfCW6j6UXI8x/GtNTCXGCwaK06DQCU3k/SWMJvILEM1wEkcdf78l5bZOudk1Mj3V3LePm4gsoNARyTcPfxKHse5Opi26XioBnK0Tofd2yWlvE+v5Lz9P3obtTLZXr0tRypy/8qWk6CkLmWOKKaMyidN4LBhHcZ4BojkRBwEAE4TJQWmTUmrlL72kfm81Rm8b5jFzW2WlqkxqGZuyfqp37zX1mrvfNpQqNRsgWAQkJgc9BgAE6AEhn0PxCOgXhBkT30BFAQ=="
}
		

       

3. Decode and Decompress Results File

Reading the results file involves:

  • File decoding: Decode the Base64 content into a binary file.
  • File decompression: Decompress the binary file into the plain results file.

Below is an example on how to do this using Java.

Reading results using Java

Prerequisites: 

  • Java version 8 or newer
  • Library zstd-jni, a java binding for native Zstd library.
  • Library Apache Commons Codec, a library with implementations of commons encoders/decoders.

Both of the libraries are publicly available. If using a project management tool (e.g., maven), these libraries can be obtained by including in the pom.xml file the following dependencies:

<dependency>
    <groupId>commons-codec</groupId>
    <artifactId>commons-codec</artifactId>
    <version>1.15</version>
</dependency>
<dependency>
    <groupId>com.github.luben</groupId>
    <artifactId>zstd-jni</artifactId>
    <version>1.5.4-2</version>
</dependency>
		

       

Key Steps

Step 1 - Decode from Base64 into binary, the following snippet can be used:
static void decode(Path inputFile, Path outputFile) throws Exception {
    try (Base64InputStream bis = new Base64InputStream(Files.newInputStream(inputFile))) {
        Files.copy(bis, outputFile);
    }
}
		

The method copies the input file to an output file stream, decoding it on the fly. The Base64InputStream class is from library Commons Codec, and the Files class is from java.nio package.

 

Step 2 - In a similar fashion, a helper method to decompress the binary file may look like the following:

static void decompress(Path inputFile, Path outputFile) throws Exception {
    try (ZstdInputStream zis = new ZstdInputStream(Files.newInputStream(inputFile))) {
        Files.copy(zis, outputFile, StandardCopyOption.REPLACE_EXISTING);
    }
}
		

       

Please see below a snippet which uses both helper methods mentioned above:

public static void main(String[] args) throws Exception {
    Path encoded = Paths.get("./0-result.b64");
    Path compressed = Paths.get("./1-result.zstd");
    Path plain = Paths.get("./2-result.txt");

    decode(encoded, compressed);
    decompress(compressed, plain);
}
		

       

The final output is a plain text data file with the batch results.

The output file format is similar to the input file:

  • One line per result.
  • Semicolon-separated values.

The format of each line is:

<rowNumber>;<recordId>;<batchItemStatus>;<finishedOk>;<apiResponseStatus>;<apiResponseBody>

Where:

  • rowNumber: Row index in the file, for legibility, 1-based.
  • recordId: Unique record id as given in the input file.
  • batchItemStatus: Status of the batch item. Example: PROCESSED, FAILED.
  • finishedOk: true/false flag indicating that the API call returned ok.
  • apiResponseStatus: Response status of the actual API call. Example: 201.
  • apiResponseBody: Response body of the actual API call. (If API returns body). Or business error message in case the response was not successful (for example, missing mandatory field).

Sample output below:

1;394f96eb-068a-4468-8e21-bc36024428b6;PROCESSED;true;200;{"id":"d3b7daf9-c7b5-4e32-9cd3-2af163b59e9f","externalId":"98d44f7b-d053-4d2b-b23c-a67cd4e040ad","paymentCredentials":[{"type":"CARD","id":"d2c1a76d-80e7-40e0-9778-37783965c600","externalId":"29945006-82ac-4519-af14-892eda191a6b"},{"type":"BANK","id":"414bc3e9-fa14-488b-84a5-48ce134a2045","externalId":"e2fe672f-2586-48ad-ac8b-354f47832b0a"}]}
2;6e61a0cb-d072-4ca8-a4c4-e626dca3faed;PROCESSED;true;200;{"id":"1fce69f1-24f3-477b-88fb-7c4ae352b651","externalId":"92ae5ae0-5900-45a2-8138-23f631047cdd","paymentCredentials":[{"type":"CARD","id":"2e7847e0-2226-4d23-ad44-8f2a2175eee2","externalId":"44b4602d-0b8c-4ea7-a214-7a078b24e951"},{"type":"BANK","id":"520c5e64-ae3c-4d53-81b7-231e670b550a","externalId":"ec7f4c2f-1e2f-4ae5-ae57-7e9247307b18"}]}
3;c0204aa0-a195-4369-b72e-130d0f5188aa;PROCESSED;true;200;{"id":"af4afa3e-bfac-41cd-ab07-d9963cb56881","externalId":"64536505-e55a-424c-97d3-fabfa099f0c8","paymentCredentials":[{"type":"CARD","id":"b44b3e94-5234-4f65-a763-dc2e1a7c65e4","externalId":"4bac61b8-b3f6-47b7-976d-f623f7a74f32"},{"type":"BANK","id":"3910c05f-f3f8-419a-a992-037ca630fdde","externalId":"3257c2e4-b4e7-4ead-99a5-2a96b294feec"}]}
		

Please ask your Visa representation for a sample tool for reading Batch results.