whereDate('date_at', '<=', date("Y-m-d")) ->whereDate('date_at', '>', Carbon::now()->subDays(30)->format("Y-m-d")) ->get()->toArray(); $a = []; foreach ($candle as $c) { $create['date'] = $c["date_at"]; unset($c["date_at"]); $create['candle'] = array_values($c); $a[] = array_values($create); } return response()->json($a); } public function updatePrise() { $difference = (float) (Setting::where('key', 'fee_single')->value('value') ?? config('fee.single', 0)); $lastPrice = Price::latest()->first(); if (!$lastPrice) { return response()->json(); } $PriceTriggers = PriceTrigger::where("is_active", true)->get(); foreach ($PriceTriggers as $PriceTrigger) { $priseGold = $PriceTrigger->dirction == 1 ? $lastPrice->price - $difference : ($PriceTrigger->dirction == 2 ? $lastPrice->price + $difference : $lastPrice->price); if (eval('return $priseGold ' . $PriceTrigger->price_condition . ' $PriceTrigger->target_price;')) { $customer = Customer::find($PriceTrigger->customer_id); if (!$customer) { continue; } $message = "قیمت طلا به " . number_format($priseGold, -1) . " در هر گرم رسید\n" .$this->Config('name_fa'); if ($PriceTrigger->action == 'email') { Mail::to("$customer->email")->send(new YourMailableClass($message, '', '', '', '')); } elseif ($PriceTrigger->action == 'sms') { $this->send($customer->mobile, $message); } $PriceTrigger->is_active = false; $PriceTrigger->triggered_at = Carbon::now(); $PriceTrigger->save(); } } return response()->json(); } public function upDownPrice() { return $this->buildUpDownPrices(); } protected function buildUpDownPrices(): array { $config = app(ConfigService::class); $diffBuy = $config->displayBuySpreadRial(); $diffSell = $config->displaySellSpreadRial(); $extremes = $config->resolvedDailyBaseExtremes(); $up = $extremes['up']; $down = $extremes['down']; if ($up > 0 && $down > 0) { return [ 'sell' => max(0, (int) ceil($down - $diffSell)), 'buy' => (int) ceil($up + $diffBuy), ]; } if (!$config->getBool('show_last_price', false)) { return ['sell' => 0, 'buy' => 0]; } $price = Price::orderByDesc('id')->first(); $priceValue = $price ? (float) $price->price : 0.0; if ($priceValue <= 0) { return ['sell' => 0, 'buy' => 0]; } return [ 'sell' => max(0, (int) ceil($priceValue - $diffSell)), 'buy' => (int) ceil($priceValue + $diffBuy), ]; } protected function appendUpPrices(array $payload, bool $saveFullCache = false): array { $payload['up'] = $this->buildUpDownPrices(); $payload['last_historical'] = app(ProductDisplayPriceService::class)->resolveHistoricalBasePrice(); app(ProductDisplayPriceService::class)->cacheLivePricePayload($payload); if ($saveFullCache || request()->boolean('force_refresh')) { $cache = app(LivePriceCacheService::class); $cache->markTick(); return $cache->put($payload); } return $payload; } public function lastPrice(Request $request) { $config = app(ConfigService::class); $cache = app(LivePriceCacheService::class); $forceRefresh = $request->boolean('force_refresh'); if (! $forceRefresh) { $cached = $cache->get(); if ($cached !== null) { return $cached; } // فقط وقتی کران اخیراً tick زده — وگرنه API زنده (جلوگیری از قفل قیمت) if ($cache->hasRecentTick()) { $dbBuilt = $cache->buildFromDatabase(); if (($dbBuilt['price'] ?? 0) > 0) { return $cache->put($dbBuilt); } } } if ($config->isStore()) { $storePayload = array_merge([ 'closed' => false, 'time' => now(), 'main_product' => 0, 'zaarbox' => 0, ], $this->storeLastPrice($config)); if ($forceRefresh) { $this->recordHalfHourPriceSnapshot( (int) ($storePayload['buy'] ?? 0), 'store', null, (int) ($storePayload['price'] ?? $storePayload['buy'] ?? 0) ); } return $this->appendUpPrices($storePayload, $forceRefresh); } $closed = false; $montzar_price = 0; $zaarbox_price = 0; $pr_price = 0; $montzar_open_buy = false; $montzar_open_sell = false; $priceSource = null; $priceValue = 0; $toBool = function ($value) { return filter_var($value, FILTER_VALIDATE_BOOLEAN); }; $zeroResponse = function () use ($forceRefresh) { return $this->appendUpPrices([ 'sell' => 0, 'buy' => 0, 'price_last' => 0, 'price' => 0, 'main_product' => 0, 'montzar' => 0, 'zaarbox' => 0, 'closed' => true, 'time' => now(), ], $forceRefresh); }; $priceProvider = $config->priceProvider(); /* |-------------------------------------------------------------------------- | بستن قیمت طبق منطق قبلی |-------------------------------------------------------------------------- */ if ($toBool($config->Config('close_price'))) { if ($config->isOutsideTradingHours()) { $config->syncAppClosedFlag(); return $zeroResponse(); } Cnt::where('key', 'app_closed')->update(['value' => 'false']); } /* |-------------------------------------------------------------------------- | Settings |-------------------------------------------------------------------------- */ $settings = Setting::whereIn('key', [ 'main_product_price', ])->get(); $settingsMap = $settings->pluck('value', 'key'); $show_last_price = $config->getBool('show_last_price', false); $main_product_price = $settingsMap->get('main_product_price'); /* |-------------------------------------------------------------------------- | Montzar — فقط وقتی price_provider=montzar |-------------------------------------------------------------------------- */ if ($priceProvider === 'montzar' && !$closed) { try { $montzarBaseUrl = rtrim($config->Config('montzar_base_url') ?: 'https://montpar.ir', '/'); $montzarProductId = (int) ($config->Config('montzar_product_id') ?: 25); $montzar = app(MontzarService::class)->productList(); if (isset($montzar['message'])) { throw new \Exception('Provider message: ' . $montzar['message']); } $collection = collect($montzar); $montzarProduct = $collection->firstWhere('id', $montzarProductId); if (!$montzarProduct) { throw new \Exception("Provider product not found. product_id={$montzarProductId}"); } if (!isset($montzarProduct['sub_agent'])) { throw new \Exception("Provider product has no sub_agent. product_id={$montzarProductId}"); } $buy = (float) ($montzarProduct['sub_agent']['rate_buy_gram_price'] ?? 0); $sell = (float) ($montzarProduct['sub_agent']['rate_sell_gram_price'] ?? 0); if ($buy <= 0 || $sell <= 0) { throw new \Exception("Provider invalid gram price. buy={$buy}, sell={$sell}"); } $customPrice = []; $customPrice['price'] = ($buy + $sell) / 2; $customPrice['diff'] = ($buy - $sell) / 2; $config->UpdateConfig('montzar_live_price', (float) $customPrice['price']); $config->UpdateConfig('montzar_diff', (float) $customPrice['diff']); $config->UpdateConfig('montzar_mazaneh', ((float) $customPrice['price'] * 4.331802)); $config->UpdateConfig( 'montzar_truly_buy_mazaneh', $montzarProduct['sub_agent']['rate_buy_price'] ?? 0 ); $config->UpdateConfig( 'montzar_truly_sell_mazaneh', $montzarProduct['sub_agent']['rate_sell_price'] ?? 0 ); $config->UpdateConfig( 'montzar_last_product_log', json_encode($montzarProduct, JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT) ); $montzarFlags = $config->syncMontzarOpenFlagsFromProduct($montzarProduct); $montzar_open_buy = $montzarFlags['open_buy']; $montzar_open_sell = $montzarFlags['open_sell']; $montzar_price = (int) $customPrice['price']; $config->UpdateConfig('montzar_closed', 'false'); } catch (\Throwable $e) { $montzar_price = 0; \Log::error('MONZAR PRICE ERROR', [ 'message' => $e->getMessage(), 'montzar_product_id' => $montzarProductId ?? null, 'montzar_response' => $montzar ?? null, ]); $config->applyMontzarSyncFailure(); if (!$config->getBool('montzar_closed', true)) { $montzar_price = $config->getInt('montzar_live_price', 0); } } } /* |-------------------------------------------------------------------------- | Zaarbox — price_provider=zaarbox + settings.zaarbox_price_key |-------------------------------------------------------------------------- */ if ($priceProvider === 'zaarbox' && !$closed) { $zaarbox = app(ZaarboxPriceService::class)->fetchPrice(); $zaarbox_price = (int) ($zaarbox['order_price'] ?? 0); } /* |-------------------------------------------------------------------------- | Main Product — settings.main_product سپس const |-------------------------------------------------------------------------- */ $pr_product = null; if ($priceProvider === 'main_product' || $toBool($main_product_price)) { $pr_product = $config->mainProduct(); } if ($pr_product && !$closed) { if ($priceProvider === 'main_product') { if (Product::hasStoredPriceColumns()) { app(ZaarboxPriceService::class)->syncProductFromApi($pr_product->fresh()); $pr_product->refresh(); $pr_price = (float) $pr_product->price + (float) ($pr_product->price_profit ?? 0); } else { $live = app(ZaarboxPriceService::class)->fetchLiveOrderPrice( $pr_product->reading_method ); $pr_price = (float) ($live['order_price'] ?? 0); } } else { $pr_price = Product::hasStoredPriceColumns() ? (float) $pr_product->price + (float) ($pr_product->price_profit ?? 0) : 0.0; } } /* |-------------------------------------------------------------------------- | انتخاب قیمت اصلی (همان price_provider) |-------------------------------------------------------------------------- */ if ($priceProvider === 'zaarbox' && $zaarbox_price > 0 && !$closed) { $priceValue = $zaarbox_price; $priceSource = 'zaarbox'; } elseif ($priceProvider === 'montzar' && ($montzar_price ?? 0) !== 0 && !$closed) { $priceValue = (int) $montzar_price; $priceSource = 'montzar'; } elseif ($priceProvider === 'main_product' && ($pr_price ?? 0) !== 0 && !$closed) { $priceValue = $pr_price; $priceSource = 'main_product'; } else { $priceValue = 0; $priceSource = null; } if ($priceValue <= 0) { $lastPrice = Price::latest()->first(); $storedPrice = $lastPrice ? (float) $lastPrice->price : 0.0; $useFallback = $request->boolean('force_refresh') || $show_last_price; if ($storedPrice > 30_000_000 && $useFallback) { $priceValue = $storedPrice; $priceSource = 'database_last'; } else { return $this->appendUpPrices([ 'sell' => 0, 'buy' => 0, 'price_last' => 0, 'price' => 0, 'main_product' => $pr_price ?? 0, 'montzar' => $montzar_price ?? 0, 'zaarbox' => $zaarbox_price ?? 0, 'closed' => true, 'time' => now(), ], $forceRefresh); } } /* |-------------------------------------------------------------------------- | محاسبه sell / buy |-------------------------------------------------------------------------- */ $display = $config->buildTradeDisplayPrices( (float) $priceValue, $priceSource, [ 'montzar_open_buy' => $montzar_open_buy, 'montzar_open_sell' => $montzar_open_sell, ] ); $sell = $display['sell']; $buy = $display['buy']; $priceLast = $display['priceLast']; if (!$closed && $priceValue > 0) { $config->trackDailyPriceExtreme((float) $priceValue); } if ($forceRefresh) { $this->recordHalfHourPriceSnapshot( (int) $buy, (string) ($priceSource ?: ($priceProvider ?: 'legacy')), $this->resolvePriceSourceUrl($priceSource, $config), (int) $priceValue ); } return $this->appendUpPrices([ 'sell' => $sell, 'buy' => $buy, 'price_last' => $priceLast, 'price' => $priceValue, 'main_product' => $pr_price ?? 0, 'montzar' => $montzar_price ?? 0, 'zaarbox' => $zaarbox_price ?? 0, 'closed' => false, 'time' => now(), ], $forceRefresh); } protected function recordHalfHourPriceSnapshot( int $buyPrice, string $source, ?string $sourceUrl, int $referencePrice ): void { if ($buyPrice <= 0) { return; } $reference = $referencePrice > 0 ? $referencePrice : $buyPrice; app(PriceSyncLogService::class)->recordSnapshotIfDue( $source, $sourceUrl, $reference, PriceSnapshotService::HALF_HOUR_MINUTES ); app(PriceSnapshotService::class)->recordHalfHourBuyPrice($buyPrice); } protected function resolvePriceSourceUrl(?string $priceSource, ConfigService $config): ?string { if ($priceSource === 'zaarbox') { return app(ZaarboxPriceService::class)->apiUrl(); } if ($priceSource === 'montzar') { return rtrim($config->Config('montzar_base_url') ?: 'https://montpar.ir', '/'); } return null; } /** * فروشگاه — منطق lastPrice قبل مرج (ghatreh): montzar_price / nasiryan / prices */ protected function storeLastPrice(ConfigService $config): array { $toBool = fn ($value) => filter_var($value, FILTER_VALIDATE_BOOLEAN); $difference = (float) config('fee.single'); $talaIr = 0; $nasiryan = 0; $montzar = 0; $montzarExists = Setting::where('key', 'montzar_price')->exists(); $montzarEnabled = $montzarExists && $toBool($config->Config('montzar_price')); if ($montzarEnabled) { try { $montzarProductId = (int) ($config->Config('montzar_product_id') ?: 25); $montzarProducts = app(MontzarService::class)->productList(); if (isset($montzarProducts['message'])) { throw new \Exception('Montzar message: ' . $montzarProducts['message']); } $montzarProduct = collect($montzarProducts)->firstWhere('id', $montzarProductId); if (! $montzarProduct || ! isset($montzarProduct['sub_agent'])) { throw new \Exception("Montzar product not found. product_id={$montzarProductId}"); } $buy = (float) ($montzarProduct['sub_agent']['rate_buy_gram_price'] ?? 0); $sell = (float) ($montzarProduct['sub_agent']['rate_sell_gram_price'] ?? 0); if ($buy <= 0 || $sell <= 0) { throw new \Exception("Montzar invalid gram price. buy={$buy}, sell={$sell}"); } $customPrice = [ 'price' => ($buy + $sell) / 2, 'diff' => ($buy - $sell) / 2, ]; $config->UpdateConfig('montzar_live_price', (float) $customPrice['price']); $config->UpdateConfig('montzar_diff', (float) $customPrice['diff']); $config->UpdateConfig('montzar_mazaneh', ((float) $customPrice['price'] * 4.331802)); $config->UpdateConfig('montzar_truly_buy_mazaneh', $montzarProduct['sub_agent']['rate_buy_price'] ?? 0); $config->UpdateConfig('montzar_truly_sell_mazaneh', $montzarProduct['sub_agent']['rate_sell_price'] ?? 0); $config->UpdateConfig( 'montzar_last_product_log', json_encode($montzarProduct, JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT) ); $montzarFlags = $config->syncMontzarOpenFlagsFromProduct($montzarProduct); $openBuy = $montzarFlags['open_buy']; $openSell = $montzarFlags['open_sell']; $montzar = (int) $customPrice['price']; $config->UpdateConfig('montzar_closed', 'false'); } catch (\Throwable $e) { $montzar = 0; $config->applyMontzarSyncFailure(); if (!$config->getBool('montzar_closed', true)) { $montzar = $config->getInt('montzar_live_price', 0); } \Log::error('STORE MONZAR PRICE ERROR', ['message' => $e->getMessage()]); } } $nasiryanEnabled = $config->Config('price_from_nasiryan') == 'true'; if ($nasiryanEnabled) { try { $nasiryanRes = Http::withoutVerifying() ->timeout(2) ->withToken(Cnt::where('key', 'nasiryan')->first()['value'] ?? '') ->get('https://nasiryan.com/server/customer/product/list') ->json(); if ((isset($nasiryanRes['message']) && $nasiryanRes['message'] == 'no authorised') || $nasiryanRes == null) { $cnt = new Cnt(); $cnt->nasiryan_login(); $nasiryanRes = Http::withoutVerifying() ->timeout(2) ->withToken(Cnt::where('key', 'nasiryan')->first()['value'] ?? '') ->get('https://nasiryan.com/server/customer/product/list') ->json(); } $lp = collect($nasiryanRes)->firstWhere('id', 1); if (! $lp || ! isset($lp['sub_agent'])) { throw new \Exception('Nasiryan product/sub_agent not found'); } $buy = (float) $lp['sub_agent']['rate_buy_gram_price']; $sell = (float) $lp['sub_agent']['rate_sell_gram_price']; $customPrice = [ 'price' => ($buy + $sell) / 2, 'diff' => ($buy - $sell) / 2, ]; Cnt::where('key', 'nasiryan_price')->update(['value' => (float) $customPrice['price']]); Cnt::where('key', 'nasiryan_diff')->update(['value' => (float) $customPrice['diff']]); Cnt::where('key', 'nasiryan_mazaneh')->update(['value' => ((float) $customPrice['price'] * 4.331802)]); Cnt::where('key', 'nasiryan_truly_buy_mazaneh')->update(['value' => $lp['sub_agent']['rate_buy_price']]); Cnt::where('key', 'nasiryan_truly_sell_mazaneh')->update(['value' => $lp['sub_agent']['rate_sell_price']]); Cnt::where('key', 'log')->update(['value' => json_encode($nasiryanRes, JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT)]); $nasiryan = (int) $customPrice['price']; Cnt::where('key', 'nasiryan_closed')->update(['value' => $nasiryan == 0 ? 'true' : 'false']); } catch (\Throwable $e) { $nasiryan = 0; Cnt::where('key', 'nasiryan_closed')->update(['value' => 'true']); } } if ($montzarEnabled && $montzar !== 0) { $priceValue = $montzar; $priceSource = 'montzar'; } elseif ($nasiryanEnabled && $nasiryan !== 0) { $priceValue = $nasiryan; $priceSource = 'nasiryan'; } else { $priceValue = $talaIr; $priceSource = 'tala_ir'; } $lastStored = Price::latest()->first(); if ($priceValue <= 0 && $lastStored && (float) $lastStored->price > 0) { $priceValue = (float) $lastStored->price; $priceSource = 'database_last'; } if ($priceValue <= 0) { return []; } $display = $config->buildTradeDisplayPrices( (float) $priceValue, $priceSource ); $response = [ 'sell' => $display['sell'], 'buy' => $display['buy'], 'price_last' => $display['priceLast'], 'price' => $priceValue, 'tala_ir' => $talaIr, 'nasiryan' => $nasiryan, ]; if ($montzarExists) { $response['montzar'] = $montzar; } return $response; } public function check() { $service = Http:: withHeaders([ 'accept' => 'application/json', 'Authorization' => 'Bearer ohxsrbjagqvbt0glaygt' ])->get('https://studio.persianapi.com/index.php/web-service/common/gold-currency-coin?format=json&limit=30&page=1') ->json(); $list = []; if (isset($service['result'])) { foreach ($service['result'] as $item) { if ($item['key'] == 137120 || $item['key'] == 137119) { $list[] = $item; if ($item['key'] == 137120) { (new PriceController())->store(new Request(["price" => $item['price']])); } } } Cnt::where('key', 'price')->update(['value_json' => $list]); } } public function test() { $a = '{{12, 23, {4, 0, {1}, {1}}}, 0, {1}}'; $b = str_split($a); $c = []; $str = ""; foreach ($b as $item) { if ($item != " ") { print_r($item); print_r('++'); if ($item == ',' || $item == '}') { if (!in_array($c[count($c) - 1], ['{', '}'])) { $c[count($c) - 1] += (int)$str; print_r((int)$str); print_r('^^'); } else { $c[] = $str; print_r($c); print_r('&&'); } $str = ""; } elseif (in_array($item, ['{', '}'])) { $c[] = $item; print_r($c); print_r('**'); } else { $str .= $item; print_r($str); print_r('@@'); } } } dd($c); $d = []; $e = []; foreach ($c as $item) { if ($item == '}') { print_r($d[count($d) - 1]); print_r('***'); $e[] = $d[count($d) - 1]; } else { $d[] = $item; print_r($d); print_r('-----'); } } dd($e); } }