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.
This commit is contained in:
wood chen 2024-12-19 22:15:04 +08:00
parent 212aa549ae
commit c74d6ecb97
12 changed files with 517 additions and 223 deletions

View File

@ -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();
<strong><?php _e('CZL订单号:', 'woo-czl-express'); ?></strong>
<?php echo esc_html($czl_order_id); ?><br>
<strong><?php _e('参考号:', 'woo-czl-express'); ?></strong>
<?php echo esc_html($reference_number); ?><br>
<?php if ($label_url): ?>
<a href="<?php echo esc_url($label_url); ?>" target="_blank" class="button">
<?php _e('打印标签', 'woo-czl-express'); ?>
</a>
<?php endif; ?>
<?php echo esc_html($reference_number); ?>
<?php else: ?>
<?php _e('未创建运单', 'woo-czl-express'); ?>
<?php endif; ?>
</td>
<td>
<?php if (!$tracking_number): ?>
<button class="button create-shipment" data-order-id="<?php echo esc_attr($order->get_id()); ?>">
<?php if (!empty($tracking_number)): ?>
<button type="button" class="button" onclick="printLabel(<?php echo $order->get_id(); ?>)">
<?php _e('打印标签', 'woo-czl-express'); ?>
</button>
<?php endif; ?>
<?php if (empty($tracking_number)): ?>
<button type="button" class="button" onclick="createShipment(<?php echo $order->get_id(); ?>)">
<?php _e('创建运单', 'woo-czl-express'); ?>
</button>
<?php endif; ?>
@ -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: '<?php echo wp_create_nonce("czl-print-label"); ?>'
},
success: function(response) {
if (response.success && response.data.url) {
// 在新窗口打开标签
window.open(response.data.url, '_blank');
} else {
alert(response.data.message || '获取标签失败');
}
},
error: function() {
alert('请求失败,请重试');
}
});
}
</script>

View File

@ -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()));
}
}
}

View File

@ -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']) : '未知错误';

View File

@ -1,28 +1,63 @@
<?php
class CZL_Label {
private static $api;
public static function init() {
self::$api = new CZL_API();
}
/**
* 获取标签URL
*/
public static function get_label_url($order_id) {
$czl_order_id = get_post_meta($order_id, '_czl_order_id', true);
if (!$czl_order_id) {
return false;
try {
$order = wc_get_order($order_id);
if (!$order) {
throw new Exception('订单不存在');
}
// 获取运单号
$tracking_number = $order->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;
}
}
}
// 在插件初始化时调用
add_action('init', array('CZL_Label', 'init'));

View File

@ -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);
}
}

View File

@ -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;

View File

@ -6,23 +6,41 @@ class CZL_Product_Fields {
}
/**
* 添加自定义字段
* 添加自定义字段到产品编辑页面
*/
public function add_custom_fields() {
echo '<div class="options_group">';
// 中文品名字段
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 '</div>';
@ -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);
}
}

View File

@ -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;
}
}

View File

@ -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());
}
}

View File

@ -1,5 +1,73 @@
<?php
class CZL_Tracking {
public function __construct() {
// 添加定时任务钩子
add_action('czl_update_tracking_cron', array($this, 'update_all_tracking_info'));
// 如果定时任务未设置,则设置它
if (!wp_next_scheduled('czl_update_tracking_cron')) {
wp_schedule_event(time(), 'hourly', 'czl_update_tracking_cron');
}
}
/**
* 更新所有活跃订单的轨迹信息
*/
public function update_all_tracking_info() {
$orders = wc_get_orders(array(
'limit' => -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 {
</div>
<?php
}
}
}
// 初始化类
new CZL_Tracking();

View File

@ -108,14 +108,22 @@ class WooCzlExpress {
__('CZL Express', 'woo-czl-express'),
__('CZL Express', 'woo-czl-express'),
'manage_woocommerce',
'czl-express',
'woo-czl-express',
array($this, 'render_settings_page'),
'dashicons-airplane'
);
// 添加订单管理子菜单
add_submenu_page(
'czl-express',
'woo-czl-express',
__('基本设置', 'woo-czl-express'),
__('基本设置', 'woo-czl-express'),
'manage_woocommerce',
'woo-czl-express',
array($this, 'render_settings_page')
);
add_submenu_page(
'woo-czl-express',
__('订单管理', 'woo-czl-express'),
__('订单管理', 'woo-czl-express'),
'manage_woocommerce',
@ -124,15 +132,7 @@ class WooCzlExpress {
);
add_submenu_page(
'czl-express',
__('基本设置', 'woo-czl-express'),
__('基本设置', 'woo-czl-express'),
'manage_options',
'czl-express'
);
add_submenu_page(
'czl-express',
'woo-czl-express',
__('产品分组', 'woo-czl-express'),
__('产品分组', 'woo-czl-express'),
'manage_options',
@ -141,7 +141,7 @@ class WooCzlExpress {
);
add_submenu_page(
'czl-express',
'woo-czl-express',
__('汇率设置', 'woo-czl-express'),
__('汇率设置', 'woo-czl-express'),
'manage_options',
@ -364,24 +364,24 @@ class WooCzlExpress {
* 注册自定义订单状态
*/
public function register_custom_order_statuses() {
register_post_status('wc-shipping', array(
'label' => __('运输中', '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('运输中 <span class="count">(%s)</span>',
'运输中 <span class="count">(%s)</span>', 'woo-czl-express')
'show_in_admin_all_list' => true,
'show_in_admin_status_list' => true,
'label_count' => _n_noop('In Transit <span class="count">(%s)</span>',
'In Transit <span class="count">(%s)</span>', '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('已送达 <span class="count">(%s)</span>',
'已送达 <span class="count">(%s)</span>', 'woo-czl-express')
'show_in_admin_all_list' => true,
'show_in_admin_status_list' => true,
'label_count' => _n_noop('Delivered <span class="count">(%s)</span>',
'Delivered <span class="count">(%s)</span>', '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);

View File

@ -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'));
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');
}
}