$request->ip(), 'number' => $request->input('number'), 'orderid' => $request->input('orderid'), ]); $user = Auth::user(); if (!$user) { Log::warning('CallThroughApi@initiate: unauthenticated'); return response()->json(['status' => 'error', 'message' => 'Unauthorized'], 401); } Log::info('CallThroughApi@initiate: authenticated as user#' . $user->id); // ── Permission check ────────────────────────────────────────────────── if (!$user->hasPermissionTo('calls.through.api')) { Log::warning('CallThroughApi@initiate: user#' . $user->id . ' lacks calls.through.api permission'); return response()->json(['status' => 'error', 'message' => 'Unauthorized'], 403); } // ── Validation ──────────────────────────────────────────────────────── $validator = Validator::make($request->all(), [ 'number' => 'required|string', 'voice' => 'required|array|min:1', 'voice.*.key' => 'required|integer', 'voice.*.value' => 'required|string|url', 'orderid' => 'nullable|string', ]); if ($validator->fails()) { Log::warning('CallThroughApi@initiate: validation failed', [ 'errors' => $validator->errors()->toArray(), ]); return response()->json([ 'status' => 'error', 'message' => 'Validation failed', 'errors' => $validator->errors(), ], 422); } // ── Resolve DID from company settings ───────────────────────────────── $did = CompanySettings::get('api_did')?? '0020221282797'; // Default DID if not configured if (!$did) { Log::error('CallThroughApi@initiate: api_did not configured in dialer settings'); return response()->json([ 'status' => 'error', 'message' => 'Outgoing DID is not configured. Please set it in Settings → Dialer Settings.', ], 500); } Log::info('CallThroughApi@initiate: using DID=' . $did); // Warn if webhook not configured (non-fatal — call still proceeds) if (!CompanySettings::get('api_webhook_url')) { Log::warning('CallThroughApi@initiate: api_webhook_url is not configured — results will not be posted'); } // ── Create DialerCalls record ───────────────────────────────────────── $dialer_call = new DialerCalls(); $dialer_call->number = $request->input('number'); $dialer_call->orderid = $request->input('orderid'); // nullable $dialer_call->communication_method = 'call'; $dialer_call->voices = json_encode($request->input('voice')); $dialer_call->did = $did; $dialer_call->order_status = 'New'; $dialer_call->save(); Log::info('CallThroughApi@initiate: DialerCalls record created', [ 'id' => $dialer_call->id, 'number' => $dialer_call->number, 'did' => $dialer_call->did, ]); // ── Fire one:shoot in background ────────────────────────────────────── exec("/var/www/ccsystem/artisan one:shoot {$dialer_call->id} > /dev/null 2>&1 &"); Log::info('CallThroughApi@initiate: one:shoot dispatched', [ 'dialer_call_id' => $dialer_call->id, ]); return response()->json([ 'status' => 'success', 'message' => 'Call initiated successfully', 'data' => [ 'call_id' => $dialer_call->id, 'orderid' => $dialer_call->orderid, 'number' => $dialer_call->number, ], ], 200); } /** * Handle webhook callbacks from the dialer system. * * This endpoint is called by the dialer system to report call status updates. * It expects a JSON payload with the following fields: * - call_id : integer (required) ID of the DialerCalls record * - status : string (required) Call status (e.g., "completed", "failed") * - details : string (optional) Additional details about the call */ public function webhook(HttpRequest $request) { Log::info('CallThroughApi@webhook: request received', [ 'ip' => $request->ip(), 'payload' => $request->all(), ]); return response()->json(['status' => 'received'], 200); } }