diff --git a/admin/class-twp-admin.php b/admin/class-twp-admin.php
index 2218722..6999247 100644
--- a/admin/class-twp-admin.php
+++ b/admin/class-twp-admin.php
@@ -2217,8 +2217,9 @@ class TWP_Admin {
html += '
' + formatDuration(recording.duration) + ' | ';
html += '';
if (recording.has_recording) {
- html += ' ';
- html += 'Download';
+ var proxyUrl = '' + recording.id;
+ html += ' ';
+ html += 'Download';
html += ' ';
@@ -7415,11 +7416,24 @@ class TWP_Admin {
global $wpdb;
$recordings_table = $wpdb->prefix . 'twp_call_recordings';
+ // For outbound calls from browser phone, swap the numbers for better display
+ $from_number = $call->from;
+ $to_number = $call->to;
+
+ // If this is a browser phone call (from contains 'client:'), then the customer is the 'to' number
+ if (strpos($call->from, 'client:') === 0) {
+ // This is an outbound call from browser phone
+ // Store the customer number as 'from' for display consistency
+ $from_number = $call->to; // Customer number
+ $to_number = $call->from; // Browser phone client
+ error_log("TWP: Outbound browser call - Customer: {$call->to}, Agent: {$call->from}");
+ }
+
$insert_result = $wpdb->insert($recordings_table, [
'call_sid' => $call_sid,
'recording_sid' => $recording->sid,
- 'from_number' => $call->from,
- 'to_number' => $call->to,
+ 'from_number' => $from_number,
+ 'to_number' => $to_number,
'agent_id' => $user_id,
'status' => 'recording',
'started_at' => current_time('mysql')
diff --git a/includes/class-twp-webhooks.php b/includes/class-twp-webhooks.php
index 5dd2bad..7090602 100644
--- a/includes/class-twp-webhooks.php
+++ b/includes/class-twp-webhooks.php
@@ -159,6 +159,23 @@ class TWP_Webhooks {
),
));
+ // Call recording audio proxy endpoint
+ register_rest_route('twilio-webhook/v1', '/recording-audio/(?P\d+)', array(
+ 'methods' => 'GET',
+ 'callback' => array($this, 'proxy_recording_audio'),
+ 'permission_callback' => function() {
+ // Check if user is logged in with proper permissions
+ return is_user_logged_in() && current_user_can('manage_options');
+ },
+ 'args' => array(
+ 'id' => array(
+ 'validate_callback' => function($param, $request, $key) {
+ return is_numeric($param);
+ }
+ ),
+ ),
+ ));
+
// Transcription webhook
register_rest_route('twilio-webhook/v1', '/transcription', array(
'methods' => 'POST',
@@ -1175,6 +1192,60 @@ class TWP_Webhooks {
exit;
}
+ /**
+ * Proxy call recording audio through WordPress
+ */
+ public function proxy_recording_audio($request) {
+ // Permission already checked by REST API permission_callback
+ $recording_id = intval($request->get_param('id'));
+
+ global $wpdb;
+ $table_name = $wpdb->prefix . 'twp_call_recordings';
+
+ $recording = $wpdb->get_row($wpdb->prepare(
+ "SELECT recording_url FROM $table_name WHERE id = %d",
+ $recording_id
+ ));
+
+ if (!$recording || !$recording->recording_url) {
+ header('HTTP/1.0 404 Not Found');
+ exit('Recording not found');
+ }
+
+ // Fetch the audio from Twilio using authenticated request
+ $twilio = new TWP_Twilio_API();
+ $account_sid = get_option('twp_twilio_account_sid');
+ $auth_token = get_option('twp_twilio_auth_token');
+
+ // Add .mp3 to the URL if not present
+ $audio_url = $recording->recording_url;
+ if (strpos($audio_url, '.mp3') === false && strpos($audio_url, '.wav') === false) {
+ $audio_url .= '.mp3';
+ }
+
+ // Fetch audio with authentication
+ $response = wp_remote_get($audio_url, array(
+ 'headers' => array(
+ 'Authorization' => 'Basic ' . base64_encode($account_sid . ':' . $auth_token)
+ ),
+ 'timeout' => 30
+ ));
+
+ if (is_wp_error($response)) {
+ return new WP_Error('fetch_error', 'Unable to fetch recording', array('status' => 500));
+ }
+
+ $body = wp_remote_retrieve_body($response);
+ $content_type = wp_remote_retrieve_header($response, 'content-type') ?: 'audio/mpeg';
+
+ // Return audio with proper headers
+ header('Content-Type: ' . $content_type);
+ header('Content-Length: ' . strlen($body));
+ header('Cache-Control: private, max-age=3600');
+ echo $body;
+ exit;
+ }
+
/**
* Handle voicemail callback
*/
|