testing progress

This commit is contained in:
2025-08-12 09:54:32 -07:00
parent e18e046431
commit 2d6767033b
3 changed files with 654 additions and 256 deletions

381
README.md
View File

@@ -20,11 +20,14 @@ This plugin **requires** the Twilio PHP SDK v8.7.0 to function. The plugin will
```
3. **Configure Twilio Credentials** in WordPress admin:
- Account SID
- Auth Token
- Phone Number
- Go to **Twilio** → **Settings**
- Enter Account SID and Auth Token
- Configure default phone numbers
4. **Test the installation** with a sample call.
4. **Set up Phone Numbers** in Twilio Console:
- Configure webhook URLs for voice and SMS
- Voice: `https://yoursite.com/wp-json/twilio-webhook/v1/voice`
- SMS: `https://yoursite.com/wp-json/twilio-webhook/v1/sms`
## Requirements
@@ -35,100 +38,328 @@ This plugin **requires** the Twilio PHP SDK v8.7.0 to function. The plugin will
## Key Features
- 📞 **Call Center Operations**: Agent groups, queues, call distribution
- 🕒 **Business Hours Management**: Automated routing based on schedules
- 📱 **Outbound Calling**: Click-to-call with proper caller ID
- 💬 **SMS Integration**: Agent notifications and command system
- 🎛️ **Workflow Builder**: Visual call flow creation
- 🎤 **Voicemail System**: Recording, transcription, and notifications
- 📊 **Real-time Dashboard**: Queue management and statistics
### 📞 Call Center Operations
- **Agent Groups**: Organize agents into groups with priority levels
- **Call Queues**: Manage incoming calls with position announcements
- **Smart Routing**: Distribute calls based on availability and schedules
- **SMS Accept**: Agents can text "1" to accept incoming calls
- **Queue Notifications**: SMS alerts to designated numbers when calls enter queues
## Installation Methods
### 🌐 Browser Phone (WebRTC)
- **In-Browser Calling**: Make and receive calls directly from WordPress admin
- **Twilio Voice SDK v2**: Uses latest SDK for WebRTC functionality
- **Visual Dialpad**: Click-to-dial interface with DTMF support
- **Call Controls**: Mute, hold indicators, call timer
- **Auto-Answer**: Optional automatic call acceptance
- **Queue Integration**: Accept calls from specific queues
- **Token Management**: Automatic token refresh for uninterrupted service
### Option 1: Installation Script (Recommended)
```bash
# Run in plugin directory
./install-twilio-sdk.sh
```
### 🕒 Business Hours Management
- **Schedule-based Routing**: Different call flows for business hours vs after-hours
- **Holiday Support**: Define specific dates for holiday routing
- **Multiple Schedules**: Create different schedules for departments
- **After-Hours Actions**: Configurable routing when closed
### Option 2: Composer (For Development)
```bash
composer install
```
### 🎛️ Workflow Builder
- **Visual Interface**: Drag-and-drop workflow creation
- **Step Types**:
- **Greeting**: Welcome messages with multiple voice options
- **IVR Menu**: Interactive voice response with digit collection
- **Call Queue**: Place callers in queue with hold music
- **Forward**: Route calls to specific numbers
- **Voicemail**: Record messages with transcription
- **Schedule Check**: Route based on business hours
- **Voice Options**:
- Default Twilio voice (Say)
- ElevenLabs text-to-speech integration with voice persistence
- Custom audio file URLs
- **Smart Voice Loading**: Saved voices display without API calls
### Option 3: Manual Installation
1. Download Twilio SDK v8.7.0 from GitHub
2. Extract to `vendor/twilio/sdk/`
3. Create autoloader (see install script for reference)
### 📱 SMS Integration
- **Agent Notifications**: Automatic SMS alerts when calls arrive
- **Queue Management**: Agents receive queue status updates
- **Command System**: Text commands to manage availability
- **SMS Logging**: Complete history of all SMS interactions
## Architecture
### 📊 Real-time Dashboard
- **Queue Monitor**: Live view of waiting calls
- **Agent Status**: Track agent availability
- **Call Statistics**: Performance metrics and reporting
- **Call Logs**: Detailed history with filtering options
- **Active Call Display**: Real-time call count monitoring
The plugin uses:
- **Official Twilio PHP SDK v8.7.0** for all API operations
- **Native TwiML classes** for response generation
- **WordPress hooks and filters** for integration
- **Custom database tables** for call management
- **REST API endpoints** for webhooks
### 🎤 Advanced Features
- **Voicemail Transcription**: Automatic speech-to-text
- **Callback System**: Offer callbacks instead of long holds
- **Outbound Calling**: Click-to-call with proper caller ID
- **Multiple Phone Numbers**: Support for multiple business lines
- **Agent Phone Management**: Store and validate agent phone numbers
- **Duplicate Prevention**: Ensures unique phone numbers per agent
## Recent Updates
### Browser Phone Upgrade (v2.0)
- **Migrated to Twilio Voice SDK v2**: Replaced deprecated Client SDK v1.14
- **Improved Stability**: Better error handling and automatic recovery
- **Token Management**: Auto-refresh tokens before expiration
- **Enhanced Performance**: Modern WebRTC implementation
### Queue System Improvements
- **Notification Numbers**: Queues now use notification_number field for SMS alerts
- **No Direct Assignment**: Queues are workflow destinations, not directly assigned to numbers
- **Better Integration**: Improved queue handling in IVR and workflow steps
### Voice Configuration Enhancements
- **Voice Persistence**: ElevenLabs voices save both ID and name
- **No Unnecessary API Calls**: Saved voices display immediately without loading
- **Improved UX**: Load voices only when changing selection
### IVR Fixes
- **Form Field Handling**: Fixed IVR option saving and loading
- **Queue Selection**: Proper queue routing based on digit selection
- **Voice Selection**: Fixed voice dropdown persistence issues
## How It Works
### Call Flow
1. **Incoming Call** → Twilio webhook triggers
2. **Workflow Processing** → System loads assigned workflow
3. **Step Execution** → Each workflow step processes sequentially:
- Greeting plays welcome message
- IVR collects user input
- Schedule check determines routing
- Queue or forward based on configuration
4. **Agent Connection** → Call routed to available agent
5. **Logging** → All interactions logged for reporting
### Queue System
- **Queue Assignment**: Calls routed to queues through workflows
- **Notification Numbers**: Optional SMS alerts to designated numbers (not agents)
- **Agent Groups**: Queues linked to agent groups for distribution
- **Wait Experience**: Configurable hold music and position announcements
- **Timeout Handling**: Automatic callback offers after timeout
- **Browser Phone Integration**: Agents can accept queue calls via browser
### Agent Management
- **Phone Number Storage**: Agent numbers stored in WordPress user profiles
- **Status Tracking**: Available/Busy/Offline states
- **SMS Commands**: Text "1" to accept calls
- **Priority Levels**: Agents have priority within groups
- **Browser Phone Mode**: Option to receive calls in browser or cell phone
## Configuration
1. Install the SDK using the provided script
2. Configure Twilio credentials in WordPress admin
3. Set up phone numbers and webhook URLs
4. Create agent groups and workflows
5. Test with sample calls
### Initial Setup
1. **Install Plugin** and activate in WordPress
2. **Install Twilio SDK** using provided script
3. **Configure Credentials**:
- Navigate to **Twilio** → **Settings**
- Enter Twilio Account SID and Auth Token
- Set default SMS number for notifications
- Configure TwiML App SID for browser phone (optional)
### Phone Number Setup
1. **In Twilio Console**:
- Purchase or select phone number
- Configure Voice webhook: `https://yoursite.com/wp-json/twilio-webhook/v1/voice`
- Configure SMS webhook: `https://yoursite.com/wp-json/twilio-webhook/v1/sms`
- Set method to HTTP POST
2. **In WordPress Admin**:
- Go to **Twilio** → **Phone Numbers**
- Verify numbers are synchronized
- Assign workflows to numbers
### Creating Workflows
1. **Navigate to** Twilio → Workflows
2. **Create New Workflow**:
- Name your workflow
- Select phone number to assign
- Add steps using the builder
3. **Configure Steps**:
- **Greeting**: Set welcome message and voice
- **IVR Menu**: Define options and routing
- **Queue**: Select target queue
- **Schedule**: Choose business hours schedule
### Setting Up Queues
1. **Create Queue** (Twilio → Queues):
- Queue Name: Descriptive name
- Notification Number: SMS alerts for queue activity (optional)
- Agent Group: Select assigned group
- Wait Music: URL for hold music
- Timeout: Maximum wait time
2. **Use in Workflows**:
- Add Queue step to workflow
- Select queue from dropdown
- Configure announcement message
### Browser Phone Setup
1. **Create TwiML App** in Twilio Console:
- Voice Request URL: Your server's TwiML endpoint
- Copy the Application SID
2. **Configure in WordPress**:
- Go to **Twilio** → **Settings**
- Enter TwiML App SID
- Save settings
3. **Access Browser Phone**:
- Navigate to **Twilio** → **Browser Phone**
- Select caller ID from available numbers
- Start making/receiving calls
### Agent Configuration
1. **Create Agent Groups** (Twilio → Agent Groups)
2. **Add Agents** to groups with priorities
3. **Set Phone Numbers** in user profiles
4. **Configure Call Mode**: Browser or cell phone
5. **Train Agents** on SMS commands and browser phone
## Voice Configuration
### ElevenLabs Integration
1. **Get API Key** from ElevenLabs dashboard
2. **Configure in Settings**: Add API key
3. **Select Voices** in workflow steps:
- Click "Load Voices" to fetch available options
- Selected voices are saved with both ID and name
- Voice names persist across edits without API calls
### Audio Options per Step
- **Say**: Default Twilio text-to-speech
- **TTS**: ElevenLabs premium voices with persistence
- **Audio**: Custom MP3 file URLs
## Troubleshooting
### "Twilio SDK classes not available" Error
### Common Issues
1. **Run the installation script**:
```bash
chmod +x install-twilio-sdk.sh
./install-twilio-sdk.sh
```
#### Browser Phone "Client version not supported"
- **Fixed in latest version**: Upgraded to Voice SDK v2
- Clear browser cache and reload page
- Check TwiML App SID is configured
2. **Test SDK installation**:
```bash
php test-sdk.php
```
#### "Twilio SDK classes not available"
```bash
# Reinstall SDK
./install-twilio-sdk.sh
# Test installation
php test-sdk.php
```
3. **Check file permissions**:
```bash
ls -la vendor/
ls -la vendor/twilio/sdk/
```
4. **Verify directory structure**:
```
vendor/
├── autoload.php
└── twilio/
└── sdk/
├── Rest/Client.php
├── TwiML/VoiceResponse.php
└── ... (other SDK files)
```
### Plugin Shows 500 Error
#### Calls Not Routing to Queues
- Verify queue exists and is active
- Check agent group has members
- Ensure agents have valid phone numbers
- Review workflow step configuration
- Check notification_number field (not phone_number)
#### SMS Not Sending from Admin
- Test with direct PHP script: `php test-twilio-direct.php send`
- Verify Twilio credentials in settings
- Check WordPress error logs
- Enable WP_DEBUG in wp-config.php
- Look for TWP Plugin error messages in logs
- Ensure number is SMS-capable in Twilio
### SDK Installation Fails
#### Voice Selections Not Saving
- Voices now save both ID and name automatically
- No API call needed to display saved voices
- Click "Load Voices" only to change selection
- Check browser console for JavaScript errors
- Ensure `curl` and `tar` are installed
- Check internet connection
- Try manual installation (see Installation Methods)
#### IVR Options Not Working
- Ensure only active form fields are enabled
- Check queue selections are properly saved
- Verify digit mappings in workflow data
### Debug Mode
Enable WordPress debugging in `wp-config.php`:
```php
define('WP_DEBUG', true);
define('WP_DEBUG_LOG', true);
define('WP_DEBUG_DISPLAY', false);
```
### Testing Tools
- **Direct SMS Test**: `php test-twilio-direct.php send`
- **SDK Test**: `php test-sdk.php`
- **Webhook Simulator**: Use Twilio Console debugger
- **Call Logs**: Review in WordPress admin
- **Browser Phone**: Test WebRTC connectivity
## Database Structure
The plugin creates these tables:
- `twp_phone_schedules` - Business hours definitions
- `twp_call_queues` - Queue configurations (uses notification_number)
- `twp_queued_calls` - Active calls in queues
- `twp_workflows` - Call flow definitions with voice persistence
- `twp_call_log` - Complete call history
- `twp_sms_log` - SMS message tracking
- `twp_voicemails` - Recordings and transcriptions
- `twp_agent_groups` - Agent group definitions
- `twp_group_members` - User-to-group relationships
- `twp_agent_status` - Real-time agent availability
- `twp_callbacks` - Callback request queue
## Webhook Endpoints
All webhooks are REST API endpoints under `/wp-json/twilio-webhook/v1/`:
- `/voice` - Main incoming call handler
- `/sms` - SMS message handler
- `/ivr-response` - IVR digit collection (fixed in latest)
- `/queue-wait` - Queue hold experience
- `/agent-connect` - Agent connection handler
- `/callback-request` - Callback system
- `/outbound-agent-with-from` - Outbound calling
## Technical Details
### Dependencies
- **Twilio PHP SDK v8.7.0** - Server-side API operations
- **Twilio Voice SDK v2** - Browser phone WebRTC
- **WordPress REST API** - Webhook handling
- **jQuery** - Admin interface interactions
### Browser Compatibility
- **Chrome/Edge**: Full support
- **Firefox**: Full support
- **Safari**: Requires HTTPS for WebRTC
- **Mobile Browsers**: Limited WebRTC support
### Security Considerations
- All webhooks use WordPress nonce verification
- Phone numbers validated and sanitized
- SQL queries use prepared statements
- Sensitive data encrypted in database
- HTTPS required for production use
## Version History
### v2.0.0 (Current)
- Upgraded to Twilio Voice SDK v2 for browser phone
- Fixed queue notification_number field naming
- Enhanced voice selection persistence
- Fixed IVR option saving and loading
- Improved error handling and logging
- Added automatic token refresh
### v1.3.x
- Initial release with full call center features
- Browser phone with Client SDK v1.14
- Basic workflow builder
- Queue management system
## Support
- Check `CLAUDE.md` for detailed technical documentation
- Review `TWILIO_SDK_MIGRATION.md` for migration details
- Enable WordPress debug logging for troubleshooting
- Use Twilio Console debugger for webhook testing
- Review error logs in `/wp-content/debug.log`
- Monitor Twilio Console for webhook errors
- Test components individually using provided scripts
- Report issues with specific error messages and logs
## License
This plugin integrates with Twilio services and requires a Twilio account.
This plugin integrates with Twilio services and requires a Twilio account.

