Integra constancias de conservación (NOM 151) en tu proyecto con la API REST de Mifiel

La NOM-151 es una norma clave en México que regula las constancias de conservación, asegurando la autenticidad e integridad de documentos digitales. En este artículo, aprenderás a implementar constancias de conservación en tu proyecto mediante la API REST de Mifiel, con ejemplos prácticos en lenguajes como Node.js, Python, Ruby, PHP y C#.

¿Qué es la NOM-151?

La NOM-151 define los requisitos para conservar documentos digitales de manera legal y segura. Las constancias de conservación permiten garantizar que un archivo no ha sido alterado desde su creación. Para una descripción más detallada visita este artículo.

La API de Mifiel para obtener constancias de conservación

Las API de NOM 151 de Mifiel cuenta con dos endpoints, uno para generar constancias y otro para recuperar constancias generadas anteriormente:

  1. Generar constancia de conservación (POST):
    • Endpoint: /api/v1/psc/nom151
    • Parámetros aceptados en el cuerpo de la solicitud:
      • hash: Cadena hash SHA256 del documento (obligatorio).
      • external_id: Identificador único opcional para referencia externa (opcional).
    • Respuesta incluye:
      • id: Identificador único de la constancia.
      • nom151: Cadena en Base64 de la constancia generada.
      • created_at: Fecha de creación de la constancia.
      • certificate: Certificado del Prestador de Servicios de Certificación (PSC) que emitió la constancia.
      • hash: Cadena hash SHA256 proporcionada.
  2. Recuperar constancia de conservación (GET):
    • Endpoints:
      • Por external_id: /psc/api/v1/psc/nom151?external_id={:external_id}
      • Por id: /psc/api/v1/psc/nom151/{:id}
    • Respuesta incluye:
      • id: Identificador único de la constancia.
      • nom151: Cadena en Base64 de la constancia generada.
      • created_at: Fecha de creación de la constancia.
      • certificate: Certificado del PSC emisor.
      • hash: Cadena hash SHA256 proporcionada​.

API NOM 151: Primeros pasos

Mifiel cuenta con dos ambientes, el de pruebas (Sandbox) y el productivo. Para iniciar con pruebas sigue los siguientes pasos:

  1. Crear una cuenta en el Sandbox de Mifiel. Selecciona “Ninguna de las anteriores en las opciones”.
  2. Contáctanos por Chat (ícono verde en la esquina inferior derecha) y solicita que te habilitemos la API y créditos de Constancias de Conservación para hacer pruebas.
  3. Genera tus API keys en la sección de Configuraciones de API.

Tus primeras constancias

Una vez tengas tus API keys el siguiente paso es generar una constancia de conservación vía la API de NOM 151 de Mifiel. Para simplificar tus pruebas a continuación podrás consultar unos ejemplos es distintos lenguajes de programación para obtener una constancia de conservación de un archivo PDF. Los ejemplos incluyen la función de obtener el hash256 del PDF, manejar la autenticación en Mifiel usando tus API keys y la obtención de la constancia de conservación.

Ejemplos de Código


require 'faraday'
require 'digest'
require 'base64'
require 'json'

# Variables de configuración
SANDBOX_API_URL = "https://app-sandbox.mifiel.com/api/v1/psc/nom151"
SANDBOX_API_KEY = "your_sandbox_api_key"
SANDBOX_API_SECRET = "your_sandbox_api_secret"
PDF_PATH = "path/to/your-document.pdf"

# Función para calcular el hash SHA256 de un archivo
def calculate_sha256(file_path)
  digest = Digest::SHA256.new
  File.open(file_path, 'rb') do |file|
    buffer = ''
    digest.update(buffer) while file.read(1024, buffer)
  end
  digest.hexdigest
end

# Función principal
def generate_constancia
  begin
    # Calcular el hash SHA256 del archivo PDF
    pdf_hash = calculate_sha256(PDF_PATH)

    # Crear el payload
    payload = {
      hash: pdf_hash
    }

    # Crear encabezado de autenticación
    auth_header = "Basic " + Base64.strict_encode64("#{SANDBOX_API_KEY}:#{SANDBOX_API_SECRET}")

    # Crear conexión Faraday
    connection = Faraday.new do |conn|
      conn.request :json # Para enviar el cuerpo como JSON
      conn.response :json, parser_options: { symbolize_names: true } # Para parsear la respuesta como JSON
      conn.adapter Faraday.default_adapter
    end

    # Realizar la solicitud POST
    response = connection.post(SANDBOX_API_URL) do |req|
      req.headers['Authorization'] = auth_header
      req.headers['Content-Type'] = 'application/json'
      req.body = payload
    end

    # Manejar la respuesta
    if response.success?
      puts "Constancia generada con éxito:"
      puts response.body
    else
      puts "Error al generar la constancia: #{response.status}"
      puts response.body
    end
  rescue StandardError => e
    puts "Error al realizar la solicitud: #{e.message}"
  end
end

# Ejecutar la función
generate_constancia


const axios = require("axios");
const fs = require("fs");
const crypto = require("crypto");

// Variables de configuración
const SANDBOX_API_URL = "https://app-sandbox.mifiel.com/api/v1/psc/nom151";
const SANDBOX_API_KEY = "your_sandbox_api_key";
const SANDBOX_API_SECRET = "your_sandbox_api_secret";
const PDF_PATH = "path/to/your-document.pdf";

// Función para calcular el hash SHA256 de un archivo
function calculateSHA256(filePath) {
  const fileBuffer = fs.readFileSync(filePath);
  return crypto.createHash("sha256").update(fileBuffer).digest("hex");
}

// Función principal
async function generateConstancia() {
  try {
    // Calcular el hash SHA256 del archivo PDF
    const pdfHash = calculateSHA256(PDF_PATH);

    // Crear el payload
    const payload = {
      hash: pdfHash,
    };

    // Crear encabezado de autenticación
    const authHeader =
      "Basic " +
      Buffer.from(`${SANDBOX_API_KEY}:${SANDBOX_API_SECRET}`).toString("base64");

    // Enviar la solicitud POST
    const response = await axios.post(SANDBOX_API_URL, payload, {
      headers: {
        "Content-Type": "application/json",
        Authorization: authHeader,
      },
    });

    // Manejar la respuesta
    console.log("Constancia generada con éxito:");
    console.log(response.data);
  } catch (error) {
    if (error.response) {
      console.error("Error en la respuesta del servidor:");
      console.error(error.response.data);
    } else {
      console.error("Error al realizar la solicitud:");
      console.error(error.message);
    }
  }
}

// Ejecutar la función
generateConstancia();


import hashlib
import base64
import requests

# Variables de configuración
SANDBOX_API_URL = "https://app-sandbox.mifiel.com/api/v1/psc/nom151"
SANDBOX_API_KEY = "your_sandbox_api_key"
SANDBOX_API_SECRET = "your_sandbox_api_secret"
PDF_PATH = "path/to/your-document.pdf"

# Función para calcular el hash SHA256 de un archivo
def calculate_sha256(file_path):
    sha256_hash = hashlib.sha256()
    with open(file_path, "rb") as file:
        for byte_block in iter(lambda: file.read(4096), b""):
            sha256_hash.update(byte_block)
    return sha256_hash.hexdigest()

# Función principal
def generate_constancia():
    try:
        # Calcular el hash SHA256 del archivo PDF
        pdf_hash = calculate_sha256(PDF_PATH)

        # Crear el payload
        payload = {
            "hash": pdf_hash
        }

        # Crear encabezado de autenticación
        auth_header = base64.b64encode(f"{SANDBOX_API_KEY}:{SANDBOX_API_SECRET}".encode()).decode()

        # Realizar la solicitud POST
        headers = {
            "Authorization": f"Basic {auth_header}",
            "Content-Type": "application/json"
        }

        response = requests.post(SANDBOX_API_URL, json=payload, headers=headers)

        # Manejar la respuesta
        if response.status_code == 200 or response.status_code == 201:
            print("Constancia generada con éxito:")
            print(response.json())
        else:
            print(f"Error al generar la constancia: {response.status_code}")
            print(response.json())
    except Exception as e:
        print(f"Error al realizar la solicitud: {e}")

# Ejecutar la función
generate_constancia()


<?php

// Variables de configuración
$SANDBOX_API_URL = "https://app-sandbox.mifiel.com/api/v1/psc/nom151";
$SANDBOX_API_KEY = "your_sandbox_api_key";
$SANDBOX_API_SECRET = "your_sandbox_api_secret";
$PDF_PATH = "path/to/your-document.pdf";

