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:
- 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.
- Endpoint:
- 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}
- Por
- 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.
- Endpoints:
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:
- Crear una cuenta en el Sandbox de Mifiel. Selecciona “Ninguna de las anteriores en las opciones”.
- 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.
- 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
-
Ruby
-
NodeJS
-
Python
-
PHP
-
C#
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();
}
}