创建 更改campaign、adgroup、ad状态的接口

This commit is contained in:
hgc 2024-12-21 14:47:22 +08:00
parent 5e86d520c1
commit 17ee8aa79b
13 changed files with 864 additions and 105 deletions

View File

@ -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
{

View File

@ -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
{

View File

@ -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()

View File

@ -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()
{

View File

@ -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');

View File

@ -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');
}
}

View File

@ -0,0 +1,49 @@
<?php
namespace app\model;
use think\Model;
class ThirdUserAdvertiser extends Model
{
// 设置当前模型对应的完整数据表名称
/**
* @var ThirdUser|mixed
*/
public mixed $user;
protected $table = 'bps.bps_third_user_advertiser';
// 设置主键
protected $pk = 'id';
// 设置自动时间戳
// protected $autoWriteTimestamp = true;
// 定义时间戳字段
// protected $createTime = 'create_at'; // 创建时间字段
// protected $updateTime = 'update_at'; // 更新时间字段
// 字段类型映射
protected $casts = [
'id' => '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', // 设置默认广告商名称
];
// 其他自定义方法可以根据需求添加
}

View File

@ -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]);
}
);

104
app/service/BaseService.php Normal file
View File

@ -0,0 +1,104 @@
<?php
// app/service/BaseService.php
namespace app\service;
use app\model\ThirdUserAdvertiser;
use think\db\exception\BindParamException;
use think\facade\Db as ThinkDb;
use app\model\Campaign as CampaignModel;
class BaseService
{
/**
* 更新广告系列状态
*
* @param int $campaignId 广告系列ID
* @param int $status 新的状态值
* @return bool
*/
public function modifyDbCampaignStatus(int $campaignId, 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_campaign SET status = :status, update_at = CURRENT_TIMESTAMP WHERE campaign_id = :campaign_id";
// 执行 SQL 更新
$result = ThinkDb::execute($sql, ['status' => $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
}
}

View File

@ -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.

View File

@ -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());
// }
// }
}

View File

@ -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();
// }
}

View File

@ -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']);
});
});