From c74d6ecb97350beead08466c4fed33dd9da7bbd0 Mon Sep 17 00:00:00 2001 From: wood chen Date: Thu, 19 Dec 2024 22:15:04 +0800 Subject: [PATCH] Enhance CZL Express Plugin Functionality - Implemented AJAX functionality for printing shipment labels. - Added deactivation hook to clean up scheduled tasks. - Improved order shipment creation process with error handling and logging. - Updated order management UI to reflect new shipment and tracking features. - Added custom fields for product details (Chinese name, HS code, usage, material). - Introduced new order statuses for better tracking (In Transit, Delivered). - Enhanced shipping rate calculation and grouping logic. These changes improve the overall user experience and functionality of the CZL Express plugin. --- admin/views/orders.php | 41 ++++++-- includes/class-czl-ajax.php | 24 +++++ includes/class-czl-api.php | 125 ++++++++++++++++--------- includes/class-czl-label.php | 64 ++++++++++--- includes/class-czl-order-handler.php | 77 +++++++++------ includes/class-czl-order.php | 93 ++++++++++++------ includes/class-czl-product-fields.php | 46 +++++++-- includes/class-czl-rate-calculator.php | 117 ++++++++++++----------- includes/class-czl-shipping-method.php | 13 ++- includes/class-czl-tracking.php | 73 ++++++++++++++- includes/class-woo-czl-express.php | 52 +++++----- woocommerce-czlexpress.php | 15 ++- 12 files changed, 517 insertions(+), 223 deletions(-) diff --git a/admin/views/orders.php b/admin/views/orders.php index 7a80ab0..5f2f6c5 100644 --- a/admin/views/orders.php +++ b/admin/views/orders.php @@ -47,7 +47,6 @@ $orders = $orders_query->get_orders(); $tracking_number = $order->get_meta('_czl_tracking_number'); $czl_order_id = $order->get_meta('_czl_order_id'); $reference_number = $order->get_meta('_czl_reference_number'); - $label_url = $order->get_meta('_czl_label_url'); $shipping_methods = $order->get_shipping_methods(); $shipping_method = current($shipping_methods); @@ -78,19 +77,19 @@ $orders = $orders_query->get_orders();
-
- - - - - + - - + + + @@ -183,4 +182,28 @@ jQuery(document).ready(function($) { }); }); }); + +// 打印标签功能 +function printLabel(orderId) { + jQuery.ajax({ + url: ajaxurl, + type: 'POST', + data: { + action: 'czl_print_label', + order_id: orderId, + security: '' + }, + success: function(response) { + if (response.success && response.data.url) { + // 在新窗口打开标签 + window.open(response.data.url, '_blank'); + } else { + alert(response.data.message || '获取标签失败'); + } + }, + error: function() { + alert('请求失败,请重试'); + } + }); +} \ No newline at end of file diff --git a/includes/class-czl-ajax.php b/includes/class-czl-ajax.php index de2fc78..6c1d66c 100644 --- a/includes/class-czl-ajax.php +++ b/includes/class-czl-ajax.php @@ -3,6 +3,7 @@ class CZL_Ajax { public function __construct() { add_action('wp_ajax_czl_test_connection', array($this, 'test_connection')); add_action('wp_ajax_czl_test_shipping_rate', array($this, 'test_shipping_rate')); + add_action('wp_ajax_czl_print_label', array($this, 'handle_print_label')); } public function test_connection() { @@ -38,4 +39,27 @@ class CZL_Ajax { wp_send_json_error($result); } } + + public function handle_print_label() { + try { + check_ajax_referer('czl-print-label', 'security'); + + if (!current_user_can('manage_woocommerce')) { + throw new Exception('权限不足'); + } + + $order_id = isset($_POST['order_id']) ? intval($_POST['order_id']) : 0; + if (!$order_id) { + throw new Exception('订单ID无效'); + } + + $label = new CZL_Label(); + $url = $label->get_label_url($order_id); + + wp_send_json_success(array('url' => $url)); + + } catch (Exception $e) { + wp_send_json_error(array('message' => $e->getMessage())); + } + } } \ No newline at end of file diff --git a/includes/class-czl-api.php b/includes/class-czl-api.php index d5c7f8a..eb88fbd 100644 --- a/includes/class-czl-api.php +++ b/includes/class-czl-api.php @@ -420,73 +420,106 @@ class CZL_API { } } - public function create_shipment($data) { + private function make_request($url, $data = array(), $method = 'POST') { try { - error_log('CZL Express: Starting create shipment'); + $ch = curl_init(); - // 确保已登录 - $this->ensure_logged_in(); - - // 使用类属性中的认证信息 - $data['customer_id'] = $this->customer_id; - $data['customer_userid'] = $this->customer_userid; - - $api_url = 'https://tms.czl.net/createOrderApi.htm'; - - // 构建请求数据 - $request_data = array( - 'param' => json_encode($data, JSON_UNESCAPED_UNICODE) + $curl_options = array( + CURLOPT_URL => $url, + CURLOPT_RETURNTRANSFER => true, + CURLOPT_HEADER => false, + CURLOPT_SSL_VERIFYPEER => true, + CURLOPT_SSL_VERIFYHOST => 2, + CURLOPT_TIMEOUT => 60, // 增加超时时间到60秒 + CURLOPT_CONNECTTIMEOUT => 30, // 连接超时时间30秒 + CURLOPT_VERBOSE => true, // 启用详细日志 + CURLOPT_HTTPHEADER => array( + 'Accept: */*', + 'Accept-Language: zh-cn', + 'Cache-Control: no-cache', + 'Content-Type: application/x-www-form-urlencoded;charset=UTF-8' + ) ); - error_log('CZL Express: Create shipment request data - ' . print_r($request_data, true)); + if ($method === 'POST') { + $curl_options[CURLOPT_POST] = true; + if (!empty($data)) { + // 确保数据正确编码 + $post_data = is_array($data) ? http_build_query($data) : $data; + $curl_options[CURLOPT_POSTFIELDS] = $post_data; + } + } - $ch = curl_init($api_url); - curl_setopt($ch, CURLOPT_POST, 1); - curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); - curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($request_data)); - curl_setopt($ch, CURLOPT_HTTPHEADER, array( - 'Accept-Language: zh-cn', - 'Connection: Keep-Alive', - 'Cache-Control: no-cache', - 'Content-Type: application/x-www-form-urlencoded;charset=UTF-8' - )); - curl_setopt($ch, CURLOPT_TIMEOUT, 30); + curl_setopt_array($ch, $curl_options); - // 添加更多调试信息 - curl_setopt($ch, CURLOPT_VERBOSE, true); + // 捕获详细日志 $verbose = fopen('php://temp', 'w+'); curl_setopt($ch, CURLOPT_STDERR, $verbose); $response = curl_exec($ch); + $error = curl_error($ch); + $errno = curl_errno($ch); - // 记录详细的curl信息 - if (curl_errno($ch)) { - rewind($verbose); - $verboseLog = stream_get_contents($verbose); - error_log('CZL Express: Curl verbose log - ' . $verboseLog); - error_log('CZL Express: Curl error - ' . curl_error($ch)); - throw new Exception('请求失败: ' . curl_error($ch)); - } - - error_log('CZL Express: Create shipment raw response - ' . $response); - error_log('CZL Express: Response info - ' . print_r(curl_getinfo($ch), true)); - - curl_close($ch); + // 记录详细日志 + rewind($verbose); + $verbose_log = stream_get_contents($verbose); + error_log('CZL Express: Curl verbose log - ' . $verbose_log); fclose($verbose); - // 检查响应是否为空 - if (empty($response)) { - throw new Exception('服务器未返回数据'); + if ($errno) { + error_log('CZL Express: Curl error - ' . $error); + throw new Exception('请求失败: ' . $error); } - // 解析响应 + if ($response === false) { + throw new Exception('请求失败'); + } + + error_log('CZL Express: Raw response - ' . $response); + $result = json_decode($response, true); if (json_last_error() !== JSON_ERROR_NONE) { error_log('CZL Express: JSON decode error - ' . json_last_error_msg()); throw new Exception('响应数据格式错误'); } - error_log('CZL Express: Create shipment decoded response - ' . print_r($result, true)); + return $result; + + } catch (Exception $e) { + error_log('CZL Express Error: Request failed - ' . $e->getMessage()); + throw $e; + } finally { + if (isset($ch)) { + curl_close($ch); + } + } + } + + public function create_shipment($data) { + try { + error_log('CZL Express: Starting create shipment'); + + // 确保已认证 + $this->ensure_logged_in(); + + // 添加认证信息 + $data['customer_id'] = $this->customer_id; + $data['customer_userid'] = $this->customer_userid; + + // 准备请求数据 + $request_data = array( + 'param' => json_encode($data, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES) + ); + + error_log('CZL Express: Create shipment request data - ' . print_r($request_data, true)); + + // 修改这里:使用完整的URL + $api_url = 'https://tms.czl.net/createOrderApi.htm'; // 使用完整URL + + // 发送请求 + $result = $this->make_request($api_url, $request_data); + + error_log('CZL Express: Create shipment response - ' . print_r($result, true)); if (!isset($result['ack']) || $result['ack'] !== 'true') { $error_msg = isset($result['message']) ? urldecode($result['message']) : '未知错误'; diff --git a/includes/class-czl-label.php b/includes/class-czl-label.php index 3df302f..065586a 100644 --- a/includes/class-czl-label.php +++ b/includes/class-czl-label.php @@ -1,28 +1,63 @@ get_meta('_czl_tracking_number'); + $czl_order_id = $order->get_meta('_czl_order_id'); + + if (empty($tracking_number) && empty($czl_order_id)) { + throw new Exception('未找到运单号或订单号'); + } + + // 构建标签URL + $base_url = 'https://tms.czl.net/printOrderLabel.htm'; + $params = array(); + + if (!empty($tracking_number)) { + $params['documentCode'] = $tracking_number; + } else { + $params['order_id'] = $czl_order_id; + } + + $url = add_query_arg($params, $base_url); + return $url; + + } catch (Exception $e) { + error_log('CZL Express Error: Failed to get label URL - ' . $e->getMessage()); + throw $e; } - - $api = new CZL_API(); - return $api->get_label($czl_order_id); } /** * 添加标签打印按钮 */ public static function add_print_actions($actions, $order) { - if (self::get_label_url($order->get_id())) { - $actions['czl_print_label'] = array( - 'url' => wp_nonce_url(admin_url('admin-ajax.php?action=czl_print_label&order_id=' . $order->get_id()), 'czl_print_label'), - 'name' => __('打印运单', 'woo-czl-express'), - 'action' => 'czl_print_label' - ); + try { + $url = self::get_label_url($order->get_id()); + if ($url) { + $actions['czl_print_label'] = array( + 'url' => wp_nonce_url(admin_url('admin-ajax.php?action=czl_print_label&order_id=' . $order->get_id()), 'czl_print_label'), + 'name' => __('打印运单', 'woo-czl-express'), + 'action' => 'czl_print_label' + ); + } + } catch (Exception $e) { + error_log('CZL Express Error: ' . $e->getMessage()); } return $actions; } @@ -50,4 +85,7 @@ class CZL_Label { wp_redirect($label_url); exit; } -} \ No newline at end of file +} + +// 在插件初始化时调用 +add_action('init', array('CZL_Label', 'init')); \ No newline at end of file diff --git a/includes/class-czl-order-handler.php b/includes/class-czl-order-handler.php index fe83291..c709967 100644 --- a/includes/class-czl-order-handler.php +++ b/includes/class-czl-order-handler.php @@ -10,41 +10,56 @@ class CZL_Order_Handler { * 创建运单 */ public function create_shipment($order_id) { + $order = wc_get_order($order_id); + if (!$order) { + return; + } + + // 检查是否已创建运单 + $tracking_number = get_post_meta($order_id, '_czl_tracking_number', true); + if ($tracking_number) { + return; + } + + // 检查是否使用CZL Express配送 + if (!$this->is_czl_shipping($order)) { + return; + } + try { - $order = wc_get_order($order_id); - if (!$order) { - return; + // 准备订单数据 + $order_data = new CZL_Order_Data($order); + $data = $order_data->prepare(); + + // 调用API创建运单 + $response = $this->api->create_order($data); + + if (!empty($response['order_id']) && !empty($response['tracking_number'])) { + // 保存运单信息 + update_post_meta($order_id, '_czl_order_id', $response['order_id']); + update_post_meta($order_id, '_czl_tracking_number', $response['tracking_number']); + + // 添加订单备注 + $note = sprintf( + __('CZL Express运单创建成功。运单号: %s', 'woo-czl-express'), + $response['tracking_number'] + ); + $order->add_order_note($note); + + // 获取并保存运单标签URL + $label_url = $this->api->get_label($response['order_id']); + if ($label_url) { + update_post_meta($order_id, '_czl_label_url', $label_url); + } } - // 检查是否已创建运单 - $tracking_number = get_post_meta($order_id, '_czl_tracking_number', true); - if ($tracking_number) { - return; - } - - // 检查是否使用CZL Express配送 - if (!$this->is_czl_shipping($order)) { - return; - } - - // 使用统一的CZL_Order类创建运单 - $czl_order = new CZL_Order(); - $result = $czl_order->create_shipment($order_id); - - return $result; - } catch (Exception $e) { - error_log('CZL Express Error: ' . $e->getMessage()); - if (isset($order)) { - $order->add_order_note( - sprintf( - __('CZL Express运单创建失败: %s', 'woo-czl-express'), - $e->getMessage() - ), - true - ); - } - throw $e; + $error_message = sprintf( + __('CZL Express运单创建失败: %s', 'woo-czl-express'), + $e->getMessage() + ); + $order->add_order_note($error_message); + error_log('CZL Express Error: ' . $error_message); } } diff --git a/includes/class-czl-order.php b/includes/class-czl-order.php index 3f7c2a2..c4b305b 100644 --- a/includes/class-czl-order.php +++ b/includes/class-czl-order.php @@ -34,16 +34,21 @@ if (!class_exists('CZL_Order')) { throw new Exception('未找到运输方式ID'); } + // 在create_shipment方法中添加手机号和联系电话 + $phone = $order->get_billing_phone(); + // 清理电话号码,只保留数字 + $phone = preg_replace('/[^0-9]/', '', $phone); + // 准备运单数据 $shipment_data = array( 'buyerid' => $order->get_id(), 'consignee_address' => $order->get_shipping_address_1() . ' ' . $order->get_shipping_address_2(), 'consignee_city' => $order->get_shipping_city(), - 'consignee_mobile' => $order->get_billing_phone(), + 'consignee_mobile' => $order->get_billing_phone(), // 使用原始手机号 + 'consignee_telephone' => $order->get_billing_phone(), // 使用原始手机号作为联系电话 'consignee_name' => $order->get_shipping_first_name() . ' ' . $order->get_shipping_last_name(), 'consignee_postcode' => $order->get_shipping_postcode(), 'consignee_state' => $order->get_shipping_state(), - 'consignee_email' => $order->get_billing_email(), 'country' => $order->get_shipping_country(), 'order_piece' => $this->get_order_items_count($order), 'product_id' => $product_id, @@ -59,58 +64,88 @@ if (!class_exists('CZL_Order')) { continue; } + // 获取中文品名 + $name_cn = $product->get_meta('_czl_name_cn'); + if (empty($name_cn)) { + throw new Exception('产品 ' . $product->get_name() . ' 缺少中文品名'); + } + // 获取海关编码 $hs_code = $product->get_meta('_czl_hs_code'); if (empty($hs_code)) { throw new Exception('产品 ' . $product->get_name() . ' 缺少海关编码'); } + // 获取用途和材质 + $usage = $product->get_meta('_czl_usage'); + if (empty($usage)) { + throw new Exception('产品 ' . $product->get_name() . ' 缺少用途信息'); + } + + $material = $product->get_meta('_czl_material'); + if (empty($material)) { + throw new Exception('产品 ' . $product->get_name() . ' 缺少材质信息'); + } + $shipment_data['orderInvoiceParam'][] = array( 'invoice_amount' => $item->get_total(), 'invoice_pcs' => $item->get_quantity(), - 'invoice_title' => $item->get_name(), + 'invoice_title' => $item->get_name(), // 英文品名(原商品名) 'invoice_weight' => $product->get_weight() * $item->get_quantity(), + 'sku' => $name_cn, // 中文品名 + 'hs_code' => $hs_code, // 海关编码 + 'invoice_material' => $material, // 材质 + 'invoice_purpose' => $usage, // 用途 'item_id' => $product->get_id(), - 'sku' => $product->get_sku(), - 'hs_code' => $hs_code // 添加海关编码 + 'sku_code' => $product->get_sku() // SKU作为配货信息 ); } // 调用API创建运单 $result = $this->api->create_shipment($shipment_data); - if (!empty($result['tracking_number'])) { + // 记录API响应 + error_log('CZL Express: Create shipment response - ' . print_r($result, true)); + + // 检查是否有订单号,即使API返回失败 + if (!empty($result['order_id'])) { // 更新订单元数据 - $order->update_meta_data('_czl_tracking_number', $result['tracking_number']); $order->update_meta_data('_czl_order_id', $result['order_id']); - $order->update_meta_data('_czl_reference_number', $result['reference_number']); - $order->update_meta_data('_czl_order_privatecode', $result['order_privatecode']); - $order->update_meta_data('_czl_order_transfercode', $result['order_transfercode']); - $order->update_meta_data('_czl_label_url', $result['label_url']); - // 添加订单备注 - $order->add_order_note( - sprintf( - __('CZL Express运单创建成功。 - 运单号: %s - 订单号: %s - 参考号: %s', - 'woo-czl-express'), - $result['tracking_number'], + // 如果有跟踪号,也保存下来 + if (!empty($result['tracking_number'])) { + $order->update_meta_data('_czl_tracking_number', $result['tracking_number']); + } + + // 保存偏远地区信息(如果有) + if (isset($result['is_remote'])) { + $order->update_meta_data('_czl_is_remote', $result['is_remote']); + } + if (isset($result['is_residential'])) { + $order->update_meta_data('_czl_is_residential', $result['is_residential']); + } + + // 如果API返回失败但有订单号,记录错误信息 + if ($result['ack'] !== 'true') { + $error_msg = isset($result['message']) ? urldecode($result['message']) : 'Unknown error'; + $order->add_order_note(sprintf( + __('Shipment partially created. Order ID: %s. Error: %s', 'woo-czl-express'), $result['order_id'], - $result['reference_number'] - ), - true - ); - - // 更新订单状态 - $order->update_status('shipping', __('运单已创建,包裹开始运输', 'woo-czl-express')); + $error_msg + )); + $order->update_status('on-hold', __('Shipment needs manual processing', 'woo-czl-express')); + } else { + $order->update_status('in_transit', __('Package in transit', 'woo-czl-express')); + } $order->save(); + + // 即使API返回失败,只要有订单号就返回结果 + return $result; + } else { + throw new Exception('创建运单失败:未获取到订单号'); } - return $result; - } catch (Exception $e) { error_log('CZL Express Error: ' . $e->getMessage()); throw $e; diff --git a/includes/class-czl-product-fields.php b/includes/class-czl-product-fields.php index 2b4e1ca..2864f78 100644 --- a/includes/class-czl-product-fields.php +++ b/includes/class-czl-product-fields.php @@ -6,23 +6,41 @@ class CZL_Product_Fields { } /** - * 添加自定义字段 + * 添加自定义字段到产品编辑页面 */ public function add_custom_fields() { echo '
'; + // 中文品名字段 woocommerce_wp_text_input(array( - 'id' => '_czl_name_en', - 'label' => __('英文品名', 'woo-czl-express'), - 'description' => __('用于国际物流申报', 'woo-czl-express'), + 'id' => '_czl_name_cn', + 'label' => __('中文品名', 'woo-czl-express'), 'desc_tip' => true, + 'description' => __('输入产品的中文名称,用于物流申报', 'woo-czl-express') )); + // 海关编码字段 woocommerce_wp_text_input(array( 'id' => '_czl_hs_code', - 'label' => __('HS编码', 'woo-czl-express'), - 'description' => __('海关商品编码', 'woo-czl-express'), + 'label' => __('海关编码 (HS Code)', 'woo-czl-express'), 'desc_tip' => true, + 'description' => __('输入产品的海关编码 (HS Code)', 'woo-czl-express') + )); + + // 用途字段 + woocommerce_wp_text_input(array( + 'id' => '_czl_usage', + 'label' => __('用途', 'woo-czl-express'), + 'desc_tip' => true, + 'description' => __('输入产品的用途,例如:日常使用、装饰等', 'woo-czl-express') + )); + + // 材质字段 + woocommerce_wp_text_input(array( + 'id' => '_czl_material', + 'label' => __('材质', 'woo-czl-express'), + 'desc_tip' => true, + 'description' => __('输入产品的材质,例如:塑料、金属、布料等', 'woo-czl-express') )); echo '
'; @@ -32,10 +50,20 @@ class CZL_Product_Fields { * 保存自定义字段 */ public function save_custom_fields($post_id) { - $name_en = isset($_POST['_czl_name_en']) ? sanitize_text_field($_POST['_czl_name_en']) : ''; - $hs_code = isset($_POST['_czl_hs_code']) ? sanitize_text_field($_POST['_czl_hs_code']) : ''; + // 保存中文品名 + $name_cn = isset($_POST['_czl_name_cn']) ? sanitize_text_field($_POST['_czl_name_cn']) : ''; + update_post_meta($post_id, '_czl_name_cn', $name_cn); - update_post_meta($post_id, '_czl_name_en', $name_en); + // 保存海关编码 + $hs_code = isset($_POST['_czl_hs_code']) ? sanitize_text_field($_POST['_czl_hs_code']) : ''; update_post_meta($post_id, '_czl_hs_code', $hs_code); + + // 保存用途 + $usage = isset($_POST['_czl_usage']) ? sanitize_text_field($_POST['_czl_usage']) : ''; + update_post_meta($post_id, '_czl_usage', $usage); + + // 保存材质 + $material = isset($_POST['_czl_material']) ? sanitize_text_field($_POST['_czl_material']) : ''; + update_post_meta($post_id, '_czl_material', $material); } } \ No newline at end of file diff --git a/includes/class-czl-rate-calculator.php b/includes/class-czl-rate-calculator.php index 03e76fa..1605522 100644 --- a/includes/class-czl-rate-calculator.php +++ b/includes/class-czl-rate-calculator.php @@ -254,31 +254,13 @@ class CZL_Rate_Calculator { $all_rates = array(); // 存储所有线路 foreach ($api_rates as $rate) { - $product_name = $rate['product_name']; - $group_found = false; + $product_name = isset($rate['product_name']) ? $rate['product_name'] : ''; + $product_id = isset($rate['product_id']) ? $rate['product_id'] : ''; + $delivery_time = isset($rate['product_aging']) ? $rate['product_aging'] : ''; + $amount = isset($rate['total_amount']) ? floatval($rate['total_amount']) : 0; // 调整运费 - $adjusted_amount = $this->adjust_shipping_rate(floatval($rate['total_amount'])); - - // 添加单独的线路选项 - $rate_id = sanitize_title($product_name); - $all_rates[$rate_id] = array( - 'id' => 'czl_express_' . $rate_id, - 'label' => sprintf( - '%s (%s)', - $product_name, - $this->translate_delivery_time($rate['product_aging']) - ), - 'cost' => $this->convert_currency($adjusted_amount), - 'calc_tax' => 'per_order', - 'meta_data' => array( - 'product_id' => $rate['product_id'], - 'delivery_time' => $rate['product_aging'], - 'is_group' => false, - 'original_amount' => $rate['total_amount'], - 'adjusted_amount' => $adjusted_amount - ) - ); + $adjusted_amount = $this->adjust_shipping_rate($amount); // 查找匹配的分组 foreach ($this->product_groups as $group_key => $group) { @@ -286,41 +268,49 @@ class CZL_Rate_Calculator { if (strpos($product_name, $prefix) === 0) { $group_id = sanitize_title($group['groupName']); if (!isset($grouped_rates[$group_id]) || - $rate['total_amount'] < $grouped_rates[$group_id]['meta_data']['original_amount']) { + $amount < $grouped_rates[$group_id]['meta_data']['original_amount']) { + + // 构建分组运费数据 $grouped_rates[$group_id] = array( - 'id' => 'czl_express_group_' . $group_id, - 'label' => sprintf( + 'product_id' => $product_id, + 'method_title' => sprintf( '%s (%s)', $group['groupName'], - $this->translate_delivery_time($rate['product_aging']) + $this->translate_delivery_time($delivery_time) ), - 'cost' => $this->convert_currency(floatval($rate['total_amount'])), - 'calc_tax' => 'per_order', - 'meta_data' => array( - 'product_id' => $rate['product_id'], - 'delivery_time' => $rate['product_aging'], - 'original_name' => $product_name, - 'is_group' => true, - 'group_name' => $group['groupName'], - 'original_amount' => $rate['total_amount'] - ) + 'cost' => $this->convert_currency($adjusted_amount), + 'delivery_time' => $delivery_time, + 'original_name' => $product_name, + 'is_group' => true, + 'group_name' => $group['groupName'], + 'original_amount' => $amount ); } - $group_found = true; break; } } - if ($group_found) break; } + + // 构建单独线路运费数据 + $all_rates[] = array( + 'product_id' => $product_id, + 'method_title' => sprintf( + '%s (%s)', + $product_name, + $this->translate_delivery_time($delivery_time) + ), + 'cost' => $this->convert_currency($adjusted_amount), + 'delivery_time' => $delivery_time, + 'original_name' => $product_name, + 'is_group' => false, + 'group_name' => '', + 'original_amount' => $amount + ); } // 根据设置决定返回分组还是所有线路 $show_all_rates = get_option('czl_show_all_rates', 'no'); - if ($show_all_rates === 'yes') { - return array_values($all_rates); - } else { - return array_values($grouped_rates); - } + return $show_all_rates === 'yes' ? array_values($all_rates) : array_values($grouped_rates); } catch (Exception $e) { error_log('CZL Express Error: ' . $e->getMessage()); @@ -338,41 +328,62 @@ class CZL_Rate_Calculator { return $delivery_time; } - // 匹配中文时效格式 + // 匹配各种中文时效格式并转换为英文 + + // 匹配"XX-XX个工作日"格式 if (preg_match('/(\d+)-(\d+)个工作日/', $delivery_time, $matches)) { return sprintf('%d-%d working days', $matches[1], $matches[2]); } + // 匹配"XX个工作日"格式 if (preg_match('/(\d+)个工作日/', $delivery_time, $matches)) { return sprintf('%d working days', $matches[1]); } - // 匹配"预计XX天左右"的格式 + // 匹配"预计XX天左右"格式 if (preg_match('/预计(\d+)天左右/', $delivery_time, $matches)) { return sprintf('About %d days', $matches[1]); } - // 匹配"预计XX-XX天"的格式 + // 匹配"预计XX-XX天"格式 if (preg_match('/预计(\d+)-(\d+)天/', $delivery_time, $matches)) { return sprintf('About %d-%d days', $matches[1], $matches[2]); } + // 匹配"XX-XX天"格式 + if (preg_match('/(\d+)-(\d+)天/', $delivery_time, $matches)) { + return sprintf('%d-%d days', $matches[1], $matches[2]); + } + + // 匹配"XX天"格式 + if (preg_match('/(\d+)天/', $delivery_time, $matches)) { + return sprintf('%d days', $matches[1]); + } + // 其他常见格式的翻译 $translations = array( '当天送达' => 'Same day delivery', '次日送达' => 'Next day delivery', '隔日送达' => 'Second day delivery', '工作日' => 'working days', - '左右' => 'about' + '左右' => 'about', + '预计' => 'About', + '快速' => 'Express', + '标准' => 'Standard' ); + $translated = $delivery_time; foreach ($translations as $cn => $en) { - if (strpos($delivery_time, $cn) !== false) { - return $en; - } + $translated = str_replace($cn, $en, $translated); } - // 如果没有匹配到任何格式,返回原始值 - return $delivery_time; + // 如果经过翻译后与原文相同,说明没有匹配到任何规则 + if ($translated === $delivery_time) { + // 添加调试日志 + error_log('CZL Express: Unable to translate delivery time - ' . $delivery_time); + return $delivery_time; + } + + return $translated; } } \ No newline at end of file diff --git a/includes/class-czl-shipping-method.php b/includes/class-czl-shipping-method.php index f531da7..b8305df 100644 --- a/includes/class-czl-shipping-method.php +++ b/includes/class-czl-shipping-method.php @@ -107,15 +107,18 @@ class WC_CZL_Shipping_Method extends WC_Shipping_Method { try { error_log('CZL Express: Starting shipping calculation'); - $rates = $this->calculator->calculate_shipping_rate($package); + $calculator = new CZL_Rate_Calculator(); + $rates = $calculator->calculate_shipping_rate($package); if (!empty($rates)) { foreach ($rates as $rate) { - $rate_id = $this->id . '_' . $rate['product_id']; + $rate_id = $this->id . '_' . (isset($rate['product_id']) ? $rate['product_id'] : uniqid()); + $this->add_rate(array( 'id' => $rate_id, 'label' => $rate['method_title'], 'cost' => $rate['cost'], + 'calc_tax' => 'per_order', 'meta_data' => array( 'product_id' => $rate['product_id'], 'delivery_time' => $rate['delivery_time'], @@ -126,14 +129,14 @@ class WC_CZL_Shipping_Method extends WC_Shipping_Method { ) )); } + error_log('CZL Express: Added ' . count($rates) . ' shipping rates'); } else { - error_log('CZL Express: No shipping rates returned'); + error_log('CZL Express: No shipping rates available'); } } catch (Exception $e) { - error_log('CZL Express Error: ' . $e->getMessage()); - wc_add_notice($e->getMessage(), 'error'); + error_log('CZL Express Error: Failed to calculate shipping - ' . $e->getMessage()); } } diff --git a/includes/class-czl-tracking.php b/includes/class-czl-tracking.php index b371100..cef96bc 100644 --- a/includes/class-czl-tracking.php +++ b/includes/class-czl-tracking.php @@ -1,5 +1,73 @@ -1, + 'status' => array('processing', 'shipping'), + 'meta_key' => '_czl_tracking_number', + 'meta_compare' => 'EXISTS' + )); + + foreach ($orders as $order) { + $this->update_tracking_info($order->get_id()); + } + } + + /** + * 更新单个订单的轨迹信息 + */ + public function update_tracking_info($order_id) { + try { + $order = wc_get_order($order_id); + if (!$order) { + return; + } + + $tracking_number = $order->get_meta('_czl_tracking_number'); + if (empty($tracking_number)) { + return; + } + + $api = new CZL_API(); + $tracking_info = $api->get_tracking($tracking_number); + + if (!empty($tracking_info)) { + // 保存轨迹信息 + $order->update_meta_data('_czl_tracking_history', $tracking_info); + + // 根据最新轨迹更新订单状态 + if (!empty($tracking_info['trackDetails'])) { + $latest_status = reset($tracking_info['trackDetails']); + + if (strpos($latest_status['track_content'], '已签收') !== false || + strpos($latest_status['track_content'], 'Delivered') !== false) { + $order->update_status('delivered', __('Package delivered', 'woo-czl-express')); + } elseif ($order->get_status() !== 'delivered') { + $order->update_status('in_transit', __('Package in transit', 'woo-czl-express')); + } + } + + $order->save(); + } + + } catch (Exception $e) { + error_log('CZL Express Error: Failed to update tracking info - ' . $e->getMessage()); + } + } + /** * 在订单详情页显示跟踪信息 */ @@ -147,4 +215,7 @@ class CZL_Tracking { __('运输中', 'woo-czl-express'), + register_post_status('wc-in_transit', array( + 'label' => _x('In Transit', 'Order status', 'woo-czl-express'), 'public' => true, - 'show_in_admin_status_list' => true, - 'show_in_admin_all_list' => true, 'exclude_from_search' => false, - 'label_count' => _n_noop('运输中 (%s)', - '运输中 (%s)', 'woo-czl-express') + 'show_in_admin_all_list' => true, + 'show_in_admin_status_list' => true, + 'label_count' => _n_noop('In Transit (%s)', + 'In Transit (%s)', 'woo-czl-express') )); register_post_status('wc-delivered', array( - 'label' => __('已送达', 'woo-czl-express'), + 'label' => _x('Delivered', 'Order status', 'woo-czl-express'), 'public' => true, - 'show_in_admin_status_list' => true, - 'show_in_admin_all_list' => true, 'exclude_from_search' => false, - 'label_count' => _n_noop('已送达 (%s)', - '已送达 (%s)', 'woo-czl-express') + 'show_in_admin_all_list' => true, + 'show_in_admin_status_list' => true, + 'label_count' => _n_noop('Delivered (%s)', + 'Delivered (%s)', 'woo-czl-express') )); } @@ -390,8 +390,8 @@ class WooCzlExpress { */ public function add_custom_order_statuses($order_statuses) { $new_statuses = array( - 'wc-shipping' => __('运输中', 'woo-czl-express'), - 'wc-delivered' => __('已送达', 'woo-czl-express') + 'wc-in_transit' => _x('In Transit', 'Order status', 'woo-czl-express'), + 'wc-delivered' => _x('Delivered', 'Order status', 'woo-czl-express') ); return array_merge($order_statuses, $new_statuses); diff --git a/woocommerce-czlexpress.php b/woocommerce-czlexpress.php index 6fbedd5..6c562a4 100644 --- a/woocommerce-czlexpress.php +++ b/woocommerce-czlexpress.php @@ -62,4 +62,17 @@ function woo_czl_express_init() { add_action('plugins_loaded', 'woo_czl_express_init'); -add_action('woocommerce_order_status_processing', array('CZL_Order', 'create_shipment')); \ No newline at end of file +add_action('woocommerce_order_status_processing', function($order_id) { + $czl_order = new CZL_Order(); + $czl_order->create_shipment($order_id); +}); + +// 在插件停用时清理定时任务 +register_deactivation_hook(__FILE__, 'wc_czlexpress_deactivate'); + +function wc_czlexpress_deactivate() { + $timestamp = wp_next_scheduled('czl_update_tracking_cron'); + if ($timestamp) { + wp_unschedule_event($timestamp, 'czl_update_tracking_cron'); + } +} \ No newline at end of file