From 16965b29e1fcc8749e3e634ee357e9174a65910b Mon Sep 17 00:00:00 2001 From: wood chen Date: Wed, 15 Jan 2025 00:08:34 +0800 Subject: [PATCH] Enhance CZL Express for WooCommerce Plugin Functionality - Updated plugin URI for better branding consistency. - Added environment checks to ensure WooCommerce is installed and meets version requirements. - Improved AJAX handling for shipment creation and tracking updates, including enhanced error messages. - Streamlined order management with new custom order statuses and improved logging for better tracking. - Removed deprecated API test page and updated admin interface for clarity. - Enhanced localization by ensuring all translatable strings use esc_html functions for security. These changes improve the robustness, usability, and maintainability of the CZL Express plugin. --- admin/views/admin-page.php | 4 +- admin/views/api-settings.php | 16 +- admin/views/api-test.php | 69 ----- admin/views/exchange-rates.php | 12 +- admin/views/orders.php | 70 ++--- admin/views/product-groups.php | 20 +- assets/js/admin.js | 6 +- czlexpress-for-woocommerce.php | 180 +++++++------ includes/class-czl-api.php | 346 ++++++++++--------------- includes/class-czl-install.php | 27 +- includes/class-czl-label.php | 72 +++-- includes/class-czl-logger.php | 76 ++++++ includes/class-czl-order-handler.php | 27 +- includes/class-czl-order.php | 19 +- includes/class-czl-product-fields.php | 60 ++++- includes/class-czl-rate-calculator.php | 31 ++- includes/class-czl-shipping-method.php | 8 +- includes/class-czl-tracking.php | 129 +++++---- includes/class-czlexpress.php | 52 ++-- templates/shipping-method-group.php | 2 +- uninstall.php | 46 ++++ 21 files changed, 672 insertions(+), 600 deletions(-) delete mode 100644 admin/views/api-test.php create mode 100644 includes/class-czl-logger.php create mode 100644 uninstall.php diff --git a/admin/views/admin-page.php b/admin/views/admin-page.php index 352b7a6..844ac04 100644 --- a/admin/views/admin-page.php +++ b/admin/views/admin-page.php @@ -9,10 +9,10 @@ $tab = isset($_GET['tab']) ? sanitize_text_field($_GET['tab']) : 'settings'; diff --git a/admin/views/api-settings.php b/admin/views/api-settings.php index 445ee85..848bb4a 100644 --- a/admin/views/api-settings.php +++ b/admin/views/api-settings.php @@ -74,12 +74,12 @@ $settings = array(
-

+

@@ -92,11 +92,11 @@ jQuery(function($) { var $result = $('#czl-test-result'); $button.prop('disabled', true); - $result.html(''); + $result.html(''); $.post(ajaxurl, { action: 'czl_test_connection', - nonce: '' + nonce: '' }, function(response) { $button.prop('disabled', false); if (response.success) { @@ -112,15 +112,15 @@ jQuery(function($) { var $result = $('#czl-test-result'); $button.prop('disabled', true); - $result.html(''); + $result.html(''); $.post(ajaxurl, { action: 'czl_test_shipping_rate', - nonce: '' + nonce: '' }, function(response) { $button.prop('disabled', false); if (response.success) { - var html = '

'; + var html = '

'; html += '
' + wp.escapeHtml(JSON.stringify(response.data, null, 2)) + '
'; $result.html(html); } else { diff --git a/admin/views/api-test.php b/admin/views/api-test.php deleted file mode 100644 index 6568278..0000000 --- a/admin/views/api-test.php +++ /dev/null @@ -1,69 +0,0 @@ - - -
-

- -

- -

- -
- - - -
- -
-
- - \ No newline at end of file diff --git a/admin/views/exchange-rates.php b/admin/views/exchange-rates.php index 340dfcf..b299707 100644 --- a/admin/views/exchange-rates.php +++ b/admin/views/exchange-rates.php @@ -23,8 +23,8 @@ foreach ($supported_currencies as $code => $name) {

- - ' . $current_currency . ''); ?> + + ' . esc_html($current_currency) . ''); ?>

@@ -35,9 +35,9 @@ foreach ($supported_currencies as $code => $name) { - - - + + + @@ -79,7 +79,7 @@ foreach ($supported_currencies as $code => $name) { diff --git a/admin/views/orders.php b/admin/views/orders.php index 6d19143..f783448 100644 --- a/admin/views/orders.php +++ b/admin/views/orders.php @@ -51,24 +51,24 @@ wp_enqueue_script('jquery'); ?>
-

+

- +
@@ -78,19 +78,19 @@ wp_enqueue_script('jquery');
- - - - - - - + + + + + + + '; + echo ''; } else { foreach ($orders as $order): $order_id = $order->get_id(); @@ -115,7 +115,7 @@ wp_enqueue_script('jquery'); get_status()); $status_class = sanitize_html_class('status-' . $order->get_status()); - echo "" . esc_html($status_name) . ""; + echo wp_kses_post("" . esc_html($status_name) . ""); ?> @@ -178,17 +178,17 @@ wp_enqueue_script('jquery');
@@ -208,7 +208,7 @@ jQuery(document).ready(function($) { // 打开对话框 tb_show( - '', + '', '#TB_inline?width=300&height=180&inlineId=edit-tracking-dialog' ); @@ -296,7 +296,7 @@ jQuery(document).ready(function($) { // 处理创建运单按钮点击 $(document).on('click', '.czl-create-btn', function() { var $button = $(this); - var orderId = $button.data('order-id'); + var orderId = $(this).data('order-id'); // 如果按钮已经在处理中,则返回 if ($button.hasClass('processing')) { diff --git a/admin/views/product-groups.php b/admin/views/product-groups.php index 86d572d..ed9dfdc 100644 --- a/admin/views/product-groups.php +++ b/admin/views/product-groups.php @@ -10,7 +10,7 @@ $groups = get_option('czl_product_groups', array());
-

+

@@ -20,10 +20,10 @@ $groups = get_option('czl_product_groups', array());
' . __('没有找到订单', 'czlexpress-for-woocommerce') . '
' . esc_html__('没有找到订单', 'czlexpress-for-woocommerce') . '
@@ -128,40 +128,40 @@ wp_enqueue_script('jquery'); tracking_number)): ?> - + tracking_number); ?>
- + czl_order_id); ?>
- + reference_number); ?>
- + shipment_status); ?> - +
tracking_number)): ?> czl_order_id)): ?>
- - - - + + + + @@ -41,7 +41,7 @@ $groups = get_option('czl_product_groups', array()); - + @@ -61,7 +61,7 @@ $groups = get_option('czl_product_groups', array()); @@ -83,7 +83,7 @@ $groups = get_option('czl_product_groups', array()); '); + $table.find('tbody').append(''); } }); }); diff --git a/assets/js/admin.js b/assets/js/admin.js index 0370fc2..96db624 100644 --- a/assets/js/admin.js +++ b/assets/js/admin.js @@ -65,9 +65,10 @@ jQuery(document).ready(function($) { }, success: function(response) { if (response.success) { + alert(response.data.message); location.reload(); } else { - alert(response.data); + alert(response.data.message); } }, error: function() { @@ -109,9 +110,10 @@ jQuery(document).ready(function($) { }, success: function(response) { if (response.success) { + alert('轨迹更新成功'); location.reload(); } else { - alert(response.data); + alert(response.data.message || '更新失败'); } }, error: function() { diff --git a/czlexpress-for-woocommerce.php b/czlexpress-for-woocommerce.php index 9846f8a..f0bc249 100644 --- a/czlexpress-for-woocommerce.php +++ b/czlexpress-for-woocommerce.php @@ -1,7 +1,7 @@

' . - esc_html__('CZL Express requires WooCommerce to be installed and active', 'czlexpress-for-woocommerce') . + esc_html__('CZL Express requires WooCommerce to be installed and activated', 'czlexpress-for-woocommerce') . '

'; }); return false; } - + + // 检查WooCommerce版本 if (version_compare(WC_VERSION, '6.0.0', '<')) { add_action('admin_notices', function() { echo '

' . @@ -102,23 +72,49 @@ function czl_express_check_environment() { return true; } +// 在插件激活时创建数据表 +register_activation_hook(__FILE__, 'czl_express_activate'); + +function czl_express_activate() { + // 确保加载安装类 + require_once CZL_EXPRESS_PATH . 'includes/class-czl-install.php'; + + // 创建数据表和默认选项 + CZL_Install::init(); + + // 记录版本号 + update_option('czl_express_version', CZL_EXPRESS_VERSION); +} + +// 在插件停用时清理 +register_deactivation_hook(__FILE__, function() { + // 清理定时任务 + wp_clear_scheduled_hook('czl_update_tracking_info'); +}); + +// 声明支持HPOS +add_action('before_woocommerce_init', function() { + if (class_exists('\Automattic\WooCommerce\Utilities\FeaturesUtil')) { + \Automattic\WooCommerce\Utilities\FeaturesUtil::declare_compatibility('custom_order_tables', __FILE__, true); + } +}); + // 初始化插件 function czl_express_init() { if (czl_express_check_environment()) { - // 加载语言文件 - load_plugin_textdomain( - 'czlexpress-for-woocommerce', - false, - dirname(plugin_basename(__FILE__)) . '/languages' - ); + CZL_Logger::info('Plugin initialization started'); // 加载必要的类文件 require_once CZL_EXPRESS_PATH . 'includes/class-czlexpress.php'; require_once CZL_EXPRESS_PATH . 'includes/class-czl-api.php'; require_once CZL_EXPRESS_PATH . 'includes/class-czl-order.php'; + require_once CZL_EXPRESS_PATH . 'includes/class-czl-ajax.php'; CZLExpress::instance(); + // 初始化AJAX处理器 + new CZL_Ajax(); + // 添加AJAX处理 add_action('wp_ajax_czl_create_shipment', 'czl_ajax_create_shipment'); add_action('wp_ajax_czl_update_tracking_number', 'czl_ajax_update_tracking_number'); @@ -129,6 +125,17 @@ function czl_express_init() { // 注册自定义订单状态 add_action('init', 'register_czl_order_statuses'); + + // 在init钩子中加载翻译文件 + add_action('init', function() { + load_plugin_textdomain( + 'czlexpress-for-woocommerce', + false, + dirname(plugin_basename(__FILE__)) . '/languages' + ); + }); + + CZL_Logger::info('Plugin initialization completed'); } } @@ -226,14 +233,14 @@ function czl_ajax_update_tracking_number() { check_ajax_referer('czl_ajax_nonce', 'nonce'); if (!current_user_can('edit_shop_orders')) { - wp_send_json_error('Permission denied'); + wp_send_json_error(array('message' => '权限不足')); } $order_id = isset($_POST['order_id']) ? intval($_POST['order_id']) : 0; $tracking_number = isset($_POST['tracking_number']) ? sanitize_text_field($_POST['tracking_number']) : ''; if (!$order_id || !$tracking_number) { - wp_send_json_error('Invalid parameters'); + wp_send_json_error(array('message' => '参数无效')); } try { @@ -241,10 +248,10 @@ function czl_ajax_update_tracking_number() { // 获取运单信息 $shipment = $wpdb->get_row($wpdb->prepare( - "SELECT id FROM {$wpdb->prefix}czl_shipments WHERE order_id = %d", + "SELECT * FROM {$wpdb->prefix}czl_shipments WHERE order_id = %d", $order_id )); - + if (!$shipment) { throw new Exception('运单不存在'); } @@ -270,7 +277,7 @@ function czl_ajax_update_tracking_number() { // 添加订单备注 $order->add_order_note(sprintf( - 'Tracking number updated to: %s', + '运单号已更新为: %s', $tracking_number )); } @@ -280,30 +287,42 @@ function czl_ajax_update_tracking_number() { $tracking->clear_tracking_cache($shipment->id, $tracking_number, $order_id); wp_send_json_success(array( - 'message' => '运单号更新成功' + 'message' => '运单号更新成功', + 'tracking_number' => $tracking_number )); } catch (Exception $e) { - wp_send_json_error($e->getMessage()); + wp_send_json_error(array('message' => $e->getMessage())); } } // 更新轨迹信息的AJAX处理函数 function czl_ajax_update_tracking_info() { - check_ajax_referer('czl_ajax_nonce', 'nonce'); - - if (!current_user_can('edit_shop_orders')) { - wp_send_json_error('权限不足'); + try { + // 验证nonce + if (!check_ajax_referer('czl_update_tracking_info', 'nonce', false)) { + throw new Exception('无效的请求'); + } + + // 验证权限 + if (!current_user_can('edit_shop_orders')) { + throw new Exception('权限不足'); + } + + $tracking_number = isset($_POST['tracking_number']) ? sanitize_text_field($_POST['tracking_number']) : ''; + if (empty($tracking_number)) { + throw new Exception('运单号不能为空'); + } + + $tracking = new CZL_Tracking(); + $result = $tracking->update_tracking_info($tracking_number); + + wp_send_json_success($result); + + } catch (Exception $e) { + CZL_Logger::error('Error updating tracking info', array('error' => $e->getMessage())); + wp_send_json_error(array('message' => $e->getMessage())); } - - $order_id = isset($_POST['order_id']) ? intval($_POST['order_id']) : 0; - if (!$order_id) { - wp_send_json_error('订单ID无效'); - } - - // 使用 wp_schedule_single_event 来异步处理更新 - wp_schedule_single_event(time(), 'czl_do_update_tracking_info', array($order_id)); - wp_send_json_success(array('message' => 'Update scheduled')); } // 异步处理轨迹更新 @@ -312,7 +331,10 @@ function czl_do_update_tracking_info($order_id) { $czl_order = new CZL_Order(); $czl_order->update_tracking_info($order_id); } catch (Exception $e) { - error_log('CZL Express: Error updating tracking info - ' . $e->getMessage()); + CZL_Logger::error('Error updating tracking info', array( + 'order_id' => $order_id, + 'error' => $e->getMessage() + )); } } add_action('czl_do_update_tracking_info', 'czl_do_update_tracking_info'); @@ -325,7 +347,10 @@ add_action('woocommerce_order_status_processing', function($order_id) { try { $czl_order->create_shipment($order_id); } catch (Exception $e) { - error_log('CZL Express: Auto create shipment failed - ' . $e->getMessage()); + CZL_Logger::error('Auto create shipment failed', array( + 'order_id' => $order_id, + 'error' => $e->getMessage() + )); } }); @@ -384,8 +409,14 @@ function czl_sync_tracking_numbers() { // 更新最后同步时间 update_option('czl_last_tracking_sync', $current_time); + CZL_Logger::info('Tracking sync scheduled', array( + 'shipment_count' => count($shipments) + )); + } catch (Exception $e) { - error_log('CZL Express: Tracking number sync failed - ' . $e->getMessage()); + CZL_Logger::error('Tracking number sync failed', array( + 'error' => $e->getMessage() + )); } } @@ -424,13 +455,15 @@ function czl_do_sync_single_tracking($order_id, $current_tracking, $czl_order_id $order->save(); $tracking_link = sprintf( - 'Track Your Package', - $response['tracking_number'] + '%s', + $response['tracking_number'], + __('查看物流', 'czlexpress-for-woocommerce') ); $order->add_order_note( sprintf( - 'Tracking number updated to: %s\n%s', + /* translators: 1: tracking number 2: tracking link */ + __('运单号已更新为: %1$s\n%2$s', 'czlexpress-for-woocommerce'), $response['tracking_number'], $tracking_link ), @@ -439,10 +472,9 @@ function czl_do_sync_single_tracking($order_id, $current_tracking, $czl_order_id } } } catch (Exception $e) { - error_log(sprintf( - 'CZL Express: Failed to sync tracking number for order %d: %s', - $order_id, - $e->getMessage() + CZL_Logger::error('Failed to sync tracking number', array( + 'order_id' => $order_id, + 'error' => $e->getMessage() )); } } diff --git a/includes/class-czl-api.php b/includes/class-czl-api.php index d67fc91..bc58445 100644 --- a/includes/class-czl-api.php +++ b/includes/class-czl-api.php @@ -46,10 +46,10 @@ class CZL_API { } $this->country_mapping = $mapping; set_transient('czl_country_mapping', $mapping, DAY_IN_SECONDS); - error_log('CZL Express: Country mapping updated'); + CZL_Logger::info('Country mapping updated'); } } catch (Exception $e) { - error_log('CZL Express Error: Failed to get country mapping - ' . $e->getMessage()); + CZL_Logger::error('Failed to get country mapping', array('error' => $e->getMessage())); $this->country_mapping = array(); } } @@ -58,7 +58,7 @@ class CZL_API { * 转换国家代码 */ private function convert_country_code($wc_country) { - error_log('CZL Express: Converting country code ' . $wc_country); + CZL_Logger::debug('Converting country code', array('country' => $wc_country)); // 获取WooCommerce国家名称 $countries = WC()->countries->get_countries(); @@ -67,13 +67,16 @@ class CZL_API { // 在映射中查找 foreach ($this->country_mapping as $name => $code) { if (stripos($name, $country_name) !== false || stripos($country_name, $name) !== false) { - error_log('CZL Express: Found country mapping ' . $wc_country . ' => ' . $code); + CZL_Logger::debug('Found country mapping', array( + 'from' => $wc_country, + 'to' => $code + )); return $code; } } // 如果没找到映射,返回原始代码 - error_log('CZL Express: No mapping found for ' . $wc_country . ', using original code'); + CZL_Logger::debug('No mapping found, using original code', array('country' => $wc_country)); return $wc_country; } @@ -94,13 +97,13 @@ class CZL_API { )); if (is_wp_error($response)) { - throw new Exception($response->get_error_message()); + throw new Exception(esc_html($response->get_error_message())); } $body = json_decode(wp_remote_retrieve_body($response), true); if (empty($body['success'])) { - throw new Exception(!empty($body['message']) ? esc_html($body['message']) : esc_html__('认证失败', 'woocommerce-czlexpress')); + throw new Exception(!empty($body['message']) ? esc_html($body['message']) : esc_html__('认证失败', 'czlexpress-for-woocommerce')); } $this->token = $body['data']['token']; @@ -115,33 +118,55 @@ class CZL_API { /** * 发送API请求 */ - private function request($endpoint, $method = 'GET', $data = null) { - $args = array( - 'method' => $method, - 'headers' => array( - 'Authorization' => $this->get_token(), - 'Content-Type' => 'application/json' - ), - 'timeout' => 30 - ); - - if ($data !== null) { - $args['body'] = wp_json_encode($data); + private function send_request($endpoint, $params = array(), $method = 'GET') { + try { + $url = $this->get_api_url($endpoint); + $headers = $this->get_headers(); + + $args = array( + 'method' => $method, + 'headers' => $headers, + 'timeout' => 30, + 'sslverify' => false + ); + + if ($method === 'POST') { + $args['body'] = json_encode($params); + CZL_Logger::debug('API request', array( + 'url' => $url, + 'method' => $method, + 'params' => $params + )); + } + + $response = wp_remote_request($url, $args); + + if (is_wp_error($response)) { + throw new Exception($response->get_error_message()); + } + + $body = wp_remote_retrieve_body($response); + $data = json_decode($body, true); + + CZL_Logger::debug('API response', array( + 'url' => $url, + 'response' => $data + )); + + if (!$data) { + throw new Exception('Invalid JSON response'); + } + + return $data; + + } catch (Exception $e) { + CZL_Logger::error('API request failed', array( + 'url' => $url, + 'error' => $e->getMessage(), + 'params' => $params + )); + throw $e; } - - $response = wp_remote_request($this->api_url . $endpoint, $args); - - if (is_wp_error($response)) { - throw new Exception($response->get_error_message()); - } - - $body = json_decode(wp_remote_retrieve_body($response), true); - - if (empty($body['success'])) { - throw new Exception(!empty($body['message']) ? esc_html($body['message']) : esc_html__('请求失败', 'woocommerce-czlexpress')); - } - - return $body['data']; } /** @@ -165,7 +190,7 @@ class CZL_API { 'postcode' => $params['postcode'] ); - error_log('CZL Express: Shipping rate request - ' . print_r($query, true)); + CZL_Logger::debug('Shipping rate request', $query); // 发送请求 $response = wp_remote_post($api_url . '?' . http_build_query($query), array( @@ -180,7 +205,7 @@ class CZL_API { } $body = wp_remote_retrieve_body($response); - error_log('CZL Express: API raw response - ' . $body); + CZL_Logger::debug('API raw response', $body); $data = json_decode($body, true); if (empty($data)) { @@ -195,7 +220,7 @@ class CZL_API { return $data; } catch (Exception $e) { - error_log('CZL Express API Error: ' . esc_html($e->getMessage())); + CZL_Logger::error('API Error', array('message' => $e->getMessage())); throw $e; } } @@ -225,7 +250,7 @@ class CZL_API { public function create_order($order_data) { try { // 添加请求前的日志 - error_log('CZL Express: Creating order with data - ' . print_r($order_data, true)); + CZL_Logger::debug('Creating order', array('data' => $order_data)); $response = wp_remote_post('https://tms.czl.net/createOrderApi.htm', array( 'body' => array( @@ -235,7 +260,7 @@ class CZL_API { )); // 添加响应日志 - error_log('CZL Express: Raw API response - ' . print_r($response, true)); + CZL_Logger::debug('API response received', array('response' => $response)); if (is_wp_error($response)) { throw new Exception('API请求失败: ' . $response->get_error_message()); @@ -247,14 +272,16 @@ class CZL_API { } if (empty($result['ack']) || $result['ack'] !== 'true') { - throw new Exception(!empty($result['message']) ? esc_html($result['message']) : esc_html__('未知错误', 'woocommerce-czlexpress')); + throw new Exception(!empty($result['message']) ? esc_html($result['message']) : esc_html__('未知错误', 'czlexpress-for-woocommerce')); } return $result; } catch (Exception $e) { - error_log('CZL Express Error: Create order failed - ' . esc_html($e->getMessage())); - error_log('CZL Express Error Stack Trace: ' . $e->getTraceAsString()); + CZL_Logger::error('Create order failed', array( + 'error' => $e->getMessage(), + 'trace' => $e->getTraceAsString() + )); throw $e; } } @@ -284,7 +311,7 @@ class CZL_API { return $result[0]['data'][0]; } catch (Exception $e) { - error_log('CZL Express API Error: ' . esc_html($e->getMessage())); + CZL_Logger::error('Failed to get tracking', array('error' => $e->getMessage())); throw $e; } } @@ -338,7 +365,7 @@ class CZL_API { ); } catch (Exception $e) { - error_log('CZL Express API Error: ' . esc_html($e->getMessage())); + CZL_Logger::error('Authentication test failed', array('error' => $e->getMessage())); throw $e; } } @@ -365,14 +392,14 @@ class CZL_API { return $result['data']; } catch (Exception $e) { - error_log('CZL Express API Error: ' . esc_html($e->getMessage())); + CZL_Logger::error('Failed to get countries list', array('error' => $e->getMessage())); throw $e; } } private function ensure_logged_in() { try { - error_log('CZL Express: Starting authentication'); + CZL_Logger::info('Starting authentication'); $auth_url = 'https://tms.czl.net/selectAuth.htm'; $auth_data = array( @@ -380,7 +407,7 @@ class CZL_API { 'password' => $this->password ); - error_log('CZL Express: Auth request data - ' . print_r($auth_data, true)); + CZL_Logger::debug('Auth request data', array('data' => $auth_data)); $ch = curl_init($auth_url); curl_setopt($ch, CURLOPT_POST, 1); @@ -394,7 +421,7 @@ class CZL_API { curl_setopt($ch, CURLOPT_TIMEOUT, 30); $response = curl_exec($ch); - error_log('CZL Express: Auth raw response - ' . $response); + CZL_Logger::debug('Auth raw response', array('response' => $response)); if (curl_errno($ch)) { throw new Exception('认证请求失败'); @@ -404,7 +431,7 @@ class CZL_API { // 解析响应 $result = json_decode(str_replace("'", '"', $response), true); - error_log('CZL Express: Auth decoded response - ' . print_r($result, true)); + CZL_Logger::debug('Auth decoded response', array('result' => $result)); if (empty($result) || !isset($result['customer_id'])) { throw new Exception('认证失败'); @@ -415,7 +442,7 @@ class CZL_API { $this->customer_userid = $result['customer_userid']; } catch (Exception $e) { - error_log('CZL Express Error: Authentication failed - ' . esc_html($e->getMessage())); + CZL_Logger::error('Authentication failed', array('error' => $e->getMessage())); throw new Exception('认证失败,请联系CZL Express'); } } @@ -441,7 +468,6 @@ class CZL_API { $args['body'] = is_array($data) ? $data : wp_json_encode($data); } - // 使用wp_remote_request替代curl $response = wp_remote_request($url, $args); if (is_wp_error($response)) { @@ -454,25 +480,25 @@ class CZL_API { throw new Exception('请求失败: 空响应'); } - // 记录响应日志 - if (defined('WP_DEBUG_LOG') && WP_DEBUG_LOG) { - error_log('CZL Express: Raw response - ' . $body); - } + CZL_Logger::debug('API raw response', array('response' => $body)); $result = json_decode($body, true); if (json_last_error() !== JSON_ERROR_NONE) { - if (defined('WP_DEBUG_LOG') && WP_DEBUG_LOG) { - error_log('CZL Express: JSON decode error - ' . json_last_error_msg()); - } + CZL_Logger::error('JSON decode error', array('error' => json_last_error_msg())); throw new Exception('响应数据格式错误'); } + CZL_Logger::debug('API decoded response', array('result' => $result)); + + // 检查API错误信息 + if (isset($result['message']) && !empty($result['message'])) { + CZL_Logger::warning('API returned error message', array('message' => $result['message'])); + } + return $result; } catch (Exception $e) { - if (defined('WP_DEBUG_LOG') && WP_DEBUG_LOG) { - error_log('CZL Express Error: Request failed - ' . esc_html($e->getMessage())); - } + CZL_Logger::error('Request failed', array('error' => $e->getMessage())); throw $e; } } @@ -544,74 +570,53 @@ class CZL_API { } } - public function create_shipment($params) { + /** + * 获取运单轨迹 + */ + public function get_tracking_info($tracking_number) { try { - if (defined('WP_DEBUG_LOG') && WP_DEBUG_LOG) { - error_log('CZL Express: Starting create shipment'); - } - - // 先进行认证 - $auth_result = $this->authenticate(); - if (!$auth_result['ack']) { - throw new Exception('认证失败: ' . $auth_result['message']); - } - - // 添加认证信息到参数 - $params['customer_id'] = $auth_result['customer_id']; - $params['customer_userid'] = $auth_result['customer_userid']; - - // 准备请求数据 - $request_data = array( - 'param' => wp_json_encode($params) - ); - - if (defined('WP_DEBUG_LOG') && WP_DEBUG_LOG) { - error_log('CZL Express: Create shipment request data - ' . print_r($request_data, true)); - } - - // 发送请求 - $response = wp_remote_post('https://tms.czl.net/createOrderApi.htm', array( - 'body' => $request_data, - 'timeout' => 30, - 'headers' => array( - 'Accept' => '*/*', - 'Accept-Language' => 'zh-cn', - 'Cache-Control' => 'no-cache', - 'Content-Type' => 'application/x-www-form-urlencoded;charset=UTF-8' - ) + $response = $this->send_request('/tracking/query', array( + 'tracking_number' => $tracking_number + ), 'POST'); + + CZL_Logger::debug('Tracking info retrieved', array( + 'tracking_number' => $tracking_number, + 'response' => $response )); - - if (is_wp_error($response)) { - throw new Exception('CURL错误: ' . $response->get_error_message()); - } - - $body = wp_remote_retrieve_body($response); - if (defined('WP_DEBUG_LOG') && WP_DEBUG_LOG) { - error_log('CZL Express: Raw response - ' . $body); - } - - $result = json_decode($body, true); - if (json_last_error() !== JSON_ERROR_NONE) { - throw new Exception('JSON解析错误: ' . json_last_error_msg()); - } - - if (defined('WP_DEBUG_LOG') && WP_DEBUG_LOG) { - error_log('CZL Express: Create shipment response - ' . print_r($result, true)); - } - - // 检查API错误信息 - if (isset($result['message']) && !empty($result['message'])) { - if (defined('WP_DEBUG_LOG') && WP_DEBUG_LOG) { - error_log('CZL Express: API error message - ' . $result['message']); - } - } - - return $result; - + + return $response; + } catch (Exception $e) { - if (defined('WP_DEBUG_LOG') && WP_DEBUG_LOG) { - error_log('CZL Express API Error: ' . esc_html($e->getMessage())); - } + CZL_Logger::error('Failed to get tracking info', array( + 'tracking_number' => $tracking_number, + 'error' => $e->getMessage() + )); + throw $e; + } + } + + /** + * 创建运单 + */ + public function create_shipment($order_data) { + try { + CZL_Logger::debug('Creating shipment', array( + 'order_data' => $order_data + )); + + $response = $this->send_request('/shipment/create', $order_data, 'POST'); + + CZL_Logger::debug('Shipment created', array( + 'response' => $response + )); + + return $response; + + } catch (Exception $e) { + CZL_Logger::error('Failed to create shipment', array( + 'order_data' => $order_data, + 'error' => $e->getMessage() + )); throw $e; } } @@ -646,95 +651,4 @@ class CZL_API { throw new Exception('获取跟踪单号失败: ' . esc_html($e->getMessage())); } } - - /** - * 获取运单跟踪信息 - */ - public function get_tracking_info($tracking_number) { - try { - $response = wp_remote_post('https://tms.czl.net/selectTrack.htm', array( - 'body' => array( - 'documentCode' => $tracking_number - ), - 'timeout' => 30, - 'headers' => array( - 'Accept-Encoding' => '', - 'Accept-Language' => 'zh-CN,zh;q=0.9' - ) - )); - - if (is_wp_error($response)) { - throw new Exception($response->get_error_message()); - } - - $body = wp_remote_retrieve_body($response); - error_log('CZL Express: Track raw response - ' . $body); - - // 处理中文编码问题 - $body = preg_replace('/[\x00-\x1F\x80-\xFF]/', '', $body); - $result = json_decode($body, true); - - if (json_last_error() !== JSON_ERROR_NONE) { - error_log('CZL Express: JSON decode error - ' . json_last_error_msg()); - throw new Exception('JSON解析失败: ' . json_last_error_msg()); - } - - error_log('CZL Express: Track decoded response - ' . print_r($result, true)); - - if (empty($result) || !isset($result[0])) { - throw new Exception('无效的API响应'); - } - - if (empty($result[0]['ack']) || $result[0]['ack'] !== 'true') { - throw new Exception('获取跟踪信息失败: ' . ($result[0]['message'] ?? '未知错误')); - } - - if (empty($result[0]['data']) || !is_array($result[0]['data'])) { - return array( - 'success' => true, - 'data' => array( - 'status' => 'pending', - 'track_content' => '暂无轨迹信息', - 'track_time' => current_time('mysql'), - 'track_location' => '' - ), - 'message' => '' - ); - } - - // 获取最新的轨迹状态 - $latest_track = $result[0]['data'][0]; - $track_details = $latest_track['trackDetails'] ?? array(); - $latest_detail = !empty($track_details) ? $track_details[0] : array(); - - // 根据轨迹内容判断状态 - $status = 'in_transit'; // 默认状态 - $track_content = strtolower($latest_detail['track_content'] ?? ''); - - if (strpos($track_content, 'delivered') !== false || strpos($track_content, 'signed') !== false) { - $status = 'delivered'; - } elseif (strpos($track_content, 'pickup') !== false || strpos($track_content, 'picked up') !== false) { - $status = 'picked_up'; - } - - return array( - 'success' => true, - 'data' => array( - 'status' => $status, - 'track_content' => $latest_detail['track_content'] ?? '', - 'track_time' => $latest_detail['track_date'] ?? current_time('mysql'), - 'track_location' => $latest_detail['track_location'] ?? '' - ), - 'message' => '' - ); - - } catch (Exception $e) { - error_log('CZL Express API Error: ' . esc_html($e->getMessage())); - return array( - 'success' => false, - 'data' => null, - 'message' => esc_html($e->getMessage()) - ); - } - } } \ No newline at end of file diff --git a/includes/class-czl-install.php b/includes/class-czl-install.php index 87c8f08..70aaece 100644 --- a/includes/class-czl-install.php +++ b/includes/class-czl-install.php @@ -23,6 +23,7 @@ class CZL_Install { is_residential varchar(10), shipping_method varchar(50), status varchar(20), + label_url text, last_sync_time datetime DEFAULT NULL, created_at datetime NOT NULL, updated_at datetime NOT NULL, @@ -47,30 +48,6 @@ class CZL_Install { public static function deactivate() { // 只清理定时任务 wp_clear_scheduled_hook('czl_sync_tracking_numbers_hook'); - } - - public static function uninstall() { - global $wpdb; - - // 只有在卸载时才删除数据 - if (!defined('WP_UNINSTALL_PLUGIN')) { - return; - } - - // 删除数据表 - $wpdb->query("DROP TABLE IF EXISTS {$wpdb->prefix}czl_shipments"); - $wpdb->query("DROP TABLE IF EXISTS {$wpdb->prefix}czl_tracking_history"); - $wpdb->query("DROP TABLE IF EXISTS {$wpdb->prefix}czl_shipping_rules"); - $wpdb->query("DROP TABLE IF EXISTS {$wpdb->prefix}czl_product_groups"); - - // 删除选项 - delete_option('czl_express_api_url'); - delete_option('czl_express_api_key'); - delete_option('czl_express_api_secret'); - delete_option('czl_express_test_mode'); - delete_option('czl_express_version'); - delete_option('czl_last_tracking_sync'); - delete_option('czl_express_db_version'); - delete_option('czl_product_groups'); + wp_clear_scheduled_hook('czl_update_tracking_info'); } } \ No newline at end of file diff --git a/includes/class-czl-label.php b/includes/class-czl-label.php index 23bffca..f8c4a97 100644 --- a/includes/class-czl-label.php +++ b/includes/class-czl-label.php @@ -11,37 +11,50 @@ class CZL_Label { */ public static function get_label_url($order_id) { try { - $order = wc_get_order($order_id); - if (!$order) { - throw new Exception('Order not found'); + $czl_order_id = get_post_meta($order_id, '_czl_order_id', true); + if (!$czl_order_id) { + throw new Exception('未找到CZL订单号'); } - // 获取运单号和订单号 - $tracking_number = $order->get_meta('_czl_tracking_number'); - $czl_order_id = $order->get_meta('_czl_order_id'); + $api = new CZL_API(); + $url = $api->get_label($czl_order_id); - // 构建标签URL - $base_url = 'https://tms.czl.net/printOrderLabel.htm'; - $params = array(); - - // 优先使用订单号 - if (!empty($czl_order_id)) { - $params['order_id'] = $czl_order_id; - $url = add_query_arg($params, $base_url); - return $url; + if (empty($url)) { + throw new Exception('获取标签URL失败'); } - // 如果没有订单号但有运单号,使用运单号 - if (!empty($tracking_number)) { - $params['documentCode'] = $tracking_number; - $url = add_query_arg($params, $base_url); - return $url; - } - - throw new Exception('No tracking number or order ID found'); + return $url; } catch (Exception $e) { - error_log('CZL Express Error: Failed to get label URL - ' . $e->getMessage()); + CZL_Logger::error('Failed to get label URL', array( + 'order_id' => $order_id, + 'error' => $e->getMessage() + )); + throw $e; + } + } + + /** + * 打印运单标签 + */ + public static function print_label($order_id) { + try { + $url = self::get_label_url($order_id); + + if (empty($url)) { + throw new Exception('标签URL为空'); + } + + // 保存标签URL + update_post_meta($order_id, '_czl_label_url', $url); + + return $url; + + } catch (Exception $e) { + CZL_Logger::error('Failed to print label', array( + 'order_id' => $order_id, + 'error' => $e->getMessage() + )); throw $e; } } @@ -60,7 +73,10 @@ class CZL_Label { ); } } catch (Exception $e) { - error_log('CZL Express Error: ' . $e->getMessage()); + CZL_Logger::error('Label print action error', array( + 'order_id' => $order->get_id(), + 'error' => $e->getMessage() + )); } return $actions; } @@ -70,19 +86,19 @@ class CZL_Label { */ public static function handle_print_request() { if (!current_user_can('edit_shop_orders')) { - wp_die(__('您没有权限执行此操作', 'czlexpress-for-woocommerce')); + wp_die(esc_html__('您没有权限执行此操作', 'czlexpress-for-woocommerce')); } check_admin_referer('czl_print_label'); $order_id = isset($_GET['order_id']) ? absint($_GET['order_id']) : 0; if (!$order_id) { - wp_die(__('订单ID无效', 'czlexpress-for-woocommerce')); + wp_die(esc_html__('订单ID无效', 'czlexpress-for-woocommerce')); } $label_url = self::get_label_url($order_id); if (!$label_url) { - wp_die(__('未找到运单标签', 'czlexpress-for-woocommerce')); + wp_die(esc_html__('未找到运单标签', 'czlexpress-for-woocommerce')); } wp_redirect($label_url); diff --git a/includes/class-czl-logger.php b/includes/class-czl-logger.php new file mode 100644 index 0000000..b2bf46b --- /dev/null +++ b/includes/class-czl-logger.php @@ -0,0 +1,76 @@ + 'czlexpress-for-woocommerce'); + + if ($data !== null) { + if (is_array($data) || is_object($data)) { + $message .= ' Data: ' . wp_json_encode($data); + } else { + $message .= ' Data: ' . strval($data); + } + } + + switch ($level) { + case 'error': + $logger->error($message, $context); + break; + case 'warning': + $logger->warning($message, $context); + break; + case 'info': + $logger->info($message, $context); + break; + case 'debug': + $logger->debug($message, $context); + break; + } + } + + /** + * 记录错误日志 + */ + public static function error($message, $data = null) { + self::log($message, $data, 'error'); + } + + /** + * 记录警告日志 + */ + public static function warning($message, $data = null) { + self::log($message, $data, 'warning'); + } + + /** + * 记录信息日志 + */ + public static function info($message, $data = null) { + self::log($message, $data, 'info'); + } + + /** + * 记录调试日志 + */ + public static function debug($message, $data = null) { + self::log($message, $data, 'debug'); + } +} \ No newline at end of file diff --git a/includes/class-czl-order-handler.php b/includes/class-czl-order-handler.php index d72b523..557ad6d 100644 --- a/includes/class-czl-order-handler.php +++ b/includes/class-czl-order-handler.php @@ -62,7 +62,10 @@ class CZL_Order_Handler { return $response; } } catch (Exception $e) { - error_log('CZL Express Error: Failed to create shipment - ' . $e->getMessage()); + CZL_Logger::error('Failed to create shipment', array( + 'order_id' => $order_id, + 'error' => $e->getMessage() + )); throw $e; } @@ -114,18 +117,24 @@ class CZL_Order_Handler { $e->getMessage() ); $order->add_order_note($error_message); - error_log('CZL Express Error: ' . $error_message); + CZL_Logger::error('Shipment cancellation failed', array( + 'order_id' => $order_id, + 'error' => $e->getMessage() + )); } } public function process_order_action($order) { try { - error_log('CZL Express: Processing order action for order ' . $order->get_id()); + CZL_Logger::info('Processing order action', array('order_id' => $order->get_id())); // 检查是否已经创建过运单 $tracking_number = $order->get_meta('_czl_tracking_number'); if (!empty($tracking_number)) { - error_log('CZL Express: Order already has tracking number: ' . $tracking_number); + CZL_Logger::info('Order already has tracking number', array( + 'order_id' => $order->get_id(), + 'tracking_number' => $tracking_number + )); return; } @@ -133,10 +142,16 @@ class CZL_Order_Handler { $czl_order = new CZL_Order(); $result = $czl_order->create_shipment($order->get_id()); - error_log('CZL Express: Create shipment result - ' . print_r($result, true)); + CZL_Logger::info('Create shipment result', array( + 'order_id' => $order->get_id(), + 'result' => $result + )); } catch (Exception $e) { - error_log('CZL Express Error: Failed to process order action - ' . $e->getMessage()); + CZL_Logger::error('Failed to process order action', array( + 'order_id' => $order->get_id(), + 'error' => $e->getMessage() + )); } } } \ No newline at end of file diff --git a/includes/class-czl-order.php b/includes/class-czl-order.php index f2661fa..f8dfb14 100644 --- a/includes/class-czl-order.php +++ b/includes/class-czl-order.php @@ -15,7 +15,7 @@ if (!class_exists('CZL_Order')) { global $wpdb; try { - error_log('CZL Express: Starting create shipment for order ' . $order_id); + CZL_Logger::info('Starting create shipment', array('order_id' => $order_id)); // 更新订单备注以显示处理状态 $order = wc_get_order($order_id); @@ -70,7 +70,10 @@ if (!class_exists('CZL_Order')) { // 调用API创建运单 $result = $this->api->create_shipment($shipment_data); - error_log('CZL Express: API response - ' . print_r($result, true)); + CZL_Logger::info('API response for shipment creation', array( + 'order_id' => $order_id, + 'response' => $result + )); // 检查API响应状态 if ($result['ack'] !== 'true') { @@ -131,8 +134,11 @@ if (!class_exists('CZL_Order')) { } } catch (Exception $e) { - error_log('CZL Express Error: Create shipment failed - ' . esc_html($e->getMessage())); - error_log('CZL Express Error Stack Trace: ' . esc_html($e->getTraceAsString())); + CZL_Logger::error('Create shipment failed', array( + 'order_id' => $order_id, + 'error' => $e->getMessage(), + 'trace' => $e->getTraceAsString() + )); // 添加错误提示到订单备注 if (isset($order)) { @@ -217,7 +223,10 @@ if (!class_exists('CZL_Order')) { // 获取轨迹信息 $api = new CZL_API(); $tracking_info = $api->get_tracking_info($shipment->tracking_number); - error_log('CZL Express: Tracking API response - ' . print_r($tracking_info, true)); + CZL_Logger::info('Tracking API response', array( + 'tracking_number' => $shipment->tracking_number, + 'response' => $tracking_info + )); // 处理API响应 if (!empty($tracking_info) && isset($tracking_info['success']) && $tracking_info['success'] == 1) { diff --git a/includes/class-czl-product-fields.php b/includes/class-czl-product-fields.php index 5ab72e4..f11c692 100644 --- a/includes/class-czl-product-fields.php +++ b/includes/class-czl-product-fields.php @@ -50,20 +50,56 @@ class CZL_Product_Fields { * 保存自定义字段 */ public function save_custom_fields($post_id) { - // 保存中文品名 - $name_cn = isset($_POST['_czl_name_cn']) ? sanitize_text_field($_POST['_czl_name_cn']) : ''; - update_post_meta($post_id, '_czl_name_cn', $name_cn); + // 验证nonce + if (!isset($_POST['czl_product_fields_nonce']) || + !wp_verify_nonce($_POST['czl_product_fields_nonce'], 'czl_save_product_fields')) { + return; + } - // 保存海关编码 - $hs_code = isset($_POST['_czl_hs_code']) ? sanitize_text_field($_POST['_czl_hs_code']) : ''; - update_post_meta($post_id, '_czl_hs_code', $hs_code); + // 检查自动保存 + if (defined('DOING_AUTOSAVE') && DOING_AUTOSAVE) { + return; + } - // 保存用途 - $usage = isset($_POST['_czl_usage']) ? sanitize_text_field($_POST['_czl_usage']) : ''; - update_post_meta($post_id, '_czl_usage', $usage); + // 检查权限 + if (!current_user_can('edit_product', $post_id)) { + return; + } - // 保存材质 - $material = isset($_POST['_czl_material']) ? sanitize_text_field($_POST['_czl_material']) : ''; - update_post_meta($post_id, '_czl_material', $material); + // 中文品名 + if (isset($_POST['_czl_name_cn'])) { + update_post_meta( + $post_id, + '_czl_name_cn', + sanitize_text_field(wp_unslash($_POST['_czl_name_cn'])) + ); + } + + // HS编码 + if (isset($_POST['_czl_hs_code'])) { + update_post_meta( + $post_id, + '_czl_hs_code', + sanitize_text_field(wp_unslash($_POST['_czl_hs_code'])) + ); + } + + // 用途 + if (isset($_POST['_czl_usage'])) { + update_post_meta( + $post_id, + '_czl_usage', + sanitize_text_field(wp_unslash($_POST['_czl_usage'])) + ); + } + + // 材质 + if (isset($_POST['_czl_material'])) { + update_post_meta( + $post_id, + '_czl_material', + sanitize_text_field(wp_unslash($_POST['_czl_material'])) + ); + } } } \ No newline at end of file diff --git a/includes/class-czl-rate-calculator.php b/includes/class-czl-rate-calculator.php index 5dcea05..541b748 100644 --- a/includes/class-czl-rate-calculator.php +++ b/includes/class-czl-rate-calculator.php @@ -154,16 +154,15 @@ class CZL_Rate_Calculator { $rate = $operator === '+' ? $rate + $amount : $rate - $amount; } - error_log(sprintf( - 'CZL Express: Adjusted rate from %f to %f using formula: %s', - $original_rate, - $rate, - $adjustment + CZL_Logger::debug('Rate adjustment', array( + 'original_rate' => $original_rate, + 'adjusted_rate' => $rate, + 'formula' => $adjustment )); return max(0, $rate); } catch (Exception $e) { - error_log('CZL Express: Rate adjustment error - ' . $e->getMessage()); + CZL_Logger::error('Rate adjustment error', array('error' => $e->getMessage())); return $rate; } } @@ -197,13 +196,16 @@ class CZL_Rate_Calculator { return $chargeable_weight * $quantity; } + /** + * 计算运费 + */ public function calculate_shipping_rate($package) { try { - error_log('CZL Express: Calculating shipping rate for package: ' . print_r($package, true)); + CZL_Logger::debug('Calculating shipping rate for package', array('package' => $package)); // 基本验证 if (empty($package['destination']['country'])) { - error_log('CZL Express: Empty destination country'); + CZL_Logger::warning('Empty destination country'); return array(); } @@ -229,11 +231,11 @@ class CZL_Rate_Calculator { 'height' => 10 // 添加固定尺寸 ); - error_log('CZL Express: API params with chargeable weight: ' . print_r($api_params, true)); + CZL_Logger::debug('API params with chargeable weight', array('params' => $api_params)); // 调用API获取运费 $api_rates = $this->api->get_shipping_rate($api_params); - error_log('CZL Express: API response: ' . print_r($api_rates, true)); + CZL_Logger::debug('API response', array('rates' => $api_rates)); if (empty($api_rates)) { return array(); @@ -305,12 +307,15 @@ class CZL_Rate_Calculator { return $show_all_rates === 'yes' ? array_values($all_rates) : array_values($grouped_rates); } catch (Exception $e) { - error_log('CZL Express Error: ' . $e->getMessage()); + CZL_Logger::error('Failed to calculate shipping rate', array('error' => $e->getMessage())); wc_add_notice($e->getMessage(), 'error'); return array(); } } + /** + * 翻译配送时间 + */ private function translate_delivery_time($delivery_time) { // 获取当前语言环境 $locale = determine_locale(); @@ -369,9 +374,7 @@ class CZL_Rate_Calculator { // 如果经过翻译后与原文相同,说明没有匹配到任何规则 if ($translated === $delivery_time) { - // 添加调试日志 - error_log('CZL Express: Unable to translate delivery time - ' . $delivery_time); - return $delivery_time; + CZL_Logger::warning('Unable to translate delivery time', array('delivery_time' => $delivery_time)); } return $translated; diff --git a/includes/class-czl-shipping-method.php b/includes/class-czl-shipping-method.php index b6dc0b0..a0c6c00 100644 --- a/includes/class-czl-shipping-method.php +++ b/includes/class-czl-shipping-method.php @@ -106,7 +106,7 @@ class WC_CZL_Shipping_Method extends WC_Shipping_Method { } try { - error_log('CZL Express: Starting shipping calculation'); + CZL_Logger::info('Starting shipping calculation'); $calculator = new CZL_Rate_Calculator(); $rates = $calculator->calculate_shipping_rate($package); @@ -131,13 +131,13 @@ class WC_CZL_Shipping_Method extends WC_Shipping_Method { )); } - error_log('CZL Express: Added ' . count($rates) . ' shipping rates'); + CZL_Logger::info('Added shipping rates', array('count' => count($rates))); } else { - error_log('CZL Express: No shipping rates available'); + CZL_Logger::info('No shipping rates available'); } } catch (Exception $e) { - error_log('CZL Express Error: Failed to calculate shipping - ' . $e->getMessage()); + CZL_Logger::error('Failed to calculate shipping', array('error' => $e->getMessage())); } } diff --git a/includes/class-czl-tracking.php b/includes/class-czl-tracking.php index 1ad36d5..a41bede 100644 --- a/includes/class-czl-tracking.php +++ b/includes/class-czl-tracking.php @@ -35,80 +35,72 @@ class CZL_Tracking { * 更新单个运单的轨迹信息 */ public function update_tracking_info($tracking_number) { - global $wpdb; - try { - // 获取运单信息 - $shipment = $wpdb->get_row($wpdb->prepare( - "SELECT * FROM {$wpdb->prefix}czl_shipments WHERE tracking_number = %s", - $tracking_number - )); + $api = new CZL_API(); + $tracking_info = $api->get_tracking_info($tracking_number); - if (!$shipment) { + if (!$tracking_info['success']) { + throw new Exception($tracking_info['message']); + } + + // 更新跟踪记录 + $this->update_tracking_record($tracking_number, $tracking_info['data']); + + return $tracking_info; + + } catch (Exception $e) { + CZL_Logger::error('Failed to update tracking info', array( + 'tracking_number' => $tracking_number, + 'error' => $e->getMessage() + )); + throw $e; + } + } + + /** + * 更新订单状态 + */ + public function update_order_status($order_id, $tracking_info) { + try { + $order = wc_get_order($order_id); + if (!$order) { return; } - // 获取轨迹信息 - $tracking_info = $this->api->get_tracking($tracking_number); + $status = $tracking_info['status']; + $content = $tracking_info['track_content']; + $location = $tracking_info['track_location']; + $time = $tracking_info['track_time']; - if (!empty($tracking_info['trackDetails'])) { - foreach ($tracking_info['trackDetails'] as $detail) { - // 检查是否已存在该轨迹记录 - $exists = $wpdb->get_var($wpdb->prepare( - "SELECT id FROM {$wpdb->prefix}czl_tracking_history - WHERE shipment_id = %d AND track_date = %s AND track_content = %s", - $shipment->id, - $detail['track_date'], - $detail['track_content'] - )); - - if (!$exists) { - // 插入新的轨迹记录 - $wpdb->insert( - $wpdb->prefix . 'czl_tracking_history', - array( - 'shipment_id' => $shipment->id, - 'tracking_number' => $tracking_number, - 'track_date' => $detail['track_date'], - 'track_location' => $detail['track_location'], - 'track_content' => $detail['track_content'], - 'created_at' => current_time('mysql') - ), - array('%d', '%s', '%s', '%s', '%s', '%s') - ); - } - } - - // 更新运单状态 - $latest = reset($tracking_info['trackDetails']); - $new_status = 'in_transit'; - - if (strpos($latest['track_content'], '已签收') !== false || - strpos($latest['track_content'], 'Delivered') !== false) { - $new_status = 'delivered'; - } - - // 更新运单状态 - $wpdb->update( - $wpdb->prefix . 'czl_shipments', - array('status' => $new_status), - array('id' => $shipment->id), - array('%s'), - array('%d') - ); - - // 更新WooCommerce订单状态 - $order = wc_get_order($shipment->order_id); - if ($order) { - $order->update_status($new_status, esc_html__('Package status updated from tracking info', 'czlexpress-for-woocommerce')); - } - - // 清除相关缓存 - $this->clear_tracking_cache($shipment->id, $tracking_number, $shipment->order_id); + // 添加订单备注 + $order->add_order_note(sprintf( + /* translators: 1: status 2: location 3: time 4: details */ + __('包裹状态: %1$s, 位置: %2$s, 时间: %3$s, 详情: %4$s', 'czlexpress-for-woocommerce'), + $status, + $location, + $time, + $content + )); + + // 更新订单状态 + switch ($status) { + case 'delivered': + $order->update_status('completed'); + break; + case 'in_transit': + $order->update_status('in_transit'); + break; + case 'picked_up': + $order->update_status('processing'); + break; } } catch (Exception $e) { - error_log('CZL Express Error: Failed to update tracking info - ' . $e->getMessage()); + CZL_Logger::error('Tracking error', array( + 'order_id' => $order_id, + 'error' => $e->getMessage() + )); + throw $e; } } @@ -180,7 +172,10 @@ class CZL_Tracking { echo '

'; } } catch (Exception $e) { - error_log('CZL Express Tracking Error: ' . $e->getMessage()); + CZL_Logger::error('Tracking display error', array( + 'tracking_number' => $tracking_number, + 'error' => $e->getMessage() + )); } } @@ -256,7 +251,7 @@ class CZL_Tracking { } if ($remote_text) { echo '

' . esc_html__('地区类型:', 'czlexpress-for-woocommerce') . ' ' . - $remote_text . '

'; + esc_html($remote_text) . '

'; } } diff --git a/includes/class-czlexpress.php b/includes/class-czlexpress.php index fce49d7..ef89781 100644 --- a/includes/class-czlexpress.php +++ b/includes/class-czlexpress.php @@ -153,15 +153,15 @@ class CZLExpress { public function render_product_groups_page() { // 处理表单提交 - if ($_SERVER['REQUEST_METHOD'] === 'POST' && + if (isset($_SERVER['REQUEST_METHOD']) && $_SERVER['REQUEST_METHOD'] === 'POST' && check_admin_referer('czl_save_product_groups', 'czl_product_groups_nonce')) { $groups = array(); if (!empty($_POST['groups'])) { - foreach ($_POST['groups'] as $key => $group) { + foreach (wp_unslash($_POST['groups']) as $key => $group) { if (empty($group['groupName'])) continue; - $prefixes = array_filter(array_map('trim', explode("\n", $group['prefixes']))); + $prefixes = array_filter(array_map('sanitize_text_field', array_map('trim', explode("\n", $group['prefixes'])))); if (empty($prefixes)) continue; $groups[sanitize_key($group['groupName'])] = array( @@ -333,7 +333,7 @@ class CZLExpress { public function render_exchange_rates_page() { // 处理表单提交 - if ($_SERVER['REQUEST_METHOD'] === 'POST' && + if (isset($_SERVER['REQUEST_METHOD']) && $_SERVER['REQUEST_METHOD'] === 'POST' && check_admin_referer('czl_save_exchange_rates', 'czl_exchange_rates_nonce')) { // 删除所有现有汇率 @@ -342,11 +342,10 @@ class CZLExpress { // 保存新的汇率 if (!empty($_POST['rates'])) { - foreach ($_POST['rates'] as $data) { + foreach (wp_unslash($_POST['rates']) as $data) { if (empty($data['currency']) || !isset($data['rate'])) continue; - $currency = sanitize_text_field($data['currency']); - $rate = (float)$data['rate']; + $rate = (float) $data['rate']; if ($rate > 0) { update_option('czl_exchange_rate_' . $currency, $rate); @@ -470,15 +469,33 @@ class CZLExpress { * 定时更新所有运输中订单的轨迹 */ public function schedule_tracking_updates() { - $orders = wc_get_orders(array( - 'status' => array('shipping'), - 'limit' => -1, - 'meta_key' => '_czl_tracking_number', - 'meta_compare' => 'EXISTS' - )); + global $wpdb; - foreach ($orders as $order) { - $this->order_handler->update_tracking_info($order->get_id()); + // 从自定义表中获取需要更新的运单 + $shipments = $wpdb->get_results( + $wpdb->prepare( + "SELECT order_id FROM {$wpdb->prefix}czl_shipments + WHERE status NOT IN ('delivered', 'cancelled', 'failed') + AND tracking_number IS NOT NULL + ORDER BY last_sync_time ASC + LIMIT %d", + 50 // 每次处理的最大数量 + ) + ); + + if (empty($shipments)) { + return; + } + + foreach ($shipments as $shipment) { + try { + $this->order_handler->update_tracking_info($shipment->order_id); + } catch (Exception $e) { + CZL_Logger::error('Failed to update tracking info', array( + 'order_id' => $shipment->order_id, + 'error' => $e->getMessage() + )); + } } } @@ -543,7 +560,10 @@ class CZLExpress { } } catch (Exception $e) { - error_log('CZL Express Error: ' . $e->getMessage()); + CZL_Logger::error('Shipment creation error', array( + 'error' => $e->getMessage(), + 'order_id' => isset($order) ? $order->get_id() : null + )); if (isset($order)) { $order->add_order_note( sprintf( diff --git a/templates/shipping-method-group.php b/templates/shipping-method-group.php index 5f9ebfb..3ab3edd 100644 --- a/templates/shipping-method-group.php +++ b/templates/shipping-method-group.php @@ -25,7 +25,7 @@ defined('ABSPATH') || exit; remote_fee > 0): ?>
remote_fee)) diff --git a/uninstall.php b/uninstall.php new file mode 100644 index 0000000..fd3924f --- /dev/null +++ b/uninstall.php @@ -0,0 +1,46 @@ +query("DROP TABLE IF EXISTS {$wpdb->prefix}{$table}"); +} + +// 删除所有相关的选项 +$options = array( + 'czl_express_api_url', + 'czl_express_api_key', + 'czl_express_api_secret', + 'czl_express_test_mode', + 'czl_express_version', + 'czl_last_tracking_sync', + 'czl_express_db_version', + 'czl_product_groups', + 'czl_username', + 'czl_password', + 'czl_rate_adjustment' +); + +foreach ($options as $option) { + delete_option($option); +} + +// 删除所有订单的相关元数据 +$wpdb->query("DELETE FROM {$wpdb->postmeta} WHERE meta_key LIKE '_czl_%'"); + +// 清理定时任务 +wp_clear_scheduled_hook('czl_sync_tracking_numbers_hook'); +wp_clear_scheduled_hook('czl_update_tracking_info'); \ No newline at end of file
-

+

-

+