Files
Odoo-Modules/fusion-woo-odoo/fusion-woodoo/includes/class-rest-endpoints.php
2026-03-31 20:48:16 -04:00

190 lines
7.7 KiB
PHP

<?php
if (!defined('ABSPATH')) exit;
class Fusion_WooDoo_REST_Endpoints {
public function __construct() {
add_action('rest_api_init', [$this, 'register_routes']);
}
public function register_routes(): void {
$namespace = 'fusion-woodoo/v1';
register_rest_route($namespace, '/order/update', [
'methods' => WP_REST_Server::CREATABLE,
'callback' => [$this, 'handle_order_update'],
'permission_callback' => [$this, 'verify_api_key'],
'args' => [
'order_id' => ['required' => true, 'validate_callback' => 'is_numeric'],
'status' => ['required' => false, 'sanitize_callback' => 'sanitize_text_field'],
'tracking_number' => ['required' => false, 'sanitize_callback' => 'sanitize_text_field'],
'shipping_carrier' => ['required' => false, 'sanitize_callback' => 'sanitize_text_field'],
],
]);
register_rest_route($namespace, '/order/invoice', [
'methods' => WP_REST_Server::CREATABLE,
'callback' => [$this, 'handle_order_invoice'],
'permission_callback' => [$this, 'verify_api_key'],
'args' => [
'order_id' => ['required' => true, 'validate_callback' => 'is_numeric'],
'pdf_data' => ['required' => true],
'filename' => ['required' => false, 'sanitize_callback' => 'sanitize_file_name'],
],
]);
register_rest_route($namespace, '/order/delivery', [
'methods' => WP_REST_Server::CREATABLE,
'callback' => [$this, 'handle_order_delivery'],
'permission_callback' => [$this, 'verify_api_key'],
'args' => [
'order_id' => ['required' => true, 'validate_callback' => 'is_numeric'],
'pdf_data' => ['required' => true],
'filename' => ['required' => false, 'sanitize_callback' => 'sanitize_file_name'],
],
]);
register_rest_route($namespace, '/order/messages', [
'methods' => WP_REST_Server::CREATABLE,
'callback' => [$this, 'handle_order_messages'],
'permission_callback' => [$this, 'verify_api_key'],
'args' => [
'order_id' => ['required' => true, 'validate_callback' => 'is_numeric'],
'messages' => ['required' => true],
],
]);
}
/**
* Validate Bearer token from Authorization header.
*/
public function verify_api_key(WP_REST_Request $request): bool|WP_Error {
$auth_header = $request->get_header('authorization');
if (empty($auth_header) || !str_starts_with($auth_header, 'Bearer ')) {
return new WP_Error('missing_auth', __('Authorization header missing or malformed.', 'fusion-woodoo'), ['status' => 401]);
}
$provided_key = trim(substr($auth_header, 7));
$stored_key = get_option('fusion_woodoo_api_key', '');
if (empty($stored_key) || !hash_equals($stored_key, $provided_key)) {
return new WP_Error('invalid_api_key', __('Invalid API key.', 'fusion-woodoo'), ['status' => 403]);
}
return true;
}
/**
* POST /order/update — update order status and tracking info.
*/
public function handle_order_update(WP_REST_Request $request): WP_REST_Response|WP_Error {
$order_id = (int) $request->get_param('order_id');
$order = wc_get_order($order_id);
if (!$order) {
return new WP_Error('order_not_found', __('Order not found.', 'fusion-woodoo'), ['status' => 404]);
}
if ($status = $request->get_param('status')) {
$order->update_meta_data('_odoo_order_status', sanitize_text_field($status));
}
if ($tracking = $request->get_param('tracking_number')) {
$order->update_meta_data('_odoo_tracking_number', sanitize_text_field($tracking));
}
if ($carrier = $request->get_param('shipping_carrier')) {
$order->update_meta_data('_odoo_shipping_carrier', sanitize_text_field($carrier));
}
$order->save();
return rest_ensure_response(['success' => true, 'order_id' => $order_id]);
}
/**
* POST /order/invoice — store base64-encoded invoice PDF.
*/
public function handle_order_invoice(WP_REST_Request $request): WP_REST_Response|WP_Error {
return $this->save_pdf($request, 'invoices', '_odoo_invoice_pdf');
}
/**
* POST /order/delivery — store base64-encoded delivery PDF.
*/
public function handle_order_delivery(WP_REST_Request $request): WP_REST_Response|WP_Error {
return $this->save_pdf($request, 'deliveries', '_odoo_delivery_pdf');
}
/**
* POST /order/messages — store Odoo messages array against the order.
*/
public function handle_order_messages(WP_REST_Request $request): WP_REST_Response|WP_Error {
$order_id = (int) $request->get_param('order_id');
$order = wc_get_order($order_id);
if (!$order) {
return new WP_Error('order_not_found', __('Order not found.', 'fusion-woodoo'), ['status' => 404]);
}
$messages = $request->get_param('messages');
if (!is_array($messages)) {
return new WP_Error('invalid_messages', __('Messages must be a JSON array.', 'fusion-woodoo'), ['status' => 400]);
}
// Sanitize each message entry
$sanitized = array_map(function($msg) {
return [
'author' => sanitize_text_field($msg['author'] ?? ''),
'date' => sanitize_text_field($msg['date'] ?? ''),
'body' => wp_kses_post($msg['body'] ?? ''),
'type' => sanitize_text_field($msg['type'] ?? 'note'),
];
}, $messages);
$order->update_meta_data('_odoo_messages', $sanitized);
$order->save();
return rest_ensure_response(['success' => true, 'count' => count($sanitized)]);
}
/**
* Shared logic to decode and store a PDF file.
*/
private function save_pdf(WP_REST_Request $request, string $folder, string $meta_key): WP_REST_Response|WP_Error {
$order_id = (int) $request->get_param('order_id');
$order = wc_get_order($order_id);
if (!$order) {
return new WP_Error('order_not_found', __('Order not found.', 'fusion-woodoo'), ['status' => 404]);
}
$pdf_data = $request->get_param('pdf_data');
$decoded = base64_decode($pdf_data, true);
if ($decoded === false) {
return new WP_Error('invalid_pdf', __('Invalid base64-encoded PDF data.', 'fusion-woodoo'), ['status' => 400]);
}
$filename = $request->get_param('filename') ?: ($folder . '-' . $order_id . '-' . time() . '.pdf');
$filename = sanitize_file_name($filename);
$upload = wp_upload_dir();
$save_dir = $upload['basedir'] . '/fusion-woodoo/' . $folder . '/';
if (!file_exists($save_dir)) {
wp_mkdir_p($save_dir);
file_put_contents($save_dir . '.htaccess', 'deny from all');
}
$file_path = $save_dir . $filename;
$bytes = file_put_contents($file_path, $decoded);
if ($bytes === false) {
return new WP_Error('file_write_error', __('Could not save PDF to disk.', 'fusion-woodoo'), ['status' => 500]);
}
$relative = str_replace($upload['basedir'], '', $file_path);
$order->update_meta_data($meta_key, $relative);
$order->save();
return rest_ensure_response(['success' => true, 'path' => $relative]);
}
}