From 9d6e55988f5f70cc1a3ab99f5a0c8c27e68027a3 Mon Sep 17 00:00:00 2001 From: hgc Date: Mon, 6 Jan 2025 14:47:09 +0800 Subject: [PATCH] =?UTF-8?q?jwt=20grpc=E8=B0=83=E7=94=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/controller/AdController.php | 53 +++--- app/controller/OAuthController.php | 91 +++++------ app/middleware/Jwt.php | 164 +++++++++++++------ app/middleware/JwtLocal.php | 79 +++++++++ app/middleware/JwtRpc.php | 88 ---------- app/service/GoogleAdsReportService.php | 218 ++++++------------------- generated/GRPC/Auth/AuthClient.php | 2 +- 7 files changed, 313 insertions(+), 382 deletions(-) create mode 100644 app/middleware/JwtLocal.php delete mode 100644 app/middleware/JwtRpc.php diff --git a/app/controller/AdController.php b/app/controller/AdController.php index 89c4c68..1842696 100644 --- a/app/controller/AdController.php +++ b/app/controller/AdController.php @@ -70,7 +70,7 @@ class AdController $startDate, // 开始日期 $endDate ); // 结束日期); - return $this->successResponse($result); + return $this->successResponse($result, $request); } public function listAssets(Request $request) @@ -88,15 +88,13 @@ class AdController // $customerId = 4060397299; $customers = $this->googleOAuthService->getGoogleAdCustomers(['refresh_token' => $request->refresh_token]); $customerIds = array_column($customers, 'customer_id'); - - // 你可以进一步验证日期格式(可选) -// if ($startDate && !strtotime($startDate)) { -// return response()->json(['error' => 'Invalid start date format'], 400); -// } -// if ($endDate && !strtotime($endDate)) { -// return response()->json(['error' => 'Invalid end date format'], 400); -// } - +//dump( $customerIds, // 客户 ID 数组 +// $page, // 页码 +// $pageSize, // 每页数量 +// $keyword, // 关键字 +// $dateRange, +// $startDate, // 开始日期 +// $endDate); // 调用 Service 层查询 $result = $this->googleAdsReportService->getAssetConversionData( $customerIds, // 客户 ID 数组 @@ -106,7 +104,7 @@ class AdController $dateRange, $startDate, // 开始日期 $endDate); - return $this->successResponse($result); + return $this->successResponse($result, $request); } public function listCampaigns(Request $request) @@ -133,7 +131,7 @@ class AdController $startDate, // 开始日期 $endDate // 结束日期 ); - return $this->successResponse($result); + return $this->successResponse($result, $request); // return $this->errorResponse(300,'授权失败'); } @@ -217,7 +215,7 @@ class AdController $startDate, // 开始日期 $endDate ); - return $this->successResponse($result); + return $this->successResponse($result, $request); } @@ -260,7 +258,7 @@ class AdController if (!$reslut) { return $this->errorResponse(101, 'Status update failed'); } - return $this->successResponse(['message' => 'Status updated successfully']); + return $this->successResponse(['message' => 'Status updated successfully'], $request); // } catch (ValidateException $e) { // return $this->errorResponse(400, $e->getMessage()); // } @@ -334,7 +332,7 @@ class AdController if (!$result) { return $this->errorResponse(101, 'Status update failed'); } - return $this->successResponse(['message' => 'Status updated successfully']); + return $this->successResponse(['message' => 'Status updated successfully'], $request); // } catch (ValidateException $e) { // return $this->errorResponse(400, $e->getMessage()); // } @@ -367,7 +365,7 @@ class AdController if (!$result) { return $this->errorResponse(101, 'Status update failed'); } - return $this->successResponse(['message' => 'Status updated successfully']); + return $this->successResponse(['message' => 'Status updated successfully'], $request); // } catch (ValidateException $e) { // return $this->errorResponse(400, $e->getMessage()); // } @@ -375,13 +373,24 @@ class AdController // 可以加入一些公共方法 - protected function successResponse($data): Response + protected function successResponse($data, Request $request): Response { - return Json([ - 'code' => 0, - 'msg' => 'ok', - 'data' => $data, - ]); + if ($request->jwtNewToken) { + return new Response(200, + [ + 'Content-Type' => 'application/json', + 'X-New-Token' => $request->jwtNewToken + ], + json_encode($data, JSON_UNESCAPED_UNICODE)); + } else { + return Json([ + 'code' => 0, + 'msg' => 'ok', + 'data' => $data, + ]); + } + + } protected function errorResponse($code, $message, $data = []): Response diff --git a/app/controller/OAuthController.php b/app/controller/OAuthController.php index aaac230..4768a88 100644 --- a/app/controller/OAuthController.php +++ b/app/controller/OAuthController.php @@ -28,7 +28,7 @@ class OAuthController $authUrl = $this->googleOAuthService->getAuthUrl($state); return $this->successResponse([ 'url' => $authUrl, - ]); + ],$request); } @@ -62,7 +62,7 @@ class OAuthController // } else { // return $this->errorResponse(300, 'Invalid state parameter'); // } - return $this->successResponse($tokens); + return $this->successResponse($tokens,$request); } @@ -114,7 +114,7 @@ class OAuthController $googleOAuthService = new GoogleOAuthService(); $googleOAuthService->revokeToken($accessToken, $thirdUser->id); - return $this->successResponse(['deleted' => 'success']); + return $this->successResponse(['deleted' => 'success'],$request); } @@ -138,29 +138,7 @@ class OAuthController public function testRefreshToken(Request $request) { - // 接建立socket连到内部推送端口 - $client = stream_socket_client('tcp://192.168.21.27:22101', $errorCode, $errorMessage); - if (false === $client) { - throw new \Exception('rpc failed to connect: ' . $errorMessage); - } - $rpc_request = [ - 'class' => 'Auth', - 'method' => 'ValidateJwtToken', - 'args' => [ - [ - 'uid' => 2023, - 'username' => 'Tinywan', - ] - ] - ]; - // 发送数据,注意5678端口是Text协议的端口,Text协议需要在数据末尾加上换行符 - fwrite($client, json_encode($rpc_request) . "\n"); - // 读取推送结果 - $result = fgets($client, 10240000); - // 解析JSON字符串 - $result = json_decode($result, true); - dump($result); - return $this->successResponse($result); + return $this->successResponse([],$request); //发布事件 // $dayBeforeYesterdayStart = date('Y-m-d', strtotime('-2 day')); @@ -173,10 +151,10 @@ class OAuthController // Event::emit(GoogleAdsGroups::type, []); // dump(date('Y-m-d H:i:s') . '更新' . GoogleAdsAds::type . '开始'); // Event::emit(GoogleAdsAdMaterials::type, []); - dump(date('Y-m-d H:i:s') . '更新' . GoogleAdsMaterials::type . '开始'); - Event::emit(GoogleAdsMaterials::type, []); +// dump(date('Y-m-d H:i:s') . '更新' . GoogleAdsMaterials::type . '开始'); +// Event::emit(GoogleAdsMaterials::type, []); - return $this->successResponse(['data' => []]); +// return $this->successResponse(['data' => []]); // $customers = $this->googleOAuthService->getGoogleAdCustomers([]); @@ -205,37 +183,46 @@ class OAuthController // 使用 ThinkDb 进行联表查询 // $advertiserId = 'your-advertiser-id'; // 假设你已经获得了广告商ID - $requestData = $request->all(); // 获取请求数据 - $customerId = $requestData['customer_id']; - - // 通过 advertiser_id 查询 ThirdUserAdvertiser,联表查询 ThirdUser 数据 - $userAdvertiser = ThirdUserAdvertiser::with('googleUser') // 联表查询 user 关联 - ->where('advertiser_id', $customerId) // 根据 advertiser_id 查询 - ->find(); // 获取第一个结果 +// $requestData = $request->all(); // 获取请求数据 +// $customerId = $requestData['customer_id']; +// +// // 通过 advertiser_id 查询 ThirdUserAdvertiser,联表查询 ThirdUser 数据 +// $userAdvertiser = ThirdUserAdvertiser::with('googleUser') // 联表查询 user 关联 +// ->where('advertiser_id', $customerId) // 根据 advertiser_id 查询 +// ->find(); // 获取第一个结果 // 如果找到广告主数据 - if ($userAdvertiser && $userAdvertiser->googleUser) { - // 获取关联用户的 access_token - $accessToken = $userAdvertiser->googleUser->access_token; -// dump($accessToken); // 打印 access_token - return $this->successResponse($accessToken); // 返回 access_token - } else { - // 如果没有找到广告主或关联的用户,返回错误信息 -// dump('未找到该广告主或关联的用户'); - return $this->errorResponse('101', '未找到该广告主或关联的用户'); - } +// if ($userAdvertiser && $userAdvertiser->googleUser) { +// // 获取关联用户的 access_token +// $accessToken = $userAdvertiser->googleUser->access_token; +//// dump($accessToken); // 打印 access_token +// return $this->successResponse($accessToken); // 返回 access_token +// } else { +// // 如果没有找到广告主或关联的用户,返回错误信息 +//// dump('未找到该广告主或关联的用户'); +// return $this->errorResponse('101', '未找到该广告主或关联的用户'); +// } } // 可以加入一些公共方法 - protected function successResponse($data): Response + protected function successResponse($data,Request $request): Response { - return Json([ - 'code' => 0, - 'msg' => 'ok', - 'data' => $data, - ]); + if ($request->jwtNewToken) { + return new Response(200, + [ + 'Content-Type' => 'application/json', + 'X-New-Token' => $request->jwtNewToken + ], + json_encode($data, JSON_UNESCAPED_UNICODE)); + } else { + return Json([ + 'code' => 0, + 'msg' => 'ok', + 'data' => $data, + ]); + } } protected function errorResponse($code, $message, $data = []): Response diff --git a/app/middleware/Jwt.php b/app/middleware/Jwt.php index 71c197b..1c1b32d 100644 --- a/app/middleware/Jwt.php +++ b/app/middleware/Jwt.php @@ -2,78 +2,134 @@ namespace app\middleware; -use Webman\MiddlewareInterface; use Webman\Http\Request; use Webman\Http\Response; -use Firebase\JWT\JWT as FJWT; -use Firebase\JWT\Key; -use Exception; +use Webman\MiddlewareInterface; +use GRPC\Auth\AuthClient; +use GRPC\Auth\ValidateJwtTokenReq; +use GRPC\Auth\JwtVerifyResult; class Jwt implements MiddlewareInterface { - // 签名密钥 - private const SIGNING_KEY = '83OP5jf43875jK7'; + protected $authClient; + + public function __construct() + { + // 初始化 AuthClient + $host = "192.168.21.27:22101"; // 替换为你的 Auth 服务地址 + $this->authClient = new AuthClient($host); + } public function process(Request $request, callable $handler): Response { - // 获取 Authorization 头 - $authorization = $request->header('Authorization', ''); - if (empty($authorization) || strpos($authorization, 'Bearer ') !== 0) { + // 从请求头中获取 JWT token + $jwtToken = $request->header('Authorization'); + + if (!$jwtToken) { return Json([ 'code' => 1, - 'msg' => '缺少 Authorization 头或格式无效', + 'msg' => 'Authorization token is missing', 'data' => [] ]); } - // 提取 JWT token - $jwtToken = substr($authorization, 7); + // 去除 Bearer 前缀 + if (strpos($jwtToken, 'Bearer ') === 0) { + $jwtToken = substr($jwtToken, 7); + } +// try { + // 创建 GRPC 请求 +// dump($jwtToken); + $grpcRequest = new ValidateJwtTokenReq(); + $grpcRequest->setJwtToken($jwtToken); + // 调用 GRPC 服务 +// list($response, $status) = $this->authClient->ValidateJwtToken($grpcRequest); + $responseAuth = $this->authClient->ValidateJwtToken($grpcRequest); - try { - // 使用 firebase/php-jwt 解码并验证 JWT -// $decoded = FJWT::decode($jwtToken, new Key(self::SIGNING_KEY, 'HS512'), $headers = new stdClass()); // 使用 HMAC-SHA512 算法进行验证 - $decoded = FJWT::decode($jwtToken, new Key(self::SIGNING_KEY, 'HS512')); - // 将解码后的数据(即 claims)存入请求对象,后续可以访问 - $request->jwtClaims = (array)$decoded; + // 检查验证结果 + // 获取验证结果 + $result = $responseAuth->getResult(); - // 验证 JWT Token -// dump((array)$decoded); -// return Json([ -// 'code' => 0, -// 'msg' => 'JWT 验证成功', -// 'data' => [] -// ]); + // 根据验证结果返回不同的消息 + switch ($result) { + case JwtVerifyResult::JWT_VERIFY_OK: + // Token 验证成功,继续执行下层逻辑 + break; - // 继续处理请求 + case JwtVerifyResult::JWT_VERIFY_BAD_FORMAT: + return Json([ + 'code' => 1, + 'msg' => 'Invalid token format', + 'data' => [] + ]); + + case JwtVerifyResult::JWT_VERIFY_SIGN_FAILED: + return Json([ + 'code' => 1, + 'msg' => 'Token signature is invalid', + 'data' => [] + ]); + + case JwtVerifyResult::JWT_VERIFY_EXPIRED: + return Json([ + 'code' => 1, + 'msg' => 'Token has expired', + 'data' => [] + ]); + + case JwtVerifyResult::JWT_VERIFY_REVOKED: + return Json([ + 'code' => 1, + 'msg' => 'Token has been revoked', + 'data' => [] + ]); + + case JwtVerifyResult::JWT_VERSION_LOW: + return Json([ + 'code' => 1, + 'msg' => 'Token version is too low', + 'data' => [] + ]); + + default: + return Json([ + 'code' => 1, + 'msg' => 'Unknown token verification error', + 'data' => [] + ]); + } + + // 将解析的 claims 数据传递给下层业务逻辑 + $claims = $responseAuth->getClaims(); + + if ($claims) { + // 获取 uid 和 merchant_id + $uid = $claims->getUid(); + $merchantId = $claims->getMerchantId(); + +// dump("UID: " . $uid); // 打印 uid +// dump("Merchant ID: " . $merchantId); // 打印 merchant_id + + // 将 claims 数据附加到请求对象中,供后续使用 + $request->jwtClaims = [ + 'uid' => $uid, + 'merchant_id' => $merchantId + ]; + } + + // 检查是否存在新 token + $newToken = $responseAuth->getNewToken(); + + if ($newToken) { + $request->jwtNewToken = $newToken; +// response()->withHeader('X-New-Token',$newToken); + } + + // 如果验证通过,则继续处理请求 return $handler($request); - } catch (Exception $e) { - - return Json([ - 'code' => 1, - 'msg' => $e->getMessage(), - 'data' => [] - ]); - -// return response(['code' => 1, 'msg' => 'JWT 验证失败: ' . $e->getMessage()], 200); - } - } - - private function getErrorMessage($result) - { - switch ($result) { - case 'JWT_VERIFY_BAD_FORMAT': - return '无效的 token 格式'; - case 'JWT_VERIFY_SIGN_FAILED': - return 'token 签名无效'; - case 'JWT_VERIFY_EXPIRED': - return 'token 已过期'; - case 'JWT_VERIFY_REVOKED': - return 'token 已被撤销'; - case 'JWT_VERSION_LOW': - return 'token 版本过低'; - default: - return '未知错误'; - } +// } catch (\Exception $e) { +// return new Response(500, [], json_encode(['error' => 'Internal server error'])); +// } } } diff --git a/app/middleware/JwtLocal.php b/app/middleware/JwtLocal.php new file mode 100644 index 0000000..cb445dd --- /dev/null +++ b/app/middleware/JwtLocal.php @@ -0,0 +1,79 @@ +header('Authorization', ''); + if (empty($authorization) || strpos($authorization, 'Bearer ') !== 0) { + return Json([ + 'code' => 1, + 'msg' => '缺少 Authorization 头或格式无效', + 'data' => [] + ]); + } + + // 提取 JWT token + $jwtToken = substr($authorization, 7); + + try { + // 使用 firebase/php-jwt 解码并验证 JWT +// $decoded = FJWT::decode($jwtToken, new Key(self::SIGNING_KEY, 'HS512'), $headers = new stdClass()); // 使用 HMAC-SHA512 算法进行验证 + $decoded = FJWT::decode($jwtToken, new Key(self::SIGNING_KEY, 'HS512')); + + // 将解码后的数据(即 claims)存入请求对象,后续可以访问 + $request->jwtClaims = (array)$decoded; + + // 验证 JWT Token +// dump((array)$decoded); +// return Json([ +// 'code' => 0, +// 'msg' => 'JWT 验证成功', +// 'data' => [] +// ]); + + // 继续处理请求 + return $handler($request); + } catch (Exception $e) { + + return Json([ + 'code' => 1, + 'msg' => $e->getMessage(), + 'data' => [] + ]); + +// return response(['code' => 1, 'msg' => 'JWT 验证失败: ' . $e->getMessage()], 200); + } + } + + private function getErrorMessage($result) + { + switch ($result) { + case 'JWT_VERIFY_BAD_FORMAT': + return '无效的 token 格式'; + case 'JWT_VERIFY_SIGN_FAILED': + return 'token 签名无效'; + case 'JWT_VERIFY_EXPIRED': + return 'token 已过期'; + case 'JWT_VERIFY_REVOKED': + return 'token 已被撤销'; + case 'JWT_VERSION_LOW': + return 'token 版本过低'; + default: + return '未知错误'; + } + } +} diff --git a/app/middleware/JwtRpc.php b/app/middleware/JwtRpc.php deleted file mode 100644 index 0503049..0000000 --- a/app/middleware/JwtRpc.php +++ /dev/null @@ -1,88 +0,0 @@ -authClient = new AuthClient($host); - } - - public function process(Request $request, callable $handler): Response - { - - // 从请求头中获取 JWT token - $jwtToken = $request->header('Authorization'); - - if (!$jwtToken) { - return response()->json(['error' => 'Authorization token is missing'], 401); - } - - // 去除 Bearer 前缀 - if (strpos($jwtToken, 'Bearer ') === 0) { - $jwtToken = substr($jwtToken, 7); - } - try { - // 创建 GRPC 请求 - dump($jwtToken); - $grpcRequest = new ValidateJwtTokenReq(); - $grpcRequest->setJwtToken($jwtToken); - // 调用 GRPC 服务 - list($response, $status) = $this->authClient->ValidateJwtToken($grpcRequest)->wait(); - - if ($status->code !== \Grpc\STATUS_OK) { - return Json([ - 'code' => 1, - 'msg' => 'GRPC service error', - 'data' => [] - ]); - } - - // 检查验证结果 - if ($response->getResult() !== JwtVerifyResult::JWT_VERIFY_OK) { - return Json([ - 'code' => 1, - 'msg' => 'Invalid token', - 'data' => [] - ]); - } - - // 将解析的 claims 数据传递给下层业务逻辑 - $claims = $response->getClaims(); - dump($claims); - return Json([ - 'code' => 0, - 'msg' => 'test token well', - 'data' => [] - ]); - $request->jwtClaims = $claims; - -// if ($result['is_valid']) { -// dump("JWT 验证成功: " . json_encode($result['claims'])); -// } else { -// dump("JWT 验证失败: " . $result['error']); -// } - -// if (!$isValid) { -// return response()->json(['error' => 'Invalid token'], 401); -// } - - // 如果验证通过,则继续处理请求 - return $handler($request); - } catch (\Exception $e) { - return new Response(500, [], json_encode(['error' => 'Internal server error'])); - } - } -} diff --git a/app/service/GoogleAdsReportService.php b/app/service/GoogleAdsReportService.php index 82984c9..af90384 100644 --- a/app/service/GoogleAdsReportService.php +++ b/app/service/GoogleAdsReportService.php @@ -16,6 +16,13 @@ use think\model\Collection; class GoogleAdsReportService { + // 状态映射数组 + private static $statusMapping = [ + 2 => 'ENABLE', // 2 代表广告已启用 + 3 => 'PAUSED', // 3 代表广告待审核等状态 + // 其他状态可以继续添加 + ]; + /** * 获取广告列表 */ @@ -106,7 +113,7 @@ class GoogleAdsReportService 'revenue' => '-', 'roas' => '-', 'profit' => '-', - 'spend' => number_format(array_sum(array_column($allAds, 'spend')),2) ?: '0.00', + 'spend' => '$' . number_format(array_sum(array_column($allAds, 'spend')), 2) ?: '$0.00', 'be_roas' => '-' ]; // 获取查询结果 @@ -155,11 +162,11 @@ class GoogleAdsReportService 'revenue' => $item['revenue'] == -1 ? '-' : $item['revenue'], 'roas' => $item['roas'] == -1 ? '-' : $item['roas'], 'profit' => $item['profit'] == -1 ? '-' : $item['profit'], - 'spend' => number_format($item['spend'], 2), + 'spend' => '$' . number_format($item['spend'], 2), 'campaign_name' => $item['campaign_name'], 'ad_set_name' => $item['ad_group_name'], // Assuming ad_group_name as ad_set_name - 'delivery' => $item['ad_status'], - 'delivery_status' => '-', // Assuming active as '活动' + 'delivery' => self::$statusMapping[$item['ad_status']], + 'delivery_status' => $item['ad_status'], // Assuming active as '活动' 'be_roas' => $item['be_roas'] == -1 ? '-' : $item['be_roas'], 'image_url' => $assetUrl, // Add logic to populate image URLs if available ]; @@ -200,7 +207,7 @@ class GoogleAdsReportService * @param string $dateRange * @return void */ - public static function exportAdListToExcel($customerIds,$keyword, $dateRange, $startDate = null, $endDate = null) + public static function exportAdListToExcel($customerIds, $keyword, $dateRange, $startDate = null, $endDate = null) { if (empty($customerIds)) { return []; @@ -412,7 +419,7 @@ class GoogleAdsReportService $statistics = [ 'results' => '-', 'reach' => array_sum(array_column($allCampaigns, 'reach')) ?: 0, - 'spend' => number_format(array_sum(array_column($allCampaigns, 'spend')),2) ?: '0.00', + 'spend' => '$' . number_format(array_sum(array_column($allCampaigns, 'spend')), 2) ?: '$0.00', 'revenue' => '-', 'roas' => '-', 'profit' => '-', @@ -434,9 +441,9 @@ class GoogleAdsReportService 'revenue' => $item['revenue'] == -1 ? '-' : $item['revenue'], 'roas' => $item['roas'] == -1 ? '-' : $item['roas'], 'profit' => $item['profit'] == -1 ? '-' : $item['profit'], - 'spend' => number_format($item['spend'], 2), - 'delivery' => $item['campaign_status'], - 'delivery_status' => '-', // 默认状态 + 'spend' => '$' . number_format($item['spend'], 2), + 'delivery' => self::$statusMapping[$item['campaign_status']], + 'delivery_status' => $item['campaign_status'], // 默认状态 'be_roas' => $item['be_roas'] == -1 ? '-' : $item['be_roas'], ]; }, $campaigns->items()); @@ -459,75 +466,6 @@ class GoogleAdsReportService } - /** - * 获取广告系列列表 - */ - public static function getCampaignList1111($page, $pageSize, $keyword, $dateRange, $startDate = null, $endDate = null) - { -// 动态构建日期条件 - $dateCondition = ''; - if ($startDate && $endDate) { - $dateCondition = "d.date BETWEEN '{$startDate}' AND '{$endDate}'"; - } else { - switch ($dateRange) { - case 'Today': - $dateCondition = "d.date = '" . date('Y-m-d') . "'"; - break; - case 'Yesterday': - $dateCondition = "d.date = '" . date('Y-m-d', strtotime('-1 day')) . "'"; - break; - case 'Last Week': - $dateCondition = "d.date >= ' " . date('Y-m-d', strtotime('-1 week')) . "'"; - break; - case 'Last Month': - $dateCondition = "d.date >= '" . date('Y-m-d', strtotime('-1 month')) . "'"; - break; - case 'Last Year': - $dateCondition = "d.date >= '" . date('Y-m-d', strtotime('-1 year')) . "'"; - break; - default: - $dateCondition = "1=1"; // 无日期限制,默认条件始终为真 - break; - } - } - -// 基础查询:广告活动和日数据表联接 - $query = Campaign::alias('c') - ->leftJoin('bps.bps_google_ad_day_data d', "c.campaign_id = d.campaign_id AND {$dateCondition}") // 将日期条件加入到 ON 子句中 - ->field('c.campaign_id, c.status as campaign_status, c.campaign_name, c.customer_id, - COALESCE(SUM(d.clicks), -1) as clicks, - COALESCE(SUM(d.cost_micros) / 1000000, -1) as spend, - COALESCE(SUM(d.conversions), -1) as results, - COALESCE(SUM(d.conversions_value), -1) as conversions_value, - COALESCE(SUM(d.impressions), -1) as reach, - -1 as roas, -1 as be_roas, -1 as revenue, -1 as profit, -1 as delivery') - ->group('c.campaign_id, c.status, c.customer_id, c.campaign_name') - ->where(function ($query) use ($keyword) { - if ($keyword) { - $query->where('c.campaign_name', 'like', '%' . $keyword . '%'); - } - }); - - // 获取分页数据 - $campaigns = $query->paginate($pageSize, false, ['page' => $page]); - - // 确保转换为数值 - $result = array_map(function ($item) { - $item['spend'] = (float)$item['spend']; - $item['conversions_value'] = (float)$item['conversions_value']; - return $item; - }, $campaigns->items()); - - // 返回分页和总数信息 - return [ - 'data' => $campaigns->items(), - 'total' => $campaigns->total(), - 'current_page' => $campaigns->currentPage(), - 'last_page' => $campaigns->lastPage(), - ]; - } - - /** * 导出广告系列数据到 Excel * @@ -535,9 +473,9 @@ class GoogleAdsReportService * @param string $dateRange * @return void */ - public function exportCampaignsToExcel($customerIds,$keyword, $dateRange, $startDate = null, $endDate = null) + public function exportCampaignsToExcel($customerIds, $keyword, $dateRange, $startDate = null, $endDate = null) { - if(empty($customerIds)){ + if (empty($customerIds)) { return []; } @@ -732,7 +670,7 @@ class GoogleAdsReportService $statistics = [ 'results' => '-', 'reach' => array_sum(array_column($allAdGroups, 'reach')) ?: 0, - 'spend' => number_format(array_sum(array_column($allAdGroups, 'spend')),2)?: '0.00', + 'spend' => '$' . number_format(array_sum(array_column($allAdGroups, 'spend')), 2) ?: '$0.00', 'revenue' => '-', 'roas' => '-', 'profit' => '-', @@ -749,10 +687,12 @@ class GoogleAdsReportService 'customer_id' => $item['customer_id'], 'name' => $item['ad_group_name'] ?: '-', 'status' => $item['ad_group_status'], + 'delivery' => self::$statusMapping[$item['ad_group_status']], + 'delivery_status' => $item['ad_group_status'], // Assuming active as '活动' 'campaign_name' => $item['campaign_name'], 'results' => $item['results'], 'reach' => $item['reach'], - 'spend' => number_format($item['spend'], 2), + 'spend' => '$' . number_format($item['spend'], 2), 'revenue' => $item['revenue'] == -1 ? '-' : $item['revenue'], 'roas' => $item['roas'] == -1 ? '-' : $item['roas'], 'profit' => $item['profit'] == -1 ? '-' : $item['profit'], @@ -779,81 +719,12 @@ class GoogleAdsReportService } - /** - * 获取广告系列列表 - */ - public static function getAdGroupList1111($page, $pageSize, $keyword, $dateRange, $startDate = null, $endDate = null) - { -// 动态构建日期条件 - $dateCondition = ''; - if ($startDate && $endDate) { - $dateCondition = "d.date BETWEEN '{$startDate}' AND '{$endDate}'"; - } else { - switch ($dateRange) { - case 'Today': - $dateCondition = "d.date = '" . date('Y-m-d') . "'"; - break; - case 'Yesterday': - $dateCondition = "d.date = '" . date('Y-m-d', strtotime('-1 day')) . "'"; - break; - case 'Last Week': - $dateCondition = "d.date >= '" . date('Y-m-d', strtotime('-1 week')) . "'"; - break; - case 'Last Month': - $dateCondition = "d.date >= '" . date('Y-m-d', strtotime('-1 month')) . "'"; - break; - case 'Last Year': - $dateCondition = "d.date >= '" . date('Y-m-d', strtotime('-1 year')) . "'"; - break; - default: - $dateCondition = "1=1"; // 默认无日期限制 - break; - } - } - -// 初始化查询 - $query = AdGroup::alias('ag') - ->leftJoin("bps.bps_google_ad_day_data d", "ag.ad_group_id = d.ad_group_id AND {$dateCondition}") // 日期条件放入 ON 子句 - ->leftJoin("bps.bps_google_ads_campaign c", "ag.campaign_id = c.campaign_id") // 关联广告系列表 - ->field('ag.ad_group_id, ag.ad_group_name, ag.status as ad_group_status, ag.campaign_id, c.campaign_name, ag.customer_id, - COALESCE(SUM(d.clicks), -1) as clicks, - COALESCE(SUM(d.cost_micros) / 1000000, -1) as spend, - COALESCE(SUM(d.conversions), -1) as results, - COALESCE(SUM(d.conversions_value), -1) as conversions_value, - COALESCE(SUM(d.impressions), -1) as reach, - -1 as roas, -1 as be_roas, -1 as revenue, -1 as profit, -1 as delivery') - ->group('ag.ad_group_id, ag.ad_group_name, ag.status, ag.campaign_id, c.campaign_name, ag.customer_id') - ->where(function ($query) use ($keyword) { - if ($keyword) { - $query->where('ag.ad_group_name', 'like', '%' . $keyword . '%'); - } - }); - -// 获取分页数据 - $adGroups = $query->paginate($pageSize, false, ['page' => $page]); - // 确保转换为数值 - $result = array_map(function ($item) { - $item['spend'] = (float)$item['spend']; - $item['conversions_value'] = (float)$item['conversions_value']; - return $item; - }, $adGroups->items()); - -// 返回分页和总数信息 - return [ - 'data' => $adGroups->items(), - 'total' => $adGroups->total(), - 'current_page' => $adGroups->currentPage(), - 'last_page' => $adGroups->lastPage(), - ]; - } - - /** * 将广告组数据导出到 Excel 文件 */ - public function exportAdGroupsToExcel($customerIds,$keyword = '', $dateRange = 'Today', $startDate = null, $endDate = null) + public function exportAdGroupsToExcel($customerIds, $keyword = '', $dateRange = 'Today', $startDate = null, $endDate = null) { - if(empty($customerIds)){ + if (empty($customerIds)) { return []; } // 动态构建日期条件 @@ -1012,16 +883,22 @@ class GoogleAdsReportService } }); - // 如果提供了 customerIds,增加查询条件 + // 如果提供了 customerIds,增加查询条件 if (!empty($customerIds)) { $adIdsQuery->whereIn('a.customer_id', $customerIds); // 添加 customer_id 的查询约束 } else { return [ - 'data' => [], - 'chat_1_data' => [], // 返回按月汇总的 chat_data - 'total' => 0, - 'current_page' => 1, - 'last_page' => 1, + 'data' => [], + 'chat_1_data' => [], // 返回按月汇总的 chat_data + 'total' => 0, + 'pagination' => [ + 'startIndex' => 0, + 'maxResults' => $pageSize, + 'count' => 0, + 'pageNo' => 1, + 'pageSize' => $pageSize, + 'pages' => 1 + ] ]; } @@ -1207,7 +1084,7 @@ class GoogleAdsReportService 'creative' => $data['asset_name'], 'creative_type' => $data['asset_type'], 'creative_url' => $data['asset_url'], - 'spend' => number_format($data['total_spend'], 2), + 'spend' => '$' . number_format($data['total_spend'], 2), 'purchase_value' => '-', 'roas' => number_format($roas, 2) . '%', 'cpa' => '-', @@ -1228,7 +1105,7 @@ class GoogleAdsReportService 'video_plays_75_rate' => '-', 'video_plays_100_rate' => '-', 'hold_rate' => '-', - 'total_conversions_value' => number_format($data['total_conversions_value'], 2), + 'total_conversions_value' => '$' . number_format($data['total_conversions_value'], 2), 'total_conversions' => $data['total_conversions'], 'total_impressions' => $data['total_impressions'], 'ad_count' => count($data['ad']), @@ -1269,15 +1146,26 @@ class GoogleAdsReportService $chat_data[$month]['roas'] = number_format($chat_data[$month]['roas'], 2) . '%'; } + // 返回分页数据 + $totalItems = count($assetSummaryData); + $totalPages = ceil($totalItems / $pageSize); + $startIndex = ($page - 1) * $pageSize; + // 截取返回的数据 +// $pagedData = array_slice($assetSummaryData, $startIndex, $pageSize); $resultDataPaginated = array_slice($resultData, ($page - 1) * $pageSize, $pageSize); return [ - 'data' => $resultDataPaginated, + 'pagination' => [ + 'startIndex' => $startIndex, + 'maxResults' => $pageSize, + 'count' => $totalItems, + 'pageNo' => $page, + 'pageSize' => $pageSize, + 'pages' => $totalPages + ], 'chat_1_data' => array_values($chat_data), // 返回按月汇总的 chat_data - 'total' => count($resultData), - 'current_page' => (int)$page, - 'last_page' => ceil(count($resultData) / $pageSize), + 'data' => $resultDataPaginated ]; } diff --git a/generated/GRPC/Auth/AuthClient.php b/generated/GRPC/Auth/AuthClient.php index 61a8f21..489312b 100644 --- a/generated/GRPC/Auth/AuthClient.php +++ b/generated/GRPC/Auth/AuthClient.php @@ -65,7 +65,7 @@ class AuthClient extends BaseStub list($response, $status) = $unaryCall->wait(); // 调试:输出 GRPC 状态码 - dump($status); +// dump('2222',$response->getResult(),$response->getClaims(),$status); // 检查请求是否成功 if ($status->code !== \Grpc\STATUS_OK) {