Update: 2026-08-06 18:32:03
This commit is contained in:
@@ -0,0 +1,58 @@
|
||||
<?php
|
||||
|
||||
namespace App\Services;
|
||||
|
||||
/**
|
||||
* Chooses which channel delivers an OTP.
|
||||
*
|
||||
* OTP_PROVIDER=nabeh -> Nabeh gateway
|
||||
* OTP_PROVIDER=whatsapp -> legacy self-hosted WhatsApp bots
|
||||
*
|
||||
* Callers pass the code, not a rendered message: Nabeh composes its own message
|
||||
* around the code, while the WhatsApp bots need finished text. Keeping that
|
||||
* difference here means call sites do not care which channel is active.
|
||||
*
|
||||
* With OTP_FALLBACK_ENABLED on, a failure is retried on the other channel
|
||||
* before the login is refused - losing OTP delivery locks out every user.
|
||||
*/
|
||||
class OtpSender
|
||||
{
|
||||
public static function sendOtp(string $phone, string $otp): array
|
||||
{
|
||||
$provider = strtolower(trim((string)env('OTP_PROVIDER', 'whatsapp')));
|
||||
$fallback = strtolower((string)env('OTP_FALLBACK_ENABLED', 'true')) === 'true';
|
||||
|
||||
$result = self::dispatch($provider, $phone, $otp);
|
||||
$result['provider'] = $provider;
|
||||
|
||||
if ($result['success'] || !$fallback) {
|
||||
return $result;
|
||||
}
|
||||
|
||||
$alternate = $provider === 'nabeh' ? 'whatsapp' : 'nabeh';
|
||||
error_log(sprintf(
|
||||
'[OTP] primary channel "%s" failed, falling back to "%s" | error=%s',
|
||||
$provider,
|
||||
$alternate,
|
||||
$result['error'] ?? substr((string)($result['raw_response'] ?? ''), 0, 200)
|
||||
));
|
||||
|
||||
$fallbackResult = self::dispatch($alternate, $phone, $otp);
|
||||
$fallbackResult['provider'] = $alternate;
|
||||
$fallbackResult['primary_error'] = $result['error'] ?? null;
|
||||
|
||||
return $fallbackResult;
|
||||
}
|
||||
|
||||
private static function dispatch(string $channel, string $phone, string $otp): array
|
||||
{
|
||||
if ($channel === 'nabeh') {
|
||||
return (new NabehOtpService())->sendOtp($phone, $otp);
|
||||
}
|
||||
|
||||
$appName = (string)env('NABEH_APP_NAME', 'مُصادَق');
|
||||
$message = "رمز التحقق لتطبيق {$appName}:\n*{$otp}*\n\nصالح لمدة 5 دقائق.";
|
||||
|
||||
return (new WhatsAppProxyService())->sendMessage($phone, $message);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user