feat: implement OTP sending via Kavenegar VerifyLookup and add image cropping modal

- Added support for sending OTP messages using Kavenegar's VerifyLookup method, ensuring compliance with specified token formatting and template usage.
- Updated OtpService to handle new template parameters and fallback mechanisms.
- Introduced ImageCropModal component for cropping images with a user-friendly interface.
- Created utility function for cropping images and generating downloadable files.
This commit is contained in:
hamed
2026-07-04 21:50:55 +03:30
parent 1bb9cedd22
commit 6ade17a5b4
10 changed files with 822 additions and 2185 deletions
+14 -1
View File
@@ -20,6 +20,7 @@ class OtpService
private readonly CityRepository $cityRepo,
private readonly int $otpTtl = 1200,
private readonly string $appEnv = 'dev',
private readonly ?string $otpTemplate = null,
) {}
private function key(string $uuid): string
@@ -73,7 +74,19 @@ class OtpService
if ($this->appEnv !== 'dev') {
$site = $this->resolveSiteName($domain);
$message = $this->smsText->resolve(SmsLog::TAG_OTP, ['code' => $code, 'site' => $site]);
$this->sms->dispatchAsync($mobile, $message, tag: SmsLog::TAG_OTP);
if ($this->otpTemplate) {
// Kavenegar VerifyLookup: code has no spaces → token; site may contain spaces → token10.
$this->sms->dispatchAsync(
$mobile,
$message,
templateCode: $this->otpTemplate,
templateVars: ['token' => $code, 'token10' => $site],
tag: SmsLog::TAG_OTP,
);
} else {
$this->sms->dispatchAsync($mobile, $message, tag: SmsLog::TAG_OTP);
}
}
return $uuid;
+13 -2
View File
@@ -47,8 +47,19 @@ class KavehNegarProvider implements SmsProviderInterface
{
try {
$params = ['receptor' => $mobile, 'template' => $templateCode];
foreach (array_values($vars) as $i => $v) {
$params['token' . ($i > 0 ? $i + 1 : '')] = $v;
// Kavenegar token slots: token/token2/token3 reject spaces; token10/token20 allow them.
// If every key is an explicit slot name, honor it (e.g. site with spaces → token10);
// otherwise fall back to positional mapping (token, token2, token3, ...).
$slots = ['token', 'token2', 'token3', 'token10', 'token20'];
if ($vars !== [] && array_keys($vars) !== range(0, count($vars) - 1)
&& array_diff(array_keys($vars), $slots) === []) {
foreach ($vars as $slot => $v) {
$params[$slot] = $v;
}
} else {
foreach (array_values($vars) as $i => $v) {
$params['token' . ($i > 0 ? $i + 1 : '')] = $v;
}
}
$resp = $this->httpClient->request('POST',
self::BASE . '/' . $this->key() . '/verify/lookup.json', [