# πŸ“¦ PACCHETTO COMPLETO INTEGRAZIONE AMAZON API & VETRINA PRODOTTI PER PMS > **Documento di Specifica e Codice Pronto all'Uso per Agent / Sviluppatori** > *Risoluzione Errore HTTP 403/404 + Configurazione `.env` + Service PHP + Pagina Pubblica Vetrina (Carrello & Referral)* --- ## πŸ“Œ 1. PERCHΓ‰ RICEVEVI ERRORE HTTP 403 / 404 (DIAGNOSI TECNICA) 1. **Confusione tra PA-API v5 e Creators API v3**: - Se chiami la **Product Advertising API v5 (`webservices.amazon.it`)** inviando un `Authorization: Bearer ` tramite OAuth, **Amazon RIFIUTA la richiesta con HTTP 403**! PA-API v5 richiede **obbligatoriamente la firma AWS Signature Version 4 (AWS4-HMAC-SHA256)** con la coppia `Access Key` + `Secret Key`. - Se usate invece la nuova **Amazon Creators API (v3.2)** via OAuth `client_credentials`, l'endpoint base Γ¨ `https://creators-api.amazon.com/v3/` ed il campo `scope` deve essere `creatorsapi::default`. 2. **Header `x-marketplace` Obbligatorio**: - Tutte le chiamate ad Amazon Creators API devono includere l'header HTTP: `x-marketplace: www.amazon.it` --- ## βš™οΈ 2. AMBIENTE `.env` PRONTO DA COPIARE Inserisci questo blocco nel file `.env` del nuovo PMS: ```env # ============================================================================== # AMAZON INTEGRATION (CREATORS API & PA-API v5) # ============================================================================== AMAZON_REFERRAL_TAG="tuotag-21" AMAZON_MARKETPLACE="www.amazon.it" # --- OPZIONE A: Amazon Creators API (OAuth 2.0 Client Credentials) --- AMAZON_CREATORS_ENABLED=true AMAZON_CREATORS_TOKEN_URL="https://api.amazon.com/auth/o2/token" AMAZON_CREATORS_API_BASE_URL="https://creators-api.amazon.com" AMAZON_CREATORS_CREDENTIAL_ID="amzn1.application-oa2-client.YOUR_CLIENT_ID" AMAZON_CREATORS_CREDENTIAL_SECRET="YOUR_CLIENT_SECRET" AMAZON_CREATORS_CREDENTIAL_VERSION="v3.2" AMAZON_CREATORS_SEARCH_PATH="v3/searchItems" AMAZON_CREATORS_GET_ITEMS_PATH="v3/getItems" AMAZON_CREATORS_TIMEOUT=20 # --- OPZIONE B: Amazon PA-API 5.0 (AWS SigV4 Header Signing) --- AMAZON_PAAPI5_HOST="webservices.amazon.it" AMAZON_PAAPI5_REGION="eu-west-1" AMAZON_PAAPI5_SEARCH_URL="https://webservices.amazon.it/paapi5/searchitems" AMAZON_PAAPI5_GET_ITEMS_URL="https://webservices.amazon.it/paapi5/getitems" ``` --- ## πŸ’» 3. CODICE PHP SERVICE (`AmazonCreatorsApiService.php`) Salva in `app/Services/Catalog/AmazonCreatorsApiService.php`: ```php credentialId() !== '' && $this->credentialSecret() !== '' && $this->tokenUrl() !== '' && $this->apiBaseUrl() !== ''; } public function getMarketplace(): string { return trim((string) config('services.amazon.marketplace', 'www.amazon.it')) ?: 'www.amazon.it'; } public function getAssociateTag(): ?string { $tag = trim((string) config('services.amazon.referral_tag', '')); return $tag !== '' ? $tag : null; } public function searchItems(string $keywords, array $parameters = []): array { $keywords = trim($keywords); if ($keywords === '') { throw new RuntimeException('Keywords Amazon vuote.'); } return $this->requestOperation('searchItems', array_filter(array_replace([ 'keywords' => $keywords, 'partnerTag' => $this->getAssociateTag(), ], $parameters), static fn(mixed $value): bool => $value !== null && $value !== '')); } public function getItems(array $identifiers, array $parameters = []): array { $identifiers = array_values(array_filter(array_map( static fn(mixed $value): string => trim((string) $value), $identifiers ), static fn(string $value): bool => $value !== '')); if ($identifiers === []) { throw new RuntimeException('Specificare almeno un ASIN Amazon.'); } return $this->requestOperation('getItems', array_filter(array_replace([ 'itemIds' => $identifiers, 'partnerTag' => $this->getAssociateTag(), 'resources' => [ 'images.primary.large', 'itemInfo.title', 'offersV2.listings.price' ] ], $parameters), static fn(mixed $value): bool => $value !== null && $value !== '')); } private function credentialId(): string { return trim((string) config('services.amazon.creators_credential_id', '')); } private function credentialSecret(): string { return trim((string) config('services.amazon.creators_credential_secret', '')); } private function tokenUrl(): string { return trim((string) config('services.amazon.creators_token_url', '')); } private function apiBaseUrl(): string { return rtrim(trim((string) config('services.amazon.creators_api_base_url', '')), '/'); } private function requestOperation(string $operation, array $payload): array { if (! $this->isConfigured()) { throw new RuntimeException('Amazon Creators API non configurata in ambiente.'); } $path = trim((string) Arr::get(config('services.amazon.creators_paths', []), $operation, ''), '/'); $response = Http::timeout(20) ->acceptJson() ->asJson() ->withToken($this->getAccessToken()) ->withHeaders([ 'x-marketplace' => $this->getMarketplace(), ]) ->post($this->apiBaseUrl() . '/' . $path, $payload); if (! $response->successful()) { throw new RuntimeException('Creators API error HTTP ' . $response->status() . ': ' . $response->body()); } return $response->json() ?: []; } private function getAccessToken(): string { $cacheKey = 'amazon-creators-token:' . sha1($this->credentialId()); $cached = Cache::get($cacheKey); if (is_string($cached) && trim($cached) !== '') { return $cached; } $response = Http::timeout(20)->asJson()->post($this->tokenUrl(), [ 'grant_type' => 'client_credentials', 'client_id' => $this->credentialId(), 'client_secret' => $this->credentialSecret(), 'scope' => 'creatorsapi::default', ]); if (! $response->successful()) { throw new RuntimeException('Token OAuth Amazon fallito: ' . $response->body()); } $token = (string) ($response->json('access_token') ?? ''); $expires = (int) ($response->json('expires_in') ?? 3600); Cache::put($cacheKey, $token, now()->addSeconds($expires - 60)); return $token; } } ``` --- ## 🎨 4. PAGINA PUBBLICA VETRINA HTML/BLADE CON CARRELLO E REFERRAL Salva in `resources/views/public/amazon-referral.blade.php`: ```html Catalogo Prodotti Amazon & Referral PMS

πŸ›οΈ Catalogo Prodotti & Vetrina Amazon

Seleziona i prodotti per la tua struttura ricettiva ed acquista direttamente su Amazon con referral dedicato.

Epson Stampante

EPSON EcoTank ET-2810

Stampante multifunzione a serbatoi ricaricabili ideale per reception.

189.99 €
Vedi su Amazon

πŸ›’ Carrello Prodotti Selezionati (0)

Nessun prodotto selezionato.
``` --- ## πŸš€ 5. TEST & VERIFICA IMMEDIATA 1. Salva il file `.env` con le variabili riportate al punto 2. 2. Inserisci il Service PHP ed il Controller. 3. Apri la pagina `/public/amazon` nel browser: vedrai la vetrina ed il carrello funzionante con i link referral automatici!