npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@hanix.io/business

v0.4.0

Published

SDK oficial de Node.js para la Hanix Business API (pagos, checkout, pedidos, envíos, catálogo y webhooks con autenticación HMAC)

Downloads

255

Readme

@hanix.io/business

SDK oficial de Node.js para la Hanix Business API: órdenes de pago, checkout, pedidos de venta, envíos, catálogo (merchant y storefront), webhooks y métodos PSP con autenticación HMAC-SHA256.

Instalación

npm install @hanix.io/business
pnpm add @hanix.io/business

Requisitos

  • Node.js 22.12 o superior
  • merchantId: UUID del comercio (cabecera business-merchant-id)
  • apiKey: secreto HMAC del comercio (no se envía en la red; solo firma las solicitudes). Obtén ambos en el panel Hanix o en GET /merchants/me con tu sesión merchant.

El SDK apunta por defecto a https://api.hanix.io/api/v1.

Inicio rápido

import { HanixBusinessClient } from '@hanix.io/business';

const client = new HanixBusinessClient({
  merchantId: process.env.HANIX_MERCHANT_ID!,
  apiKey: process.env.HANIX_API_KEY!,
});

const order = await client.createPaymentOrder({
  merchant_reference: 'pedido-1001',
  amount_in_cents: 15000,
  currency_id: 'xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx',
  country_id: 'yyyyyyyy-yyyy-yyyy-yyyy-yyyyyyyyyyyy',
  description: 'Suscripción mensual',
  customer_email: '[email protected]',
});

console.log(order.payment_url);

API del cliente

new HanixBusinessClient(options)

| Opción | Obligatorio | Descripción | |--------|-------------|-------------| | merchantId | Sí | UUID del comercio | | apiKey | Sí | Clave API (secreto HMAC) | | timeoutMs | No | Tiempo máximo por solicitud (default: 30000) | | fetch | No | Implementación de fetch (tests o entornos custom) | | userAgent | No | Cabecera User-Agent (default: @hanix.io/business) |

createPaymentOrder(input)

Crea una orden de pago (POST /business/payment-orders).

Campos obligatorios: merchant_reference, amount_in_cents, currency_id, country_id.

Opcionales: description, customer_email, success_url, cancel_url, expires_at, metadata.

Devuelve una PaymentOrder con payment_url, public_token, status, etc.

listPaymentOrders(params?)

Lista órdenes del comercio (GET /business/payment-orders).

Filtros opcionales: status, merchant_reference, currency_id, country_id, created_from, created_to, expires_from, expires_to, page, limit, sort (created_at_asc | created_at_desc).

getPaymentOrder(paymentOrderId)

Obtiene una orden por id (GET /business/payment-orders/:id).

listPaymentOrderAttempts(paymentOrderId, params?)

Lista intentos de pago de una orden (GET /business/payment-orders/:id/attempts).

Filtros opcionales: status (initiated, processing, succeeded, failed, expired, abandoned), page, limit, sort.

listMerchantPspMethods()

Lista métodos PSP del comercio agrupados por PSP (GET /business/merchant-payment-settings/psp-methods).

Devuelve un array de MerchantPspGroup con pspId, pspName, methods (cada uno con pspMethodId, countryId, currencyId, códigos ISO, isActive) y credentials descifradas por PSP, o null.

cancelBusinessPaymentOrder(paymentOrderId, input?)

Cancela una orden de pago (POST /business/payment-orders/:id/cancel).

getBusinessPaymentOrderCheckout(paymentOrderId)

Vista enriquecida para UI de checkout (GET /business/payment-orders/:id/checkout).

getBusinessPaymentOrderCheckoutByPublicToken(publicToken)

Vista de checkout por public_token (GET /business/payment-orders/by-public-token/:token/checkout).

listBusinessCheckoutPspMethods(params)

Métodos PSP para formulario de checkout, sin credenciales (GET /business/checkout/psp-methods). Requiere country_id y currency_id.

