api_url = get_option('czl_api_url', ''); $this->username = get_option('czl_username', ''); $this->password = get_option('czl_password', ''); $this->token = get_transient('czl_api_token'); $this->token_expires = get_transient('czl_api_token_expires'); $this->init_country_mapping(); } /** * 初始化国家代码映射 */ private function init_country_mapping() { // 从API获取国家列表并缓存 $cached_mapping = get_transient('czl_country_mapping'); if ($cached_mapping !== false) { $this->country_mapping = $cached_mapping; return; } try { $response = wp_remote_get('https://tms-api-go.czl.net/api/countries', array( 'timeout' => 30 )); if (is_wp_error($response)) { throw new Exception($response->get_error_message()); } $data = json_decode(wp_remote_retrieve_body($response), true); if (!empty($data['data'])) { $mapping = array(); foreach ($data['data'] as $country) { $mapping[$country['ename']] = $country['code']; } $this->country_mapping = $mapping; set_transient('czl_country_mapping', $mapping, DAY_IN_SECONDS); CZL_Logger::info('Country mapping updated'); } } catch (Exception $e) { CZL_Logger::error('Failed to get country mapping', array('error' => $e->getMessage())); $this->country_mapping = array(); } } /** * 转换国家代码 */ private function convert_country_code($wc_country) { CZL_Logger::debug('Converting country code', array('country' => $wc_country)); // 获取WooCommerce国家名称 $countries = WC()->countries->get_countries(); $country_name = isset($countries[$wc_country]) ? $countries[$wc_country] : ''; // 在映射中查找 foreach ($this->country_mapping as $name => $code) { if (stripos($name, $country_name) !== false || stripos($country_name, $name) !== false) { CZL_Logger::debug('Found country mapping', array( 'from' => $wc_country, 'to' => $code )); return $code; } } // 如果没找到映射,返回原始代码 CZL_Logger::debug('No mapping found, using original code', array('country' => $wc_country)); return $wc_country; } /** * 获取API认证Token */ private function get_token() { if ($this->token && time() < $this->token_expires) { return $this->token; } $response = wp_remote_post($this->api_url . '/auth/login', array( 'body' => array( 'username' => $this->username, 'password' => md5($this->password) // CZL API需要MD5加密的密码 ), 'timeout' => 30 )); if (is_wp_error($response)) { throw new Exception(esc_html($response->get_error_message())); } $body = json_decode(wp_remote_retrieve_body($response), true); if (empty($body['success'])) { throw new Exception(!empty($body['message']) ? esc_html($body['message']) : esc_html__('认证失败', 'czlexpress-for-woocommerce')); } $this->token = $body['data']['token']; $this->token_expires = time() + 7200; // CZL token有效期通常是2小时 set_transient('czl_api_token', $this->token, 7200); set_transient('czl_api_token_expires', $this->token_expires, 7200); return $this->token; } /** * 发送API请求 */ private function send_request($endpoint, $params = array(), $method = 'GET') { try { $url = $this->get_api_url($endpoint); $headers = $this->get_headers(); $args = array( 'method' => $method, 'headers' => $headers, 'timeout' => 30, 'sslverify' => false ); if ($method === 'POST') { $args['body'] = json_encode($params); CZL_Logger::debug('API request', array( 'url' => $url, 'method' => $method, 'params' => $params )); } $response = wp_remote_request($url, $args); if (is_wp_error($response)) { throw new Exception($response->get_error_message()); } $body = wp_remote_retrieve_body($response); $data = json_decode($body, true); CZL_Logger::debug('API response', array( 'url' => $url, 'response' => $data )); if (!$data) { throw new Exception('Invalid JSON response'); } return $data; } catch (Exception $e) { CZL_Logger::error('API request failed', array( 'url' => $url, 'error' => $e->getMessage(), 'params' => $params )); throw $e; } } /** * 获取运费报价 */ public function get_shipping_rate($params) { try { $api_url = 'https://tms.czl.net/defaultPriceSearchJson.htm'; // 转换国家代码 $country_code = $this->convert_country_code($params['country']); // 构建请求参数 $query = array( 'weight' => $params['weight'], 'country' => $country_code, 'cargoType' => $params['cargoType'], 'length' => $params['length'], 'width' => $params['width'], 'height' => $params['height'], 'postcode' => $params['postcode'] ); CZL_Logger::debug('Shipping rate request', $query); // 发送请求 $response = wp_remote_post($api_url . '?' . http_build_query($query), array( 'headers' => array( 'Authorization' => 'Basic ' . base64_encode($this->username . ':' . $this->password) ), 'timeout' => 30 )); if (is_wp_error($response)) { throw new Exception($response->get_error_message()); } $body = wp_remote_retrieve_body($response); CZL_Logger::debug('API raw response', $body); $data = json_decode($body, true); if (empty($data)) { throw new Exception('Empty API response'); } // 检查响应格式 if (!is_array($data)) { throw new Exception('Invalid API response format'); } return $data; } catch (Exception $e) { CZL_Logger::error('API Error', array('message' => $e->getMessage())); throw $e; } } /** * 格式化运费报价结果 */ private function format_shipping_rates($rates) { $formatted_rates = array(); foreach ($rates as $rate) { $formatted_rates[] = array( 'method_id' => 'czl_express_' . sanitize_title($rate['product_id']), 'method_title' => $rate['product_name'], 'method_name' => $rate['product_name'], 'cost' => floatval($rate['total_amount']), 'delivery_time' => $rate['product_aging'], 'product_id' => $rate['product_id'], 'product_note' => $rate['product_note'] ); } return $formatted_rates; } /** * 创建运单 */ public function create_order($order_data) { try { // 添加请求前的日志 CZL_Logger::debug('Creating order', array('data' => $order_data)); $response = wp_remote_post('https://tms.czl.net/createOrderApi.htm', array( 'body' => array( 'Param' => wp_json_encode($order_data) ), 'timeout' => 30 )); // 添加响应日志 CZL_Logger::debug('API response received', array('response' => $response)); if (is_wp_error($response)) { throw new Exception('API请求失败: ' . $response->get_error_message()); } $result = json_decode(wp_remote_retrieve_body($response), true); if (json_last_error() !== JSON_ERROR_NONE) { throw new Exception('JSON解析失败: ' . json_last_error_msg()); } if (empty($result['ack']) || $result['ack'] !== 'true') { throw new Exception(!empty($result['message']) ? esc_html($result['message']) : esc_html__('未知错误', 'czlexpress-for-woocommerce')); } return $result; } catch (Exception $e) { CZL_Logger::error('Create order failed', array( 'error' => $e->getMessage(), 'trace' => $e->getTraceAsString() )); throw $e; } } /** * 获取运单跟踪信息 */ public function get_tracking($tracking_number) { try { $response = wp_remote_post('https://tms.czl.net/selectTrack.htm', array( 'body' => array( 'documentCode' => $tracking_number ), 'timeout' => 30 )); if (is_wp_error($response)) { throw new Exception($response->get_error_message()); } $result = json_decode(wp_remote_retrieve_body($response), true); if (empty($result[0]['ack']) || $result[0]['ack'] !== 'true') { throw new Exception('获取跟踪信息失败'); } return $result[0]['data'][0]; } catch (Exception $e) { CZL_Logger::error('Failed to get tracking', array('error' => $e->getMessage())); throw $e; } } /** * 获取运单标签 */ public function get_label($order_id) { $url = sprintf( 'https://tms-label.czl.net/order/FastRpt/PDF_NEW.aspx?Format=lbl_sub一票多件161810499441.frx&PrintType=1&order_id=%s', $order_id ); return $url; } /** * 取消运单 */ public function cancel_order($order_number) { return $this->request('/shipping/cancel', 'POST', array( 'order_number' => $order_number )); } /** * 测试认证 */ public function test_auth() { try { $response = wp_remote_post('https://tms.czl.net/selectAuth.htm', array( 'body' => array( 'username' => $this->username, 'password' => $this->password ), 'timeout' => 30 )); if (is_wp_error($response)) { throw new Exception($response->get_error_message()); } $result = json_decode(wp_remote_retrieve_body($response), true); if (empty($result['success'])) { throw new Exception('认证失败'); } return array( 'customer_id' => $result['customer_id'], 'customer_userid' => $result['customer_userid'] ); } catch (Exception $e) { CZL_Logger::error('Authentication test failed', array('error' => $e->getMessage())); throw $e; } } /** * 获取支持的国家列表 */ public function get_countries() { try { $response = wp_remote_get('https://tms-api-go.czl.net/api/countries', array( 'timeout' => 30 )); if (is_wp_error($response)) { throw new Exception($response->get_error_message()); } $result = json_decode(wp_remote_retrieve_body($response), true); if ($result['code'] !== 200) { throw new Exception('获取国家列表失败'); } return $result['data']; } catch (Exception $e) { CZL_Logger::error('Failed to get countries list', array('error' => $e->getMessage())); throw $e; } } private function ensure_logged_in() { try { CZL_Logger::info('Starting authentication'); $auth_url = 'https://tms.czl.net/selectAuth.htm'; $auth_data = array( 'username' => $this->username, 'password' => $this->password ); CZL_Logger::debug('Auth request data', array('data' => $auth_data)); $ch = curl_init($auth_url); curl_setopt($ch, CURLOPT_POST, 1); curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($auth_data)); curl_setopt($ch, CURLOPT_HTTPHEADER, array( 'Accept-Language: zh-cn', 'Connection: Keep-Alive', 'Cache-Control: no-cache' )); curl_setopt($ch, CURLOPT_TIMEOUT, 30); $response = curl_exec($ch); CZL_Logger::debug('Auth raw response', array('response' => $response)); if (curl_errno($ch)) { throw new Exception('认证请求失败'); } curl_close($ch); // 解析响应 $result = json_decode(str_replace("'", '"', $response), true); CZL_Logger::debug('Auth decoded response', array('result' => $result)); if (empty($result) || !isset($result['customer_id'])) { throw new Exception('认证失败'); } // 保存认证信息 $this->customer_id = $result['customer_id']; $this->customer_userid = $result['customer_userid']; } catch (Exception $e) { CZL_Logger::error('Authentication failed', array('error' => $e->getMessage())); throw new Exception('认证失败,请联系CZL Express'); } } private function make_request($url, $data = array(), $method = 'POST') { try { $args = array( 'method' => $method, 'timeout' => 60, 'redirection' => 5, 'httpversion' => '1.1', 'blocking' => true, 'headers' => array( 'Accept' => '*/*', 'Accept-Language' => 'zh-cn', 'Cache-Control' => 'no-cache', 'Content-Type' => 'application/x-www-form-urlencoded;charset=UTF-8' ), 'cookies' => array() ); if ($method === 'POST' && !empty($data)) { $args['body'] = is_array($data) ? $data : wp_json_encode($data); } $response = wp_remote_request($url, $args); if (is_wp_error($response)) { throw new Exception('请求失败: ' . $response->get_error_message()); } $body = wp_remote_retrieve_body($response); if (empty($body)) { throw new Exception('请求失败: 空响应'); } CZL_Logger::debug('API raw response', array('response' => $body)); $result = json_decode($body, true); if (json_last_error() !== JSON_ERROR_NONE) { CZL_Logger::error('JSON decode error', array('error' => json_last_error_msg())); throw new Exception('响应数据格式错误'); } CZL_Logger::debug('API decoded response', array('result' => $result)); // 检查API错误信息 if (isset($result['message']) && !empty($result['message'])) { CZL_Logger::warning('API returned error message', array('message' => $result['message'])); } return $result; } catch (Exception $e) { CZL_Logger::error('Request failed', array('error' => $e->getMessage())); throw $e; } } /** * 认证方法 */ public function authenticate() { try { if (defined('WP_DEBUG_LOG') && WP_DEBUG_LOG) { error_log('CZL Express: Starting authentication'); } $auth_url = 'https://tms.czl.net/selectAuth.htm'; $auth_data = array( 'username' => $this->username, 'password' => $this->password ); if (defined('WP_DEBUG_LOG') && WP_DEBUG_LOG) { error_log('CZL Express: Auth request data - ' . print_r($auth_data, true)); } $response = wp_remote_post($auth_url, array( 'body' => $auth_data, 'timeout' => 30, 'headers' => array( 'Accept-Language' => 'zh-cn', 'Connection' => 'Keep-Alive', 'Cache-Control' => 'no-cache' ) )); if (is_wp_error($response)) { throw new Exception('认证请求失败: ' . $response->get_error_message()); } $body = wp_remote_retrieve_body($response); if (defined('WP_DEBUG_LOG') && WP_DEBUG_LOG) { error_log('CZL Express: Auth raw response - ' . $body); } // 解析响应 $result = json_decode(str_replace("'", '"', $body), true); if (defined('WP_DEBUG_LOG') && WP_DEBUG_LOG) { error_log('CZL Express: Auth decoded response - ' . print_r($result, true)); } if (empty($result) || !isset($result['customer_id'])) { throw new Exception('认证失败: 无效的响应数据'); } // 返回认证结果 return array( 'ack' => true, 'customer_id' => $result['customer_id'], 'customer_userid' => $result['customer_userid'], 'message' => '' ); } catch (Exception $e) { if (defined('WP_DEBUG_LOG') && WP_DEBUG_LOG) { error_log('CZL Express Error: Authentication failed - ' . esc_html($e->getMessage())); } return array( 'ack' => false, 'message' => esc_html($e->getMessage()) ); } } /** * 获取运单轨迹 */ public function get_tracking_info($tracking_number) { try { $response = $this->send_request('/tracking/query', array( 'tracking_number' => $tracking_number ), 'POST'); CZL_Logger::debug('Tracking info retrieved', array( 'tracking_number' => $tracking_number, 'response' => $response )); return $response; } catch (Exception $e) { CZL_Logger::error('Failed to get tracking info', array( 'tracking_number' => $tracking_number, 'error' => $e->getMessage() )); throw $e; } } /** * 创建运单 */ public function create_shipment($order_data) { try { CZL_Logger::debug('Creating shipment', array( 'order_data' => $order_data )); $response = $this->send_request('/shipment/create', $order_data, 'POST'); CZL_Logger::debug('Shipment created', array( 'response' => $response )); return $response; } catch (Exception $e) { CZL_Logger::error('Failed to create shipment', array( 'order_data' => $order_data, 'error' => $e->getMessage() )); throw $e; } } /** * 获取跟踪单号 * * @param string $czl_order_id CZL订单号 * @return array 包含跟踪单号的响应数据 * @throws Exception 如果请求失败 */ public function get_tracking_number($czl_order_id) { $endpoint = '/api/tracking/number'; $params = array( 'order_id' => $czl_order_id ); try { $response = $this->send_request('GET', $endpoint, $params); if (empty($response['tracking_number'])) { throw new Exception('未找到跟踪单号'); } return array( 'tracking_number' => $response['tracking_number'], 'status' => isset($response['status']) ? $response['status'] : null ); } catch (Exception $e) { throw new Exception('获取跟踪单号失败: ' . esc_html($e->getMessage())); } } }