new feature on sms and some bugs fixed

This commit is contained in:
2026-07-18 22:22:01 +03:30
parent 518334da11
commit fc9de5198c
20 changed files with 489 additions and 95 deletions
@@ -25,7 +25,9 @@ class BankAccountController extends SuperController
$accoun->save();
if ($accoun->sts == 2) {
$customer = Customer::find($accoun->customer_id);
$this->SendMessage($customer->mobile, 'کارت بانکی شما در ' . $this->Config('name_fa') . ' تایید شد');
if (self::isSmsNotifEnabled('sms_notif_bank_card_customer')) {
$this->SendMessage($customer->mobile, 'کارت بانکی شما در ' . $this->Config('name_fa') . ' تایید شد');
}
}
@@ -8,6 +8,8 @@ use App\Models\Message;
use App\Models\Order;
use Illuminate\Http\Request;
use App\Http\Controllers\Controller;
use App\Services\ConfigService;
use App\Services\SmsProfanityFilter;
use Symfony\Component\HttpKernel\Exception\UnprocessableEntityHttpException;
@@ -22,6 +24,9 @@ class MassageController extends Controller
// یافتن مشتریان با شماره‌های داده شده
$customers = Customer::whereIn('mobile', $request->numbers)->get();
$filter = app(SmsProfanityFilter::class);
$filter->assertClean((string) ($request->message ?? ''));
foreach ($customers as $customer) {
// جایگزین کردن نام در پیام
$message = str_replace('%name%', $customer->name, $request->message);
@@ -32,6 +37,59 @@ class MassageController extends Controller
return response()->json(true);
}
/**
* پیامک تکی به یک مشتری — فقط وقتی customer_direct_sms روشن باشد.
*/
public function send_customer_message(Request $request)
{
if (! app(ConfigService::class)->getBool('customer_direct_sms', false)) {
throw new UnprocessableEntityHttpException('ارسال پیامک تکی به مشتری غیرفعال است.');
}
$customerId = (int) ($request->input('customer_id') ?? 0);
$rawMessage = trim((string) ($request->input('message') ?? ''));
if ($customerId <= 0) {
throw new UnprocessableEntityHttpException('مشتری مشخص نشده است.');
}
if ($rawMessage === '') {
throw new UnprocessableEntityHttpException('متن پیامک خالی است.');
}
if (mb_strlen($rawMessage) > 700) {
throw new UnprocessableEntityHttpException('متن پیامک بیش از حد طولانی است.');
}
app(SmsProfanityFilter::class)->assertClean($rawMessage);
$customer = Customer::find($customerId);
if (! $customer || ! $customer->mobile) {
throw new UnprocessableEntityHttpException('مشتری یا شماره موبایل یافت نشد.');
}
$cfg = app(ConfigService::class);
$appName = (string) ($cfg->get('name_fa', '') ?: '');
$appUrl = (string) ($cfg->get('app_url', '') ?: '');
$message = str_replace(
['%name%', '%نام%', '%app_name%', '%نام_اپ%', '%app_url%', '%لینک_اپ%', '%لینک%'],
[
(string) $customer->name,
(string) $customer->name,
$appName,
$appName,
$appUrl,
$appUrl,
$appUrl,
],
$rawMessage
);
$this->send($customer->mobile, $message);
return response()->json(['ok' => true]);
}
public function getFunctionDescriptions()
{
+20 -20
View File
@@ -142,7 +142,7 @@ class WalletController extends Controller
//send sms to users and customer
$status = $data['value'] > 0 ?" شارژ شد ": " کسر شد ";
if($this->Config('charge_notif') == "true"){
if (self::isSmsNotifEnabled('charge_notif')) {
$message = 'کیف پول کاربر ' . $customer->name . ' به مقدار ' . self::formatSmsRialAmount($data['value']) . " ریال در تاریخ " . verta()->format('Y/n/j H:i:s') .$status . "بابت" . "\n"
. $data['note']
. "\n"
@@ -150,13 +150,13 @@ class WalletController extends Controller
User::where('send_sms', 1)->get()->each(function ($admin) use ($message, $data) {
$this->send($admin->mobile, $message);
});
}
$message = 'کیف پول شما به اندازه ' . self::formatSmsRialAmount($data['value']) . " ریال در تاریخ " . verta()->format('Y/n/j H:i:s') .$status . "بابت" . "\n"
. $data['note']
. "\n"
. $this->Config('name_fa');
$this->Send($customer->mobile, $message);
$message = 'کیف پول شما به اندازه ' . self::formatSmsRialAmount($data['value']) . " ریال در تاریخ " . verta()->format('Y/n/j H:i:s') .$status . "بابت" . "\n"
. $data['note']
. "\n"
. $this->Config('name_fa');
$this->Send($customer->mobile, $message);
}
$this->broadcastCustomerWalletAssets($customer);
return response()->json(true);
@@ -215,7 +215,7 @@ class WalletController extends Controller
//send sms to users and customer
$status = $data['value'] > 0 ?" شارژ شد ": " کسر شد ";
$weightUnit = self::tradeWeightUnit();
if($this->Config('charge_notif') == "true"){
if (self::isSmsNotifEnabled('charge_notif')) {
$message = 'کیف پول کاربر ' . $customer->name . ' به مقدار ' . self::formatSmsGoldWeight($data['value']) . " {$weightUnit} در تاریخ " . verta()->format('Y/n/j H:i:s') .$status . "بابت" . "\n"
. $data['note']
. "\n"
@@ -223,12 +223,12 @@ class WalletController extends Controller
User::where('send_sms', 1)->get()->each(function ($admin) use ($message, $data) {
$this->send($admin->mobile, $message);
});
}
$message = 'کیف پول شما به اندازه ' . self::formatSmsGoldWeight($data['value']) . " {$weightUnit} در تاریخ " . verta()->format('Y/n/j H:i:s') . $status . " بابت" . "\n"
. $data['note']
. $this->Config('name_fa');
$this->Send($customer->mobile, $message);
$message = 'کیف پول شما به اندازه ' . self::formatSmsGoldWeight($data['value']) . " {$weightUnit} در تاریخ " . verta()->format('Y/n/j H:i:s') . $status . " بابت" . "\n"
. $data['note']
. $this->Config('name_fa');
$this->Send($customer->mobile, $message);
}
$this->broadcastCustomerWalletAssets($customer);
return response()->json(true);
@@ -364,7 +364,7 @@ class WalletController extends Controller
$status = $deposit ? ' شارژ شد ' : ' کسر شد ';
$formatted = self::formatSmsGoldWeight($data['value']);
if ($this->Config('charge_notif') == 'true') {
if (self::isSmsNotifEnabled('charge_notif')) {
$message = 'کیف پول کاربر ' . $customer->name . ' به مقدار ' . $formatted . ' ' . $unitLabel . ' در تاریخ ' . verta()->format('Y/n/j H:i:s') . $status . 'بابت' . "\n"
. ($data['note'] ?? '')
. "\n"
@@ -372,13 +372,13 @@ class WalletController extends Controller
User::where('send_sms', 1)->get()->each(function ($admin) use ($message) {
$this->send($admin->mobile, $message);
});
}
$message = 'کیف پول شما به اندازه ' . $formatted . ' ' . $unitLabel . ' در تاریخ ' . verta()->format('Y/n/j H:i:s') . $status . ' بابت' . "\n"
. ($data['note'] ?? '')
. "\n"
. $this->Config('name_fa');
$this->Send($customer->mobile, $message);
$message = 'کیف پول شما به اندازه ' . $formatted . ' ' . $unitLabel . ' در تاریخ ' . verta()->format('Y/n/j H:i:s') . $status . ' بابت' . "\n"
. ($data['note'] ?? '')
. "\n"
. $this->Config('name_fa');
$this->Send($customer->mobile, $message);
}
$this->broadcastCustomerWalletAssets($customer);
return response()->json(true);
+14 -9
View File
@@ -104,7 +104,9 @@ class AuthController extends Controller
$user->token_sms = $rand;
$user->save();
$this->SendMessage($mobile, 'رمز عبور یکبار مصرف شما جهت ورود به اپلیکشن ' . $this->Config('name_fa') . ' ' . $rand . ' می باشد' . PHP_EOL . "@$subDomain" . " #" . $rand,true ,"sms");
if (self::isSmsNotifEnabled('sms_notif_login_otp')) {
$this->SendMessage($mobile, 'رمز عبور یکبار مصرف شما جهت ورود به اپلیکشن ' . $this->Config('name_fa') . ' ' . $rand . ' می باشد' . PHP_EOL . "@$subDomain" . " #" . $rand,true ,"sms");
}
return $user->id;
}
@@ -151,10 +153,9 @@ class AuthController extends Controller
$data['referral_to_id'] = $data['referral_id'];
}
$data['name'] = $data['fname'] . ' ' . $data['lname'];
// فقط ورود به اپ — نه اجازهٔ معامله؛ معامله با is_legal جداست
$data['active'] = $cfg->getBool('auto_active_customer', false);
if (isset($data['type']) && $data['type'] == 2) {
$data['active'] = true;
}
$data['is_legal'] = (int) ($data['is_legal'] ?? 0);
$cnt = Cnt::where('key', 'gram')->first();
if ($cnt !== null && trim((string) $cnt->value) !== '') {
$data['gram'] = (int) $cnt->value;
@@ -201,7 +202,7 @@ class AuthController extends Controller
if ($cfg->getBool('register_referral_sms_to_referrer', false)) {
$messageRef = "{$data['name']} با کد معرف شما ثبت نام کرد.\nبا اولین خرید او پاداش دریافت میکنید.\n" . $this->Config('name_fa');
$this->Send($referrer->mobile, $messageRef);
} else {
} elseif (self::isSmsNotifEnabled('sms_notif_register_admin')) {
$adminMessage = "با معرفی {$referrer->name}، کاربر {$data['name']} در اپ {$this->Config('name_fa')} ثبت نام کرده و منتظر تایید شماست.";
User::where('send_sms', 1)->get()->each(function ($admin) use ($adminMessage) {
$this->send($admin->mobile, $adminMessage);
@@ -213,9 +214,11 @@ class AuthController extends Controller
$message = $customer->is_legal === 1
? 'احرازهویت برای ' . $customer->name . ' با کد ' . $customer->id . ' انجام شد.'
: 'احرازهویت برای ' . $customer->name . ' با کد ' . $customer->id . ' تأیید نشد لطفا از پنل ادمین اقدام فرمایید.';
User::where('send_sms', 1)->get()->each(function ($admin) use ($message) {
$this->SendMessage($admin->mobile, $message);
});
if (self::isSmsNotifEnabled('sms_notif_jibit_admin')) {
User::where('send_sms', 1)->get()->each(function ($admin) use ($message) {
$this->SendMessage($admin->mobile, $message);
});
}
}
$message = "{$data['name']} عزیز، اکانت شما در پلتفرم {$this->Config('name_fa')} ایجاد شد.";
@@ -227,7 +230,9 @@ class AuthController extends Controller
}
}
$message .= "\nنام کاربری: {$data['mobile']}\nورود به نرم افزار: {$this->Config('app_url')}";
$this->Send($data['mobile'], $message);
if (self::isSmsNotifEnabled('sms_notif_register_customer')) {
$this->Send($data['mobile'], $message);
}
return response()->json($customer);
}
+42 -26
View File
@@ -103,6 +103,23 @@ class Controller extends BaseController
// }
}
/** آیا این نوع پیامک اعلان روشن است؟ پیش‌فرض true اگر کلید در settings نباشد. */
public static function isSmsNotifEnabled(string $key, bool $default = true): bool
{
return app(ConfigService::class)->isSmsNotifEnabled($key, $default);
}
/**
* خرید/فروش فقط بعد از احراز هویت (is_legal ≠ 0).
* جدا از active / auto_active_customer که فقط ورود به اپ را کنترل می‌کنند.
*/
public static function assertCustomerIdentityVerified(?Customer $customer): void
{
if (!$customer || (int) ($customer->is_legal ?? 0) === 0) {
throw new UnprocessableEntityHttpException('لطفا ابتدا فرآیند احراز هویت خود را تکمیل کنید');
}
}
public static function SendMessage($to, $msg ,$is_send = false,$force_method ='null')
{
$credentials = [
@@ -111,7 +128,6 @@ class Controller extends BaseController
],
"bale" => [
"token" => self::Config('bale_bot_token')
// "token" => Setting::where('key', 'bale_bot_token')->where('is_active', true)->first()->value ?? null
],
"sms" => [
'user_name' => 'ysms1362',
@@ -120,8 +136,9 @@ class Controller extends BaseController
],
];
$platforms = [];
$send_sms = true;
$user = User::where('mobile', $to)->first() ?: Customer::where('mobile', $to)->first();
// بله و پیامک مستقل‌اند — موفقیت یکی، دیگری را قطع نمی‌کند
if ($user) {
$baleToken = trim((string) ($credentials['bale']['token'] ?? ''));
$baleChatId = trim((string) ($user->bale ?? ''));
@@ -137,44 +154,43 @@ class Controller extends BaseController
$balePayload = $baleResponse->json();
if ($baleResponse->successful() && ($balePayload['ok'] ?? false) === true) {
$platforms[] = "bale:{$baleChatId}";
$send_sms = false;
} else {
$platforms[] = "bale_failed:{$baleChatId}";
}
} catch (\Throwable $e) {
report($e);
$platforms[] = "bale_error:{$baleChatId}";
}
}
}
//SMS
if ($send_sms or $force_method=="sms") {
try {
$gateway = app(SmsGatewayService::class);
try {
$gateway = app(SmsGatewayService::class);
if ($force_method == "sms") {
$smsResult = $gateway->sendOrThrow($to, trim($msg), 'notification');
} else {
$smsResult = $gateway->send($to, trim($msg), 'notification');
}
if ($smsResult->blocked) {
$platforms[] = "blocked:{$to}";
} elseif ($smsResult->sent && $smsResult->provider) {
$platforms[] = "{$smsResult->provider}:{$to}";
} else {
$platforms[] = "sms_failed:{$to}";
}
} catch (SmsBlockedException $e) {
throw $e;
} catch (\Throwable $e) {
report($e);
$platforms[] = "sms_error:{$to}";
if ($force_method == "sms") {
$smsResult = $gateway->sendOrThrow($to, trim($msg), 'notification');
} else {
$smsResult = $gateway->send($to, trim($msg), 'notification');
}
if ($smsResult->blocked) {
$platforms[] = "blocked:{$to}";
} elseif ($smsResult->sent && $smsResult->provider) {
$platforms[] = "{$smsResult->provider}:{$to}";
} else {
$platforms[] = "sms_failed:{$to}";
}
} catch (SmsBlockedException $e) {
throw $e;
} catch (\Throwable $e) {
report($e);
$platforms[] = "sms_error:{$to}";
}
Message::create([
'sms' => $msg,
'receiver' => $to,
'platforms' => implode(', ', $platforms), // ذخیره لیست سامانه‌ها
'platforms' => implode(', ', $platforms),
]);
}
public static function SendTelegram($to , $msg)
@@ -136,8 +136,7 @@ class CartController extends Controller
$data = $request->json()->all();
$user= auth()->user();
if ($user->is_legal == 0 || !$user) {
return response()->json(['massage' => 'شما باید اول خود را احراز هویت کنید'], 422);
throw new UnprocessableEntityHttpException('لطفا ابتدا فرآیند احراز هویت خود را تکمیل کنید');
}
// $data->validate([
@@ -18,9 +18,7 @@ class OrderController extends Controller
public function store(Request $request)
{
$user = auth()->user();
if ($user->is_legal == 0 || $user->id == 4) {
return response()->json(['massage' => 'لطفا ابتدا فرآیند احراز هویت خود را تکمیل کنید'], 422);
}
self::assertCustomerIdentityVerified($user instanceof Customer ? $user : null);
if (!auth('customer')->user()->trade_active) {
throw new UnprocessableEntityHttpException('امکان سفارش برای شما غیرفعال است.');
@@ -419,7 +419,9 @@ class WalletController extends Controller
}
}
User::where('send_sms', 1)->get()->each(function ($admin) use ($message) {
$this->Send($admin->mobile, $message . ' ' . now()->format('H:i:s'));
if (self::isSmsNotifEnabled('sms_notif_withdraw_admin')) {
$this->Send($admin->mobile, $message . ' ' . now()->format('H:i:s'));
}
});
return response()->json($Withdraw);
@@ -583,10 +585,12 @@ class WalletController extends Controller
$otp = rand(1000, 9999);
$customer->token_sms = $otp;
$customer->save();
$this->Send(
$customer->mobile,
'رمز عبور یکبار مصرف شما جهت برداشت پول از اپلیکیشن ' . $this->Config('name_fa') . ' می باشد: ' . $otp
);
if (self::isSmsNotifEnabled('sms_notif_withdraw_otp')) {
$this->Send(
$customer->mobile,
'رمز عبور یکبار مصرف شما جهت برداشت پول از اپلیکیشن ' . $this->Config('name_fa') . ' می باشد: ' . $otp
);
}
return response()->json(true);
}
@@ -208,7 +208,9 @@ class FinanceController extends Controller
// Getting admin mobile numbers and sending the SMS
User::where('active', 1)->get()->each(function($admin) use ($message) {
$this->Send($admin->mobile, $message);
if (self::isSmsNotifEnabled('sms_notif_gateway_charge_admin')) {
$this->Send($admin->mobile, $message);
}
});
@@ -97,9 +97,11 @@ class BankAccountController extends SuperController
} else {
$message = "احرازهویت برای شماره کارت کاربر " . $user->name . " توسط جیبیت انجام نشد. لطفا از پنل ادمین اقدام کنید. ";
User::where('send_sms', 1)->get()->each(function ($admin) use ($message) {
$this->SendMessage($admin->mobile, $message);
});
if (self::isSmsNotifEnabled('sms_notif_bank_card_admin')) {
User::where('send_sms', 1)->get()->each(function ($admin) use ($message) {
$this->SendMessage($admin->mobile, $message);
});
}
$BA = BankAccount::create([
'customer_id' => $user->id,
'cart_number' => $request->cart_number,
@@ -115,9 +117,11 @@ class BankAccountController extends SuperController
$message = "کارت جدیدی برای $customer->name ساخته شد منتظر تایید شما هستیم.";
$message .= $this->Config('name_fa');
User::where('active', 1) ->where('send_sms', 1)->get()->each(function($admin) use ($message) {
$this->Send($admin->mobile, $message);
});
if (self::isSmsNotifEnabled('sms_notif_bank_card_admin')) {
User::where('active', 1)->where('send_sms', 1)->get()->each(function ($admin) use ($message) {
$this->Send($admin->mobile, $message);
});
}
$data = $request->only(['account_number', 'bank_name', 'cart_number', 'shaba_number', 'customer_id']);
BankAccount::create($data);
return response()->json($data);
@@ -58,6 +58,7 @@ class SingleOrderController extends Controller
if (!$customer || !$customer->trade_active) {
throw new UnprocessableEntityHttpException('امکان سفارش برای شما غیرفعال است.');
}
self::assertCustomerIdentityVerified($customer);
$data['customer_id'] = auth('customer')->id();
@@ -778,9 +779,11 @@ class SingleOrderController extends Controller
$message = "کاربر {$customer->name} با شماره موبایل {$customer->mobile} اقدام به $transactionType {$subjectTitle} به مقدار " .
"{$amount} گرم به مبلغ " . number_format($totalPrice) .
" ریال کرد. با تشکر، $companyName";
User::where('send_sms', 1)->get()->each(function ($admin) use ($message, $data, $transactionType, $companyName) {
$this->send($admin->mobile, $message);
});
if (self::isSmsNotifEnabled('sms_notif_order_admin')) {
User::where('send_sms', 1)->get()->each(function ($admin) use ($message) {
$this->send($admin->mobile, $message);
});
}
$wallet = Wallet::where('owner', $data['customer_id'])
->whereNull('fund_id')
->whereNull('product_id')
@@ -795,8 +798,9 @@ class SingleOrderController extends Controller
$this->Config('app_url');
// ارسال SMS به مشتری
$this->send($customer->mobile, $customerMessage);
if (self::isSmsNotifEnabled('sms_notif_order_customer')) {
$this->send($customer->mobile, $customerMessage);
}
}
private function assertProviderOrderAccepted(array &$data): void
@@ -73,7 +73,9 @@ class ReportController extends Controller
if ($PriceTrigger->action == 'email') {
Mail::to("$customer->email")->send(new YourMailableClass($message, '', '', '', ''));
} elseif ($PriceTrigger->action == 'sms') {
$this->send($customer->mobile, $message);
if (self::isSmsNotifEnabled('sms_notif_price_trigger')) {
$this->send($customer->mobile, $message);
}
}
$PriceTrigger->is_active = false;
$PriceTrigger->triggered_at = Carbon::now();
@@ -163,7 +163,9 @@ class RequestsController extends Controller
" ریال کرد. با تشکر، $companyName";
}
User::where('send_sms', 1)->get()->each(function ($admin) use ($message, $data, $transactionType, $companyName) {
$this->send($admin->mobile, $message);
if (self::isSmsNotifEnabled('sms_notif_fund_withdraw_admin')) {
$this->send($admin->mobile, $message);
}
});
// User::whereNotNull('telegram')->get()->each(function ($admin) use ($message, $data, $transactionType, $companyName) {
// $this->SendTelegram($admin->telegram, $message);
@@ -214,8 +216,9 @@ class RequestsController extends Controller
// "\nمبلغ کل: " . number_format($data['total_price']) . "\n\nموجودی طلایی: {$wallet->gold}\n" .
// "مانده ریالی: " . number_format($wallet->cash) . "\n" . $this->Config('app_url');
// ارسال SMS به مشتری
$this->send($customer->mobile, $customerMessage);
if (self::isSmsNotifEnabled('sms_notif_fund_withdraw_customer')) {
$this->send($customer->mobile, $customerMessage);
}
}
}
@@ -175,7 +175,9 @@ class paypingController extends Controller
. ' حساب خود را به مقدار ' . number_format($Withdraw->cash) . ' ریال شارژ کرد. با تشکر، ' . $this->Config('name_fa');
User::where('send_sms', 1)->get()->each(function ($admin) use ($message) {
$this->Send($admin->mobile, $message);
if (self::isSmsNotifEnabled('sms_notif_gateway_charge_admin')) {
$this->Send($admin->mobile, $message);
}
});
return view('showTransactionReport', compact('Withdraw', 'app_url'));
@@ -249,7 +251,9 @@ class paypingController extends Controller
. ' حساب خود را به مقدار ' . number_format($Withdraw->cash) . ' ریال شارژ کرد. با تشکر، ' . $this->Config('name_fa');
User::where('send_sms', 1)->get()->each(function ($admin) use ($message) {
$this->Send($admin->mobile, $message);
if (self::isSmsNotifEnabled('sms_notif_gateway_charge_admin')) {
$this->Send($admin->mobile, $message);
}
});
return view('showTransactionReport', compact('Withdraw', 'app_url'));