文章目录
-
- 随着全球电子商务的蓬勃发展,越来越多的企业开始涉足跨境销售。然而,跨境交易带来的税务计算复杂性常常让行业新人和程序员感到困惑。不同国家/地区的税率规则、免税门槛、产品分类标准等差异,使得手动计算税务几乎成为不可能完成的任务。 对于使用WordPress开源系统的电商网站来说,如何高效、准确地处理跨境税务计算接口,直接关系到用户体验、合规性和运营效率。本文将基于WordPress开发环境,分享三个精准策略,帮助您构建可靠的跨境税务计算解决方案。
-
- 在开始编码之前,我们需要明确跨境税务计算的关键要素: 交易发生地:买家所在国家/地区 产品分类:不同产品类别可能适用不同税率 商家所在地:卖家注册地影响税务义务 交易金额:某些地区有免税门槛 客户类型:B2B与B2C交易税务处理不同
- WordPress及其流行的电商插件WooCommerce提供了完整的税务计算钩子体系。以下是一个基础税务计算类的框架: /** * 跨境税务计算器基类 */ class CrossBorderTaxCalculator { private $api_client; private $cache_handler; private $fallback_rates; public function __construct() { $this->api_client = new TaxApiClient(); $this->cache_handler = new TaxCacheHandler(); $this->fallback_rates = $this->load_fallback_rates(); } /** * 计算订单税务 */ public function calculate_tax($order_data) { // 1. 验证输入数据 $validated_data = $this->validate_order_data($order_data); // 2. 确定税务管辖区域 $jurisdiction = $this->determine_jurisdiction($validated_data); // 3. 尝试从缓存获取税率 $cached_rate = $this->cache_handler->get_rate($jurisdiction, $validated_data['product_type']); if ($cached_rate) { return $this->apply_tax_calculation($validated_data, $cached_rate); } // 4. 调用外部API获取实时税率 $api_rate = $this->get_api_tax_rate($jurisdiction, $validated_data); if ($api_rate) { // 缓存API结果 $this->cache_handler->set_rate($jurisdiction, $validated_data['product_type'], $api_rate); return $this->apply_tax_calculation($validated_data, $api_rate); } // 5. 使用备用税率 return $this->apply_tax_calculation($validated_data, $this->fallback_rates[$jurisdiction]); } /** * 确定税务管辖区域 */ private function determine_jurisdiction($order_data) { $country = $order_data['shipping_country']; $state = $order_data['shipping_state']; $postcode = $order_data['shipping_postcode']; // 复杂逻辑:根据国家、州/省、邮编确定具体税务区域 if ($country === 'US') { return $this->determine_us_jurisdiction($state, $postcode); } elseif ($country === 'CA') { return $this->determine_ca_jurisdiction($state, $postcode); } elseif (in_array($country, ['DE', 'FR', 'IT', 'ES'])) { return $this->determine_eu_jurisdiction($country, $postcode); } return $country; // 默认使用国家代码 } }
- 为了支持多个税务计算API,我们可以设计一个提供者模式: /** * 税率提供者接口 */ interface TaxRateProvider { public function get_rate($jurisdiction, $product_type); public function is_available($jurisdiction); public function get_provider_name(); } /** * TaxJar API实现 */ class TaxJarProvider implements TaxRateProvider { private $api_key; private $api_endpoint = 'https://api.taxjar.com/v2/'; public function __construct($api_key) { $this->api_key = $api_key; } public function get_rate($jurisdiction, $product_type) { $response = wp_remote_get($this->api_endpoint . 'rates/' . $jurisdiction, [ 'headers' => [ 'Authorization' => 'Bearer ' . $this->api_key, 'Content-Type' => 'application/json' ], 'timeout' => 5 ]); if (is_wp_error($response)) { return false; } $body = json_decode(wp_remote_retrieve_body($response), true); if (isset($body['rate']['combined_rate'])) { return $body['rate']['combined_rate']; } return false; } public function is_available($jurisdiction) { // TaxJar支持大多数国家 $supported_countries = ['US', 'CA', 'AU', 'GB', 'DE', 'FR', 'IT', 'ES']; return in_array($jurisdiction, $supported_countries) || strlen($jurisdiction) > 2; // 支持州/省级别 } public function get_provider_name() { return 'TaxJar'; } } /** * 提供者工厂 */ class TaxProviderFactory { private $providers = []; public function register_provider(TaxRateProvider $provider) { $this->providers[] = $provider; } public function get_provider_for_jurisdiction($jurisdiction) { foreach ($this->providers as $provider) { if ($provider->is_available($jurisdiction)) { return $provider; } } return null; } }
-
- 跨境税务API调用可能产生延迟和成本,因此缓存至关重要: /** * 多层税务缓存处理器 */ class TaxCacheHandler { private $transient_expiry = 3600; // 1小时 private $long_term_expiry = 86400 * 7; // 7天 /** * 获取税率 - 多层缓存检查 */ public function get_rate($jurisdiction, $product_type) { $cache_key = 'tax_rate_' . md5($jurisdiction . '_' . $product_type); // 第一层:WordPress瞬态缓存(快速) $rate = get_transient($cache_key); if ($rate !== false) { return $rate; } // 第二层:数据库缓存(中长期) $rate = $this->get_db_cached_rate($jurisdiction, $product_type); if ($rate) { // 回填瞬态缓存 set_transient($cache_key, $rate, $this->transient_expiry); return $rate; } return false; } /** * 数据库缓存查询 */ private function get_db_cached_rate($jurisdiction, $product_type) { global $wpdb; $table_name = $wpdb->prefix . 'tax_rates_cache'; $query = $wpdb->prepare( "SELECT rate_value FROM $table_name WHERE jurisdiction = %s AND product_type = %s AND expiry_date > %s ORDER BY updated_at DESC LIMIT 1", $jurisdiction, $product_type, current_time('mysql') ); return $wpdb->get_var($query); } /** * 存储税率到所有缓存层 */ public function set_rate($jurisdiction, $product_type, $rate) { $cache_key = 'tax_rate_' . md5($jurisdiction . '_' . $product_type); // 1. 瞬态缓存 set_transient($cache_key, $rate, $this->transient_expiry); // 2. 数据库缓存 $this->set_db_cached_rate($jurisdiction, $product_type, $rate); // 3. 更新备用税率文件(极端情况备用) $this->update_fallback_file($jurisdiction, $product_type, $rate); } /** * 创建缓存数据库表 */ public function create_cache_table() { global $wpdb; $table_name = $wpdb->prefix . 'tax_rates_cache'; $charset_collate = $wpdb->get_charset_collate(); $sql = "CREATE TABLE IF NOT EXISTS $table_name ( id bigint(20) NOT NULL AUTO_INCREMENT, jurisdiction varchar(100) NOT NULL, product_type varchar(50) NOT NULL, rate_value decimal(8,4) NOT NULL, created_at datetime DEFAULT CURRENT_TIMESTAMP, updated_at datetime DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, expiry_date datetime NOT NULL, source varchar(50) DEFAULT 'api', PRIMARY KEY (id), INDEX jurisdiction_product (jurisdiction, product_type), INDEX expiry_idx (expiry_date) ) $charset_collate;"; require_once(ABSPATH . 'wp-admin/includes/upgrade.php'); dbDelta($sql); } }
- 当外部API不可用时,系统应优雅降级: /** * 智能税务计算器(带容错) */ class ResilientTaxCalculator { private $primary_provider; private $fallback_providers = []; private $cache_handler; private $circuit_breaker; public function __construct() { $this->cache_handler = new TaxCacheHandler(); $this->circuit_breaker = new CircuitBreaker('tax_api'); // 初始化提供者(按优先级) $this->primary_provider = new TaxJarProvider(get_option('taxjar_api_key')); $this->fallback_providers[] = new AvalaraProvider(get_option('avalara_api_key')); $this->fallback_providers[] = new LocalTaxProvider(); // 本地数据库提供者 } /** * 容错税率获取 */ public function get_tax_rate_with_fallback($jurisdiction, $product_type) { // 检查缓存 $cached_rate = $this->cache_handler->get_rate($jurisdiction, $product_type); if ($cached_rate) { return $cached_rate; } // 检查断路器状态 if ($this->circuit_breaker->is_open()) { error_log('税务API断路器已打开,使用本地备用税率'); return $this->get_local_fallback_rate($jurisdiction, $product_type); } // 尝试主提供者 try { $rate = $this->primary_provider->get_rate($jurisdiction, $product_type); if ($rate !== false) { $this->cache_handler->set_rate($jurisdiction, $product_type, $rate); $this->circuit_breaker->record_success(); return $rate; } } catch (Exception $e) { $this->circuit_breaker->record_failure(); error_log('主税务API失败: ' . $e->getMessage()); } // 尝试备用提供者 foreach ($this->fallback_providers as $provider) { try { if ($provider->is_available($jurisdiction)) { $rate = $provider->get_rate($jurisdiction, $product_type); if ($rate !== false) { $this->cache_handler->set_rate($jurisdiction, $product_type, $rate); return $rate; } } } catch (Exception $e) { error_log('备用税务API失败: ' . $e->getMessage()); continue; } } // 所有API都失败,使用本地备用 return $this->get_local_fallback_rate($jurisdiction, $product_type); } } /** * 断路器模式实现 */ class CircuitBreaker { private $service_name; private $failure_threshold = 5; private $reset_timeout = 60; // 60秒后尝试恢复 private $failures = 0; private $last_failure_time = 0; private $state = 'closed'; // closed, open, half-open public function __construct($service_name) { $this->service_name = $service_name; $this->load_state(); } public function is_open() { if ($this->state === 'open') { // 检查是否应该进入半开状态 if (time() - $this->last_failure_time > $this->reset_timeout) { $this->state = 'half-open'; $this->save_state(); } return true; } return false; } public function record_failure() { $this->failures++; $this->last_failure_time = time(); if ($this->failures >= $this->failure_threshold) { $this->state = 'open'; } $this->save_state(); } public function record_success() { $this->failures = 0; $this->state = 'closed'; $this->save_state(); } private function load_state() { $state = get_transient('circuit_breaker_' . $this->service_name); if ($state) { $this->failures = $state['failures']; $this->last_failure_time = $state['last_failure_time']; $this->state = $state['state']; } } private function save_state() { $state = [ 'failures' => $this->failures, 'last_failure_time' => $this->last_failure_time, 'state' => $this->state ]; set_transient('circuit_breaker_' . $this->service_name, $state, $this->reset_timeout * 2); } }
-
- 在购物车和结账页面提供实时税务计算: /** * WordPress AJAX税务计算端点 */ class TaxAjaxHandler { public function __construct() { add_action('wp_ajax_calculate_tax_preview', [$this, 'calculate_tax_preview']); add_action('wp_ajax_nopriv_calculate_tax_preview', [$this, 'calculate_tax_preview']); add_action('wp_enqueue_scripts', [$this, 'enqueue_tax_scripts']); } /** * 前端税务计算脚本 */ public function enqueue_tax_scripts() { if (is_cart() || is_checkout()) { wp_enqueue_script( 'tax-calculator', plugin_dir_url(__FILE__) . 'js/tax-calculator.js', ['jquery'], '1.0.0', true ); wp_localize_script('tax-calculator', 'tax_calculator_vars', [ 'ajax_url' => admin_url('admin-ajax.php'), 'nonce' => wp_create_nonce('tax_calculate_nonce') ]); } } /** * AJAX税务预览计算 */ public function calculate_tax_preview() { // 验证nonce if (!wp_verify_nonce($_POST['nonce'], 'tax_calculate_nonce')) { wp_die('安全验证失败'); } $country = sanitize_text_field($_POST['country']); $state = sanitize_text_field($_POST['state']); $postcode = sanitize_text_field($_POST['postcode']); $cart_total = floatval($_POST['cart_total']); $product_types = isset($_POST['product_types']) ? array_map('sanitize_text_field', $_POST['product_types']) : []; $tax_calculator = new ResilientTaxCalculator(); // 为每种产品类型计算税务 $tax_details = []; $total_tax = 0; foreach ($product_types as $product_type) { $jurisdiction = $this->determine_jurisdiction($country, $state, $postcode); $rate = $tax_calculator->get_tax_rate_with_fallback($jurisdiction, $product_type); // 简化:假设每种产品类型金额平均分配 $product_amount = $cart_total / count($product_types); $tax_amount = $product_amount * $rate; $tax_details[] = [ 'product_type' => $product_type, 'rate' => $rate * 100, // 转换为百分比 'amount' => $tax_amount ]; $total_tax += $tax_amount; } wp_send_json_success([ 'tax_details' => $tax_details, 'total_tax' => round($total_tax, 2), 'total_with_tax' => round($cart_total + $total_tax, 2), 'currency' => get_woocommerce_currency() ]); } }
- 保持完整的税务计算记录以满足合规要求: /** * 税务审计日志系统 */ class TaxAuditLogger { private $log_table; public function __construct() { global $wpdb; $this->log_table = $wpdb->prefix . 'tax_audit_log'; $this->create_log_table(); } /** * 记录税务计算事件 */ public function log_tax_calculation($event_data) { global $wpdb; $defaults = [ 'order_id' => 0, 0, 'calculation_type' => 'checkout', 'jurisdiction' => '', 'product_types' => '', 'subtotal' => 0.00, 'tax_amount' => 0.00, 'tax_rate' => 0.0000, 'tax_provider' => 'local', 'api_response' => '', 'ip_address' => '', 'user_agent' => '', 'calculated_at' => current_time('mysql') ]; $data = wp_parse_args($event_data, $defaults); // 序列化数组字段 if (is_array($data['product_types'])) { $data['product_types'] = json_encode($data['product_types']); } if (is_array($data['api_response'])) { $data['api_response'] = json_encode($data['api_response']); } $wpdb->insert($this->log_table, $data); return $wpdb->insert_id; } /** * 创建审计日志表 */ private function create_log_table() { global $wpdb; $charset_collate = $wpdb->get_charset_collate(); $sql = "CREATE TABLE IF NOT EXISTS {$this->log_table} ( id bigint(20) NOT NULL AUTO_INCREMENT, order_id bigint(20) DEFAULT 0, customer_id bigint(20) DEFAULT 0, calculation_type varchar(50) NOT NULL, jurisdiction varchar(100) NOT NULL, product_types text, subtotal decimal(12,4) NOT NULL, tax_amount decimal(12,4) NOT NULL, tax_rate decimal(8,6) NOT NULL, tax_provider varchar(50) NOT NULL, api_response text, ip_address varchar(45) DEFAULT '', user_agent text, calculated_at datetime NOT NULL, PRIMARY KEY (id), INDEX idx_order_id (order_id), INDEX idx_customer_id (customer_id), INDEX idx_jurisdiction (jurisdiction), INDEX idx_calculated_at (calculated_at) ) $charset_collate;"; require_once(ABSPATH . 'wp-admin/includes/upgrade.php'); dbDelta($sql); } /** * 生成税务报告 */ public function generate_tax_report($start_date, $end_date, $jurisdiction = '') { global $wpdb; $where_clauses = ["calculated_at BETWEEN %s AND %s"]; $where_values = [$start_date, $end_date]; if (!empty($jurisdiction)) { $where_clauses[] = "jurisdiction = %s"; $where_values[] = $jurisdiction; } $where_sql = implode(' AND ', $where_clauses); $query = $wpdb->prepare( "SELECT jurisdiction, tax_provider, COUNT(*) as calculation_count, SUM(subtotal) as total_subtotal, SUM(tax_amount) as total_tax, AVG(tax_rate) as average_rate, MIN(calculated_at) as first_calculation, MAX(calculated_at) as last_calculation FROM {$this->log_table} WHERE {$where_sql} GROUP BY jurisdiction, tax_provider ORDER BY jurisdiction, total_tax DESC", $where_values ); return $wpdb->get_results($query, ARRAY_A); } } /** WooCommerce税务计算集成 */ class WooCommerceTaxIntegration { private $tax_calculator; private $audit_logger; public function __construct() { $this->tax_calculator = new ResilientTaxCalculator(); $this->audit_logger = new TaxAuditLogger(); // 集成WooCommerce税务计算钩子 add_filter('woocommerce_calc_tax', [$this, 'calculate_woocommerce_tax'], 10, 5); add_action('woocommerce_checkout_update_order_meta', [$this, 'save_tax_calculation_metadata']); add_filter('woocommerce_get_tax_location', [$this, 'adjust_tax_location'], 10, 2); } /** * 自定义WooCommerce税务计算 */ public function calculate_woocommerce_tax($taxes, $price, $rates, $price_includes_tax, $suppress_rounding) { // 获取当前税务管辖区域 $location = WC_Tax::get_tax_location(); $country = $location[0]; $state = $location[1]; $postcode = $location[2]; $city = $location[3]; // 获取购物车中的产品类型 $product_types = $this->get_cart_product_types(); // 计算每个产品类型的税务 $calculated_taxes = []; foreach ($product_types as $product_type) { $jurisdiction = $this->determine_jurisdiction($country, $state, $postcode); $tax_rate = $this->tax_calculator->get_tax_rate_with_fallback($jurisdiction, $product_type); if ($tax_rate > 0) { // 根据产品类型分配金额(简化逻辑) $type_price = $price / count($product_types); $tax_amount = $type_price * $tax_rate; // 创建税率键(兼容WooCommerce格式) $rate_key = $jurisdiction . '|' . ($tax_rate * 100); if (!isset($calculated_taxes[$rate_key])) { $calculated_taxes[$rate_key] = 0; } $calculated_taxes[$rate_key] += $tax_amount; } } // 记录审计日志 $this->audit_logger->log_tax_calculation([ 'calculation_type' => 'woocommerce_cart', 'jurisdiction' => $jurisdiction ?? '', 'product_types' => $product_types, 'subtotal' => $price, 'tax_amount' => array_sum($calculated_taxes), 'tax_rate' => $tax_rate ?? 0, 'tax_provider' => 'woocommerce_integration', 'ip_address' => $_SERVER['REMOTE_ADDR'] ?? '', 'user_agent' => $_SERVER['HTTP_USER_AGENT'] ?? '' ]); return $calculated_taxes; } /** * 获取购物车中的产品类型 */ private function get_cart_product_types() { $product_types = []; if (!WC()->cart) { return ['default']; } foreach (WC()->cart->get_cart() as $cart_item) { $product = $cart_item['data']; $product_type = $product->get_type(); // 获取自定义产品税务分类(如果存在) $tax_class = $product->get_tax_class(); if (!empty($tax_class)) { $product_type = $tax_class; } if (!in_array($product_type, $product_types)) { $product_types[] = $product_type; } } return empty($product_types) ? ['default'] : $product_types; } /** * 保存税务计算元数据到订单 */ public function save_tax_calculation_metadata($order_id) { $order = wc_get_order($order_id); if (!$order) { return; } // 获取税务计算详情 $tax_details = [ 'jurisdiction' => $order->get_tax_location()['country'] ?? '', 'calculated_at' => current_time('mysql'), 'tax_provider' => get_option('active_tax_provider', 'local'), 'tax_breakdown' => $order->get_taxes() ]; $order->update_meta_data('_cross_border_tax_details', $tax_details); $order->save(); } /** * 调整税务计算位置 */ public function adjust_tax_location($location, $tax_class) { // 这里可以根据业务逻辑调整税务计算位置 // 例如:根据产品类型或客户类型使用不同的位置逻辑 // 示例:如果是B2B客户,使用公司注册地而非收货地址 $customer_id = get_current_user_id(); if ($customer_id) { $is_b2b = get_user_meta($customer_id, 'is_b2b_customer', true); if ($is_b2b) { $b2b_location = get_user_meta($customer_id, 'business_location', true); if ($b2b_location) { return [ $b2b_location['country'], $b2b_location['state'], $b2b_location['postcode'], $b2b_location['city'] ]; } } } return $location; } } /** 前端税务显示优化 */ class TaxDisplayEnhancer { public function __construct() { add_filter('woocommerce_cart_totals_order_total_html', [$this, 'enhance_tax_display']); add_action('woocommerce_review_order_before_order_total', [$this, 'show_detailed_tax_breakdown']); add_filter('woocommerce_get_price_suffix', [$this, 'add_tax_inclusive_suffix'], 10, 4); } /** * 增强税务显示 */ public function enhance_tax_display($value) { if (is_cart() || is_checkout()) { $tax_total = WC()->cart->get_taxes_total(); if ($tax_total > 0) { $tax_message = sprintf( '<small class="tax-included-notice">%s</small>', __('(已包含税费)', 'your-text-domain') ); return $value . $tax_message; } } return $value; } /** * 显示详细税务明细 */ public function show_detailed_tax_breakdown() { $taxes = WC()->cart->get_tax_totals(); if (empty($taxes)) { return; } echo '<tr class="tax-breakdown-header">'; echo '<th colspan="2"><strong>' . __('税务明细', 'your-text-domain') . '</strong></th>'; echo '</tr>'; foreach ($taxes as $tax) { echo '<tr class="tax-rate tax-rate-' . sanitize_title($tax->label) . '">'; echo '<th>' . $tax->label . '</th>'; echo '<td>' . wc_price($tax->amount) . '</td>'; echo '</tr>'; } } /** * 添加含税价格后缀 */ public function add_tax_inclusive_suffix($html, $product, $price, $qty) { if (is_product() && wc_prices_include_tax()) { $tax_message = sprintf( ' <small class="tax-inclusive">%s</small>', __('(含税)', 'your-text-domain') ); return $html . $tax_message; } return $html; } } /** 管理界面扩展 */ class TaxAdminInterface { public function __construct() { add_action('admin_menu', [$this, 'add_tax_admin_pages']); add_action('admin_enqueue_scripts', [$this, 'enqueue_admin_scripts']); add_action('wp_ajax_clear_tax_cache', [$this, 'clear_tax_cache_ajax']); } /** * 添加管理页面 */ public function add_tax_admin_pages() { add_submenu_page( 'woocommerce', __('跨境税务设置', 'your-text-domain'), __('跨境税务', 'your-text-domain'), 'manage_woocommerce', 'cross-border-tax', [$this, 'render_tax_settings_page'] ); add_submenu_page( 'woocommerce', __('税务审计日志', 'your-text-domain'), __('税务审计', 'your-text-domain'), 'manage_woocommerce', 'tax-audit-logs', [$this, 'render_tax_audit_page'] ); } /** * 渲染税务设置页面 */ public function render_tax_settings_page() { ?> <div class="wrap"> <h1><?php _e('跨境税务设置', 'your-text-domain'); ?></h1> <div class="card"> <h2><?php _e('税务API配置', 'your-text-domain'); ?></h2> <form method="post" action="options.php"> <?php settings_fields('cross_border_tax_settings'); ?> <?php do_settings_sections('cross_border_tax_settings'); ?> <table class="form-table"> <tr> <th scope="row"> <label for="taxjar_api_key"><?php _e('TaxJar API密钥', 'your-text-domain'); ?></label> </th> <td> <input type="password" id="taxjar_api_key" name="taxjar_api_key" value="<?php echo esc_attr(get_option('taxjar_api_key')); ?>" class="regular-text"> <p class="description"> <?php _e('从TaxJar账户获取API密钥', 'your-text-domain'); ?> </p> </td> </tr> <tr> <th scope="row"> <label for="avalara_api_key"><?php _e('Avalara API密钥', 'your-text-domain'); ?></label> </th> <td> <input type="password" id="avalara_api_key" name="avalara_api_key" value="<?php echo esc_attr(get_option('avalara_api_key')); ?>" class="regular-text"> </td> </tr> <tr> <th scope="row"> <?php _e('缓存设置', 'your-text-domain'); ?> </th> <td> <label> <input type="checkbox" name="enable_tax_cache" value="1" <?php checked(get_option('enable_tax_cache'), 1); ?>> <?php _e('启用税率缓存', 'your-text-domain'); ?> </label> <br> <label> <input type="number" name="cache_duration" value="<?php echo esc_attr(get_option('cache_duration', 24)); ?>" min="1" max="720" style="width: 80px;"> <?php _e('缓存时长(小时)', 'your-text-domain'); ?> </label> </td> </tr> </table> <?php submit_button(); ?> </form> <hr> <h3><?php _e('缓存管理', 'your-text-domain'); ?></h3> <p> <button type="button" class="button" id="clear-tax-cache"> <?php _e('清除税率缓存', 'your-text-domain'); ?> </button> <span id="cache-clear-result" style="margin-left: 10px;"></span> </p> </div> <div class="card"> <h2><?php _e('备用税率设置', 'your-text-domain'); ?></h2> <p><?php _e('当所有API都不可用时使用的默认税率', 'your-text-domain'); ?></p> <div id="fallback-rates-container"> <!-- 通过AJAX动态加载备用税率设置 --> </div> </div> </div> <script> jQuery(document).ready(function($) { $('#clear-tax-cache').on('click', function() { var $button = $(this); var $result = $('#cache-clear-result'); $button.prop('disabled', true).text('清除中...'); $result.text(''); $.ajax({ url: ajaxurl, type: 'POST', data: { action: 'clear_tax_cache', nonce: '<?php echo wp_create_nonce('clear_tax_cache'); ?>' }, success: function(response) { if (response.success) { $result.text('缓存已清除').css('color', 'green'); } else { $result.text('清除失败').css('color', 'red'); } }, complete: function() { $button.prop('disabled', false).text('清除税率缓存'); } }); }); }); </script> <?php } /** * 渲染税务审计页面 */ public function render_tax_audit_page() { $audit_logger = new TaxAuditLogger(); // 获取报告数据 $start_date = isset($_GET['start_date']) ? sanitize_text_field($_GET['start_date']) : date('Y-m-01'); $end_date = isset($_GET['end_date']) ? sanitize_text_field($_GET['end_date']) : date('Y-m-d'); $jurisdiction = isset($_GET['jurisdiction']) ? sanitize_text_field($_GET['jurisdiction']) : ''; $report_data = $audit_logger->generate_tax_report($start_date, $end_date, $jurisdiction); ?> <div class="wrap"> <h1><?php _e('税务审计日志', 'your-text-domain'); ?></h1> <div class="card"> <h2><?php _e('报告筛选', 'your-text-domain'); ?></h2> <form method="get" action=""> <input type="hidden" name="page" value="tax-audit-logs"> <table class="form-table"> <tr> <th scope="row"> <label for="start_date"><?php _e('开始日期', 'your-text-domain'); ?></label> </th> <td> <input type="date" id="start_date" name="start_date" value="<?php echo esc_attr($start_date); ?>"> </td> </tr> <tr>
随着全球电子商务的蓬勃发展,越来越多的企业开始涉足跨境销售。然而,跨境交易带来的税务计算复杂性常常让行业新人和程序员感到困惑。不同国家/地区的税率规则、免税门槛、产品分类标准等差异,使得手动计算税务几乎成为不可能完成的任务。
对于使用WordPress开源系统的电商网站来说,如何高效、准确地处理跨境税务计算接口,直接关系到用户体验、合规性和运营效率。本文将基于WordPress开发环境,分享三个精准策略,帮助您构建可靠的跨境税务计算解决方案。
在开始编码之前,我们需要明确跨境税务计算的关键要素:
- 交易发生地:买家所在国家/地区
- 产品分类:不同产品类别可能适用不同税率
- 商家所在地:卖家注册地影响税务义务
- 交易金额:某些地区有免税门槛
- 客户类型:B2B与B2C交易税务处理不同
WordPress及其流行的电商插件WooCommerce提供了完整的税务计算钩子体系。以下是一个基础税务计算类的框架:
/**
* 跨境税务计算器基类
*/
class CrossBorderTaxCalculator {
private $api_client;
private $cache_handler;
private $fallback_rates;
public function __construct() {
$this->api_client = new TaxApiClient();
$this->cache_handler = new TaxCacheHandler();
$this->fallback_rates = $this->load_fallback_rates();
}
/**
* 计算订单税务
*/
public function calculate_tax($order_data) {
// 1. 验证输入数据
$validated_data = $this->validate_order_data($order_data);
// 2. 确定税务管辖区域
$jurisdiction = $this->determine_jurisdiction($validated_data);
// 3. 尝试从缓存获取税率
$cached_rate = $this->cache_handler->get_rate($jurisdiction, $validated_data['product_type']);
if ($cached_rate) {
return $this->apply_tax_calculation($validated_data, $cached_rate);
}
// 4. 调用外部API获取实时税率
$api_rate = $this->get_api_tax_rate($jurisdiction, $validated_data);
if ($api_rate) {
// 缓存API结果
$this->cache_handler->set_rate($jurisdiction, $validated_data['product_type'], $api_rate);
return $this->apply_tax_calculation($validated_data, $api_rate);
}
// 5. 使用备用税率
return $this->apply_tax_calculation($validated_data, $this->fallback_rates[$jurisdiction]);
}
/**
* 确定税务管辖区域
*/
private function determine_jurisdiction($order_data) {
$country = $order_data['shipping_country'];
$state = $order_data['shipping_state'];
$postcode = $order_data['shipping_postcode'];
// 复杂逻辑:根据国家、州/省、邮编确定具体税务区域
if ($country === 'US') {
return $this->determine_us_jurisdiction($state, $postcode);
} elseif ($country === 'CA') {
return $this->determine_ca_jurisdiction($state, $postcode);
} elseif (in_array($country, ['DE', 'FR', 'IT', 'ES'])) {
return $this->determine_eu_jurisdiction($country, $postcode);
}
return $country; // 默认使用国家代码
}
}
为了支持多个税务计算API,我们可以设计一个提供者模式:
/**
* 税率提供者接口
*/
interface TaxRateProvider {
public function get_rate($jurisdiction, $product_type);
public function is_available($jurisdiction);
public function get_provider_name();
}
/**
* TaxJar API实现
*/
class TaxJarProvider implements TaxRateProvider {
private $api_key;
private $api_endpoint = 'https://api.taxjar.com/v2/';
public function __construct($api_key) {
$this->api_key = $api_key;
}
public function get_rate($jurisdiction, $product_type) {
$response = wp_remote_get($this->api_endpoint . 'rates/' . $jurisdiction, [
'headers' => [
'Authorization' => 'Bearer ' . $this->api_key,
'Content-Type' => 'application/json'
],
'timeout' => 5
]);
if (is_wp_error($response)) {
return false;
}
$body = json_decode(wp_remote_retrieve_body($response), true);
if (isset($body['rate']['combined_rate'])) {
return $body['rate']['combined_rate'];
}
return false;
}
public function is_available($jurisdiction) {
// TaxJar支持大多数国家
$supported_countries = ['US', 'CA', 'AU', 'GB', 'DE', 'FR', 'IT', 'ES'];
return in_array($jurisdiction, $supported_countries) ||
strlen($jurisdiction) > 2; // 支持州/省级别
}
public function get_provider_name() {
return 'TaxJar';
}
}
/**
* 提供者工厂
*/
class TaxProviderFactory {
private $providers = [];
public function register_provider(TaxRateProvider $provider) {
$this->providers[] = $provider;
}
public function get_provider_for_jurisdiction($jurisdiction) {
foreach ($this->providers as $provider) {
if ($provider->is_available($jurisdiction)) {
return $provider;
}
}
return null;
}
}
跨境税务API调用可能产生延迟和成本,因此缓存至关重要:
/**
* 多层税务缓存处理器
*/
class TaxCacheHandler {
private $transient_expiry = 3600; // 1小时
private $long_term_expiry = 86400 * 7; // 7天
/**
* 获取税率 - 多层缓存检查
*/
public function get_rate($jurisdiction, $product_type) {
$cache_key = 'tax_rate_' . md5($jurisdiction . '_' . $product_type);
// 第一层:WordPress瞬态缓存(快速)
$rate = get_transient($cache_key);
if ($rate !== false) {
return $rate;
}
// 第二层:数据库缓存(中长期)
$rate = $this->get_db_cached_rate($jurisdiction, $product_type);
if ($rate) {
// 回填瞬态缓存
set_transient($cache_key, $rate, $this->transient_expiry);
return $rate;
}
return false;
}
/**
* 数据库缓存查询
*/
private function get_db_cached_rate($jurisdiction, $product_type) {
global $wpdb;
$table_name = $wpdb->prefix . 'tax_rates_cache';
$query = $wpdb->prepare(
"SELECT rate_value FROM $table_name
WHERE jurisdiction = %s
AND product_type = %s
AND expiry_date > %s
ORDER BY updated_at DESC LIMIT 1",
$jurisdiction,
$product_type,
current_time('mysql')
);
return $wpdb->get_var($query);
}
/**
* 存储税率到所有缓存层
*/
public function set_rate($jurisdiction, $product_type, $rate) {
$cache_key = 'tax_rate_' . md5($jurisdiction . '_' . $product_type);
// 1. 瞬态缓存
set_transient($cache_key, $rate, $this->transient_expiry);
// 2. 数据库缓存
$this->set_db_cached_rate($jurisdiction, $product_type, $rate);
// 3. 更新备用税率文件(极端情况备用)
$this->update_fallback_file($jurisdiction, $product_type, $rate);
}
/**
* 创建缓存数据库表
*/
public function create_cache_table() {
global $wpdb;
$table_name = $wpdb->prefix . 'tax_rates_cache';
$charset_collate = $wpdb->get_charset_collate();
$sql = "CREATE TABLE IF NOT EXISTS $table_name (
id bigint(20) NOT NULL AUTO_INCREMENT,
jurisdiction varchar(100) NOT NULL,
product_type varchar(50) NOT NULL,
rate_value decimal(8,4) NOT NULL,
created_at datetime DEFAULT CURRENT_TIMESTAMP,
updated_at datetime DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
expiry_date datetime NOT NULL,
source varchar(50) DEFAULT 'api',
PRIMARY KEY (id),
INDEX jurisdiction_product (jurisdiction, product_type),
INDEX expiry_idx (expiry_date)
) $charset_collate;";
require_once(ABSPATH . 'wp-admin/includes/upgrade.php');
dbDelta($sql);
}
}
当外部API不可用时,系统应优雅降级:
/**
* 智能税务计算器(带容错)
*/
class ResilientTaxCalculator {
private $primary_provider;
private $fallback_providers = [];
private $cache_handler;
private $circuit_breaker;
public function __construct() {
$this->cache_handler = new TaxCacheHandler();
$this->circuit_breaker = new CircuitBreaker('tax_api');
// 初始化提供者(按优先级)
$this->primary_provider = new TaxJarProvider(get_option('taxjar_api_key'));
$this->fallback_providers[] = new AvalaraProvider(get_option('avalara_api_key'));
$this->fallback_providers[] = new LocalTaxProvider(); // 本地数据库提供者
}
/**
* 容错税率获取
*/
public function get_tax_rate_with_fallback($jurisdiction, $product_type) {
// 检查缓存
$cached_rate = $this->cache_handler->get_rate($jurisdiction, $product_type);
if ($cached_rate) {
return $cached_rate;
}
// 检查断路器状态
if ($this->circuit_breaker->is_open()) {
error_log('税务API断路器已打开,使用本地备用税率');
return $this->get_local_fallback_rate($jurisdiction, $product_type);
}
// 尝试主提供者
try {
$rate = $this->primary_provider->get_rate($jurisdiction, $product_type);
if ($rate !== false) {
$this->cache_handler->set_rate($jurisdiction, $product_type, $rate);
$this->circuit_breaker->record_success();
return $rate;
}
} catch (Exception $e) {
$this->circuit_breaker->record_failure();
error_log('主税务API失败: ' . $e->getMessage());
}
// 尝试备用提供者
foreach ($this->fallback_providers as $provider) {
try {
if ($provider->is_available($jurisdiction)) {
$rate = $provider->get_rate($jurisdiction, $product_type);
if ($rate !== false) {
$this->cache_handler->set_rate($jurisdiction, $product_type, $rate);
return $rate;
}
}
} catch (Exception $e) {
error_log('备用税务API失败: ' . $e->getMessage());
continue;
}
}
// 所有API都失败,使用本地备用
return $this->get_local_fallback_rate($jurisdiction, $product_type);
}
}
/**
* 断路器模式实现
*/
class CircuitBreaker {
private $service_name;
private $failure_threshold = 5;
private $reset_timeout = 60; // 60秒后尝试恢复
private $failures = 0;
private $last_failure_time = 0;
private $state = 'closed'; // closed, open, half-open
public function __construct($service_name) {
$this->service_name = $service_name;
$this->load_state();
}
public function is_open() {
if ($this->state === 'open') {
// 检查是否应该进入半开状态
if (time() - $this->last_failure_time > $this->reset_timeout) {
$this->state = 'half-open';
$this->save_state();
}
return true;
}
return false;
}
public function record_failure() {
$this->failures++;
$this->last_failure_time = time();
if ($this->failures >= $this->failure_threshold) {
$this->state = 'open';
}
$this->save_state();
}
public function record_success() {
$this->failures = 0;
$this->state = 'closed';
$this->save_state();
}
private function load_state() {
$state = get_transient('circuit_breaker_' . $this->service_name);
if ($state) {
$this->failures = $state['failures'];
$this->last_failure_time = $state['last_failure_time'];
$this->state = $state['state'];
}
}
private function save_state() {
$state = [
'failures' => $this->failures,
'last_failure_time' => $this->last_failure_time,
'state' => $this->state
];
set_transient('circuit_breaker_' . $this->service_name, $state, $this->reset_timeout * 2);
}
}
在购物车和结账页面提供实时税务计算:
/**
* WordPress AJAX税务计算端点
*/
class TaxAjaxHandler {
public function __construct() {
add_action('wp_ajax_calculate_tax_preview', [$this, 'calculate_tax_preview']);
add_action('wp_ajax_nopriv_calculate_tax_preview', [$this, 'calculate_tax_preview']);
add_action('wp_enqueue_scripts', [$this, 'enqueue_tax_scripts']);
}
/**
* 前端税务计算脚本
*/
public function enqueue_tax_scripts() {
if (is_cart() || is_checkout()) {
wp_enqueue_script(
'tax-calculator',
plugin_dir_url(__FILE__) . 'js/tax-calculator.js',
['jquery'],
'1.0.0',
true
);
wp_localize_script('tax-calculator', 'tax_calculator_vars', [
'ajax_url' => admin_url('admin-ajax.php'),
'nonce' => wp_create_nonce('tax_calculate_nonce')
]);
}
}
/**
* AJAX税务预览计算
*/
public function calculate_tax_preview() {
// 验证nonce
if (!wp_verify_nonce($_POST['nonce'], 'tax_calculate_nonce')) {
wp_die('安全验证失败');
}
$country = sanitize_text_field($_POST['country']);
$state = sanitize_text_field($_POST['state']);
$postcode = sanitize_text_field($_POST['postcode']);
$cart_total = floatval($_POST['cart_total']);
$product_types = isset($_POST['product_types']) ?
array_map('sanitize_text_field', $_POST['product_types']) : [];
$tax_calculator = new ResilientTaxCalculator();
// 为每种产品类型计算税务
$tax_details = [];
$total_tax = 0;
foreach ($product_types as $product_type) {
$jurisdiction = $this->determine_jurisdiction($country, $state, $postcode);
$rate = $tax_calculator->get_tax_rate_with_fallback($jurisdiction, $product_type);
// 简化:假设每种产品类型金额平均分配
$product_amount = $cart_total / count($product_types);
$tax_amount = $product_amount * $rate;
$tax_details[] = [
'product_type' => $product_type,
'rate' => $rate * 100, // 转换为百分比
'amount' => $tax_amount
];
$total_tax += $tax_amount;
}
wp_send_json_success([
'tax_details' => $tax_details,
'total_tax' => round($total_tax, 2),
'total_with_tax' => round($cart_total + $total_tax, 2),
'currency' => get_woocommerce_currency()
]);
}
}
保持完整的税务计算记录以满足合规要求:
/**
* 税务审计日志系统
*/
class TaxAuditLogger {
private $log_table;
public function __construct() {
global $wpdb;
$this->log_table = $wpdb->prefix . 'tax_audit_log';
$this->create_log_table();
}
/**
* 记录税务计算事件
*/
public function log_tax_calculation($event_data) {
global $wpdb;
$defaults = [
'order_id' => 0,
0,
'calculation_type' => 'checkout',
'jurisdiction' => '',
'product_types' => '',
'subtotal' => 0.00,
'tax_amount' => 0.00,
'tax_rate' => 0.0000,
'tax_provider' => 'local',
'api_response' => '',
'ip_address' => '',
'user_agent' => '',
'calculated_at' => current_time('mysql')
];
$data = wp_parse_args($event_data, $defaults);
// 序列化数组字段
if (is_array($data['product_types'])) {
$data['product_types'] = json_encode($data['product_types']);
}
if (is_array($data['api_response'])) {
$data['api_response'] = json_encode($data['api_response']);
}
$wpdb->insert($this->log_table, $data);
return $wpdb->insert_id;
}
/**
* 创建审计日志表
*/
private function create_log_table() {
global $wpdb;
$charset_collate = $wpdb->get_charset_collate();
$sql = "CREATE TABLE IF NOT EXISTS {$this->log_table} (
id bigint(20) NOT NULL AUTO_INCREMENT,
order_id bigint(20) DEFAULT 0,
customer_id bigint(20) DEFAULT 0,
calculation_type varchar(50) NOT NULL,
jurisdiction varchar(100) NOT NULL,
product_types text,
subtotal decimal(12,4) NOT NULL,
tax_amount decimal(12,4) NOT NULL,
tax_rate decimal(8,6) NOT NULL,
tax_provider varchar(50) NOT NULL,
api_response text,
ip_address varchar(45) DEFAULT '',
user_agent text,
calculated_at datetime NOT NULL,
PRIMARY KEY (id),
INDEX idx_order_id (order_id),
INDEX idx_customer_id (customer_id),
INDEX idx_jurisdiction (jurisdiction),
INDEX idx_calculated_at (calculated_at)
) $charset_collate;";
require_once(ABSPATH . 'wp-admin/includes/upgrade.php');
dbDelta($sql);
}
/**
* 生成税务报告
*/
public function generate_tax_report($start_date, $end_date, $jurisdiction = '') {
global $wpdb;
$where_clauses = ["calculated_at BETWEEN %s AND %s"];
$where_values = [$start_date, $end_date];
if (!empty($jurisdiction)) {
$where_clauses[] = "jurisdiction = %s";
$where_values[] = $jurisdiction;
}
$where_sql = implode(' AND ', $where_clauses);
$query = $wpdb->prepare(
"SELECT
jurisdiction,
tax_provider,
COUNT(*) as calculation_count,
SUM(subtotal) as total_subtotal,
SUM(tax_amount) as total_tax,
AVG(tax_rate) as average_rate,
MIN(calculated_at) as first_calculation,
MAX(calculated_at) as last_calculation
FROM {$this->log_table}
WHERE {$where_sql}
GROUP BY jurisdiction, tax_provider
ORDER BY jurisdiction, total_tax DESC",
$where_values
);
return $wpdb->get_results($query, ARRAY_A);
}
}
/**
- WooCommerce税务计算集成
*/
class WooCommerceTaxIntegration {
private $tax_calculator;
private $audit_logger;
public function __construct() {
$this->tax_calculator = new ResilientTaxCalculator();
$this->audit_logger = new TaxAuditLogger();
// 集成WooCommerce税务计算钩子
add_filter('woocommerce_calc_tax', [$this, 'calculate_woocommerce_tax'], 10, 5);
add_action('woocommerce_checkout_update_order_meta', [$this, 'save_tax_calculation_metadata']);
add_filter('woocommerce_get_tax_location', [$this, 'adjust_tax_location'], 10, 2);
}
/**
* 自定义WooCommerce税务计算
*/
public function calculate_woocommerce_tax($taxes, $price, $rates, $price_includes_tax, $suppress_rounding) {
// 获取当前税务管辖区域
$location = WC_Tax::get_tax_location();
$country = $location[0];
$state = $location[1];
$postcode = $location[2];
$city = $location[3];
// 获取购物车中的产品类型
$product_types = $this->get_cart_product_types();
// 计算每个产品类型的税务
$calculated_taxes = [];
foreach ($product_types as $product_type) {
$jurisdiction = $this->determine_jurisdiction($country, $state, $postcode);
$tax_rate = $this->tax_calculator->get_tax_rate_with_fallback($jurisdiction, $product_type);
if ($tax_rate > 0) {
// 根据产品类型分配金额(简化逻辑)
$type_price = $price / count($product_types);
$tax_amount = $type_price * $tax_rate;
// 创建税率键(兼容WooCommerce格式)
$rate_key = $jurisdiction . '|' . ($tax_rate * 100);
if (!isset($calculated_taxes[$rate_key])) {
$calculated_taxes[$rate_key] = 0;
}
$calculated_taxes[$rate_key] += $tax_amount;
}
}
// 记录审计日志
$this->audit_logger->log_tax_calculation([
'calculation_type' => 'woocommerce_cart',
'jurisdiction' => $jurisdiction ?? '',
'product_types' => $product_types,
'subtotal' => $price,
'tax_amount' => array_sum($calculated_taxes),
'tax_rate' => $tax_rate ?? 0,
'tax_provider' => 'woocommerce_integration',
'ip_address' => $_SERVER['REMOTE_ADDR'] ?? '',
'user_agent' => $_SERVER['HTTP_USER_AGENT'] ?? ''
]);
return $calculated_taxes;
}
/**
* 获取购物车中的产品类型
*/
private function get_cart_product_types() {
$product_types = [];
if (!WC()->cart) {
return ['default'];
}
foreach (WC()->cart->get_cart() as $cart_item) {
$product = $cart_item['data'];
$product_type = $product->get_type();
// 获取自定义产品税务分类(如果存在)
$tax_class = $product->get_tax_class();
if (!empty($tax_class)) {
$product_type = $tax_class;
}
if (!in_array($product_type, $product_types)) {
$product_types[] = $product_type;
}
}
return empty($product_types) ? ['default'] : $product_types;
}
/**
* 保存税务计算元数据到订单
*/
public function save_tax_calculation_metadata($order_id) {
$order = wc_get_order($order_id);
if (!$order) {
return;
}
// 获取税务计算详情
$tax_details = [
'jurisdiction' => $order->get_tax_location()['country'] ?? '',
'calculated_at' => current_time('mysql'),
'tax_provider' => get_option('active_tax_provider', 'local'),
'tax_breakdown' => $order->get_taxes()
];
$order->update_meta_data('_cross_border_tax_details', $tax_details);
$order->save();
}
/**
* 调整税务计算位置
*/
public function adjust_tax_location($location, $tax_class) {
// 这里可以根据业务逻辑调整税务计算位置
// 例如:根据产品类型或客户类型使用不同的位置逻辑
// 示例:如果是B2B客户,使用公司注册地而非收货地址
$customer_id = get_current_user_id();
if ($customer_id) {
$is_b2b = get_user_meta($customer_id, 'is_b2b_customer', true);
if ($is_b2b) {
$b2b_location = get_user_meta($customer_id, 'business_location', true);
if ($b2b_location) {
return [
$b2b_location['country'],
$b2b_location['state'],
$b2b_location['postcode'],
$b2b_location['city']
];
}
}
}
return $location;
}
}
/**
- 前端税务显示优化
*/
class TaxDisplayEnhancer {
public function __construct() {
add_filter('woocommerce_cart_totals_order_total_html', [$this, 'enhance_tax_display']);
add_action('woocommerce_review_order_before_order_total', [$this, 'show_detailed_tax_breakdown']);
add_filter('woocommerce_get_price_suffix', [$this, 'add_tax_inclusive_suffix'], 10, 4);
}
/**
* 增强税务显示
*/
public function enhance_tax_display($value) {
if (is_cart() || is_checkout()) {
$tax_total = WC()->cart->get_taxes_total();
if ($tax_total > 0) {
$tax_message = sprintf(
'<small class="tax-included-notice">%s</small>',
__('(已包含税费)', 'your-text-domain')
);
return $value . $tax_message;
}
}
return $value;
}
/**
* 显示详细税务明细
*/
public function show_detailed_tax_breakdown() {
$taxes = WC()->cart->get_tax_totals();
if (empty($taxes)) {
return;
}
echo '<tr class="tax-breakdown-header">';
echo '<th colspan="2"><strong>' . __('税务明细', 'your-text-domain') . '</strong></th>';
echo '</tr>';
foreach ($taxes as $tax) {
echo '<tr class="tax-rate tax-rate-' . sanitize_title($tax->label) . '">';
echo '<th>' . $tax->label . '</th>';
echo '<td>' . wc_price($tax->amount) . '</td>';
echo '</tr>';
}
}
/**
* 添加含税价格后缀
*/
public function add_tax_inclusive_suffix($html, $product, $price, $qty) {
if (is_product() && wc_prices_include_tax()) {
$tax_message = sprintf(
' <small class="tax-inclusive">%s</small>',
__('(含税)', 'your-text-domain')
);
return $html . $tax_message;
}
return $html;
}
}
/**
- 管理界面扩展
*/
class TaxAdminInterface {
public function __construct() {
add_action('admin_menu', [$this, 'add_tax_admin_pages']);
add_action('admin_enqueue_scripts', [$this, 'enqueue_admin_scripts']);
add_action('wp_ajax_clear_tax_cache', [$this, 'clear_tax_cache_ajax']);
}
/**
* 添加管理页面
*/
public function add_tax_admin_pages() {
add_submenu_page(
'woocommerce',
__('跨境税务设置', 'your-text-domain'),
__('跨境税务', 'your-text-domain'),
'manage_woocommerce',
'cross-border-tax',
[$this, 'render_tax_settings_page']
);
add_submenu_page(
'woocommerce',
__('税务审计日志', 'your-text-domain'),
__('税务审计', 'your-text-domain'),
'manage_woocommerce',
'tax-audit-logs',
[$this, 'render_tax_audit_page']
);
}
/**
* 渲染税务设置页面
*/
public function render_tax_settings_page() {
?>
<div class="wrap">
<h1><?php _e('跨境税务设置', 'your-text-domain'); ?></h1>
<div class="card">
<h2><?php _e('税务API配置', 'your-text-domain'); ?></h2>
<form method="post" action="options.php">
<?php settings_fields('cross_border_tax_settings'); ?>
<?php do_settings_sections('cross_border_tax_settings'); ?>
<table class="form-table">
<tr>
<th scope="row">
<label for="taxjar_api_key"><?php _e('TaxJar API密钥', 'your-text-domain'); ?></label>
</th>
<td>
<input type="password" id="taxjar_api_key"
name="taxjar_api_key"
value="<?php echo esc_attr(get_option('taxjar_api_key')); ?>"
class="regular-text">
<p class="description">
<?php _e('从TaxJar账户获取API密钥', 'your-text-domain'); ?>
</p>
</td>
</tr>
<tr>
<th scope="row">
<label for="avalara_api_key"><?php _e('Avalara API密钥', 'your-text-domain'); ?></label>
</th>
<td>
<input type="password" id="avalara_api_key"
name="avalara_api_key"
value="<?php echo esc_attr(get_option('avalara_api_key')); ?>"
class="regular-text">
</td>
</tr>
<tr>
<th scope="row">
<?php _e('缓存设置', 'your-text-domain'); ?>
</th>
<td>
<label>
<input type="checkbox" name="enable_tax_cache"
value="1" <?php checked(get_option('enable_tax_cache'), 1); ?>>
<?php _e('启用税率缓存', 'your-text-domain'); ?>
</label>
<br>
<label>
<input type="number" name="cache_duration"
value="<?php echo esc_attr(get_option('cache_duration', 24)); ?>"
min="1" max="720" style="width: 80px;">
<?php _e('缓存时长(小时)', 'your-text-domain'); ?>
</label>
</td>
</tr>
</table>
<?php submit_button(); ?>
</form>
<hr>
<h3><?php _e('缓存管理', 'your-text-domain'); ?></h3>
<p>
<button type="button" class="button" id="clear-tax-cache">
<?php _e('清除税率缓存', 'your-text-domain'); ?>
</button>
<span id="cache-clear-result" style="margin-left: 10px;"></span>
</p>
</div>
<div class="card">
<h2><?php _e('备用税率设置', 'your-text-domain'); ?></h2>
<p><?php _e('当所有API都不可用时使用的默认税率', 'your-text-domain'); ?></p>
<div id="fallback-rates-container">
<!-- 通过AJAX动态加载备用税率设置 -->
</div>
</div>
</div>
<script>
jQuery(document).ready(function($) {
$('#clear-tax-cache').on('click', function() {
var $button = $(this);
var $result = $('#cache-clear-result');
$button.prop('disabled', true).text('清除中...');
$result.text('');
$.ajax({
url: ajaxurl,
type: 'POST',
data: {
action: 'clear_tax_cache',
nonce: '<?php echo wp_create_nonce('clear_tax_cache'); ?>'
},
success: function(response) {
if (response.success) {
$result.text('缓存已清除').css('color', 'green');
} else {
$result.text('清除失败').css('color', 'red');
}
},
complete: function() {
$button.prop('disabled', false).text('清除税率缓存');
}
});
});
});
</script>
<?php
}
/**
* 渲染税务审计页面
*/
public function render_tax_audit_page() {
$audit_logger = new TaxAuditLogger();
// 获取报告数据
$start_date = isset($_GET['start_date']) ? sanitize_text_field($_GET['start_date']) : date('Y-m-01');
$end_date = isset($_GET['end_date']) ? sanitize_text_field($_GET['end_date']) : date('Y-m-d');
$jurisdiction = isset($_GET['jurisdiction']) ? sanitize_text_field($_GET['jurisdiction']) : '';
$report_data = $audit_logger->generate_tax_report($start_date, $end_date, $jurisdiction);
?>
<div class="wrap">
<h1><?php _e('税务审计日志', 'your-text-domain'); ?></h1>
<div class="card">
<h2><?php _e('报告筛选', 'your-text-domain'); ?></h2>
<form method="get" action="">
<input type="hidden" name="page" value="tax-audit-logs">
<table class="form-table">
<tr>
<th scope="row">
<label for="start_date"><?php _e('开始日期', 'your-text-domain'); ?></label>
</th>
<td>
<input type="date" id="start_date" name="start_date"
value="<?php echo esc_attr($start_date); ?>">
</td>
</tr>
<tr>


