Files
boursecu_server/app/Http/Controllers/Controller.php
T
2026-06-16 20:38:48 +03:30

527 lines
18 KiB
PHP

<?php
namespace App\Http\Controllers;
use App\Models\Cnt;
use App\Models\User;
use App\Models\Customer;
use App\Models\Setting;
use App\Models\Message;
use App\Services\ConfigService;
use Illuminate\Foundation\Auth\Access\AuthorizesRequests;
use Illuminate\Foundation\Bus\DispatchesJobs;
use Illuminate\Foundation\Validation\ValidatesRequests;
use Illuminate\Routing\Controller as BaseController;
use Illuminate\Support\Facades\Storage;
use Illuminate\Support\Arr;
use Illuminate\Support\Facades\Http;
use Symfony\Component\HttpKernel\Exception\UnprocessableEntityHttpException;
class Controller extends BaseController
{
use AuthorizesRequests, DispatchesJobs, ValidatesRequests;
public function resultCreate($id){
return response()->json(['id'=>$id] , 201);
}
/**
* add paginate to list
* @param array $list
* @param object $table
* @return array mixed
*/
protected function addPaginate($table,$list){
$list = $this->addLimitPage($list);
$list['count'] = $table->count();
$list['rows'] = $table->offset( $list['page']*$list['limit'])
->limit($list['limit'])
->get();
$list['page'] = (int)$list['page'];
$list['limit'] = (int)$list['limit'];
return $list;
}
/**
* add page and limit to list
* @param $list
* @return mixed
*/
protected function addLimitPage($list){
if (!isset($list['page'])){
$list['page'] = 0;
}
if (!isset($list['limit'])){
$list['limit'] = 5;
}
if ($list['limit']>50){
$list['limit'] = 50;
}
return $list;
}
/** مبلغ ریالی در پیامک — جداکننده هزارگان */
public static function formatSmsRialAmount(float|int|string $value): string
{
return number_format(abs((float) $value), 0, '.', ',');
}
/** وزن طلا در پیامک — تا ۳ رقم اعشار، بدون گرد کردن به صفر برای زیر ۱ گرم */
public static function formatSmsGoldWeight(float|int|string $value): string
{
$formatted = rtrim(rtrim(number_format(abs((float) $value), 3, '.', ''), '0'), '.');
return $formatted !== '' ? $formatted : '0';
}
public static function Send($to , $msg, $is_customer = true)
{
$r = self::SendMessage($to , $msg, $is_customer);
// if ($r == 200){
// Sms::set($to,$msg , $is_customer);
// }
}
public static function SendMessage($to, $msg ,$is_send = false,$force_method ='null')
{
$config = app(ConfigService::class);
// $config = config('message', false);
$credentials = [
"telegram" => [
"token" => self::Config('telegram_bot_token')
],
"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',
'password' => 'tL4w0PfNy2()',
'sender' => '3000164545',
],
];
$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 ?? ''));
if ($baleToken !== '' && $baleChatId !== '') {
try {
$baleResponse = Http::withoutVerifying()->get(
"https://tapi.bale.ai/bot{$baleToken}/sendMessage",
[
'chat_id' => $baleChatId,
'text' => "جناب {$user->name} \n{$msg}",
]
);
$balePayload = $baleResponse->json();
if ($baleResponse->successful() && ($balePayload['ok'] ?? false) === true) {
$platforms[] = "bale:{$baleChatId}";
$send_sms = false;
}
} catch (\Throwable $e) {
report($e);
}
}
}
//SMS
if ($send_sms or $force_method=="sms") {
/* $endpoint = "https://www.0098sms.com/sendsmslink.aspx";
$response = Http::withoutVerifying()->get($endpoint, [
'FROM' => $credentials['sms']['sender'],
'TO' => $to,
'TEXT' => trim($msg),
'USERNAME' => $credentials['sms']['user_name'],
'PASSWORD' => $credentials['sms']['password'],
'DOMAIN' => '0098',
]);
$platforms[] = "0098:{$to}";*/
$response = Http::timeout(15)
->withHeaders([
'Content-Type' => 'application/json',
'secret_key' => 'f21debfb-83ac-4624-a2f4-f08375043181',
])
->withOptions([
'curl' => [
\CURLOPT_IPRESOLVE => \CURL_IPRESOLVE_V4,
]
])
->post('http://185.231.112.101/api/createsms', [
'phone' => $to,
'host' => $config->Config('name_fa') ?? gethostname(),
'text' => trim($msg),
'platform' => 'rayegansms',
]);
$platforms[] = $response->successful()
? "rayegansms:{$to}"
: "rayegansms_failed:{$to}:{$response->status()}";
}
Message::create([
'sms' => $msg,
'receiver' => $to,
'platforms' => implode(', ', $platforms), // ذخیره لیست سامانه‌ها
]);
}
public static function SendTelegram($to , $msg)
{
// "chatId" => 504951108,
// "chatId" => 5870340227, fathi
$response = Http::withHeaders([
'x-secret-key' => 'PvQM36mgk2FUELHjcm4YG49Nu56uQxot',
])->post('https://tele.ygram.ir/send-message', ["message" => $msg, "chatId" => $to, "botToken" => 'Paramisgold_bot']);
return $response->json();
}
public static function Config($name)
{
$row = Setting::where('key', $name)->first();
if ($row && $row->is_active && $row->value !== null && $row->value !== '') {
return $row->value;
}
return false;
}
protected static function metalTypeSettingValue(): ?string
{
$metalType = Setting::where('key', 'metal_type')->value('value');
if ($metalType === null) {
return null;
}
$metalType = trim((string) $metalType);
return $metalType !== '' ? $metalType : null;
}
/** برچسب موجودی کیف اصلی: مقدار setting یا «طلا» */
public static function metalTypeLabel(): string
{
return self::metalTypeSettingValue() ?? 'طلا';
}
/** برچسب معاملات آبشده: مقدار setting یا «آبشده» */
public static function meltedGoldLabel(): string
{
return self::metalTypeSettingValue() ?? 'آبشده';
}
public static function cashTransactionTitles(): array
{
return ['برداشت وجه نقد', 'واریز وجه نقد'];
}
public static function legacyMeltedTransactionTitles(): array
{
return [
'واریز طلای ابشده',
'واریز طلای آبشده',
'برداشت طلای ابشده',
'برداشت طلای آبشده',
];
}
protected static function metalLabelVariants(): array
{
return array_values(array_unique([
self::meltedGoldLabel(),
self::metalTypeLabel(),
'طلا',
'آبشده',
]));
}
public static function genericMetalTransactionTitles(): array
{
$titles = self::legacyMeltedTransactionTitles();
foreach (self::metalLabelVariants() as $label) {
$titles[] = "موجودی {$label}";
$titles[] = "برداشت {$label}";
$titles[] = "خرید {$label}";
$titles[] = "فروش {$label}";
}
return array_values(array_unique($titles));
}
public static function isCashTransactionTitle(?string $title): bool
{
return $title !== null && in_array($title, self::cashTransactionTitles(), true);
}
public static function isGenericMetalTransactionTitle(?string $title): bool
{
if ($title === null || self::isCashTransactionTitle($title)) {
return false;
}
return in_array($title, self::genericMetalTransactionTitles(), true);
}
public static function productBuyTitle(string $productTitle): string
{
return 'خرید ' . $productTitle;
}
public static function productSellTitle(string $productTitle): string
{
return 'فروش ' . $productTitle;
}
public static function mainMetalBuyTitle(): string
{
return self::productBuyTitle(self::metalTypeLabel());
}
public static function mainMetalSellTitle(): string
{
return self::productSellTitle(self::metalTypeLabel());
}
/**
* آیا محصول به کیف اصلی متصل است؟ (setting: main_wallet_products)
* موجودی این محصولات = gold کیف اصلی؛ تراکنش‌هایشان روی کیف اصلی می‌نشیند.
*/
public static function isMainWalletProduct(?int $productId): bool
{
if (!$productId) {
return false;
}
return app(ConfigService::class)->isMainWalletProduct((int) $productId);
}
/**
* شناسه کیف مؤثر برای تراکنش محصول.
* محصولات متصل به کیف اصلی → null (کیف اصلی)؛ بقیه → کیف محصول خودشان.
*/
public static function effectiveProductWalletId(?int $productId): ?int
{
return self::isMainWalletProduct($productId) ? null : $productId;
}
/** واحد وزن معاملات فلز — از ستینگ unit؛ پیش‌فرض گرم */
public static function tradeWeightUnit(): string
{
return self::resolveTradeWeightUnit(
Setting::where('key', 'unit')->value('value')
);
}
public static function resolveTradeWeightUnit(?string $value): string
{
$unit = trim((string) $value);
if ($unit === 'کیلوگرم' || $unit === 'kilogram' || $unit === 'kg') {
return 'کیلوگرم';
}
return 'گرم';
}
public static function weightToGrams(float $value, ?string $fromUnit = null): float
{
$from = $fromUnit ?? self::tradeWeightUnit();
return $from === 'کیلوگرم' ? $value * 1000 : $value;
}
public static function gramsToTradeUnit(float $grams): float
{
return self::tradeWeightUnit() === 'کیلوگرم' ? $grams / 1000 : $grams;
}
public static function productStorageWeightUnit($product): string
{
$unit = trim((string) (is_object($product) ? ($product->unit ?? '') : ($product['unit'] ?? '')));
if (self::isWeightBasedProductUnit($unit)) {
return $unit;
}
return 'گرم';
}
public static function productLineWeightToGrams($product, $quantity): float
{
$groupType = is_object($product) ? ($product->group_type ?? '') : ($product['group_type'] ?? '');
if ((string) $groupType === 'سکه') {
return 0.0;
}
$qty = (float) $quantity;
$unit = trim((string) (is_object($product) ? ($product->unit ?? '') : ($product['unit'] ?? '')));
$amount = (float) (is_object($product) ? ($product->amount ?? 0) : ($product['amount'] ?? 0));
if (self::isWeightBasedProductUnit($unit)) {
return self::weightToGrams($qty, $unit);
}
return self::weightToGrams($amount * $qty, self::productStorageWeightUnit($product));
}
public static function isWeightBasedProductUnit(?string $unit): bool
{
$unit = trim((string) $unit);
return in_array($unit, ['کیلوگرم', 'گرم'], true);
}
public static function meltedGoldBuyTitle(): string
{
return 'خرید ' . self::meltedGoldLabel();
}
public static function meltedGoldSellTitle(): string
{
return 'فروش ' . self::meltedGoldLabel();
}
public static function meltedGoldDepositTitle(): string
{
return 'موجودی ' . self::meltedGoldLabel();
}
public static function meltedGoldWithdrawTitle(): string
{
return 'برداشت ' . self::meltedGoldLabel();
}
public static function isCountBasedProduct(?array $product): bool
{
if (!$product) {
return false;
}
if (self::isWeightBasedProductUnit($product['unit'] ?? null)) {
return false;
}
if (isset($product['direct_price']) && (int) $product['direct_price'] !== 0) {
return true;
}
$group = trim((string) ($product['group_type'] ?? ''));
if (in_array($group, ['مفتول مس'], true)) {
return true;
}
return in_array($group, ['سکه', 'گوی', 'مکعب', 'شمش', 'سکه پارسیان'], true);
}
public static function productQuantityUnit(?array $product): string
{
$unit = trim((string) ($product['unit'] ?? ''));
if ($unit !== '') {
return $unit;
}
if (self::isCountBasedProduct($product)) {
return 'عدد';
}
return 'گرم';
}
/** مطابق ادمین: وزن «دارد» => amount != 1 ؛ «ندارد» => amount = 1 */
public static function hasProductUnitWeight(?array $product): bool
{
if (!$product || !isset($product['amount'])) {
return false;
}
$amount = (float) $product['amount'];
return $amount > 0 && $amount !== 1.0;
}
public function jibitNcode($nationalCode, $mobile)
{
$counter = Cnt::where('key', 'jibit_counter')->first();
if (empty($counter)) {
$counter = new Cnt();
$counter->key = 'jibit_counter';
$counter->value = 0;
$counter->save();
}
$apiData['refresh'] = Http::withoutVerifying()->withToken(Storage::get('refreshTokenGibit'))
->post('https://napi.jibit.ir/ide/v1/tokens/generate', [
'apiKey' => 'J5WxrPxPOg',
'secretKey' => '7dgeE70xQXsQL7r36j3wif6X9',
])->json();
Storage::put('accessTokenGibit', $apiData['refresh']['accessToken']);
$response = Http::withoutVerifying()->withToken(Storage::get('accessTokenGibit'))
->get("https://napi.jibit.ir/ide/v1/services/matching?mobileNumber=$mobile&nationalCode=$nationalCode")
->json();
if ((isset($response['code'])) && $response['code'] == 'forbidden') {
$refreshToken = Http::withoutVerifying()->withToken(Storage::get('refreshTokenGibit'))
->post('https://napi.jibit.ir/ide/v1/tokens/generate', [
'apiKey' => 'J5WxrPxPOg',
'secretKey' => '7dgeE70xQXsQL7r36j3wif6X9',
])->json();
Storage::put('accessTokenGibit', $refreshToken['accessToken']);
Storage::put('refreshTokenGibit', $refreshToken['refreshToken']);
$response = Http::withoutVerifying()->withToken(Storage::get('accessTokenGibit'))
->get("https://napi.jibit.ir/ide/v1/services/matching?mobileNumber=$mobile&nationalCode=$nationalCode")
->json();
}
$counter->value = (int) $counter->value + 1;
$counter->save();
return $response;
}
public static function jibit($method, $p1 = null, $p2 = null, $p3 = null)
{
$counter = Cnt::where('key', 'jibit_counter')->first();
if(empty($counter)){
$counter = new Cnt();
$counter->key = "jibit_counter";
$counter->value = 0;
$counter->save();
}
$apiData['refresh'] = Http::withoutVerifying()->withoutVerifying()->withToken(Storage::get('refreshTokenGibit'))
->post("https://napi.jibit.ir/ide/v1/tokens/generate", ['apiKey' => "J5WxrPxPOg", 'secretKey' => "7dgeE70xQXsQL7r36j3wif6X9",])->json();
Storage::put('accessTokenGibit', $apiData['refresh']['accessToken']);
if (!Storage::exists('accessTokenGibit') || !Storage::exists('refreshTokenGibit')) {
Storage::put('accessTokenGibit', 'توکن اولیه');
Storage::put('refreshTokenGibit', 'توکن رفرش اولیه');
}
$apiData['cartMatching'] = Http::withoutVerifying()->withToken(Storage::get('accessTokenGibit'))->get("https://napi.jibit.ir/ide/v1/services/matching?cardNumber=$p1&nationalCode=$p2&birthDate=$p3")->json();
if ((isset($apiData['cartMatching']['code'])) and $apiData['cartMatching']['code'] == "forbidden") {
$apiData['refresh'] = Http::withoutVerifying()->withToken(Storage::get('refreshTokenGibit'))
->post("https://napi.jibit.ir/ide/v1/tokens/generate", ['apiKey' => "J5WxrPxPOg", 'secretKey' => "7dgeE70xQXsQL7r36j3wif6X9",])->json();
Storage::put('accessTokenGibit', $apiData['refresh']['accessToken']);
Storage::put('refreshTokenGibit', $apiData['refresh']['refreshToken']);
$apiData['cartMatching'] = Http::withoutVerifying()->withToken(Storage::get('accessTokenGibit'))->get("https://napi.jibit.ir/ide/v1/services/matching?cardNumber=$p1&nationalCode=$p2&birthDate=$p3")->json();
}
//update jibit counter
$counter->value = (int)$counter->value + 1;
$counter->save();
if (isset( $apiData['cartMatching']['matched']) and $apiData['cartMatching']['matched'] == true) {
$apiData['cartData'] = Http::withoutVerifying()->withToken(Storage::get('accessTokenGibit'))->get("https://napi.jibit.ir/ide/v1/cards?number=$p1&iban=true")->json();
return $apiData;
}elseif(isset( $apiData['cartMatching']['matched']) and $apiData['cartMatching']['matched'] == false){
return $apiData;
} else {
throw new UnprocessableEntityHttpException($apiData['cartMatching']['message']);
}
}
}