# Autorización y cálculo de Signature

## <mark style="color:blue;">Credenciales de la API</mark>

Nuestra API de Depósitos usa las Credenciales para autenticar todas las llamadas. Podrán encontrar sus credenciales en el **Panel Tupay**, desde **Settings -> API Access**.

* Las Credenciales de los ambientes de STG y Producción son diferentes.

Básicamente, hay dos juegos de credenciales:

* Un juego de Credenciales para llamadas del tipo POST, que contiene una API Key y una API Signature.
* Un juego de Credenciales read-only, que contiene una API Key.

La Autenticación para la API es hecha vía [HTTP Basic Auth](http://en.wikipedia.org/wiki/Basic_access_authentication). Se debe enviar la API Key en todos las llamadas como autenticación básica del valor username. No se requiere proveer una contraseña.

La API Key debe ser enviada en todas las llamadas a la API usando el campo X-Login en los encabezados del request.

## <mark style="color:blue;">Encabezados</mark>

<table><thead><tr><th width="204">Encabezado</th><th width="100">Formato</th><th width="122">Obligatorio</th><th>Descripción</th></tr></thead><tbody><tr><td>Authorization</td><td>String</td><td>Si</td><td><code>"D24"</code> más un hash HMAC256 para verificar la integridad de las llamadas.</td></tr><tr><td>X-Login</td><td>String</td><td>Si</td><td>Su <code>API Key</code></td></tr><tr><td>X-Date</td><td>String</td><td>Si</td><td>Fecha según el estándar ISO 8601 en el siguiente formato: <code>yyyy-MM-dd'T'HH:mm:ssZ</code>. E.g.: <code>2020-06-21T12:33:20Z</code></td></tr><tr><td>Content-Type</td><td>String</td><td>Si</td><td><code>application/json</code></td></tr><tr><td>X-Idempotency-Key</td><td>String</td><td>Si</td><td>Valor único generado por el cliente que usa el servidor para reconocer reintentos subsecuentes de la misma llamada.</td></tr></tbody></table>

## <mark style="color:blue;">Cálculo de Signature</mark>

Todas las llamadas a nuestra API de Depósitos debe contener el campo Authorization en el encabezado para asegurar la integridad de la llamada y autenticar las credenciales del Comercio, ya que usaran su propia secret key (también llamada API Signature).

Tiene que ser creada usando codificación **HMAC-SHA-256 (RFC 2104)** y el contenido debe incluir los siguientes detalles:

> [X-Date](#notas) + [X-Login](#notas) + `JSONPayload`

{% hint style="success" %}
Usa tu API Signature para generar el valor `Authorization`.
{% endhint %}

El campo `Authorization` en el encabezado de la llamada debe contener el string "**D24** " más el hash generado, en el siguiente formato:

> Authorization: "D24 " + HMAC256(X-Date + X-Login + JSONPayload)

Ejemplo:

> Authorization: D24 223a9dd4784726f1536c926da7dc69155a57612c5c3c1e1b429c367a5eee67cf

<details>

<summary>Notas</summary>

* Él [`X-Login`](#notas) es su API Key, puede ser encontrada en el Tupay Panel, yendo a Settings -> API Access -> Deposit credentials -> API Key.
* El [`X-Date`](#notas) es la fecha en ISO8601 Datetime con huso horario. El formato esperado es:  ISO8601 Datetime con huso horario: <mark style="color:blue;">`yyyy-MM-dd'T'HH:mm:ssZ`</mark>. Ejemplo: [<mark style="color:blue;">`2020-06-21T12:33:20Z`</mark>](#user-content-fn-1)[^1].&#x20;
* El <mark style="color:blue;">`JSONPayload`</mark> debe ser convertido a UTF-8 antes del hashing para prevenir el error Invalid Signature cuando se envían caracteres con distinta codificación.

</details>

{% tabs %}
{% tab title="IP Whitelisting" %}
Por motivos de seguridad, necesitarán hacer whitelist de sus IPs desde las cuales van a estar haciendo las llamada a nuestras APIs.\
Para hacer este proceso lo más eficiente y rápido posible, deben entrar al Tupay Panel e ir a **Settings -> API Access** y agregar la lista de IPs de las cuales podrían usar bajo la sección **Deposit IP Address**.

<figure><img src="/files/v2agSiDM1XPkxTK5wfsP" alt="" width="298"><figcaption></figcaption></figure>
{% endtab %}
{% endtabs %}

<details>

<summary>Buenas Practicas</summary>

* Asegúrese siempre de verificar las Signatures control string enviados en las notificaciones para validar la veracidad.
* Toda la información que recibimos es convertida a UTF-8. Asegúrese de convertirla también a UTF-8 para garantizar que ambas partes tengan los mismos detalles.
* Siempre valide que un depósito no se libere más de una vez según el `deposit_id` (Las notificaciones se pueden enviar varias veces).\
  Asegúrese de que un depósito no es liberado más de una vez basándonos en el `deposit_id`, ya que la notificación puede ser enviada más de una vez.

</details>

## <mark style="color:blue;">Ejemplos</mark>

Revisa cómo calcular la Signature en los diferentes lenguajes.

{% tabs %}
{% tab title="PHP" %}

```php
<?php
class TupayExample {
	const D24_AUTHORIZATION_SCHEME = "D24 ";
	const HMAC_SHA256 = 'sha256';
	
	public static function build_deposit_key_signature($api_signature, $x_date, $deposits_api_key, $json_payload) {
		// Concatenate the content of the header X-Date, your deposits API Key (X-Login) and 
		// the whole JSON payload of the body of the request
		
		$string = $x_date . $deposits_api_key . $json_payload;
		
		// Generate the HASH by using yur own deposits API Signature and 
		// concatenate "D24 " in front of the hash
		return  self::D24_AUTHORIZATION_SCHEME . hash_hmac(self::HMAC_SHA256, $string, $api_signature);
	}
}
```

{% endtab %}

{% tab title="JAVA" %}

```java
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.util.Formatter;
import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;

public static final String D24_AUTHORIZATION_SCHEME = "D24 ";

private static final String HMAC_SHA256 = "HmacSHA256";

public static String buildDepositKeySignature(String apiSignature, String xDate, String depositKey, String JSONPayload)
      throws NoSuchAlgorithmException, InvalidKeyException, IOException {
   byte[] hmacSha256 = null;
   Mac mac = Mac.getInstance(HMAC_SHA256);
   SecretKeySpec secretKeySpec = new SecretKeySpec(apiSignature.getBytes(StandardCharsets.UTF_8), HMAC_SHA256);
   mac.init(secretKeySpec);
   hmacSha256 = mac.doFinal(buildByteArray(xDate, apiKey, JSONPayload));
   return D24_AUTHORIZATION_SCHEME + toHexString(hmacSha256);
}

private static byte[] buildByteArray(String xDate, String apiKey, String JSONPayload) throws IOException {
   ByteArrayOutputStream bos = new ByteArrayOutputStream();
   bos.write(xDate.getBytes(StandardCharsets.UTF_8));
   bos.write(apiKey.getBytes(StandardCharsets.UTF_8));
   if (JSONPayload != null) {
      bos.write(payload.getBytes(StandardCharsets.UTF_8));
   }
   return bos.toByteArray();
}

private static String toHexString(byte[] bytes) {
   Formatter formatter = new Formatter();
   for (byte b : bytes) {
      formatter.format("%02x", b);
   }
   return formatter.toString();
}
```

{% endtab %}

{% tab title="C#" %}

```csharp
using System;
using System.Text;
using System.IO;
using System.Security.Cryptography;

namespace Application 
{

    class Directa24Example 
    {
    
        public readonly static string D24_AUTHORIZATION_SCHEME = "D24 ";
        
        private readonly static string HMAC_SHA256 = "HmacSHA256";
        
        public static String buildDepositKeySignature(String apiSignature, String xDate, String depositKey, String jsonPayload)
        {
            byte[] hmacSha256 = null;
            var apiSignatureEncod = Encoding.UTF8.GetBytes(apiSignature);
            var hash = new HMACSHA256(apiSignatureEncod);
            hmacSha256 = hash.ComputeHash(buildByteArray(xDate, depositKey, jsonPayload));  
            return D24_AUTHORIZATION_SCHEME + toHexString(hmacSha256).ToLower();
        }
        
        private static byte[] buildByteArray(String xDate, String apiKey, String jsonPayload)
        {
            try
            {
                MemoryStream stream = new MemoryStream();
                var xDateEncod = Encoding.UTF8.GetBytes(xDate);
                var apiKeyEncod = Encoding.UTF8.GetBytes(apiKey);
                stream.Write(xDateEncod, 0, xDateEncod.Length);
                stream.Write(apiKeyEncod, 0, apiKeyEncod.Length);
                if (!string.IsNullOrWhiteSpace(jsonPayload))
                {
                    var jsonPayloadEncod = Encoding.UTF8.GetBytes(jsonPayload);
                    stream.Write(jsonPayloadEncod, 0, jsonPayloadEncod.Length);
                }
                return stream.ToArray();
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }
        
        private static string toHexString(byte[] bytes)
        {
            return BitConverter.ToString(bytes).Replace("-", string.Empty);
        }
    }
}
```

{% endtab %}
{% endtabs %}

[^1]:


---

# Agent Instructions: 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.tupayonline.com/documentacion-de-la-api/tu-payplus/tu-verify/autorizacion-y-calculo-de-signature.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.