Checkout y pedidos (/business/cart, /business/sales-orders)

| Método del SDK | HTTP | |----------------|------| | quoteBusinessCart(input) | POST /business/cart/quote | | createBusinessSalesOrder(input) | POST /business/sales-orders | | listBusinessSalesOrders(params?) | GET /business/sales-orders | | getBusinessSalesOrder(salesOrderId) | GET /business/sales-orders/:id | | payBusinessSalesOrder(salesOrderId, input?) | POST /business/sales-orders/:id/pay | | getBusinessSalesOrderTracking(salesOrderId) | GET /business/sales-orders/:id/tracking | | getBusinessSalesOrderInvoice(salesOrderId) | GET /business/sales-orders/:id/invoice | | cancelBusinessSalesOrder(salesOrderId) | POST /business/sales-orders/:id/cancel | | changeBusinessSalesOrderFulfillment(salesOrderId, input) | PATCH /business/sales-orders/:id/fulfillment | | refundBusinessSalesOrder(salesOrderId) | POST /business/sales-orders/:id/refund |

Referencia, tienda y webhooks

| Método del SDK | HTTP | |----------------|------| | listBusinessCountries() | GET /business/countries | | listBusinessCurrencies() | GET /business/currencies | | getBusinessStoreSettings() | GET /business/store/settings | | getBusinessWebhookSettings() | GET /business/webhooks/settings | | updateBusinessWebhookSettings(input) | PUT /business/webhooks/settings |

Envíos (/business/shipping)

| Método del SDK | HTTP | |----------------|------| | getBusinessShippingSettings() | GET /settings | | updateBusinessShippingSettings(input) | PUT /settings | | listBusinessShippingZones() | GET /zones | | createBusinessShippingZone(input) | POST /zones | | updateBusinessShippingZone(zoneId, input) | PUT /zones/:id | | deleteBusinessShippingZone(zoneId) | DELETE /zones/:id | | createBusinessShippingRate(zoneId, input) | POST /zones/:id/rates | | updateBusinessShippingRate(zoneId, rateId, input) | PUT /zones/:id/rates/:rateId | | deleteBusinessShippingRate(zoneId, rateId) | DELETE /zones/:id/rates/:rateId | | listBusinessShippingPackageProfiles() | GET /package-profiles | | createBusinessShippingPackageProfile(input) | POST /package-profiles | | updateBusinessShippingPackageProfile(profileId, input) | PUT /package-profiles/:id | | deleteBusinessShippingPackageProfile(profileId) | DELETE /package-profiles/:id |

Catálogo storefront (/business/catalog)

| Método del SDK | HTTP | |----------------|------| | searchBusinessCatalogProducts(params?) | GET /products/search | | getBusinessCatalogProductSearchFacets(params?) | GET /products/search/facets | | getBusinessCatalogProductBySlug(slug) | GET /products/by-slug/:slug | | listBusinessCatalogCategories(params?) | GET /categories |

Catálogo merchant (/business/merchant-catalog)

Todos los métodos usan la misma autenticación HMAC. Los cuerpos de solicitud usan camelCase; las respuestas usan snake_case (como la API admin).

Categorías

| Método del SDK | HTTP | |----------------|------| | listCatalogCategories() | GET /categories | | upsertCatalogCategories(categories) | PUT /categories/bulk | | deleteCatalogCategories(ids) | DELETE /categories/bulk | | requestCatalogCategoryImageDirectUploads(uploads) | POST /categories/images/direct-uploads | | registerCatalogCategoryImages(images) | PUT /categories/images/bulk | | deleteCatalogCategoryImages(ids) | DELETE /categories/images/bulk |

Productos

