109 خطوط
4.2 KiB
PHP
109 خطوط
4.2 KiB
PHP
<?php
|
|
|
|
namespace App\Services\VoIP;
|
|
|
|
use App\Models\Setting;
|
|
use Illuminate\Support\Facades\Http;
|
|
use Throwable;
|
|
|
|
class ApiProvider implements VoIPProviderInterface
|
|
{
|
|
public function initiateCall(string $phone, ?string $callerId = null): array
|
|
{
|
|
$baseUrl = rtrim((string) Setting::where('key', 'voip_api_base_url')->value('value'), '/');
|
|
$token = Setting::where('key', 'voip_api_token')->value('value');
|
|
$callPath = Setting::where('key', 'voip_api_call_path')->value('value') ?: '/calls';
|
|
|
|
if (! $baseUrl) {
|
|
return [
|
|
'success' => false,
|
|
'provider_call_id' => null,
|
|
'message' => 'نشانی ایپیآی تماس تنظیم نشده است',
|
|
'status' => 'configuration_error',
|
|
];
|
|
}
|
|
|
|
$request = Http::acceptJson()->timeout(10);
|
|
if ($token) {
|
|
$request = $request->withToken($token);
|
|
}
|
|
|
|
$response = $request->post($baseUrl.'/'.ltrim($callPath, '/'), [
|
|
'phone' => $phone,
|
|
'caller_id' => $callerId,
|
|
]);
|
|
|
|
$body = $response->json() ?: [];
|
|
|
|
return [
|
|
'success' => $response->successful(),
|
|
'provider_call_id' => $body['provider_call_id'] ?? $body['call_id'] ?? null,
|
|
'message' => $body['message'] ?? ($response->successful() ? 'تماس از راه ایپیآی ارسال شد' : 'خطا در ارسال تماس از راه ایپیآی'),
|
|
'status' => $body['status'] ?? ($response->successful() ? 'initiated' : 'failed'),
|
|
'raw' => $body,
|
|
];
|
|
}
|
|
|
|
public function getCallStatus(string $providerCallId): array
|
|
{
|
|
$baseUrl = rtrim((string) Setting::where('key', 'voip_api_base_url')->value('value'), '/');
|
|
$token = Setting::where('key', 'voip_api_token')->value('value');
|
|
$statusPath = Setting::where('key', 'voip_api_status_path')->value('value') ?: '/calls/{id}';
|
|
|
|
if (! $baseUrl) {
|
|
return ['status' => 'configuration_error'];
|
|
}
|
|
|
|
$request = Http::acceptJson()->timeout(10);
|
|
if ($token) {
|
|
$request = $request->withToken($token);
|
|
}
|
|
|
|
$url = $baseUrl.'/'.ltrim(str_replace('{id}', $providerCallId, $statusPath), '/');
|
|
$response = $request->get($url);
|
|
|
|
return $response->json() ?: [
|
|
'status' => $response->successful() ? 'unknown' : 'failed',
|
|
];
|
|
}
|
|
|
|
public function getRecordingUrl(string $providerCallId): ?string
|
|
{
|
|
$template = Setting::where('key', 'voip_api_recording_url')->value('value');
|
|
|
|
return $template ? str_replace('{id}', $providerCallId, $template) : null;
|
|
}
|
|
|
|
public function testConnection(): array
|
|
{
|
|
$missing = [];
|
|
foreach (['voip_api_base_url', 'voip_api_token'] as $key) {
|
|
if (! Setting::where('key', $key)->value('value')) {
|
|
$missing[] = $key;
|
|
}
|
|
}
|
|
|
|
if ($missing !== []) {
|
|
return ['ok' => false, 'message' => 'تنظیمات اتصال API کامل نیست.', 'missing' => $missing];
|
|
}
|
|
|
|
$baseUrl = rtrim((string) Setting::where('key', 'voip_api_base_url')->value('value'), '/');
|
|
$token = Setting::where('key', 'voip_api_token')->value('value');
|
|
$healthPath = Setting::where('key', 'voip_api_health_path')->value('value') ?: '/health';
|
|
$started = microtime(true);
|
|
try {
|
|
$response = Http::acceptJson()->withToken($token)->timeout(10)->get($baseUrl.'/'.ltrim($healthPath, '/'));
|
|
$latency = (int) round((microtime(true) - $started) * 1000);
|
|
return [
|
|
'ok' => $response->successful(),
|
|
'message' => $response->successful() ? "اتصال واقعی API موفق بود ({$latency} میلیثانیه)." : "سرویس API پاسخ {$response->status()} داد.",
|
|
'missing' => [],
|
|
'latency_ms' => $latency,
|
|
'http_status' => $response->status(),
|
|
];
|
|
} catch (Throwable $error) {
|
|
return ['ok' => false, 'message' => 'اتصال واقعی API برقرار نشد: '.$error->getMessage(), 'missing' => []];
|
|
}
|
|
}
|
|
}
|