|
@@ -9,8 +9,11 @@ use ApiPlatform\State\Pagination\Pagination;
|
|
|
use ApiPlatform\State\ProviderInterface;
|
|
use ApiPlatform\State\ProviderInterface;
|
|
|
use Illuminate\Pagination\LengthAwarePaginator;
|
|
use Illuminate\Pagination\LengthAwarePaginator;
|
|
|
use Illuminate\Support\Facades\Auth;
|
|
use Illuminate\Support\Facades\Auth;
|
|
|
|
|
+use Illuminate\Support\Facades\Request;
|
|
|
use Webkul\BagistoApi\Exception\AuthorizationException;
|
|
use Webkul\BagistoApi\Exception\AuthorizationException;
|
|
|
use Webkul\BagistoApi\Exception\ResourceNotFoundException;
|
|
use Webkul\BagistoApi\Exception\ResourceNotFoundException;
|
|
|
|
|
+use Webkul\BagistoApi\Facades\CartTokenFacade;
|
|
|
|
|
+use Webkul\BagistoApi\Facades\TokenHeaderFacade;
|
|
|
use Webkul\BagistoApi\Models\CustomerOrder;
|
|
use Webkul\BagistoApi\Models\CustomerOrder;
|
|
|
use Webkul\Customer\Models\Customer;
|
|
use Webkul\Customer\Models\Customer;
|
|
|
|
|
|
|
@@ -31,15 +34,23 @@ class CustomerOrderProvider implements ProviderInterface
|
|
|
*/
|
|
*/
|
|
|
public function provide(Operation $operation, array $uriVariables = [], array $context = []): object|array|null
|
|
public function provide(Operation $operation, array $uriVariables = [], array $context = []): object|array|null
|
|
|
{
|
|
{
|
|
|
|
|
+ $isCollection = $operation instanceof GetCollection
|
|
|
|
|
+ || $operation instanceof \ApiPlatform\Metadata\GraphQl\QueryCollection;
|
|
|
|
|
+
|
|
|
$customer = Auth::guard('sanctum')->user();
|
|
$customer = Auth::guard('sanctum')->user();
|
|
|
|
|
|
|
|
- if (! $customer) {
|
|
|
|
|
|
|
+ // Collection API remains customer-only.
|
|
|
|
|
+ if ($isCollection && ! $customer) {
|
|
|
throw new AuthorizationException(__('bagistoapi::app.graphql.logout.unauthenticated'));
|
|
throw new AuthorizationException(__('bagistoapi::app.graphql.logout.unauthenticated'));
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
/** Single item — GET /api/shop/customer-orders/{id} */
|
|
/** Single item — GET /api/shop/customer-orders/{id} */
|
|
|
- if (! $operation instanceof GetCollection && ! ($operation instanceof \ApiPlatform\Metadata\GraphQl\QueryCollection)) {
|
|
|
|
|
- return $this->provideItem($customer, $uriVariables);
|
|
|
|
|
|
|
+ if (! $isCollection) {
|
|
|
|
|
+ if ($customer) {
|
|
|
|
|
+ return $this->provideCustomerItem($customer, $uriVariables);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ return $this->provideGuestItem($uriVariables);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
return $this->provideCollection($customer, $context);
|
|
return $this->provideCollection($customer, $context);
|
|
@@ -48,21 +59,39 @@ class CustomerOrderProvider implements ProviderInterface
|
|
|
/**
|
|
/**
|
|
|
* Return a single order owned by the customer
|
|
* Return a single order owned by the customer
|
|
|
*/
|
|
*/
|
|
|
- private function provideItem(object $customer, array $uriVariables): CustomerOrder
|
|
|
|
|
|
|
+ private function provideCustomerItem(object $customer, array $uriVariables): CustomerOrder
|
|
|
{
|
|
{
|
|
|
- $id = $uriVariables['id'] ?? null;
|
|
|
|
|
|
|
+ $order = $this->baseOrderDetailsQuery()
|
|
|
|
|
+ ->where('customer_id', $customer->id)
|
|
|
|
|
+ ->where('customer_type', Customer::class)
|
|
|
|
|
+ ->find($this->resolveOrderId($uriVariables));
|
|
|
|
|
|
|
|
- if (! $id) {
|
|
|
|
|
- throw new ResourceNotFoundException(__('bagistoapi::app.graphql.customer-order.id-required'));
|
|
|
|
|
|
|
+ if (! $order) {
|
|
|
|
|
+ throw new ResourceNotFoundException(
|
|
|
|
|
+ __('bagistoapi::app.graphql.customer-order.not-found', ['id' => $uriVariables['id'] ?? null])
|
|
|
|
|
+ );
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- $orderQuery = CustomerOrder::with(['items', 'addresses', 'payment', 'shipments.items', 'shipments.shippingAddress'])
|
|
|
|
|
- ->where('customer_id', $customer->id)
|
|
|
|
|
- ->where('customer_type', Customer::class);
|
|
|
|
|
|
|
+ return $order;
|
|
|
|
|
+ }
|
|
|
|
|
|
|
|
- $order = $orderQuery->find($id);
|
|
|
|
|
|
|
+ /**
|
|
|
|
|
+ * Return a single order for a guest token owner.
|
|
|
|
|
+ */
|
|
|
|
|
+ private function provideGuestItem(array $uriVariables): CustomerOrder
|
|
|
|
|
+ {
|
|
|
|
|
+ $id = $this->resolveOrderId($uriVariables);
|
|
|
|
|
|
|
|
- if (! $order) {
|
|
|
|
|
|
|
+ $request = Request::instance();
|
|
|
|
|
+ $token = $request ? TokenHeaderFacade::getAuthorizationBearerToken($request) : null;
|
|
|
|
|
+
|
|
|
|
|
+ if (! $token || CartTokenFacade::getTokenType($token) !== 'guest') {
|
|
|
|
|
+ throw new AuthorizationException(__('bagistoapi::app.graphql.logout.unauthenticated'));
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ $order = $this->baseOrderDetailsQuery()->find($id);
|
|
|
|
|
+
|
|
|
|
|
+ if (! $order || ! $this->guestTokenOwnsOrder($token, $order)) {
|
|
|
throw new ResourceNotFoundException(
|
|
throw new ResourceNotFoundException(
|
|
|
__('bagistoapi::app.graphql.customer-order.not-found', ['id' => $id])
|
|
__('bagistoapi::app.graphql.customer-order.not-found', ['id' => $id])
|
|
|
);
|
|
);
|
|
@@ -71,6 +100,49 @@ class CustomerOrderProvider implements ProviderInterface
|
|
|
return $order;
|
|
return $order;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+ /**
|
|
|
|
|
+ * Shared order detail relations for single-order APIs.
|
|
|
|
|
+ */
|
|
|
|
|
+ private function baseOrderDetailsQuery()
|
|
|
|
|
+ {
|
|
|
|
|
+ return CustomerOrder::with(['items', 'addresses', 'payment', 'shipments.items', 'shipments.shippingAddress']);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ private function resolveOrderId(array $uriVariables): int
|
|
|
|
|
+ {
|
|
|
|
|
+ $id = $uriVariables['id'] ?? null;
|
|
|
|
|
+
|
|
|
|
|
+ if (! $id || ! is_numeric($id)) {
|
|
|
|
|
+ throw new ResourceNotFoundException(__('bagistoapi::app.graphql.customer-order.id-required'));
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ return (int) $id;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
|
|
+ * Same ownership check used by CancelOrder: guest can access only orders
|
|
|
|
|
+ * paid with their own cart token.
|
|
|
|
|
+ */
|
|
|
|
|
+ private function guestTokenOwnsOrder(string $token, CustomerOrder $order): bool
|
|
|
|
|
+ {
|
|
|
|
|
+ $additional = $order->payment?->additional ?? [];
|
|
|
|
|
+ $expectedToken = $additional['cart_token'] ?? null;
|
|
|
|
|
+
|
|
|
|
|
+ if ($expectedToken && hash_equals((string) $expectedToken, $token)) {
|
|
|
|
|
+ return true;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ $tokenRecord = CartTokenFacade::getGuestTokenRecord($token);
|
|
|
|
|
+
|
|
|
|
|
+ if (! $tokenRecord) {
|
|
|
|
|
+ return false;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ $expectedCartId = $additional['cart_id'] ?? null;
|
|
|
|
|
+
|
|
|
|
|
+ return $expectedCartId && (int) $tokenRecord->cart_id === (int) $expectedCartId;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
/**
|
|
/**
|
|
|
* Enable debug dumps only when explicitly requested via header:
|
|
* Enable debug dumps only when explicitly requested via header:
|
|
|
* X-DEBUG-CUSTOMER-ORDER: 1
|
|
* X-DEBUG-CUSTOMER-ORDER: 1
|