Files
finance_app/app/Jobs/UpdateAssetPriceJob.php
henry yo 85972f950c feat: 前端分離+功能api化
1. 新增資產管理CRUD、googleOAuth登入
2. 更改原記帳controller
2026-06-25 14:19:07 +08:00

149 lines
6.3 KiB
PHP
Raw Blame History

This file contains invisible Unicode characters
This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<?php
namespace App\Jobs;
use App\Models\Security;
use App\Models\SecurityPriceHistories;
use Carbon\Carbon;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Queue\SerializesModels;
use Illuminate\Support\Facades\Http;
use Illuminate\Support\Facades\Log;
class UpdateAssetPriceJob implements ShouldQueue
{
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
protected $symbol;
protected $type;
protected $defaultName;
public function __construct(string $symbol, string $type, string $defaultName)
{
$this->symbol = $symbol;
$this->type = $type;
$this->defaultName = $defaultName;
}
public function handle(): void
{
try {
Log::info("🔄 開始從持倉清單發動爬蟲: [{$this->symbol}] {$this->defaultName}");
$isRealPrice = true;
$latestPrice = 0;
$latestPriceDate = null;
$name = $this->defaultName;
$changeAmount = 0;
$changeRate = 0;
$error = null;
// 股票去爬證交所
if ($this->type === 'stock') {
Log::info("開始抓取{$this->type}:{$this->symbol}價格");
$response = Http::timeout(10)->get("https://mis.twse.com.tw/stock/api/getStockInfo.jsp?ex_ch=tse_{$this->symbol}.tw");
if ($response->successful()) {
$json = $response->json();
$info = $json['msgArray'][0] ?? null;
if (isset($info['^']) && !Carbon::parse($info['^'])->isToday()) {
$isRealPrice = false;
}
if ($info) {
$latestPrice = floatval($info['z'] ?? $info['o'] ?? 0);
$latestPriceDate = isset($info['d']) ? Carbon::parse($info['d'])->format('Y-m-d') : now()->format('Y-m-d');
$name = $info['n'] ?? $this->defaultName;
if (isset($info['y']) && $latestPrice > 0) {
$changeAmount = floatval($latestPrice - $info['y']);
$changeRate = ($changeAmount / $info['y']) * 100;
}
}
}
} elseif ($this->type === 'fund') {
Log::info("開始抓取{$this->type}:{$this->symbol}價格");
// 去鉅亨網抓
$response = Http::timeout(10)
->withHeaders([
'User-Agent' => 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36',
'Referer' => 'https://www.anuefund.com/',
'Accept' => 'application/json, text/plain, */*',
])
->get("https://www.anuefund.com/anuefundApi/FundDetail/FundInfo", [
'fundDetailEnum' => 'FundINFO',
'FundID' => $this->symbol
]);
if ($response->successful()) {
$json = $response->json();
$headerInfo = $json['data']['hearder'] ?? null;
if (isset($headerInfo['navDate']) && !Carbon::parse($headerInfo['navDate'])->isToday()) {
//不是當天資料不更新
$isRealPrice = false;
}
if ($headerInfo) {
$latestPriceDate = isset($headerInfo['navDate']) ? substr($headerInfo['navDate'], 0, 10) : now()->format('Y-m-d');
$latestPrice = floatval($headerInfo['nav'] ?? 0);
if ($latestPriceDate !== now()->format('Y-m-d')) {
//不是當天資料不更新
$isRealPrice = false;
$latestPrice = 0;
}
$name = $headerInfo['fundName'] ?? $this->defaultName;
$changeAmount = floatval($headerInfo['upDown'] ?? 0);
$changeRate = floatval($headerInfo['upDownRate'] ?? 0);
}
}
Log::info("抓取{$this->type}:{$this->symbol}資料結束");
}
// 爬蟲成功拿到有效股價,幫新表補資料
if ($latestPrice > 0 && $isRealPrice) {
Log::info("開始寫入Security和SecurityPriceHistories表標的: [{$this->symbol}],價格: {$latestPrice}---");
$security = Security::updateOrCreate(
['code' => $this->symbol],
[
'type' => $this->type,
'name' => $name,
'latest_price' => $latestPrice,
'latest_price_at' => $latestPriceDate,
'change_amount' => $changeAmount,
'change_rate' => $changeRate,
'source' => 'twse',
]
);
SecurityPriceHistories::updateOrCreate(
[
'security_id' => $security->id,
'price_date' => now()->format('Y-m-d'), // 記錄今天的日期
],
[
'price' => $latestPrice,
'change_amount' => $changeAmount,
'change_rate' => $changeRate,
'created_at' => now(),
'updated_at' => now(),
]
);
Log::info("✅ Security & SecurityPriceHistories 標的 [{$this->symbol}] 補齊並更新成功: {$latestPrice}");
} elseif (!$isRealPrice) {
Log::info(" 標的 [{$this->symbol}] 抓到的價格是非即時的,不更新價格資訊。");
} else {
Log::warning("⚠️ 標的 [{$this->symbol}] 未能從證交所抓到有效價格,{$error}");
}
} catch (\Exception $e) {
Log::error("❌ 更新標的 [{$this->symbol}] 價格時發生異常: " . $e->getMessage());
$this->release(60);
}
}
}