From 17ee8aa79bb26b78d4b7b20512727dd867ca75ff Mon Sep 17 00:00:00 2001 From: hgc Date: Sat, 21 Dec 2024 14:47:22 +0800 Subject: [PATCH] =?UTF-8?q?=E5=88=9B=E5=BB=BA=20=20=E6=9B=B4=E6=94=B9campa?= =?UTF-8?q?ign=E3=80=81adgroup=E3=80=81ad=E7=8A=B6=E6=80=81=E7=9A=84?= =?UTF-8?q?=E6=8E=A5=E5=8F=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/controller/AdController.php | 177 ++++++++++++++++++++++- app/controller/OAuthController.php | 37 ++++- app/model/Ad.php | 50 ++++++- app/model/AdGroup.php | 47 ++++++ app/model/Campaign.php | 52 ++++++- app/model/ThirdUser.php | 20 ++- app/model/ThirdUserAdvertiser.php | 49 +++++++ app/process/UpdateGoogleAdsTask.php | 30 ++-- app/service/BaseService.php | 104 +++++++++++++ app/service/GoogleAdsAdService.php | 142 ++++++++++++++---- app/service/GoogleAdsCampaignService.php | 105 +++++++++++--- app/service/GoogleAdsGroupService.php | 132 ++++++++++++++--- config/route.php | 24 ++- 13 files changed, 864 insertions(+), 105 deletions(-) create mode 100644 app/model/ThirdUserAdvertiser.php create mode 100644 app/service/BaseService.php diff --git a/app/controller/AdController.php b/app/controller/AdController.php index a037e28..5c17466 100644 --- a/app/controller/AdController.php +++ b/app/controller/AdController.php @@ -2,11 +2,15 @@ namespace app\controller; +use app\service\GoogleAdsCampaignService; +use app\service\GoogleAdsGroupService; +use app\service\GoogleAdsAdService; use app\service\GoogleAdsReportService; use support\Request; use support\Response; use DI\Annotation\Inject; + class AdController { @@ -16,6 +20,24 @@ class AdController */ private $googleAdsReportService; + /** + * @Inject + * @var GoogleAdsGroupService + */ + private $googleAdsGroupService; + + /** + * @Inject + * @var GoogleAdsAdService + */ + private $googleAdsAdService; + + /** + * @Inject + * @var GoogleAdsCampaignService + */ + private $googleAdsCampaignService; + public function listAds(Request $request) { // 获取请求参数 @@ -44,7 +66,7 @@ class AdController public function exportAdsToExcel(Request $request) { - $keyword = $request->input('keyword', ''); // 获取关键字参数 + $keyword = $request->input('keyword', ''); // 获取关键字参数 $dateRange = $request->input('date_range', ''); // 获取日期范围参数 // 调用 service 层导出数据 @@ -53,7 +75,7 @@ class AdController public function exportCampaignsToExcel(Request $request) { - $keyword = $request->input('keyword', ''); // 获取关键字参数 + $keyword = $request->input('keyword', ''); // 获取关键字参数 $dateRange = $request->input('date_range', ''); // 获取日期范围参数 // 调用 service 层导出数据 @@ -62,7 +84,7 @@ class AdController public function exportGroupsToExcel(Request $request) { - $keyword = $request->input('keyword', ''); // 获取关键字参数 + $keyword = $request->input('keyword', ''); // 获取关键字参数 $dateRange = $request->input('date_range', ''); // 获取日期范围参数 // 调用 service 层导出数据 @@ -82,6 +104,155 @@ class AdController return $this->successResponse($result); } + + /** + * 获取广告系列的状态 备用 + */ +// public function getCampaignStatus(int $campaignId): Response +// { +// try { +// $status = $this->googleAdsCampaignService->getCampaignStatus($campaignId); +// return $this->successResponse(['status' => $status]); +// } catch (ValidateException $e) { +// return $this->errorResponse(400, $e->getMessage()); +// } +// } + + /** + * 更新广告系列的状态 + */ + public function updateCampaignStatus(Request $request): Response + { + $campaignStatus = [ + 0, // UNSPECIFIED + 1, // UNKNOWN + 2, // ENABLED + 3, // PAUSED + 4, // REMOVED + ]; + $requestData = $request->all(); // 获取请求数据 + $customerId = $requestData['customer_id']; + $campaignId = $requestData['campaign_id']; + $status = $requestData['status']; + if (!in_array($status, $campaignStatus)) { + return $this->errorResponse(101, 'status参数错误'); + } +// try { + $reslut = $this->googleAdsCampaignService->updateCampaignStatus($customerId, $campaignId, $status); + if (!$reslut) { + return $this->errorResponse(101, 'Status update failed'); + } + return $this->successResponse(['message' => 'Status updated successfully']); +// } catch (ValidateException $e) { +// return $this->errorResponse(400, $e->getMessage()); +// } + } + + /** + * 判断广告系列是否启用 + */ +// public function isEnabled(int $campaignId): Json +// { +// try { +// $isEnabled = $this->campaignService->isCampaignEnabled($campaignId); +// return json(['enabled' => $isEnabled], 200); +// } catch (ValidateException $e) { +// return json(['error' => $e->getMessage()], 400); +// } +// } + + /** + * 判断广告系列是否暂停 + */ +// public function isPaused(int $campaignId): Json +// { +// try { +// $isPaused = $this->campaignService->isCampaignPaused($campaignId); +// return json(['paused' => $isPaused], 200); +// } catch (ValidateException $e) { +// return json(['error' => $e->getMessage()], 400); +// } +// } + + /** + * 判断广告系列是否停止 + */ +// public function isStopped(int $campaignId): Json +// { +// try { +// $isStopped = $this->campaignService->isCampaignStopped($campaignId); +// return json(['stopped' => $isStopped], 200); +// } catch (ValidateException $e) { +// return json(['error' => $e->getMessage()], 400); +// } +// } +// + + /** + * 更新广告组的状态 + */ + public function updateGroupStatus(Request $request): Response + { + $adGroupStatus = [ + 0, // UNSPECIFIED + 1, // UNKNOWN + 2, // ENABLED + 3, // PAUSED + 4 // REMOVED + ]; + + $requestData = $request->all(); // 获取请求数据 + $customerId = $requestData['customer_id']; + $groupId = $requestData['group_id']; + $status = $requestData['status']; + // $options['bid_micro_amount'] = $options['amount'] * 1000000 < 0 ? 0 : $options['amount'] * 1000000; + if (!in_array($status, $adGroupStatus)) { + return $this->errorResponse(101, 'status参数错误'); + } +// try { + $result = $this->googleAdsGroupService->updateGroupStatus($customerId, $groupId, $status); + if (!$result) { + return $this->errorResponse(101, 'Status update failed'); + } + return $this->successResponse(['message' => 'Status updated successfully']); +// } catch (ValidateException $e) { +// return $this->errorResponse(400, $e->getMessage()); +// } + } + + /** + * 更新广告的状态 + */ + public function updateAdStatus(Request $request): Response + { + $adStatus = [ + 0, // UNSPECIFIED + 1, // UNKNOWN + 2, // ENABLED + 3, // PAUSED + 4 // REMOVED + ]; + + $requestData = $request->all(); // 获取请求数据 + $customerId = $requestData['customer_id']; + $groupId = $requestData['group_id']; + $adId = $requestData['ad_id']; + $status = $requestData['status']; + if (!in_array($status, $adStatus)) { + return $this->errorResponse(101, 'status参数错误'); + } +// try { + $result = $this->googleAdsAdService->updateAdStatus($customerId, $groupId, $adId, $status); + if (!$result) { + return $this->errorResponse(101, 'Status update failed'); + } + return $this->successResponse(['message' => 'Status updated successfully']); +// } catch (ValidateException $e) { +// return $this->errorResponse(400, $e->getMessage()); +// } + } + + // 可以加入一些公共方法 protected function successResponse($data): Response { diff --git a/app/controller/OAuthController.php b/app/controller/OAuthController.php index 674eaae..c8aec23 100644 --- a/app/controller/OAuthController.php +++ b/app/controller/OAuthController.php @@ -6,6 +6,8 @@ use app\service\GoogleOAuthService; use support\Request; use support\Response; use DI\Annotation\Inject; +use app\model\ThirdUserAdvertiser; +use app\model\ThirdUser; class OAuthController { @@ -29,7 +31,7 @@ class OAuthController public function handleCallback(Request $request) { // $state = $request->input('state'); // 从Google回调中获取state - $code = $request->input('code'); // 授权码 + $code = $request->input('code'); // 授权码 // 验证state值是否与保存的值一致 // if ($state !== $_SESSION['oauth_state']) { @@ -45,7 +47,7 @@ class OAuthController public function getRefreshToken(Request $request) { - $authCode = $request->input('code'); + $authCode = $request->input('code'); // $state = $request->input('state'); // 从Google回调中获取state // 验证state值是否与保存的值一致 // if ($state !== $_SESSION['oauth_state']) { @@ -55,7 +57,7 @@ class OAuthController $tokens = $googleOAuthService->getRefreshToken($authCode); if (!isset($tokens['refresh_token'])) { - return $this->successResponse($tokens); + return $this->successResponse($tokens); } // 保存refresh token到数据库 // $googleOAuthService->saveRefreshToken($tokens['refresh_token'], $tokens['access_token'], $request->user_id); @@ -74,7 +76,7 @@ class OAuthController public function revokeRefreshToken(Request $request) { - $accessToken = $request->input('token'); //access token + $accessToken = $request->input('token'); //access token $googleOAuthService = new GoogleOAuthService(); $googleOAuthService->revokeToken($accessToken); @@ -83,6 +85,33 @@ class OAuthController } + public function testRefreshToken(Request $request) + { + // 使用 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(); // 获取第一个结果 + +// 如果找到广告主数据 + 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 { diff --git a/app/model/Ad.php b/app/model/Ad.php index 31ee750..bb3e38a 100644 --- a/app/model/Ad.php +++ b/app/model/Ad.php @@ -25,12 +25,58 @@ class Ad extends Model 'ad_group_id' => 'int', 'customer_id' => 'int', ]; - // 默认值设置 protected $defaults = [ - 'status' => 'ENABLED', // 广告状态默认值为 'ENABLED' + 'status' => 1, // 广告状态默认值为 'ENABLED' ]; + // 状态判断常量 + const STATUS_UNSPECIFIED = 0; + const STATUS_UNKNOWN = 1; + const STATUS_ENABLED = 2; + const STATUS_PAUSED = 3; + const STATUS_REMOVED = 4; + + // 获取广告状态 + public function getStatusTextAttr($value, $data) + { + $statusMap = [ + self::STATUS_UNSPECIFIED => 'UNSPECIFIED', + self::STATUS_UNKNOWN => 'UNKNOWN', + self::STATUS_ENABLED => 'ENABLED', + self::STATUS_PAUSED => 'PAUSED', + self::STATUS_REMOVED => 'REMOVED', + ]; + return $statusMap[$data['status']] ?? 'UNKNOWN'; + } + + // 更新广告状态 +// public function updateStatus($status) +// { +// if (!in_array($status, [self::STATUS_ENABLED, self::STATUS_PAUSED, self::STATUS_REMOVED])) { +//// throw new \think\exception\ValidateException('Invalid status'); +// } +// +// $this->status = $status; +// return $this->save(); +// } + + // 判断广告状态 + public function isEnabled() + { + return $this->status == self::STATUS_ENABLED; + } + + public function isPaused() + { + return $this->status == self::STATUS_PAUSED; + } + + public function isRemoved() + { + return $this->status == self::STATUS_REMOVED; + } + // 关联 AdGroup 模型(广告属于广告组) // 即使没有外键约束,依然可以使用 belongsTo 访问 AdGroup 数据 public function adGroup() diff --git a/app/model/AdGroup.php b/app/model/AdGroup.php index 572133c..ad90d6c 100644 --- a/app/model/AdGroup.php +++ b/app/model/AdGroup.php @@ -32,6 +32,53 @@ class AdGroup extends Model 'cpc_bid_micros' => 0, // 每次点击出价默认值为0 ]; + // 状态判断常量 + const STATUS_UNSPECIFIED = 0; + const STATUS_UNKNOWN = 1; + const STATUS_ENABLED = 2; + const STATUS_PAUSED = 3; + const STATUS_REMOVED = 4; + // 获取广告组状态 + public function getStatusTextAttr($value, $data) + { + $statusMap = [ + self::STATUS_UNSPECIFIED => 'UNSPECIFIED', + self::STATUS_UNKNOWN => 'UNKNOWN', + self::STATUS_ENABLED => 'ENABLED', + self::STATUS_PAUSED => 'PAUSED', + self::STATUS_REMOVED => 'REMOVED', + ]; + return $statusMap[$data['status']] ?? 'UNKNOWN'; + } + + // 更新广告组状态 +// public function updateStatus($status) +// { +// if (!in_array($status, [self::STATUS_ENABLED, self::STATUS_PAUSED, self::STATUS_REMOVED])) { +//// throw new \think\exception\ValidateException('Invalid status'); +// } +// +// $this->status = $status; +// return $this->save(); +// } + + // 判断广告组状态 + public function isEnabled() + { + return $this->status == self::STATUS_ENABLED; + } + + public function isPaused() + { + return $this->status == self::STATUS_PAUSED; + } + + public function isRemoved() + { + return $this->status == self::STATUS_REMOVED; + } + + // 关联 Campaign 模型(广告组属于广告活动) public function campaign() { diff --git a/app/model/Campaign.php b/app/model/Campaign.php index 604ac4e..2e2163e 100644 --- a/app/model/Campaign.php +++ b/app/model/Campaign.php @@ -32,6 +32,56 @@ class Campaign extends Model 'advertising_channel_type' => 'SEARCH', // 广告渠道类型默认值为 'SEARCH' ]; + + // 状态判断常量 + const STATUS_UNSPECIFIED = 0; + const STATUS_UNKNOWN = 1; + const STATUS_ENABLED = 2; + const STATUS_PAUSED = 3; + const STATUS_REMOVED = 4; + + // 获取活动状态 + public function getStatusTextAttr($value, $data) + { + $statusMap = [ + self::STATUS_UNSPECIFIED => 'UNSPECIFIED', + self::STATUS_UNKNOWN => 'UNKNOWN', + self::STATUS_ENABLED => 'ENABLED', + self::STATUS_PAUSED => 'PAUSED', + self::STATUS_REMOVED => 'REMOVED', + ]; + return $statusMap[$data['status']] ?? 'UNKNOWN'; + } + + // 更新状态方法 +// public function updateStatus($status) +// { +// if (!in_array($status, [self::STATUS_ENABLED, self::STATUS_PAUSED, self::STATUS_REMOVED])) { +//// throw new \think\exception\ValidateException('Invalid status'); +// } +// $this->status = $status; +// return $this->save(); +// } + + + + // 判断当前活动状态 + public function isEnabled() + { + return $this->status == self::STATUS_ENABLED; + } + + public function isPaused() + { + return $this->status == self::STATUS_PAUSED; + } + + public function isRemoved() + { + return $this->status == self::STATUS_REMOVED; + } + + // 关联 Customer 模型(广告活动属于客户) // public function customer() // { @@ -50,7 +100,7 @@ class Campaign extends Model return $this->hasManyThrough(Ad::class, GoogleAdsAdGroup::class, 'campaign_id', 'ad_group_id', 'campaign_id', 'ad_group_id'); } - // 关联到广告数据表 + // 关联到广告数据表 public function adDayData() { return $this->hasMany(DayData::class, 'campaign_id', 'campaign_id'); diff --git a/app/model/ThirdUser.php b/app/model/ThirdUser.php index e019ba1..929376b 100644 --- a/app/model/ThirdUser.php +++ b/app/model/ThirdUser.php @@ -6,5 +6,23 @@ use think\Model; class ThirdUser extends Model { protected $table = 'bps.bps_third_user'; - protected $primaryKey = 'id'; + // 设置主键 + protected $pk = 'id'; + // 设置自动时间戳 +// protected $autoWriteTimestamp = true; + + // 定义时间戳字段 +// protected $createTime = 'create_at'; // 创建时间字段 +// protected $updateTime = 'update_at'; // 更新时间字段 + + // 字段类型映射 + protected $casts = [ + 'id' => 'int', + ]; + + // 与广告主模型的关联 + public function advertisers() + { + return $this->hasMany(ThirdUserAdvertiser::class, 'doc_', 'id'); + } } \ No newline at end of file diff --git a/app/model/ThirdUserAdvertiser.php b/app/model/ThirdUserAdvertiser.php new file mode 100644 index 0000000..4f843af --- /dev/null +++ b/app/model/ThirdUserAdvertiser.php @@ -0,0 +1,49 @@ + 'int', + 'doc_' => 'int', // 外键字段,指向 bps_third_user 表的 id + ]; + + // 关联第三方用户模型(广告主属于用户) + public function googleUser() + { + return $this->belongsTo(ThirdUser::class, 'doc_', 'id'); + } + + // 关联广告主的其他数据模型,按需要可以增加(例如广告系列,广告组等) + // public function campaign() + // { + // return $this->hasMany(Campaign::class, 'advertiser_id', 'advertiser_id'); + // } + + // 默认值设置(例如,如果您需要广告商名称为默认值,可以在此设置) + protected $defaults = [ + 'advertiser_name' => 'google', // 设置默认广告商名称 + ]; + + // 其他自定义方法可以根据需求添加 +} \ No newline at end of file diff --git a/app/process/UpdateGoogleAdsTask.php b/app/process/UpdateGoogleAdsTask.php index 41ab4c9..8b61a5a 100644 --- a/app/process/UpdateGoogleAdsTask.php +++ b/app/process/UpdateGoogleAdsTask.php @@ -23,47 +23,47 @@ class UpdateGoogleAdsTask // 每15分钟执行一次 new Crontab('10 */1 * * * *', function () { - $dayBeforeYesterdayStart = date('Y-m-d', strtotime('-2 day')); - dump($dayBeforeYesterdayStart . '更新' . GoogleAdsDateDatas::type . '开始'); - Event::emit(GoogleAdsDateDatas::type, ['customer_id' => 4060397299, 'date' => $dayBeforeYesterdayStart]); +// $dayBeforeYesterdayStart = date('Y-m-d', strtotime('-2 day')); +// dump($dayBeforeYesterdayStart . '更新' . GoogleAdsDateDatas::type . '开始'); +// Event::emit(GoogleAdsDateDatas::type, ['customer_id' => 4060397299, 'date' => $dayBeforeYesterdayStart]); } ); // 每15分钟执行一次 new Crontab('20 */1 * * * *', function () { - $yesterdayStart = date('Y-m-d', strtotime('-1 day')); - dump($yesterdayStart . '更新' . GoogleAdsDateDatas::type . '开始'); - Event::emit(GoogleAdsDateDatas::type, ['customer_id' => 4060397299, 'date' => $yesterdayStart]); +// $yesterdayStart = date('Y-m-d', strtotime('-1 day')); +// dump($yesterdayStart . '更新' . GoogleAdsDateDatas::type . '开始'); +// Event::emit(GoogleAdsDateDatas::type, ['customer_id' => 4060397299, 'date' => $yesterdayStart]); } ); // 每15分钟执行一次 new Crontab('30 */1 * * * *', function () { //获取今天的 0 点的YYYY-MM-DD格式 - $todayStart = date('Y-m-d', strtotime('0 day')); - dump($todayStart . '更新' . GoogleAdsDateDatas::type . '开始'); - Event::emit(GoogleAdsDateDatas::type, ['customer_id' => 4060397299, 'date' => $todayStart]); +// $todayStart = date('Y-m-d', strtotime('0 day')); +// dump($todayStart . '更新' . GoogleAdsDateDatas::type . '开始'); +// Event::emit(GoogleAdsDateDatas::type, ['customer_id' => 4060397299, 'date' => $todayStart]); } ); // 每15分钟执行一次 new Crontab('40 */1 * * * *', function () { - dump(date('Y-m-d H:i:s') . '更新' . GoogleAdsCampaigns::type . '开始'); - Event::emit(GoogleAdsCampaigns::type, ['customer_id'=>4060397299]); +// dump(date('Y-m-d H:i:s') . '更新' . GoogleAdsCampaigns::type . '开始'); +// Event::emit(GoogleAdsCampaigns::type, ['customer_id'=>4060397299]); } ); // 每15分钟执行一次 new Crontab('50 */1 * * * *', function () { - dump(date('Y-m-d H:i:s') . '更新' . GoogleAdsGroups::type . '开始'); - Event::emit(GoogleAdsGroups::type, ['customer_id'=>4060397299]); +// dump(date('Y-m-d H:i:s') . '更新' . GoogleAdsGroups::type . '开始'); +// Event::emit(GoogleAdsGroups::type, ['customer_id'=>4060397299]); } ); // 每15分钟执行一次 new Crontab('55 */1 * * * *', function () { - dump(date('Y-m-d H:i:s') . '更新' . GoogleAdsAds::type . '开始'); - Event::emit(GoogleAdsAds::type, ['customer_id'=>4060397299]); +// dump(date('Y-m-d H:i:s') . '更新' . GoogleAdsAds::type . '开始'); +// Event::emit(GoogleAdsAds::type, ['customer_id'=>4060397299]); } ); diff --git a/app/service/BaseService.php b/app/service/BaseService.php new file mode 100644 index 0000000..a391af9 --- /dev/null +++ b/app/service/BaseService.php @@ -0,0 +1,104 @@ + $status, 'campaign_id' => $campaignId]); + + return $result > 0; // 如果更新成功,返回 true,否则返回 false + } + + /** + * 更新广告组状态 + * + * @param int $groupId 广告组ID + * @param int $status 新的状态值 + * @return bool + * @throws BindParamException + */ + public function modifyDbGroupStatus(int $groupId, int $status) + { + // 确保状态值是有效的(例如可以是 ENABLED、PAUSED 等) + if (!in_array($status, [2, 3, 4])) { // 这里 1、2、3 是示例状态码,按需替换 +// throw new \think\exception\ValidateException('Invalid status'); + } + + // 使用原始 SQL 更新状态 + $sql = "UPDATE bps.bps_google_ads_ad_group SET status = :status, update_at = CURRENT_TIMESTAMP WHERE ad_group_id = :ad_group_id"; + + // 执行 SQL 更新 + $result = ThinkDb::execute($sql, ['status' => $status, 'ad_group_id' => $groupId]); + + return $result > 0; // 如果更新成功,返回 true,否则返回 false + } + + /** + * 更新广告组状态 + * + * @param int $groupId 广告组ID + * @param int $status 新的状态值 + * @return bool + * @throws BindParamException + */ + public function modifyDbAdStatus(int $adId, int $status) + { + // 确保状态值是有效的(例如可以是 ENABLED、PAUSED 等) + if (!in_array($status, [2, 3, 4])) { // 这里 1、2、3 是示例状态码,按需替换 +// throw new \think\exception\ValidateException('Invalid status'); + } + + // 使用原始 SQL 更新状态 + $sql = "UPDATE bps.bps_google_ads_ad SET status = :status, update_at = CURRENT_TIMESTAMP WHERE ad_id = :ad_id"; + + // 执行 SQL 更新 + $result = ThinkDb::execute($sql, ['status' => $status, 'ad_id' => $adId]); + + return $result > 0; // 如果更新成功,返回 true,否则返回 false + } + + + /** + * 从数据库获取 refreshToken + * + * @param string $advertiserId 广告主ID + * @return string|null + */ + public function getRefreshTokenFromDatabase($advertiserId) + { + // 通过 advertiser_id 查询 ThirdUserAdvertiser,联表查询 ThirdUser 数据 + $userAdvertiser = ThirdUserAdvertiser::with('googleUser') + ->where('advertiser_id', $advertiserId) + ->find(); + + // 如果找到广告主数据 + if ($userAdvertiser && $userAdvertiser->googleUser) { + return $userAdvertiser->googleUser->access_token; // 返回 access_token + } + + return null; // 如果没有找到,返回 null + } +} diff --git a/app/service/GoogleAdsAdService.php b/app/service/GoogleAdsAdService.php index 06ce060..c444048 100644 --- a/app/service/GoogleAdsAdService.php +++ b/app/service/GoogleAdsAdService.php @@ -3,6 +3,7 @@ namespace app\service; +use app\model\ThirdUserAdvertiser; use app\util\Helper; use app\util\ArgumentNames; use app\util\ArgumentParser; @@ -34,24 +35,25 @@ use Google\Ads\GoogleAds\V18\Services\SearchGoogleAdsRequest; use Google\Ads\GoogleAds\V18\Services\SearchGoogleAdsStreamRequest; use Google\Protobuf\Internal\RepeatedField; use think\facade\Db as ThinkDb; +use app\model\Ad as AdModel; use Google\ApiCore\ApiException; -class GoogleAdsAdService +class GoogleAdsAdService extends BaseService { private $googleAdsClient; public function __construct() { $advertiserId = getenv('GOOGLE_ADS_CUSTOMER_ID'); - - // 从数据库获取 access_token +// +// // 从数据库获取 access_token $refreshToken = $this->getRefreshTokenFromDatabase($advertiserId); - - if (!$refreshToken) { - throw new \Exception("Access token not found for advertiserId: " . $advertiserId); - } +// +// if (!$refreshToken) { +// throw new \Exception("Access token not found for advertiserId: " . $advertiserId); +// } // OAuth2 Token Authentication $oAuth2Credential = (new OAuth2TokenBuilder()) @@ -67,19 +69,21 @@ class GoogleAdsAdService } // 从数据库动态获取 google RefreshToken - private function getRefreshTokenFromDatabase($advertiserId) - { - // 使用 ThinkDb 进行联表查询 -// $advertiserId = 'your-advertiser-id'; // 假设你已经获得了广告商ID - - $user = ThinkDb::table('bps.bps_third_user_advertiser as a') - ->join('bps_third_user as u', 'a.doc_ = u.id', 'left') // 连接 bps_third_user 表 - ->where('a.advertiser_id', $advertiserId) - ->select('u.access_token') // 只选择 access_token 字段 - ->first(); - - return $user ? $user->access_token : null; - } +// private function getRefreshTokenFromDatabase($advertiserId) +// { +// // 通过 advertiser_id 查询 ThirdUserAdvertiser,联表查询 ThirdUser 数据 +// $userAdvertiser = ThirdUserAdvertiser::with('googleUser') // 联表查询 user 关联 +// ->where('advertiser_id', $advertiserId) // 根据 advertiser_id 查询 +// ->find(); // 获取第一个结果 +// +//// 如果找到广告主数据 +// if ($userAdvertiser && $userAdvertiser->googleUser) { +// // 获取关联用户的 access_token +// return $userAdvertiser->googleUser ? $userAdvertiser->googleUser->access_token : null; +// } else { +//// return $this->errorResponse('101', '未找到该广告主或关联的用户'); +// } +// } /* @param int $customerId the customer ID @@ -92,13 +96,13 @@ class GoogleAdsAdService $googleAdsClient = $this->googleAdsClient; // Creates a single shared budget to be used by the campaigns added below. - $groupadsResourceName = self::getAds($googleAdsClient, $customerId); + $groupAdsResourceName = self::getAds($googleAdsClient, $customerId); // dump(json_encode($groupadsResourceName)); - if (is_array($groupadsResourceName)) { - self::saveAds($groupadsResourceName); + if (is_array($groupAdsResourceName)) { + self::saveAds($groupAdsResourceName); } - return $groupadsResourceName; + return $groupAdsResourceName; } @@ -243,14 +247,94 @@ class GoogleAdsAdService // Prints the resource name of the paused ad group ad. /** @var AdGroupAd $pausedAdGroupAd */ $pausedAdGroupAd = $response->getResults()[0]; - printf( - "Ad group ad with resource name: '%s' is paused.%s", - $pausedAdGroupAd->getResourceName(), - PHP_EOL - ); +// printf( +// "Ad group ad with resource name: '%s' is paused.%s", +// $pausedAdGroupAd->getResourceName(), +// PHP_EOL +// ); return $pausedAdGroupAd->getResourceName(); } + /** + * 更新广告状态 + */ + public function updateAdStatus(int $customerId, int $adGroupId, int $adId, int $status) + { + // 从数据库获取 Ad + $ad = AdModel::find($adId); + if (!$ad) { +// throw new ValidateException('Ad not found'); + return false; + } + // 更新数据库中的状态 +// $ad->updateStatus($status); + if ($this->modifyDbAdStatus($adId, $status)){ + // 更新 Google Ads 上的状态 + $googleAdsClient = $this->googleAdsClient; + $resourceName = self::updateAd($googleAdsClient,$customerId, $adGroupId, $adId, $status); + return true; + } + + return false; + } + + /** + * 获取广告状态 + */ + public function getAdStatus(int $adId) + { + // 从数据库获取 Ad + $ad = AdModel::find($adId); + if (!$ad) { +// throw new ValidateException('Ad not found'); + } + + // 返回广告状态 + return $ad->getStatusTextAttr(null, $ad->toArray()); + } + + + + /** + * 判断广告是否启用 + */ +// public function isAdEnabled(int $adId) +// { +// $ad = Ad::find($adId); +// if (!$ad) { +// throw new ValidateException('Ad not found'); +// } +// +// return $ad->isEnabled(); +// } + + /** + * 判断广告是否暂停 + */ +// public function isAdPaused(int $adId) +// { +// $ad = Ad::find($adId); +// if (!$ad) { +// throw new ValidateException('Ad not found'); +// } +// +// return $ad->isPaused(); +// } + + /** + * 判断广告是否停止 + */ +// public function isAdStopped(int $adId) +// { +// $ad = Ad::find($adId); +// if (!$ad) { +// throw new ValidateException('Ad not found'); +// } +// +// return $ad->isStopped(); +// } + + /** * This example updates the CPC bid and status for a given ad group. To get ad groups, run * GetAdAds.php. diff --git a/app/service/GoogleAdsCampaignService.php b/app/service/GoogleAdsCampaignService.php index 75aa98e..44f2c22 100644 --- a/app/service/GoogleAdsCampaignService.php +++ b/app/service/GoogleAdsCampaignService.php @@ -3,6 +3,7 @@ namespace app\service; +use app\model\ThirdUserAdvertiser; use app\util\Helper; use app\util\ArgumentNames; use app\util\ArgumentParser; @@ -35,7 +36,7 @@ use think\facade\Db as ThinkDb; use Google\ApiCore\ApiException; -class GoogleAdsCampaignService +class GoogleAdsCampaignService extends BaseService { private $googleAdsClient; private $customerId; @@ -44,13 +45,13 @@ class GoogleAdsCampaignService public function __construct() { $advertiserId = getenv('GOOGLE_ADS_CUSTOMER_ID'); - +// // 从数据库获取 access_token $refreshToken = $this->getRefreshTokenFromDatabase($advertiserId); - - if (!$refreshToken) { - throw new \Exception("Access token not found for advertiserId: " . $advertiserId); - } +// +// if (!$refreshToken) { +// throw new \Exception("Access token not found for advertiserId: " . $advertiserId); +// } // OAuth2 Token Authentication $oAuth2Credential = (new OAuth2TokenBuilder()) @@ -66,19 +67,21 @@ class GoogleAdsCampaignService } // 从数据库动态获取 google RefreshToken - private function getRefreshTokenFromDatabase($advertiserId) - { - // 使用 ThinkDb 进行联表查询 -// $advertiserId = 'your-advertiser-id'; // 假设你已经获得了广告商ID - - $user = ThinkDb::table('bps.bps_third_user_advertiser as a') - ->join('bps_third_user as u', 'a.doc_ = u.id', 'left') // 连接 bps_third_user 表 - ->where('a.advertiser_id', $advertiserId) - ->select('u.access_token') // 只选择 access_token 字段 - ->first(); - - return $user ? $user->access_token : null; - } +// private function getRefreshTokenFromDatabase($advertiserId) +// { +// // 通过 advertiser_id 查询 ThirdUserAdvertiser,联表查询 ThirdUser 数据 +// $userAdvertiser = ThirdUserAdvertiser::with('googleUser') // 联表查询 user 关联 +// ->where('advertiser_id', $advertiserId) // 根据 advertiser_id 查询 +// ->find(); // 获取第一个结果 +// +//// 如果找到广告主数据 +// if ($userAdvertiser && $userAdvertiser->googleUser) { +// // 获取关联用户的 access_token +// return $userAdvertiser->googleUser ? $userAdvertiser->googleUser->access_token : null; +// } else { +//// return $this->errorResponse('101', '未找到该广告主或关联的用户'); +// } +// } /** @@ -653,4 +656,68 @@ class GoogleAdsCampaignService ); return $updatedCampaign->getResourceName(); } + + + /** + * 更新广告系列状态 + */ + public function updateCampaignStatus(int $customerId, int $campaignId, int $status) + { + // 从数据库获取 Campaign 对象 + $campaign = CampaignModel::find($campaignId); +// dump($campaign);return; + if (!$campaign) { +// throw new ValidateException('Campaign not found'); + return false; + } + // 更新本地数据库的状态 + if ($this->modifyDbCampaignStatus($campaignId, $status)) { + // 更新 Google Ads 上的状态 + $googleAdsClient = $this->googleAdsClient; + $resourceName = self::updateCampaign($googleAdsClient, $customerId, $campaignId, $status); + return true; + } + return false; + } + + + + /** + * 获取广告活动状态 + */ +// public function getCampaignStatus(int $campaignId) +// { +// // 从本地数据库获取状态 +// $campaign = CampaignModel::find($campaignId); +// if (!$campaign) { +// throw new ValidateException('Campaign not found'); +// } +// +// // 获取 Google Ads 状态 +// $googleAdsStatus = $this->googleAdsClient->getCampaignStatus($campaignId); +// +// // 返回 Google Ads 的状态 +// return $googleAdsStatus; +// } + + + /** + * 获取 Google Ads Campaign 状态 + */ +// public function getCampaignStatus(int $campaignId) +// { +// try { +// // 获取 Google Ads 客户端 +// $campaignServiceClient = $this->client->getCampaignServiceClient(); +// +// // 获取 Campaign 资源 +// $resourceName = "customers/{customer_id}/campaigns/{$campaignId}"; +// $campaign = $campaignServiceClient->getCampaign($resourceName); +// +// return $campaign->getStatus(); +// } catch (ApiException $e) { +// throw new \Exception("Google Ads API error: " . $e->getMessage()); +// } +// } + } diff --git a/app/service/GoogleAdsGroupService.php b/app/service/GoogleAdsGroupService.php index 0b337ec..ff41b98 100644 --- a/app/service/GoogleAdsGroupService.php +++ b/app/service/GoogleAdsGroupService.php @@ -3,6 +3,7 @@ namespace app\service; +use app\model\ThirdUserAdvertiser; use app\util\Helper; use app\util\ArgumentNames; use app\util\ArgumentParser; @@ -22,9 +23,10 @@ use Google\Ads\GoogleAds\V18\Services\MutateAdGroupsRequest; use Google\Ads\GoogleAds\V18\Services\SearchGoogleAdsStreamRequest; use Google\ApiCore\ApiException; use think\facade\Db as ThinkDb; +use app\model\AdGroup as AdGroupModel; -class GoogleAdsGroupService +class GoogleAdsGroupService extends BaseService { private $googleAdsClient; @@ -34,10 +36,10 @@ class GoogleAdsGroupService // 从数据库获取 access_token $refreshToken = $this->getRefreshTokenFromDatabase($advertiserId); - - if (!$refreshToken) { - throw new \Exception("Access token not found for advertiserId: " . $advertiserId); - } +// +// if (!$refreshToken) { +// throw new \Exception("Access token not found for advertiserId: " . $advertiserId); +// } // OAuth2 Token Authentication $oAuth2Credential = (new OAuth2TokenBuilder()) @@ -54,19 +56,21 @@ class GoogleAdsGroupService // 从数据库动态获取 google RefreshToken - private function getRefreshTokenFromDatabase($advertiserId) - { - // 使用 ThinkDb 进行联表查询 -// $advertiserId = 'your-advertiser-id'; // 假设你已经获得了广告商ID - - $user = ThinkDb::table('bps.bps_third_user_advertiser as a') - ->join('bps_third_user as u', 'a.doc_ = u.id', 'left') // 连接 bps_third_user 表 - ->where('a.advertiser_id', $advertiserId) - ->select('u.access_token') // 只选择 access_token 字段 - ->first(); - - return $user ? $user->access_token : null; - } +// private function getRefreshTokenFromDatabase($advertiserId) +// { +// // 通过 advertiser_id 查询 ThirdUserAdvertiser,联表查询 ThirdUser 数据 +// $userAdvertiser = ThirdUserAdvertiser::with('googleUser') // 联表查询 user 关联 +// ->where('advertiser_id', $advertiserId) // 根据 advertiser_id 查询 +// ->find(); // 获取第一个结果 +// +//// 如果找到广告主数据 +// if ($userAdvertiser && $userAdvertiser->googleUser) { +// // 获取关联用户的 access_token +// return $userAdvertiser->googleUser ? $userAdvertiser->googleUser->access_token : null; +// } else { +//// return $this->errorResponse('101', '未找到该广告主或关联的用户'); +// } +// } /* @param int $customerId the customer ID @@ -111,7 +115,7 @@ class GoogleAdsGroupService cpc_bid_micros = EXCLUDED.cpc_bid_micros, update_at = EXCLUDED.update_at"; - ThinkDb::execute($sql, $data); + ThinkDb::execute($sql, $data); } } @@ -268,7 +272,8 @@ class GoogleAdsGroupService $googleAdsClient = $this->googleAdsClient; // Creates a single shared budget to be used by the campaigns added below. - $resourceNames = self::updateGroup($googleAdsClient, $options['customer_id'], $options['group_id'], $options['bid_micro_amount'], $options['status']); +// $resourceNames = self::updateGroup($googleAdsClient, $options['customer_id'], $options['group_id'], $options['status'], $options['bid_micro_amount'],); + $resourceNames = self::updateGroup($googleAdsClient, $options['customer_id'], $options['group_id'], $options['status']); return $resourceNames; } @@ -286,15 +291,15 @@ class GoogleAdsGroupService GoogleAdsClient $googleAdsClient, int $customerId, int $adGroupId, - $bidMicroAmount, - int $status + int $status, + // $bidMicroAmount ) { // Creates an ad group object with the specified resource name and other changes. $adGroup = new AdGroup([ 'resource_name' => ResourceNames::forAdGroup($customerId, $adGroupId), - 'cpc_bid_micros' => $bidMicroAmount, +// 'cpc_bid_micros' => $bidMicroAmount, // 'status' => AdGroupStatus::PAUSED 'status' => $status ]); @@ -324,4 +329,85 @@ class GoogleAdsGroupService return $updatedAdGroup->getResourceName(); } // [END update_ad_group] + + + /** + * 更新广告组状态 + */ + public function updateGroupStatus(int $customerId, int $adGroupId, int $status) + { + // 从数据库获取 AdGroup + $adGroup = AdGroupModel::find($adGroupId); + if (!$adGroup) { + return false; +// throw new ValidateException('AdGroup not found'); + } + + // 更新数据库中的状态 +// $adGroup->updateStatus($status); + if ($this->modifyDbGroupStatus($adGroupId, $status)) { + // 更新 Google Ads 上的状态 + $googleAdsClient = $this->googleAdsClient; + $resourceName = self::updateGroup($googleAdsClient, $customerId, $adGroupId, $status); + return true; + } + + return false; + } + + /** + * 获取广告组状态 + */ +// public function getAdGroupStatus(int $adGroupId) +// { +// // 从数据库获取 AdGroup +// $adGroup = AdGroupModel::find($adGroupId); +// if (!$adGroup) { +// throw new ValidateException('AdGroup not found'); +// } +// +// // 返回广告组状态 +// return $adGroup->getStatusTextAttr(null, $adGroup->toArray()); +// } + + /** + * 判断广告组是否启用 + */ +// public function isAdGroupEnabled(int $adGroupId) +// { +// $adGroup = AdGroup::find($adGroupId); +// if (!$adGroup) { +// throw new ValidateException('AdGroup not found'); +// } +// +// return $adGroup->isEnabled(); +// } + + /** + * 判断广告组是否暂停 + */ +// public function isAdGroupPaused(int $adGroupId) +// { +// $adGroup = AdGroup::find($adGroupId); +// if (!$adGroup) { +// throw new ValidateException('AdGroup not found'); +// } +// +// return $adGroup->isPaused(); +// } + + /** + * 判断广告组是否停止 + */ +// public function isAdGroupStopped(int $adGroupId) +// { +// $adGroup = AdGroup::find($adGroupId); +// if (!$adGroup) { +// throw new ValidateException('AdGroup not found'); +// } +// +// return $adGroup->isStopped(); +// } + + } diff --git a/config/route.php b/config/route.php index 4c99621..edff486 100644 --- a/config/route.php +++ b/config/route.php @@ -33,28 +33,36 @@ Route::group('/googleads', function () { Route::group('/v18', function () { Route::group('/ad', function () { Route::post('/list', [AdController::class, 'listAds']); + Route::post('/export', [AdController::class, 'exportAdsToExcel']); + Route::group('/status', function () { + Route::post('/update', [AdController::class, 'updateAdStatus']); +// Route::post('/get', [AdController::class, 'getAdStatus']); + }); }); Route::group('/campaign', function () { Route::post('/list', [AdController::class, 'listCampaigns']); + Route::post('/export', [AdController::class, 'exportCampaignsToExcel']); + Route::group('/status', function () { + Route::post('/update', [AdController::class, 'updateCampaignStatus']); +// Route::post('/get', [AdController::class, 'getCampaignStatus']); + }); }); Route::group('/adgroup', function () { Route::post('/list', [AdController::class, 'listGroups']); - }); - Route::group('/ad', function () { - Route::post('/export', [AdController::class, 'exportAdsToExcel']); - }); - Route::group('/campaign', function () { - Route::post('/export', [AdController::class, 'exportCampaignsToExcel']); - }); - Route::group('/adgroup', function () { Route::post('/export', [AdController::class, 'exportGroupsToExcel']); + Route::group('/status', function () { + Route::post('/update', [AdController::class, 'updateGroupStatus']); +// Route::post('/get', [AdController::class, 'getGroupStatus']); + }); }); + Route::group('/auth', function () { Route::get('/code', [OAuthController::class, 'getAuthCode']); Route::post('/callback', [OAuthController::class, 'handleCallback']); 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']); }); });