Connect product options/add-cart, server cart checkout payloads, favorite/rebuy/receipt REST, and order-center actions without localStorage dual-read or hardcoded cart/orders URL hacks.
396 lines
17 KiB
PHP
396 lines
17 KiB
PHP
<?php
|
|
/**
|
|
* AKSRT Admin — Shop Controller
|
|
*
|
|
* Owns REST routes for the "商城&商品" domain.
|
|
* Provides product CRUD, order management, and shop overview.
|
|
*
|
|
* @package AKSRT
|
|
*/
|
|
|
|
defined('ABSPATH') || exit;
|
|
|
|
class AKSRT_Admin_Shop_Controller extends AKSRT_Admin_Controller_Base {
|
|
use AKSRT_Admin_Shop_Controller_Product_Admin_Columns;
|
|
use AKSRT_Admin_Shop_Controller_Frontend_Flow_Operations;
|
|
use AKSRT_Admin_Shop_Controller_Product_Operations;
|
|
use AKSRT_Admin_Shop_Controller_Order_Operations;
|
|
use AKSRT_Admin_Shop_Controller_Fulfillment_Operations;
|
|
use AKSRT_Admin_Shop_Controller_Coupon_Gateway_Operations;
|
|
use AKSRT_Admin_Shop_Controller_Variant_Export_Operations;
|
|
|
|
private static $instance = null;
|
|
private $admin;
|
|
|
|
public static function get_instance(): self {
|
|
if (null === self::$instance) self::$instance = new self();
|
|
return self::$instance;
|
|
}
|
|
|
|
public function set_admin(AKSRT_Admin $admin): void {
|
|
$this->admin = $admin;
|
|
}
|
|
|
|
public function register_routes(): void {
|
|
register_rest_route(self::API_NAMESPACE, '/shop/frontend/checkout/preview', [
|
|
'methods' => 'POST',
|
|
'callback' => [$this, 'preview_checkout'],
|
|
'permission_callback' => [$this, 'check_logged_in_permission'],
|
|
]);
|
|
|
|
register_rest_route(self::API_NAMESPACE, '/shop/frontend/orders', [
|
|
'methods' => 'POST',
|
|
'callback' => [$this, 'create_frontend_order'],
|
|
'permission_callback' => [$this, 'check_logged_in_permission'],
|
|
]);
|
|
|
|
register_rest_route(self::API_NAMESPACE, '/shop/frontend/orders', [
|
|
'methods' => 'GET',
|
|
'callback' => [$this, 'get_frontend_orders'],
|
|
'permission_callback' => [$this, 'check_logged_in_permission'],
|
|
]);
|
|
|
|
register_rest_route(self::API_NAMESPACE, '/shop/frontend/orders/(?P<order_number>[A-Za-z0-9]+)/pay', [
|
|
'methods' => 'POST',
|
|
'callback' => [$this, 'pay_frontend_order'],
|
|
'permission_callback' => [$this, 'check_logged_in_permission'],
|
|
]);
|
|
|
|
register_rest_route(self::API_NAMESPACE, '/shop/frontend/orders/(?P<order_number>[A-Za-z0-9]+)/cancel', [
|
|
'methods' => 'POST',
|
|
'callback' => [$this, 'cancel_frontend_order'],
|
|
'permission_callback' => [$this, 'check_logged_in_permission'],
|
|
]);
|
|
|
|
register_rest_route(self::API_NAMESPACE, '/shop/frontend/orders/(?P<order_number>[A-Za-z0-9]+)', [
|
|
'methods' => 'GET',
|
|
'callback' => [$this, 'get_frontend_order'],
|
|
'permission_callback' => [$this, 'check_logged_in_permission'],
|
|
]);
|
|
|
|
register_rest_route(self::API_NAMESPACE, '/shop/frontend/orders/(?P<order_number>[A-Za-z0-9]+)/after-sale', [
|
|
'methods' => 'POST',
|
|
'callback' => [$this, 'create_frontend_after_sale'],
|
|
'permission_callback' => [$this, 'check_logged_in_permission'],
|
|
]);
|
|
|
|
// ── Address book CRUD (frontend) ──
|
|
|
|
register_rest_route(self::API_NAMESPACE, '/shop/frontend/address', [
|
|
'methods' => 'GET',
|
|
'callback' => [$this, 'get_frontend_addresses'],
|
|
'permission_callback' => [$this, 'check_logged_in_permission'],
|
|
]);
|
|
|
|
register_rest_route(self::API_NAMESPACE, '/shop/frontend/address', [
|
|
'methods' => 'POST',
|
|
'callback' => [$this, 'create_frontend_address'],
|
|
'permission_callback' => [$this, 'check_logged_in_permission'],
|
|
]);
|
|
|
|
register_rest_route(self::API_NAMESPACE, '/shop/frontend/address/(?P<id>\d+)', [
|
|
'methods' => 'POST',
|
|
'callback' => [$this, 'update_frontend_address'],
|
|
'permission_callback' => [$this, 'check_logged_in_permission'],
|
|
]);
|
|
|
|
register_rest_route(self::API_NAMESPACE, '/shop/frontend/address/(?P<id>\d+)', [
|
|
'methods' => 'DELETE',
|
|
'callback' => [$this, 'delete_frontend_address'],
|
|
'permission_callback' => [$this, 'check_logged_in_permission'],
|
|
]);
|
|
|
|
register_rest_route(self::API_NAMESPACE, '/shop/frontend/address/(?P<id>\d+)/default', [
|
|
'methods' => 'POST',
|
|
'callback' => [$this, 'set_default_frontend_address'],
|
|
'permission_callback' => [$this, 'check_logged_in_permission'],
|
|
]);
|
|
|
|
register_rest_route(self::API_NAMESPACE, '/shop/frontend/products', [
|
|
'methods' => 'POST',
|
|
'callback' => [$this, 'create_frontend_product'],
|
|
'permission_callback' => [$this, 'check_logged_in_permission'],
|
|
]);
|
|
|
|
register_rest_route(self::API_NAMESPACE, '/shop/frontend/products/(?P<id>\d+)', [
|
|
'methods' => 'POST',
|
|
'callback' => [$this, 'update_frontend_product'],
|
|
'permission_callback' => [$this, 'check_logged_in_permission'],
|
|
]);
|
|
|
|
// Cart endpoints (§6.4)
|
|
register_rest_route(self::API_NAMESPACE, '/shop/frontend/cart', [
|
|
'methods' => 'GET',
|
|
'callback' => [$this, 'get_cart'],
|
|
'permission_callback' => [$this, 'check_logged_in_permission'],
|
|
]);
|
|
|
|
register_rest_route(self::API_NAMESPACE, '/shop/frontend/cart/add', [
|
|
'methods' => 'POST',
|
|
'callback' => [$this, 'handle_add_to_cart'],
|
|
'permission_callback' => [$this, 'check_logged_in_permission'],
|
|
]);
|
|
|
|
register_rest_route(self::API_NAMESPACE, '/shop/frontend/cart/reduce', [
|
|
'methods' => 'POST',
|
|
'callback' => [$this, 'handle_reduce_from_cart'],
|
|
'permission_callback' => [$this, 'check_logged_in_permission'],
|
|
]);
|
|
|
|
register_rest_route(self::API_NAMESPACE, '/shop/frontend/cart/remove', [
|
|
'methods' => 'POST',
|
|
'callback' => [$this, 'handle_remove_from_cart'],
|
|
'permission_callback' => [$this, 'check_logged_in_permission'],
|
|
]);
|
|
|
|
register_rest_route(self::API_NAMESPACE, '/shop/frontend/cart/remove-multi', [
|
|
'methods' => 'POST',
|
|
'callback' => [$this, 'handle_remove_multi_from_cart'],
|
|
'permission_callback' => [$this, 'check_logged_in_permission'],
|
|
]);
|
|
|
|
register_rest_route(self::API_NAMESPACE, '/shop/frontend/cart/empty', [
|
|
'methods' => 'POST',
|
|
'callback' => [$this, 'handle_empty_cart'],
|
|
'permission_callback' => [$this, 'check_logged_in_permission'],
|
|
]);
|
|
|
|
register_rest_route(self::API_NAMESPACE, '/shop/frontend/cart/count', [
|
|
'methods' => 'GET',
|
|
'callback' => [$this, 'get_cart_count'],
|
|
'permission_callback' => [$this, 'check_logged_in_permission'],
|
|
]);
|
|
|
|
// Shop overview / dashboard
|
|
register_rest_route(self::API_NAMESPACE, '/shop/overview', [
|
|
'methods' => 'GET',
|
|
'callback' => [$this, 'get_overview'],
|
|
'permission_callback' => [$this, 'check_permission'],
|
|
]);
|
|
|
|
// Product taxonomy options used by the product editor.
|
|
register_rest_route(self::API_NAMESPACE, '/shop/products/taxonomy', [
|
|
'methods' => 'GET',
|
|
'callback' => [$this, 'get_product_taxonomy'],
|
|
'permission_callback' => [$this, 'check_permission'],
|
|
]);
|
|
|
|
// Create product category or tag term for the product editor.
|
|
register_rest_route(self::API_NAMESPACE, '/shop/products/taxonomy', [
|
|
'methods' => 'POST',
|
|
'callback' => [$this, 'create_product_taxonomy_term'],
|
|
'permission_callback' => [$this, 'check_permission'],
|
|
]);
|
|
|
|
// Product list
|
|
register_rest_route(self::API_NAMESPACE, '/shop/products', [
|
|
'methods' => 'GET',
|
|
'callback' => [$this, 'get_products'],
|
|
'permission_callback' => [$this, 'check_permission'],
|
|
]);
|
|
|
|
// Product create
|
|
register_rest_route(self::API_NAMESPACE, '/shop/products', [
|
|
'methods' => 'POST',
|
|
'callback' => [$this, 'create_product'],
|
|
'permission_callback' => [$this, 'check_permission'],
|
|
]);
|
|
|
|
// Product update
|
|
register_rest_route(self::API_NAMESPACE, '/shop/products/(?P<id>\d+)', [
|
|
'methods' => 'POST',
|
|
'callback' => [$this, 'update_product'],
|
|
'permission_callback' => [$this, 'check_permission'],
|
|
]);
|
|
|
|
// Product single read
|
|
register_rest_route(self::API_NAMESPACE, '/shop/products/(?P<id>\d+)', [
|
|
'methods' => 'GET',
|
|
'callback' => [$this, 'get_product'],
|
|
'permission_callback' => [$this, 'check_permission'],
|
|
]);
|
|
|
|
// Order list
|
|
register_rest_route(self::API_NAMESPACE, '/shop/orders', [
|
|
'methods' => 'GET',
|
|
'callback' => [$this, 'get_orders'],
|
|
'permission_callback' => [$this, 'check_permission'],
|
|
]);
|
|
|
|
// Order single read
|
|
register_rest_route(self::API_NAMESPACE, '/shop/orders/(?P<order_number>[A-Za-z0-9]+)', [
|
|
'methods' => 'GET',
|
|
'callback' => [$this, 'get_order'],
|
|
'permission_callback' => [$this, 'check_permission'],
|
|
]);
|
|
|
|
// Order status update — canonical field is order_number
|
|
register_rest_route(self::API_NAMESPACE, '/shop/orders/update-status', [
|
|
'methods' => 'POST',
|
|
'callback' => [$this, 'update_order_status'],
|
|
'permission_callback' => [$this, 'check_permission'],
|
|
]);
|
|
|
|
// Gateway status
|
|
register_rest_route(self::API_NAMESPACE, '/shop/gateways', [
|
|
'methods' => 'GET',
|
|
'callback' => [$this, 'get_gateways'],
|
|
'permission_callback' => [$this, 'check_permission'],
|
|
]);
|
|
|
|
// Coupon list (admin)
|
|
register_rest_route(self::API_NAMESPACE, '/shop/coupons', [
|
|
'methods' => 'GET',
|
|
'callback' => [$this, 'get_coupons'],
|
|
'permission_callback' => [$this, 'check_permission'],
|
|
]);
|
|
|
|
// Coupon create (admin)
|
|
register_rest_route(self::API_NAMESPACE, '/shop/coupons', [
|
|
'methods' => 'POST',
|
|
'callback' => [$this, 'create_coupon'],
|
|
'permission_callback' => [$this, 'check_permission'],
|
|
]);
|
|
|
|
// Coupon disable (admin)
|
|
register_rest_route(self::API_NAMESPACE, '/shop/coupons/(?P<id>\d+)/disable', [
|
|
'methods' => 'POST',
|
|
'callback' => [$this, 'disable_coupon'],
|
|
'permission_callback' => [$this, 'check_permission'],
|
|
]);
|
|
|
|
// ── After Sale ──
|
|
|
|
// After-sale list (admin)
|
|
register_rest_route(self::API_NAMESPACE, '/shop/after-sale', [
|
|
'methods' => 'GET',
|
|
'callback' => [$this, 'get_after_sale_list'],
|
|
'permission_callback' => [$this, 'check_permission'],
|
|
]);
|
|
|
|
// After-sale create (admin)
|
|
register_rest_route(self::API_NAMESPACE, '/shop/after-sale', [
|
|
'methods' => 'POST',
|
|
'callback' => [$this, 'create_after_sale'],
|
|
'permission_callback' => [$this, 'check_permission'],
|
|
]);
|
|
|
|
// After-sale status update (admin)
|
|
register_rest_route(self::API_NAMESPACE, '/shop/after-sale/(?P<id>\d+)/update-status', [
|
|
'methods' => 'POST',
|
|
'callback' => [$this, 'update_after_sale_status'],
|
|
'permission_callback' => [$this, 'check_permission'],
|
|
]);
|
|
|
|
register_rest_route(self::API_NAMESPACE, '/shop/after-sale/(?P<id>\d+)', [
|
|
'methods' => 'GET',
|
|
'callback' => [$this, 'get_after_sale_detail'],
|
|
'permission_callback' => [$this, 'check_permission'],
|
|
]);
|
|
|
|
// ── Shipping ──
|
|
|
|
// Shipping list (admin)
|
|
register_rest_route(self::API_NAMESPACE, '/shop/shipping', [
|
|
'methods' => 'GET',
|
|
'callback' => [$this, 'get_shipping_list'],
|
|
'permission_callback' => [$this, 'check_permission'],
|
|
]);
|
|
|
|
// Shipping create (admin)
|
|
register_rest_route(self::API_NAMESPACE, '/shop/shipping', [
|
|
'methods' => 'POST',
|
|
'callback' => [$this, 'create_shipping'],
|
|
'permission_callback' => [$this, 'check_permission'],
|
|
]);
|
|
|
|
// Shipping status update (admin)
|
|
register_rest_route(self::API_NAMESPACE, '/shop/shipping/(?P<id>\d+)/update-status', [
|
|
'methods' => 'POST',
|
|
'callback' => [$this, 'update_shipping_status'],
|
|
'permission_callback' => [$this, 'check_permission'],
|
|
]);
|
|
|
|
register_rest_route(self::API_NAMESPACE, '/shop/shipping/(?P<id>\d+)', [
|
|
'methods' => 'GET',
|
|
'callback' => [$this, 'get_shipping_detail'],
|
|
'permission_callback' => [$this, 'check_permission'],
|
|
]);
|
|
|
|
register_rest_route(self::API_NAMESPACE, '/shop/shipping/batch-update-status', [
|
|
'methods' => 'POST',
|
|
'callback' => [$this, 'batch_update_shipping_status'],
|
|
'permission_callback' => [$this, 'check_permission'],
|
|
]);
|
|
|
|
|
|
// ── R68: Order export + confirm receipt + after-sale reasons ──
|
|
|
|
register_rest_route(self::API_NAMESPACE, '/shop/orders/export', [
|
|
'methods' => 'GET',
|
|
'callback' => [$this, 'export_orders'],
|
|
'permission_callback' => [$this, 'check_permission'],
|
|
]);
|
|
|
|
// ── R69: Frontend after-sale reasons (§6.8) ──
|
|
|
|
register_rest_route(self::API_NAMESPACE, '/shop/frontend/after-sale/reasons', [
|
|
'methods' => 'GET',
|
|
'callback' => [$this, 'get_frontend_after_sale_reasons'],
|
|
'permission_callback' => [$this, 'check_logged_in_permission'],
|
|
]);
|
|
|
|
register_rest_route(self::API_NAMESPACE, '/shop/frontend/orders/(?P<order_number>[A-Za-z0-9]+)/confirm-receipt', [
|
|
'methods' => 'POST',
|
|
'callback' => [$this, 'confirm_receipt'],
|
|
'permission_callback' => [$this, 'check_logged_in_permission'],
|
|
]);
|
|
|
|
register_rest_route(self::API_NAMESPACE, '/shop/frontend/orders/(?P<order_number>[A-Za-z0-9]+)/rebuy', [
|
|
'methods' => 'POST',
|
|
'callback' => [$this, 'rebuy_frontend_order'],
|
|
'permission_callback' => [$this, 'check_logged_in_permission'],
|
|
]);
|
|
|
|
register_rest_route(self::API_NAMESPACE, '/shop/frontend/products/(?P<id>\d+)/favorite', [
|
|
'methods' => 'POST',
|
|
'callback' => [$this, 'toggle_frontend_product_favorite'],
|
|
'permission_callback' => [$this, 'check_logged_in_permission'],
|
|
]);
|
|
|
|
register_rest_route(self::API_NAMESPACE, '/shop/after-sale/reasons', [
|
|
'methods' => 'GET',
|
|
'callback' => [$this, 'get_after_sale_reasons'],
|
|
'permission_callback' => [$this, 'check_permission'],
|
|
]);
|
|
|
|
// ── Product Variants / SKU ──
|
|
|
|
// List variants for a product
|
|
register_rest_route(self::API_NAMESPACE, '/shop/products/(?P<id>\d+)/variants', [
|
|
'methods' => 'GET',
|
|
'callback' => [$this, 'get_product_variants'],
|
|
'permission_callback' => [$this, 'check_permission'],
|
|
]);
|
|
|
|
// Save variants for a product (replace all)
|
|
register_rest_route(self::API_NAMESPACE, '/shop/products/(?P<id>\d+)/variants', [
|
|
'methods' => 'POST',
|
|
'callback' => [$this, 'save_product_variants'],
|
|
'permission_callback' => [$this, 'check_permission'],
|
|
]);
|
|
|
|
// Delete a variant
|
|
register_rest_route(self::API_NAMESPACE, '/shop/variants/(?P<id>\d+)', [
|
|
'methods' => 'DELETE',
|
|
'callback' => [$this, 'delete_variant'],
|
|
'permission_callback' => [$this, 'check_permission'],
|
|
]);
|
|
}
|
|
|
|
public function check_logged_in_permission(): bool {
|
|
return is_user_logged_in();
|
|
}
|
|
|
|
}
|