Monta una tienda de eSIM funcional sobre la API de eSIMfly: autentícate con HMAC-SHA256, obtén el catálogo de paquetes a precio mayorista, crea pedidos con cargo al saldo de tu cuenta y entrega a tu usuario un código QR listo para escanear. Todo en Node.js puro, sin SDK.
fetch integrado) y el paquete uuidCada petición lleva cuatro cabeceras: tu código de acceso, un ID de petición único (UUID v4), una marca de tiempo en milisegundos y una firma HMAC-SHA256 de timestamp + requestId + accessCode + requestBody calculada con tu clave secreta. Así se evitan manipulaciones y ataques de repetición: las peticiones con más de 5 minutos de antigüedad se rechazan.
const crypto = require('crypto');
const { v4: uuidv4 } = require('uuid');
const BASE_URL = 'https://esimfly.net';
const ACCESS_CODE = process.env.ESIMFLY_ACCESS_CODE; // esf_...
const SECRET_KEY = process.env.ESIMFLY_SECRET_KEY; // sk_...
function hmacHeaders(requestBody = '') {
const timestamp = Date.now().toString();
const requestId = uuidv4();
// signData = Timestamp + RequestID + AccessCode + RequestBody
const signData = timestamp + requestId + ACCESS_CODE + requestBody;
const signature = crypto
.createHmac('sha256', SECRET_KEY)
.update(signData)
.digest('hex')
.toUpperCase();
return {
'RT-AccessCode': ACCESS_CODE,
'RT-RequestID': requestId,
'RT-Timestamp': timestamp,
'RT-Signature': signature,
'Content-Type': 'application/json'
};
}El catálogo devuelve todos los paquetes que puedes vender con tu precio mayorista; la cobertura abarca 200 países y más de 450 redes. Guárdalo en caché y actualízalo periódicamente: los precios cambian cuando los operadores modifican sus tarifas.
async function getPackages(country) {
const query = country ? '?country=' + encodeURIComponent(country) : '';
const res = await fetch(BASE_URL + '/api/v1/business/esims/packages' + query, {
headers: hmacHeaders() // GET request: empty body in the signature
});
const data = await res.json();
return data.data.packages;
}
// Example: list Turkey packages with your wholesale prices
const packages = await getPackages('Turkey');
console.log(packages[0]);
// { package_code: 'TR1GB7D', name: 'Turkey 1 GB 7 Days',
// price: 2.72, data_amount: 1, duration: 7, ... }Un solo POST con el código del paquete compra la eSIM con cargo al saldo de tu cuenta y devuelve todo lo necesario para instalarla: cadena LPA, imagen del código QR y enlaces de instalación con un toque. En la mayoría de los proveedores es síncrono; unos pocos (como KDDI Japón) devuelven status: "pending_details" y entregan la eSIM por webhook unos minutos después, como se explica en la segunda parte.
async function createOrder(packageCode, quantity = 1) {
const body = JSON.stringify({ packageCode, quantity });
const res = await fetch(BASE_URL + '/api/v1/business/esims/order', {
method: 'POST',
headers: hmacHeaders(body), // body is part of the HMAC signature
body
});
return res.json();
}
const order = await createOrder('TR1GB7D');
console.log(order.orderReference); // order_1692123456_ab7cd
console.log(order.lpaString); // LPA:1$rsp-3104.idemia.io$DOAZJ-...
console.log(order.newBalance); // 47.28 - charged from your balanceCada pedido incluye tres mecanismos de entrega, y conviene mostrarlos todos: el código QR para instalar desde otro dispositivo, el enlace universal de Apple para instalar en iOS con un toque y la cadena LPA en bruto como alternativa manual.
// The order response contains everything your user needs:
//
// order.qrCodeUrl -> base64 PNG, render it directly:
// <img src={order.qrCodeUrl} alt="Scan to install eSIM" />
//
// order.directAppleInstallUrl -> one-tap install on iOS 17.4+
// (universal link, no QR scanning needed)
//
// order.lpaString -> manual entry fallback
// (Settings > Cellular > Add eSIM > Enter manually)
app.get('/my-esim/:orderRef', async (req, res) => {
const esim = await db.getEsimByOrder(req.params.orderRef);
res.render('esim', {
qrCode: esim.qrCodeUrl,
appleUrl: esim.directAppleInstallUrl,
lpa: esim.lpaString
});
});orderReference, el ICCID y los datos de instalación para que los usuarios puedan volver a abrir su eSIM más tarde.newBalance y avísate antes de que se agote.La referencia completa de endpoints, ejemplos en Python y PHP y un entorno de pruebas interactivo están en la documentación.