mirror of
https://github.com/woodchen-ink/czlexpress-for-woocommerce.git
synced 2025-07-18 05:51:57 +08:00
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:
parent
212aa549ae
commit
c74d6ecb97
@ -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>
|
@ -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()));
|
||||
}
|
||||
}
|
||||
}
|
@ -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']) : '未知错误';
|
||||
|
@ -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'));
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
@ -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;
|
||||
}
|
||||
}
|
@ -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());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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();
|
@ -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);
|
||||
|
@ -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');
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user