settings = $settings; $this->cors = new CorsManager( $settings, self::NAMESPACE ); $this->rateLimiter = new RateLimiter( self::RATE_PREFIX, self::RATE_WINDOW, self::RATE_MAX ); $this->resolver = new OrderResolver(); $this->serializer = new OrderSerializer(); } public function register(): void { \add_action( 'rest_api_init', [ $this, 'registerRoutes' ] ); \add_action( 'rest_api_init', [ $this->cors, 'attachToRest' ], 15 ); } public function registerRoutes(): void { \register_rest_route( self::NAMESPACE, '/orders/(?P[A-Za-z0-9_-]{1,64})', [ 'methods' => [ 'GET', 'POST' ], 'callback' => [ $this, 'lookup' ], 'permission_callback' => [ $this, 'authorize' ], 'args' => [ 'number' => [ 'required' => true, 'sanitize_callback' => 'sanitize_text_field', ], 'email' => [ 'required' => true, 'sanitize_callback' => 'sanitize_email', ], ], ] ); } /** * @return true|WP_Error */ public function authorize( WP_REST_Request $request ) { if ( $this->isBackendRequest( $request ) || $this->isWidgetRequest( $request ) ) { return true; } return new WP_Error( 'agent001_unauthorized', 'Invalid auth header.', [ 'status' => 401 ] ); } /** * @return WP_REST_Response|WP_Error */ public function lookup( WP_REST_Request $request ) { if ( ! $this->isBackendRequest( $request ) && ! $this->rateLimiter->consume() ) { return new WP_Error( 'agent001_rate_limited', 'Too many requests, slow down.', [ 'status' => 429 ] ); } if ( ! \function_exists( 'wc_get_order' ) ) { return new WP_Error( 'agent001_no_woocommerce', 'WooCommerce is not available on this site.', [ 'status' => 503 ] ); } $number = (string) $request->get_param( 'number' ); $email = (string) $request->get_param( 'email' ); if ( $email === '' ) { return new WP_Error( 'agent001_missing_email', 'Missing email parameter.', [ 'status' => 400 ] ); } $order = $this->resolver->findByNumber( $number ); if ( $order === null || ! $this->resolver->emailMatches( $order, $email ) ) { return new WP_Error( 'agent001_order_not_found', 'Order not found.', [ 'status' => 404 ] ); } return new WP_REST_Response( $this->serializer->toArray( $order ), 200 ); } private function isBackendRequest( WP_REST_Request $request ): bool { $apiKey = $this->settings->apiKey(); $provided = (string) $request->get_header( self::AUTH_HEADER ); return $apiKey !== '' && $provided !== '' && \hash_equals( $apiKey, $provided ); } private function isWidgetRequest( WP_REST_Request $request ): bool { if ( $this->settings->apiKey() === '' ) { return false; } $widgetKey = $this->settings->widgetKey(); $provided = (string) $request->get_header( self::AUTH_HEADER ); return $widgetKey !== '' && $provided !== '' && \hash_equals( $widgetKey, $provided ); } }