webman_ad/app/service/GoogleAdsService.php
2024-12-19 20:38:45 +08:00

223 lines
7.0 KiB
PHP
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<?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;
}
}