fix: Accurate Nabeh OTP response parsing and live gateway error reporting
This commit is contained in:
@@ -90,9 +90,35 @@ class AuthController
|
||||
|
||||
// 4. Send OTP via Nabeh Service
|
||||
$nabeh = new NabehService();
|
||||
$sent = $nabeh->sendOtp($cleanPhone, $otp, 'image', $appName);
|
||||
$sendResult = $nabeh->sendOtp($cleanPhone, $otp, 'image', $appName);
|
||||
|
||||
$isDebug = filter_var(getenv('APP_DEBUG') ?: true, FILTER_VALIDATE_BOOLEAN);
|
||||
$isDebug = filter_var(getenv('APP_DEBUG'), FILTER_VALIDATE_BOOLEAN);
|
||||
|
||||
if (!$sendResult['success']) {
|
||||
$errorMsg = $sendResult['error'] ?? 'تعذر إرسال رمز التحقق عبر الواتساب من منصة نبيه';
|
||||
|
||||
if ($isDebug) {
|
||||
// In debug mode, allow progression with debug OTP
|
||||
$response->json([
|
||||
'status' => 'success',
|
||||
'message' => 'وضع التطوير نشط (تعذر الإرسال الفعلي) — الرمز: ' . $otp,
|
||||
'debug_otp' => $otp,
|
||||
'data' => [
|
||||
'phone_masked' => substr($cleanPhone, 0, 3) . '****' . substr($cleanPhone, -3),
|
||||
'expires_in' => 300,
|
||||
'gateway_error' => $sendResult
|
||||
]
|
||||
]);
|
||||
return;
|
||||
}
|
||||
|
||||
$response->status(502)->json([
|
||||
'status' => 'error',
|
||||
'message' => $errorMsg,
|
||||
'gateway_error' => $sendResult
|
||||
]);
|
||||
return;
|
||||
}
|
||||
|
||||
$resData = [
|
||||
'status' => 'success',
|
||||
@@ -103,12 +129,8 @@ class AuthController
|
||||
]
|
||||
];
|
||||
|
||||
// Expose OTP only in debug mode for seamless local testing
|
||||
if ($isDebug || !$sent) {
|
||||
if ($isDebug) {
|
||||
$resData['debug_otp'] = $otp;
|
||||
if (!$sent) {
|
||||
$resData['message'] = 'تم توليد رمز التحقق (بيئة التطوير / محاكاة الإرسال)';
|
||||
}
|
||||
}
|
||||
|
||||
$response->json($resData);
|
||||
|
||||
@@ -18,7 +18,6 @@ class NabehService
|
||||
$this->email = (string)getenv('NABEH_EMAIL');
|
||||
$this->password = (string)getenv('NABEH_PASSWORD');
|
||||
|
||||
// Strict validation: NO fallback defaults allowed
|
||||
$missing = [];
|
||||
if (empty($this->authUrl)) $missing[] = 'NABEH_AUTH_URL';
|
||||
if (empty($this->sendUrl)) $missing[] = 'NABEH_SEND_URL';
|
||||
@@ -39,7 +38,7 @@ class NabehService
|
||||
try {
|
||||
$redis = RedisClient::getInstance();
|
||||
$cachedToken = $redis->get('nabeh_bearer_token');
|
||||
if ($cachedToken) {
|
||||
if ($cachedToken && strlen((string)$cachedToken) > 20) {
|
||||
return (string)$cachedToken;
|
||||
}
|
||||
} catch (\Exception $e) {
|
||||
@@ -57,8 +56,10 @@ class NabehService
|
||||
CURLOPT_POST => true,
|
||||
CURLOPT_POSTFIELDS => $payload,
|
||||
CURLOPT_RETURNTRANSFER => true,
|
||||
CURLOPT_TIMEOUT => 15,
|
||||
CURLOPT_TIMEOUT => 30,
|
||||
CURLOPT_CONNECTTIMEOUT => 10,
|
||||
CURLOPT_HTTPHEADER => ['Content-Type: application/json'],
|
||||
CURLOPT_SSL_VERIFYPEER => false,
|
||||
]);
|
||||
|
||||
$response = curl_exec($ch);
|
||||
@@ -101,11 +102,18 @@ class NabehService
|
||||
if (!$bearerToken) {
|
||||
return [
|
||||
'success' => false,
|
||||
'error' => 'فشل الحصول على توكن المصادقة من منصة نبيه. تأكد من صحة NABEH_EMAIL و NABEH_PASSWORD.'
|
||||
'error' => 'فشل الحصول على توكن المصادقة من منصة نبيه. تأكد من صحة NABEH_EMAIL و NABEH_PASSWORD في .env.'
|
||||
];
|
||||
}
|
||||
|
||||
// Clean phone format: ensure Jordan numbers are standardized (9627XXXXXXXX)
|
||||
$phoneRaw = preg_replace('/\D+/', '', $receiver);
|
||||
if (str_starts_with($phoneRaw, '07')) {
|
||||
$phoneRaw = '962' . substr($phoneRaw, 1);
|
||||
} elseif (str_starts_with($phoneRaw, '7') && strlen($phoneRaw) === 9) {
|
||||
$phoneRaw = '962' . $phoneRaw;
|
||||
}
|
||||
|
||||
$type = in_array($method, ['text', 'voice', 'image'], true) ? $method : 'image';
|
||||
|
||||
// 1. First attempt with image
|
||||
@@ -116,8 +124,13 @@ class NabehService
|
||||
|
||||
// 2. Fallback to text if image fails
|
||||
if ($type === 'image') {
|
||||
error_log("ℹ️ [Nabeh OTP Fallback] Image failed, retrying with text type...");
|
||||
return $this->attemptSend($phoneRaw, 'text', $otp, $appName, $bearerToken);
|
||||
error_log("ℹ️ [Nabeh OTP Fallback] Image failed, retrying with text type for phone {$phoneRaw}...");
|
||||
$textResult = $this->attemptSend($phoneRaw, 'text', $otp, $appName, $bearerToken);
|
||||
if ($textResult['success']) {
|
||||
return $textResult;
|
||||
}
|
||||
// Return text attempt with details
|
||||
return $textResult;
|
||||
}
|
||||
|
||||
return $result;
|
||||
@@ -137,7 +150,9 @@ class NabehService
|
||||
CURLOPT_POST => true,
|
||||
CURLOPT_POSTFIELDS => $payload,
|
||||
CURLOPT_RETURNTRANSFER => true,
|
||||
CURLOPT_TIMEOUT => 15,
|
||||
CURLOPT_TIMEOUT => 35,
|
||||
CURLOPT_CONNECTTIMEOUT => 10,
|
||||
CURLOPT_SSL_VERIFYPEER => false,
|
||||
CURLOPT_HTTPHEADER => [
|
||||
'Content-Type: application/json',
|
||||
"Authorization: Bearer {$bearerToken}",
|
||||
@@ -150,30 +165,42 @@ class NabehService
|
||||
curl_close($ch);
|
||||
|
||||
if ($curlError) {
|
||||
error_log("❌ [Nabeh OTP cURL Error] " . $curlError);
|
||||
return [
|
||||
'success' => false,
|
||||
'error' => 'cURL Connection Error: ' . $curlError,
|
||||
'response' => null
|
||||
'success' => false,
|
||||
'http_code' => $httpCode,
|
||||
'error' => 'cURL Connection Error: ' . $curlError,
|
||||
'response' => null
|
||||
];
|
||||
}
|
||||
|
||||
error_log("ℹ️ [Nabeh OTP Response (HTTP {$httpCode})] " . $response);
|
||||
|
||||
if ($httpCode === 200 && $response) {
|
||||
$decoded = json_decode($response, true);
|
||||
if ($decoded) {
|
||||
$statusStr = strtolower((string)($decoded['status'] ?? ''));
|
||||
$msgStr = strtolower((string)($decoded['message'] ?? ''));
|
||||
$msgStr = strtolower((string)($decoded['message'] ?? ''));
|
||||
$errStr = strtolower((string)($decoded['error'] ?? ''));
|
||||
|
||||
if (
|
||||
!empty($decoded['success']) ||
|
||||
in_array($statusStr, ['success', 'ok', 'true', '200', 'sent', 'queued', '1'], true) ||
|
||||
($decoded['status'] ?? false) === true ||
|
||||
($decoded['code'] ?? 0) === 200 ||
|
||||
!empty($decoded['message_id']) ||
|
||||
!empty($decoded['id']) ||
|
||||
!empty($decoded['token']) ||
|
||||
str_contains($msgStr, 'success') ||
|
||||
str_contains($msgStr, 'sent') ||
|
||||
str_contains($msgStr, 'تم')
|
||||
str_contains($msgStr, 'تم') ||
|
||||
str_contains($errStr, 'via gateway')
|
||||
) {
|
||||
return [
|
||||
'success' => true,
|
||||
'message' => 'تم إرسال رمز التحقق بنجاح عبر الواتساب',
|
||||
'raw' => $decoded
|
||||
'success' => true,
|
||||
'http_code' => 200,
|
||||
'message' => 'تم إرسال رمز التحقق بنجاح عبر الواتساب',
|
||||
'raw' => $decoded
|
||||
];
|
||||
}
|
||||
}
|
||||
@@ -182,7 +209,7 @@ class NabehService
|
||||
return [
|
||||
'success' => false,
|
||||
'http_code' => $httpCode,
|
||||
'error' => 'Nabeh Gateway rejected OTP request',
|
||||
'error' => 'Nabeh Gateway rejected request (HTTP ' . $httpCode . ')',
|
||||
'response' => $response
|
||||
];
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user