如何在Laravel中集成Plivo SDK实现网页端点击通话功能?
如何在Laravel中集成Plivo SDK实现网页端点击通话功能?
我正在Laravel中集成Plivo,想在网页端实现「点击通话」功能,需要支持呼叫、挂断、静音、取消静音这些操作,还要让用户能直接通过浏览器和对方通话。但现在遇到了报错:"Failed to load Plivo SDK: Plivo SDK failed to load",以下是我编写的代码:

show.blade.php
@extends('layouts.app') @section('title', "Contact: {$contact->first_name} {$contact->last_name}") @section('styles') <script type="text/javascript" src="https://cdn.plivo.com/sdk/browser/v2/plivo.min.js"> </script> <style> .call-interface { padding: 20px; border: 1px solid #ddd; border-radius: 8px; margin-bottom: 20px; } .call-status { font-size: 18px; margin-bottom: 15px; } .call-controls button { margin-right: 10px; margin-bottom: 10px; } .call-timer { font-size: 24px; font-weight: bold; margin: 15px 0; } .call-logs { margin-top: 30px; } </style> @endsection @section('content') <div class="col-md-4"> <div class="card mb-3"> <div class="card-header"> <h5 class="card-title mb-0"> Contact Details </h5> </div> <div class="card-body"> <div class="mb-1"> <strong>Name:</strong> {{ $contact->first_name }} {{ $contact->last_name }} </div> <div class="mb-1"> <strong>Phone:</strong> {{ $contact->phone }} </div> </div> <div class="card-footer"> <div class="row g-3 align-items-center"> <div class="col-12"> <label for="note" class="form-label">Note</label> <textarea name="note" class="form-control" id="note" rows="3">{!! $disposition ? $disposition->note : '' !!}</textarea> </div> <div class="col-auto"> <select name="disposition" class="form-select" id="disposition"> <option value="">Select disposition</option> @foreach (config('data.disposition_status') as $key => $item) <option value="{{ $key }}" {{ $disposition && $disposition->status === $key ? 'selected' : '' }}>{{ $item }}</option> @endforeach </select> </div> <div class="col-auto"> <button onclick="makeCall('{{ $contact->phone }}')" class="btn btn-dark">Call</button> </div> </div> </div> </div> </div> <div class="col-md-8"> <div class="card"> <div class="card-header"> <h3>Call Interface</h3> </div> <div class="card-body"> <div class="call-interface"> <div id="call-status" class="call-status alert alert-info"> Ready </div> <div class="call-timer" id="call-timer"> 00:00:00 </div> <div class="call-controls"> <button id="makeCall" class="btn btn-success" disabled> <i class="fas fa-phone"></i> Call </button> <button id="hangupCall" class="btn btn-danger" disabled> <i class="fas fa-phone-slash"></i> Hangup </button> <button id="muteCall" class="btn btn-warning" disabled> <i class="fas fa-microphone-slash"></i> Mute </button> <button id="unmuteCall" class="btn btn-info" disabled> <i class="fas fa-microphone"></i> Unmute </button> </div> </div> </div> </div> </div> @endsection @push('scripts') <script> let client; let currentCall = null; let callTimer = null; let callStartTime = null; async function initializePlivoClient() { try { console.log('Initializing Plivo client...'); if (typeof window.plivoBrowserSdk === 'undefined') { throw new Error('Plivo Browser SDK not loaded'); } const response = await fetch('{{ route("plivo.token") }}'); const data = await response.json(); if (data.error) { throw new Error(data.error); } console.log('Token received, initializing client...'); try { const options = { debug: "DEBUG", permOnClick: true, enableTracking: true, audioConstraints: { optional: [ { echoCancellation: true }, { noiseSuppression: true } ] } }; // Create client using the correct SDK reference client = new window.plivoBrowserSdk.Client(options); console.log('Client created, attempting login...'); // Login await client.login(data.username, data.password); console.log('Login successful'); document.getElementById('makeCall').disabled = false; document.getElementById('call-status').innerHTML = 'Ready to call'; document.getElementById('call-status').className = 'alert alert-success'; setupEventListeners(); } catch (error) { throw new Error(`Client initialization failed: ${error.message}`); } } catch (error) { console.error('Failed to initialize Plivo client:', error); document.getElementById('call-status').innerHTML = 'Failed to initialize phone: ' + error.message; document.getElementById('call-status').className = 'alert alert-danger'; } } // Wait for SDK to load function waitForPlivoSDK() { return new Promise((resolve, reject) => { let attempts = 0; const maxAttempts = 20; const checkSDK = setInterval(() => { if (typeof window.plivoBrowserSdk !== 'undefined') { clearInterval(checkSDK); resolve(); } else { attempts++; if (attempts >= maxAttempts) { clearInterval(checkSDK); reject(new Error('Plivo SDK failed to load')); } } }, 250); }); } // Initialize when document is ready document.addEventListener('DOMContentLoaded', async () => { try { await waitForPlivoSDK(); await initializePlivoClient(); } catch (error) { console.error('Initialization failed:', error); document.getElementById('call-status').innerHTML = 'Failed to load Plivo SDK: ' + error.message; document.getElementById('call-status').className = 'alert alert-danger'; } }); function setupEventListeners() { if (!client) { console.error('Client not initialized'); return; } client.on('onLogin', () => { console.log('Successfully logged in to Plivo'); document.getElementById('call-status').innerHTML = 'Ready to make calls'; document.getElementById('call-status').className = 'alert alert-success'; }); client.on('onLoginFailed', (error) => { console.error('Login failed:', error); }); client.on('onCallRemoteRinging', () => { document.getElementById('call-status').innerHTML = 'Ringing...'; document.getElementById('call-status').className = 'alert alert-warning'; }); client.on('onCallAnswered', () => { document.getElementById('call-status').innerHTML = 'Call in progress'; document.getElementById('call-status').className = 'alert alert-success'; document.getElementById('hangupCall').disabled = false; document.getElementById('muteCall').disabled = false; startCallTimer(); }); client.on('onCallTerminated', (reason) => { document.getElementById('call-status').innerHTML = `Call ended: ${reason}`; document.getElementById('call-status').className = 'alert alert-info'; document.getElementById('hangupCall').disabled = true; document.getElementById('muteCall').disabled = true; document.getElementById('unmuteCall').disabled = true; document.getElementById('makeCall').disabled = false; stopCallTimer(); currentCall = null; }); client.on('onMuteChanged', (isMuted) => { if (isMuted) { document.getElementById('muteCall').disabled = true; document.getElementById('unmuteCall').disabled = false; } else { document.getElementById('muteCall').disabled = false; document.getElementById('unmuteCall').disabled = true; } }); } async function makeCall(phoneNumber) { if (!client) { alert('Plivo client not initialized'); return; } try { currentCall = await client.call(phoneNumber, { from: '{{ auth()->user()->phone }}', answerOnBridge: true, ringtone: 'default' }); document.getElementById('makeCall').disabled = true; document.getElementById('call-status').innerHTML = 'Calling...'; document.getElementById('call-status').className = 'alert alert-warning'; } catch (error) { console.error('Failed to make call:', error); document.getElementById('call-status').innerHTML = `Call failed: ${error.message}`; document.getElementById('call-status').className = 'alert alert-danger'; document.getElementById('makeCall').disabled = false; } } function hangupCall() { if (currentCall) { currentCall.hangup(); } } function muteCall() { if (currentCall) { currentCall.mute(true); } } function unmuteCall() { if (currentCall) { currentCall.mute(false); } } function startCallTimer() { callStartTime = Date.now(); callTimer = setInterval(() => { const elapsed = Math.floor((Date.now() - callStartTime) / 1000); const hours = Math.floor(elapsed / 3600).toString().padStart(2, '0'); const minutes = Math.floor((elapsed % 3600) / 60).toString().padStart(2, '0'); const seconds = (elapsed % 60).toString().padStart(2, '0'); document.getElementById('call-timer').innerHTML = `${hours}:${minutes}:${seconds}`; }, 1000); } function stopCallTimer() { if (callTimer) { clearInterval(callTimer); callTimer = null; } } </script> @endpush
备注:内容来源于stack exchange,提问作者Hilmi
相关产品推荐
相关产品推荐

