223 lines
		
	
	
		
			7.0 KiB
		
	
	
	
		
			PHP
		
	
	
	
	
	
			
		
		
	
	
			223 lines
		
	
	
		
			7.0 KiB
		
	
	
	
		
			PHP
		
	
	
	
	
	
| <?php
 | ||
| 
 | ||
| namespace app\service;
 | ||
| 
 | ||
| use app\model\Campaign;
 | ||
| use app\model\CampaignBudget;
 | ||
| use app\model\AdGroup;
 | ||
| use app\model\Ad;
 | ||
| use GuzzleHttp\Client as GuzzleClient;
 | ||
| use GuzzleHttp\Exception\RequestException;
 | ||
| 
 | ||
| class GoogleAdsService
 | ||
| {
 | ||
|     // Google Ads API 基础 URL
 | ||
|     private $baseUrl = 'https://googleads.googleapis.com/v17';
 | ||
| 
 | ||
|     // Google Ads API 客户 ID
 | ||
|     private $customerId;
 | ||
| 
 | ||
|     private $loginCustomerId; // 增加 login-customer-id 属性
 | ||
| 
 | ||
|     // OAuth2 access token
 | ||
|     private $accessToken;
 | ||
| 
 | ||
|     // Developer Token
 | ||
|     private $developerToken;
 | ||
| 
 | ||
|     private $client;
 | ||
| 
 | ||
|     public function __construct($accessToken, $customerId, $developerToken, $loginCustomerId = null)
 | ||
|     {
 | ||
|         $this->accessToken     = $accessToken;
 | ||
|         $this->customerId      = $customerId;
 | ||
|         $this->developerToken  = $developerToken;
 | ||
|         $this->loginCustomerId = $loginCustomerId;
 | ||
| 
 | ||
|         // 初始化 Guzzle 客户端
 | ||
|         $this->client = new GuzzleClient();
 | ||
|     }
 | ||
| 
 | ||
|     /**
 | ||
|      * 发起 HTTP 请求
 | ||
|      * @param string $method 请求方法(GET, POST, PATCH, DELETE)
 | ||
|      * @param string $endpoint API 端点
 | ||
|      * @param array $data 请求数据
 | ||
|      * @return array API 响应
 | ||
|      */
 | ||
|     private function sendRequest($method, $endpoint, $data = [])
 | ||
|     {
 | ||
|         // 构建 URL
 | ||
|         $url = "{$this->baseUrl}/customers/{$this->customerId}/$endpoint";
 | ||
| 
 | ||
|         // 设置请求头
 | ||
|         $headers = [
 | ||
|             'Authorization' => "Bearer {$this->accessToken}",
 | ||
|             'developer-token' => $this->developerToken,
 | ||
|             'Content-Type' => 'application/json'
 | ||
|         ];
 | ||
|         // 如果有广告经理 ID,添加到请求头
 | ||
|         if ($this->loginCustomerId) {
 | ||
|             $headers['login-customer-id'] = $this->loginCustomerId;
 | ||
|         }
 | ||
| 
 | ||
|         // 调试:输出请求的 URL 和头部信息
 | ||
| //        return [$url, $headers, $data];
 | ||
|         // 使用 Guzzle 发起请求
 | ||
|         try {
 | ||
|             $response = $this->client->request($method, $url, [
 | ||
|                 'headers' => $headers,
 | ||
|                 'json' => $data
 | ||
|             ]);
 | ||
| 
 | ||
| 
 | ||
|             // 获取响应体并解析为数组
 | ||
|             $body = $response->getBody()->getContents();
 | ||
|             return json_decode($body, true);
 | ||
| 
 | ||
|         } catch (RequestException $e) {
 | ||
|             // 处理请求错误
 | ||
|             echo "HTTP Request failed: " . $e->getMessage();
 | ||
|             return [];
 | ||
|         }
 | ||
|     }
 | ||
| 
 | ||
|     /**
 | ||
|      * 创建广告预算并存储到数据库
 | ||
|      */
 | ||
|     public function createCampaignBudget($budgetName, $amount)
 | ||
|     {
 | ||
|         // 构建请求数据
 | ||
|         $data = [
 | ||
|             'operations' => [
 | ||
|                 [
 | ||
|                     'create' => [
 | ||
|                         'name' => $budgetName,
 | ||
|                         'amountMicros' => $amount * 1000000, // 转换为微单位
 | ||
| //                        'delivery_method' => 'STANDARD',
 | ||
| //                        'status' => 'ENABLED'
 | ||
|                     ]
 | ||
|                 ]
 | ||
|             ]
 | ||
|         ];
 | ||
| //        return $data;
 | ||
|         // 调用 sendRequest 方法发起 POST 请求到 mutate 端点
 | ||
|         $response = $this->sendRequest('POST', 'campaignBudgets:mutate', $data);
 | ||
| 
 | ||
|         // 存储返回的广告预算数据到数据库
 | ||
| //        if (isset($response['results'][0]['resource_name'])) {
 | ||
| //            CampaignBudget::create([
 | ||
| //                'name' => $response['results'][0]['name'],
 | ||
| //                'amount_micros' => $response['results'][0]['amount_micros'],
 | ||
| //                'status' => $response['results'][0]['status'],
 | ||
| //                'delivery_method' => $response['results'][0]['delivery_method'],
 | ||
| //            ]);
 | ||
| //        }
 | ||
| 
 | ||
|         return $response;
 | ||
|     }
 | ||
| 
 | ||
|     /**
 | ||
|      * 创建广告系列并存储到数据库
 | ||
|      */
 | ||
|     public function createCampaign($campaignName, $budgetId)
 | ||
|     {
 | ||
|         // 构建请求数据
 | ||
|         $data = [
 | ||
|             'name' => $campaignName,
 | ||
|             'status' => 'PAUSED',
 | ||
|             'advertising_channel_type' => 'SEARCH',
 | ||
|             'campaign_budget' => "customers/{$this->customerId}/campaignBudgets/{$budgetId}",
 | ||
|             'network_settings' => [
 | ||
|                 'target_google_search' => true,
 | ||
|                 'target_search_network' => true,
 | ||
|                 'target_content_network' => false,
 | ||
|                 'target_partner_search_network' => false
 | ||
|             ],
 | ||
|             'start_date' => date('Y-m-d'),
 | ||
|             'end_date' => date('Y-m-d', strtotime('+1 year'))
 | ||
|         ];
 | ||
| 
 | ||
|         // 调用 sendRequest 方法发起 POST 请求
 | ||
|         $response = $this->sendRequest('POST', 'campaigns', $data);
 | ||
| 
 | ||
|         // 存储返回的广告系列数据到数据库
 | ||
|         if (isset($response['resource_name'])) {
 | ||
|             Campaign::create([
 | ||
|                 'name' => $response['name'],
 | ||
|                 'status' => $response['status'],
 | ||
|                 'advertising_channel_type' => $response['advertising_channel_type'],
 | ||
|                 'campaign_budget' => $response['campaign_budget'],
 | ||
|                 'start_date' => $response['start_date'],
 | ||
|                 'end_date' => $response['end_date'],
 | ||
|             ]);
 | ||
|         }
 | ||
| 
 | ||
|         return $response;
 | ||
|     }
 | ||
| 
 | ||
|     /**
 | ||
|      * 创建广告组并存储到数据库
 | ||
|      */
 | ||
|     public function createAdGroup($adGroupName, $campaignId)
 | ||
|     {
 | ||
|         // 构建请求数据
 | ||
|         $data = [
 | ||
|             'name' => $adGroupName,
 | ||
|             'status' => 'PAUSED',
 | ||
|             'campaign' => "customers/{$this->customerId}/campaigns/{$campaignId}",
 | ||
|             'type' => 'SEARCH_STANDARD'
 | ||
|         ];
 | ||
| 
 | ||
|         // 调用 sendRequest 方法发起 POST 请求
 | ||
|         $response = $this->sendRequest('POST', 'adGroups', $data);
 | ||
| 
 | ||
|         // 存储返回的广告组数据到数据库
 | ||
|         if (isset($response['resource_name'])) {
 | ||
|             AdGroup::create([
 | ||
|                 'name' => $response['name'],
 | ||
|                 'status' => $response['status'],
 | ||
|                 'campaign_id' => $campaignId,
 | ||
|                 'type' => $response['type'],
 | ||
|             ]);
 | ||
|         }
 | ||
| 
 | ||
|         return $response;
 | ||
|     }
 | ||
| 
 | ||
|     /**
 | ||
|      * 创建广告并存储到数据库
 | ||
|      */
 | ||
|     public function createAd($adGroupId, $adName, $finalUrl)
 | ||
|     {
 | ||
|         // 构建请求数据
 | ||
|         $data = [
 | ||
|             'ad' => [
 | ||
|                 'expanded_text_ad' => [
 | ||
|                     'headline_part1' => 'Headline 1',
 | ||
|                     'headline_part2' => 'Headline 2',
 | ||
|                     'description' => 'Description',
 | ||
|                     'final_urls' => [$finalUrl]
 | ||
|                 ],
 | ||
|                 'status' => 'PAUSED'
 | ||
|             ],
 | ||
|             'ad_group' => "customers/{$this->customerId}/adGroups/{$adGroupId}"
 | ||
|         ];
 | ||
| 
 | ||
|         // 调用 sendRequest 方法发起 POST 请求
 | ||
|         $response = $this->sendRequest('POST', 'ads', $data);
 | ||
| 
 | ||
|         // 存储返回的广告数据到数据库
 | ||
|         if (isset($response['resource_name'])) {
 | ||
|             Ad::create([
 | ||
|                 'name' => $response['ad']['expanded_text_ad']['headline_part1'], // 使用广告的标题字段作为示例
 | ||
|                 'ad_group_id' => $adGroupId,
 | ||
|                 'status' => $response['ad']['status'],
 | ||
|                 'final_url' => $response['ad']['expanded_text_ad']['final_urls'][0],
 | ||
|             ]);
 | ||
|         }
 | ||
| 
 | ||
|         return $response;
 | ||
|     }
 | ||
| }
 |