czlexpress-for-woocommerce/woocommerce-czlexpress.php
wood chen 64e952903a Update system requirements and enhance plugin functionality
- Updated system requirements in the README to reflect compatibility with WordPress 6.0+ and PHP 7.4+.
- Revised usage steps for better clarity on plugin installation and configuration.
- Improved order management features, including AJAX handling for shipment creation and tracking updates.
- Added new custom order statuses (In Transit, Delivered) for better order tracking.
- Enhanced error handling and logging during shipment creation and tracking updates.
- Introduced chargeable weight calculation for shipping rates based on product dimensions and weight.

These changes enhance the overall performance and usability of the CZL Express plugin.
2024-12-20 03:03:12 +08:00

435 lines
14 KiB
PHP

<?php
/**
* Plugin Name: CZL Express for WooCommerce
* Plugin URI: https://exp.czl.net
* Description: CZL Express shipping integration for WooCommerce. Provides real-time shipping rates, shipment creation, and package tracking for CZL Express delivery service.
* Version: 1.0.0
* Requires at least: 5.8
* Requires PHP: 7.2
* Author: CZL Express
* Author URI: https://exp.czl.net
* License: GPL v2 or later
* License URI: https://www.gnu.org/licenses/gpl-2.0.html
* Text Domain: woo-czl-express
* Domain Path: /languages
* WC requires at least: 6.0.0
* WC tested up to: 8.3.0
*
* This plugin is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 2 of the License, or
* any later version.
*
* This plugin is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this plugin. If not, see https://www.gnu.org/licenses/gpl-2.0.html.
*/
// 防止直接访问
if (!defined('ABSPATH')) {
exit;
}
// 防止重复加载
if (defined('WOO_CZL_EXPRESS_VERSION')) {
return;
}
// 定义插件常量
define('WOO_CZL_EXPRESS_VERSION', '1.0.0');
define('WOO_CZL_EXPRESS_PATH', plugin_dir_path(__FILE__));
define('WOO_CZL_EXPRESS_URL', plugin_dir_url(__FILE__));
// 在插件激活时创建数据表
register_activation_hook(__FILE__, 'wc_czlexpress_activate');
function wc_czlexpress_activate() {
// 确保加载安装类
require_once WOO_CZL_EXPRESS_PATH . 'includes/class-czl-install.php';
// 创建数据表和默认选项
CZL_Install::init();
// 记录版本号
update_option('czl_express_version', WOO_CZL_EXPRESS_VERSION);
// 注册定时任务
if (!wp_next_scheduled('czl_sync_tracking_numbers_hook')) {
wp_schedule_event(time(), 'hourly', 'czl_sync_tracking_numbers_hook');
}
}
// 在插件停用时清理
register_deactivation_hook(__FILE__, function() {
// 清理定时任务
wp_clear_scheduled_hook('czl_sync_tracking_numbers_hook');
});
// 在插件卸载时清理数据
register_uninstall_hook(__FILE__, array('CZL_Install', 'uninstall'));
// 声明支持HPOS
add_action('before_woocommerce_init', function() {
if (class_exists('\Automattic\WooCommerce\Utilities\FeaturesUtil')) {
\Automattic\WooCommerce\Utilities\FeaturesUtil::declare_compatibility('custom_order_tables', __FILE__, true);
}
});
// 检查环境
function wc_czlexpress_check_environment() {
if (!class_exists('WooCommerce')) {
add_action('admin_notices', function() {
echo '<div class="error"><p>' .
__('CZL Express requires WooCommerce to be installed and active', 'woocommerce-czlexpress') .
'</p></div>';
});
return false;
}
if (version_compare(WC_VERSION, '6.0.0', '<')) {
add_action('admin_notices', function() {
echo '<div class="error"><p>' .
__('CZL Express requires WooCommerce 6.0.0 or higher', 'woocommerce-czlexpress') .
'</p></div>';
});
return false;
}
return true;
}
// 初始化插件
function woo_czl_express_init() {
if (wc_czlexpress_check_environment()) {
// 加载语言文件
load_plugin_textdomain(
'woo-czl-express',
false,
dirname(plugin_basename(__FILE__)) . '/languages'
);
// 加载必要的类文件
require_once WOO_CZL_EXPRESS_PATH . 'includes/class-woo-czl-express.php';
require_once WOO_CZL_EXPRESS_PATH . 'includes/class-czl-api.php';
require_once WOO_CZL_EXPRESS_PATH . 'includes/class-czl-order.php';
WooCzlExpress::instance();
// 添加AJAX处理
add_action('wp_ajax_czl_create_shipment', 'czl_ajax_create_shipment');
add_action('wp_ajax_czl_update_tracking_number', 'czl_ajax_update_tracking_number');
add_action('wp_ajax_czl_update_tracking_info', 'czl_ajax_update_tracking_info');
// 添加前端脚本
add_action('admin_enqueue_scripts', 'czl_enqueue_admin_scripts');
// 注册自定义订单状态
add_action('init', 'register_czl_order_statuses');
}
}
// 注册自定义订单状态
function register_czl_order_statuses() {
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(
'In Transit <span class="count">(%s)</span>',
'In Transit <span class="count">(%s)</span>',
'woo-czl-express'
)
));
// 添加到WooCommerce订单状态列表
add_filter('wc_order_statuses', function($order_statuses) {
$new_statuses = array();
// 在processing后面插入新状态
foreach ($order_statuses as $key => $status) {
$new_statuses[$key] = $status;
if ($key === 'wc-processing') {
$new_statuses['wc-in_transit'] = _x('In Transit', 'Order status', 'woo-czl-express');
}
}
return $new_statuses;
});
}
// 注册前端脚本
function czl_enqueue_admin_scripts($hook) {
// 在WooCommerce订单页面和CZL Express订单页面加载脚本
if (!in_array($hook, array('woocommerce_page_wc-orders', 'toplevel_page_czl-express-orders'))) {
return;
}
// 加载 Thickbox
add_thickbox();
// 加载自定义脚本
wp_enqueue_script(
'czl-admin-script',
WOO_CZL_EXPRESS_URL . 'assets/js/admin.js',
array('jquery'),
WOO_CZL_EXPRESS_VERSION,
true
);
wp_localize_script('czl-admin-script', 'czl_ajax', array(
'ajax_url' => admin_url('admin-ajax.php'),
'nonce' => wp_create_nonce('czl_ajax_nonce'),
'creating_text' => 'Creating shipment...',
'success_text' => 'Shipment created successfully',
'error_text' => 'Failed to create shipment'
));
}
// AJAX处理函数
function czl_ajax_create_shipment() {
check_ajax_referer('czl_ajax_nonce', 'nonce');
if (!current_user_can('edit_shop_orders')) {
wp_send_json_error('Permission denied');
}
$order_id = isset($_POST['order_id']) ? intval($_POST['order_id']) : 0;
if (!$order_id) {
wp_send_json_error('Invalid order ID');
}
try {
$czl_order = new CZL_Order();
$result = $czl_order->create_shipment($order_id);
if ($result) {
wp_send_json_success(array(
'message' => 'Shipment created successfully'
));
} else {
wp_send_json_error('Failed to create shipment');
}
} catch (Exception $e) {
wp_send_json_error($e->getMessage());
}
}
// 更新跟踪单号的AJAX处理函数
function czl_ajax_update_tracking_number() {
check_ajax_referer('czl_ajax_nonce', 'nonce');
if (!current_user_can('edit_shop_orders')) {
wp_send_json_error('Permission denied');
}
$order_id = isset($_POST['order_id']) ? intval($_POST['order_id']) : 0;
$tracking_number = isset($_POST['tracking_number']) ? sanitize_text_field($_POST['tracking_number']) : '';
if (!$order_id || !$tracking_number) {
wp_send_json_error('Invalid parameters');
}
try {
global $wpdb;
// 更新数据库中的跟踪单号
$updated = $wpdb->update(
$wpdb->prefix . 'czl_shipments',
array('tracking_number' => $tracking_number),
array('order_id' => $order_id),
array('%s'),
array('%d')
);
if ($updated === false) {
throw new Exception('数据库更新失败');
}
// 更新订单元数据
$order = wc_get_order($order_id);
if ($order) {
$order->update_meta_data('_czl_tracking_number', $tracking_number);
$order->save();
// 添加订单备注
$order->add_order_note(sprintf(
'Tracking number updated to: %s',
$tracking_number
));
}
wp_send_json_success();
} catch (Exception $e) {
wp_send_json_error($e->getMessage());
}
}
// 更新轨迹信息的AJAX处理函数
function czl_ajax_update_tracking_info() {
check_ajax_referer('czl_ajax_nonce', 'nonce');
if (!current_user_can('edit_shop_orders')) {
wp_send_json_error('权限不足');
}
$order_id = isset($_POST['order_id']) ? intval($_POST['order_id']) : 0;
if (!$order_id) {
wp_send_json_error('订单ID无效');
}
// 使用 wp_schedule_single_event 来异步处理更新
wp_schedule_single_event(time(), 'czl_do_update_tracking_info', array($order_id));
wp_send_json_success(array('message' => 'Update scheduled'));
}
// 异步处理轨迹更新
function czl_do_update_tracking_info($order_id) {
try {
$czl_order = new CZL_Order();
$czl_order->update_tracking_info($order_id);
} catch (Exception $e) {
error_log('CZL Express: Error updating tracking info - ' . $e->getMessage());
}
}
add_action('czl_do_update_tracking_info', 'czl_do_update_tracking_info');
add_action('plugins_loaded', 'woo_czl_express_init');
// 自动创建运单的钩子
add_action('woocommerce_order_status_processing', function($order_id) {
$czl_order = new CZL_Order();
try {
$czl_order->create_shipment($order_id);
} catch (Exception $e) {
error_log('CZL Express: Auto create shipment failed - ' . $e->getMessage());
}
});
// 添加自定义Cron间隔
add_filter('cron_schedules', 'czl_add_cron_interval');
function czl_add_cron_interval($schedules) {
// 添加每30分钟执行一次的间隔
$schedules['czl_thirty_minutes'] = array(
'interval' => 1800, // 30分钟 = 1800秒
'display' => __('Every 30 minutes', 'woo-czl-express')
);
return $schedules;
}
// 添加定时任务处理函数
function czl_sync_tracking_numbers() {
global $wpdb;
// 获取最后同步时间
$last_sync = get_option('czl_last_tracking_sync', 0);
$current_time = time();
// 如果距离上次同步不到25分钟,则跳过
if (($current_time - $last_sync) < 1500) {
return;
}
// 限制每次处理的订单数量
$limit = 10;
// 获取需要同步的订单
$shipments = $wpdb->get_results($wpdb->prepare("
SELECT order_id, tracking_number, czl_order_id
FROM {$wpdb->prefix}czl_shipments
WHERE czl_order_id IS NOT NULL
AND (last_sync_time IS NULL OR last_sync_time < DATE_SUB(NOW(), INTERVAL 25 MINUTE))
LIMIT %d
", $limit));
if (empty($shipments)) {
return;
}
try {
$api = new CZL_API();
foreach ($shipments as $shipment) {
// 为每个订单安排单独的更新事件
wp_schedule_single_event(
time() + rand(1, 300), // 随机延迟1-300秒
'czl_do_sync_single_tracking',
array($shipment->order_id, $shipment->tracking_number, $shipment->czl_order_id)
);
}
// 更新最后同步时间
update_option('czl_last_tracking_sync', $current_time);
} catch (Exception $e) {
error_log('CZL Express: Tracking number sync failed - ' . $e->getMessage());
}
}
// 处理单个订单的同步
function czl_do_sync_single_tracking($order_id, $current_tracking, $czl_order_id) {
try {
global $wpdb;
$api = new CZL_API();
// 获取最新的跟踪单号
$response = $api->get_tracking_number($czl_order_id);
// 更新最后同步时间
$wpdb->update(
$wpdb->prefix . 'czl_shipments',
array('last_sync_time' => current_time('mysql')),
array('order_id' => $order_id),
array('%s'),
array('%d')
);
if (!empty($response['tracking_number']) && $response['tracking_number'] !== $current_tracking) {
// 更新跟踪单号
$wpdb->update(
$wpdb->prefix . 'czl_shipments',
array('tracking_number' => $response['tracking_number']),
array('order_id' => $order_id),
array('%s'),
array('%d')
);
// 更新订单信息
$order = wc_get_order($order_id);
if ($order) {
$order->update_meta_data('_czl_tracking_number', $response['tracking_number']);
$order->save();
$tracking_link = sprintf(
'<a href="https://exp.czl.net/track/?query=%s" target="_blank">Track Your Package</a>',
$response['tracking_number']
);
$order->add_order_note(
sprintf(
'Tracking number updated to: %s\n%s',
$response['tracking_number'],
$tracking_link
),
true
);
}
}
} catch (Exception $e) {
error_log(sprintf(
'CZL Express: Failed to sync tracking number for order %d: %s',
$order_id,
$e->getMessage()
));
}
}
add_action('czl_do_sync_single_tracking', 'czl_do_sync_single_tracking', 10, 3);
// 注册定时任务钩子
add_action('czl_sync_tracking_numbers_hook', 'czl_sync_tracking_numbers');