You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

基于PHP/Laravel与Nexmo Voice API实现双向私密语音通话技术咨询

Implementing Anonymous Two-Way Voice Calls with Vonage (Nexmo) in Laravel/PHP

I get it—you’ve got the TTS one-way call working, but now you need that anonymous two-way bridge for your ride-hailing/food delivery platform where neither the user nor the driver sees each other’s real numbers. Let’s walk through how to make this happen, including clearing up those web-side questions.

Core Concept: Anonymous Call Bridging with NCCOs

Unlike your TTS setup, two-way anonymous calls rely on Vonage’s Call Control Objects (NCCO). Here’s the flow:

  1. When your user clicks the call button, your Laravel backend tells Vonage to initiate a call to the user’s phone (or their browser via the Vonage Client SDK).
  2. Once the user answers, Vonage automatically dials the driver’s number using your purchased Nexmo/Vonage number as the "from" ID for both parties.
  3. The two calls are bridged—both sides only see your Vonage number, not each other’s real digits.

Web端 Requirements

Yes, your web users will need a headset (or speakers + microphone) to participate. Browsers require media permissions (microphone and audio output) to handle voice calls, so your frontend will need to prompt the user for access. We’ll cover a basic frontend snippet later.

Step-by-Step Implementation in Laravel

1. Set Up the Vonage Laravel Package

First, ditch the raw CURL and use the official Laravel integration—it’s way cleaner:

composer require vonage/vonage-laravel

Then add your credentials to .env:

VONAGE_KEY=your_api_key
VONAGE_SECRET=your_api_secret
VONAGE_NUMBER=your_purchased_nexmo_number # e.g., 16169281703

2. Backend: Initiate the Anonymous Call

Create a controller method to handle the call request (e.g., CallController@initiateAnonymousCall). This will generate the NCCO and trigger the call via Vonage’s Voice API.

<?php

namespace App\Http\Controllers;

use Vonage\Client;
use Vonage\Voice\NCCO\Action\Connect;
use Vonage\Voice\NCCO\NCCO;
use Vonage\Voice\OutboundCall;
use Illuminate\Http\Request;

class CallController extends Controller
{
    public function initiateAnonymousCall(Request $request)
    {
        // Validate incoming request (user phone, driver phone)
        $request->validate([
            'user_phone' => 'required|string', // e.g., +14083934444 (use E.164 format)
            'driver_phone' => 'required|string' // e.g., +15551234567
        ]);

        $vonage = app(Client::class);

        // Build the NCCO to bridge the two calls
        $ncco = new NCCO();
        
        // First, connect to the user (show your Vonage number as caller ID)
        $userConnect = new Connect();
        $userConnect->setTo($request->user_phone);
        $userConnect->setFrom(env('VONAGE_NUMBER'));
        
        // Once user answers, connect to the driver (again, use your Vonage number as caller ID)
        $driverConnect = new Connect();
        $driverConnect->setTo($request->driver_phone);
        $driverConnect->setFrom(env('VONAGE_NUMBER'));

        $ncco->addAction($userConnect);
        $ncco->addAction($driverConnect);

        // Initiate the outbound call to the user first
        $call = new OutboundCall(
            $request->user_phone,
            env('VONAGE_NUMBER')
        );
        $call->setNCCO($ncco);

        $response = $vonage->voice()->createOutboundCall($call);

        // Optionally, save call ID to your database for tracking
        // DB::table('calls')->insert([
        //     'call_id' => $response['uuid'],
        //     'user_phone' => $request->user_phone,
        //     'driver_phone' => $request->driver_phone,
        //     'created_at' => now()
        // ]);

        return response()->json([
            'success' => true,
            'call_id' => $response['uuid']
        ]);
    }
}

3. Handle Webhooks (Call Status Updates)

Vonage will send webhook events (like call started, answered, ended) to a URL you specify. Create a webhook controller to log these events:

<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;

class VonageWebhookController extends Controller
{
    public function callStatus(Request $request)
    {
        // Log call status to your database for auditing
        DB::table('call_logs')->insert([
            'call_id' => $request->input('uuid'),
            'status' => $request->input('status'),
            'from' => $request->input('from'),
            'to' => $request->input('to'),
            'timestamp' => now()
        ]);

        return response('', 200); // Vonage expects a 200 OK response to confirm receipt
    }
}

Add the route in routes/api.php:

Route::post('/vonage/webhook/call-status', [VonageWebhookController::class, 'callStatus']);

Then configure this webhook URL in your Vonage dashboard under Voice > Applications > Your App > Webhooks.

4. Frontend: Trigger the Call (Web User)

If your user is initiating the call from the browser (instead of a phone), use the Vonage Client SDK to handle in-browser audio. Here’s a basic example:

<button id="callDriverBtn">Call Driver</button>

<script src="https://cdn.jsdelivr.net/npm/@vonage/client@latest/dist/vonageClient.min.js"></script>
<script>
const callDriverBtn = document.getElementById('callDriverBtn');

callDriverBtn.addEventListener('click', async () => {
    try {
        // Request microphone/audio permissions first
        await navigator.mediaDevices.getUserMedia({ audio: true });

        // Fetch session ID and token from your Laravel backend (generate these server-side)
        const authResponse = await fetch('/api/vonage/generate-client-token');
        const { sessionId, token } = await authResponse.json();

        // Initialize Vonage Client
        const client = new VonageClient({ apiKey: 'your_vonage_key', sessionId, token });
        await client.connect();

        // Trigger the call (your backend will handle the bridging logic)
        const call = await client.call({
            number: 'driver_phone_number',
            from: 'your_vonage_number'
        });

        // Handle call events
        call.on('connected', () => alert('Call connected!'));
        call.on('ended', () => alert('Call ended.'));
    } catch (error) {
        console.error('Call failed:', error);
        alert('Failed to start call. Please check your audio permissions.');
    }
});
</script>

Note: You’ll need to add a server-side endpoint to generate the sessionId and token using Vonage’s Client SDK—check the official docs for generating user tokens for browser calls.

Key Notes to Avoid Headaches

  • Number Formatting: Always use E.164 format for phone numbers (e.g., +14083934444 instead of 14083934444).
  • Anonymous Guarantee: By setting the from parameter to your Vonage number for both connections, neither party will see the other’s real number.
  • Error Handling: Add try/catch blocks in your Laravel controller to handle cases like invalid numbers, insufficient balance, or API timeouts.

内容的提问来源于stack exchange,提问作者Ganesh Selvarajan

火山引擎 最新活动