# Algoritmo de firma

En los request de operaciones existe un campo que es "sing", este campo es uno de los requisitos de seguridad para validar la identidad del comercio y el origen del request, y tomara el valor de lo generado por los siguientes pasos.

Pasos para la generación de firma

1. Listar todos los campos del Request.
2. Se deben organizar de forma alfabetica todos los campos.
3. Concatenar los campo y los valores asignados utilizando signo de igual "=" para separar el nombre del campo del valor, y para separar lo campos con sus valores utilizar el signo de amperson "&".

```
campoA=valorA&campoB=valorB
```

4. Se debe agregar el campo de key y el valor correspondiente a la llave del comercio para la API, en este ejemplo es "11111111111111111111111111111111".

```
campoA=valorA&campoB=valorB&key=11111111111111111111111111111111
```

5. A toda esta cadena de texto se debe aplicar una operacion de generación de hash MD5 para obtener el valor del campo sign se debe agregar al request de la operación a realizar.

{% hint style="info" %}
Atención

1. Los nombres de los parámetros se ordenan de menor a mayor según su código ASCII (en orden alfabetico).
2. Si el valor de un parámetro está vacío, no se incluye en el proceso de firma.
3. En los nombres de los parámetros se diferencian mayúsculas de minúsculas.
4. Cuando se envia el callback para la verificación o el sistema de pago notifica activamente la firma, el parámetro sign en los datos no participa en la firma; se debe verificar la firma generada con el valor de sign.
5. En los requerimientos de operaciones se pueden agregar campos. Los campos que se agreguen deben ser compatibles al verificar las firmas.
6. Al firmar, se debe utilizar la clave del comerciante en <mark style="background-color:red;">texto claro</mark> (la falta de vinculación con Google Authenticator puede causar que la clave en el backoffice del comerciante se muestre en texto cifrado).
   {% endhint %}

## Ejemplo

1. Por ejemplo, los parámetros de la solicitud son los siguientes：

```json
 {
  "countryId": "COL",
  "currency": "COP",
  "customerAccount": "3720000264",
  "merId": "8301000002750275",
  "merOrderNo": "merOrderNo",
  "nonceStr": "string",
  "orderAmount": "30000",
  "payProduct": "08",
  "nonceStr": "4cKcL83FIsDgjAi"
}
```

2. Según las reglas, se concatena para obtener la cadena a firmar:

```
countryId=COL&currency=COP&customerAccount=3720000264&merId=8301000002750275&merOrderNo=merOrderNo&nonceStr=4cKcL83FIsDgjAi&orderAmount=30000&payProduct=08&key=11111111111111111111111111111111
```

3. Resultado final de la firma:

```
1DD2448C750D92B3AE512F2E493F5665
```

4. Parámetros finales del request:

```
 {
  "countryId": "COL",
  "currency": "COP",
  "customerAccount": "3720000264",
  "merId": "8301000002750275",
  "merOrderNo": "merOrderNo",
  "nonceStr": "string",
  "orderAmount": "30000",
  "payProduct": "08",
  "nonceStr": "4cKcL83FIsDgjAi",
  "sign": "1DD2448C750D92B3AE512F2E493F5665"
}
```

Uso del SDK de firma

1. Para descargar el SDK, consulte “Recursos del diccionario > Descargas” - “SDK de firma”.
2. Incorpore el archivo JAR “supefina-sign” en su proyecto.
3. Completa la operación de firma mediante el método com.supefina.sign.SupefinaSignUtils#sign(java.lang.Object, java.lang.String) (parámetro 1: objeto JSON de parámetros de solicitud; parámetro 2: clave del comerciante).

## Demo de firma &#x20;

<mark style="background-color:red;">java</mark>

```java
public static String sign(Object data, String key) {
        return sign(JSON.parseObject(JSONObject.toJSONString(data)), key);
    }

public static String sign(Map<String, Object> data, String key) {
        data.remove("sign");
        String signedValue = getSignedValue(data);
        signedValue += "key=" + key;
        log.info("signedValue:{}", signedValue);
        return md5(signedValue, "UTF-8").toUpperCase();
    }

private static String getSignedValue(Map<String, Object> reqMap) {
        Map<String, String> copy = new TreeMap<>();
        reqMap.forEach((k, v) -> {
            if (v != null && !"".equals(v)) {
                copy.put(k, v.toString());
            }
        });
        StringBuilder sb = new StringBuilder();
        copy.forEach((k, v) -> {
            if (v != null) {
                sb.append(k).append("=").append(v).append("&");
            }
        });
        return sb.toString();
    }
```

## Demo de verificación de firma

```java
String callbackData = "{\n" + "  \"countryId\": \"COL\",\n" + "  \"currency\": \"COP\",\n"
+ "  \"customerAccount\": \"3720000264\",\n" + "  \"merId\": \"8301000002750275\",\n"
+ "  \"merOrderNo\": \"merOrderNo\",\n" + "  \"nonceStr\": \"string\",\n"
+ "  \"orderAmount\": \"30000\",\n" + "  \"payProduct\": \"08\",\n"
+ "  \"nonceStr\": \"4cKcL83FIsDgjAi\",\n" + "  \"sign\": \"1DD2448C750D92B3AE512F2E493F5665\"\n" + "}";
JSONObject data = JSON.parseObject(callbackData);

String sign = data.get("sign").toString();
data.remove("sign");
String signValue = SupefinaSignUtils.sign(data, "merchant key");
if (Objects.equals(sign, signValue)) {
    // Verificación de firma aprobada
} else {
    // Fallo
}
```


---

# 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://developers.supefina.net/bienvenido-a-la-documentacion-api-de-supefina/algoritmo-de-firma.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.