// Función para calcular el hash SHA256 de un archivo
function calculateSHA256($filePath) {
    $hash = hash_file('sha256', $filePath);
    return $hash;
}

// Función principal
function generateConstancia($url, $apiKey, $apiSecret, $pdfPath) {
    try {
        // Calcular el hash SHA256 del archivo PDF
        $pdfHash = calculateSHA256($pdfPath);

        // Crear el payload
        $payload = json_encode([
            "hash" => $pdfHash
        ]);

        // Crear encabezado de autenticación
        $authHeader = "Basic " . base64_encode("$apiKey:$apiSecret");

        // Configurar la solicitud cURL
        $ch = curl_init($url);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
        curl_setopt($ch, CURLOPT_POST, true);
        curl_setopt($ch, CURLOPT_HTTPHEADER, [
            "Authorization: $authHeader",
            "Content-Type: application/json"
        ]);
        curl_setopt($ch, CURLOPT_POSTFIELDS, $payload);

        // Ejecutar la solicitud
        $response = curl_exec($ch);
        $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);

        // Manejar errores de cURL
        if ($response === false) {
            throw new Exception('Error en la solicitud cURL: ' . curl_error($ch));
        }

        // Cerrar cURL
        curl_close($ch);

        // Manejar la respuesta
        if ($httpCode === 200 || $httpCode === 201) {
            echo "Constancia generada con éxito:\n";
            echo $response . "\n";
        } else {
            echo "Error al generar la constancia (HTTP $httpCode):\n";
            echo $response . "\n";
        }
    } catch (Exception $e) {
        echo "Error: " . $e->getMessage() . "\n";
    }
}

// Ejecutar la función
generateConstancia($SANDBOX_API_URL, $SANDBOX_API_KEY, $SANDBOX_API_SECRET, $PDF_PATH);

?>


using System;
using System.IO;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Security.Cryptography;
using System.Text;
using System.Text.Json;
using System.Threading.Tasks;

class Program
{
    // Variables de configuración
    private const string SANDBOX_API_URL = "https://app-sandbox.mifiel.com/api/v1/psc/nom151";
    private const string SANDBOX_API_KEY = "your_sandbox_api_key";
    private const string SANDBOX_API_SECRET = "your_sandbox_api_secret";
    private const string PDF_PATH = "path/to/your-document.pdf";

    static async Task Main(string[] args)
    {
        try
        {
            // Calcular el hash SHA256 del archivo PDF
            string pdfHash = CalculateSHA256(PDF_PATH);

            // Crear el payload
            var payload = new
            {
                hash = pdfHash
            };

            string payloadJson = JsonSerializer.Serialize(payload);

            // Configurar el cliente HTTP
            using HttpClient client = new HttpClient();
            var authHeader = Convert.ToBase64String(Encoding.UTF8.GetBytes($"{SANDBOX_API_KEY}:{SANDBOX_API_SECRET}"));
            client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Basic", authHeader);
            client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));

            // Crear el contenido de la solicitud
            var content = new StringContent(payloadJson, Encoding.UTF8, "application/json");

            // Realizar la solicitud POST
            HttpResponseMessage response = await client.PostAsync(SANDBOX_API_URL, content);

            // Manejar la respuesta
            if (response.IsSuccessStatusCode)
            {
                string responseBody = await response.Content.ReadAsStringAsync();
                Console.WriteLine("Constancia generada con éxito:");
                Console.WriteLine(responseBody);
            }
            else
            {
                string errorBody = await response.Content.ReadAsStringAsync();
                Console.WriteLine($"Error al generar la constancia: {response.StatusCode}");
                Console.WriteLine(errorBody);
            }
        }
        catch (Exception ex)
        {
            Console.WriteLine($"Error: {ex.Message}");
        }
    }

    // Método para calcular el hash SHA256 de un archivo
    private static string CalculateSHA256(string filePath)
    {
        using FileStream stream = File.OpenRead(filePath);
        using SHA256 sha256 = SHA256.Create();
        byte[] hashBytes = sha256.ComputeHash(stream);
        StringBuilder hashString = new StringBuilder();
        foreach (byte b in hashBytes)
        {
            hashString.Append(b.ToString("x2"));
        }
        return hashString.ToString();
    }
}

Scroll al inicio