commit 6b6170389df14fc7b28809d17a0a34768d725de8 Author: jaybe Date: Wed Mar 5 04:34:16 2025 +0000 Upload files to "/" diff --git a/FBDB.php b/FBDB.php new file mode 100644 index 0000000..221988f --- /dev/null +++ b/FBDB.php @@ -0,0 +1,862 @@ +db = \Config\Database::connect('facebook'); + $this->zenith = \Config\Database::connect(); + // $this->db_query("SET FOREIGN_KEY_CHECKS = 0;"); + } + + // 메인 계정에 대한 엑세스 토큰 로드 + public function getAccessToken() + { + $sql = "SELECT access_token, ad_account_id FROM fb_ad_account WHERE is_admin = 1"; + $result = $this->db_query($sql); + $row = $result->getRowArray(); + + return $row; + } + + // 광고 계정 목록 + public function getAdAccounts($perm = true, $query = "") + { + $sql = "SELECT * FROM fb_ad_account WHERE 1 AND status = 1"; + if ($perm) { + $sql .= " AND perm = 1"; + } + if ($query) { + $sql .= $query; + } + $sql .= " ORDER BY name DESC"; + $result = $this->db_query($sql); + + return $result; + } + + public function getCampaign($campaign_id) + { + if (empty($campaign_id)) { + return null; + } + + $sql = "SELECT * FROM fb_campaign WHERE campaign_id = {$campaign_id}"; + $result = $this->db_query($sql); + $row = $result->getRowArray(); + + return $row; + } + + public function getAdset($adset_id) + { + if (empty($adset_id)) { + return null; + } + + $sql = "SELECT * FROM fb_adset WHERE adset_id = {$adset_id}"; + $result = $this->db_query($sql); + $row = $result->getRowArray(); + + return $row; + } + + // 광고 목록 + public function getAds($query = '') + { + $sql = "SELECT ad_id, adset_id, ad_name, effective_status FROM fb_ad WHERE 1 {$query} ORDER BY update_date DESC"; + $result = $this->db_query($sql); + + return $result; + } + + public function getAdsWithAccount($query = '') + { + $sql = "SELECT ad_id, adset_id, ad_name, effective_status FROM fb_ad_with_account WHERE 1 {$query} ORDER BY update_date DESC"; + $result = $this->db_query($sql); + + return $result; + } + + public function getAdSetsWithAccount($selector = ['adset_id', 'campaign_id'], $query = '') + { + $select = implode(',', $selector); + $sql = "SELECT {$select} FROM fb_adset_with_account WHERE 1 {$query} ORDER BY update_date DESC"; + $result = $this->db_query($sql); + + return $result; + } + + public function getCampaignsWithAccount($query = '') + { + $sql = "SELECT campaign_id, budget FROM fb_campaign_with_account WHERE 1 {$query} ORDER BY update_date DESC"; + $result = $this->db_query($sql); + + return $result; + } + + public function getLeadgenAds() { + $sql = "SELECT * FROM fb_ad WHERE (leadgen_id IS NOT NULL AND leadgen_id <> '')"; + $result = $this->db_query($sql); + return $result; + } + + + public function updateAdAccounts($list) + { + if (empty($list)) { + return null; + } + + if(!empty($list[0][0])){ + $this->db->query("UPDATE fb_ad_account SET status = 0, disable_reason = 0, perm = 0 WHERE business_id = '{$list[0][0]}'"); + } + + foreach ($list as $key => $row) { + if (empty($row)) { + continue; + } + + $sql = "INSERT INTO fb_ad_account (business_id, ad_account_id, name, funding_source, status, disable_reason, pixel_id, perm, update_time) + VALUES ('{$row[0]}', '{$row[1]}', '{$row[2]}', '{$row[3]}', {$row[4]}, {$row[5]}, {$row[6]}, 1, NOW()) + ON DUPLICATE KEY + UPDATE name = '{$row[2]}', funding_source = '{$row[3]}', status = {$row[4]}, disable_reason = {$row[5]}, pixel_id = {$row[6]}, perm = 1, update_time = NOW();"; + $result = $this->db_query($sql); + } + } + + + public function insertAsyncInsights($lists) + { + foreach ($lists as $key => $report) { + if ($report['date_start'] != $report['date_stop']) continue; + $hour = ($report['date_start'] == date('Y-m-d')) ? date('H') : 23; + if(isset($report['hourly_stats_aggregated_by_audience_time_zone'])) + $hour = preg_replace('/^([0-9]{2}).+$/', '$1', $report['hourly_stats_aggregated_by_audience_time_zone']); + $data = [ + 'ad_id' => $report['ad_id'], + 'date' => $report['date_start'], + 'hour' => $hour, + 'impressions' => $report['impressions']??0, + 'clicks' => $report['clicks']??0, + 'inline_link_clicks' => $report['inline_link_clicks']??0, + 'spend' => $report['spend']??0, + ]; + $builder = $this->db->table('fb_ad_insight_history'); + $builder->setData($data); + $updateTime = ['update_date' => new RawSql('NOW()')]; + $builder->updateFields($updateTime, true); + $result = $builder->upsert(); + + // 캠페인 저장 + $data = [ + 'campaign_id' => $report['campaign_id'], + 'campaign_name' => $report['campaign_name'], + 'account_id' => $report['account_id'] + ]; + $builder = $this->db->table('fb_campaign'); + $builder->setData($data); + $updateTime = ['update_date' => new RawSql('NOW()')]; + $builder->updateFields($updateTime, true); + $result = $builder->upsert(); + + // 광고세트 저장 + $data = [ + 'adset_id' => $report['adset_id'], + 'adset_name' => $report['adset_name'], + 'campaign_id' => $report['campaign_id'] + ]; + $builder = $this->db->table('fb_adset'); + $builder->setData($data); + $updateTime = ['update_date' => new RawSql('NOW()')]; + $builder->updateFields($updateTime, true); + $result = $builder->upsert(); + // 광고 저장 + $use_landing = 0; + if (preg_match('/\#[0-9\_]+.+\*[0-9]+.+\&[a-z]+.*/i', $report['ad_name'])) { + $use_landing = 1; + } + $data = [ + 'ad_id' => $report['ad_id'], + 'ad_name' => $report['ad_name'], + 'adset_id' => $report['adset_id'], + 'use_landing' => $use_landing + ]; + $builder = $this->db->table('fb_ad'); + $builder->setData($data); + $updateTime = ['update_date' => new RawSql('NOW()')]; + $builder->updateFields($updateTime, true); + $result = $builder->upsert(); + } + } + + public function updateAdCreatives($lists) + { + if (!is_array($lists) && !count($lists)) return; + foreach ($lists as $row) { + if (empty($row)) continue; + $data = [ + 'adcreative_id' => $row['adcreative_id'], + 'ad_id' => $row['ad_id'], + 'object_type' => $row['object_type']??null, + 'thumbnail' => $row['thumbnail_url']??null, + 'link' => $row['link']??null + ]; + $builder = $this->db->table('fb_adcreative'); + $builder->setData($data); + $updateTime = ['update_date' => new RawSql('NOW()')]; + $builder->updateFields($updateTime, true); + $result = $builder->upsert(); + } + } + + public function updateAds($data) + { + $cnt = 0; + foreach ($data as $key => $report) { + $report['page'] = null; + $report['fb_pixel'] = null; + $report['post'] = null; + $created_time = null; + $updated_time = null; + if (!empty($report['tracking_specs'])) { + foreach ($report['tracking_specs'] as $list) { + foreach ($list as $key => $data) { + if ($key == 'page') { + $report['page'] = $list['page'][0]; + } + if ($key == 'fb_pixel') { + $report['fb_pixel'] = $list['fb_pixel'][0]; + } + if ($key == 'post') { + $report['post'] = $list['post'][0]; + } + } + } + } + $report['leadgen'] = null; + if (!empty($report['conversion_specs'])) { + foreach ($report['conversion_specs'] as $list) { + foreach ($list as $key => $data) { + if ($key == 'leadgen') { + $report['leadgen'] = $list['leadgen'][0]; + } + } + } + } + + $created_time = $report['created_time'] && $report['created_time'] != '1970-01-01T08:59:59+0900' ? date('Y-m-d H:i:s', strtotime($report['created_time'])) : null; + $updated_time = $report['updated_time'] && $report['updated_time'] != '1970-01-01T08:59:59+0900' ? date('Y-m-d H:i:s', strtotime($report['updated_time'])) : null; + // $name = addslashes($report['name']); + $use_landing = 0; + if (preg_match('/\#[0-9\_]+.+\*[0-9]+.+\&[a-z]+.*/i', $report['name'])) { + $use_landing = 1; + } + $sql = "INSERT INTO fb_ad ( + ad_id, + ad_name, + effective_status, + status, + fb_pixel, + page_id, + adset_id, + use_landing, + leadgen_id, + created_time, + updated_time, + create_date + ) VALUES ( + :ad_id:, + :name:, + :effective_status:, + :status:, + :fb_pixel:, + :page_id:, + :adset_id:, + :use_landing:, + :leadgen_id:, + :created_time:, + :updated_time:, + NOW() + ) ON DUPLICATE KEY UPDATE + ad_name = :name:, + effective_status = :effective_status:, + status = :status:, + fb_pixel = :fb_pixel:, + page_id = :page_id:, + use_landing = :use_landing:, + leadgen_id = :leadgen_id:, + created_time = :created_time:, + updated_time = :updated_time:, + update_date = NOW()"; + $result = $this->db->query($sql, [ + 'ad_id' => $report['id'], + 'name' => $report['name'], + 'effective_status' => $report['effective_status'], + 'status' => $report['status'], + 'fb_pixel' => $report['fb_pixel'] ?? '', + 'page_id' => $report['page_id'] ?? '', + 'adset_id' => $report['adset_id'], + 'use_landing' => $use_landing, + 'leadgen_id' => $report['leadgen'] ?? '', + 'created_time' => $created_time, + 'updated_time' => $updated_time + ]); + if(!$result){return false;}; + /* + $this->db_query("DELETE FROM fb_recommendations WHERE ad_id = '{$report['id']}'"); + if (!empty($report['recommendations'])) { //권고사항 정보 같이 저장 + foreach ($report['recommendations'] as $data) { + $sql = "INSERT INTO fb_recommendations ( + ad_id, + code, + title, + message, + importance, + confidence, + blame_field + ) VALUES ( + '{$report['id']}', + '{$data['code']}', + '".addslashes($data['title'])."', + '".addslashes($data['message'])."', + '{$data['importance']}', + '{$data['confidence']}', + '{$data['blame_field']}' + ) ON DUPLICATE KEY UPDATE + ad_id = '{$report['id']}';"; + $this->db_query($sql); + $sql = " INSERT IGNORE INTO fb_translation (seq, original_txt) VALUES ((SELECT MAX(seq)+1 FROM fb_translation a), '".addslashes($data['title'])."') "; + $this->db_query($sql); + $sql = " INSERT IGNORE INTO fb_translation (seq, original_txt) VALUES ((SELECT MAX(seq)+1 FROM fb_translation a), '".addslashes($data['message'])."') "; + $this->db_query($sql); + } + } + */ + } + return true; + } + + public function updateAdsets($data) + { + $cnt = 0; + foreach ($data as $key => $report) { + if (!$report['budget_remaining']) $report['budget_remaining'] = NULL; + $start_time = $report['start_time'] && $report['start_time'] != '1970-01-01T08:59:59+0900' ? date('Y-m-d H:i:s', strtotime($report['start_time'])) : NULL; + $created_time = $report['created_time'] && $report['created_time'] != '1970-01-01T08:59:59+0900' ? date('Y-m-d H:i:s', strtotime($report['created_time'])) : NULL; + $updated_time = $report['updated_time'] && $report['updated_time'] != '1970-01-01T08:59:59+0900' ? date('Y-m-d H:i:s', strtotime($report['updated_time'])) : NULL; + if (isset($report['lifetime_budget'])) { + $budget_type = 'lifetime'; + $budget = (integer)$report['lifetime_budget']; + } elseif (isset($report['daily_budget'])) { + $budget_type = 'daily'; + $budget = (integer)$report['daily_budget']; + } else { + $budget_type = NULL; + $budget = NULL; + } + + $lst_sig_edit_ts = NULL; + $lsiConversions = 0; + $lsiStatus = ''; + if(!empty($report['learning_stage_info'])){ + if(!empty($report['learning_stage_info']['last_sig_edit_ts'])){ + $lst_sig_edit_ts = date('Y-m-d H:i:s', $report['learning_stage_info']['last_sig_edit_ts']); + } + + if(!empty($report['learning_stage_info']['conversions'])){ + $lsiConversions = (integer)$report['learning_stage_info']['conversions']; + } + + if(!empty($report['learning_stage_info']['status'])){ + $lsiStatus = (integer)$report['learning_stage_info']['status']; + } + } + + $sql = "INSERT INTO fb_adset ( + adset_id, + adset_name, + campaign_id, + effective_status, + status, + start_time, + lsi_conversions, + lsi_status, + lsi_last_sig_edit_ts, + created_time, + updated_time, + create_date + ) VALUES ( + :adset_id:, + :name:, + :campaign_id:, + :effective_status:, + :status:, + :start_time:, + :lsi_conversions:, + :lsiStatus:, + :lst_sig_edit_ts:, + :created_time:, + :updated_time:, + NOW() + ) ON DUPLICATE KEY UPDATE + adset_name = :name:, + budget_type = :budget_type:, + budget = :budget:, + budget_remaining = :budget_remaining:, + effective_status = :effective_status:, + status = :status:, + start_time = :start_time:, + lsi_conversions = :lsi_conversions:, + lsi_status = :lsiStatus:, + lsi_last_sig_edit_ts = :lst_sig_edit_ts:, + created_time = :created_time:, + updated_time = :updated_time:, + update_date = NOW()"; + $result = $this->db->query($sql, [ + 'adset_id' => $report['id'], + 'name' => $report['name'], + 'campaign_id' => $report['campaign_id'], + 'effective_status' => $report['effective_status'], + 'status' => $report['status'], + 'start_time' => $start_time, + 'lsi_conversions' => $lsiConversions, + 'lsiStatus' => $lsiStatus, + 'lst_sig_edit_ts' => $lst_sig_edit_ts, + 'created_time' => $created_time, + 'updated_time' => $updated_time, + 'budget_type' => $budget_type, + 'budget' => $budget, + 'budget_remaining' => $report['budget_remaining'], + ]); + if(!$result){return false;}; + /* + $this->db_query("DELETE FROM fb_recommendations WHERE adset_id = '{$report['id']}'"); + if (!empty($report['recommendations'])) { //권고사항 정보 같이 저장 + foreach ($report['recommendations'] as $data) { + $sql = "INSERT INTO fb_recommendations ( + adset_id, + code, + title, + message, + importance, + confidence, + blame_field + ) VALUES ( + '{$report['id']}', + '{$data['code']}', + '".addslashes($data['title'])."', + '".addslashes($data['message'])."', + '{$data['importance']}', + '{$data['confidence']}', + '{$data['blame_field']}' + ) ON DUPLICATE KEY UPDATE + adset_id = '{$report['id']}';"; + $this->db_query($sql); + $sql = " INSERT IGNORE INTO fb_translation (seq, original_txt) VALUES ((SELECT MAX(seq)+1 FROM fb_translation a), '".addslashes($data['title'])."') "; + $this->db_query($sql); + $sql = " INSERT IGNORE INTO fb_translation (seq, original_txt) VALUES ((SELECT MAX(seq)+1 FROM fb_translation a), '".addslashes($data['message'])."') "; + $this->db_query($sql); + } + } + */ + } + return true; + } + + public function updateCampaigns($data) + { + foreach ($data as $key => $report) { + if (empty($report['budget_remaining'])) (integer)$report['budget_remaining'] = NULL; + $start_time = $report['start_time'] && $report['start_time'] != '1970-01-01T08:59:59+0900' ? date('Y-m-d H:i:s', strtotime($report['start_time'])) : NULL; + $created_time = $report['created_time'] && $report['created_time'] != '1970-01-01T08:59:59+0900' ? date('Y-m-d H:i:s', strtotime($report['created_time'])) : NULL; + $updated_time = $report['updated_time'] && $report['updated_time'] != '1970-01-01T08:59:59+0900' ? date('Y-m-d H:i:s', strtotime($report['updated_time'])) : NULL; + $can_use_spend_cap = $report['can_use_spend_cap'] ? $report['can_use_spend_cap'] : '0'; + $budget_rebalance_flag = $report['budget_rebalance_flag'] ? $report['budget_rebalance_flag'] : '0'; + $spend_cap = isset($report['spend_cap']) ? (integer)$report['spend_cap'] : NULL; + + if (isset($report['lifetime_budget']) && $report['lifetime_budget']) { + $budget_type = 'lifetime'; + $budget = (integer)$report['lifetime_budget']; + } elseif (isset($report['daily_budget']) && $report['daily_budget']) { + $budget_type = 'daily'; + $budget = (integer)$report['daily_budget']; + } else { + $budget_type = ""; + $budget = NULL; + } + + $sql = "INSERT INTO fb_campaign ( + campaign_id, + campaign_name, + account_id, + effective_status, + status, + budget_type, + budget, + budget_remaining, + budget_rebalance_flag, + can_use_spend_cap, + spend_cap, + objective, + start_time, + created_time, + updated_time, + create_date + ) VALUES ( + :campaign_id:, + :name:, + :account_id:, + :effective_status:, + :status:, + :budget_type:, + :budget:, + :budget_remaining:, + :budget_rebalance_flag:, + :can_use_spend_cap:, + :spend_cap:, + :objective:, + :start_time:, + :created_time:, + :updated_time:, + NOW() + ) ON DUPLICATE KEY UPDATE + campaign_name = :name:, + budget_type = :budget_type:, + budget = :budget:, + budget_remaining = :budget_remaining:, + budget_rebalance_flag = :budget_rebalance_flag:, + can_use_spend_cap = :can_use_spend_cap:, + spend_cap = :spend_cap:, + objective = :objective:, + effective_status = :effective_status:, + status = :status:, + start_time = :start_time:, + created_time = :created_time:, + updated_time = :updated_time:, + is_updating = 0, + update_date = NOW()"; + $result = $this->db->query($sql, [ + 'campaign_id' => $report['id'], + 'name' => $report['name'], + 'account_id' => $report['account_id'], + 'effective_status' => $report['effective_status'], + 'status' => $report['status'], + 'budget_type' => $budget_type, + 'budget' => $budget, + 'budget_remaining' => $report['budget_remaining'], + 'budget_rebalance_flag' => $budget_rebalance_flag, + 'can_use_spend_cap' => $can_use_spend_cap, + 'spend_cap' => $spend_cap, + 'objective' => $report['objective'], + 'start_time' => $start_time, + 'created_time' => $created_time, + 'updated_time' => $updated_time, + ]); + if(!$result){return false;}; + /* + $this->db_query("DELETE FROM fb_recommendations WHERE campaign_id = '{$report['id']}'"); + if (!empty($report['recommendations'])) { //권고사항 정보 같이 저장 + foreach ($report['recommendations'] as $data) { + $sql = "INSERT INTO fb_recommendations ( + campaign_id, + code, + title, + message, + importance, + confidence, + blame_field + ) VALUES ( + '{$report['id']}', + '{$data['code']}', + '".addslashes($data['title'])."', + '".addslashes($data['message'])."', + '{$data['importance']}', + '{$data['confidence']}', + '{$data['blame_field']}' + ) ON DUPLICATE KEY UPDATE + campaign_id = '{$report['id']}';"; + $this->db_query($sql); + $sql = " INSERT IGNORE INTO fb_translation (seq, original_txt) VALUES ((SELECT MAX(seq)+1 FROM fb_translation a), '".addslashes($data['title'])."') "; + $this->db_query($sql); + $sql = " INSERT IGNORE INTO fb_translation (seq, original_txt) VALUES ((SELECT MAX(seq)+1 FROM fb_translation a), '".addslashes($data['message'])."') "; + $this->db_query($sql); + } + } + */ + } + return true; + } + + public function insertAdLeads($data) + { + if (count($data) > 0) { + $total = count($data); + $step = 1; + $insert = "INSERT INTO `fb_ad_lead` SET "; + $this->db_query('BEGIN'); + foreach ($data as $key => $lead) { + CLI::showProgress($step++, $total); + $time = new DateTime($lead['created_time']); + $korea = new DateTimeZone('Asia/Seoul'); + $time->setTimezone($korea); + $created_time = $time->format('Y-m-d H:i:s'); + $full_name = $phone_number = $date_of_birth = $gender = null; + $is_organic = (strlen($lead['is_organic']) == 0) ? 0 : 1; + $custom_fields = array(); + $values = "id = '{$lead['id']}', form_id = '{$lead['form_id']}', ad_id = '{$lead['ad_id']}', is_organic = '{$is_organic}'"; + if (count($lead['field_data']) > 0) { + foreach ($lead['field_data'] as $key => $field) { + switch ($field['name']) { + case '이름': + $field['name'] = 'full_name'; + break; + case '전화번호': + $field['name'] = 'phone_number'; + break; + case '성별': + $field['name'] = 'gender'; + break; + case '생년월일': + $field['name'] = 'date_of_birth'; + break; + } + if (preg_match("/[a-z\_]+/i", $field['name']) && !preg_match("/[가-힣]+/i", $field['name'])) { + $val = ""; + if(isset($field['values']) && isset($field['values'][0])) $val = trim(addslashes($field['values'][0])); + // @$this->db->query("ALTER TABLE `fb_ad_lead` ADD `{$field['name']}` VARCHAR(50) NULL DEFAULT NULL AFTER `gender`;"); + // @$this->db->query("ALTER TABLE `fb_ad_lead_delete` ADD `{$field['name']}` VARCHAR(50) NULL DEFAULT NULL AFTER `gender`;"); + if (trim($val)) { + $values .= ", {$field['name']} = '{$val}'"; + } + } else { + array_push($custom_fields, $field); + } + } + $field_data = addslashes(var_export($custom_fields, true)); // 배열 그대로 저장하는데 조금 이상하다...이상해씨 + $values .= ", field_data = '{$field_data}'"; + $sql = $insert . $values . ", created_time = '{$created_time}' ON DUPLICATE KEY UPDATE {$values}, update_date = NOW();"; + $result = $this->db_query($sql, true); + } + } + $this->db_query('COMMIT'); + } + } + + // 광고 활성/종료 업데이트하는 + public function setCampaignStatus($campaign_id, $status) + { + if (empty($campaign_id) || empty($status)) { + return null; + } + $sql = "UPDATE fb_campaign SET status = '$status' WHERE campaign_id = '$campaign_id'"; + $result = $this->db_query($sql); + } + + public function setAdsetStatus($adset_id, $status) + { + if (empty($adset_id) || empty($status)) { + return null; + } + $sql = "UPDATE fb_adset SET status = '$status' WHERE adset_id = '$adset_id'"; + $this->db_query($sql); + } + + public function setAdStatus($ad_id, $status) + { + if (empty($ad_id) || empty($status)) { + return null; + } + $sql = "UPDATE fb_ad SET status = '$status' WHERE ad_id = '$ad_id'"; + $this->db_query($sql); + } + + public function updateCampaignName($data) + { + if (empty($data)) { + return null; + } + + $sql = "UPDATE fb_campaign SET campaign_name = '{$data['name']}' WHERE campaign_id = {$data['id']}"; + $result = $this->db_query($sql); + } + + public function updateAdsetName($data) + { + if (empty($data)) { + return null; + } + + $sql = "UPDATE fb_adset SET adset_name = '{$data['name']}' WHERE adset_id = {$data['id']}"; + $result = $this->db_query($sql); + } + + public function updateAdName($data) + { + if (empty($data)) { + return null; + } + + $sql = "UPDATE fb_ad SET ad_name = '{$data['name']}' WHERE ad_id = {$data['id']}"; + $result = $this->db_query($sql); + } + + public function updateInsight($data) + { + $row = $data; + if(empty($row['data'])) return; + foreach($row['data'] as $v) { + if ($row['ad_id']) { + $data = [ + 'ad_id' => $row['ad_id'], + 'date' => $row['date'], + 'hour' => $v['hour'], + 'media' => $row['media'], + 'period' => $row['period_ad'], + 'event_seq' => $row['event_seq'], + 'site' => $row['site'], + 'db_price' => (integer)$row['db_price'], + 'db_count' => (integer)$v['count'], + 'margin' => (integer)$v['margin'], + 'sales' => (integer)$v['sales'], + ]; + $builder = $this->db->table('fb_ad_insight_history'); + $builder->setData($data); + $updateTime = ['update_date' => new RawSql('NOW()')]; + $builder->updateFields($updateTime, true); + // d($builder->getCompiledUpsert()); + $builder->upsert(); + /* + $sql = "UPDATE `z_facebook`.`fb_ad_insight_history` + SET `media` = '{$row['media']}', `period` = '{$row['period_ad']}', `event_seq` = '{$row['event_seq']}', `site` = '{$row['site']}', `db_price` = '{$row['db_price']}', `db_count` = '{$v['count']}', `margin` = '{$v['margin']}', `sales` = '{$v['sales']}', `update_date` = NOW() + WHERE `ad_id` = '{$row['ad_id']}' AND `date` = '{$row['date']}' AND `hour` = '{$v['hour']}'"; + $this->db_query($sql, true); + */ + } + } + } + + public function getAdLeads($date) + { + $sql = "SELECT his.ad_id, CONCAT('{',GROUP_CONCAT('\"',his.`hour`,'\":',his.spend),'}') AS spend_data, ad.code, ad.ad_name, adset.adset_name, campaign.campaign_name + FROM `z_facebook`.`fb_ad_insight_history` AS his + LEFT JOIN `z_facebook`.fb_ad AS ad + ON his.ad_id = ad.ad_id + LEFT JOIN `z_facebook`.fb_adset AS adset + ON adset.adset_id = ad.adset_id + LEFT JOIN `z_facebook`.fb_campaign AS campaign + ON adset.campaign_id = campaign.campaign_id + LEFT JOIN `z_facebook`.fb_ad_account AS account + ON campaign.account_id = account.ad_account_id + WHERE his.date = '{$date}' AND account.perm = 1 GROUP BY his.ad_id;"; + $result = $this->db_query($sql); + + return $result; + } + + public function getDbPrice($data) + { + if (empty($data['ad_id']) || empty($data['date'])) return NULL; + $sql = "SELECT ad_id, date, db_price FROM `z_facebook`.`fb_ad_insight_history` WHERE `ad_id` = '{$data['ad_id']}' AND `date` = '{$data['date']}' GROUP BY date ORDER BY hour DESC LIMIT 1;"; + $result = $this->db_query($sql); + if (empty($result)) return null; + return $result->getResultArray(); + } + + public function updateCampaignBudget($campaign_id, $budget) + { + $sql = "UPDATE fb_campaign set budget = {$budget} where campaign_id = {$campaign_id}"; + $result = $this->db_query($sql); + $sql = "UPDATE fb_adset set budget_type = '', budget = NULL, budget_remaining = NULL where campaign_id = {$campaign_id}"; + $result = $this->db_query($sql); + + if (empty($result)) return null; + return true; + } + + public function updateAdSetBudget($adset_id, $budget) + { + $sql = "UPDATE fb_adset set budget = {$budget} where adset_id = {$adset_id}"; + $result = $this->db_query($sql); + if (empty($result)) return null; + return true; + } + + public function getLeads($data) + { + if (empty($data['event_seq'])) return null; + $sql = "SELECT event_seq, site, date(from_unixtime(reg_timestamp)) AS date, HOUR(from_unixtime(reg_timestamp)) AS hour, count(event_seq) AS db_count + FROM `zenith`.`event_leads` + WHERE `reg_timestamp` >= unix_timestamp('{$data['date']}') + AND `status` = 1 AND `is_deleted` = 0 + AND `event_seq` = {$data['event_seq']} AND `site` = '{$data['site']}' AND DATE_FORMAT(`reg_date`, '%Y-%m-%d') = '{$data['date']}' + GROUP BY `event_seq`, `site`, HOUR(from_unixtime(reg_timestamp))"; + $result = $this->zenith->query($sql); + return $result; + } + + public function db_query($sql, $error = false) + { + if (empty($sql)) return false; + $result = null; + $this->sltDB = $this->db; + + $this->sltDB->transStart(); + $result = $this->sltDB->query($sql); + if (!$result && $error) { + $err = $this->sltDB->error(); + exit($err['code'] .' : '. $err['message'] .' - '. $sql); + } + $this->sltDB->transComplete(); + return $result; + } + + //////////////////////////////////////////////////// + public function getMemo($p) + { + $query = ""; + if ($p['id']) $query = " AND fm.id = '{$p['id']}' "; + $sql = "SELECT fc.campaign_name, fac.name AS account_name, fm.* + FROM fb_memo AS fm + LEFT JOIN fb_campaign AS fc ON fm.id = fc.campaign_id + LEFT JOIN fb_ad_account AS fac ON fc.account_id = fac.ad_account_id + WHERE 1 AND fm.type = '{$p['type']}'{$query} AND (fm.datetime >= DATE_SUB(NOW(), INTERVAL 3 DAY) OR (fm.datetime <= DATE_SUB(NOW(), INTERVAL 3 DAY) AND fm.is_done = 0)) ORDER BY fm.is_done ASC, fac.name ASC, fm.datetime DESC"; + // echo $sql; + $result = $this->db_query($sql); + if ($result->num_rows) { + foreach ($result->getResultArray() as $row) { + $memo[] = $row; + } + } + return $memo; + } + + public function addMemo($data) + { + $data['memo'] = $this->db->escape($data['memo']); + $sql = "INSERT INTO fb_memo (`id`, `type`, `memo`, `mb_name`, `datetime`) VALUES({$data['id']}, '{$data['type']}', {$data['memo']}, '{$data['mb_name']}', NOW())"; + if ($this->db_query($sql)) + return $data['id']; + } + + public function updateMemo($data) + { + $query = ""; + if ($data['is_done']) { + $query = ", done_mb_name = '{$data['done_mb_name']}', done_datetime = NOW()"; + } + $sql = "UPDATE fb_memo SET is_done = '{$data['is_done']}'{$query} WHERE seq = {$data['seq']}"; + if ($this->db_query($sql)) + return $data['seq']; + } +} diff --git a/FacebookAdsAPI.php b/FacebookAdsAPI.php new file mode 100644 index 0000000..12f24ac --- /dev/null +++ b/FacebookAdsAPI.php @@ -0,0 +1,1638 @@ +app_id = $config['app_id']; + $this->app_secret = $config['app_secret']; + $this->access_token = $config['access_token']; + $this->longLivedAccessToken = $config['longLivedAccessToken']; + $this->business_id_list = $config['business_id_list']; + + $this->db = new FBDB(); + $this->access_token = empty($this->access_token) ? "" : (empty($this->longLivedAccessToken) ? $this->access_token : $this->longLivedAccessToken); + if(empty($this->access_token)) { + $this->access_token = $this->getAccessToken(); + } + Api::init($this->app_id, $this->app_secret, $this->access_token, false); + $this->fb = new Facebook([ + 'app_id' => $this->app_id, + 'app_secret' => $this->app_secret, + 'default_access_token' => $this->access_token, + 'default_graph_version' => 'v20.0' + ]); + $this->business_id = $bs_id ? $bs_id : $this->business_id_list[0]; + $this->slack = new SlackChat(); + } catch (Exception $ex) { + echo $ex->getMessage(); + return false; + } + } + + public function getAccessToken() + { + $url = "https://graph.facebook.com/oauth/access_token"; + $params = [ + 'client_id' => $this->app_id, + 'client_secret' => $this->app_secret, + 'grant_type' => 'client_credentials' + ]; + + $ch = curl_init(); + curl_setopt($ch, CURLOPT_URL, $url . '?' . http_build_query($params)); + curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); + curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); + curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false); + + $response = curl_exec($ch); + if (curl_errno($ch)) { + throw new Exception(curl_error($ch)); + } + curl_close($ch); + + $data = json_decode($response, true); + if (isset($data['access_token'])) { + return $data['access_token']; + } else { + throw new Exception("Error getting access token: " . $response); + } + } + + // 일반 엑세스 토큰을 연장시킴 + public function getLongLivedAccessToken() + { + try { //EAAEhoHjMl7gBAJVuAZCygZCHp11NFWNmf6Hng4KSCDBZCEakZC7yEkZAnAkqvXw9wSAqWX3Qg20r0rzoQORglAp1RMNdqHEeQ4Gy1GZCBlVaDIwvI4BiQzBNavFDRWk49adliwGauowZCc6j3DoMKyDuenoSa0iBVHh9t2hMJ35Pfd8Y1XcHRBy + $oAuth2Client = $this->fb->getOAuth2Client(); + $longLivedAccessToken = $oAuth2Client->getLongLivedAccessToken($this->access_token); + $this->access_token = $longLivedAccessToken; + CLI::write("longLivedAccessToken at ". CLI::color($longLivedAccessToken, "white"), "yellow"); + + } catch (Exception $ex) { + echo $ex->getMessage(); + } + } + + // 페이스북 광고 계정 목록 + /* 1 = ACTIVE + 2 = DISABLED + 101 = CLOSED */ + + public function getFBAccounts() + { + try { + $response = $this->fb->get( + '/' . $this->business_id . '/owned_ad_accounts?fields=account_id,name,account_status,disable_reason,funding_source_details,adspixels{id,name}&limit=20', + $this->access_token + ); + $edges = $response->getGraphEdge(); + $results = []; + + do { + foreach ($edges as $account) { + $account = $account->asArray(); + $pixel_id = 'NULL'; + $funding_source = 'NULL'; + if (isset($account['adspixels'])) { + $pixel_id = $account['adspixels'][0]['id']; + } + if (isset($account['funding_source_details']) && isset($account['funding_source_details']['display_string'])) { + $funding_source = $account['funding_source_details']['display_string']; + } + array_push($results, [$this->business_id, $account['account_id'], $account['name'], $funding_source, $account['account_status'], $account['disable_reason'], $pixel_id]); + } + } while ($edges = $this->fb->next($edges)); + + return $results; + } catch (Exception $ex) { + $msgs = [ + 'channel' => '광고API', + 'text' => "[".date("Y-m-d H:i:s")."][" . getenv('MY_SERVER_NAME') . "][페이스북][광고계정] 수신 오류 : " . $ex->getMessage(), + ]; + $this->slack->sendMessage($msgs); + } + } + + // 비지니스 설정 + public function setBusinessId($bs_id = null) { + if(!is_null($bs_id)) $this->business_id = $bs_id; + } + + // 광고 계정 설정 + function setAdAccount($account_id) + { + $this->account_id = "act_" . $account_id; + $this->account = new AdAccount($this->account_id); + } + + // 캠페인 ID 설정 + function setCampaignId($campaign_id) + { + $this->campaign_id = $campaign_id; + $this->campaign = new Campaign($this->campaign_id); + } + + // 광고세트 ID 설정 + function setAdsetId($adset_id) + { + $this->adset_id = $adset_id; + $this->adset = new AdSet($this->adset_id); + } + + // 광고 ID 설정 + function setAdId($adset_id) + { + $this->ad_id = $adset_id; + $this->ad = new Ad($this->ad_id); + } + + // 인사이트 비동기 호출 + public function getAsyncInsights($all = "false", $date = null, $edate = null, $account_id = null) + { + try { + $startTime = microtime(true); // 시작 시간 기록 + + $params = [ + 'date_preset' => AdsInsightsDatePresetValues::TODAY, + 'level' => AdsInsightsLevelValues::AD, + 'breakdowns' => AdsInsightsBreakdownsValues::HOURLY_STATS_AGGREGATED_BY_AUDIENCE_TIME_ZONE, + 'filtering' => [ + // [ + // 'field' => 'ad.impressions', + // 'operator' => 'GREATER_THAN', + // 'value' => 0 + // ], + // [ + // 'field' => 'ad.spend', + // 'operator' => 'GREATER_THAN', + // 'value' => 0 + // ], + // [ + // 'field' => 'ad.effective_status', + // 'operator' => 'IN', + // 'value' => ['ACTIVE', 'ADSET_PAUSED', 'ARCHIVED', 'CAMPAIGN_PAUSED', 'DELETED', 'DISAPPROVED', 'IN_PROCESS', 'PAUSED', 'PENDING_BILLING_INFO', 'PENDING_REVIEW', 'PREAPPROVED', 'WITH_ISSUES'] + // ] + ], + 'fields' => [ + AdsInsightsFields::ACCOUNT_ID, + AdsInsightsFields::CAMPAIGN_ID, + AdsInsightsFields::CAMPAIGN_NAME, + AdsInsightsFields::ADSET_ID, + AdsInsightsFields::ADSET_NAME, + AdsInsightsFields::AD_ID, + AdsInsightsFields::AD_NAME, + AdsInsightsFields::DATE_START, + AdsInsightsFields::DATE_STOP, + AdsInsightsFields::IMPRESSIONS, + AdsInsightsFields::CLICKS, + AdsInsightsFields::INLINE_LINK_CLICKS, + AdsInsightsFields::SPEND + ] + ]; + if (!is_null($date)) { + if (is_null($edate)) { + $edate = $date; + } + $params['time_range'] = ['since' => $date, 'until' => $edate]; + unset($params['date_preset']); + } + if(!is_null($account_id)) { + $accounts[]['ad_account_id'] = $account_id; + $total = 1; + } else { + $account_id = $this->db->getAdAccounts(true); + $accounts = $account_id->getResultArray(); + $total = $account_id->getNumRows(); + } + $step = 1; + CLI::write("[".date("Y-m-d H:i:s")."]"."{$total}개의 계정에 대한 광고인사이트 수신을 시작합니다.", "light_red"); + $return = []; + foreach ($accounts as $row) { + $result = []; + $this->setAdAccount($row['ad_account_id']); + $async_job = $this->account->getInsightsAsync([], $params); + $getSelf = $async_job->getSelf(); + $count = 0; + $continue = false; + while (!$getSelf->isComplete() && !$continue) { + $getSelf = $async_job->getSelf(); + if ($count > 100 && !$getSelf->isComplete()) { + ob_flush(); flush(); sleep(1); + $continue = true; + } + $count++; + } + CLI::showProgress($step++, $total); + // if ($continue) continue; + $insights = $getSelf->getInsights(); + $getResponse = $insights->getResponse(); + $response = $getResponse->getContent(); + $result = array_merge($result, $response['data']); + if (isset($response['paging'])) { + $url = isset($response['paging']['next']) ? $response['paging']['next'] : false; + while ($url) { + $data = $this->getFBRequest_CURL($url); + if (!is_null($data) && isset($data['data'])) $result = array_merge($result, $data['data']); + $url = isset($data['paging']['next']) ? $data['paging']['next'] : false; + } + } + + $this->db->insertAsyncInsights($result); + $return = array_merge($return, $result); + } + $endTime = microtime(true); // 종료 시간 기록 + $executionTime = round($endTime - $startTime, 2); // 실행 시간 계산 + + $msgs = [ + 'channel' => $this->slackChannel, + 'text' => "[".date("Y-m-d H:i:s")."][" . getenv('MY_SERVER_NAME') . "][페이스북][인사이트] {$date}~{$edate} 수신 완료 (실행 시간: {$executionTime}초)", + ]; + $this->slack->sendMessage($msgs); + if ($all == "true") { + $this->updateAds($return); + $this->updateAdCreatives($return); + $this->updateAdsets($return); + $this->updateCampaigns($return); + } + + return $return; + } catch (Exception $ex) { + $msgs = [ + 'channel' => $this->slackChannel, + 'text' => "[".date("Y-m-d H:i:s")."][" . getenv('MY_SERVER_NAME') . "][페이스북][인사이트] {$date}~{$edate} 수신 오류 : " . $ex->getMessage(), + ]; + $this->slack->sendMessage($msgs); + } + } + + public function updateAllByAccounts() { + foreach($this->business_id_list as $bs_id) { + self::setBusinessId($bs_id); + CLI::write("[".date("Y-m-d H:i:s")."]"."{$bs_id}비지니스 업데이트 시작", "white", "magenta"); + self::updateAllByAccount(); + CLI::write("[".date("Y-m-d H:i:s")."]"."{$bs_id}비지니스 업데이트 종료", "white", "magenta"); + } + $msgs = [ + 'channel' => $this->slackChannel, + 'text' => "[".date("Y-m-d H:i:s")."][" . getenv('MY_SERVER_NAME') . "][페이스북]비지니스별 캠페인/광고그룹/광고 정보 수신 완료", + ]; + $this->slack->sendMessage($msgs); + } + + public function updateAllByAccount($bs_id=null) { + try { + if(is_null($bs_id)) $bs_id = $this->business_id; + $account_id = $this->db->getAdAccounts(true, " AND business_id = '{$bs_id}'"); + $accounts = $account_id->getResultArray(); + $total = $account_id->getNumRows(); + $step = 1; + CLI::write("[".date("Y-m-d H:i:s")."]"."{$total}개의 계정에 대한 광고데이터 수신을 시작합니다.", "light_red"); + $result = []; + $campaigns_fields = implode(',', [ CampaignFields::ID, CampaignFields::NAME, CampaignFields::ACCOUNT_ID, CampaignFields::DAILY_BUDGET, CampaignFields::BUDGET_REMAINING, CampaignFields::BUDGET_REBALANCE_FLAG, CampaignFields::CAN_USE_SPEND_CAP, CampaignFields::SPEND_CAP, CampaignFields::OBJECTIVE, CampaignFields::EFFECTIVE_STATUS, CampaignFields::STATUS, CampaignFields::START_TIME, CampaignFields::CREATED_TIME, CampaignFields::UPDATED_TIME ]); + $adsets_fields = implode(',', [ AdSetFields::ID, AdSetFields::NAME, AdSetFields::CAMPAIGN_ID, AdSetFields::EFFECTIVE_STATUS, AdSetFields::STATUS, AdSetFields::LEARNING_STAGE_INFO, AdSetFields::START_TIME, AdSetFields::UPDATED_TIME, AdSetFields::CREATED_TIME, AdSetFields::DAILY_BUDGET, AdSetFields::LIFETIME_BUDGET, AdSetFields::BUDGET_REMAINING ]); + $ads_fields = implode(',', [ AdFields::ID, AdFields::NAME, AdFields::ADSET_ID, AdFields::EFFECTIVE_STATUS, AdFields::STATUS, AdFields::UPDATED_TIME, AdFields::CREATED_TIME, AdFields::TRACKING_SPECS, AdFields::CONVERSION_SPECS ]); + $adcreatives_fields = implode(',', [ AdCreativeFields::ID, AdCreativeFields::BODY, AdCreativeFields::OBJECT_TYPE, AdCreativeFields::OBJECT_URL, AdCreativeFields::THUMBNAIL_URL, AdCreativeFields::IMAGE_FILE, AdCreativeFields::IMAGE_URL, AdCreativeFields::CALL_TO_ACTION_TYPE, AdCreativeFields::OBJECT_STORY_SPEC ]); + foreach($accounts as $account) { + CLI::showProgress($step++, $total); + $response = $this->fb->get( + "/act_{$account['ad_account_id']}?fields=id,name,campaigns{{$campaigns_fields},adsets{{$adsets_fields},ads{{$ads_fields},adcreatives{{$adcreatives_fields}}}}}", + $this->access_token + ); + $data = $response->getDecodedBody(); + $results = []; + $campaigns = $data['campaigns']['data'] ?? []; + foreach ($campaigns as $campaign) { + $adsets = $campaign['adsets']['data'] ?? []; + foreach ($adsets as $adset) { + $ads = $adset['ads']['data'] ?? []; + foreach ($ads as $ad) { + $adcreatives = $ad['adcreatives']['data'] ?? []; + foreach ($adcreatives as &$adcreative) { + $adcreative['ad_id'] = $ad['id']; + } + unset($adcreative); + $this->updateAdcreatives(null, $adcreatives); + } + $this->db->updateAds($ads); + } + $this->db->updateAdsets($adsets); + } + $this->db->updateCampaigns($campaigns); + } + } catch (Exception $ex) { + $msgs = [ + 'channel' => $this->slackChannel, + 'text' => "[".date("Y-m-d H:i:s")."][" . getenv('MY_SERVER_NAME') . "][페이스북] {$bs_id} 캠페인/광고그룹/광고 정보 수신 오류 : " . $ex->getMessage(), + ]; + $this->slack->sendMessage($msgs); + } + } + + public function updateAdCreatives($data = null, $adcreatives = null) + { + try { + if(is_null($adcreatives)) $adcreatives = $this->getAdCreatives($data); + + $result = []; + foreach ($adcreatives as $data) { + $updatedAdCreative = [ + 'adcreative_id' => $data['id'], + 'ad_id' => $data['ad_id'], + 'thumbnail_url' => $data['thumbnail_url'] ?? '', + 'object_type' => $data[AdCreativeFields::OBJECT_TYPE] ?? '', + ]; + $asset_feed_spec = $data[AdCreativeFields::ASSET_FEED_SPEC] ?? []; + if(isset($asset_feed_spec['call_to_action_types']) && isset($asset_feed_spec['call_to_action_types'][0])) + $data[AdCreativeFields::CALL_TO_ACTION_TYPE] = $asset_feed_spec['call_to_action_types'][0]; + if (isset($data[AdCreativeFields::CALL_TO_ACTION_TYPE]) && in_array($data[AdCreativeFields::CALL_TO_ACTION_TYPE], ["LEARN_MORE", "APPLY_NOW", "SIGN_UP", "SHOP_NOW"])) { + $object_story_spec = $data[AdCreativeFields::OBJECT_STORY_SPEC] ?? []; + $video_data = $object_story_spec[AdCreativeObjectStorySpecFields::VIDEO_DATA] ?? []; + $link_data = $object_story_spec[AdCreativeObjectStorySpecFields::LINK_DATA] ?? []; + if(isset($updatedAdCreative['object_type'])){ + switch ($updatedAdCreative['object_type']) { + case 'SHARE': + case 'STATUS': + if (is_array($link_data) && isset($link_data['link'])) { //슬라이드형 + $updatedAdCreative['link'] = $link_data['link']; + } else if(isset($asset_feed_spec['link_urls']) && isset($asset_feed_spec['link_urls'][0]) && isset($asset_feed_spec['link_urls'][0]['website_url'])) { + $updatedAdCreative['link'] = $asset_feed_spec['link_urls'][0]['website_url']; + } + break; + case 'VIDEO': + if (is_array($video_data) && isset($video_data['call_to_action']) && isset($video_data['call_to_action']['value'])) { //비디오 + $updatedAdCreative['link'] = $video_data['call_to_action']['value']['link']; + } + break; + default: + break; + } + } + if (isset($updatedAdCreative['link']) && ($updatedAdCreative['link'] == 'https://fb.me/' || $updatedAdCreative['link'] == 'http://fb.me/')) + $updatedAdCreative['link'] = ''; + } + $result[] = $updatedAdCreative; + } + $this->db->updateAdCreatives($result); + return $result; + } catch (Exception $ex) { + $msgs = [ + 'channel' => $this->slackChannel, + 'text' => "[".date("Y-m-d H:i:s")."][" . getenv('MY_SERVER_NAME') . "][페이스북][소재 정보] 수신 오류 : " . $ex->getMessage(), + ]; + $this->slack->sendMessage($msgs); + } + } + + public function getAdCreatives($data = null) + { + $result = []; + $params = [ + 'thumbnail_width' => 250, + 'thumbnail_height' => 250, + ]; + $fields = [ + AdCreativeFields::ID, + AdCreativeFields::BODY, + AdCreativeFields::OBJECT_TYPE, + AdCreativeFields::OBJECT_URL, + AdCreativeFields::THUMBNAIL_URL, + AdCreativeFields::IMAGE_FILE, + AdCreativeFields::IMAGE_URL, + AdCreativeFields::CALL_TO_ACTION_TYPE, + AdCreativeFields::ASSET_FEED_SPEC, + AdCreativeFields::OBJECT_STORY_SPEC + ]; + if ($data == null) { + $ad_ids = $this->db->getAdsWithAccount(); + foreach ($ad_ids->getResultArray() as $row) { + $data[] = $row; + } + } + foreach ($data as $row) { + if (isset($row['id'])) + $row['ad_id'] = $row['id']; + $this->setAdId($row['ad_id']); + $adcrearives = $this->ad->getAdCreatives($fields, $params); + $response = $adcrearives->getResponse()->getContent(); + + if (!empty($response['data'])) { + $response['data'][0]['ad_id'] = $row['ad_id']; + $result = array_merge($result, $response['data']); + } + } + return $result; + } + + // 개별 광고 조회 업데이트 + + public function updateAds($data = null) + { + try { + $params = [ + 'fields' => [ + AdFields::ID, + AdFields::NAME, + AdFields::ADSET_ID, + AdFields::EFFECTIVE_STATUS, + AdFields::STATUS, + //AdFields::RECOMMENDATIONS, + AdFields::UPDATED_TIME, + AdFields::CREATED_TIME, + AdFields::TRACKING_SPECS, + AdFields::CONVERSION_SPECS + ] + ]; + if ($data == null) { + $ad_ids = $this->db->getAds(); + $data = $ad_ids->getResultArray(); + } + $result = []; + $_ids = []; + $ids = []; + foreach ($data as $row) $_ids[] = $row['ad_id']; + if (count($_ids)) { + $ids = array_unique($_ids); + $total = count($ids); + $step = 1; + if(is_cli()){ + CLI::write("[".date("Y-m-d H:i:s")."]"."{$total}개의 광고 데이터 수신을 시작합니다.", "light_red"); + } + foreach ($ids as $ad_id) { + $this->setAdId($ad_id); + $ads = $this->ad->getSelf([], $params); + $response = $ads->getData(); + if(is_cli()){ + CLI::showProgress($step++, $total); + } + $result[] = [ + 'tracking_specs' => $response['tracking_specs'] ?? [], + 'conversion_specs' => $response['conversion_specs'] ?? [], + 'created_time' => $response['created_time'] ?? '', + 'updated_time' => $response['updated_time'] ?? '', + 'name' => $response['name'] ?? '', + 'id' => $response['id'] ?? '', + 'adset_id' => $response['adset_id'] ?? '', + 'campaign_id' => $response['campaign_id'] ?? '', + 'effective_status' => $response['effective_status'] ?? '', + 'status' => $response['status'] ?? '', + 'fb_pixel' => $response['fb_pixel'] ?? '', + ]; + } + $this->db->updateAds($result); + } + + return $result; + } catch (Exception $ex) { + $msgs = [ + 'channel' => $this->slackChannel, + 'text' => "[".date("Y-m-d H:i:s")."][" . getenv('MY_SERVER_NAME') . "][페이스북][광고 정보] 수신 오류 : " . $ex->getMessage(), + ]; + $this->slack->sendMessage($msgs); + } + } + + // 개별 광고세트 조회 업데이트 + public function updateAdsets($data = null) + { + try { + $params = [ + 'fields' => [ + AdSetFields::ID, + AdSetFields::NAME, + AdSetFields::CAMPAIGN_ID, + AdSetFields::EFFECTIVE_STATUS, + AdSetFields::STATUS, + AdSetFields::LEARNING_STAGE_INFO, + //AdSetFields::RECOMMENDATIONS, + AdSetFields::START_TIME, + AdSetFields::UPDATED_TIME, + AdSetFields::CREATED_TIME, + AdSetFields::DAILY_BUDGET, + AdSetFields::LIFETIME_BUDGET, + AdSetFields::BUDGET_REMAINING + ] + ]; + if ($data == null) { + $adset_ids = $this->db->getAdSetsWithAccount(); + foreach ($adset_ids->getResultArray() as $row) { + $data[] = $row; + } + } + $result = []; + $_ids = []; + $ids = []; + foreach ($data as $row) $_ids[] = $row['adset_id']; + if (count($_ids)) { + $ids = array_unique($_ids); + $total = count($ids); + $step = 1; + if(is_cli()){ + CLI::write("[".date("Y-m-d H:i:s")."]"."{$total}개의 광고그룹 데이터 수신을 시작합니다.", "light_red"); + } + foreach ($ids as $adset_id) { + $this->setAdsetId($adset_id); + $adset = $this->adset->getSelf([], $params); + $response = $adset->getData(); + // echo '
'.print_r($response,1).'
'; exit; + if(is_cli()){ + CLI::showProgress($step++, $total); + } + $result[] = [ + 'budget_remaining' => $response['budget_remaining'] ?? '', + 'start_time' => $response['start_time'] ?? '', + 'created_time' => $response['created_time'] ?? '', + 'updated_time' => $response['updated_time'] ?? '', + 'name' => $response['name'] ?? '', + 'lifetime_budget' => $response['lifetime_budget'] ?? '', + 'daily_budget' => $response['daily_budget'] ?? '', + 'learning_stage_info' => $response['learning_stage_info'] ?? [], + 'id' => $response['id'] ?? '', + 'campaign_id' => $response['campaign_id'] ?? '', + 'effective_status' => $response['effective_status'] ?? '', + 'status' => $response['status'] ?? '', + ]; + } + $this->db->updateAdsets($result); + } + return $result; + } catch (Exception $ex) { + $msgs = [ + 'channel' => $this->slackChannel, + 'text' => "[".date("Y-m-d H:i:s")."][" . getenv('MY_SERVER_NAME') . "][페이스북][광고그룹 정보] 수신 오류 : " . $ex->getMessage(), + ]; + $this->slack->sendMessage($msgs); + } + } + + // 개별 캠페인 조회 업데이트 + public function updateCampaigns($data = null) + { + try { + $params = [ + 'fields' => [ + CampaignFields::ID, + CampaignFields::NAME, + CampaignFields::ACCOUNT_ID, + CampaignFields::DAILY_BUDGET, + CampaignFields::BUDGET_REMAINING, + CampaignFields::BUDGET_REBALANCE_FLAG, + CampaignFields::CAN_USE_SPEND_CAP, + CampaignFields::SPEND_CAP, + CampaignFields::OBJECTIVE, + CampaignFields::EFFECTIVE_STATUS, + CampaignFields::LIFETIME_BUDGET, + //CampaignFields::RECOMMENDATIONS, + CampaignFields::STATUS, + CampaignFields::START_TIME, + CampaignFields::CREATED_TIME, + CampaignFields::UPDATED_TIME + ] + ]; + if ($data == null) { + $campaign_ids = $this->db->getCampaignsWithAccount(); + foreach ($campaign_ids->getResultArray() as $row) { + $data[] = $row; + } + } + $result = []; + $_ids = []; + $ids = []; + foreach ($data as $row) $_ids[] = $row['campaign_id']; + if (count($_ids)) { + $ids = array_unique($_ids); + $total = count($ids); + $step = 1; + if(is_cli()){ + CLI::write("[".date("Y-m-d H:i:s")."]"."{$total}개의 캠페인 데이터 수신을 시작합니다.", "light_red"); + } + foreach ($ids as $campaign_id) { + $this->setCampaignId($campaign_id); + $campaign = $this->campaign->getSelf([], $params); + $response = $campaign->getData(); + if(is_cli()){ + CLI::showProgress($step++, $total); + } + $result[] = [ + 'budget_remaining' => $response['budget_remaining'] ?? '', + 'start_time' => $response['start_time'] ?? '', + 'created_time' => $response['created_time'] ?? '', + 'updated_time' => $response['updated_time'] ?? '', + 'name' => $response['name'] ?? '', + 'can_use_spend_cap' => $response['can_use_spend_cap'] ?? '', + 'budget_rebalance_flag' => $response['budget_rebalance_flag'] ?? '', + 'spend_cap' => $response['spend_cap'] ?? '', + 'lifetime_budget' => $response['lifetime_budget'] ?? '', + 'daily_budget' => $response['daily_budget'] ?? '', + 'id' => $response['id'] ?? '', + 'account_id' => $response['account_id'] ?? '', + 'effective_status' => $response['effective_status'] ?? '', + 'status' => $response['status'] ?? '', + 'objective' => $response['objective'] ?? '', + ]; + } + + $this->db->updateCampaigns($result); + } + + return $result; + } catch (Exception $ex) { + $msgs = [ + 'channel' => $this->slackChannel, + 'text' => "[".date("Y-m-d H:i:s")."][" . getenv('MY_SERVER_NAME') . "][페이스북][캠페인 정보] 수신 오류 : " . $ex->getMessage(), + ]; + $this->slack->sendMessage($msgs); + } + } + + // 광고 조회 + public function getAds() + { + try { + $params = [ + // 'time_range' => ['since'=>date('Y-m-d', strtotime('-2 year')), 'until'=>date('Y-m-d')], + // 'date_preset' => 'today', + AdFields::EFFECTIVE_STATUS => [ + 'ACTIVE', + // 'ADSET_PAUSED', + // 'ARCHIVED', + // 'CAMPAIGN_PAUSED', + // 'DELETED', + 'DISAPPROVED', + // 'IN_PROCESS', + 'PAUSED', + 'PENDING_BILLING_INFO', + 'PENDING_REVIEW', + 'PREAPPROVED', + 'WITH_ISSUES' + ], + /* + AdFields::STATUS => array( + 'ACTIVE', + 'PAUSED' + ),*/ + 'fields' => [ + AdFields::ID, + AdFields::NAME, + AdFields::ADSET_ID, + AdFields::EFFECTIVE_STATUS, + AdFields::STATUS, + AdFields::RECOMMENDATIONS, + AdFields::UPDATED_TIME, + AdFields::CREATED_TIME, + AdFields::TRACKING_SPECS, + AdFields::CONVERSION_SPECS + ] + ]; + + $ad_accounts = $this->db->getAdAccounts(); // 각 광고 계정별 + $total = $ad_accounts->getNumRows(); + $step = 1; + $result = []; + CLI::write("[".date("Y-m-d H:i:s")."]"."{$total}개의 계정에 대한 광고 데이터 수신을 시작합니다.", "light_red"); + foreach ($ad_accounts->getResultArray() as $row) { + // $row['ad_account_id'] = 796319794698742; + $this->setAdAccount($row['ad_account_id']); + $ads = $this->account->getAds([], $params); + $response = $ads->getResponse()->getContent(); + CLI::showProgress($step++, $total); + $result = array_merge($result, $response['data']); + if (isset($response['paging'])) { + $url = isset($response['paging']['next']) ? $response['paging']['next'] : false; + while ($url) { + $data = $this->getFBRequest_CURL($url); + + if (isset($data['data'])) { + $result = array_merge($result, $data['data']); + } + + $url = isset($data['paging']['next']) ? $data['paging']['next'] : false; + } + } + // echo '
'.print_r($result,1).'
'; exit; + } + $this->db->updateAds($result); + return $result; + } catch (Exception $ex) { + $msgs = [ + 'channel' => $this->slackChannel, + 'text' => "[".date("Y-m-d H:i:s")."][" . getenv('MY_SERVER_NAME') . "][페이스북][광고 정보] 수신 오류 : " . $ex->getMessage(), + ]; + $this->slack->sendMessage($msgs); + } + } + + // 페이징 전용 함수 + private function getFBRequest_CURL($url) + { + $ch = curl_init(); + curl_setopt($ch, CURLOPT_URL, $url); + curl_setopt($ch, CURLOPT_HEADER, 0); + curl_setopt($ch, CURLOPT_TIMEOUT, 600); + curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); + curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); + curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false); + $result = curl_exec($ch); + curl_close($ch); + + $data = json_decode($result, true); + + return $data; + } + + public function adLeadByAd($ad_id, $from = "-1 day", $to = null) { + $result = []; + $params = []; + // 시작 날짜 + $from_dt = new DateTime($from); + $from_dt->format('Y-m-d 00:00:00'); + $from_date = $from_dt->getTimestamp(); + + $params['filtering'] = [ + [ + 'field' => 'time_created', + 'operator' => 'GREATER_THAN', + 'value' => $from_date + ], + ]; + + // 끝 날짜 + if ($from !== "-1 day" && $to !== null) { + $to_dt = new DateTime($to." 23:59:59"); + $to_dt->format('Y-m-d H:i:s'); + $to_date = $to_dt->getTimestamp(); + + $params['filtering'][1] = [ + 'field' => 'time_created', + 'operator' => 'LESS_THAN', + 'value' => $to_date + ]; + } + + $fields = [ + LeadFields::ID, + LeadFields::FORM_ID, + LeadFields::AD_ID, + LeadFields::AD_NAME, + LeadFields::ADSET_ID, + LeadFields::ADSET_NAME, + LeadFields::CAMPAIGN_ID, + LeadFields::CAMPAIGN_NAME, + LeadFields::IS_ORGANIC, + LeadFields::FIELD_DATA, + LeadFields::CREATED_TIME, + LeadFields::CUSTOM_DISCLAIMER_RESPONSES + ]; + $this->setAdId($ad_id); + $leads = $this->ad->getLeads($fields, $params); + $response = $leads->getResponse()->getContent(); + $lead_data = []; + if (!empty($response['data'])) { + $lead_data = array_merge($lead_data, $response['data']); + $result = array_merge($result, $response['data']); + } + if (isset($response['paging'])) { + $url = isset($response['paging']['next']) ? $response['paging']['next'] : false; + while ($url) { + $data = $this->getFBRequest_CURL($url); + if (isset($data['data'])) { + $lead_data = array_merge($lead_data, $response['data']); + $result = array_merge($result, $data['data']); + } + $url = isset($data['paging']['next']) ? $data['paging']['next'] : false; + } + } + if(count($lead_data)) + $this->db->insertAdLeads($lead_data); + return $lead_data; + } + + // 각 AdID별 폼 목록 + public function getAdLead($from = "-1 day", $to = null) + { + try { + $result = []; + $params = []; + + // 시작 날짜 + $from_dt = new DateTime($from); + $from_dt->format('Y-m-d 00:00:00'); + $from_date = $from_dt->getTimestamp(); + + $params['filtering'] = [ + [ + 'field' => 'time_created', + 'operator' => 'GREATER_THAN', + 'value' => $from_date + ], + ]; + + // 끝 날짜 + if ($from !== "-1 day" && $to !== null) { + $to_dt = new DateTime($to." 23:59:59"); + $to_dt->format('Y-m-d H:i:s'); + $to_date = $to_dt->getTimestamp(); + + $params['filtering'][1] = [ + 'field' => 'time_created', + 'operator' => 'LESS_THAN', + 'value' => $to_date + ]; + } + + $fields = [ + LeadFields::ID, + LeadFields::FORM_ID, + LeadFields::AD_ID, + LeadFields::AD_NAME, + LeadFields::ADSET_ID, + LeadFields::ADSET_NAME, + LeadFields::CAMPAIGN_ID, + LeadFields::CAMPAIGN_NAME, + LeadFields::IS_ORGANIC, + LeadFields::FIELD_DATA, + LeadFields::CREATED_TIME, + LeadFields::CUSTOM_DISCLAIMER_RESPONSES + ]; + + $ad_ids = $this->db->getLeadgenAds(); //from DB + $total = $ad_ids->getNumRows(); + $step = 1; + CLI::write("[".date("Y-m-d H:i:s")."]"."{$total}개의 광고에서 {$from} ~ {$to} 기간의 잠재고객 데이터를 수신합니다.", "light_red"); + foreach ($ad_ids->getResultArray() as $row) { //while $row['page_id'] + CLI::showProgress($step++, $total); + if ($row['leadgen_id'] == null || $row['leadgen_id'] == '' || $row['status'] != 'ACTIVE') {// || strtotime($row['update_date']) <= strtotime('-1 month')) { //소재가 1개월 이상 업데이트 되지 않았으면 잠재고객을 받지 않음 + continue; + } + // echo '
'.print_r($row,1).'
'; + $this->setAdId($row['ad_id']); + $leads = $this->ad->getLeads($fields, $params); + $response = $leads->getResponse()->getContent(); + $lead_data = []; + if (!empty($response['data'])) { + $lead_data = array_merge($lead_data, $response['data']); + $result = array_merge($result, $response['data']); + } + if (isset($response['paging'])) { + $url = isset($response['paging']['next']) ? $response['paging']['next'] : false; + while ($url) { + $data = $this->getFBRequest_CURL($url); + if (isset($data['data'])) { + $lead_data = array_merge($lead_data, $data['data']); + $result = array_merge($result, $data['data']); + } + $url = isset($data['paging']['next']) ? $data['paging']['next'] : false; + } + } + if(count($lead_data)) { + $this->db->insertAdLeads($lead_data); + } + } + + return $result; + } catch (Exception $ex) { + $msgs = [ + 'channel' => $this->slackChannel, + 'text' => "[".date("Y-m-d H:i:s")."][" . getenv('MY_SERVER_NAME') . "][페이스북][잠재고객] 수신 오류 : " . $ex->getMessage(), + ]; + $this->slack->sendMessage($msgs); + } + } + + + public function updateAdAccounts() + { + + $result = []; + foreach($this->business_id_list as $bs_id) { + self::setBusinessId($bs_id); + $accounts = self::getFBAccounts(); + $this->db->updateAdAccounts($accounts); + $result = array_merge($result, $accounts); + } + $msgs = [ + 'channel' => $this->slackChannel, + 'text' => "[".date("Y-m-d H:i:s")."][" . getenv('MY_SERVER_NAME') . "][페이스북][광고계정] 수신 완료", + ]; + $this->slack->sendMessage($msgs); + return $result; + } + + public function getCampaignStatusBudget($campaign_id) + { + $params = [ + 'fields' => [ + CampaignFields::ID, + CampaignFields::DAILY_BUDGET, + CampaignFields::STATUS, + ] + ]; + + $this->setCampaignId($campaign_id); + $campaign = $this->campaign->getSelf([], $params); + $response = $campaign->getData(); + + $result = [ + 'id' => $response['id'], + 'budget' => $response['daily_budget'], + 'status' => $response['status'] + ]; + return $result; + } + + //광고 상태 업데이트 + public function setCampaignStatus($id, $status) + { + $result = []; + $statusValue = $status == 'ACTIVE' ? Campaign::STATUS_ACTIVE : Campaign::STATUS_PAUSED; + + $this->setCampaignId($id); + $campaign = $this->campaign->updateSelf([], [ + Campaign::STATUS_PARAM_NAME => $statusValue, + ]); + + $campaign = $campaign->getData(); + if ($campaign['success'] == 1) { + $this->db->setCampaignStatus($id, $status); + $result = ['response' => true]; + return $result; + } + + return null; + } + + public function getAdsetStatusBudget($adset_id) + { + $params = [ + 'fields' => [ + AdSetFields::ID, + AdSetFields::STATUS, + AdSetFields::DAILY_BUDGET, + AdSetFields::LIFETIME_BUDGET, + ] + ]; + + $row = $this->db->getAdSet($adset_id); + switch ($row['budget_type']) { + case 'lifetime': + $params[] = AdSetFields::LIFETIME_BUDGET; + break; + case 'daily': + $params[] = AdSetFields::DAILY_BUDGET; + break; + default: + return null; + } + + $this->setAdsetId($adset_id); + $adset = $this->adset->getSelf([], $params); + $response = $adset->getData(); + if ($response['success'] == 1) { + $result = [ + 'id' => $response['id'], + 'status' => $response['status'] + ]; + switch ($row['budget_type']) { + case 'lifetime': + $result['budget'] = $response['lifetime_budget']; + break; + case 'daily': + $result['budget'] = $response['daily_budget']; + break; + default: + return null; + } + return $result; + }else{ + return null; + } + } + + public function setAdsetStatus($id, $status) + { + $result = []; + $statusValue = $status == 'ACTIVE' ? AdSet::STATUS_ACTIVE : AdSet::STATUS_PAUSED; + + $this->setAdsetId($id); + $adset = $this->adset->updateSelf([], [ + AdSet::STATUS_PARAM_NAME => $statusValue, + ]); + $adset = $adset->getData(); + if ($adset['success'] == 1) { + $this->db->setAdsetStatus($id, $status); + $result = ['response' => true]; + return $result; + } + + return null; + } + + public function getAdStatusBudget($ad_id) + { + $params = [ + 'fields' => [ + AdFields::ID, + AdFields::STATUS, + ] + ]; + + $this->setAdId($ad_id); + $ads = $this->ad->getSelf([], $params); + $response = $ads->getData(); + + $result = [ + 'id' => $response['id'], + 'status' => $response['status'] + ]; + return $result; + } + + public function setAdStatus($id, $status) + { + $result = []; + $statusValue = $status == 'ACTIVE' ? Ad::STATUS_ACTIVE : Ad::STATUS_PAUSED; + + $this->setAdId($id); + $ad = $this->ad->updateSelf([], [ + Ad::STATUS_PARAM_NAME => $statusValue, + ]); + $ad = $ad->getData(); + if ($ad['success'] == 1) { + $this->db->setAdStatus($id, $status); + $result = ['response' => true]; + return $result; + } + + return null; + } + + public function updateCampaignBudget($data) + { + //한개씩 캠페인 일일예산 수정 + $campaign_id = $data['id'] ?? null; + $budget = $data['budget'] ?? null; + + if (!$campaign_id || $budget === null) { + return null; + } + + $row = $this->db->getCampaign($campaign_id); + // 기본 정보 설정 + $campaignfields = [CampaignFields::DAILY_BUDGET => intval($budget)]; + + $campaign = new Campaign($campaign_id); + + // $campaign->setData($campaignfields); + $campaign = $campaign->updateSelf([], $campaignfields); + $campaign = $campaign->getData(); + + if ($campaign['success'] == 1) { + $this->db->updateCampaignBudget($campaign_id, $budget); + return $campaign_id; + } + return null; + } + + public function updateAdSetBudget($data) + { + //한개씩 일일예산 수정 + $adset_id = $data['id'] ?? null; + $budget = $data['budget'] ?? null; + if (!$adset_id || !$budget || $budget < 1000) { + return null; + } + $row = $this->db->getAdSet($adset_id); + $field = ''; + switch ($row['budget_type']) { + case 'lifetime': + $field = AdSetFields::LIFETIME_BUDGET; + break; + case 'daily': + $field = AdSetFields::DAILY_BUDGET; + break; + } + // 기본 정보 설정 + $adsetfields = [$field => $budget]; + + $adset = new AdSet($adset_id); + // $adset->setData($adsetfields); + $adset = $adset->updateSelf([], $adsetfields); + $adset = $adset->getData(); + + if ($adset['success'] == 1) { + $this->db->updateAdSetBudget($adset_id, $budget); + return $adset_id; + } + + return null; + } + + public function updateName($data) + { + $id = trim($data['id'] ?? ''); + $type = trim($data['type'] ?? ''); + + if (!$id || !$type) { + return null; + } + $result = ''; + switch ($type) { + case 'campaigns': + $result = $this->updateCampaignName($data); + break; + case 'adsets': + $result = $this->updateAdsetName($data); + break; + case 'ads': + $result = $this->updateAdName($data); + break; + default: + return null; + } + return $result; + } + + private function updateCampaign(array $fields, array $data) + { + if (empty($fields) || empty($data)) { + return null; + } + + if (empty($data['id'])) { + return null; + } + + $campaign = new Campaign($data['id']); + // $campaign->setData($fields); + $campaign = $campaign->updateSelf([], $data); + $campaign = $campaign->getData(); + if ($campaign['success'] == 1) { + return $data; + } + + return null; + } + + private function updateAdset(array $fields, array $data) + { + if (empty($fields) || empty($data)) { + return null; + } + + if (empty($data['id'])) { + return null; + } + + $adset = new AdSet($data['id']); + // $adset->setData($fields); + $adset = $adset->updateSelf([], $data); + $adset = $adset->getData(); + if ($adset['success'] == 1) { + return $data; + } + + return null; + } + + private function updateAd(array $fields, array $data) + { + if (empty($fields) || empty($data)) { + return null; + } + + if (empty($data['id'])) { + return null; + } + + $ad = new Ad($data['id']); + // $ad->setData($fields); + $ad = $ad->updateSelf([], $data); + $ad = $ad->getData(); + if ($ad['success'] == 1) { + return $data; + } + + return null; + } + + public function updateCampaignName(array $data) + { + if(empty($data['name'])){ + return null; + } + + $fields = [CampaignFields::NAME => $data['name']]; + $apiResult = $this->updateCampaign($fields, $data); + if ($apiResult) { + $this->db->updateCampaignName($data); + return $apiResult; + } + + return null; + } + + public function updateAdsetName(array $data) + { + if(empty($data['name'])){ + return null; + } + + $fields = [AdSetFields::NAME => $data['name']]; + $apiResult = $this->updateAdset($fields, $data); + if ($apiResult) { + $this->db->updateAdsetName($data); + return $apiResult; + } + return null; + } + + public function updateAdName(array $data) + { + if(empty($data['name'])){ + return null; + } + + $fields = [AdFields::NAME => $data['name']]; + $apiResult = $this->updateAd($fields, $data); + if ($apiResult) { + $this->db->updateAdName($data); + return $apiResult; + } + return null; + } + + public function setManualUpdate($campaignIds) + { + if(!$campaignIds){return false;} + + $campaignParam = [ + CampaignFields::ID, + CampaignFields::NAME, + CampaignFields::ACCOUNT_ID, + CampaignFields::DAILY_BUDGET, + CampaignFields::BUDGET_REMAINING, + CampaignFields::BUDGET_REBALANCE_FLAG, + CampaignFields::CAN_USE_SPEND_CAP, + CampaignFields::SPEND_CAP, + CampaignFields::OBJECTIVE, + CampaignFields::EFFECTIVE_STATUS, + //CampaignFields::RECOMMENDATIONS, + CampaignFields::STATUS, + CampaignFields::START_TIME, + CampaignFields::CREATED_TIME, + CampaignFields::UPDATED_TIME + ]; + + $adsetParam = [ + AdSetFields::ID, + AdSetFields::NAME, + AdSetFields::CAMPAIGN_ID, + AdSetFields::EFFECTIVE_STATUS, + AdSetFields::STATUS, + AdSetFields::LEARNING_STAGE_INFO, + //AdSetFields::RECOMMENDATIONS, + AdSetFields::START_TIME, + AdSetFields::UPDATED_TIME, + AdSetFields::CREATED_TIME, + AdSetFields::DAILY_BUDGET, + AdSetFields::LIFETIME_BUDGET, + AdSetFields::BUDGET_REMAINING + ]; + + $adParam = [ + AdFields::ID, + AdFields::NAME, + AdFields::ADSET_ID, + AdFields::EFFECTIVE_STATUS, + AdFields::STATUS, + //AdFields::RECOMMENDATIONS, + AdFields::UPDATED_TIME, + AdFields::CREATED_TIME, + AdFields::TRACKING_SPECS, + AdFields::CONVERSION_SPECS + ]; + + $adCreativeParams = [ + 'thumbnail_width' => 250, + 'thumbnail_height' => 250, + ]; + + $adCreativeFields = [ + AdCreativeFields::ID, + AdCreativeFields::BODY, + AdCreativeFields::OBJECT_TYPE, + AdCreativeFields::OBJECT_URL, + AdCreativeFields::THUMBNAIL_URL, + AdCreativeFields::IMAGE_FILE, + AdCreativeFields::IMAGE_URL, + AdCreativeFields::CALL_TO_ACTION_TYPE, + AdCreativeFields::OBJECT_STORY_SPEC + ]; + + $campaignResult = []; + foreach ($campaignIds as $campaignId) { + $this->setCampaignId($campaignId); + $campaign = $this->campaign->read($campaignParam); + $campaignResponse = $campaign->getData(); + $campaignResult[] = [ + 'budget_remaining' => $campaignResponse['budget_remaining'] ?? '', + 'start_time' => $campaignResponse['start_time'] ?? '', + 'created_time' => $campaignResponse['created_time'] ?? '', + 'updated_time' => $campaignResponse['updated_time'] ?? '', + 'name' => $campaignResponse['name'] ?? '', + 'can_use_spend_cap' => $campaignResponse['can_use_spend_cap'] ?? '', + 'budget_rebalance_flag' => $campaignResponse['budget_rebalance_flag'] ?? '', + 'spend_cap' => $campaignResponse['spend_cap'] ?? '', + 'lifetime_budget' => $campaignResponse['lifetime_budget'] ?? '', + 'daily_budget' => $campaignResponse['daily_budget'] ?? '', + 'id' => $campaignResponse['id'] ?? '', + 'account_id' => $campaignResponse['account_id'] ?? '', + 'effective_status' => $campaignResponse['effective_status'] ?? '', + 'status' => $campaignResponse['status'] ?? '', + 'objective' => $campaignResponse['objective'] ?? '', + ]; + + $adsetResult = []; + $adsets = $this->campaign->getAdSets($adsetParam); + foreach ($adsets as $adset) { + $adsetResponse = $adset->getData(); + $adsetResult[] = [ + 'budget_remaining' => $adsetResponse['budget_remaining'] ?? '', + 'start_time' => $adsetResponse['start_time'] ?? '', + 'created_time' => $adsetResponse['created_time'] ?? '', + 'updated_time' => $adsetResponse['updated_time'] ?? '', + 'name' => $adsetResponse['name'] ?? '', + 'lifetime_budget' => $adsetResponse['lifetime_budget'] ?? '', + 'daily_budget' => $adsetResponse['daily_budget'] ?? '', + 'learning_stage_info' => $adsetResponse['learning_stage_info'] ?? [], + 'id' => $adsetResponse['id'] ?? '', + 'campaign_id' => $adsetResponse['campaign_id'] ?? '', + 'effective_status' => $adsetResponse['effective_status'] ?? '', + 'status' => $adsetResponse['status'] ?? '', + ]; + + $adResult = []; + $ads = $adset->getAds($adParam); + foreach ($ads as $ad) { + $adResponse = $ad->getData(); + $adResult[] = [ + 'tracking_specs' => $adResponse['tracking_specs'] ?? [], + 'conversion_specs' => $adResponse['conversion_specs'] ?? [], + 'created_time' => $adResponse['created_time'] ?? '', + 'updated_time' => $adResponse['updated_time'] ?? '', + 'name' => $adResponse['name'] ?? '', + 'id' => $adResponse['id'] ?? '', + 'adset_id' => $adResponse['adset_id'] ?? '', + 'campaign_id' => $adResponse['campaign_id'] ?? '', + 'effective_status' => $adResponse['effective_status'] ?? '', + 'status' => $adResponse['status'] ?? '', + 'fb_pixel' => $adResponse['fb_pixel'] ?? '', + ]; + + $adCreatives = $ad->getAdCreatives($adCreativeFields, $adCreativeParams); + foreach ($adCreatives as $adCreative) { + $acResponse = $adCreative->getData(); + $acResponse['ad_id'] = $adResponse['id']; + $acResult[] = $acResponse; + } + $result = $this->updateAdcreatives(null, $acResult); + if(!$result){ + return false; + } + } + $result = $this->db->updateAds($adResult); + if(!$result){ + return false; + } + } + $result = $this->db->updateAdsets($adsetResult); + if(!$result){ + return false; + } + } + $result = $this->db->updateCampaigns($campaignResult); + if(!$result){ + return false; + } + return true; + } + + public function landingGroup($title) + { + if (empty($title)) return null; + preg_match_all('/.+\#([0-9]+)?(\_([0-9]+))?([\s]+)?(\*([0-9]+)?)?([\s]+)?(\&([a-z]+))?([\s]+)?(\^([0-9]+))?/i', $title, $matches); + if(!isset($matches[9][0])) $matches[9][0] = ""; + switch ($matches[9][0]) { + case 'fer': $media = '이벤트 랜딩'; break; + case 'fercpm': $media = '이벤트 랜딩_cpm'; break; + case 'ler': $media = '이벤트 잠재고객'; break; + case 'lercpm': $media = '이벤트 잠재고객_cpm'; break; + case 'cpm': $media = 'cpm'; break; + default: $media = '';break; + } + if ($media) { + $period_ad = isset($matches[12][0]) && $matches[12][0] ? $matches[12][0] : 0; + $result = [ + 'name' => $matches[0][0] ?? '' + ,'media' => $media + ,'media_code' => $matches[9][0]??'' + ,'event_seq' => $matches[1][0] ?? '' + ,'site' => $matches[3][0] ?? '' + ,'db_price' => $matches[6][0] ?? 0 + ,'period_ad' => $period_ad + ]; + return $result; + } + return null; + } + + public function getAdsUseLanding($date = null) + { + //유효DB 개수 업데이트 + if ($date == null) { + $date = date('Y-m-d'); + } + $ads = $this->db->getAdLeads($date); + $step = 1; + $total = $ads->getNumRows(); + if(!$total) return null; + $result = []; + foreach($ads->getResultArray() as $row) { + $error = []; + CLI::showProgress($step++, $total); + if (!empty($row['code'])) { + $title = trim($row['code']); + }else{ + $title = $row['ad_name']; + } + $landing = $this->landingGroup($title); //소재와 이벤트 매칭 + $data = []; + $data = [ + 'date' => $date + ,'ad_id' => $row['ad_id'] + ]; + if(!is_null($landing)){ + $data = array_merge($data, $landing); + if (!preg_match('/cpm/', $landing['media'])) { + if (!$landing['event_seq']) $error[] = $row['ad_name'] . '(' . $row['ad_id'] . '): 이벤트번호 미입력' . PHP_EOL; + if (!$landing['db_price']) $error[] = $row['ad_name'] . '(' . $row['ad_id'] . '): DB단가 미입력' . PHP_EOL; + } + }else if(preg_match('/&[a-z]+/', $row['ad_name'])){ + $error[] = $row['ad_name'] . '(' . $row['ad_id'] . '): 인식 오류' . PHP_EOL; + } + + if(!empty($error)){ + foreach($error as $err) CLI::write("{$err}", "light_purple"); + } + + if(empty($landing)) continue; + + $dp = $this->db->getDbPrice($data); + $leads = $this->db->getLeads($data); + $cpm = false; + if(is_null($leads) && $data['media'] === 'cpm') $cpm = true; + $db_price = $data['db_price']; + if(isset($dp['db_price']) && $data['date'] != date('Y-m-d')) + $db_price = $data['db_price'] = $dp['db_price']; + /* + *수익, 매출액 계산 + !xxxcpm - 유효db n / 수익,매출0 + !cpm - 유효db 0 / 수익,매출0 + !period - ^25 = *0.25 + */ + $sp_data = json_decode($row['spend_data'],1); + if(!$data['event_seq'] && $data['media']) { + foreach($sp_data as $hour => $spend) { + $margin = 0; + if($data['period_ad']) $margin = $spend * ('0.' . $data['period_ad']); + $data['data'][] = ['hour' => $hour,'spend' => $spend,'count' => "",'sales' => "",'margin' => $margin]; + } + } + $initZero = false; + if(preg_match('/cpm/i', $data['media'])) //cpm (fhrm, fhspcpm, jhrcpm) 계산을 무효화 + $initZero = true; + $lead = []; + if(!is_null($leads)) { + foreach($leads->getResultArray() as $row) { + // if($data['ad_id'] == 23853888597370162) dd($row); + $sales = 0; + $db_count = $row['db_count'] ?? 0; + if($db_price) $sales = $db_price * $db_count; + if($initZero) $sales = 0; + if(preg_match('/cpm/i', $data['media'])) $db_count = 0; + $lead[$row['hour']] = [ + 'sales' => $sales + ,'db_count' => $db_count + ]; + } + } + for($i=0; $i<=23; $i++) { //DB수량이 없어도 지출금액이 갱신되어야하기 때문에 0~23시까지 모두 저장 + // if($data['ad_id'] == 23853888597370162) dd($lead); + $hour = $i; + $spend = $sp_data[$i]??0; + $count = $lead[$i]['db_count']??0; + $sales = $lead[$i]['sales']??0; + $margin = $sales - $spend; + if($initZero) $margin = $sales = 0; + if(preg_match('/cpm/i', $data['media'])) $count = 0; + if($data['period_ad']) $margin = $spend * ('0.' . $data['period_ad']); + $data['data'][] = [ + 'hour' => $hour + ,'spend' => $spend + ,'count' => $count + ,'sales' => $sales + ,'margin' => $margin + ]; + $result = array_merge($result, $data); + } + // d($data); + // if($data['ad_id'] == 23852707712760746) dd($data); + if(isset($data['ad_id'])) $this->db->updateInsight($data); + } + return $result; + } + + public static function exception_handler($e) + { + //echo nl2br(print_r($e,1)); + echo (''); + print_r($e); + echo (''); + return true; + } + + //////////////////////////////////////////////////// + public function getMemo($data) + { + if(!empty($data)){ + $response = $this->db->getMemo($data); + return $response; + } + } + + public function addMemo($data) + { + if(!empty($data)){ + return $this->db->addMemo($data); + } + } + + public function updateMemo($data) + { + if(!empty($data)){ + return $this->db->updateMemo($data); + } + } +} diff --git a/composer.json b/composer.json new file mode 100644 index 0000000..c2f9f3d --- /dev/null +++ b/composer.json @@ -0,0 +1,12 @@ +{ + "require": { + "janu-software/facebook-php-sdk": "*", + "facebook/php-business-sdk": "*", + "php-http/guzzle7-adapter": "^1.0" + }, + "config": { + "allow-plugins": { + "php-http/discovery": true + } + } +} \ No newline at end of file diff --git a/composer.lock b/composer.lock new file mode 100644 index 0000000..9ca5283 --- /dev/null +++ b/composer.lock @@ -0,0 +1,1266 @@ +{ + "_readme": [ + "This file locks the dependencies of your project to a known state", + "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", + "This file is @generated automatically" + ], + "content-hash": "3ea6fcac584779a8c743ad518249ad67", + "packages": [ + { + "name": "clue/stream-filter", + "version": "v1.7.0", + "source": { + "type": "git", + "url": "https://github.com/clue/stream-filter.git", + "reference": "049509fef80032cb3f051595029ab75b49a3c2f7" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/clue/stream-filter/zipball/049509fef80032cb3f051595029ab75b49a3c2f7", + "reference": "049509fef80032cb3f051595029ab75b49a3c2f7", + "shasum": "" + }, + "require": { + "php": ">=5.3" + }, + "require-dev": { + "phpunit/phpunit": "^9.6 || ^5.7 || ^4.8.36" + }, + "type": "library", + "autoload": { + "files": [ + "src/functions_include.php" + ], + "psr-4": { + "Clue\\StreamFilter\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Christian Lück", + "email": "christian@clue.engineering" + } + ], + "description": "A simple and modern approach to stream filtering in PHP", + "homepage": "https://github.com/clue/stream-filter", + "keywords": [ + "bucket brigade", + "callback", + "filter", + "php_user_filter", + "stream", + "stream_filter_append", + "stream_filter_register" + ], + "support": { + "issues": "https://github.com/clue/stream-filter/issues", + "source": "https://github.com/clue/stream-filter/tree/v1.7.0" + }, + "funding": [ + { + "url": "https://clue.engineering/support", + "type": "custom" + }, + { + "url": "https://github.com/clue", + "type": "github" + } + ], + "time": "2023-12-20T15:40:13+00:00" + }, + { + "name": "facebook/php-business-sdk", + "version": "19.0.3", + "source": { + "type": "git", + "url": "https://github.com/facebook/facebook-php-business-sdk.git", + "reference": "f3eb099fa895ff6b5ddd98ba993982c2803b22d3" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/facebook/facebook-php-business-sdk/zipball/f3eb099fa895ff6b5ddd98ba993982c2803b22d3", + "reference": "f3eb099fa895ff6b5ddd98ba993982c2803b22d3", + "shasum": "" + }, + "require": { + "guzzlehttp/guzzle": "^6.5 || ^7.0", + "php": ">=8.0" + }, + "require-dev": { + "mockery/mockery": "1.3.3", + "phpunit/phpunit": "~9", + "symfony/finder": "~2.6" + }, + "type": "library", + "autoload": { + "psr-4": { + "FacebookAds\\": "src/FacebookAds/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "description": "PHP SDK for Facebook Business", + "homepage": "https://developers.facebook.com/", + "keywords": [ + "ads", + "business", + "facebook", + "instagram", + "page", + "sdk" + ], + "support": { + "issues": "https://github.com/facebook/facebook-php-business-sdk/issues", + "source": "https://github.com/facebook/facebook-php-business-sdk/tree/19.0.3" + }, + "time": "2024-04-15T18:22:25+00:00" + }, + { + "name": "guzzlehttp/guzzle", + "version": "7.8.1", + "source": { + "type": "git", + "url": "https://github.com/guzzle/guzzle.git", + "reference": "41042bc7ab002487b876a0683fc8dce04ddce104" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/guzzle/guzzle/zipball/41042bc7ab002487b876a0683fc8dce04ddce104", + "reference": "41042bc7ab002487b876a0683fc8dce04ddce104", + "shasum": "" + }, + "require": { + "ext-json": "*", + "guzzlehttp/promises": "^1.5.3 || ^2.0.1", + "guzzlehttp/psr7": "^1.9.1 || ^2.5.1", + "php": "^7.2.5 || ^8.0", + "psr/http-client": "^1.0", + "symfony/deprecation-contracts": "^2.2 || ^3.0" + }, + "provide": { + "psr/http-client-implementation": "1.0" + }, + "require-dev": { + "bamarni/composer-bin-plugin": "^1.8.2", + "ext-curl": "*", + "php-http/client-integration-tests": "dev-master#2c025848417c1135031fdf9c728ee53d0a7ceaee as 3.0.999", + "php-http/message-factory": "^1.1", + "phpunit/phpunit": "^8.5.36 || ^9.6.15", + "psr/log": "^1.1 || ^2.0 || ^3.0" + }, + "suggest": { + "ext-curl": "Required for CURL handler support", + "ext-intl": "Required for Internationalized Domain Name (IDN) support", + "psr/log": "Required for using the Log middleware" + }, + "type": "library", + "extra": { + "bamarni-bin": { + "bin-links": true, + "forward-command": false + } + }, + "autoload": { + "files": [ + "src/functions_include.php" + ], + "psr-4": { + "GuzzleHttp\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Graham Campbell", + "email": "hello@gjcampbell.co.uk", + "homepage": "https://github.com/GrahamCampbell" + }, + { + "name": "Michael Dowling", + "email": "mtdowling@gmail.com", + "homepage": "https://github.com/mtdowling" + }, + { + "name": "Jeremy Lindblom", + "email": "jeremeamia@gmail.com", + "homepage": "https://github.com/jeremeamia" + }, + { + "name": "George Mponos", + "email": "gmponos@gmail.com", + "homepage": "https://github.com/gmponos" + }, + { + "name": "Tobias Nyholm", + "email": "tobias.nyholm@gmail.com", + "homepage": "https://github.com/Nyholm" + }, + { + "name": "Márk Sági-Kazár", + "email": "mark.sagikazar@gmail.com", + "homepage": "https://github.com/sagikazarmark" + }, + { + "name": "Tobias Schultze", + "email": "webmaster@tubo-world.de", + "homepage": "https://github.com/Tobion" + } + ], + "description": "Guzzle is a PHP HTTP client library", + "keywords": [ + "client", + "curl", + "framework", + "http", + "http client", + "psr-18", + "psr-7", + "rest", + "web service" + ], + "support": { + "issues": "https://github.com/guzzle/guzzle/issues", + "source": "https://github.com/guzzle/guzzle/tree/7.8.1" + }, + "funding": [ + { + "url": "https://github.com/GrahamCampbell", + "type": "github" + }, + { + "url": "https://github.com/Nyholm", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/guzzlehttp/guzzle", + "type": "tidelift" + } + ], + "time": "2023-12-03T20:35:24+00:00" + }, + { + "name": "guzzlehttp/promises", + "version": "2.0.2", + "source": { + "type": "git", + "url": "https://github.com/guzzle/promises.git", + "reference": "bbff78d96034045e58e13dedd6ad91b5d1253223" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/guzzle/promises/zipball/bbff78d96034045e58e13dedd6ad91b5d1253223", + "reference": "bbff78d96034045e58e13dedd6ad91b5d1253223", + "shasum": "" + }, + "require": { + "php": "^7.2.5 || ^8.0" + }, + "require-dev": { + "bamarni/composer-bin-plugin": "^1.8.2", + "phpunit/phpunit": "^8.5.36 || ^9.6.15" + }, + "type": "library", + "extra": { + "bamarni-bin": { + "bin-links": true, + "forward-command": false + } + }, + "autoload": { + "psr-4": { + "GuzzleHttp\\Promise\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Graham Campbell", + "email": "hello@gjcampbell.co.uk", + "homepage": "https://github.com/GrahamCampbell" + }, + { + "name": "Michael Dowling", + "email": "mtdowling@gmail.com", + "homepage": "https://github.com/mtdowling" + }, + { + "name": "Tobias Nyholm", + "email": "tobias.nyholm@gmail.com", + "homepage": "https://github.com/Nyholm" + }, + { + "name": "Tobias Schultze", + "email": "webmaster@tubo-world.de", + "homepage": "https://github.com/Tobion" + } + ], + "description": "Guzzle promises library", + "keywords": [ + "promise" + ], + "support": { + "issues": "https://github.com/guzzle/promises/issues", + "source": "https://github.com/guzzle/promises/tree/2.0.2" + }, + "funding": [ + { + "url": "https://github.com/GrahamCampbell", + "type": "github" + }, + { + "url": "https://github.com/Nyholm", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/guzzlehttp/promises", + "type": "tidelift" + } + ], + "time": "2023-12-03T20:19:20+00:00" + }, + { + "name": "guzzlehttp/psr7", + "version": "2.6.2", + "source": { + "type": "git", + "url": "https://github.com/guzzle/psr7.git", + "reference": "45b30f99ac27b5ca93cb4831afe16285f57b8221" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/guzzle/psr7/zipball/45b30f99ac27b5ca93cb4831afe16285f57b8221", + "reference": "45b30f99ac27b5ca93cb4831afe16285f57b8221", + "shasum": "" + }, + "require": { + "php": "^7.2.5 || ^8.0", + "psr/http-factory": "^1.0", + "psr/http-message": "^1.1 || ^2.0", + "ralouphie/getallheaders": "^3.0" + }, + "provide": { + "psr/http-factory-implementation": "1.0", + "psr/http-message-implementation": "1.0" + }, + "require-dev": { + "bamarni/composer-bin-plugin": "^1.8.2", + "http-interop/http-factory-tests": "^0.9", + "phpunit/phpunit": "^8.5.36 || ^9.6.15" + }, + "suggest": { + "laminas/laminas-httphandlerrunner": "Emit PSR-7 responses" + }, + "type": "library", + "extra": { + "bamarni-bin": { + "bin-links": true, + "forward-command": false + } + }, + "autoload": { + "psr-4": { + "GuzzleHttp\\Psr7\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Graham Campbell", + "email": "hello@gjcampbell.co.uk", + "homepage": "https://github.com/GrahamCampbell" + }, + { + "name": "Michael Dowling", + "email": "mtdowling@gmail.com", + "homepage": "https://github.com/mtdowling" + }, + { + "name": "George Mponos", + "email": "gmponos@gmail.com", + "homepage": "https://github.com/gmponos" + }, + { + "name": "Tobias Nyholm", + "email": "tobias.nyholm@gmail.com", + "homepage": "https://github.com/Nyholm" + }, + { + "name": "Márk Sági-Kazár", + "email": "mark.sagikazar@gmail.com", + "homepage": "https://github.com/sagikazarmark" + }, + { + "name": "Tobias Schultze", + "email": "webmaster@tubo-world.de", + "homepage": "https://github.com/Tobion" + }, + { + "name": "Márk Sági-Kazár", + "email": "mark.sagikazar@gmail.com", + "homepage": "https://sagikazarmark.hu" + } + ], + "description": "PSR-7 message implementation that also provides common utility methods", + "keywords": [ + "http", + "message", + "psr-7", + "request", + "response", + "stream", + "uri", + "url" + ], + "support": { + "issues": "https://github.com/guzzle/psr7/issues", + "source": "https://github.com/guzzle/psr7/tree/2.6.2" + }, + "funding": [ + { + "url": "https://github.com/GrahamCampbell", + "type": "github" + }, + { + "url": "https://github.com/Nyholm", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/guzzlehttp/psr7", + "type": "tidelift" + } + ], + "time": "2023-12-03T20:05:35+00:00" + }, + { + "name": "janu-software/facebook-php-sdk", + "version": "v0.2.3", + "source": { + "type": "git", + "url": "https://github.com/janu-software/facebook-php-sdk.git", + "reference": "b4118d696f1fdcdb4e5eeddcdbfd9f95f5ebdff5" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/janu-software/facebook-php-sdk/zipball/b4118d696f1fdcdb4e5eeddcdbfd9f95f5ebdff5", + "reference": "b4118d696f1fdcdb4e5eeddcdbfd9f95f5ebdff5", + "shasum": "" + }, + "require": { + "guzzlehttp/psr7": "^2.5", + "php": ">=8.1 <8.4", + "php-http/client-implementation": "^1.0", + "php-http/discovery": "^1.15", + "php-http/httplug": "^2.4", + "php-http/message": "^1.14", + "psr/http-message": "^1.1", + "thecodingmachine/safe": "^2.5" + }, + "require-dev": { + "guzzlehttp/guzzle": "^7.8", + "jetbrains/phpstorm-attributes": "^1.0", + "php-http/guzzle7-adapter": "^1.0", + "phpunit/phpunit": "^10.3", + "rector/rector": "^0.19", + "stanislav-janu/phpstan": "^1.0", + "symfony/deprecation-contracts": "^2.5" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "0.2-dev" + } + }, + "autoload": { + "psr-4": { + "JanuSoftware\\Facebook\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "proprietary" + ], + "authors": [ + { + "name": "Facebook", + "homepage": "https://github.com/facebook/php-graph-sdk/contributors" + }, + { + "name": "Stanislav Janů", + "homepage": "https://janu.software" + } + ], + "description": "Alternative toolkit for Facebook Graph API", + "homepage": "https://github.com/janu-software/facebook-php-sdk", + "keywords": [ + "facebook", + "graph", + "sdk" + ], + "support": { + "issues": "https://github.com/janu-software/facebook-php-sdk/issues", + "source": "https://github.com/janu-software/facebook-php-sdk/tree/v0.2.3" + }, + "funding": [ + { + "url": "https://revolut.me/stanisp8hg", + "type": "custom" + }, + { + "url": "https://www.patreon.com/stanislavjanu", + "type": "patreon" + } + ], + "time": "2024-01-31T14:04:28+00:00" + }, + { + "name": "php-http/discovery", + "version": "1.19.4", + "source": { + "type": "git", + "url": "https://github.com/php-http/discovery.git", + "reference": "0700efda8d7526335132360167315fdab3aeb599" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-http/discovery/zipball/0700efda8d7526335132360167315fdab3aeb599", + "reference": "0700efda8d7526335132360167315fdab3aeb599", + "shasum": "" + }, + "require": { + "composer-plugin-api": "^1.0|^2.0", + "php": "^7.1 || ^8.0" + }, + "conflict": { + "nyholm/psr7": "<1.0", + "zendframework/zend-diactoros": "*" + }, + "provide": { + "php-http/async-client-implementation": "*", + "php-http/client-implementation": "*", + "psr/http-client-implementation": "*", + "psr/http-factory-implementation": "*", + "psr/http-message-implementation": "*" + }, + "require-dev": { + "composer/composer": "^1.0.2|^2.0", + "graham-campbell/phpspec-skip-example-extension": "^5.0", + "php-http/httplug": "^1.0 || ^2.0", + "php-http/message-factory": "^1.0", + "phpspec/phpspec": "^5.1 || ^6.1 || ^7.3", + "sebastian/comparator": "^3.0.5 || ^4.0.8", + "symfony/phpunit-bridge": "^6.4.4 || ^7.0.1" + }, + "type": "composer-plugin", + "extra": { + "class": "Http\\Discovery\\Composer\\Plugin", + "plugin-optional": true + }, + "autoload": { + "psr-4": { + "Http\\Discovery\\": "src/" + }, + "exclude-from-classmap": [ + "src/Composer/Plugin.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Márk Sági-Kazár", + "email": "mark.sagikazar@gmail.com" + } + ], + "description": "Finds and installs PSR-7, PSR-17, PSR-18 and HTTPlug implementations", + "homepage": "http://php-http.org", + "keywords": [ + "adapter", + "client", + "discovery", + "factory", + "http", + "message", + "psr17", + "psr7" + ], + "support": { + "issues": "https://github.com/php-http/discovery/issues", + "source": "https://github.com/php-http/discovery/tree/1.19.4" + }, + "time": "2024-03-29T13:00:05+00:00" + }, + { + "name": "php-http/guzzle7-adapter", + "version": "1.0.0", + "source": { + "type": "git", + "url": "https://github.com/php-http/guzzle7-adapter.git", + "reference": "fb075a71dbfa4847cf0c2938c4e5a9c478ef8b01" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-http/guzzle7-adapter/zipball/fb075a71dbfa4847cf0c2938c4e5a9c478ef8b01", + "reference": "fb075a71dbfa4847cf0c2938c4e5a9c478ef8b01", + "shasum": "" + }, + "require": { + "guzzlehttp/guzzle": "^7.0", + "php": "^7.2 | ^8.0", + "php-http/httplug": "^2.0", + "psr/http-client": "^1.0" + }, + "provide": { + "php-http/async-client-implementation": "1.0", + "php-http/client-implementation": "1.0", + "psr/http-client-implementation": "1.0" + }, + "require-dev": { + "php-http/client-integration-tests": "^3.0", + "phpunit/phpunit": "^8.0|^9.3" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "0.2.x-dev" + } + }, + "autoload": { + "psr-4": { + "Http\\Adapter\\Guzzle7\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Tobias Nyholm", + "email": "tobias.nyholm@gmail.com" + } + ], + "description": "Guzzle 7 HTTP Adapter", + "homepage": "http://httplug.io", + "keywords": [ + "Guzzle", + "http" + ], + "support": { + "issues": "https://github.com/php-http/guzzle7-adapter/issues", + "source": "https://github.com/php-http/guzzle7-adapter/tree/1.0.0" + }, + "time": "2021-03-09T07:35:15+00:00" + }, + { + "name": "php-http/httplug", + "version": "2.4.0", + "source": { + "type": "git", + "url": "https://github.com/php-http/httplug.git", + "reference": "625ad742c360c8ac580fcc647a1541d29e257f67" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-http/httplug/zipball/625ad742c360c8ac580fcc647a1541d29e257f67", + "reference": "625ad742c360c8ac580fcc647a1541d29e257f67", + "shasum": "" + }, + "require": { + "php": "^7.1 || ^8.0", + "php-http/promise": "^1.1", + "psr/http-client": "^1.0", + "psr/http-message": "^1.0 || ^2.0" + }, + "require-dev": { + "friends-of-phpspec/phpspec-code-coverage": "^4.1 || ^5.0 || ^6.0", + "phpspec/phpspec": "^5.1 || ^6.0 || ^7.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "Http\\Client\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Eric GELOEN", + "email": "geloen.eric@gmail.com" + }, + { + "name": "Márk Sági-Kazár", + "email": "mark.sagikazar@gmail.com", + "homepage": "https://sagikazarmark.hu" + } + ], + "description": "HTTPlug, the HTTP client abstraction for PHP", + "homepage": "http://httplug.io", + "keywords": [ + "client", + "http" + ], + "support": { + "issues": "https://github.com/php-http/httplug/issues", + "source": "https://github.com/php-http/httplug/tree/2.4.0" + }, + "time": "2023-04-14T15:10:03+00:00" + }, + { + "name": "php-http/message", + "version": "1.16.1", + "source": { + "type": "git", + "url": "https://github.com/php-http/message.git", + "reference": "5997f3289332c699fa2545c427826272498a2088" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-http/message/zipball/5997f3289332c699fa2545c427826272498a2088", + "reference": "5997f3289332c699fa2545c427826272498a2088", + "shasum": "" + }, + "require": { + "clue/stream-filter": "^1.5", + "php": "^7.2 || ^8.0", + "psr/http-message": "^1.1 || ^2.0" + }, + "provide": { + "php-http/message-factory-implementation": "1.0" + }, + "require-dev": { + "ergebnis/composer-normalize": "^2.6", + "ext-zlib": "*", + "guzzlehttp/psr7": "^1.0 || ^2.0", + "laminas/laminas-diactoros": "^2.0 || ^3.0", + "php-http/message-factory": "^1.0.2", + "phpspec/phpspec": "^5.1 || ^6.3 || ^7.1", + "slim/slim": "^3.0" + }, + "suggest": { + "ext-zlib": "Used with compressor/decompressor streams", + "guzzlehttp/psr7": "Used with Guzzle PSR-7 Factories", + "laminas/laminas-diactoros": "Used with Diactoros Factories", + "slim/slim": "Used with Slim Framework PSR-7 implementation" + }, + "type": "library", + "autoload": { + "files": [ + "src/filters.php" + ], + "psr-4": { + "Http\\Message\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Márk Sági-Kazár", + "email": "mark.sagikazar@gmail.com" + } + ], + "description": "HTTP Message related tools", + "homepage": "http://php-http.org", + "keywords": [ + "http", + "message", + "psr-7" + ], + "support": { + "issues": "https://github.com/php-http/message/issues", + "source": "https://github.com/php-http/message/tree/1.16.1" + }, + "time": "2024-03-07T13:22:09+00:00" + }, + { + "name": "php-http/promise", + "version": "1.3.1", + "source": { + "type": "git", + "url": "https://github.com/php-http/promise.git", + "reference": "fc85b1fba37c169a69a07ef0d5a8075770cc1f83" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-http/promise/zipball/fc85b1fba37c169a69a07ef0d5a8075770cc1f83", + "reference": "fc85b1fba37c169a69a07ef0d5a8075770cc1f83", + "shasum": "" + }, + "require": { + "php": "^7.1 || ^8.0" + }, + "require-dev": { + "friends-of-phpspec/phpspec-code-coverage": "^4.3.2 || ^6.3", + "phpspec/phpspec": "^5.1.2 || ^6.2 || ^7.4" + }, + "type": "library", + "autoload": { + "psr-4": { + "Http\\Promise\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Joel Wurtz", + "email": "joel.wurtz@gmail.com" + }, + { + "name": "Márk Sági-Kazár", + "email": "mark.sagikazar@gmail.com" + } + ], + "description": "Promise used for asynchronous HTTP requests", + "homepage": "http://httplug.io", + "keywords": [ + "promise" + ], + "support": { + "issues": "https://github.com/php-http/promise/issues", + "source": "https://github.com/php-http/promise/tree/1.3.1" + }, + "time": "2024-03-15T13:55:21+00:00" + }, + { + "name": "psr/http-client", + "version": "1.0.3", + "source": { + "type": "git", + "url": "https://github.com/php-fig/http-client.git", + "reference": "bb5906edc1c324c9a05aa0873d40117941e5fa90" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/http-client/zipball/bb5906edc1c324c9a05aa0873d40117941e5fa90", + "reference": "bb5906edc1c324c9a05aa0873d40117941e5fa90", + "shasum": "" + }, + "require": { + "php": "^7.0 || ^8.0", + "psr/http-message": "^1.0 || ^2.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "Psr\\Http\\Client\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "https://www.php-fig.org/" + } + ], + "description": "Common interface for HTTP clients", + "homepage": "https://github.com/php-fig/http-client", + "keywords": [ + "http", + "http-client", + "psr", + "psr-18" + ], + "support": { + "source": "https://github.com/php-fig/http-client" + }, + "time": "2023-09-23T14:17:50+00:00" + }, + { + "name": "psr/http-factory", + "version": "1.1.0", + "source": { + "type": "git", + "url": "https://github.com/php-fig/http-factory.git", + "reference": "2b4765fddfe3b508ac62f829e852b1501d3f6e8a" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/http-factory/zipball/2b4765fddfe3b508ac62f829e852b1501d3f6e8a", + "reference": "2b4765fddfe3b508ac62f829e852b1501d3f6e8a", + "shasum": "" + }, + "require": { + "php": ">=7.1", + "psr/http-message": "^1.0 || ^2.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "Psr\\Http\\Message\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "https://www.php-fig.org/" + } + ], + "description": "PSR-17: Common interfaces for PSR-7 HTTP message factories", + "keywords": [ + "factory", + "http", + "message", + "psr", + "psr-17", + "psr-7", + "request", + "response" + ], + "support": { + "source": "https://github.com/php-fig/http-factory" + }, + "time": "2024-04-15T12:06:14+00:00" + }, + { + "name": "psr/http-message", + "version": "1.1", + "source": { + "type": "git", + "url": "https://github.com/php-fig/http-message.git", + "reference": "cb6ce4845ce34a8ad9e68117c10ee90a29919eba" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/http-message/zipball/cb6ce4845ce34a8ad9e68117c10ee90a29919eba", + "reference": "cb6ce4845ce34a8ad9e68117c10ee90a29919eba", + "shasum": "" + }, + "require": { + "php": "^7.2 || ^8.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.1.x-dev" + } + }, + "autoload": { + "psr-4": { + "Psr\\Http\\Message\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "http://www.php-fig.org/" + } + ], + "description": "Common interface for HTTP messages", + "homepage": "https://github.com/php-fig/http-message", + "keywords": [ + "http", + "http-message", + "psr", + "psr-7", + "request", + "response" + ], + "support": { + "source": "https://github.com/php-fig/http-message/tree/1.1" + }, + "time": "2023-04-04T09:50:52+00:00" + }, + { + "name": "ralouphie/getallheaders", + "version": "3.0.3", + "source": { + "type": "git", + "url": "https://github.com/ralouphie/getallheaders.git", + "reference": "120b605dfeb996808c31b6477290a714d356e822" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/ralouphie/getallheaders/zipball/120b605dfeb996808c31b6477290a714d356e822", + "reference": "120b605dfeb996808c31b6477290a714d356e822", + "shasum": "" + }, + "require": { + "php": ">=5.6" + }, + "require-dev": { + "php-coveralls/php-coveralls": "^2.1", + "phpunit/phpunit": "^5 || ^6.5" + }, + "type": "library", + "autoload": { + "files": [ + "src/getallheaders.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Ralph Khattar", + "email": "ralph.khattar@gmail.com" + } + ], + "description": "A polyfill for getallheaders.", + "support": { + "issues": "https://github.com/ralouphie/getallheaders/issues", + "source": "https://github.com/ralouphie/getallheaders/tree/develop" + }, + "time": "2019-03-08T08:55:37+00:00" + }, + { + "name": "symfony/deprecation-contracts", + "version": "v3.5.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/deprecation-contracts.git", + "reference": "0e0d29ce1f20deffb4ab1b016a7257c4f1e789a1" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/deprecation-contracts/zipball/0e0d29ce1f20deffb4ab1b016a7257c4f1e789a1", + "reference": "0e0d29ce1f20deffb4ab1b016a7257c4f1e789a1", + "shasum": "" + }, + "require": { + "php": ">=8.1" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "3.5-dev" + }, + "thanks": { + "name": "symfony/contracts", + "url": "https://github.com/symfony/contracts" + } + }, + "autoload": { + "files": [ + "function.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "A generic function and convention to trigger deprecation notices", + "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/deprecation-contracts/tree/v3.5.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2024-04-18T09:32:20+00:00" + }, + { + "name": "thecodingmachine/safe", + "version": "v2.5.0", + "source": { + "type": "git", + "url": "https://github.com/thecodingmachine/safe.git", + "reference": "3115ecd6b4391662b4931daac4eba6b07a2ac1f0" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/thecodingmachine/safe/zipball/3115ecd6b4391662b4931daac4eba6b07a2ac1f0", + "reference": "3115ecd6b4391662b4931daac4eba6b07a2ac1f0", + "shasum": "" + }, + "require": { + "php": "^8.0" + }, + "require-dev": { + "phpstan/phpstan": "^1.5", + "phpunit/phpunit": "^9.5", + "squizlabs/php_codesniffer": "^3.2", + "thecodingmachine/phpstan-strict-rules": "^1.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.2.x-dev" + } + }, + "autoload": { + "files": [ + "deprecated/apc.php", + "deprecated/array.php", + "deprecated/datetime.php", + "deprecated/libevent.php", + "deprecated/misc.php", + "deprecated/password.php", + "deprecated/mssql.php", + "deprecated/stats.php", + "deprecated/strings.php", + "lib/special_cases.php", + "deprecated/mysqli.php", + "generated/apache.php", + "generated/apcu.php", + "generated/array.php", + "generated/bzip2.php", + "generated/calendar.php", + "generated/classobj.php", + "generated/com.php", + "generated/cubrid.php", + "generated/curl.php", + "generated/datetime.php", + "generated/dir.php", + "generated/eio.php", + "generated/errorfunc.php", + "generated/exec.php", + "generated/fileinfo.php", + "generated/filesystem.php", + "generated/filter.php", + "generated/fpm.php", + "generated/ftp.php", + "generated/funchand.php", + "generated/gettext.php", + "generated/gmp.php", + "generated/gnupg.php", + "generated/hash.php", + "generated/ibase.php", + "generated/ibmDb2.php", + "generated/iconv.php", + "generated/image.php", + "generated/imap.php", + "generated/info.php", + "generated/inotify.php", + "generated/json.php", + "generated/ldap.php", + "generated/libxml.php", + "generated/lzf.php", + "generated/mailparse.php", + "generated/mbstring.php", + "generated/misc.php", + "generated/mysql.php", + "generated/network.php", + "generated/oci8.php", + "generated/opcache.php", + "generated/openssl.php", + "generated/outcontrol.php", + "generated/pcntl.php", + "generated/pcre.php", + "generated/pgsql.php", + "generated/posix.php", + "generated/ps.php", + "generated/pspell.php", + "generated/readline.php", + "generated/rpminfo.php", + "generated/rrd.php", + "generated/sem.php", + "generated/session.php", + "generated/shmop.php", + "generated/sockets.php", + "generated/sodium.php", + "generated/solr.php", + "generated/spl.php", + "generated/sqlsrv.php", + "generated/ssdeep.php", + "generated/ssh2.php", + "generated/stream.php", + "generated/strings.php", + "generated/swoole.php", + "generated/uodbc.php", + "generated/uopz.php", + "generated/url.php", + "generated/var.php", + "generated/xdiff.php", + "generated/xml.php", + "generated/xmlrpc.php", + "generated/yaml.php", + "generated/yaz.php", + "generated/zip.php", + "generated/zlib.php" + ], + "classmap": [ + "lib/DateTime.php", + "lib/DateTimeImmutable.php", + "lib/Exceptions/", + "deprecated/Exceptions/", + "generated/Exceptions/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "description": "PHP core functions that throw exceptions instead of returning FALSE on error", + "support": { + "issues": "https://github.com/thecodingmachine/safe/issues", + "source": "https://github.com/thecodingmachine/safe/tree/v2.5.0" + }, + "time": "2023-04-05T11:54:14+00:00" + } + ], + "packages-dev": [], + "aliases": [], + "minimum-stability": "stable", + "stability-flags": [], + "prefer-stable": false, + "prefer-lowest": false, + "platform": [], + "platform-dev": [], + "plugin-api-version": "2.6.0" +} diff --git a/config.php b/config.php new file mode 100644 index 0000000..c8051ba --- /dev/null +++ b/config.php @@ -0,0 +1,37 @@ + '718087176708750', //(주)케어랩스 //'318448081868728'; // 열혈패밀리_ver3 + 'app_secret' => '81b9a694a853428e88f7c6f144efc080', //'881a2a6c6edcc9a5291e829278cb91e2'; + 'access_token' => 'EAAKNGLMV4o4BO6fymBdgU0MuizER168JBEMJCC3Dr1aFXo1th14FVFrnkkC03mwdDPGd7AVnOxquF3udW9aiwKTCZAqwUqlhWGZCJg0ZAnYLnIWQ67xKg01P0nMglSaGoKGQx193JfirYNZCUnjOB0xJ8bbgeOYAi0w8KODF3Dd0fFpK1KzKwxHBpv9TiW3dZANBWZArT1OiPLZCJ1QoFTsSuhSJQZDZD', + 'longLivedAccessToken' => 'EAAKNGLMV4o4BO8ZAs48R6lDQ9fcZCw91DmvJtEIZBUyZAzTCGAYsSaEA9oxQPLtDLu7ZBdayalAZCelVleSTavjdRpAziJuB1D2TzFBEMTmtDWZCD1UkepAzeISFGtV8AJezUOXPM6wkAdweTHL93CRCguGPHaKY7nOKJxP1vKkCqoRO9StEDEvzxCJ1vXuzjQg', + 'business_id_list' => [ + '889300682548023' //케어랩스8 + ,'213123902836946' //케어랩스7 + ,'2859468974281473' //케어랩스5 + ,'316991668497111' //열혈패밀리 + ] + ]; +} else if(getenv('MY_SERVER_NAME') == 'resta') { + $config = [ + 'app_id' => '203750579450030', //(주)케어랩스 //'318448081868728'; // 열혈패밀리_ver3 + 'app_secret' => '274a4d9851d2a551f663799d9257ba3f', //'881a2a6c6edcc9a5291e829278cb91e2'; + 'access_token' => 'EAAC5T2DpMK4BO8IhTBJHsZAD37x3RTZAxXpUxeuJsNzoJpCNNKas6XTcoZAD1ZBZCKUZAtGEfUpx3udHJmEcbZCU04oUefYeOo1CCmT6kqgMEU0Nn3LFPauLcz6ZA7OpGH9mW52DWoblMdLHBIuygSxTm6f3SyzM6wL2erm4KsrsZAQZBMGvnYHdZAifZCrsr5YjuEQDEYfK6gZABo8WgKj9hGjCS7lZC5pb6XSP88giAZD', + 'longLivedAccessToken' => 'EAAC5T2DpMK4BOw7lZAAiwV09ZCFjsvgjdh2rZBmmLsPqZBVbigKFQuYJvw1hWZAeG36qNByTiQQXlMTEycZCIwnkbxb83w0YLXnLkb4gAawjOEDfZCDZBux7Loumpv0ZCFUuQc1vZCV3U1hzHYaptCntY0f7xd71H4OlrBsJUavKeYkt5aIYKcamck1zXEBI5ZCE7x3', + 'business_id_list' => [ + '334206136772827', + '1077747392407033' + ] + ]; +} else if(getenv('MY_SERVER_NAME') == 'savemarketing') { + $config = [ + 'app_id' => '440585915610883', + 'app_secret' => 'dbb559cc53da175156e8e2b2e06725f0', //'881a2a6c6edcc9a5291e829278cb91e2'; + 'access_token' => 'EAAGQtebZBNwMBOxK04X3YfqeTgLVZCu1w5ZBLPf39wj8py2tGxTuTHRytVwiFCvEoZCDxz1bUDrKj80AddblUQZBBiK32UddpZBf2ucYyoxcEeqbrk0CKSvKAsLKRBv5fHufBhhdZBtkFyr9YPS0RM89uaoXt1DQpDtLNwjihq34ObZCOyetj6AseXfI3qvptgH6wNGnKekK5KwOqfnJUYlId2YXcwZDZD', + 'longLivedAccessToken' => 'EAAGQtebZBNwMBO5AHdytJjAgSPZBaN5yZB6HKZB8ZC6KTOrzEUVaXBDY1CT90TJ6IjOLqFZAEwxGUZAdu4yZAzc1EIUCSZBv3w2natkiRNRtombZBaT2o2aH4BGc14fLptEimnNh5995BcfJWwfxlwF1jw9yy6IXeCK9nGiEg99z7za5x2vovZCyumSXnl5UPvlFtxo', + 'business_id_list' => [ + '1677888252282772', + '766224524981797' + ] + ]; +} \ No newline at end of file