fix: Use HVAC_Secure_Storage consistently for Zoho credentials
- Fix Client ID regex to allow lowercase letters - Update HVAC_Zoho_CRM_Auth to use encrypted storage for all operations - Update class-zoho-admin.php to use HVAC_Secure_Storage for credential retrieval - Update OAuth callback to use secure storage for token storage - Update Status.md with blocking production issue (400 Bad Request) Note: Issue persists on production - needs further investigation 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
parent
08944d48ee
commit
5a55b78d03
3 changed files with 90 additions and 35 deletions
44
Status.md
44
Status.md
|
|
@ -8,9 +8,49 @@
|
|||
|
||||
## 🎯 CURRENT SESSION - ZOHO CRM INTEGRATION SETUP (Dec 16, 2025)
|
||||
|
||||
### Zoho CRM Integration - Staging Environment
|
||||
### Zoho CRM Integration - Production Issue (BLOCKING)
|
||||
|
||||
**Objective:** Configure and test Zoho CRM sync implementation for staging environment.
|
||||
**Objective:** Configure and test Zoho CRM sync implementation for production environment.
|
||||
|
||||
**Status:** 🔴 BLOCKING - Credential save hangs on production (400 Bad Request)
|
||||
|
||||
### Active Issue - Credential Save Hanging on Production
|
||||
|
||||
**Problem:** When saving Zoho CRM credentials at `https://upskillhvac.com/wp-admin/admin.php?page=hvac-zoho-sync`, the AJAX request returns a 400 Bad Request error and the form hangs on "Saving...".
|
||||
|
||||
**Console Error:**
|
||||
```
|
||||
POST https://upskillhvac.com/wp-admin/admin-ajax.php 400 (Bad Request)
|
||||
```
|
||||
|
||||
**Investigation Completed:**
|
||||
1. ✅ Fixed Client ID regex to allow lowercase letters (`[A-Z0-9]` → `[A-Za-z0-9]`)
|
||||
2. ✅ Fixed credential storage mismatch - all methods now use `HVAC_Secure_Storage`
|
||||
3. ✅ Updated `HVAC_Zoho_CRM_Auth` class to use encrypted storage consistently
|
||||
4. ✅ Updated OAuth callback to use secure storage
|
||||
5. ✅ Updated test_connection to use secure storage
|
||||
6. ✅ Deployed fixes to production - **Issue persists**
|
||||
|
||||
**Files Modified:**
|
||||
- `includes/admin/class-zoho-admin.php` - Secure storage for credentials, fixed regex
|
||||
- `includes/zoho/class-zoho-crm-auth.php` - All credential operations use HVAC_Secure_Storage
|
||||
|
||||
**Next Steps for Investigation:**
|
||||
1. Check PHP error logs on production server for detailed error
|
||||
2. Test AJAX endpoint directly via curl to isolate frontend vs backend issue
|
||||
3. Verify nonce generation and validation on production
|
||||
4. Check if WAF/security plugin is blocking the request
|
||||
5. Test with browser network tab to see exact request/response
|
||||
|
||||
**Possible Causes:**
|
||||
- Server-side security rules (Cloudflare, ModSecurity) blocking POST to admin-ajax.php
|
||||
- Nonce validation failing due to caching
|
||||
- Plugin conflict on production
|
||||
- HVAC_Secure_Storage encryption key difference between environments
|
||||
|
||||
---
|
||||
|
||||
### Zoho CRM Integration - Staging Environment (Working)
|
||||
|
||||
**Status:** ✅ OAuth Working, Sync Methods Implemented, Dry-Run Tested
|
||||
|
||||
|
|
|
|||
|
|
@ -386,7 +386,7 @@ class HVAC_Zoho_Admin {
|
|||
}
|
||||
|
||||
// Validate Client ID format (should start with "1000.")
|
||||
if (!preg_match('/^1000\.[A-Z0-9]+$/', $client_id)) {
|
||||
if (!preg_match('/^1000\.[A-Za-z0-9]+$/', $client_id)) {
|
||||
wp_send_json_error(array('message' => 'Invalid Client ID format. Should start with "1000."'));
|
||||
return;
|
||||
}
|
||||
|
|
@ -557,6 +557,11 @@ class HVAC_Zoho_Admin {
|
|||
wp_die('OAuth callback missing state parameter. Possible CSRF attack.');
|
||||
}
|
||||
|
||||
// Load secure storage for credential handling
|
||||
if (!class_exists('HVAC_Secure_Storage')) {
|
||||
require_once HVAC_PLUGIN_DIR . 'includes/class-hvac-secure-storage.php';
|
||||
}
|
||||
|
||||
require_once HVAC_PLUGIN_DIR . 'includes/zoho/class-zoho-crm-auth.php';
|
||||
$auth = new HVAC_Zoho_CRM_Auth();
|
||||
|
||||
|
|
@ -564,9 +569,12 @@ class HVAC_Zoho_Admin {
|
|||
wp_die('OAuth state validation failed. Please try the authorization again.');
|
||||
}
|
||||
|
||||
// Get credentials from WordPress options
|
||||
$client_id = get_option('hvac_zoho_client_id', '');
|
||||
$client_secret = get_option('hvac_zoho_client_secret', '');
|
||||
// Get credentials using secure storage (credentials are stored encrypted)
|
||||
if (!class_exists('HVAC_Secure_Storage')) {
|
||||
require_once HVAC_PLUGIN_DIR . 'includes/class-hvac-secure-storage.php';
|
||||
}
|
||||
$client_id = HVAC_Secure_Storage::get_credential('hvac_zoho_client_id', '');
|
||||
$client_secret = HVAC_Secure_Storage::get_credential('hvac_zoho_client_secret', '');
|
||||
|
||||
if (empty($client_id) || empty($client_secret)) {
|
||||
wp_die('OAuth callback error: Missing client credentials. Please configure your Zoho CRM credentials first.');
|
||||
|
|
@ -609,20 +617,19 @@ class HVAC_Zoho_Admin {
|
|||
exit;
|
||||
}
|
||||
|
||||
// Save tokens
|
||||
update_option('hvac_zoho_access_token', $token_data['access_token']);
|
||||
// Save tokens using secure storage
|
||||
HVAC_Secure_Storage::store_credential('hvac_zoho_access_token', $token_data['access_token']);
|
||||
update_option('hvac_zoho_token_expires', time() + ($token_data['expires_in'] ?? 3600));
|
||||
|
||||
// Refresh token might not be returned on subsequent authorizations
|
||||
if (isset($token_data['refresh_token']) && !empty($token_data['refresh_token'])) {
|
||||
update_option('hvac_zoho_refresh_token', $token_data['refresh_token']);
|
||||
HVAC_Secure_Storage::store_credential('hvac_zoho_refresh_token', $token_data['refresh_token']);
|
||||
} else {
|
||||
$existing_refresh = get_option('hvac_zoho_refresh_token');
|
||||
$existing_refresh = HVAC_Secure_Storage::get_credential('hvac_zoho_refresh_token', '');
|
||||
if (empty($existing_refresh)) {
|
||||
// This is critical - we need a refresh token for long-term access
|
||||
// Store a warning but still complete the flow
|
||||
update_option('hvac_zoho_missing_refresh_token', true);
|
||||
} else {
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -653,9 +660,12 @@ class HVAC_Zoho_Admin {
|
|||
return;
|
||||
}
|
||||
|
||||
// Get credentials from WordPress options
|
||||
$client_id = get_option('hvac_zoho_client_id', '');
|
||||
$client_secret = get_option('hvac_zoho_client_secret', '');
|
||||
// Get credentials using secure storage (credentials are stored encrypted)
|
||||
if (!class_exists('HVAC_Secure_Storage')) {
|
||||
require_once HVAC_PLUGIN_DIR . 'includes/class-hvac-secure-storage.php';
|
||||
}
|
||||
$client_id = HVAC_Secure_Storage::get_credential('hvac_zoho_client_id', '');
|
||||
$client_secret = HVAC_Secure_Storage::get_credential('hvac_zoho_client_secret', '');
|
||||
|
||||
// Check configuration before attempting connection
|
||||
if (empty($client_id)) {
|
||||
|
|
@ -679,7 +689,7 @@ class HVAC_Zoho_Admin {
|
|||
}
|
||||
|
||||
// Check if we have stored refresh token from previous OAuth
|
||||
$stored_refresh_token = get_option('hvac_zoho_refresh_token');
|
||||
$stored_refresh_token = HVAC_Secure_Storage::get_credential('hvac_zoho_refresh_token', '');
|
||||
|
||||
if (empty($stored_refresh_token)) {
|
||||
|
||||
|
|
|
|||
|
|
@ -23,10 +23,15 @@ class HVAC_Zoho_CRM_Auth {
|
|||
private $last_error = null;
|
||||
|
||||
public function __construct() {
|
||||
// Load credentials from WordPress options (new approach)
|
||||
$this->client_id = get_option('hvac_zoho_client_id', '');
|
||||
$this->client_secret = get_option('hvac_zoho_client_secret', '');
|
||||
$this->refresh_token = get_option('hvac_zoho_refresh_token', '');
|
||||
// Load secure storage class
|
||||
if (!class_exists('HVAC_Secure_Storage')) {
|
||||
require_once plugin_dir_path(dirname(__FILE__)) . 'class-hvac-secure-storage.php';
|
||||
}
|
||||
|
||||
// Load credentials from WordPress options using secure storage (encrypted)
|
||||
$this->client_id = HVAC_Secure_Storage::get_credential('hvac_zoho_client_id', '');
|
||||
$this->client_secret = HVAC_Secure_Storage::get_credential('hvac_zoho_client_secret', '');
|
||||
$this->refresh_token = HVAC_Secure_Storage::get_credential('hvac_zoho_refresh_token', '');
|
||||
$this->redirect_uri = get_site_url() . '/oauth/callback';
|
||||
|
||||
// Fallback to config file if options are empty (backward compatibility)
|
||||
|
|
@ -354,31 +359,31 @@ class HVAC_Zoho_CRM_Auth {
|
|||
}
|
||||
|
||||
/**
|
||||
* Save tokens to WordPress options
|
||||
* Save tokens to WordPress options using secure storage
|
||||
*/
|
||||
private function save_tokens() {
|
||||
update_option('hvac_zoho_refresh_token', $this->refresh_token);
|
||||
HVAC_Secure_Storage::store_credential('hvac_zoho_refresh_token', $this->refresh_token);
|
||||
$this->save_access_token();
|
||||
}
|
||||
|
||||
/**
|
||||
* Save access token
|
||||
* Save access token using secure storage
|
||||
*/
|
||||
private function save_access_token() {
|
||||
update_option('hvac_zoho_access_token', $this->access_token);
|
||||
HVAC_Secure_Storage::store_credential('hvac_zoho_access_token', $this->access_token);
|
||||
update_option('hvac_zoho_token_expiry', $this->token_expiry);
|
||||
}
|
||||
|
||||
/**
|
||||
* Load access token from WordPress options
|
||||
* Load access token from WordPress options using secure storage
|
||||
*/
|
||||
private function load_access_token() {
|
||||
$this->access_token = get_option('hvac_zoho_access_token');
|
||||
$this->access_token = HVAC_Secure_Storage::get_credential('hvac_zoho_access_token', '');
|
||||
$this->token_expiry = get_option('hvac_zoho_token_expiry', 0);
|
||||
|
||||
// Load refresh token if not set
|
||||
if (!$this->refresh_token) {
|
||||
$this->refresh_token = get_option('hvac_zoho_refresh_token');
|
||||
$this->refresh_token = HVAC_Secure_Storage::get_credential('hvac_zoho_refresh_token', '');
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue