From 1400f8a01416bf74b12026d5544cd47f49b0ea45 Mon Sep 17 00:00:00 2001 From: Hamza-Ayed Date: Fri, 18 Sep 2026 18:12:45 +0300 Subject: [PATCH] feat(telecom): integrate verified OTPIQ live API with whatsapp-sms and auto-formatting --- backend/app/Services/OtpIqService.php | 39 ++++++++++++++++----------- 1 file changed, 23 insertions(+), 16 deletions(-) diff --git a/backend/app/Services/OtpIqService.php b/backend/app/Services/OtpIqService.php index aaf01a6..4381224 100644 --- a/backend/app/Services/OtpIqService.php +++ b/backend/app/Services/OtpIqService.php @@ -7,40 +7,41 @@ namespace App\Services; class OtpIqService { private string $apiKey; - private string $senderId; private string $endpoint; + private string $provider; public function __construct() { - $this->apiKey = getenv('OTPIQ_API_KEY') ?: ''; - $this->senderId = getenv('OTPIQ_SENDER_ID') ?: 'URUK-PRIZE'; + $this->apiKey = getenv('OTPIQ_API_KEY') ?: 'sk_live_a2b4f0fe539910aee2e44be050e9767bea266607'; $this->endpoint = getenv('OTPIQ_ENDPOINT') ?: 'https://api.otpiq.com/api/sms'; + $this->provider = getenv('OTPIQ_PROVIDER') ?: 'whatsapp-sms'; } /** * Sends OTP via OTPIQ with Smart Fallback (WhatsApp first, then SMS). + * Verified with live production API credentials. */ public function sendOtp(string $phoneNumber, string $otpCode): array { + $normalizedPhone = PhoneFormatterService::normalize($phoneNumber); + // If API key is not configured, run in Mock / Dev mode if (empty($this->apiKey)) { - error_log("[MOCK OTPIQ] Sent OTP {$otpCode} to {$phoneNumber} via WhatsApp/SMS Smart Fallback."); + error_log("[MOCK OTPIQ] Sent OTP {$otpCode} to {$normalizedPhone} via whatsapp-sms."); return [ 'success' => true, 'mode' => 'mock', - 'phone' => $phoneNumber, + 'phone' => $normalizedPhone, 'otp' => $otpCode, - 'provider' => 'mock-smart-fallback', + 'provider' => $this->provider, ]; } $payload = [ - 'recipient' => $phoneNumber, - 'sender_id' => $this->senderId, - 'type' => 'otp', - 'code' => $otpCode, - 'message' => "رمز التحقق الخاص بك لجائزة أوروك الدولية هو: {$otpCode}. لا تشاركه مع أحد.", - 'channels' => ['whatsapp', 'sms'], // Smart fallback pipeline + 'phoneNumber' => $normalizedPhone, + 'smsType' => 'verification', + 'provider' => $this->provider, + 'verificationCode' => (string)$otpCode, ]; $ch = curl_init($this->endpoint); @@ -49,21 +50,23 @@ class OtpIqService CURLOPT_POST => true, CURLOPT_POSTFIELDS => json_encode($payload), CURLOPT_HTTPHEADER => [ - 'Content-Type: application/json', 'Authorization: Bearer ' . $this->apiKey, + 'Content-Type: application/json', ], - CURLOPT_TIMEOUT => 10, + CURLOPT_TIMEOUT => 12, ]); $response = curl_exec($ch); $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE); $error = curl_error($ch); - curl_close($ch); + if (PHP_VERSION_ID < 80500) { + curl_close($ch); + } if ($error || $httpCode >= 400) { return [ 'success' => false, - 'error' => $error ?: "HTTP {$httpCode}: " . substr((string)$response, 0, 100), + 'error' => $error ?: "HTTP {$httpCode}: " . substr((string)$response, 0, 150), ]; } @@ -71,6 +74,10 @@ class OtpIqService return [ 'success' => true, 'data' => $data, + 'sms_id' => $data['smsId'] ?? null, + 'remaining_credit' => $data['remainingCredit'] ?? null, + 'cost' => $data['cost'] ?? 25, ]; } } +