diff --git a/includes/zoho/class-zoho-sync.php b/includes/zoho/class-zoho-sync.php index 62d4aeb4..a400791f 100644 --- a/includes/zoho/class-zoho-sync.php +++ b/includes/zoho/class-zoho-sync.php @@ -81,7 +81,30 @@ class HVAC_Zoho_Sync { ); } - // Check for HTTP-level errors + // Check for Zoho API error codes FIRST (more specific than generic HTTP errors) + if (isset($response['data'][0]['code']) && !in_array($response['data'][0]['code'], array('SUCCESS', 'DUPLICATE_DATA'))) { + $error_msg = isset($response['data'][0]['message']) ? $response['data'][0]['message'] : $response['data'][0]['code']; + // Include field-level details if available + if (isset($response['data'][0]['details'])) { + $details = $response['data'][0]['details']; + if (isset($details['api_name'])) { + $error_msg .= ' (field: ' . $details['api_name'] . ')'; + } + if (isset($details['expected_data_type'])) { + $error_msg .= ' (expected: ' . $details['expected_data_type'] . ')'; + } + if (isset($details['info'])) { + $error_msg .= ' - ' . $details['info']; + } + } + return array( + 'success' => false, + 'id' => null, + 'error' => $error_msg + ); + } + + // Check for HTTP-level errors (generic fallback) if (isset($response['error'])) { return array( 'success' => false, @@ -90,16 +113,6 @@ class HVAC_Zoho_Sync { ); } - // Check for Zoho API error codes - if (isset($response['data'][0]['code']) && !in_array($response['data'][0]['code'], array('SUCCESS', 'DUPLICATE_DATA'))) { - $error_msg = isset($response['data'][0]['message']) ? $response['data'][0]['message'] : $response['data'][0]['code']; - return array( - 'success' => false, - 'id' => null, - 'error' => $error_msg - ); - } - // Check for successful response with ID if (isset($response['data'][0]['details']['id'])) { return array( @@ -454,9 +467,10 @@ class HVAC_Zoho_Sync { $sync_succeeded = false; // Check if contact already exists in Zoho - $search_response = $this->auth->make_api_request('/Contacts/search', 'GET', array( - 'criteria' => "(Email:equals:{$contact_data['Email']})" - )); + $search_response = $this->auth->make_api_request( + '/Contacts/search?criteria=(Email:equals:' . urlencode($contact_data['Email']) . ')', + 'GET' + ); if (!empty($search_response['data'])) { // Update existing contact @@ -1334,11 +1348,25 @@ class HVAC_Zoho_Sync { $role = 'Trainee'; } - return array( + // Last_Name is required by Zoho - fallback to display_name or username + $last_name = html_entity_decode(get_user_meta($user->ID, 'last_name', true), ENT_QUOTES | ENT_HTML5, 'UTF-8'); + if (empty(trim($last_name))) { + $last_name = $user->display_name ?: $user->user_login; + } + + // Sanitize phone: strip to digits and leading +, require 10+ digits for validity + $raw_phone = get_user_meta($user->ID, 'phone_number', true); + $phone_digits = preg_replace('/\D/', '', $raw_phone); + $phone = ''; + if (strlen($phone_digits) >= 10) { + // Preserve leading + if present, otherwise just use digits + $phone = (strpos(trim($raw_phone), '+') === 0 ? '+' : '') . $phone_digits; + } + + $data = array( 'First_Name' => html_entity_decode(get_user_meta($user->ID, 'first_name', true), ENT_QUOTES | ENT_HTML5, 'UTF-8'), - 'Last_Name' => html_entity_decode(get_user_meta($user->ID, 'last_name', true), ENT_QUOTES | ENT_HTML5, 'UTF-8'), + 'Last_Name' => $last_name, 'Email' => $user->user_email, - 'Phone' => get_user_meta($user->ID, 'phone_number', true), 'Title' => html_entity_decode(get_user_meta($user->ID, 'hvac_professional_title', true), ENT_QUOTES | ENT_HTML5, 'UTF-8'), 'Company' => html_entity_decode(get_user_meta($user->ID, 'hvac_company_name', true), ENT_QUOTES | ENT_HTML5, 'UTF-8'), 'Lead_Source' => 'HVAC Community Events', @@ -1348,6 +1376,13 @@ class HVAC_Zoho_Sync { 'Years_Experience' => get_user_meta($user->ID, 'hvac_years_experience', true), 'Certification' => get_user_meta($user->ID, 'hvac_certifications', true) ); + + // Only include Phone if we have a valid value (10+ digits) + if (!empty($phone)) { + $data['Phone'] = $phone; + } + + return $data; } /**