'POST', 'callback' => array($this, 'update_order_status'), 'permission_callback' => array($this, 'verify_api_key'), )); register_rest_route('akkedli/v1', '/health', array( 'methods' => 'GET', 'callback' => array($this, 'health_check'), 'permission_callback' => '__return_true', )); // Connect endpoint: generates nonce and redirects to auto_connect register_rest_route('akkedli/v1', '/connect', array( 'methods' => 'GET', 'callback' => array($this, 'handle_connect_redirect'), 'permission_callback' => array($this, 'verify_admin_capability'), )); } /** * Permission callback: verify user is a WooCommerce admin */ public function verify_admin_capability() { return current_user_can('manage_woocommerce'); } /** * Connect redirect endpoint * * Receives connection params from Akkedli Dashboard, * generates a WordPress nonce, and redirects to the * admin auto_connect handler with all params + nonce. * * URL: GET /wp-json/akkedli/v1/connect?api_key=xxx&webhook_url=xxx&return_url=xxx */ public function handle_connect_redirect(WP_REST_Request $request) { $api_key = sanitize_text_field($request->get_param('api_key')); $webhook_url = esc_url_raw($request->get_param('webhook_url')); $return_url = esc_url_raw($request->get_param('return_url')); // Validate required params if (empty($api_key) || empty($webhook_url)) { return new WP_Error( 'akkedli_missing_params', __('Missing required parameters (api_key, webhook_url).', 'akkedli-connector'), array('status' => 400) ); } // Generate the nonce (tied to current admin session) $nonce = wp_create_nonce('akkedli_auto_connect'); // Build the admin redirect URL with nonce $redirect_url = admin_url('admin.php'); $redirect_url = add_query_arg(array( 'page' => 'akkedli-connector', 'action' => 'auto_connect', 'api_key' => rawurlencode($api_key), 'webhook_url' => rawurlencode($webhook_url), 'return_url' => rawurlencode($return_url), '_akkedli_nonce' => $nonce, ), $redirect_url); // Redirect to admin handler wp_safe_redirect(esc_url_raw($redirect_url)); exit; } /** * Verify API key from request header */ public function verify_api_key(WP_REST_Request $request) { $api_key = $request->get_header('X-API-Key'); $stored_key = Akkedli_Settings::get_api_key(); if (empty($api_key) || empty($stored_key)) { return new WP_Error( 'akkedli_unauthorized', __('Missing or invalid API key', 'akkedli-connector'), array('status' => 401) ); } if (!hash_equals($stored_key, $api_key)) { return new WP_Error( 'akkedli_unauthorized', __('Invalid API key', 'akkedli-connector'), array('status' => 401) ); } return true; } /** * Update order status from Akkedli verification */ public function update_order_status(WP_REST_Request $request) { $order_id = absint($request->get_param('order_id')); $new_status = sanitize_text_field($request->get_param('new_status')); $verification_result = sanitize_text_field($request->get_param('verification_result')); $verified_at = sanitize_text_field($request->get_param('verified_at')); // Validate required fields if (empty($order_id)) { return new WP_Error( 'akkedli_missing_order_id', __('Order ID is required', 'akkedli-connector'), array('status' => 400) ); } if (empty($new_status)) { return new WP_Error( 'akkedli_missing_status', __('New status is required', 'akkedli-connector'), array('status' => 400) ); } // Get the order $order = wc_get_order($order_id); if (!$order) { return new WP_Error( 'akkedli_order_not_found', __('Order not found', 'akkedli-connector'), array('status' => 404) ); } // Map Akkedli status to WooCommerce status $wc_status = $this->map_status($new_status); if (!$wc_status) { return new WP_Error( 'akkedli_invalid_status', __('Invalid status provided', 'akkedli-connector'), array('status' => 400) ); } // Update order status $old_status = $order->get_status(); $order->set_status($wc_status); $note = sprintf( /* translators: %1$s: verification result (verified/cancelled), %2$s: verification timestamp */ __('Order %1$s via Akkedli verification at %2$s', 'akkedli-connector'), $verification_result === 'verified' ? 'verified' : 'cancelled', $verified_at ? $verified_at : current_time('c') ); $order->add_order_note($note); // Add meta data $order->update_meta_data('_akkedli_verified', $verification_result === 'verified' ? 'yes' : 'no'); $order->update_meta_data('_akkedli_verified_at', $verified_at); $order->update_meta_data('_akkedli_verification_result', $verification_result); // Save order $order->save(); return array( 'success' => true, 'order_id' => $order_id, 'old_status' => $old_status, 'new_status' => $wc_status, 'verification_result' => $verification_result, 'message' => __('Order status updated successfully', 'akkedli-connector') ); } /** * Map Akkedli/n8n status to WooCommerce status */ private function map_status($status) { $status_map = array( 'processing' => 'processing', 'completed' => 'completed', 'cancelled' => 'cancelled', 'on-hold' => 'on-hold', 'pending' => 'pending', 'refunded' => 'refunded', 'failed' => 'failed', // Akkedli-specific mappings 'verified' => 'processing', 'confirmed' => 'akkedli-confirmed', 'rejected' => 'cancelled', ); return isset($status_map[$status]) ? $status_map[$status] : null; } /** * Health check endpoint */ public function health_check() { return array( 'status' => 'ok', 'plugin' => 'akkedli-connector', 'version' => AKKEDLI_VERSION, 'configured' => Akkedli_Settings::is_configured(), 'timestamp' => current_time('c') ); } }