| Método del SDK | HTTP | |----------------|------| | listCatalogCurrencies() | GET /currencies | | createCatalogProduct(input) | POST /products | | listCatalogProducts(params?) | GET /products | | getCatalogProduct(productId) | GET /products/:id | | updateCatalogProduct(productId, input) | PATCH /products/:id | | deleteCatalogProducts(ids) | DELETE /products/bulk | | updateCatalogProductVariant(productId, variantId, input) | PATCH /products/:id/variants/:variantId | | setCatalogVariantWarehouseStock(productId, variantId, qty) | PATCH .../warehouse-stock | | upsertCatalogVariants(variants) | PUT /variants/bulk | | deleteCatalogVariants(ids) | DELETE /variants/bulk | | requestCatalogImageDirectUploads(uploads) | POST /images/direct-uploads | | registerCatalogImages(images) | PUT /images/bulk | | deleteCatalogImages(ids) | DELETE /images/bulk | | adjustCatalogInventory(adjustments) | POST /inventory/adjustments/bulk |

Ejemplo: crear producto e imagen

const product = await client.createCatalogProduct({
  id: crypto.randomUUID(),
  name: 'Camiseta básica',
  currencyId: process.env.HANIX_CURRENCY_ID!,
  variants: [
    {
      id: crypto.randomUUID(),
      sku: 'CAM-001',
      priceInCents: 29900,
      stockQuantity: 10,
    },
  ],
});

const { uploads } = await client.requestCatalogImageDirectUploads([
  { clientReference: 'hero', productId: product.id },
]);

// Subir el archivo a uploads[0].upload_url (POST multipart a Cloudflare)
await fetch(uploads[0]!.upload_url, {
  method: 'POST',
  body: (() => {
    const form = new FormData();
    form.append('file', file);
    return form;
  })(),
});

await client.registerCatalogImages([
  {
    id: crypto.randomUUID(),
    productId: product.id,
    cloudflareImageId: uploads[0]!.cloudflare_image_id,
    isPrimary: true,
  },
]);

Autenticación

Cada solicitud lleva estas cabeceras (generadas por el SDK):

| Cabecera | Descripción | |----------|-------------| | business-merchant-id | UUID del comercio | | business-timestamp | Unix en segundos | | business-signature | HMAC-SHA256(apiKey, timestamp + rawBody) en hexadecimal |

En GET, el cuerpo firmado es la cadena vacía. En solicitudes con cuerpo (POST, PUT, PATCH, DELETE), el JSON se serializa con claves ordenadas para que la firma coincida con los bytes enviados.

Errores

import {
  HanixBusinessError,
  HanixBusinessNetworkError,
  HanixBusinessConfigError,
} from '@hanix.io/business';

try {
  await client.getPaymentOrder('...');
} catch (error) {
  if (error instanceof HanixBusinessError) {
    // 4xx / 5xx de la API (error.status, error.message, error.body)
  } else if (error instanceof HanixBusinessNetworkError) {
    // Timeout o fallo de red (error.cause)
  } else if (error instanceof HanixBusinessConfigError) {
    // merchantId o apiKey inválidos al crear el cliente
  }
}

| Clase | Cuándo | |-------|--------| | HanixBusinessError | Respuesta HTTP no exitosa de Hanix | | HanixBusinessNetworkError | Timeout, red o fetch no disponible | | HanixBusinessConfigError | Opciones inválidas del cliente |

Buenas prácticas

  • Guarda apiKey en variables de entorno o un gestor de secretos; no la subas al repositorio.
  • La apiKey nunca viaja en cabeceras ni en el cuerpo; solo se usa para firmar.
  • Usa merchant_reference único por orden para evitar conflictos (409).

Utilidades exportadas

Para integraciones avanzadas o pruebas manuales:

  • HANIX_BUSINESS_API_BASE_URL — URL base de la API
  • stableStringify, signBusinessPayload, buildBusinessAuthHeaders, verifyBusinessPayload
  • Constantes de cabeceras: BUSINESS_MERCHANT_ID_HEADER, BUSINESS_TIMESTAMP_HEADER, BUSINESS_SIGNATURE_HEADER