fix: Strict env enforcement, rock-solid Alpine portal rendering, and Nabeh/Redis test diagnostics
This commit is contained in:
@@ -8,15 +8,26 @@ class NabehService
|
||||
{
|
||||
private string $authUrl;
|
||||
private string $sendUrl;
|
||||
private ?string $email;
|
||||
private ?string $password;
|
||||
private string $email;
|
||||
private string $password;
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this->authUrl = getenv('NABEH_AUTH_URL') ?: 'https://nabeh.intaleqapp.com/api/auth/login';
|
||||
$this->sendUrl = getenv('NABEH_SEND_URL') ?: 'https://nabeh.intaleqapp.com/api/otp/send';
|
||||
$this->email = getenv('NABEH_EMAIL') ?: null;
|
||||
$this->password = getenv('NABEH_PASSWORD') ?: null;
|
||||
$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');
|
||||
|
||||
// Strict validation: NO fallback defaults allowed
|
||||
$missing = [];
|
||||
if (empty($this->authUrl)) $missing[] = 'NABEH_AUTH_URL';
|
||||
if (empty($this->sendUrl)) $missing[] = 'NABEH_SEND_URL';
|
||||
if (empty($this->email)) $missing[] = 'NABEH_EMAIL';
|
||||
if (empty($this->password)) $missing[] = 'NABEH_PASSWORD';
|
||||
|
||||
if (!empty($missing)) {
|
||||
throw new \RuntimeException("Nabeh Service configuration error: Missing environment variable(s): " . implode(', ', $missing));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -36,11 +47,6 @@ class NabehService
|
||||
}
|
||||
|
||||
// 2. Token not cached, authenticate via Nabeh Login API
|
||||
if (!$this->email || !$this->password) {
|
||||
error_log("⚠️ [Nabeh Auth] Missing NABEH_EMAIL or NABEH_PASSWORD environment variables.");
|
||||
return null;
|
||||
}
|
||||
|
||||
$payload = json_encode([
|
||||
'email' => $this->email,
|
||||
'password' => $this->password,
|
||||
@@ -51,24 +57,30 @@ class NabehService
|
||||
CURLOPT_POST => true,
|
||||
CURLOPT_POSTFIELDS => $payload,
|
||||
CURLOPT_RETURNTRANSFER => true,
|
||||
CURLOPT_TIMEOUT => 10,
|
||||
CURLOPT_TIMEOUT => 15,
|
||||
CURLOPT_HTTPHEADER => ['Content-Type: application/json'],
|
||||
]);
|
||||
|
||||
$response = curl_exec($ch);
|
||||
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
|
||||
$curlError = curl_error($ch);
|
||||
curl_close($ch);
|
||||
|
||||
if ($curlError) {
|
||||
error_log("❌ [Nabeh Auth cURL Error] " . $curlError);
|
||||
return null;
|
||||
}
|
||||
|
||||
if ($httpCode === 200 && $response) {
|
||||
$decoded = json_decode($response, true);
|
||||
$token = $decoded['token'] ?? $decoded['message']['token'] ?? $decoded['jwt'] ?? $decoded['access_token'] ?? null;
|
||||
|
||||
if ($token) {
|
||||
// Cache token in Redis for 24h
|
||||
// Cache token in Redis for 24h (86400 seconds)
|
||||
try {
|
||||
$redis = RedisClient::getInstance();
|
||||
$redis->setex('nabeh_bearer_token', 86400, (string)$token);
|
||||
error_log("[Nabeh Auth] Token cached in Redis successfully.");
|
||||
error_log("✅ [Nabeh Auth] Token cached in Redis successfully.");
|
||||
} catch (\Exception $e) {
|
||||
error_log("⚠️ [Nabeh Auth Redis Cache Save] Error saving token: " . $e->getMessage());
|
||||
}
|
||||
@@ -76,28 +88,30 @@ class NabehService
|
||||
}
|
||||
}
|
||||
|
||||
error_log("❌ [Nabeh Auth Login Failed] Response: " . $response);
|
||||
error_log("❌ [Nabeh Auth Login Failed] Code: {$httpCode} | Response: {$response}");
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Send OTP via Nabeh JWT Auth Gateway (WhatsApp Image/Text OTP)
|
||||
*/
|
||||
public function sendOtp(string $receiver, string $otp, string $method = 'image', string $appName = 'منصة صَقِل'): bool
|
||||
public function sendOtp(string $receiver, string $otp, string $method = 'image', string $appName = 'منصة صَقِل'): array
|
||||
{
|
||||
$bearerToken = $this->getBearerToken();
|
||||
if (!$bearerToken) {
|
||||
error_log("⚠️ [Nabeh OTP] Failed to obtain dynamic JWT Bearer token.");
|
||||
return false;
|
||||
return [
|
||||
'success' => false,
|
||||
'error' => 'فشل الحصول على توكن المصادقة من منصة نبيه. تأكد من صحة NABEH_EMAIL و NABEH_PASSWORD.'
|
||||
];
|
||||
}
|
||||
|
||||
$phoneRaw = preg_replace('/\D+/', '', $receiver);
|
||||
$type = in_array($method, ['text', 'voice', 'image'], true) ? $method : 'image';
|
||||
|
||||
// 1. First attempt with image
|
||||
$success = $this->attemptSend($phoneRaw, $type, $otp, $appName, $bearerToken);
|
||||
if ($success) {
|
||||
return true;
|
||||
$result = $this->attemptSend($phoneRaw, $type, $otp, $appName, $bearerToken);
|
||||
if ($result['success']) {
|
||||
return $result;
|
||||
}
|
||||
|
||||
// 2. Fallback to text if image fails
|
||||
@@ -106,10 +120,10 @@ class NabehService
|
||||
return $this->attemptSend($phoneRaw, 'text', $otp, $appName, $bearerToken);
|
||||
}
|
||||
|
||||
return false;
|
||||
return $result;
|
||||
}
|
||||
|
||||
private function attemptSend(string $phone, string $type, string $otp, string $appName, string $bearerToken): bool
|
||||
private function attemptSend(string $phone, string $type, string $otp, string $appName, string $bearerToken): array
|
||||
{
|
||||
$payload = json_encode([
|
||||
'phone' => $phone,
|
||||
@@ -123,7 +137,7 @@ class NabehService
|
||||
CURLOPT_POST => true,
|
||||
CURLOPT_POSTFIELDS => $payload,
|
||||
CURLOPT_RETURNTRANSFER => true,
|
||||
CURLOPT_TIMEOUT => 10,
|
||||
CURLOPT_TIMEOUT => 15,
|
||||
CURLOPT_HTTPHEADER => [
|
||||
'Content-Type: application/json',
|
||||
"Authorization: Bearer {$bearerToken}",
|
||||
@@ -132,8 +146,17 @@ class NabehService
|
||||
|
||||
$response = curl_exec($ch);
|
||||
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
|
||||
$curlError = curl_error($ch);
|
||||
curl_close($ch);
|
||||
|
||||
if ($curlError) {
|
||||
return [
|
||||
'success' => false,
|
||||
'error' => 'cURL Connection Error: ' . $curlError,
|
||||
'response' => null
|
||||
];
|
||||
}
|
||||
|
||||
if ($httpCode === 200 && $response) {
|
||||
$decoded = json_decode($response, true);
|
||||
if ($decoded) {
|
||||
@@ -147,12 +170,20 @@ class NabehService
|
||||
str_contains($msgStr, 'sent') ||
|
||||
str_contains($msgStr, 'تم')
|
||||
) {
|
||||
return true;
|
||||
return [
|
||||
'success' => true,
|
||||
'message' => 'تم إرسال رمز التحقق بنجاح عبر الواتساب',
|
||||
'raw' => $decoded
|
||||
];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
error_log("❌ [Nabeh OTP Attempt Failed] Code: {$httpCode} Response: {$response}");
|
||||
return false;
|
||||
return [
|
||||
'success' => false,
|
||||
'http_code' => $httpCode,
|
||||
'error' => 'Nabeh Gateway rejected OTP request',
|
||||
'response' => $response
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user