Documentation Index Fetch the complete documentation index at: https://docs.komerza.com/llms.txt
Use this file to discover all available pages before exploring further.
Descripción general
Accede a los datos de productos a través de dos métodos:
getStore() - Devuelve todos los productos de la tienda (incluidos en la respuesta de la tienda)
getProduct() - Obtiene un único producto por ID o slug
getProductReviews() - Obtiene reseñas paginadas para un producto
Obtener todos los productos
Los productos están incluidos en la respuesta de la tienda:
const response = await komerza . getStore ();
if ( response . success ) {
const products = response . data . products ;
products . forEach (( product ) => {
console . log ( product . name , product . variants . length , "variantes" );
});
}
Obtener un producto individual
Obtén un producto por ID o slug:
const response = await komerza . getProduct ( "product-id-or-slug" );
Parámetros
El ID único del producto (UUID) o el slug de URL
Ejemplo
// Por ID
const byId = await komerza . getProduct ( "550e8400-e29b-41d4-a716-446655440000" );
// Por slug
const bySlug = await komerza . getProduct ( "premium-license" );
if ( bySlug . success ) {
const product = bySlug . data ;
console . log ( product . name );
console . log ( product . description );
console . log ( product . variants );
}
Objeto Product
interface Product {
id : string ; // Identificador único
name : string ; // Nombre del producto
description : string ; // Descripción (admite markdown)
slug ?: string ; // Slug compatible con URL
imageNames : string []; // Nombres de archivo de imágenes del producto (ver página Images)
rating : number ; // Valoración media de reseñas
order : number ; // Orden de visualización
visibility : number ; // 0=Público, 1=No listado, 2=Privado
storeId : string ; // ID de la tienda padre
variants : Variant []; // Variantes del producto
dateCreated : string ; // Marca de tiempo ISO 8601
}
Variantes
Cada producto tiene una o más variantes. Cada variante tiene su propio precio, stock y configuración:
interface Variant {
id : string ; // ID de la variante
name : string ; // Nombre de la variante
productId : string ; // ID del producto padre
storeId : string ; // ID de la tienda
cost : number ; // Precio en la moneda de la tienda
stock : number ; // Stock disponible
stockMode : number ; // Modo de cálculo de stock (ver abajo)
minimumQuantity : number ; // Cantidad mínima de compra (por defecto: 1)
maximumQuantity : number ; // Cantidad máxima de compra (-1 = ilimitada)
order : number ; // Orden de visualización
imageNames : string []; // Nombres de archivo de imágenes específicas de la variante
type : number ; // 0=Único, 1=Suscripción
subscriptionPeriod ?: string ; // Duración de la suscripción si aplica
requireDiscordAuthorization : boolean ;
dateCreated : string ;
}
Modo de cálculo de stock
El campo stockMode determina cómo se calcula la disponibilidad de stock:
Valor Modo Descripción 0 Calculado El stock se calcula automáticamente a partir de artículos disponibles 1 Ignorado El stock no se rastrea — siempre disponible 2 Fijo El stock se establece manualmente y se decrementa al comprar
Consulta el enum Stock Calculation Mode para más detalles.
Mostrar imágenes
Los imageNames de productos y variantes contienen nombres de archivo, no URLs completas. Consulta la página Images para saber cómo construir URLs de imagen completas.
Mostrar variantes
async function mostrarProducto ( productId ) {
const [ productResponse , formatter ] = await Promise . all ([
komerza . getProduct ( productId ),
komerza . createFormatter (),
]);
if ( ! productResponse . success ) return ;
const product = productResponse . data ;
// Ordenar variantes por orden
const variants = product . variants . sort (( a , b ) => a . order - b . order );
variants . forEach (( variant ) => {
const price = formatter . format ( variant . cost );
const inStock = variant . stockMode === 1 || variant . stock > 0 ;
console . log ( ` ${ variant . name } : ${ price } ` );
console . log ( ` Stock: ${ inStock ? "Disponible" : "Sin stock" } ` );
console . log ( ` Cant. mín: ${ variant . minimumQuantity } ` );
console . log (
` Cant. máx: ${
variant . maximumQuantity === - 1 ? "Ilimitada" : variant . maximumQuantity
} ` ,
);
});
}
Selección de variante
< select id = "variant-select" onchange = " updatePrice ()" >
<!-- Rellenado dinámicamente -->
</ select >
< span id = "price" ></ span >
< button onclick = " addToCart ()" > Añadir al carrito </ button >
< script >
let currentProduct ;
let formatter ;
async function loadProduct ( productId ) {
[{ data: currentProduct }, formatter ] = await Promise . all ([
komerza . getProduct ( productId ),
komerza . createFormatter (),
]);
const select = document . getElementById ( "variant-select" );
select . innerHTML = currentProduct . variants
. map (
( v ) =>
`<option value=" ${ v . id } "> ${ v . name } - ${ formatter . format (
v . cost ,
) } </option>` ,
)
. join ( "" );
updatePrice ();
}
function updatePrice () {
const variantId = document . getElementById ( "variant-select" ). value ;
const variant = currentProduct . variants . find (( v ) => v . id === variantId );
document . getElementById ( "price" ). textContent = formatter . format (
variant . cost ,
);
}
function addToCart () {
const variantId = document . getElementById ( "variant-select" ). value ;
komerza . addToBasket ( currentProduct . id , variantId );
}
</ script >
Reseñas del producto
Obtén reseñas paginadas para un producto:
const response = await komerza . getProductReviews ( productId , page );
Parámetros
Número de página (indexado desde 1)
Retorna
Retorna PaginatedApiResponse<Review>:
interface PaginatedApiResponse < Review > {
success : boolean ;
pages : number ; // Número total de páginas
data ?: Review []; // Array de reseñas
message ?: string ;
}
interface Review {
id : string ;
rating : number ; // 1-5 estrellas
reason : string ; // Texto de la reseña
productId : string ;
reply ?: string ; // Respuesta del comerciante si hay
dateCreated : string ;
}
Mostrar reseñas
async function mostrarResenas ( productId , page = 1 ) {
const response = await komerza . getProductReviews ( productId , page );
if ( ! response . success ) return ;
const container = document . getElementById ( "reviews" );
container . innerHTML = response . data
. map (
( review ) => `
<div class="review">
<div class="rating"> ${ "★" . repeat ( review . rating ) }${ "☆" . repeat (
5 - review . rating ,
) } </div>
<p> ${ review . reason } </p>
${
review . reply
? `<p class="reply"><strong>Respuesta:</strong> ${ review . reply } </p>`
: ""
}
<time> ${ new Date ( review . dateCreated ). toLocaleDateString () } </time>
</div>
` ,
)
. join ( "" );
// Paginación
if ( response . pages > 1 ) {
container . innerHTML += `
<div class="pagination">
${
page > 1
? `<button onclick="mostrarResenas(' ${ productId } ', ${
page - 1
} )">Anterior</button>`
: ""
}
<span>Página ${ page } de ${ response . pages } </span>
${
page < response . pages
? `<button onclick="mostrarResenas(' ${ productId } ', ${
page + 1
} )">Siguiente</button>`
: ""
}
</div>
` ;
}
}
Imágenes del producto
Las imágenes del producto se referencian por nombre de archivo. Construye la URL completa:
function getProductImageUrl ( storeId , productId , imageName ) {
return `https://cdn.komerza.com/stores/ ${ storeId } /products/ ${ productId } / ${ imageName } ` ;
}
// Uso
const product = response . data ;
const imageUrl = getProductImageUrl (
product . storeId ,
product . id ,
product . imageNames [ 0 ],
);
Galería de imágenes
function mostrarGaleriaImagenes ( product ) {
const gallery = document . getElementById ( "gallery" );
// Usar imágenes de variante si están disponibles, si no las del producto
const images =
product . variants [ 0 ]. imageNames . length > 0
? product . variants [ 0 ]. imageNames
: product . imageNames ;
gallery . innerHTML = images
. map (
( img ) => `
<img
src="https://cdn.komerza.com/stores/ ${ product . storeId } /products/ ${ product . id } / ${ img } "
alt=" ${ product . name } "
loading="lazy"
/>
` ,
)
. join ( "" );
}
Gestión de stock
Comprueba la disponibilidad de stock antes de añadir al carrito:
function puedeAnadirAlCarrito ( variant , quantity ) {
// stockMode 1 = Ignorado (ilimitado)
if ( variant . stockMode === 1 ) return true ;
// Comprobar stock disponible
if ( variant . stock < quantity ) return false ;
// Comprobar límites de cantidad
if ( quantity < variant . minimumQuantity ) return false ;
if ( variant . maximumQuantity !== - 1 && quantity > variant . maximumQuantity )
return false ;
return true ;
}
function getEstadoStock ( variant ) {
if ( variant . stockMode === 1 ) return "En stock" ;
if ( variant . stock === 0 ) return "Sin stock" ;
if ( variant . stock < 10 ) return `Solo quedan ${ variant . stock } ` ;
return "En stock" ;
}
Ejemplo completo
<! DOCTYPE html >
< html >
< head >
< title > Página de producto </ title >
< script src = "https://cdn.komerza.com/komerza.min.js" ></ script >
< style >
.product {
max-width : 600 px ;
margin : 0 auto ;
}
.gallery img {
max-width : 100 % ;
}
.variants {
margin : 20 px 0 ;
}
.reviews {
margin-top : 40 px ;
}
.review {
border-bottom : 1 px solid #eee ;
padding : 15 px 0 ;
}
.rating {
color : gold ;
}
</ style >
</ head >
< body >
< div class = "product" >
< div id = "gallery" ></ div >
< h1 id = "name" ></ h1 >
< p id = "description" ></ p >
< p id = "rating" ></ p >
< div class = "variants" >
< select id = "variant-select" ></ select >
< span id = "price" ></ span >
< span id = "stock" ></ span >
</ div >
< div >
< label
> Cantidad: < input type = "number" id = "quantity" value = "1" min = "1"
/></ label >
< button id = "add-btn" onclick = " addToCart ()" > Añadir al carrito </ button >
</ div >
< div class = "reviews" >
< h2 > Reseñas </ h2 >
< div id = "reviews" ></ div >
</ div >
</ div >
< script >
komerza . init ( "your-store-id" );
let product ;
let formatter ;
async function loadProduct ( idOrSlug ) {
const [ productResponse , fmt ] = await Promise . all ([
komerza . getProduct ( idOrSlug ),
komerza . createFormatter (),
]);
if ( ! productResponse . success ) {
alert ( "Producto no encontrado" );
return ;
}
product = productResponse . data ;
formatter = fmt ;
// Mostrar información del producto
document . getElementById ( "name" ). textContent = product . name ;
document . getElementById ( "description" ). textContent =
product . description ;
document . getElementById ( "rating" ). textContent =
`Valoración: ${ product . rating } ★` ;
// Mostrar imágenes
const images = product . imageNames ;
document . getElementById ( "gallery" ). innerHTML = images
. map (
( img ) =>
`<img src="https://cdn.komerza.com/stores/ ${ product . storeId } /products/ ${ product . id } / ${ img } " />` ,
)
. join ( "" );
// Poblar variantes
const select = document . getElementById ( "variant-select" );
select . innerHTML = product . variants
. map (( v ) => `<option value=" ${ v . id } "> ${ v . name } </option>` )
. join ( "" );
select . onchange = updateVariantDisplay ;
updateVariantDisplay ();
loadReviews ( 1 );
}
function updateVariantDisplay () {
const variantId = document . getElementById ( "variant-select" ). value ;
const variant = product . variants . find (( v ) => v . id === variantId );
document . getElementById ( "price" ). textContent = formatter . format (
variant . cost ,
);
// Estado del stock
let stockText = "En stock" ;
if ( variant . stockMode !== 1 ) {
if ( variant . stock === 0 ) stockText = "Sin stock" ;
else if ( variant . stock < 10 )
stockText = `Solo quedan ${ variant . stock } ` ;
}
document . getElementById ( "stock" ). textContent = stockText ;
// Actualizar límites de cantidad
const qtyInput = document . getElementById ( "quantity" );
qtyInput . min = variant . minimumQuantity ;
qtyInput . max =
variant . maximumQuantity === - 1 ? 999 : variant . maximumQuantity ;
qtyInput . value = variant . minimumQuantity ;
// Deshabilitar botón si sin stock
document . getElementById ( "add-btn" ). disabled =
variant . stockMode !== 1 && variant . stock === 0 ;
}
function addToCart () {
const variantId = document . getElementById ( "variant-select" ). value ;
const quantity = parseInt ( document . getElementById ( "quantity" ). value );
komerza . addToBasket ( product . id , variantId , quantity );
alert ( "¡Añadido al carrito!" );
}
async function loadReviews ( page ) {
const response = await komerza . getProductReviews ( product . id , page );
if ( ! response . success || response . data . length === 0 ) {
document . getElementById ( "reviews" ). innerHTML =
"<p>Sin reseñas aún</p>" ;
return ;
}
document . getElementById ( "reviews" ). innerHTML = response . data
. map (
( review ) => `
<div class="review">
<div class="rating"> ${ "★" . repeat ( review . rating ) }${ "☆" . repeat (
5 - review . rating ,
) } </div>
<p> ${ review . reason } </p>
${ review . reply ? `<p><em>Respuesta: ${ review . reply } </em></p>` : "" }
</div>
` ,
)
. join ( "" );
}
// Cargar producto desde URL o por defecto
const urlParams = new URLSearchParams ( window . location . search );
const productId = urlParams . get ( "product" ) || "your-default-product-slug" ;
loadProduct ( productId );
</ script >
</ body >
</ html >
Próximos pasos
Formato de moneda Formatea precios en la moneda de tu tienda
Gestión del carrito Añade productos al carrito