GdtCostHourLogic.php 8.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239
  1. <?php
  2. namespace app\v1\logic\tool\advert;
  3. use app\v1\logic\advert\AgentSiteLogic;
  4. use GuzzleHttp\Client;
  5. use support\think\Db;
  6. class GdtCostHourLogic
  7. {
  8. protected string $dateTable = "media_cost";
  9. protected string $hourTable = "media_cost_hour";
  10. protected string $date;
  11. protected array $advertiserIds=[];
  12. protected array $siteMap=[];
  13. public function run($params=[])
  14. {
  15. // 重跑用,传数组
  16. if(!empty($params['date'])){
  17. $sDate = is_array($params['date']) ? $params['date'][0] : $params['date'];
  18. $eDate = !empty($params['date'][1]) ? $params['date'][1] : $params['date'][0];
  19. // 检查日期格式是否正确
  20. if(!isValidDate($sDate) || !isValidDate($eDate)){
  21. return json_encode(["status"=>"error", "msg"=>"日期格式不正确"], 256);
  22. }
  23. }else{
  24. $sDate = date('Y-m-d');
  25. $eDate = date('Y-m-d');
  26. }
  27. // 重跑用,传数组
  28. if(!empty($params['advertiser_ids'])){
  29. $this->advertiserIds = $params['advertiser_ids'];
  30. }
  31. for ($date = $sDate; $date <= $eDate; $date = date('Y-m-d', strtotime($date . '+1 day'))){
  32. $this->date = $date;
  33. try {
  34. $this->initStart();
  35. }catch (\Exception $e){
  36. return json_encode(["status"=>"error", "msg"=>$e->getMessage()], 256);
  37. }
  38. }
  39. $this->reRun();
  40. return json_encode(["status"=>"success", "msg"=>""], 256);
  41. }
  42. // 重跑
  43. protected function reRun(): void
  44. {
  45. if (date('H') == 8 && date('i') < 20) {
  46. $this->date = date('Y-m-d', strtotime("-1 days"));
  47. $this->initStart();
  48. }
  49. }
  50. protected function initStart(): void
  51. {
  52. $tokenMap = $this->getTokenMap();
  53. $accountList = $this->getAccountList();
  54. $this->siteMap = (new AgentSiteLogic())->getSiteAuth();
  55. // 循环执行
  56. foreach ($accountList as $account)
  57. {
  58. $accessToken = $tokenMap[$account['pmid']] ?? "";
  59. if(!$accessToken) continue;
  60. // 获取消耗
  61. $dataList = $this->getGdtCost($account['advertiser_id'], $accessToken);
  62. // 整理数据入库
  63. $this->organizeDataList($account, $dataList);
  64. }
  65. }
  66. // 获取媒体消耗
  67. protected function getGdtCost($advertiser_id, $access_token): array
  68. {
  69. $page = 1;
  70. $data = [];
  71. do {
  72. $nonce = md5(time().rand(00000, 99999));
  73. $url = 'https://api.e.qq.com/v3.0/hourly_reports/get?access_token='.$access_token.'&timestamp='.time().'&nonce='.$nonce;
  74. $request_data = [
  75. 'account_id' => $advertiser_id,
  76. 'level' => 'REPORT_LEVEL_ADGROUP',
  77. 'date_range' => json_encode(['start_date' => $this->date, 'end_date' => $this->date]),
  78. 'group_by' => json_encode(['hour', 'adgroup_id']),
  79. 'fields' => json_encode(['hour', 'adgroup_id', 'adgroup_name', 'view_count', 'valid_click_count', 'cost', 'activated_count']),
  80. 'page' => $page,
  81. 'page_size' => 100,
  82. ];
  83. $url = $url."&".http_build_query($request_data);
  84. $httpClient = new Client(['timeout' => 10]);
  85. $res = $httpClient->request('GET', $url);
  86. $result = json_decode($res->getBody(), true);
  87. if (empty($result['data']['list'])) {
  88. break;
  89. }
  90. $data = array_merge($data, $result['data']['list']);
  91. $totalPage = $result['data']['page_info']['total_page'] ?? 1;
  92. $page++;
  93. } while ($page <= $totalPage);
  94. return $data;
  95. }
  96. // 整理入库数据列表
  97. protected function organizeDataList($account, $dataList): void
  98. {
  99. if(!$dataList) return;
  100. $db = Db::connect('db_advert');
  101. // 返点率
  102. $fandianRate = ($account['son_fandian']>1) ? (1/$account['son_fandian']) : $account['son_fandian'];
  103. $adData = [];
  104. foreach ($dataList as $val) {
  105. $ad_id = $val['adgroup_id'];
  106. $ad_name = $val['adgroup_name'];
  107. $cost = $val['cost']/100;
  108. $show = $val['view_count'];
  109. $click = $val['valid_click_count'];
  110. $convert = $val['activated_count'];
  111. // Todo 从广告名称中拆分归因数据
  112. preg_match("/([\d]*)_([\d]*)_([\d]*)/", $ad_name, $matchs);
  113. $game_id = $matchs[1] ?? 0;
  114. $agent_id = $matchs[2] ?? 0;
  115. $site_id = $matchs[3] ?? 0;
  116. if(!$game_id || empty($this->siteMap[$site_id])) continue;
  117. $where = [
  118. 'ad_id' => $ad_id,
  119. 'game_id' => $game_id,
  120. 'agent_id'=> $agent_id,
  121. 'site_id' => $site_id,
  122. 'tdate' => $this->date,
  123. 'thour' => $val['hour'],
  124. ];
  125. $data = [
  126. 'advertiser_id' => $account['advertiser_id'],
  127. 'ad_show' => $show,
  128. 'ad_click' => $click,
  129. 'ad_convert' => $convert,
  130. 'ori_money' => $cost,
  131. 'money' => $cost * $fandianRate,
  132. 'media_id' => $this->siteMap[$site_id]['media_id'],
  133. 'auth_id' => $this->siteMap[$site_id]['auth_id'],
  134. ];
  135. $hourId= $db->table($this->hourTable)->where($where)->value("id");
  136. if($hourId) {
  137. $data['id'] = $hourId;
  138. }
  139. // 保存小时数据
  140. $db->table($this->hourTable)->save(array_merge($data, $where));
  141. // 计算天的数据
  142. $adKey = $game_id . "_" . $site_id . "_" . $ad_id;
  143. $adData[$adKey]['game_id'] = $game_id;
  144. $adData[$adKey]['agent_id'] = $agent_id;
  145. $adData[$adKey]['site_id'] = $site_id;
  146. $adData[$adKey]['ad_id'] = $ad_id;
  147. $adData[$adKey]['ad_show'] = !empty($adData[$adKey]['ad_show']) ? $adData[$adKey]['ad_show']+$show : $show;
  148. $adData[$adKey]['ad_click'] = !empty($adData[$adKey]['ad_click']) ? $adData[$adKey]['ad_click']+$click : $click;
  149. $adData[$adKey]['ad_convert'] = !empty($adData[$adKey]['ad_convert']) ? $adData[$adKey]['ad_convert']+$convert : $convert;
  150. $adData[$adKey]['cost'] = !empty($adData[$adKey]['cost']) ? $adData[$adKey]['cost']+$cost : $cost;
  151. }
  152. foreach($adData as $value){
  153. $where = [
  154. 'ad_id' => $value['ad_id'],
  155. 'game_id' => $value['game_id'],
  156. 'agent_id'=> $value['agent_id'],
  157. 'site_id' => $value['site_id'],
  158. 'tdate' => $this->date,
  159. ];
  160. $data = [
  161. 'advertiser_id' => $account['advertiser_id'],
  162. 'ad_show' => $value['ad_show'],
  163. 'ad_click' => $value['ad_click'],
  164. 'ad_convert'=> $value['ad_convert'],
  165. 'ori_money' => $value['cost'],
  166. 'money' => $value['cost']*$fandianRate,
  167. 'media_id' => $this->siteMap[$site_id]['media_id'],
  168. 'auth_id' => $this->siteMap[$site_id]['auth_id'],
  169. ];
  170. $dateId= $db->table($this->dateTable)->where($where)->value("id");
  171. if($dateId) {
  172. $data['id'] = $dateId;
  173. }
  174. // 保存日数据
  175. $db->table($this->dateTable)->save(array_merge($data, $where));
  176. }
  177. }
  178. // 获取需要拉取消耗的媒体账户
  179. protected function getAccountList(): array
  180. {
  181. $table = "ad_gdt_account_list";
  182. $where = [
  183. "status" => 1
  184. ];
  185. if($this->advertiserIds){
  186. $where['advertiser_id'] = $this->advertiserIds;
  187. }
  188. return Db::connect('db_advert')
  189. ->table($table)
  190. ->where($where)
  191. ->column("pmid, advertiser_id, advertiser_name, son_fandian");
  192. }
  193. protected function getTokenMap(): array
  194. {
  195. $table = "ad_gdt_account";
  196. $where = [
  197. "status" => 1
  198. ];
  199. return Db::connect('db_advert')->table($table)->where($where)->column("access_token", "id");
  200. }
  201. }