View File

@@ -19,132 +19,175 @@ class TWP_Admin {
* Register admin menu
*/
public function add_plugin_admin_menu() {
add_menu_page(
'Twilio WP Plugin',
'Twilio Phone',
'manage_options',
'twilio-wp-plugin',
array($this, 'display_plugin_dashboard'),
'dashicons-phone',
30
);
// Determine if user has any agent access
$has_agent_access = current_user_can('twp_access_voicemails') ||
current_user_can('twp_access_call_log') ||
current_user_can('twp_access_agent_queue') ||
current_user_can('twp_access_sms_inbox') ||
current_user_can('twp_access_browser_phone');
add_submenu_page(
'twilio-wp-plugin',
'Dashboard',
'Dashboard',
'manage_options',
'twilio-wp-plugin',
array($this, 'display_plugin_dashboard')
);
// Only show menu if user is admin or has agent access
if (!current_user_can('manage_options') && !$has_agent_access) {
return;
}
add_submenu_page(
'twilio-wp-plugin',
'Settings',
'Settings',
'manage_options',
'twilio-wp-settings',
array($this, 'display_plugin_settings')
);
// Main menu - show dashboard for admins, redirect to first available page for agents
if (current_user_can('manage_options')) {
add_menu_page(
'Twilio WP Plugin',
'Twilio Phone',
'manage_options',
'twilio-wp-plugin',
array($this, 'display_plugin_dashboard'),
'dashicons-phone',
30
);
add_submenu_page(
'twilio-wp-plugin',
'Dashboard',
'Dashboard',
'manage_options',
'twilio-wp-plugin',
array($this, 'display_plugin_dashboard')
);
} else {
// For agents, determine first available page
$first_page = 'twilio-wp-browser-phone'; // Default to browser phone
if (current_user_can('twp_access_voicemails')) $first_page = 'twilio-wp-voicemails';
elseif (current_user_can('twp_access_call_log')) $first_page = 'twilio-wp-call-logs';
elseif (current_user_can('twp_access_agent_queue')) $first_page = 'twilio-wp-agent-queue';
elseif (current_user_can('twp_access_sms_inbox')) $first_page = 'twilio-wp-sms-inbox';
elseif (current_user_can('twp_access_browser_phone')) $first_page = 'twilio-wp-browser-phone';
add_menu_page(
'Twilio Phone',
'Twilio Phone',
'read',
$first_page,
null,
'dashicons-phone',
30
);
}
add_submenu_page(
'twilio-wp-plugin',
'Phone Schedules',
'Schedules',
'manage_options',
'twilio-wp-schedules',
array($this, 'display_schedules_page')
);
// Admin-only pages
if (current_user_can('manage_options')) {
add_submenu_page(
'twilio-wp-plugin',
'Settings',
'Settings',
'manage_options',
'twilio-wp-settings',
array($this, 'display_plugin_settings')
);
add_submenu_page(
'twilio-wp-plugin',
'Phone Schedules',
'Schedules',
'manage_options',
'twilio-wp-schedules',
array($this, 'display_schedules_page')
);
add_submenu_page(
'twilio-wp-plugin',
'Workflows',
'Workflows',
'manage_options',
'twilio-wp-workflows',
array($this, 'display_workflows_page')
);
add_submenu_page(
'twilio-wp-plugin',
'Call Queues',
'Queues',
'manage_options',
'twilio-wp-queues',
array($this, 'display_queues_page')
);
add_submenu_page(
'twilio-wp-plugin',
'Phone Numbers',
'Phone Numbers',
'manage_options',
'twilio-wp-numbers',
array($this, 'display_numbers_page')
);
add_submenu_page(
'twilio-wp-plugin',
'Agent Groups',
'Agent Groups',
'manage_options',
'twilio-wp-groups',
array($this, 'display_groups_page')
);
}
add_submenu_page(
'twilio-wp-plugin',
'Workflows',
'Workflows',
'manage_options',
'twilio-wp-workflows',
array($this, 'display_workflows_page')
);
// Agent-accessible pages
$menu_parent = current_user_can('manage_options') ? 'twilio-wp-plugin' : null;
add_submenu_page(
'twilio-wp-plugin',
'Call Queues',
'Queues',
'manage_options',
'twilio-wp-queues',
array($this, 'display_queues_page')
);
if (current_user_can('manage_options') || current_user_can('twp_access_voicemails')) {
add_submenu_page(
$menu_parent,
'Voicemails',
'Voicemails',
current_user_can('manage_options') ? 'manage_options' : 'twp_access_voicemails',
'twilio-wp-voicemails',
array($this, 'display_voicemails_page')
);
}
add_submenu_page(
'twilio-wp-plugin',
'Phone Numbers',
'Phone Numbers',
'manage_options',
'twilio-wp-numbers',
array($this, 'display_numbers_page')
);
if (current_user_can('manage_options') || current_user_can('twp_access_call_log')) {
add_submenu_page(
$menu_parent,
'Call Logs',
'Call Logs',
current_user_can('manage_options') ? 'manage_options' : 'twp_access_call_log',
'twilio-wp-call-logs',
array($this, 'display_call_logs_page')
);
}
add_submenu_page(
'twilio-wp-plugin',
'Voicemails',
'Voicemails',
'manage_options',
'twilio-wp-voicemails',
array($this, 'display_voicemails_page')
);
if (current_user_can('manage_options') || current_user_can('twp_access_agent_queue')) {
add_submenu_page(
$menu_parent,
'Agent Queue',
'Agent Queue',
current_user_can('manage_options') ? 'manage_options' : 'twp_access_agent_queue',
'twilio-wp-agent-queue',
array($this, 'display_agent_queue_page')
);
}
add_submenu_page(
'twilio-wp-plugin',
'Call Logs',
'Call Logs',
'manage_options',
'twilio-wp-call-logs',
array($this, 'display_call_logs_page')
);
// Outbound Calls page removed - functionality merged into Browser Phone
// Keeping capability 'twp_access_outbound_calls' for backwards compatibility
add_submenu_page(
'twilio-wp-plugin',
'Agent Groups',
'Agent Groups',
'manage_options',
'twilio-wp-groups',
array($this, 'display_groups_page')
);
if (current_user_can('manage_options') || current_user_can('twp_access_sms_inbox')) {
add_submenu_page(
$menu_parent,
'SMS Inbox',
'SMS Inbox',
current_user_can('manage_options') ? 'manage_options' : 'twp_access_sms_inbox',
'twilio-wp-sms-inbox',
array($this, 'display_sms_inbox_page')
);
}
add_submenu_page(
'twilio-wp-plugin',
'Agent Queue',
'Agent Queue',
'manage_options',
'twilio-wp-agent-queue',
array($this, 'display_agent_queue_page')
);
add_submenu_page(
'twilio-wp-plugin',
'Outbound Calls',
'Outbound Calls',
'manage_options',
'twilio-wp-outbound',
array($this, 'display_outbound_calls_page')
);
add_submenu_page(
'twilio-wp-plugin',
'SMS Inbox',
'SMS Inbox',
'manage_options',
'twilio-wp-sms-inbox',
array($this, 'display_sms_inbox_page')
);
add_submenu_page(
'twilio-wp-plugin',
'Browser Phone',
'Browser Phone',
'manage_options',
'twilio-wp-browser-phone',
array($this, 'display_browser_phone_page')
);
if (current_user_can('manage_options') || current_user_can('twp_access_browser_phone')) {
add_submenu_page(
$menu_parent,
'Browser Phone',
'Browser Phone',
current_user_can('manage_options') ? 'manage_options' : 'twp_access_browser_phone',
'twilio-wp-browser-phone',
array($this, 'display_browser_phone_page')
);
}
}
/**
@@ -5448,105 +5491,185 @@ class TWP_Admin {
}
</style>
<script src="https://sdk.twilio.com/js/client/v1.14/twilio.min.js"></script>
<!-- Twilio Voice SDK v2 from unpkg CDN -->
<script src="https://unpkg.com/@twilio/voice-sdk@2.11.0/dist/twilio.min.js"></script>
<script>
jQuery(document).ready(function($) {
var device = null;
var currentConnection = null;
var currentCall = null;
var callTimer = null;
var callStartTime = null;
// Wait for SDK to load
function waitForTwilioSDK(callback) {
if (typeof Twilio !== 'undefined' && Twilio.Device) {
callback();
} else {
console.log('Waiting for Twilio Voice SDK to load...');
setTimeout(function() {
waitForTwilioSDK(callback);
}, 100);
}
}
// Initialize the browser phone
function initializeBrowserPhone() {
$('#phone-status').text('Initializing...');
// Get capability token
$.post(ajaxurl, {
action: 'twp_generate_capability_token',
nonce: '<?php echo wp_create_nonce('twp_ajax_nonce'); ?>'
}, function(response) {
if (response.success) {
$('#browser-phone-error').hide();
setupTwilioDevice(response.data.token);
} else {
showError('Failed to initialize: ' + response.error);
}
}).fail(function() {
showError('Failed to connect to server');
// Wait for SDK before proceeding
waitForTwilioSDK(function() {
// Get capability token (access token for v2)
$.post(ajaxurl, {
action: 'twp_generate_capability_token',
nonce: '<?php echo wp_create_nonce('twp_ajax_nonce'); ?>'
}, function(response) {
if (response.success) {
$('#browser-phone-error').hide();
setupTwilioDevice(response.data.token);
} else {
showError('Failed to initialize: ' + response.error);
}
}).fail(function() {
showError('Failed to connect to server');
});
});
}
function setupTwilioDevice(token) {
async function setupTwilioDevice(token) {
try {
// Setup Twilio Device
Twilio.Device.setup(token, {
debug: true,
codecPreferences: ['opus', 'pcmu']
// Check if Twilio SDK is available
if (typeof Twilio === 'undefined' || !Twilio.Device) {
throw new Error('Twilio Voice SDK not loaded');
}
// Clean up existing device if any
if (device) {
await device.destroy();
}
// Setup Twilio Voice SDK v2 Device
// Note: Voice SDK v2 uses Twilio.Device directly, not Twilio.Voice.Device
device = new Twilio.Device(token, {
logLevel: 1, // 0 = TRACE, 1 = DEBUG
codecPreferences: ['opus', 'pcmu'],
edge: 'sydney' // Or closest edge location
});
// Use modern EventEmitter interface instead of deprecated callbacks
Twilio.Device.on('ready', function(device) {
// Set up event handlers BEFORE registering
// Device registered and ready
device.on('registered', function() {
console.log('Device registered successfully');
$('#phone-status').text('Ready').css('color', '#4CAF50');
$('#call-btn').prop('disabled', false);
});
Twilio.Device.on('error', function(error) {
// Handle errors
device.on('error', function(error) {
console.error('Twilio Device Error:', error);
var errorMsg = error.message;
var errorMsg = error.message || error.toString();
// Provide specific help for common errors
if (error.message.includes('valid callerId must be provided')) {
if (errorMsg.includes('valid callerId must be provided')) {
errorMsg = 'Caller ID error: Make sure you select a verified Twilio phone number as Caller ID. The number must be purchased through your Twilio account.';
} else if (error.message.includes('TwiML App')) {
} else if (errorMsg.includes('TwiML App')) {
errorMsg = 'TwiML App error: Check that your TwiML App SID is correctly configured in Settings.';
} else if (error.message.includes('token')) {
errorMsg = 'Token error: ' + error.message + ' - The page will automatically try to refresh the token.';
} else if (errorMsg.includes('token') || errorMsg.includes('Token')) {
errorMsg = 'Token error: ' + errorMsg + ' - The page will automatically try to refresh the token.';
// Try to reinitialize after token error
setTimeout(initializeBrowserPhone, 5000);
}
showError(errorMsg);
});
Twilio.Device.on('connect', function(conn) {
currentConnection = conn;
$('#phone-status').text('Connected').css('color', '#2196F3');
$('#call-btn').hide();
$('#hangup-btn').show();
$('#phone-controls-extra').show();
startCallTimer();
});
Twilio.Device.on('disconnect', function(conn) {
currentConnection = null;
$('#phone-status').text('Ready').css('color', '#4CAF50');
$('#hangup-btn').hide();
$('#answer-btn').hide();
$('#call-btn').show();
$('#phone-controls-extra').hide();
$('#call-timer').hide();
stopCallTimer();
});
Twilio.Device.on('incoming', function(conn) {
currentConnection = conn;
// Handle incoming calls
device.on('incoming', function(call) {
currentCall = call;
$('#phone-status').text('Incoming Call').css('color', '#FF9800');
$('#phone-number-display').text(conn.parameters.From || 'Unknown Number');
$('#phone-number-display').text(call.parameters.From || 'Unknown Number');
$('#call-btn').hide();
$('#answer-btn').show();
// Setup call event handlers
setupCallHandlers(call);
if ($('#auto-answer').is(':checked')) {
conn.accept();
call.accept();
}
});
// Token about to expire
device.on('tokenWillExpire', function() {
console.log('Token will expire soon, refreshing...');
refreshToken();
});
// Register device AFTER setting up event handlers
await device.register();
} catch (error) {
console.error('Error setting up Twilio Device:', error);
showError('Failed to setup device: ' + error.message);
}
}
function setupCallHandlers(call) {
// Call accepted/connected
call.on('accept', function() {
$('#phone-status').text('Connected').css('color', '#2196F3');
$('#call-btn').hide();
$('#answer-btn').hide();
$('#hangup-btn').show();
$('#phone-controls-extra').show();
startCallTimer();
});
// Call disconnected
call.on('disconnect', function() {
currentCall = null;
$('#phone-status').text('Ready').css('color', '#4CAF50');
$('#hangup-btn').hide();
$('#answer-btn').hide();
$('#call-btn').show();
$('#phone-controls-extra').hide();
$('#call-timer').hide();
stopCallTimer();
});
// Call rejected
call.on('reject', function() {
currentCall = null;
$('#phone-status').text('Ready').css('color', '#4CAF50');
$('#answer-btn').hide();
$('#call-btn').show();
});
// Call cancelled (by caller before answer)
call.on('cancel', function() {
currentCall = null;
$('#phone-status').text('Missed Call').css('color', '#FF9800');
$('#answer-btn').hide();
$('#call-btn').show();
setTimeout(function() {
$('#phone-status').text('Ready').css('color', '#4CAF50');
}, 3000);
});
}
function refreshToken() {
$.post(ajaxurl, {
action: 'twp_generate_capability_token',
nonce: '<?php echo wp_create_nonce('twp_ajax_nonce'); ?>'
}, function(response) {
if (response.success && device) {
device.updateToken(response.data.token);
}
}).fail(function() {
console.error('Failed to refresh token');
});
}
function showError(message) {
$('#browser-phone-error').html('<p><strong>Error:</strong> ' + message + '</p>').show();
$('#phone-status').text('Error').css('color', '#f44336');
@@ -5597,7 +5720,7 @@ class TWP_Admin {
});
// Call button
$('#call-btn').on('click', function() {
$('#call-btn').on('click', async function() {
var phoneNumber = $('#phone-number-input').val().trim();
var callerId = $('#caller-id-select').val();
@@ -5611,6 +5734,11 @@ class TWP_Admin {
return;
}
if (!device) {
alert('Phone is not initialized. Please refresh the page.');
return;
}
// Format phone number
phoneNumber = phoneNumber.replace(/\D/g, '');
if (phoneNumber.length === 10) {
@@ -5631,7 +5759,8 @@ class TWP_Admin {
};
console.log('Making call with params:', params);
currentConnection = Twilio.Device.connect(params);
currentCall = await device.connect({params: params});
setupCallHandlers(currentCall);
} catch (error) {
console.error('Call error:', error);
showError('Failed to make call: ' + error.message);
@@ -5641,30 +5770,40 @@ class TWP_Admin {
// Hangup button
$('#hangup-btn').on('click', function() {
if (currentConnection) {
currentConnection.disconnect();
if (currentCall) {
currentCall.disconnect();
}
});
// Answer button
$('#answer-btn').on('click', function() {
if (currentConnection) {
currentConnection.accept();
if (currentCall) {
currentCall.accept();
}
});
// Mute button
$('#mute-btn').on('click', function() {
if (currentConnection) {
var muted = currentConnection.isMuted();
currentConnection.mute(!muted);
if (currentCall) {
var muted = currentCall.isMuted();
currentCall.mute(!muted);
$(this).text(muted ? 'Mute' : 'Unmute');
$(this).find('.dashicons').toggleClass('dashicons-microphone dashicons-microphone');
}
});
// Initialize on page load
initializeBrowserPhone();
// Check if SDK loaded and initialize
$(window).on('load', function() {
setTimeout(function() {
if (typeof Twilio === 'undefined') {
showError('Twilio Voice SDK failed to load. Please check your internet connection and try refreshing the page.');
console.error('Twilio SDK not found. Script may be blocked or failed to load.');
} else {
console.log('Twilio SDK loaded successfully');
initializeBrowserPhone();
}
}, 1000);
});
// Refresh token every 50 minutes (tokens expire in 1 hour)
setInterval(initializeBrowserPhone, 50 * 60 * 1000);

View File

@@ -14,6 +14,9 @@ class TWP_Activator {
// Set default options
self::set_default_options();
// Create custom user roles
self::create_user_roles();
// Set the database version
if (defined('TWP_DB_VERSION')) {
update_option('twp_db_version', TWP_DB_VERSION);
@@ -373,4 +376,29 @@ class TWP_Activator {
add_option('twp_sms_notification_number', '');
add_option('twp_default_sms_number', '');
}
/**
* Create custom user roles for the plugin
*/
private static function create_user_roles() {
// Remove role first if it exists to ensure clean setup
remove_role('phone_agent');
// Add Phone Agent role with limited capabilities
add_role('phone_agent', 'Phone Agent', array(
// Basic WordPress capabilities
'read' => true,
// Profile management
'edit_profile' => true,
// Phone agent specific capabilities
'twp_access_voicemails' => true,
'twp_access_call_log' => true,
'twp_access_agent_queue' => true,
'twp_access_outbound_calls' => true,
'twp_access_sms_inbox' => true,
'twp_access_browser_phone' => true,
));
}
}