> For the complete documentation index, see [llms.txt](https://docs.payments.thalescloud.io/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.payments.thalescloud.io/classic-tokenization/es/casos-de-uso/sincronizar-tokens-usando-archivos-por-lotes/estructura-del-archivo-por-lotes.md).

# Estructura del archivo por lotes

Esta página define el formato de archivo por lotes que el backend del emisor proporciona para actualizaciones por lotes.

### Estructura del archivo por lotes <a href="#batch-file-structure" id="batch-file-structure"></a>

El archivo por lotes tiene la siguiente estructura:

| NOMBRE     | TIPO   | M/O/C | DESCRIPCIÓN                                                                                                                                                                                                                                                                                                                                                               |
| ---------- | ------ | ----- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| encabezado | Objeto | M     | El encabezado que describe la solicitud de actualización por lotes.                                                                                                                                                                                                                                                                                                       |
| registros  | Matriz | M     | La matriz que contiene los registros. Cada registro corresponde a una operación.                                                                                                                                                                                                                                                                                          |
| firma      | Cadena | M     | Este campo representa una Firma Web JSON (JWS) separada. La firma debe crearse con la clave privada del emisor. Durante la incorporación D1, el emisor comparte la clave pública correspondiente. Para más detalles, consulte [JWS](https://thales-dis-dbp.stoplight.io/docs/digital-payment/branches/api-releases-v2.9.0/oeju7u3guavui-batch-file-definition#signature). |

#### Encabezado <a href="#header" id="header"></a>

El encabezado tiene la siguiente estructura:

| NOMBRE    | TIPO   | TAMAÑO | M/O/C | DESCRIPCIÓN                                                                                             |
| --------- | ------ | ------ | ----- | ------------------------------------------------------------------------------------------------------- |
| batchId   | Cadena | 48     | M     | El identificador del archivo por lotes tal como se especifica en el nombre del archivo.                 |
| seqNumber | Cadena | 48     | M     | El número de secuencia del archivo por lotes tal como se especifica en el nombre del archivo.           |
| issuerId  | Cadena | 48     | M     | El identificador del emisor.                                                                            |
| operation | Cadena | 48     | M     | Identifica la operación que se realizará con el archivo de entrada. Valor: `VIRTUAL_CARD_REGISTRATION`. |

#### Registros <a href="#records" id="records"></a>

Un registro tiene la siguiente estructura:

| NOMBRE                         | TIPO   | TAMAÑO | M/O/C | DESCRIPCIÓN                                                   |
| ------------------------------ | ------ | ------ | ----- | ------------------------------------------------------------- |
| rowId                          | int    | -      | M     | El identificador incremental de la fila.                      |
| virtualCardRegistrationRequest | Objeto | -      | M     | La carga útil de la solicitud de registro de tarjeta virtual. |

**virtualCardRegistrationRequest**

| NOMBRE | TIPO                | TAMAÑO | M/O/C | DESCRIPCIÓN                                              |
| ------ | ------------------- | ------ | ----- | -------------------------------------------------------- |
| card   | Objeto de tipo Card | N/D    | M     | Un objeto que contiene los datos cifrados de la tarjeta. |

Donde el *card* tiene la siguiente estructura:

| NOMBRE        | TIPO   | TAMAÑO | M/O/C | DESCRIPCIÓN                                          |
| ------------- | ------ | ------ | ----- | ---------------------------------------------------- |
| id            | Cadena | 1...48 | M     | El identificador único asignado por el emisor.       |
| encryptedData | Cadena | -      | M     | Carga PKCS#7 cifrada con la clave pública de Thales. |
| scheme        | Cadena | -      | M     | Valores: `VISA` o `MASTERCARD`.                      |

El algoritmo de cifrado de contenido es `AES256/CBC/PKCS7Padding`.

El algoritmo de cifrado de clave compatible para una clave pública RSA (2048 bits) es `RSA/OAEPWithSHA256AndMGF1Padding`.

Para más detalles, consulte [Cifrado de datos y seguridad](/classic-tokenization/es/comenzar/conceptos-basicos-de-la-api/cifrado-y-seguridad-de-datos.md).

La estructura de la carga útil descifrada es la siguiente:

| NOMBRE | TIPO   | TAMAÑO   | M/O/C | DESCRIPCIÓN                                                                 |
| ------ | ------ | -------- | ----- | --------------------------------------------------------------------------- |
| fpan   | Cadena | Hasta 20 | M     | FPAN de la tarjeta de financiación. Ejemplo: `{"fpan":"6789451266992345"}`. |

### Firma <a href="#signature" id="signature"></a>

El objeto de firma utiliza el esquema JWS tal como lo especifica [RFC 7515](https://datatracker.ietf.org/doc/html/rfc7515).

Durante la incorporación D1, el emisor debe compartir la clave pública.

#### Proceso <a href="#process" id="process"></a>

1. Eliminar retornos de carro y espacios en blanco de la carga útil.
2. Codificar la carga útil usando `UTF-8`.
3. Inicializar un objeto de firma con los datos codificados.
4. Establecer el encabezado protegido:
   1. `alg = "PS256"`
   2. `kid = "identificador de clave"`
5. Usar la clave privada para firmar los datos y producir un objeto JWS.
6. Dividir la cadena JWS en partes usando `.` como separador.
7. Crear la firma separada combinando la primera y la tercera partes con `..`.
8. Devolver la firma separada.

Ejemplo (Node.js):

```javascript
const jose = require("jose");
const { pem2jwk } = require("pem-jwk");

async function generateJWS() {
        const issuerSignPrivateKey = `-----BEGIN RSA PRIVATE KEY-----
................................................................
................................................................
................................................................
-----END RSA PRIVATE KEY-----`;

    // Convertir la clave privada PEM a formato JWK
    const privateKeyJWK = pem2jwk(issuerSignPrivateKey);

    // Importar el JWK en un objeto clave
    const privateKey = await jose.importJWK(privateKeyJWK);

    // Crear la carga útil para firmar (como un objeto)
    const input = {"header": {...},"records": [...]};
    // Convertir a cadena y eliminar espacios en blanco
    const payload = JSON.stringify(input).replace(/\s+|\r?\n|\r|\n|\t/g, "");
    const encode = new TextEncoder().encode(payload);

    // Firmar la carga útil con la clave privada
    const jws = await new jose.CompactSign(encode)
        .setProtectedHeader({ alg: "PS256", kid: "KID_VALUE" })
        .sign(privateKey);

    // Dividir el JWS para crear la firma
    const signParts = jws.split(".");
    const signature = signParts[0] + ".." + signParts[2];

    console.log("Firma:", signature);
}

// Llamar a la función
generateJWS();
```

**Composición JWS**

El formato siguiente muestra la representación de un objeto JWS:

`Base64URL(UTF-8(encabezado JWS)) || '.' || Base64URL(carga útil JWS) || '.' || Base64URL(firma JWS)`

Como se usa la firma separada, la Carga útil JWS se reemplaza por una cadena vacía:

`Base64URL(UTF-8(encabezado JWS)) || '..' || Base64URL(firma JWS)`

**Encabezado JWS**

El encabezado contiene los siguientes metadatos:

| NOMBRE | TIPO        | TAMAÑO | REQUERIDO/OPCIONAL/CONDICIONAL | DESCRIPCIÓN                                                         |
| ------ | ----------- | ------ | ------------------------------ | ------------------------------------------------------------------- |
| alg    | Enumeración | n/a    | Requerido                      | Algoritmo usado para firmar la carga útil JWS. El valor es `PS256`. |
| kid    | Cadena      | 64     | Requerido                      | Identificador de la clave usada para firmar la carga útil JWS.      |

**Carga útil JWS**

La carga útil a firmar es un objeto JSON con los `encabezado` y `registros` atributos. Utiliza codificación `UTF-8` y no contiene retornos de carro ni espacios en blanco. Ejemplo: `{header:{...},records:[...]}`

### Ejemplo de archivo por lotes <a href="#batch-file-example" id="batch-file-example"></a>

```json
{
    "header": {
        "batchId": "0000000000001111111111FF",
        "seqNumber": "005",
        "operation": "VIRTUAL_CARD_REGISTRATION",
        "issuerId": "BANK_ABC"},
    "records": [
            {
            "rowId": 0,
            "virtualCardRegistrationRequest": {
                "card":{
                    "id":"FWSPMC000000000fcb2f4136b2f4136a0532d2f4136a0532",
                    "encryptedData":"KDlTthhZTGufMY…….xPSUrfmqCHXaI9wOGY=",
                    "scheme":"MASTERCARD"}
                }
            },
            {
            "rowId": 1,
            "virtualCardRegistrationRequest": {
                "card":{
                    "id":"FWSPMC000000000fcb2f4136b2f4136a0532d2f4136a0532",
                    "encryptedData":"KDlTthhZTGufMY…….xPSUrfmqCHXaI9wOGY=",
                    "scheme":"MASTERCARD"}
                }
            }
    ],
    "signature": "AxY8DctDa….GlsbGljb3RoZQ="
}
```


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.payments.thalescloud.io/classic-tokenization/es/casos-de-uso/sincronizar-tokens-usando-archivos-por-lotes/estructura-del-archivo-por-lotes.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
