Enable Discovery debug logging for production troubleshooting

- Add DISCOVERY_LOG_LEVEL=debug
- Add DISCOVERY_SHOW_PROGRESS=true
- Temporary changes for debugging InitializerProcessor fixes on production
This commit is contained in:
2025-08-11 20:13:26 +02:00
parent 59fd3dd3b1
commit 55a330b223
3683 changed files with 2956207 additions and 16948 deletions

View File

@@ -1,4 +1,5 @@
<?php
declare(strict_types=1);
namespace App\Application\Shopify;
@@ -33,21 +34,22 @@ final class CustomerController
try {
$options = [
'limit' => 50,
'fields' => 'id,email,first_name,last_name,orders_count,total_spent'
'fields' => 'id,email,first_name,last_name,orders_count,total_spent',
];
$customers = $this->client->getCustomers($options);
return new JsonResult([
'success' => true,
'data' => $customers
'data' => $customers,
]);
} catch (ApiException $e) {
$result = new JsonResult([
'success' => false,
'error' => $e->getMessage()
'error' => $e->getMessage(),
]);
$result->status = Status::from($e->getCode() ?: 500);
return $result;
}
}
@@ -63,14 +65,15 @@ final class CustomerController
return new JsonResult([
'success' => true,
'data' => $customer
'data' => $customer,
]);
} catch (ApiException $e) {
$result = new JsonResult([
'success' => false,
'error' => $e->getMessage()
'error' => $e->getMessage(),
]);
$result->status = Status::from($e->getCode() ?: 500);
return $result;
}
}
@@ -91,26 +94,28 @@ final class CustomerController
'addresses' => $request->addresses ?? [],
'password' => $request->password ?? null,
'password_confirmation' => $request->password ?? null,
'send_email_welcome' => $request->sendWelcomeEmail ?? false
'send_email_welcome' => $request->sendWelcomeEmail ?? false,
];
// Entferne leere Felder
$customerData = array_filter($customerData, fn($value) => $value !== null);
$customerData = array_filter($customerData, fn ($value) => $value !== null);
$customer = $this->client->createCustomer($customerData);
$result = new JsonResult([
'success' => true,
'data' => $customer
'data' => $customer,
]);
$result->status = Status::CREATED;
return $result;
} catch (ApiException $e) {
$result = new JsonResult([
'success' => false,
'error' => $e->getMessage()
'error' => $e->getMessage(),
]);
$result->status = Status::from($e->getCode() ?: 500);
return $result;
}
}

View File

@@ -1,4 +1,5 @@
<?php
declare(strict_types=1);
namespace App\Application\Shopify;
@@ -11,8 +12,10 @@ final readonly class CustomerRequest
public string $email,
public ?string $phone = null,
public ?bool $verifiedEmail = null,
/** @var array<string, mixed>|null */
public ?array $addresses = null,
public ?string $password = null,
public ?bool $sendWelcomeEmail = null
) {}
) {
}
}

View File

@@ -1,4 +1,5 @@
<?php
declare(strict_types=1);
namespace App\Application\Shopify;
@@ -34,21 +35,22 @@ final class OrderController
$options = [
'limit' => 50,
'status' => 'any',
'fields' => 'id,order_number,customer,total_price,created_at,financial_status'
'fields' => 'id,order_number,customer,total_price,created_at,financial_status',
];
$orders = $this->client->getOrders($options);
return new JsonResult([
'success' => true,
'data' => $orders
'data' => $orders,
]);
} catch (ApiException $e) {
$result = new JsonResult([
'success' => false,
'error' => $e->getMessage()
'error' => $e->getMessage(),
]);
$result->status = Status::from($e->getCode() ?: 500);
return $result;
}
}
@@ -64,14 +66,15 @@ final class OrderController
return new JsonResult([
'success' => true,
'data' => $order
'data' => $order,
]);
} catch (ApiException $e) {
$result = new JsonResult([
'success' => false,
'error' => $e->getMessage()
'error' => $e->getMessage(),
]);
$result->status = Status::from($e->getCode() ?: 500);
return $result;
}
}
@@ -92,26 +95,28 @@ final class OrderController
'fulfillment_status' => $request->fulfillmentStatus ?? null,
'tags' => $request->tags ?? '',
'note' => $request->note ?? null,
'email' => $request->email ?? null
'email' => $request->email ?? null,
];
// Entferne leere Felder
$orderData = array_filter($orderData, fn($value) => $value !== null);
$orderData = array_filter($orderData, fn ($value) => $value !== null);
$order = $this->client->createOrder($orderData);
$result = new JsonResult([
'success' => true,
'data' => $order
'data' => $order,
]);
$result->status = Status::CREATED;
return $result;
} catch (ApiException $e) {
$result = new JsonResult([
'success' => false,
'error' => $e->getMessage()
'error' => $e->getMessage(),
]);
$result->status = Status::from($e->getCode() ?: 500);
return $result;
}
}

