From b791811abddeea4984141e7e0587f6a399fca218 Mon Sep 17 00:00:00 2001 From: huangguancheng Date: Mon, 17 Feb 2025 14:29:57 +0800 Subject: [PATCH] =?UTF-8?q?googleAds=E5=B9=BF=E5=91=8A=E8=B4=A6=E5=8F=B7-?= =?UTF-8?q?=E6=8E=88=E6=9D=83-=E7=BB=91=E5=AE=9A-=E6=BF=80=E6=B4=BB?= =?UTF-8?q?=E6=B5=81=E7=A8=8B=E6=9B=B4=E6=96=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/controller/CustomerController.php | 171 ++++++++++++++++-- app/controller/OAuthController.php | 19 +- app/event/GoogleAdsAds.php | 20 +- app/event/GoogleAdsAssetRelations.php | 40 ++-- app/event/GoogleAdsAssets.php | 26 ++- app/event/GoogleAdsCampaigns.php | 14 +- app/event/GoogleAdsCreatives.php | 17 +- app/event/GoogleAdsCustomers.php | 115 ++++++------ app/event/GoogleAdsDateDatas.php | 26 ++- app/event/GoogleAdsGroups.php | 14 +- .../redis/GoogleAdsCustomerInitQueue.php | 2 +- app/service/BpsAdAccountService.php | 17 +- app/service/GoogleAdsAccountService.php | 16 +- app/service/GoogleOAuthService.php | 96 +++++++++- config/event.php | 4 +- config/redis.php | 2 +- config/route.php | 25 ++- 17 files changed, 474 insertions(+), 150 deletions(-) diff --git a/app/controller/CustomerController.php b/app/controller/CustomerController.php index 5c5debc..f043cf3 100644 --- a/app/controller/CustomerController.php +++ b/app/controller/CustomerController.php @@ -84,10 +84,10 @@ class CustomerController return $this->getAccountHierarchy($options); } - //绑定接口-广告主体下层级账号 + //另一种方案,暂不启用 public function handleBinding(Request $request) { - $options = $request->all(); + $options = $request->all(); $options['jwtClaims'] = $request->jwtClaims; // dump($options,22222222); @@ -99,25 +99,57 @@ class CustomerController // dump($redisKey, $refresh_token, 444444); // return $this->successResponse($refresh_token); if ($refresh_token) { -// $options['refresh_token'] = $refresh_token; -// // 继续处理 Google Ads API 操作 -// $googleAdsAccounts = $this->getAccountHierarchyForBind($options); -// -// dump($googleAdsAccounts); + $options['refresh_token'] = $refresh_token; - $googleOAuthService = new GoogleOAuthService(); -// dump($options);return 0; - $hasThirdUser = $googleOAuthService->getCustomerListNew($options['jwtClaims']['merchant_id']); - dump($hasThirdUser,777); -// if(!empty($hasThirdUser)) { -// //$googleAdsAccounts和$hasThirdUser 合并 -// foreach ($hasThirdUser as $key => $value) { -// -// } -// -// return $this->successResponse($hasThirdUser);} -// } + $googleAdsAccounts = $this->getAccountHierarchyForBind($options); + $googleOAuthService = new GoogleOAuthService(); + $hasThirdUser = $googleOAuthService->getCustomerListNew($options['jwtClaims']['merchant_id']); + // 初始化返回结果数组 + $ad_accounts = []; + if (!empty($hasThirdUser)) { + // 先将 $hasThirdUser 转换为一个 account_id => true 的映射数组 + $thirdUserAccounts = []; + foreach ($hasThirdUser as $user) { + $thirdUserAccounts[$user['account_id']] = true; + } + // 遍历 $googleAdsAccounts 进行合并和匹配 + foreach ($googleAdsAccounts as $login_customer_id => $accounts) { +// dump($accounts); + if (!empty($accounts[$login_customer_id])) { + foreach ($accounts[$login_customer_id] as $account) { + $account_id = $account['account_id']; + $bind = isset($thirdUserAccounts[$account_id]) ? 1 : 0; // 如果匹配则 bind 为 true + $ad_accounts[] = [ + 'account_id' => $account['account_id'], + 'name' => $account['account_name'], + 'currency' => $account['currency'], + 'bind' => $bind, + 'login_customer_id' => $login_customer_id, + ]; + } + } + } + } else { + // 遍历 $googleAdsAccounts 进行合并和匹配 + foreach ($googleAdsAccounts as $login_customer_id => $accounts) { + if (!empty($accounts[$login_customer_id])) { + foreach ($accounts[$login_customer_id] as $account) { + $account_id = $account['account_id']; + $bind = isset($thirdUserAccounts[$account_id]) ? 1 : 0; // 如果匹配则 bind 为 true + $ad_accounts[] = [ + 'account_id' => $account['account_id'], + 'name' => $account['account_name'], + 'currency' => $account['currency'], + 'bind' => $bind, + 'login_customer_id' => $login_customer_id, + ]; + } + } + } + } +// dump($ad_accounts); + return $this->successResponse(['ad_accounts' => $ad_accounts, 'total_count' => count($ad_accounts)]); } else { return $this->errorResponse(300, 'token expired'); @@ -125,6 +157,107 @@ class CustomerController } + //绑定接口-广告主体下层级账号 + public function handleBindingNew(Request $request) + { + $options = $request->all(); + $options['jwtClaims'] = $request->jwtClaims; + +// dump($options,22222222); + // token即uuid 例如:f47ac10b-58cc-4372-a567-0e02b2c3d479 + $redisKey = self::REDIS_KEY_PREFIX . $options['token']; + + // 尝试从 Redis 中获取缓存值 + $refresh_token = Redis::get($redisKey); +// dump($redisKey, $refresh_token, 444444); +// return $this->successResponse($refresh_token); + if ($refresh_token || $options['jwtClaims']['merchant_id']) { +// $options['refresh_token'] = $refresh_token; +// +// $googleAdsAccounts = $this->getAccountHierarchyForBind($options); + $googleOAuthService = new GoogleOAuthService(); + //不论绑定状态 + $hasThirdUserAccounts = $googleOAuthService->getCustomerListNew($options['jwtClaims']['merchant_id']); + // 初始化返回结果数组 + $ad_accounts = []; + if (!empty($hasThirdUserAccounts)) { + foreach ($hasThirdUserAccounts as $account) { + $ad_accounts[] = [ + 'account_id' => $account['account_id'], + 'name' => $account['account_name'], + 'currency' => $account['currency'], + 'bind' => $account['is_unbind'] == 't'? 0 : 1, + ]; + } + } else { + return $this->successResponse(['ad_accounts' => [], 'total_count' => 0]); + } +// dump($ad_accounts); + return $this->successResponse(['ad_accounts' => $ad_accounts, 'total_count' => count($ad_accounts)]); + + } else { + return $this->errorResponse(300, 'token expired'); + } + + } + + //绑定接口-广告主体下层级账号 + public function bind(Request $request) + { + $options = $request->all(); + $options['jwtClaims'] = $request->jwtClaims; + + // 获取 bind_accounts 数据 + $bindAccounts = $options['bind_accounts'] ?? []; + + // 检查是否传递了 bind_accounts + if (empty($bindAccounts)) { + return $this->errorResponse(300, 'No bind_accounts provided'); + } + $redisKey = self::REDIS_KEY_PREFIX . $options['token']; //$options['token'] 即uuid 例如:f47ac10b-58cc-4372-a567-0e02b2c3d479 + + // 尝试从 Redis 中获取缓存值 + $refresh_token = Redis::get($redisKey); +// dump($redisKey, $refresh_token, 444444); +// return $this->successResponse($refresh_token); + if (!$refresh_token) { + return $this->errorResponse(300, 'token expired'); + } + +// $googleAccountInfo = $this->googleOAuthService->getGoogleAccountInfo($refresh_token); + + // 遍历 bind_accounts,保存或更新到 bps_ads_merchant_relation 表 + foreach ($bindAccounts as $account) { + $data = [ + 'account_id' => $account['account_id'], + 'account_name' => $account['name'], + 'currency' => $account['currency'], + 'merchant_id' => $options['jwtClaims']['merchant_id'], // 假设merchant_id从jwtClaims中获取 + 'access_token' => $refresh_token, + 'refresh_token' => $refresh_token, + 'is_unbind' => 'f' // 假设默认绑定状态为 'f' +// 'platform_user_id' => $googleAccountInfo['id'], +// 'platform_user_name' => $googleAccountInfo['name'], + //ext_info是jsonb 存放 $account['login_customer_id']的键值对 +// 'ext_info' => json_encode(['login_customer_id' => $account['login_customer_id']]), + ]; + $this->googleOAuthService->saveThirdUserAdvertiserNew($data,1); + // 查找是否已经存在该账号的绑定记录 +// $existingRelation = \App\Models\AdsMerchantRelation::where('account_id', $account['account_id']) +// ->where('merchant_id', $options['jwtClaims']['merchant_id']) +// ->first(); +// +// if ($existingRelation) { +// // 如果记录已存在,更新 +// $existingRelation->update($data); +// } else { +// // 如果记录不存在,插入新数据 +// \App\Models\AdsMerchantRelation::create($data); +// } + } + return $this->successResponse(['success' => 'Accounts successfully bound']); + } + // 没调用 管理用户访问权限 public function accountAccess(Request $request) { diff --git a/app/controller/OAuthController.php b/app/controller/OAuthController.php index f02d69c..49decac 100644 --- a/app/controller/OAuthController.php +++ b/app/controller/OAuthController.php @@ -41,6 +41,7 @@ class OAuthController ], $request); } + //废弃2025-2-13 public function listThirdUserInfos(Request $request) { $options = $request->all(); @@ -66,11 +67,11 @@ class OAuthController } - //作废2025-2-13 public function handleCallback(Request $request) { // $state = $request->input('state') ?? $request->jwtClaims['uid']; $state = $request->input('state') ?? $request->jwtClaims['merchant_id']; + $merchantId = $request->jwtClaims['merchant_id']; $code = $request->input('code'); // 授权码 if (!$state) { @@ -87,13 +88,25 @@ class OAuthController } return $this->errorResponse(300, 'Refresh Token getting failed'); } else { - $googleOAuthService->saveRefreshToken($tokens['refresh_token'], $state); - } +// $googleOAuthService->saveRefreshToken($tokens['refresh_token'], $state); //作废2025-2-13 + $googleOAuthService->saveRefreshTokenNew($tokens['refresh_token'], $merchantId); + // 生成 UUID + $uuid = $this->generateUuid(); + // echo $uuid; // 例如:f47ac10b-58cc-4372-a567-0e02b2c3d479 + $redisKey = self::REDIS_KEY_PREFIX . $uuid; + //把$tokens['refresh_token']存入redis的redisKey, 并设置过期时间为10分钟 + Redis::setex($redisKey, 600, $tokens['refresh_token']); + // 保存refresh token到数据库 + // $googleOAuthService->saveRefreshToken($tokens['refresh_token'], $state, $uuid); + // // 触发事件 + return $this->successResponse(['token' => $uuid], $request); + } return $this->successResponse($tokens, $request); } + //另一种方案,暂时没用 public function handleCallbackNew(Request $request) { // $state = $request->input('state') ?? $request->jwtClaims['uid']; diff --git a/app/event/GoogleAdsAds.php b/app/event/GoogleAdsAds.php index 277ba44..d923ad2 100644 --- a/app/event/GoogleAdsAds.php +++ b/app/event/GoogleAdsAds.php @@ -2,6 +2,7 @@ namespace app\event; +use app\service\BpsAdAccountService; use app\service\GoogleAdsAdService; use app\service\GoogleOAuthService; use Google\ApiCore\ApiException; @@ -24,6 +25,12 @@ class GoogleAdsAds private $googleOAuthService; + /** + * @Inject + * @var BpsAdAccountService + */ + + private $bpsAdAccountService; const event = 'googleads:ads:event'; const queue = 'googleads:ads:queue'; @@ -31,14 +38,15 @@ class GoogleAdsAds public function syncAds($options = []) { - $queue = self::queue; - $customers = $this->googleOAuthService->getGoogleAdCustomers($options); + $queue = self::queue; +// $customers = $this->googleOAuthService->getGoogleAdCustomers($options); + $customers = $this->bpsAdAccountService->getGoogleAdAccounts($options); foreach ($customers as $customer) { if ($customer['login_customer_id'] > 0) { - Redis::send($queue, $customer,rand(1,10)); + Redis::send($queue, $customer, rand(1, 10)); } } - return self::event.' send queue ok'; + return self::event . ' send queue ok'; } /** @@ -47,9 +55,9 @@ class GoogleAdsAds */ public function getAds($customer) { - $googleAdsAdService = new GoogleAdsAdService($customer['customer_id']); + $googleAdsAdService = new GoogleAdsAdService($customer['account_id']); if ($customer['login_customer_id'] > 0) { - $resourceName = $googleAdsAdService->runListAds($customer['customer_id'], $customer); + $resourceName = $googleAdsAdService->runListAds($customer['account_id'], $customer); } // return $this->successResponse(['ads_list' => $resourceName]); } diff --git a/app/event/GoogleAdsAssetRelations.php b/app/event/GoogleAdsAssetRelations.php index 9264c60..eff40f0 100644 --- a/app/event/GoogleAdsAssetRelations.php +++ b/app/event/GoogleAdsAssetRelations.php @@ -2,6 +2,7 @@ namespace app\event; +use app\service\BpsAdAccountService; use app\service\GoogleAdsAssetRelationService; use app\service\GoogleOAuthService; use Google\ApiCore\ApiException; @@ -21,25 +22,33 @@ class GoogleAdsAssetRelations private $googleOAuthService; + /** + * @Inject + * @var BpsAdAccountService + */ + + private $bpsAdAccountService; + const event = 'googleads:assetrelations:event'; const queue = 'googleads:assetrelations:queue'; const video_queue = 'googleads:assetrelations:video_queue'; - //2025-2-11作废,改用syncDateRangeAssetRelations + //废弃2025-2-13,改用syncDateRangeAssetRelations public function syncAssetRelations($options = []) { - $queue = self::queue; - $video_queue = self::video_queue; - $customers = $this->googleOAuthService->getGoogleAdCustomers($options); + $queue = self::queue; + $video_queue = self::video_queue; +// $customers = $this->googleOAuthService->getGoogleAdCustomers($options); + $customers = $this->bpsAdAccountService->getGoogleAdAccounts($options); // dump($customers); foreach ($customers as $customer) { if ($customer['login_customer_id'] > 0) { - Redis::send($queue, $customer,rand(5,15)); - Redis::send($video_queue, $customer,rand(5,15)); + Redis::send($queue, $customer, rand(5, 15)); + Redis::send($video_queue, $customer, rand(5, 15)); } } - return self::event.' send queue ok'; + return self::event . ' send queue ok'; } public function syncDateRangeAssetRelations($options = []) @@ -57,9 +66,10 @@ class GoogleAdsAssetRelations $startDate = new \DateTime($startDate); $endDate = new \DateTime($endDate); - $queue = self::queue; - $video_queue = self::video_queue; - $customers = $this->googleOAuthService->getGoogleAdCustomers($options); + $queue = self::queue; + $video_queue = self::video_queue; +// $customers = $this->googleOAuthService->getGoogleAdCustomers($options); + $customers = $this->bpsAdAccountService->getGoogleAdAccounts($options); // dump($customers); // 遍历每一天的日期 $interval = new \DateInterval('P1D'); // 1天间隔 @@ -74,7 +84,7 @@ class GoogleAdsAssetRelations } } } - return self::event.' send queue ok'; + return self::event . ' send queue ok'; } /** @@ -84,8 +94,8 @@ class GoogleAdsAssetRelations public function getAssetRelations($customer) { if ($customer['login_customer_id'] > 0) { - $googleAdsAssetRelationService = new GoogleAdsAssetRelationService($customer['customer_id']); - $resourceName = $googleAdsAssetRelationService->runListAssetRelations($customer['customer_id'],$customer['date']); + $googleAdsAssetRelationService = new GoogleAdsAssetRelationService($customer['account_id']); + $resourceName = $googleAdsAssetRelationService->runListAssetRelations($customer['account_id'], $customer['date']); } // return $this->successResponse(['ads_list' => $resourceName]); } @@ -96,8 +106,8 @@ class GoogleAdsAssetRelations */ public function getVideoAssetRelations($customer) { - $googleAdsAssetRelationService = new GoogleAdsAssetRelationService($customer['customer_id']); - $resourceName = $googleAdsAssetRelationService->runListVideoAssetRelations($customer['customer_id']); + $googleAdsAssetRelationService = new GoogleAdsAssetRelationService($customer['account_id']); + $resourceName = $googleAdsAssetRelationService->runListVideoAssetRelations($customer['account_id']); // return $this->successResponse(['ads_list' => $resourceName]); } diff --git a/app/event/GoogleAdsAssets.php b/app/event/GoogleAdsAssets.php index 4caa8df..75dbfc3 100644 --- a/app/event/GoogleAdsAssets.php +++ b/app/event/GoogleAdsAssets.php @@ -2,6 +2,7 @@ namespace app\event; +use app\service\BpsAdAccountService; use app\service\GoogleAdsAssetService; use app\service\GoogleOAuthService; use Google\ApiCore\ApiException; @@ -24,19 +25,28 @@ class GoogleAdsAssets private $googleOAuthService; + /** + * @Inject + * @var BpsAdAccountService + */ + + private $bpsAdAccountService; + + const event = 'googleads:assets:event'; const queue = 'googleads:assets:queue'; public function syncAssets($options = []) { - $queue = self::queue; - $customers = $this->googleOAuthService->getGoogleAdCustomers($options); + $queue = self::queue; +// $customers = $this->googleOAuthService->getGoogleAdCustomers($options); + $customers = $this->bpsAdAccountService->getGoogleAdAccounts($options); foreach ($customers as $customer) { if ($customer['login_customer_id'] > 0) { - Redis::send($queue, $customer,rand(1,10)); + Redis::send($queue, $customer, rand(1, 10)); } } - return self::event.' send queue ok'; + return self::event . ' send queue ok'; } /** @@ -45,10 +55,10 @@ class GoogleAdsAssets */ public function getAssets($customer) { - $googleAdsAssetService = new GoogleAdsAssetService($customer['customer_id']); - if ($customer['login_customer_id'] >0){ - $resourceName = $googleAdsAssetService->runListAssets($customer['customer_id'],$customer); - } + $googleAdsAssetService = new GoogleAdsAssetService($customer['account_id']); + if ($customer['login_customer_id'] > 0) { + $resourceName = $googleAdsAssetService->runListAssets($customer['account_id'], $customer); + } // return $this->successResponse(['ads_list' => $resourceName]); } diff --git a/app/event/GoogleAdsCampaigns.php b/app/event/GoogleAdsCampaigns.php index 8a07ef6..0875736 100644 --- a/app/event/GoogleAdsCampaigns.php +++ b/app/event/GoogleAdsCampaigns.php @@ -4,6 +4,7 @@ namespace app\event; use app\service\GoogleAdsCampaignService; use app\service\GoogleOAuthService; +use app\service\BpsAdAccountService; use Google\ApiCore\ApiException; use support\Response; use DI\Annotation\Inject; @@ -21,6 +22,12 @@ class GoogleAdsCampaigns */ private $googleOAuthService; + /** + * @Inject + * @var BpsAdAccountService + */ + + private $bpsAdAccountService; const event = 'googleads:campaigns:event'; const queue = 'googleads:campaigns:queue'; @@ -28,7 +35,8 @@ class GoogleAdsCampaigns public function syncCampaigns($options = []): string { $queue = self::queue; - $customers = $this->googleOAuthService->getGoogleAdCustomers($options); +// $customers = $this->googleOAuthService->getGoogleAdCustomers($options); + $customers = $this->bpsAdAccountService->getGoogleAdAccounts($options); foreach ($customers as $customer) { if ($customer['login_customer_id'] >0){ Redis::send($queue,$customer,rand(1,10)); @@ -47,9 +55,9 @@ class GoogleAdsCampaigns // dump($customers); // foreach ($customers as $customer) { // dump($customer); - $googleAdsCampaignService = new googleAdsCampaignService($customer['customer_id']); + $googleAdsCampaignService = new googleAdsCampaignService($customer['account_id']); if ($customer['login_customer_id'] >0){ - $resourceName = $googleAdsCampaignService->runListCampaigns($customer['customer_id'],$customer); + $resourceName = $googleAdsCampaignService->runListCampaigns($customer['account_id'],$customer); } // } diff --git a/app/event/GoogleAdsCreatives.php b/app/event/GoogleAdsCreatives.php index 067beee..987428b 100644 --- a/app/event/GoogleAdsCreatives.php +++ b/app/event/GoogleAdsCreatives.php @@ -2,6 +2,7 @@ namespace app\event; +use app\service\BpsAdAccountService; use app\service\GoogleAdsAssetService; use app\service\GoogleOAuthService; use Google\ApiCore\ApiException; @@ -24,13 +25,23 @@ class GoogleAdsCreatives private $googleOAuthService; + + /** + * @Inject + * @var BpsAdAccountService + */ + + private $bpsAdAccountService; + + const event = 'googleads:creatives:event'; const queue = 'googleads:creatives:queue'; public function syncCreatives($options = []) { $queue = self::queue; - $customers = $this->googleOAuthService->getGoogleAdCustomers($options); +// $customers = $this->googleOAuthService->getGoogleAdCustomers($options); + $customers = $this->bpsAdAccountService->getGoogleAdAccounts($options); foreach ($customers as $customer) { if ($customer['login_customer_id'] > 0) { Redis::send($queue, $customer,rand(1,10)); @@ -45,9 +56,9 @@ class GoogleAdsCreatives */ public function getCreatives($customer) { - $googleAdsAssetService = new GoogleAdsAssetService($customer['customer_id']); + $googleAdsAssetService = new GoogleAdsAssetService($customer['account_id']); if ($customer['login_customer_id'] >0){ - $resourceName = $googleAdsAssetService->runListCreatives($customer['customer_id'],$customer); + $resourceName = $googleAdsAssetService->runListCreatives($customer['account_id'],$customer); } // return $this->successResponse(['ads_list' => $resourceName]); } diff --git a/app/event/GoogleAdsCustomers.php b/app/event/GoogleAdsCustomers.php index 305f355..967e781 100644 --- a/app/event/GoogleAdsCustomers.php +++ b/app/event/GoogleAdsCustomers.php @@ -3,7 +3,7 @@ namespace app\event; use app\model\ThirdUser; -use app\service\GoogleAdsAssetService; +use app\model\BpsAdsMerchantRelation; use app\service\GoogleOAuthService; use app\service\GoogleAdsAccountService; use Google\ApiCore\ApiException; @@ -36,48 +36,7 @@ class GoogleAdsCustomers const add_queue = 'googleads:customers:add:queue'; const init_queue = 'googleads:customers:init:queue'; - public function addCustomers() - { -// dump($options); - $thirdUser = ThirdUser::where('is_default', 'f')->where('third_type', 'google') - ->find(); - if (!$thirdUser || !$thirdUser->access_token) { - dump('not found third user'); - return; - } - $option = []; - $option['refresh_token'] = $thirdUser->access_token; -// dump($option); -// $listAccessibleCustomers = $this->googleAdsAccountService->runListAccessibleCustomers($option); -// dump($listAccessibleCustomers); -// if (getenv('GOOGLE_DEVELOP_TOKEN_LEVEL') === 'test') { -// if (in_array(1509096882, $listAccessibleCustomers)) { -// $option['manager_customer_id'] = 1509096882; //开发者 -// $option['login_customer_id'] = 1509096882; -// } -// if (in_array(1401879025, $listAccessibleCustomers)) { -// $option['manager_customer_id'] = 1401879025; //开发者 -// $option['login_customer_id'] = 1401879025; -// } -// }else{ - //正式开发者令牌2个参数默认不赋值 -// } - $allRootAccounts = $this->googleAdsAccountService->runGetAccountHierarchy($option); -// dump($allRootAccounts); - foreach ($allRootAccounts as $rootAccountId => $accounts) { - foreach ($accounts as $account) { -// $customerId = $account['customer_id']; -// dump($customerId, $thirdUser->id, $rootAccountId, $account); -// if($account['customer_id'] == 1509096882)continue; - $this->googleOAuthService->saveThirdUserAdvertiser($account['customer_id'], $thirdUser->id, $rootAccountId, $account, $thirdUser->merchant_id); - } - } - $this->googleOAuthService->updateThirdUserDefault($thirdUser->id, 't'); -// return $this->successResponse($allAccounts); - - } - - //添加某个root广告账号的全部层级账号 + //添加某个root广告账号的全部层级账号 废弃2025-2-13 public function addRootCustomers() { // dump($options); @@ -133,24 +92,70 @@ class GoogleAdsCustomers } + //添加某个root广告账号的全部层级账号 + public function addRootCustomersNew($options) + { + $refresh_token = $options['refresh_token']; + $merchant_id = $options['merchant_id']; + + $googleAdsAccounts = $this->getAccountHierarchyForBind($options); + // 初始化返回结果数组 + $ad_accounts = []; + + //广告主体的profile信息 通过请求api返回 + $googleAccountInfo = $this->googleOAuthService->getGoogleAccountInfo($refresh_token); + + foreach ($googleAdsAccounts as $login_customer_id => $accounts) { + if (!empty($accounts[$login_customer_id])) { + foreach ($accounts[$login_customer_id] as $account) { + $data = [ + 'account_id' => $account['account_id'], + 'account_name' => $account['account_name'], + 'currency' => $account['currency'], + 'merchant_id' => $merchant_id, + 'access_token' => $refresh_token, + 'refresh_token' => $refresh_token, + 'platform_user_id' => $googleAccountInfo['id'], + 'platform_user_name' => $googleAccountInfo['name'], + 'is_unbind' => 't', + //ext_info是jsonb 存放 $account['login_customer_id']的键值对 + 'ext_info' => json_encode(['login_customer_id' => $account['login_customer_id']]), + ]; + $this->googleOAuthService->saveThirdUserAdvertiserNew($data, 0); + } + } + } +// dump($ad_accounts); +// return $this->successResponse(['ad_accounts' => $ad_accounts, 'total_count' => count($ad_accounts)]); + //绑定的授权主体全部账号更新后 将f改成t +// $this->googleOAuthService->updateThirdUserDefault($thirdUser->id, 't'); +// return $this->successResponse($allAccounts); + + } /** - * get assets + * 绑定接口-广告主体下层级账号 * @throws ApiException */ - public function getAccountHierarchy($options) + public function getAccountHierarchyForBind($options) { - $resourceName = $this->googleAdsAccountService->runGetAccountHierarchy($options); - return $this->successResponse(['links_resource_name' => $resourceName]); - - - $customers = $this->googleOAuthService->getGoogleAdCustomers([]); - foreach ($customers as $customerId) { - $googleAdsAssetService = new GoogleAdsAssetService($customerId); - $resourceName = $googleAdsAssetService->runListAssets($customerId); + //TODO 过滤经理账号 2025-2-13 + $resourceName = []; + $listAccessibleCustomers = $this->googleAdsAccountService->runListAccessibleCustomers($options); + foreach ($listAccessibleCustomers as $rootAccountId) { + $options['manager_customer_id'] = $rootAccountId; //开发者 + $options['login_customer_id'] = $rootAccountId; + try { + // 获取当前 rootAccountId 的所有账户 + $allAccountsByRoot = $this->googleAdsAccountService->runGetAccountHierarchy($options); + $resourceName[$rootAccountId] = $allAccountsByRoot; + } catch (\Exception $e) { + // 记录错误日志并跳过当前循环 + Log::error("Binding Account List Error processing rootAccountId {$rootAccountId}: " . $e->getMessage()); + continue; + } } - -// return $this->successResponse(['ads_list' => $resourceName]); + return $resourceName; } // 可以加入一些公共方法 diff --git a/app/event/GoogleAdsDateDatas.php b/app/event/GoogleAdsDateDatas.php index 232039b..d0486d6 100644 --- a/app/event/GoogleAdsDateDatas.php +++ b/app/event/GoogleAdsDateDatas.php @@ -2,6 +2,7 @@ namespace app\event; +use app\service\BpsAdAccountService; use app\service\GoogleAdsCampaignService; use app\service\GoogleOAuthService; use Google\ApiCore\ApiException; @@ -23,6 +24,14 @@ class GoogleAdsDateDatas private $googleOAuthService; + + /** + * @Inject + * @var BpsAdAccountService + */ + + private $bpsAdAccountService; + const event = 'googleads:datedatas:event'; const queue = 'googleads:datedatas:queue'; const task = 'googleads:datedatas:task'; @@ -47,7 +56,8 @@ class GoogleAdsDateDatas $queue = self::queue; // 获取客户数据 - $customers = $this->googleOAuthService->getGoogleAdCustomers($options); +// $customers = $this->googleOAuthService->getGoogleAdCustomers($options); + $customers = $this->bpsAdAccountService->getGoogleAdAccounts($options); // 遍历每一天的日期 $interval = new \DateInterval('P1D'); // 1天间隔 @@ -76,11 +86,12 @@ class GoogleAdsDateDatas return self::event . ' send queue ok'; } - //同步某天成效 2025-2-11作废,改用syncDateRangeDatas + //同步某天成效 废弃2025-2-13,改用syncDateRangeDatas public function syncDateDatas($options = []) { $queue = self::queue; - $customers = $this->googleOAuthService->getGoogleAdCustomers($options); +// $customers = $this->googleOAuthService->getGoogleAdCustomers($options); + $customers = $this->bpsAdAccountService->getGoogleAdAccounts($options); foreach ($customers as $customer) { if ($customer['login_customer_id'] > 0) { $customer['date'] = $options['date']; @@ -107,12 +118,13 @@ class GoogleAdsDateDatas */ public function getDateDatas($customer) { - - if ($customer['login_customer_id'] > 0 && ((isset($customer['manager']) && $customer['manager'] === false))) { + //新客户表不用检查manager了 +// if ($customer['login_customer_id'] > 0 && ((isset($customer['manager']) && $customer['manager'] === false))) { + if ($customer['login_customer_id'] > 0) { // dump($customer); - $googleAdsCampaignService = new googleAdsCampaignService($customer['customer_id']); + $googleAdsCampaignService = new googleAdsCampaignService($customer['account_id']); // dump($customer['customer_id'],$customer, $options['date']); - $googleAdsCampaignService->runListDateDatas($customer['customer_id'], $customer, $customer['date']); + $googleAdsCampaignService->runListDateDatas($customer['account_id'], $customer, $customer['date']); } // $this->googleAdsCampaignService->runListDateDatas($options['customer_id'], $options['date']); diff --git a/app/event/GoogleAdsGroups.php b/app/event/GoogleAdsGroups.php index 62a2486..8326241 100644 --- a/app/event/GoogleAdsGroups.php +++ b/app/event/GoogleAdsGroups.php @@ -3,6 +3,7 @@ namespace app\event; +use app\service\BpsAdAccountService; use app\service\GoogleAdsGroupService; use app\service\GoogleOAuthService; use Google\ApiCore\ApiException; @@ -23,6 +24,12 @@ class GoogleAdsGroups private $googleOAuthService; + /** + * @Inject + * @var BpsAdAccountService + */ + + private $bpsAdAccountService; const event = 'googleads:groups:event'; const queue = 'googleads:groups:queue'; @@ -31,7 +38,8 @@ class GoogleAdsGroups public function syncGroups($options = []) { $queue = self::queue; - $customers = $this->googleOAuthService->getGoogleAdCustomers($options); +// $customers = $this->googleOAuthService->getGoogleAdCustomers($options); + $customers = $this->bpsAdAccountService->getGoogleAdAccounts($options); foreach ($customers as $customer) { if ($customer['login_customer_id'] > 0) { Redis::send($queue,$customer,rand(1,10)); @@ -47,9 +55,9 @@ class GoogleAdsGroups public function getGroups($customer) { - $googleAdsGroupService = new GoogleAdsGroupService($customer['customer_id']); + $googleAdsGroupService = new GoogleAdsGroupService($customer['account_id']); if ($customer['login_customer_id'] > 0) { - $resourceName = $googleAdsGroupService->runListGroups($customer['customer_id'], $customer); + $resourceName = $googleAdsGroupService->runListGroups($customer['account_id'], $customer); } // return $this->successResponse(['groups_list' => $resourceName]); } diff --git a/app/queue/redis/GoogleAdsCustomerInitQueue.php b/app/queue/redis/GoogleAdsCustomerInitQueue.php index c73735f..04036a9 100644 --- a/app/queue/redis/GoogleAdsCustomerInitQueue.php +++ b/app/queue/redis/GoogleAdsCustomerInitQueue.php @@ -26,7 +26,7 @@ class GoogleAdsCustomerInitQueue implements Consumer { dump($this->queue . ' consumed', $data); //新绑定的客户,立即同步广告系列 - + //$data包含merchant_id,account_id Event::emit(GoogleAdsCampaigns::event, $data); //新绑定的客户,立即同步广告组 Event::emit(GoogleAdsGroups::event, $data); diff --git a/app/service/BpsAdAccountService.php b/app/service/BpsAdAccountService.php index 073e558..05b7515 100644 --- a/app/service/BpsAdAccountService.php +++ b/app/service/BpsAdAccountService.php @@ -49,20 +49,27 @@ class BpsAdAccountService { if (!empty($options)) { $merchant_id = $options['merchant_id']; - $customers = BpsAdsMerchantRelation::alias('bamr') + $account_id = $options['account_id'] ?? null; // 从 $options 中获取 account_id,如果没有则默认为 null + $query = BpsAdsMerchantRelation::alias('bamr') ->where('bamr.platform', 2) ->where('bamr.merchant_id', $merchant_id) ->where('bamr.is_unbind', 'f') - ->where('bamr.is_del', 'f') - ->field('bamr.account_id, bamr.refresh_token') - ->select(); // 执行查询 + ->where('bamr.is_del', 'f'); + // 如果传入了 account_id,则增加 account_id 的过滤条件 + if (!empty($account_id)) { + $query->where('bamr.account_id', $account_id); + } + // 选择需要的字段 + $customers = $query->field('bamr.account_id, bamr.refresh_token, bamr.ext_info->>\'login_customer_id\' as login_customer_id') + ->select(); // 执行查询 } else { // 获取符合条件的客户ID数组 $customers = ThirdUserAdvertiser::alias('bamr') ->where('bamr.platform', 2) ->where('bamr.is_unbind', 'f') ->where('bamr.is_del', 'f') - ->field('bamr.account_id, bamr.refresh_token') +// ->field('bamr.account_id, bamr.refresh_token') + ->field('bamr.account_id, bamr.refresh_token, bamr.ext_info->>\'login_customer_id\' as login_customer_id') // 提取 ext_info 中的 login_customer_id ->select(); // 执行查询 } diff --git a/app/service/GoogleAdsAccountService.php b/app/service/GoogleAdsAccountService.php index b246ed6..743a973 100644 --- a/app/service/GoogleAdsAccountService.php +++ b/app/service/GoogleAdsAccountService.php @@ -736,16 +736,16 @@ class GoogleAdsAccountService extends BaseService // Store the current customer ID and descriptive name in the result array $customerId = $customerClient->getId(); //如果$customerClient->getManager()是true则不记录到$result数组中 - if (!$customerClient->getManager()) { + if (!$customerClient->getManager() && !$customerClient->getTestAccount()) { $result[] = [ - 'customer_id' => $customerId, - 'descriptive_name' => $customerClient->getDescriptiveName(), - 'manager' => $customerClient->getManager(), - 'test_account' => $customerClient->getTestAccount(), + 'account_id' => $customerId, + 'account_name' => $customerClient->getDescriptiveName(), +// 'manager' => $customerClient->getManager(), +// 'test_account' => $customerClient->getTestAccount(), 'currency' => $customerClient->getCurrencyCode(), - 'status' => $customerClient->getStatus(), - 'level' => $customerClient->getLevel(), - 'time_zone' => $customerClient->getTimeZone(), +// 'status' => $customerClient->getStatus(), +// 'level' => $customerClient->getLevel(), +// 'time_zone' => $customerClient->getTimeZone(), ]; } diff --git a/app/service/GoogleOAuthService.php b/app/service/GoogleOAuthService.php index f9506ea..edd71f4 100644 --- a/app/service/GoogleOAuthService.php +++ b/app/service/GoogleOAuthService.php @@ -124,12 +124,13 @@ class GoogleOAuthService { // dump($merchant_id,555); //$userId = $options['uid']; // 获取用户ID - $customers = BpsAdsMerchantRelation::alias('bamr') + $customers = BpsAdsMerchantRelation::alias('bamr') ->where('bamr.merchant_id', $merchant_id) - ->where('bamr.is_unbind', 'f') +// ->where('bamr.is_unbind', 'f') ->where('bamr.is_del', 'f') ->where('bamr.platform', 2) - ->field('bamr.account_id, bamr.access_token as refresh_token') + ->field('bamr.account_id, bamr.account_name,bamr.currency') +// ->field('') ->select(); // 执行查询 // dump($customers,555); // 打印调试 SQL 查询 @@ -143,7 +144,7 @@ class GoogleOAuthService return $customers->toArray(); } - //保存或更新某个主体部广告账号 + //保存或更新某个主体部广告账号 废弃2025-2-13 public function saveThirdUserAdvertiser($customer_id, $third_user_id, $login_customer_id, $customer, $merchant_id) { // 确保 customer_id 和 third_user_id 是字符串 @@ -186,6 +187,58 @@ class GoogleOAuthService ThinkDb::execute($sql, $data); } + //保存或更新某个主体部广告账号 + public function saveThirdUserAdvertiserNew($data,$sendMq = 0) + { + // 确保 account_id 和 merchant_id 是字符串 + $data['account_id'] = (string)$data['account_id']; + $data['merchant_id'] = (string)$data['merchant_id']; + + $tableName = 'bps_ads_merchant_relation'; + $tableName = getenv('DB_PG_SCHEMA') ? getenv('DB_PG_SCHEMA') . '.' . $tableName : 'bps.' . $tableName; + + // 构造插入或更新的数据 + $insertData = [ + 'platform' => 2, // 假设google平台值为2,根据实际情况调整 + 'merchant_id' => $data['merchant_id'], + 'account_id' => $data['account_id'], + 'access_token' => $data['access_token'], + 'refresh_token' => $data['refresh_token'], + 'account_name' => $data['account_name'], + 'currency' => $data['currency'], + 'platform_user_id' => $data['platform_user_id']??'', + 'platform_user_name' => $data['platform_user_name']??'', + 'is_unbind' => $data['is_unbind']??'f', + 'ext_info' => $data['ext_info']??'{}', + ]; + + // 构造SQL语句 + $sql = " + INSERT INTO {$tableName} + (platform, merchant_id, access_token, refresh_token,account_id, account_name, currency, ext_info,platform_user_id, platform_user_name) + VALUES (:platform, :merchant_id, :access_token, :refresh_token, :account_id, :account_name, :currency, :ext_info,:platform_user_id, :platform_user_name) + ON CONFLICT (account_id, merchant_id) + DO UPDATE SET + account_name = EXCLUDED.account_name, + access_token = EXCLUDED.access_token, + refresh_token = EXCLUDED.refresh_token, + is_unbind = EXCLUDED.is_unbind, + currency = EXCLUDED.currency, + updated_at = CURRENT_TIMESTAMP"; + + // 执行SQL语句 + ThinkDb::execute($sql, $insertData); + + //如果要异步更新改广告账号数据的话。 + if($sendMq == 1){ + // Event::emit(GoogleAdsCustomers::add_queue, $data); + $options = []; + $options['merchant_id'] = $data['merchant_id']; + $options['account_id'] = $data['account_id']; + $this->queueNew($options); + } + } + public function updateThirdUserDefault($third_user_id, $is_default = 't'): void { $tableName = 'bps_third_user'; @@ -201,7 +254,7 @@ class GoogleOAuthService ThinkDb::execute($sql, $data); } - + //废弃2025-2-13 public function saveRefreshToken($refreshToken, $state = '') { // 使用ThinkORM保存数据到bps_third_user表 @@ -256,6 +309,20 @@ class GoogleOAuthService $this->queue($options); } + public function saveRefreshTokenNew($refreshToken, $merchantId) + { + $data = [ + 'refresh_token' => $refreshToken, + 'merchant_id' => $merchantId, +// 'is_default' => 'f', +// 'third_type' => 'google', + ]; + $options = []; + $options['refresh_token'] = $refreshToken; + Event::emit(GoogleAdsCustomers::add_queue, $data); + $this->queue($options); + } + public function initNewGoogleAdsAccountData($refreshToken) { @@ -311,7 +378,7 @@ class GoogleOAuthService * 批量获取全部Google广告账号数据 * 作废2025-2-13 */ - public function getGoogleAdCustomers($options = []) + public function getGoogleAdCustomersBak($options = []) { if (!empty($options['refresh_token'])) { $refreshToken = $options['refresh_token']; @@ -343,6 +410,7 @@ class GoogleOAuthService } + //废弃2025-2-13 public function queue($options = []): string { // 队列名 @@ -359,5 +427,21 @@ class GoogleOAuthService return $queue2 . ' redis queue ok'; } + public function queueNew($options = []): string + { + // 队列名 +// $queue = GoogleAdsCustomers::add_queue; + $queue2 = GoogleAdsCustomers::init_queue; + // 数据,可以直接传数组,无需序列化 +// $options = ['to' => 'tom@gmail.com', 'content' => 'hello']; + // 投递消息 +// Redis::send($queue, $options['data']); + QueueClient::send($queue2, $options); //异步投递 延后15秒 + // 投递延迟消息,消息会在60秒后处理 +// Redis::send($queue, $options['data'], 60); + + return $queue2 . ' redis queue ok'; + } + } \ No newline at end of file diff --git a/config/event.php b/config/event.php index 3ce3809..5da5b95 100644 --- a/config/event.php +++ b/config/event.php @@ -76,10 +76,10 @@ return [ // [GoogleAdsDateDatas::class, 'noticeDateDatas'], // ], GoogleAdsCustomers::event => [ - [GoogleAdsCustomers::class, 'addRootCustomers'], + [GoogleAdsCustomers::class, 'addRootCustomersNew'], ], GoogleAdsCustomers::add_queue => [ - [GoogleAdsCustomers::class, 'addRootCustomers'], + [GoogleAdsCustomers::class, 'addRootCustomersNew'], ], ShopifyOrders::event => [ diff --git a/config/redis.php b/config/redis.php index 0708352..429cb22 100644 --- a/config/redis.php +++ b/config/redis.php @@ -17,6 +17,6 @@ return [ 'host' => getenv('REDIS_HOST'), 'password' => getenv('REDIS_PASSWORD'), 'port' => 6379, - 'database' => 9, + 'database' => 0, ], ]; diff --git a/config/route.php b/config/route.php index 61f3935..7f73787 100644 --- a/config/route.php +++ b/config/route.php @@ -16,6 +16,7 @@ use app\controller\AdController; use app\controller\BpsAdController; use app\controller\OAuthController; +//use app\controller\NoticeController; use app\controller\CustomerController; use app\controller\GoogleAdsController; use support\Request; @@ -103,6 +104,19 @@ Route::group('/marketing', function () { app\middleware\JwtLocal::class, app\middleware\OauthThirdCheck::class, ]); +// Route::group('/notice', function () { +// Route::post('/init_ads_account', [NoticeController::class, 'initNewGoogleAdsAccountData']); +// }); + Route::group('/customer', function () { + Route::get('/handle_binding', [CustomerController::class, 'handleBindingNew']); //绑定接口 + })->middleware([ + app\middleware\JwtLocal::class, + ]); + Route::group('/customer', function () { + Route::get('/bind', [CustomerController::class, 'bind']); //绑定接口 + })->middleware([ + app\middleware\JwtLocal::class, + ]); }); }); @@ -152,9 +166,9 @@ Route::group('/googleads', function () { app\middleware\OauthCheck::class, ]); Route::group('/customer', function () { - Route::post('/list', [CustomerController::class, 'getCustomerList']); - Route::post('/list_resource', [CustomerController::class, 'accessibleCustomers']); - Route::post('/list_tree', [CustomerController::class, 'accountHierarchy']); + Route::post('/list', [CustomerController::class, 'getCustomerList']); //调试用 + Route::post('/list_resource', [CustomerController::class, 'accessibleCustomers']); //调试用 + Route::post('/list_tree', [CustomerController::class, 'accountHierarchy']); //调试用 Route::post('/access_role', [CustomerController::class, 'accountAccess']); })->middleware([ app\middleware\JwtLocal::class, @@ -163,12 +177,13 @@ Route::group('/googleads', function () { Route::group('/auth', function () { Route::get('/code', [OAuthController::class, 'getAuthCode']); - Route::post('/callback', [OAuthController::class, 'handleCallback']); + Route::post('/callback', [OAuthController::class, 'handleCallback']); // 授权回调 +// Route::post('/auth_callback', [OAuthController::class, 'handleCallbackNew']); //对接育才的授权回调 Route::post('/refresh_token_get', [OAuthController::class, 'getRefreshToken']); Route::post('/refresh_token_use', [OAuthController::class, 'useRefreshToken']); Route::post('/refresh_token_test', [OAuthController::class, 'testRefreshToken']); Route::post('/refresh_token_revoke', [OAuthController::class, 'revokeRefreshToken']); - Route::post('/list_third_status', [OAuthController::class, 'listThirdUserInfos']); + Route::post('/list_third_status', [OAuthController::class, 'listThirdUserInfos']); //作废2025-2-13 })->middleware([ app\middleware\JwtLocal::class, ]);