Generator modeli 3D
Endpointy importu generatora obsługują wyłącznie odczyt w komunikacji między serwerami. Wymagają standardowych nagłówków API, uprawnienia embed:session:create i aktywnego planu. Autoryzacja importu nie tworzy sesji edytora i nie zużywa jej miesięcznego limitu. Otwarcie edytora korzysta z tego samego licznika monthlyEmbedTokenLimit co pozostałe osadzone narzędzia.
Wyszukiwanie i import modeli z generatorem
Użyj /model-generator/models, aby wyświetlić dostępne modele z generatorami. Deskryptor generator wskazuje konkretne projectId, revision, configurationId, templateRevision, productId i productModel3dId. Pobierz dokładnie tę rewizję źródłową przez jego importPath. Manifesty assetów produktowych udostępniają również generators oraz deskryptor generator dla każdego modelu. Templatki można importować oddzielnie według konfiguracji i rewizji.
Filtry katalogów
| Endpoint | Szczegóły |
|---|---|
/model-generator/models | Lista modeli: name (lub q), categoryId, scope (all, own, global), limit (1-50) i offset. |
/model-generator/catalog | Katalog templatek: generatorType, productId, audience, q, templateKey, configurationId, limit i offset. |
/model-generator/projects | Lista projektów: configurationId, q, scope (all, own, global), limit i offset. Publiczny proxy domyślnie ustawia scope na all. |
/model-generator/image-libraries/:kind/assets | Biblioteki tekstur i teł: kind to texture lub background; q, category i mapType filtrują dostępne zasoby. |
Import projektu zawiera document, revision, template oraz manifest files. Każdy plik podaje path w przestrzeni /v1/model-generator/; podczas pobierania z Alter Product dodaj przed nim /public-api. Skopiuj wymagane pliki do własnego storage i zastąp odwołania źródłowe lokalnymi. Manekiny i biblioteki tekstur importuj przez ich endpointy katalogowe; public-files dopuszcza wyłącznie dozwolone ścieżki zasobów, a templatki podlegają kontroli dostępu do konfiguracji i rewizji.
Przykładowe zapytanie (fetch)
// Server-side: uses alterFetch and authHeaders from the API connection guide.
const catalog = await alterFetch('/model-generator/models?' + new URLSearchParams({
scope: 'all', limit: '24', offset: '0'
}));
const selected = catalog.items[0];
if (!selected?.generator) throw new Error('Select an available generator model');
const importPath = selected.generator.importPath;
if (!importPath.startsWith('/v1/model-generator/projects/')) {
throw new Error('Invalid generator import path');
}
const bundle = await alterFetch(importPath.slice('/v1'.length));
for (const file of bundle.files) {
if (!file.path.startsWith('/v1/model-generator/')) {
throw new Error('Invalid generator file path');
}
const response = await fetch('https://alterproduct.com/public-api' + file.path, {
headers: authHeaders,
redirect: 'error'
});
if (!response.ok) throw new Error(`File download failed: ${response.status}`);
const bytes = new Uint8Array(await response.arrayBuffer());
// Persist bytes in your local storage; record the mapping from
// file.sourceHref / file.href to the resulting local file reference.
}
// Persist bundle.document, bundle.template and revision metadata locally.
// Import the related product asset and its textures/mockups as needed:
const product = await alterFetch('/assets/products/' + selected.generator.productId);
const mannequins = await alterFetch('/model-generator/mannequins');
console.log({ product, mannequins });Sesja edytora i lokalny zapis
Utwórz sesję edytora z tool: model-generator, dodatnim liczbowym toolId lokalnego projektu generatora (nie jego UUID ani ID produktu WooCommerce) i dozwolonym origin sklepu. Dla tego narzędzia nie przekazuj designId, orderId, runtimeBindingId ani pól koszyka. UUID projektu generatora jest oddzielnym identyfikatorem. Przekaż zwrócony token przez handshake iframe; runtime bootstrap zwraca kontekst generatora ze storageMode: wordpress_local.
// Server-side, after authorizing the merchant's access to this local project.
const localProjectId = 42; // Local generator project ID, not its UUID or WC product ID.
const session = await alterFetch('/embed/session', {
method: 'POST',
body: JSON.stringify({
tool: 'model-generator',
toolId: localProjectId,
origin: 'https://yourstore.com'
})
});
// The iframe receives session.token through ALTER_CUSTOMIZER_SESSION_READY.
// Do not put API credentials or the token in the iframe URL.
const bootstrapResponse = await fetch('https://alterproduct.com/public-api/v1/runtime/bootstrap', {
headers: { Authorization: `Bearer ${session.token}` }
});
if (!bootstrapResponse.ok) throw new Error('Generator bootstrap failed');
const context = await bootstrapResponse.json();
console.log(context);Przykładowa odpowiedź
{
"runtimeBindingId": null,
"designId": null,
"productId": 42,
"toolId": 42,
"runtimeType": "model-generator",
"storageMode": "wordpress_local",
"parentOrigin": "https://yourstore.com"
}// Host page: WordPress returns a numeric toolId and a UUID in id.
const url = new URL('https://alterproduct.com/app/model-generator');
url.search = new URLSearchParams({
embedded: '1',
lng: 'en',
parentOrigin: window.location.origin,
toolId: String(localProject.toolId),
serverProjectId: localProject.id
}).toString();
// Optional: serverProjectRevision pins an existing saved revision.
iframe.src = url.toString();
// Install the authenticated handshake and storage bridge described below.
// Setting iframe.src alone does not authorize the editor or provide storage.Wiadomości iframe używane przez wtyczkę WordPress
Wtyczka WordPress obsługuje komunikację z lokalnym storage i sprawdza uprawnienia administratora lub menedżera WooCommerce. Weryfikuje origin iframe, okno źródłowe, nonce, identyfikator żądania i dozwolone ścieżki projektu. Lokalne odczyty i zapisy kieruje do /wp-json/alter-wc/v1/model-generator. Dane dostępowe API pozostają na serwerze. Własna integracja musi zapewniać równoważną, uwierzytelnioną obsługę zapisu; publiczne API generatora nie zapisuje projektów na Alter Product.
| Typ | Opis |
|---|---|
ALTER_CHILD_HELLO / ALTER_PARENT_ACK | Iframe rozpoczyna handshake z nonce; strona nadrzędna potwierdza ten sam nonce. |
ALTER_CUSTOMIZER_INIT_SESSION / ALTER_CUSTOMIZER_SESSION_READY | Iframe żąda sesji edycji model-generator; strona nadrzędna zwraca autoryzowany token. |
ALTER_MODEL_GENERATOR_REQUEST | Iframe wysyła requestId, nonce i request zawierający method, path, data oraz responseType. |
ALTER_MODEL_GENERATOR_RESPONSE | Strona nadrzędna odpowiada tym samym requestId i nonce oraz polami status, data, headers i ewentualnym error. |
// Messages after ALTER_CHILD_HELLO / ALTER_PARENT_ACK agree on the nonce.
// Iframe -> parent:
const sessionRequest = {
type: 'ALTER_CUSTOMIZER_INIT_SESSION',
nonce: handshakeNonce,
payload: {
tool: 'model-generator', alterProductId: localProject.toolId, mode: 'edit'
}
};
// Parent -> iframe, after the server authorizes the merchant and issues a token:
const sessionReady = {
type: 'ALTER_CUSTOMIZER_SESSION_READY',
nonce: handshakeNonce,
token: session.token,
tool: 'model-generator',
cartKey: `model-generator:${localProject.id}`,
mode: 'edit',
localSession: false,
adminSession: true
};
// Send only to the validated iframe's exact origin and source window.
// An authorized token and successful bootstrap are still required.Zapis przekazuje expectedRevision, templateRevision, document i odwołania do artefaktów. Tworzy niezmienną rewizję; nieaktualne expectedRevision zwraca HTTP 409. WordPress przechowuje metadane w swojej bazie, a pliki w katalogu uploads. JSON jest minifikowany i kompresowany gzip, jeśli kompresja zmniejsza jego rozmiar.
// Example message from the iframe; savedSnapshot and artifact IDs come
// from the generator. The host checks origin/source/nonce/project permissions.
const message = {
type: 'ALTER_MODEL_GENERATOR_REQUEST',
requestId: crypto.randomUUID(),
nonce: handshakeNonce,
request: {
method: 'POST',
path: `/pattern-generator/projects/${projectUuid}/revisions`,
data: {
expectedRevision: loadedRevision,
name: projectName,
templateRevision,
document: savedSnapshot,
references: { artifactIds: savedArtifactIds }
},
responseType: 'json'
}
};Akcja „Użyj zapisanego modelu w projekcie” publikuje kompletną zapisaną rewizję do powiązanego projektu produktu. Klienci widzą ją następnie w istniejącym Customizerze, Configuratorze lub Viewerze, z zachowaniem zwykłych powiązań produktu i kontroli subskrypcji. Edytor generatora pozostaje narzędziem sprzedawcy. Odnośniki zamówień zachowują zapisany projekt i rewizję, więc późniejsze edycje nie zmieniają automatycznie wcześniejszych zamówień.