View File

@@ -1,4 +1,5 @@
<?php
declare(strict_types=1);
namespace App\Application\Shopify;
@@ -6,14 +7,19 @@ namespace App\Application\Shopify;
final class OrderRequest
{
public function __construct(
/** @var array<int, array<string, mixed>> */
public readonly array $lineItems,
/** @var array<string, mixed>|null */
public readonly ?array $customer = null,
/** @var array<string, mixed>|null */
public readonly ?array $shippingAddress = null,
/** @var array<string, mixed>|null */
public readonly ?array $billingAddress = null,
public readonly ?string $financialStatus = null,
public readonly ?string $fulfillmentStatus = null,
public readonly ?string $tags = null,
public readonly ?string $note = null,
public readonly ?string $email = null
) {}
) {
}
}

View File

@@ -1,4 +1,5 @@
<?php
declare(strict_types=1);
namespace App\Application\Shopify;
@@ -33,21 +34,22 @@ final class ProductController
try {
$options = [
'limit' => 50,
'fields' => 'id,title,variants,images,status,published_at'
'fields' => 'id,title,variants,images,status,published_at',
];
$products = $this->client->getProducts($options);
return new JsonResult([
'success' => true,
'data' => $products
'data' => $products,
]);
} catch (ApiException $e) {
$result = new JsonResult([
'success' => false,
'error' => $e->getMessage()
'error' => $e->getMessage(),
]);
$result->status = Status::from($e->getCode() ?: 500);
return $result;
}
}
@@ -63,14 +65,15 @@ final class ProductController
return new JsonResult([
'success' => true,
'data' => $product
'data' => $product,
]);
} catch (ApiException $e) {
$result = new JsonResult([
'success' => false,
'error' => $e->getMessage()
'error' => $e->getMessage(),
]);
$result->status = Status::from($e->getCode() ?: 500);
return $result;
}
}
@@ -90,21 +93,23 @@ final class ProductController
'tags' => $request->tags ?? '',
'variants' => $request->variants ?? [],
'options' => $request->options ?? [],
'images' => $request->images ?? []
'images' => $request->images ?? [],
]);
$result = new JsonResult([
'success' => true,
'data' => $product
'data' => $product,
]);
$result->status = Status::CREATED;
return $result;
} catch (ApiException $e) {
$result = new JsonResult([
'success' => false,
'error' => $e->getMessage()
'error' => $e->getMessage(),
]);
$result->status = Status::from($e->getCode() ?: 500);
return $result;
}
}
@@ -119,27 +124,44 @@ final class ProductController
$productData = [];
// Nur die Felder aktualisieren, die tatsächlich im Request enthalten sind
if (isset($request->title)) $productData['title'] = $request->title;
if (isset($request->description)) $productData['body_html'] = $request->description;
if (isset($request->vendor)) $productData['vendor'] = $request->vendor;
if (isset($request->productType)) $productData['product_type'] = $request->productType;
if (isset($request->tags)) $productData['tags'] = $request->tags;
if (isset($request->variants)) $productData['variants'] = $request->variants;
if (isset($request->options)) $productData['options'] = $request->options;
if (isset($request->images)) $productData['images'] = $request->images;
if (isset($request->title)) {
$productData['title'] = $request->title;
}
if (isset($request->description)) {
$productData['body_html'] = $request->description;
}
if (isset($request->vendor)) {
$productData['vendor'] = $request->vendor;
}
if (isset($request->productType)) {
$productData['product_type'] = $request->productType;
}
if (isset($request->tags)) {
$productData['tags'] = $request->tags;
}
if (isset($request->variants)) {
$productData['variants'] = $request->variants;
}
if (isset($request->options)) {
$productData['options'] = $request->options;
}
if (isset($request->images)) {
$productData['images'] = $request->images;
}
$product = $this->client->updateProduct($id, $productData);
return new JsonResult([
'success' => true,
'data' => $product
'data' => $product,
]);
} catch (ApiException $e) {
$result = new JsonResult([
'success' => false,
'error' => $e->getMessage()
'error' => $e->getMessage(),
]);
$result->status = Status::from($e->getCode() ?: 500);
return $result;
}
}
@@ -155,14 +177,15 @@ final class ProductController
return new JsonResult([
'success' => $success,
'message' => $success ? 'Produkt erfolgreich gelöscht' : 'Produkt konnte nicht gelöscht werden'
'message' => $success ? 'Produkt erfolgreich gelöscht' : 'Produkt konnte nicht gelöscht werden',
]);
} catch (ApiException $e) {
$result = new JsonResult([
'success' => false,
'error' => $e->getMessage()
'error' => $e->getMessage(),
]);
$result->status = Status::from($e->getCode() ?: 500);
return $result;
}
}
@@ -178,14 +201,15 @@ final class ProductController
return new JsonResult([
'success' => true,
'data' => $products
'data' => $products,
]);
} catch (ApiException $e) {
$result = new JsonResult([
'success' => false,
'error' => $e->getMessage()
'error' => $e->getMessage(),
]);
$result->status = Status::from($e->getCode() ?: 500);
return $result;
}
}

