feat: 前端分離+功能api化

1. 新增資產管理CRUD、googleOAuth登入
2. 更改原記帳controller
This commit is contained in:
2026-06-25 14:19:07 +08:00
parent 7bb931c97b
commit 85972f950c
70 changed files with 4754 additions and 1520 deletions

View File

@@ -0,0 +1,115 @@
<?php
namespace App\Console\Commands;
use Illuminate\Console\Command;
use App\Models\User;
use Google\Client as GoogleClient;
use Google\Service\Gmail;
use Illuminate\Support\Facades\Log;
class TestGmailFetch extends Command
{
protected $signature = 'gmail:test-fetch';
protected $description = '測試抓取最新的一筆發票或刷卡信件,並輸出至 Log 中';
public function handle()
{
// 1. 抓取你剛才綁定成功的使用者(假設 ID 為 1
$user = User::find(1);
if (!$user || !$user->google_refresh_token) {
$this->error('找不到使用者,或該使用者尚未擁有 google_refresh_token');
return;
}
$this->info("🔄 正在初始化 Google Client 并刷新 Token...");
// 2. 初始化 Google Client
$client = new GoogleClient();
$client->setClientId(config('services.google.client_id'));
$client->setClientSecret(config('services.google.client_secret'));
// 用 refresh_token 去跟 Google 交換新的短期 access_token
$client->refreshToken($user->google_refresh_token);
$accessToken = $client->getAccessToken();
// 順手把新的 token 蓋回資料庫(防呆)
$user->update([
'google_access_token' => $accessToken['access_token'],
'google_token_expires_at' => now()->addSeconds($accessToken['expires_in']),
]);
// 3. 呼叫 Gmail 服務
$gmailService = new Gmail($client);
$this->info("🔍 正在透過標籤精準搜尋信用卡消費通知...");
$searchQuery = 'label:信用卡 -is:spam -is:trash';
$response = $gmailService->users_messages->listUsersMessages('me', [
'maxResults' => 1, // 先抓一筆來看內文
'q' => $searchQuery
]);
$messages = $response->getMessages();
if (empty($messages)) {
$this->warn('❌ 找不到任何符合關鍵字的信件!請確認你的 Gmail 裡有這種類型的信。');
return;
}
$msgId = $messages[0]->getId();
$this->info("🎯 成功找到信件 ID: {$msgId},正在下載詳細內容...");
// 4. 抓取信件完整細節
$message = $gmailService->users_messages->get('me', $msgId, ['format' => 'full']);
$payload = $message->getPayload();
$headers = $payload->getHeaders();
// 解析主旨
$subject = '';
foreach ($headers as $header) {
if ($header->getName() === 'Subject') {
$subject = $header->getValue();
break;
}
}
// 解析內文 (處理可能存在的多重 Multipart 結構)
$body = $this->getDecodedBody($payload);
// 5. 🟢 核心現形:把內容原封不動地噴進 Log
Log::info("=== 【GMAIL 測試抓取成功】 ===");
Log::info("主旨: " . $subject);
Log::info("信件 ID: " . $msgId);
Log::info("=== 原始內文開始 ===");
Log::info($body);
Log::info("=== 原始內文結束 ===");
$this->info("✅ 抓取完畢!真實內容已成功寫入 storage/logs/laravel.log快去打開瞧瞧吧");
}
/**
* 輔助方法:遞迴解析 Gmail Body 內容
*/
private function getDecodedBody($part)
{
$body = $part->getBody();
if ($body && $body->getData()) {
// Gmail 的 base64 比較特殊,需要把 - 和 _ 換回來
$sanitizedData = str_replace(['-', '_'], ['+', '/'], $body->getData());
return base64_decode($sanitizedData);
}
$parts = $part->getParts();
if ($parts) {
foreach ($parts as $subPart) {
$result = $this->getDecodedBody($subPart);
if ($result) return $result;
}
}
return '';
}
}