fix: Fast text WhatsApp OTP by default, 50s timeout for image mode with auto-fallback
This commit is contained in:
@@ -93,12 +93,14 @@ class TestController
|
||||
$cleanPhone = '962' . substr($cleanPhone, 1);
|
||||
}
|
||||
$testOtp = (string)random_int(100000, 999999);
|
||||
$type = $queryParams['type'] ?? 'text'; // Fast text mode by default
|
||||
try {
|
||||
$nabeh = new NabehService();
|
||||
$sendResult = $nabeh->sendOtp($cleanPhone, $testOtp, 'image', 'فحص منصة صَقِل');
|
||||
$sendResult = $nabeh->sendOtp($cleanPhone, $testOtp, $type, 'فحص منصة صَقِل');
|
||||
$results['live_otp_test'] = [
|
||||
'phone' => $cleanPhone,
|
||||
'code_sent' => $testOtp,
|
||||
'type_used' => $type,
|
||||
'send_result' => $sendResult
|
||||
];
|
||||
} catch (\Exception $e) {
|
||||
@@ -108,7 +110,7 @@ class TestController
|
||||
];
|
||||
}
|
||||
} else {
|
||||
$results['live_otp_test'] = 'To test sending an actual WhatsApp OTP, add ?phone=96279XXXXXXX to this URL';
|
||||
$results['live_otp_test'] = 'To test sending an actual WhatsApp OTP, add ?phone=96279XXXXXXX&type=text to this URL';
|
||||
}
|
||||
|
||||
$response->json([
|
||||
|
||||
@@ -10,13 +10,15 @@ class NabehService
|
||||
private string $sendUrl;
|
||||
private string $email;
|
||||
private string $password;
|
||||
private string $defaultType;
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this->authUrl = (string)getenv('NABEH_AUTH_URL');
|
||||
$this->sendUrl = (string)getenv('NABEH_SEND_URL');
|
||||
$this->email = (string)getenv('NABEH_EMAIL');
|
||||
$this->password = (string)getenv('NABEH_PASSWORD');
|
||||
$this->authUrl = (string)getenv('NABEH_AUTH_URL');
|
||||
$this->sendUrl = (string)getenv('NABEH_SEND_URL');
|
||||
$this->email = (string)getenv('NABEH_EMAIL');
|
||||
$this->password = (string)getenv('NABEH_PASSWORD');
|
||||
$this->defaultType = (string)(getenv('NABEH_OTP_TYPE') ?: 'text');
|
||||
|
||||
$missing = [];
|
||||
if (empty($this->authUrl)) $missing[] = 'NABEH_AUTH_URL';
|
||||
@@ -60,6 +62,7 @@ class NabehService
|
||||
CURLOPT_CONNECTTIMEOUT => 10,
|
||||
CURLOPT_HTTPHEADER => ['Content-Type: application/json'],
|
||||
CURLOPT_SSL_VERIFYPEER => false,
|
||||
CURLOPT_SSL_VERIFYHOST => false,
|
||||
]);
|
||||
|
||||
$response = curl_exec($ch);
|
||||
@@ -94,9 +97,10 @@ class NabehService
|
||||
}
|
||||
|
||||
/**
|
||||
* Send OTP via Nabeh JWT Auth Gateway (WhatsApp Image/Text OTP)
|
||||
* Send OTP via Nabeh JWT Auth Gateway (WhatsApp text/image OTP)
|
||||
* Text mode is ultra-fast (1-2s). Image mode generates dynamic card (10-25s).
|
||||
*/
|
||||
public function sendOtp(string $receiver, string $otp, string $method = 'image', string $appName = 'منصة صَقِل'): array
|
||||
public function sendOtp(string $receiver, string $otp, ?string $method = null, string $appName = 'منصة صَقِل'): array
|
||||
{
|
||||
$bearerToken = $this->getBearerToken();
|
||||
if (!$bearerToken) {
|
||||
@@ -114,22 +118,26 @@ class NabehService
|
||||
$phoneRaw = '962' . $phoneRaw;
|
||||
}
|
||||
|
||||
$type = in_array($method, ['text', 'voice', 'image'], true) ? $method : 'image';
|
||||
// Selected type: provided method > defaultType > 'text'
|
||||
$selectedType = $method ?: $this->defaultType;
|
||||
if (!in_array($selectedType, ['text', 'voice', 'image'], true)) {
|
||||
$selectedType = 'text';
|
||||
}
|
||||
|
||||
// 1. First attempt with image
|
||||
$result = $this->attemptSend($phoneRaw, $type, $otp, $appName, $bearerToken);
|
||||
// 1. First attempt with selected type (text or image)
|
||||
$result = $this->attemptSend($phoneRaw, $selectedType, $otp, $appName, $bearerToken);
|
||||
if ($result['success']) {
|
||||
return $result;
|
||||
}
|
||||
|
||||
// 2. Fallback to text if image fails
|
||||
if ($type === 'image') {
|
||||
error_log("ℹ️ [Nabeh OTP Fallback] Image failed, retrying with text type for phone {$phoneRaw}...");
|
||||
// 2. If image failed or timed out, fallback to instant text OTP
|
||||
if ($selectedType === 'image') {
|
||||
error_log("ℹ️ [Nabeh OTP Fallback] Image mode failed/timed out for {$phoneRaw}. Retrying instantly with Text mode...");
|
||||
$textResult = $this->attemptSend($phoneRaw, 'text', $otp, $appName, $bearerToken);
|
||||
if ($textResult['success']) {
|
||||
$textResult['note'] = 'Image OTP timed out, delivered via fast text fallback';
|
||||
return $textResult;
|
||||
}
|
||||
// Return text attempt with details
|
||||
return $textResult;
|
||||
}
|
||||
|
||||
@@ -145,36 +153,43 @@ class NabehService
|
||||
'message' => "رمز التحقق الخاص بك لمنصة {$appName} هو: *{$otp}* \n الرجاء عدم مشاركته مع أي شخص لحماية حسابك.",
|
||||
]);
|
||||
|
||||
$timeout = ($type === 'image') ? 50 : 25; // 50s for image rendering, 25s for text
|
||||
|
||||
$ch = curl_init($this->sendUrl);
|
||||
curl_setopt_array($ch, [
|
||||
CURLOPT_POST => true,
|
||||
CURLOPT_POSTFIELDS => $payload,
|
||||
CURLOPT_RETURNTRANSFER => true,
|
||||
CURLOPT_TIMEOUT => 35,
|
||||
CURLOPT_TIMEOUT => $timeout,
|
||||
CURLOPT_CONNECTTIMEOUT => 10,
|
||||
CURLOPT_SSL_VERIFYPEER => false,
|
||||
CURLOPT_SSL_VERIFYHOST => false,
|
||||
CURLOPT_HTTPHEADER => [
|
||||
'Content-Type: application/json',
|
||||
"Authorization: Bearer {$bearerToken}",
|
||||
],
|
||||
]);
|
||||
|
||||
$startTime = microtime(true);
|
||||
$response = curl_exec($ch);
|
||||
$duration = round(microtime(true) - $startTime, 2);
|
||||
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
|
||||
$curlError = curl_error($ch);
|
||||
curl_close($ch);
|
||||
|
||||
if ($curlError) {
|
||||
error_log("❌ [Nabeh OTP cURL Error] " . $curlError);
|
||||
error_log("❌ [Nabeh OTP cURL Error (type={$type}, duration={$duration}s)] " . $curlError);
|
||||
return [
|
||||
'success' => false,
|
||||
'type_used' => $type,
|
||||
'duration' => "{$duration}s",
|
||||
'http_code' => $httpCode,
|
||||
'error' => 'cURL Connection Error: ' . $curlError,
|
||||
'error' => 'cURL Error: ' . $curlError,
|
||||
'response' => null
|
||||
];
|
||||
}
|
||||
|
||||
error_log("ℹ️ [Nabeh OTP Response (HTTP {$httpCode})] " . $response);
|
||||
error_log("ℹ️ [Nabeh OTP Response (type={$type}, duration={$duration}s, HTTP {$httpCode})] " . $response);
|
||||
|
||||
if ($httpCode === 200 && $response) {
|
||||
$decoded = json_decode($response, true);
|
||||
@@ -198,6 +213,8 @@ class NabehService
|
||||
) {
|
||||
return [
|
||||
'success' => true,
|
||||
'type_used' => $type,
|
||||
'duration' => "{$duration}s",
|
||||
'http_code' => 200,
|
||||
'message' => 'تم إرسال رمز التحقق بنجاح عبر الواتساب',
|
||||
'raw' => $decoded
|
||||
@@ -208,6 +225,8 @@ class NabehService
|
||||
|
||||
return [
|
||||
'success' => false,
|
||||
'type_used' => $type,
|
||||
'duration' => "{$duration}s",
|
||||
'http_code' => $httpCode,
|
||||
'error' => 'Nabeh Gateway rejected request (HTTP ' . $httpCode . ')',
|
||||
'response' => $response
|
||||
|
||||
Reference in New Issue
Block a user