View File

@@ -1,4 +1,5 @@
<?php
declare(strict_types=1);
namespace App\Application\Shopify;
@@ -14,5 +15,6 @@ final class ProductRequest
public readonly ?array $variants = null,
public readonly ?array $options = null,
public readonly ?array $images = null
) {}
) {
}
}

View File

@@ -1,4 +1,5 @@
<?php
declare(strict_types=1);
namespace App\Application\Shopify;
@@ -35,14 +36,15 @@ final class ShopController
return new JsonResult([
'success' => true,
'data' => $shopInfo
'data' => $shopInfo,
]);
} catch (ApiException $e) {
$result = new JsonResult([
'success' => false,
'error' => $e->getMessage()
'error' => $e->getMessage(),
]);
$result->status = Status::from($e->getCode() ?: 500);
return $result;
}
}
@@ -58,14 +60,15 @@ final class ShopController
return new JsonResult([
'success' => true,
'data' => $webhooks
'data' => $webhooks,
]);
} catch (ApiException $e) {
$result = new JsonResult([
'success' => false,
'error' => $e->getMessage()
'error' => $e->getMessage(),
]);
$result->status = Status::from($e->getCode() ?: 500);
return $result;
}
}
@@ -85,16 +88,18 @@ final class ShopController
$result = new JsonResult([
'success' => true,
'data' => $webhook
'data' => $webhook,
]);
$result->status = Status::CREATED;
return $result;
} catch (ApiException $e) {
$result = new JsonResult([
'success' => false,
'error' => $e->getMessage()
'error' => $e->getMessage(),
]);
$result->status = Status::from($e->getCode() ?: 500);
return $result;
}
}

View File

@@ -1,9 +1,11 @@
<?php
declare(strict_types=1);
namespace App\Application\Shopify;
use App\Framework\Attributes\Route;
use App\Framework\Config\External\ExternalApiConfig;
use App\Framework\Http\Method;
use App\Framework\Http\Request;
use App\Framework\Http\Status;
@@ -11,6 +13,11 @@ use App\Framework\Router\Result\JsonResult;
final class ShopifyWebhookHandler
{
public function __construct(
private readonly ExternalApiConfig $externalApiConfig
) {
}
/**
* Verarbeitet eingehende Shopify-Webhooks
*
@@ -27,9 +34,10 @@ final class ShopifyWebhookHandler
// Validiere den HMAC, um sicherzustellen, dass der Request von Shopify kommt
$rawData = $request->body;
if (!$this->validateWebhookHmac($hmac, $rawData)) {
if (! $this->validateWebhookHmac($hmac, $rawData)) {
$result = new JsonResult(['error' => 'Ungültiger HMAC']);
$result->status = Status::UNAUTHORIZED;
return $result;
}
@@ -40,15 +48,18 @@ final class ShopifyWebhookHandler
switch ($topic) {
case 'orders/create':
$this->processOrderCreated($data);
break;
case 'products/create':
case 'products/update':
$this->processProductUpdate($data);
break;
case 'customers/create':
$this->processCustomerCreated($data);
break;
// Weitere Webhook-Themen...
// Weitere Webhook-Themen...
default:
// Unbekanntes Thema, loggen oder ignorieren
break;
@@ -63,12 +74,11 @@ final class ShopifyWebhookHandler
*/
private function validateWebhookHmac(?string $hmac, string $data): bool
{
if (!$hmac) {
if (! $hmac) {
return false;
}
// Das Shared Secret sollte eigentlich in ApiConfig sein
$secret = 'dein_webhook_shared_secret'; // ODER aus ApiConfig holen
$secret = $this->externalApiConfig->shopify->webhookSecret;
$calculatedHmac = base64_encode(hash_hmac('sha256', $data, $secret, true));
return hash_equals($calculatedHmac, $hmac);

View File

@@ -1,4 +1,5 @@
<?php
declare(strict_types=1);
namespace App\Application\Shopify;
@@ -9,5 +10,6 @@ final class WebhookRequest
public readonly string $topic,
public readonly string $address,
public readonly ?string $format = 'json'
) {}
) {
}
}