PDO::ERRMODE_EXCEPTION]); $s = $pdo->prepare('SELECT setting_key, setting_value FROM app_settings WHERE setting_key LIKE ?'); $s->execute(['gs1_%']); $cfg = []; foreach ($s->fetchAll(PDO::FETCH_ASSOC) as $r) $cfg[$r['setting_key']] = $r['setting_value']; } catch (Throwable $e) { die('DB: ' . $e->getMessage()); } $login = $cfg['gs1_api_login'] ?? ''; $password = $cfg['gs1_api_password'] ?? ''; if ($login === '' || $password === '') die("Brak credentials\n"); function gs1v(string $method, string $url, ?string $body, string $login, string $pw, array $extraHeaders = []): array { $curl = curl_init($url); $h = ['Accept: application/json']; if ($body !== null) $h[] = 'Content-Type: application/json'; $h = array_merge($h, $extraHeaders); curl_setopt_array($curl, [ CURLOPT_RETURNTRANSFER => true, CURLOPT_HTTPHEADER => $h, CURLOPT_USERPWD => $login . ':' . $pw, CURLOPT_HTTPAUTH => CURLAUTH_BASIC, CURLOPT_TIMEOUT => 30, CURLOPT_SSL_VERIFYPEER => true, CURLOPT_SSL_VERIFYHOST => 2, CURLOPT_CUSTOMREQUEST => $method, CURLOPT_VERBOSE => true, ]); // Capture verbose output $verbose = fopen('php://temp', 'w+'); curl_setopt($curl, CURLOPT_STDERR, $verbose); if ($body !== null) curl_setopt($curl, CURLOPT_POSTFIELDS, $body); $resp = curl_exec($curl); $code = (int) curl_getinfo($curl, CURLINFO_RESPONSE_CODE); curl_close($curl); rewind($verbose); $verboseLog = stream_get_contents($verbose); fclose($verbose); return [$code, is_string($resp) ? $resp : '', $verboseLog]; } $base = 'https://mojegs1.pl/api/v2'; $jf = JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES; echo "=== GS1 Diagnostic v4 ===\n\n"; // Step 1: GET existing product echo "--- Step 1: GET existing product ---\n"; [$c, $b, $v] = gs1v('GET', $base . '/products?page[offset]=1&page[limit]=1', null, $login, $password); $d = json_decode($b, true); $existing = $d['data'][0] ?? null; if (!$existing) die("Nie mozna pobrac produktu\n"); $exGtin = $existing['id']; $exAttrs = $existing['attributes']; echo "GTIN: {$exGtin}\n"; echo "Status: {$exAttrs['status']}\n\n"; // Step 2: Verbose PUT - minimal + subBrandName + name echo "--- Step 2: Verbose PUT (minimal + name + subBrandName) ---\n"; $attrs2 = [ 'brandName' => $exAttrs['brandName'], 'subBrandName' => $exAttrs['brandName'], 'commonName' => $exAttrs['commonName'], 'name' => $exAttrs['name'] ?? ($exAttrs['brandName'] . ' ' . $exAttrs['commonName']), 'gpcCode' => $exAttrs['gpcCode'], 'netContent' => $exAttrs['netContent'], 'netContentUnit' => $exAttrs['netContentUnit'], 'status' => $exAttrs['status'], 'targetMarket' => $exAttrs['targetMarket'], 'descriptionLanguage' => $exAttrs['descriptionLanguage'], ]; $payload2 = json_encode(['data' => ['type' => 'products', 'id' => $exGtin, 'attributes' => $attrs2]], $jf); echo "REQ: {$payload2}\n"; [$c, $b, $v] = gs1v('PUT', $base . '/products/' . $exGtin, $payload2, $login, $password); echo "HTTP {$c}: {$b}\n"; echo "VERBOSE:\n{$v}\n\n"; // Step 3: Try PATCH instead of PUT echo "--- Step 3: PATCH instead of PUT ---\n"; [$c, $b, $v] = gs1v('PATCH', $base . '/products/' . $exGtin, $payload2, $login, $password); echo "HTTP {$c}: {$b}\n\n"; // Step 4: Try gpcCode as string echo "--- Step 4: gpcCode as string ---\n"; $attrs4 = $attrs2; $attrs4['gpcCode'] = (string) $attrs4['gpcCode']; $payload4 = json_encode(['data' => ['type' => 'products', 'id' => $exGtin, 'attributes' => $attrs4]], $jf); echo "REQ: {$payload4}\n"; [$c, $b, $v] = gs1v('PUT', $base . '/products/' . $exGtin, $payload4, $login, $password); echo "HTTP {$c}: {$b}\n\n"; // Step 5: Try application/vnd.api+json for both Content-Type and Accept echo "--- Step 5: vnd.api+json content type ---\n"; $curl5 = curl_init($base . '/products/' . $exGtin); curl_setopt_array($curl5, [ CURLOPT_RETURNTRANSFER => true, CURLOPT_HTTPHEADER => ['Content-Type: application/vnd.api+json', 'Accept: application/vnd.api+json'], CURLOPT_USERPWD => $login . ':' . $password, CURLOPT_HTTPAUTH => CURLAUTH_BASIC, CURLOPT_TIMEOUT => 30, CURLOPT_SSL_VERIFYPEER => true, CURLOPT_SSL_VERIFYHOST => 2, CURLOPT_CUSTOMREQUEST => 'PUT', CURLOPT_POSTFIELDS => $payload2, ]); $resp5 = curl_exec($curl5); $code5 = (int) curl_getinfo($curl5, CURLINFO_RESPONSE_CODE); curl_close($curl5); echo "HTTP {$code5}: {$resp5}\n\n"; // Step 6: Try with netContent as float explicitly echo "--- Step 6: netContent as float 1.0 ---\n"; $attrs6 = $attrs2; $attrs6['netContent'] = 1.0; $payload6 = json_encode(['data' => ['type' => 'products', 'id' => $exGtin, 'attributes' => $attrs6]], $jf); // Force 1.0 in JSON (json_encode may output 1 for 1.0) $payload6 = str_replace('"netContent":1,', '"netContent":1.0,', $payload6); echo "REQ: {$payload6}\n"; [$c, $b, $v] = gs1v('PUT', $base . '/products/' . $exGtin, $payload6, $login, $password); echo "HTTP {$c}: {$b}\n\n"; // Step 7: Try completely empty attributes echo "--- Step 7: Empty attributes ---\n"; $payload7 = json_encode(['data' => ['type' => 'products', 'id' => $exGtin, 'attributes' => new \stdClass()]], $jf); echo "REQ: {$payload7}\n"; [$c, $b, $v] = gs1v('PUT', $base . '/products/' . $exGtin, $payload7, $login, $password); echo "HTTP {$c}: {$b}\n\n"; // Step 8: Binary search - ONE field at a time echo "--- Step 8: Single field tests ---\n"; $singleFields = [ 'brandName' => $exAttrs['brandName'], 'commonName' => $exAttrs['commonName'], 'gpcCode' => $exAttrs['gpcCode'], 'netContent' => $exAttrs['netContent'], 'netContentUnit' => $exAttrs['netContentUnit'], 'status' => $exAttrs['status'], 'targetMarket' => $exAttrs['targetMarket'], 'descriptionLanguage' => $exAttrs['descriptionLanguage'], ]; foreach ($singleFields as $key => $val) { $p = json_encode(['data' => ['type' => 'products', 'id' => $exGtin, 'attributes' => [$key => $val]]], $jf); [$c, $b, $v] = gs1v('PUT', $base . '/products/' . $exGtin, $p, $login, $password); echo " {$key} => HTTP {$c}\n"; } echo "\n=== DONE ===\n";