No Description

SupplementOrderService.php 21KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436
  1. <?php
  2. namespace App\Services\Data;
  3. use App\Models\JuxingAdAccount;
  4. use App\Models\JxStarVideoFlowOrderList;
  5. use App\Services\KsOpenApiService;
  6. use App\Support\EmailQueue;
  7. use App\Support\Log;
  8. use App\Support\RedisModel;
  9. use Illuminate\Support\Facades\Auth;
  10. use Illuminate\Support\Facades\Redis;
  11. use kwaiSDK\JuXing;
  12. class SupplementOrderService
  13. {
  14. public static function supplementOrderStop($supplementOrderList, $supplementOrderType)
  15. {
  16. try {
  17. # 处理订单列表信息(按广告主账户分组)
  18. $request = [];
  19. $supplementOrderList = json_decode($supplementOrderList, 1);
  20. foreach ($supplementOrderList as $supplementOrder) {
  21. $advertiserId = $supplementOrder['advertiser_id'] ?? '';
  22. $supplementOrderId = $supplementOrder['supplement_order_id'] ?? '';
  23. $supplementOrderId = intval($supplementOrderId);
  24. if (empty($advertiserId) || empty($supplementOrderId)) {
  25. Log::error('请求数据格式不合法', [$supplementOrderList], 'supplementOrder');
  26. return ['请求失败', 1102];
  27. }
  28. $request[$advertiserId][] = $supplementOrderId;
  29. }
  30. # 返回数组定义
  31. $result = [
  32. 'stat' => ['success' => 0, 'fail' => 0, 'total' => count($supplementOrderList)],
  33. 'data' => []
  34. ];
  35. # 对分组后的订单分别处理
  36. foreach ($request as $advertiserId => $supplementOrderIdList) {
  37. // 查询选择订单中当状态为推广中的订单
  38. $activeSupplementOrderIdList = self::getActiveSupplementOrderIdList($advertiserId, $supplementOrderIdList);
  39. # 避免一次请求订单数太多导致失败,将订单分批次处理
  40. $supplementOrderIdArr = array_chunk($activeSupplementOrderIdList, 100);
  41. $successSupplementOrderIdList = [];
  42. foreach ($supplementOrderIdArr as $newSupplementOrderIdList) {
  43. $data = self::supplementOrderStopRequest($advertiserId, $supplementOrderType, $newSupplementOrderIdList);
  44. Log::info('助推订单批量结束请求统计结果', ['supplement_order' => $newSupplementOrderIdList, 'res' => $data], 'supplementOrder');
  45. $result['stat']['fail'] += $data['fail']['num'];
  46. $result['stat']['success'] = $result['stat']['total'] - $result['stat']['fail'];
  47. $successSupplementOrderIdList = array_merge($successSupplementOrderIdList, $data['success']['list']);
  48. if ($data['fail']['num'] + $data['success']['num'] != count($newSupplementOrderIdList)) {
  49. EmailQueue::rPush('助推订单停投处理结果异常 - 预处理订单数与返回订单总数不符', json_encode(['supplement_order' => $newSupplementOrderIdList, 'res' => $data, 256])
  50. , ['song.shen@kuxuan-inc.com'], '聚星系统');
  51. }
  52. }
  53. if ($result['stat']['success'] > 0) {
  54. // 请求成功的直接修改订单状态为推广完成
  55. JxStarVideoFlowOrderList::updateData($advertiserId, $successSupplementOrderIdList, ['status' => 2]);
  56. // 将广告主账户ID放入更新队列中
  57. self::syncFlowOrder($advertiserId);
  58. }
  59. }
  60. Log::info('助推订单结束响应结果', ['supplementOrderList' => $supplementOrderList, 'supplementOrderType' => $supplementOrderType, 'result' => $result], 'supplementOrder');
  61. return [$result, 0];
  62. } catch (\Exception $exception) {
  63. EmailQueue::rPush('批量结束助推订单程序异常', $exception->getFile() . '(' . $exception->getLine() . ') : ' . $exception->getMessage(), ['song.shen@kuxuan-inc.com'], '聚星系统');
  64. Log::error('批量结束助推订单程序异常', ['supplement_order_list' => $supplementOrderList, 'file' => $exception->getFile(), 'line' => $exception->getLine()
  65. , 'message' => $exception->getMessage(), 'trace' => $exception->getTraceAsString()], 'supplementOrderError');
  66. }
  67. }
  68. /**
  69. * 批量修改助推订单出价
  70. * */
  71. public static function supplementOrderUpdateUnitPriceBatch($supplementOrderList, $unitPrice)
  72. {
  73. try {
  74. $supplementOrderList = json_decode($supplementOrderList, true);
  75. # 定义返回数据结构
  76. $result = [
  77. 'stat' => ['success' => 0, 'fail' => 0, 'total' => count($supplementOrderList)],
  78. 'data' => []
  79. ];
  80. $updateTotal = 0;
  81. foreach ($supplementOrderList as $supplementOrder) {
  82. $updateTotal++;
  83. $advertiserId = $supplementOrder['advertiser_id'] ?? '';
  84. $supplementOrderId = $supplementOrder['supplement_order_id'] ?? '';
  85. if (empty($advertiserId) || empty($supplementOrderId)) {
  86. Log::error('请求数据格式不合法', [$supplementOrderList], 'SupplementOrderUpdateUnitPriceBatch');
  87. return [[], 1102];
  88. }
  89. // 修改出价
  90. $response = KsOpenApiService::supplementOrderUpdatePrice($advertiserId, intval($supplementOrderId), $unitPrice);
  91. if($response===false || $response['code']) { // 修改失败
  92. $result['stat']['fail']++;
  93. array_push($result['data'], $supplementOrderId);
  94. } else { // 修改成功
  95. self::syncFlowOrder($advertiserId);
  96. $result['stat']['success']++;
  97. }
  98. }
  99. }catch (\Exception $e) {
  100. EmailQueue::rPush('批量结束助推订单流程出现异常', $e->getTraceAsString(), ['xiaohua.hou@kuxuan-inc.com'], '聚星系统');
  101. Log::error('批量结束助推订单流程出现异常', [
  102. 'supplement_order_list' => $supplementOrderList, 'line' => $e->getLine(), 'msg' => $e->getMessage()
  103. ], 'SupplementOrderUpdateUnitPriceBatch');
  104. return [[], 1090];
  105. }
  106. return [$result, 0];
  107. }
  108. /**
  109. * 批量修改助推订单预算
  110. * */
  111. public static function supplementOrderUpgradeAmountBatch($supplementOrderList, $amount, $payMethod)
  112. {
  113. try {
  114. $supplementOrderList = json_decode($supplementOrderList, true);
  115. # 定义返回数据结构
  116. $result = [
  117. 'stat' => ['success' => 0, 'fail' => 0, 'total' => count($supplementOrderList)],
  118. 'data' => []
  119. ];
  120. $updateTotal = 0;
  121. foreach ($supplementOrderList as $supplementOrder) {
  122. $updateTotal++;
  123. $advertiserId = $supplementOrder['advertiser_id'] ?? '';
  124. $supplementOrderId = $supplementOrder['supplement_order_id'] ?? '';
  125. if (empty($advertiserId) || empty($supplementOrderId)) {
  126. Log::error('请求数据格式不合法', [$supplementOrderList], 'SupplementOrderUpgradeAmountBatch');
  127. return [[], 1102];
  128. }
  129. // 升单
  130. $response = KsOpenApiService::supplementOrderAmountUpgrade($advertiserId, intval($supplementOrderId), $amount, $payMethod);
  131. if($response===false || $response['code']) { // 修改失败
  132. $result['stat']['fail']++;
  133. array_push($result['data'], $supplementOrderId);
  134. } else { // 修改成功
  135. $result['stat']['success']++;
  136. self::syncFlowOrder($advertiserId);
  137. }
  138. }
  139. }catch (\Exception $e) {
  140. EmailQueue::rPush('批量升单流程出现异常', $e->getTraceAsString(), ['xiaohua.hou@kuxuan-inc.com'], '聚星系统');
  141. Log::error('批量升单流程出现异常', [
  142. 'supplement_order_list' => $supplementOrderList, 'line' => $e->getLine(), 'msg' => $e->getMessage(),
  143. 'amount' => $amount, 'pay_method' => $payMethod
  144. ], 'SupplementOrderUpgradeAmountBatch');
  145. return [[], 1091];
  146. }
  147. return [$result, 0];
  148. }
  149. /**
  150. * 批量修改助推订单推广时间
  151. * */
  152. public static function supplementOrderUpdatePromotionEndTimeBatch($supplementOrderList, $promotionEndTime)
  153. {
  154. try {
  155. $supplementOrderList = json_decode($supplementOrderList, true);
  156. # 定义返回数据结构
  157. $result = [
  158. 'stat' => ['success' => 0, 'fail' => 0, 'total' => count($supplementOrderList)],
  159. 'data' => []
  160. ];
  161. $updateTotal = 0;
  162. foreach ($supplementOrderList as $supplementOrder) {
  163. $updateTotal++;
  164. $advertiserId = $supplementOrder['advertiser_id'] ?? '';
  165. $supplementOrderId = $supplementOrder['supplement_order_id'] ?? '';
  166. if (empty($advertiserId) || empty($supplementOrderId)) {
  167. Log::error('请求数据格式不合法', [$supplementOrderList], 'SupplementOrderUpgradeAmountBatch');
  168. return [[], 1102];
  169. }
  170. // 修改出价
  171. $response = KsOpenApiService::supplementOrderUpdatePromotionEndTime($advertiserId, intval($supplementOrderId), $promotionEndTime);
  172. if($response===false || $response['code']) { // 修改失败
  173. $result['stat']['fail']++;
  174. array_push($result['data'], $supplementOrderId);
  175. } else { // 修改成功
  176. self::syncFlowOrder($advertiserId);
  177. $result['stat']['success']++;
  178. }
  179. }
  180. }catch (\Exception $e) {
  181. EmailQueue::rPush('批量修改推广时间流程出现异常', $e->getTraceAsString(), ['xiaohua.hou@kuxuan-inc.com'], '聚星系统');
  182. Log::error('批量修改推广时间流程出现异常', [
  183. 'supplement_order_list' => $supplementOrderList, 'line' => $e->getLine(), 'msg' => $e->getMessage(),
  184. 'end_time' => $promotionEndTime
  185. ], 'SupplementOrderUpdatePromotionEndTimeBatch');
  186. return [[], 1092];
  187. }
  188. return [$result, 0];
  189. }
  190. public static function syncFlowOrder($advertiserId) {
  191. $stTime = date('Y-m-d', strtotime('-90 days'));
  192. $enTime = date('Y-m-d');
  193. # 获取时间段数组
  194. $timeRangeArr = getTimeRangeArr($stTime, $enTime);
  195. foreach ($timeRangeArr as $timeRange) {
  196. # 5分钟内不重复更新
  197. $redisKey = 'juxingFlowStarVideoSyncAdvidListLck-'.$advertiserId;
  198. $redisValue = RedisModel::get($redisKey);
  199. if(!empty($redisValue)) {
  200. continue;
  201. }
  202. # 插入队列
  203. $advertiserItem = [
  204. 'advertiserId' => $advertiserId,
  205. 'timeRange' => $timeRange
  206. ];
  207. RedisModel::lPush(JuxingAdAccount::JUXING_FLOW_STAR_VIDEO_SYNC_ADVID_LIST, json_encode($advertiserItem));
  208. # 插入队列
  209. RedisModel::lPush(JuxingAdAccount::JUXING_FLOW_QTASK_VIDEO_SYNC_ADVID_LIST, json_encode($advertiserItem));
  210. RedisModel::set($redisKey, 1);
  211. RedisModel::expire($redisValue, 300);
  212. }
  213. }
  214. public static function supplementOrderStopRequest($advertiserId, $supplementOrderType, $supplementOrderIdList, $retry=0) {
  215. $accessToken = JuxingAdAccount::getAccessToken($advertiserId);
  216. $juxing = new JuXing($accessToken);
  217. $param = [
  218. 'advertiser_id' => intval($advertiserId),
  219. 'supplement_order_type' => intval($supplementOrderType),
  220. 'supplement_order_ids' => $supplementOrderIdList
  221. ];
  222. $rst = $juxing->supplementOrderV2()->stop($param);
  223. if($rst === false && $retry < 3) {
  224. $retry++;
  225. return self::supplementOrderStopRequest($advertiserId, $supplementOrderType, $supplementOrderIdList, $retry);
  226. }
  227. Log::info('助推订单停投', ['param' => $param, 'ret' => $rst, 'operator_id' => Auth::id()], 'supplementOrder');
  228. $data = [
  229. 'success' => ['list' => [], 'num' => 0], 'fail' => ['list' => [], 'num' => 0], 'total' => count($supplementOrderIdList)
  230. ];
  231. if(isset($rst['code']) && $rst['code'] == 0) {# 请求成功
  232. $supplementOrder = $rst['data']['stop_supplement_orders'] ?? [];
  233. foreach($supplementOrder as $order) {
  234. if(isset($order['result']) && $order['result']) {
  235. $data['success']['list'][] = $order['supplement_order_id'];
  236. $data['success']['num']++;
  237. } else {
  238. $data['fail']['list'][] = $order['supplement_order_id'];
  239. $data['fail']['num']++;
  240. }
  241. }
  242. } else {
  243. if($retry < 3) {
  244. $retry++;
  245. return self::supplementOrderStopRequest($advertiserId, $supplementOrderType, $supplementOrderIdList, $retry);
  246. }
  247. $data['fail']['list'] = $supplementOrderIdList;
  248. $data['fail']['num'] = count($supplementOrderIdList);
  249. EmailQueue::rPush('助推订单停投返回异常', json_encode([
  250. 'advertiser_id' => $advertiserId,
  251. 'supplement_order_id_list' => $supplementOrderIdList,
  252. 'supplement_order_type' => $supplementOrderType,
  253. 'response' => $rst
  254. ], 256), ['song.shen@kuxuan-inc.com'], '聚星系统');
  255. }
  256. return $data;
  257. }
  258. public static function supplementOrderUpdatePromotionEndTime($advertiserId, $supplementOrderId, $promotionEndTime, $retry = 0) {
  259. $accessToken = JuxingAdAccount::getAccessToken($advertiserId);
  260. $juxing = new JuXing($accessToken);
  261. $realPromotionEndTime = date("Y-m-d H:i:s", strtotime($promotionEndTime)).'.'.rand(100, 999);
  262. $param = [
  263. 'advertiser_id' => intval($advertiserId),
  264. 'supplement_order_id' => intval($supplementOrderId),
  265. 'promotion_end_time' => $realPromotionEndTime
  266. ];
  267. $rst = $juxing->supplementOrderV2()->promotionEndtimeUpdate($param);
  268. if($rst === false && $retry < 3) {
  269. $retry++;
  270. return self::supplementOrderUpdatePromotionEndTime($advertiserId, $supplementOrderId, $promotionEndTime, $retry);
  271. }
  272. Log::info('助推订单修改推广结束时间', ['param' => $param, 'ret' => $rst, 'operator_id' => Auth::id()], 'supplementOrder');
  273. if(isset($rst['code']) && $rst['code'] == 0) {# 请求成功
  274. // 将广告主账户ID放入更新队列中或者直接更新系统数据
  275. self::syncFlowOrder($advertiserId);
  276. return ['', 0, null];
  277. } else {
  278. if($retry < 3) {
  279. $retry++;
  280. return self::supplementOrderUpdatePromotionEndTime($advertiserId, $supplementOrderId, $promotionEndTime, $retry);
  281. }
  282. EmailQueue::rPush('助推订单修改推广结束时间返回异常', json_encode([
  283. 'advertiser_id' => $advertiserId,
  284. 'supplement_order_id' => $supplementOrderId,
  285. 'promotion_end_time' => $realPromotionEndTime,
  286. 'response' => $rst
  287. ], 256), ['song.shen@kuxuan-inc.com'], '聚星系统');
  288. return ['请求失败', 501, $rst['message']];
  289. }
  290. }
  291. public static function supplementOrderUpgradeAmount($advertiserId, $supplementOrderId, $payMethod, $amount, $retry = 0) {
  292. $accessToken = JuxingAdAccount::getAccessToken($advertiserId);
  293. $juxing = new JuXing($accessToken);
  294. $param = [
  295. 'advertiser_id' => intval($advertiserId),
  296. 'supplement_order_id' => intval($supplementOrderId),
  297. 'pay_method' => $payMethod,
  298. 'increased_amount' => intval($amount * 1000), // 单位厘
  299. ];
  300. $rst = $juxing->supplementOrderV2()->amountUpgrade($param);
  301. if($rst === false && $retry < 3) {
  302. $retry++;
  303. return self::supplementOrderUpgradeAmount($advertiserId, $supplementOrderId, $payMethod, $amount, $retry);
  304. }
  305. Log::info('助推订单升单', ['param' => $param, 'ret' => $rst, 'operator_id' => Auth::id()], 'supplementOrder');
  306. if(isset($rst['code']) && $rst['code'] == 0) {# 请求成功
  307. // 将广告主账户ID放入更新队列中
  308. self::syncFlowOrder($advertiserId);
  309. return ['', 0, null];
  310. } else {
  311. if($retry < 3) {
  312. $retry++;
  313. return self::supplementOrderUpgradeAmount($advertiserId, $supplementOrderId, $payMethod, $amount, $retry);
  314. }
  315. EmailQueue::rPush('助推订单升单请求失败', json_encode([
  316. 'advertiser_id' => $advertiserId,
  317. 'supplement_order_id' => $supplementOrderId,
  318. 'pay_method' => $payMethod,
  319. 'amount' => $amount,
  320. 'response' => $rst
  321. ], 256), ['song.shen@kuxuan-inc.com'], '聚星系统');
  322. return ['请求失败', 501, $rst['message']];
  323. }
  324. }
  325. public static function supplementOrderUpdateUnitPrice($advertiserId, $supplementOrderId, $price, $retry = 0) {
  326. $accessToken = JuxingAdAccount::getAccessToken($advertiserId);
  327. $juxing = new JuXing($accessToken);
  328. $param = [
  329. 'advertiser_id' => intval($advertiserId),
  330. 'supplement_order_id' => intval($supplementOrderId),
  331. 'unit_price' => intval($price * 1000)// 单位厘
  332. ];
  333. $rst = $juxing->supplementOrderV2()->unitPriceUpdate($param);
  334. if($rst === false && $retry < 3) {
  335. $retry++;
  336. return self::supplementOrderUpdateUnitPrice($advertiserId, $supplementOrderId, $price, $retry);
  337. }
  338. Log::info('助推订单修改出价', ['param' => $param, 'ret' => $rst, 'operator_id' => Auth::id()], 'supplementOrder');
  339. if(isset($rst['code']) && $rst['code'] == 0) {# 请求成功
  340. // 将广告主账户ID放入更新队列中或者直接更新系统数据
  341. self::syncFlowOrder($advertiserId);
  342. return ['', 0, null];
  343. } else {
  344. if($retry < 3) {
  345. $retry++;
  346. return self::supplementOrderUpdateUnitPrice($advertiserId, $supplementOrderId, $price, $retry);
  347. }
  348. EmailQueue::rPush('助推订单修改出价请求失败', json_encode([
  349. 'advertiser_id' => $advertiserId,
  350. 'supplement_order_id' => $supplementOrderId,
  351. 'price' => $price,
  352. 'response' => $rst
  353. ], 256), ['song.shen@kuxuan-inc.com'], '聚星系统');
  354. return ['请求失败', 501, $rst['message']];
  355. }
  356. }
  357. # 获取所选则订单中状态为推广中的订单列表
  358. public static function getActiveSupplementOrderIdList($advertiserId, $supplementOrderIdList) {
  359. Log::info('停投订单ID记录 - 全部', ['order_list' => $supplementOrderIdList], 'supplementOrder');
  360. $adverIds = [$advertiserId];
  361. $keyword = $type = $taskIds = $stDate = $enDate = null;
  362. $status = 1;
  363. $supplementOrderModel = JxStarVideoFlowOrderList::getOrderListQuery($adverIds, $keyword, $type, $status, $taskIds, $stDate, $enDate, $supplementOrderIdList);
  364. $supplementOrderList = $supplementOrderModel->selectRaw('supplement_order_id')->get();
  365. $activeSupplementOrderIdList = [];
  366. if($supplementOrderList->isNotEmpty()) {
  367. $activeSupplementOrderIdList = array_column($supplementOrderList->toArray(), 'supplement_order_id');
  368. }
  369. Log::info('停投订单记录 - 推广中', ['order_list' => $activeSupplementOrderIdList], 'supplementOrder');
  370. if(count($activeSupplementOrderIdList) > count($supplementOrderIdList)) {
  371. EmailQueue::rPush('订单停投处理结果异常 - 查询推广中订单总数超过选择订单总数', json_encode(['select_supplement_order_list' => $supplementOrderIdList
  372. , 'active_supplement_order_list' => $activeSupplementOrderIdList], 256), ['song.shen@kuxuan-inc.com'], '聚星系统');
  373. }
  374. # 推广完成状态订单ID
  375. $finishSupplementOrderModel = JxStarVideoFlowOrderList::getOrderListQuery($adverIds, $keyword, $type, 2, $taskIds, $stDate, $enDate, $supplementOrderIdList);
  376. $finishSupplementOrderList = $finishSupplementOrderModel->selectRaw('supplement_order_id')->get();
  377. Log::info('停投订单记录 - 推广完成', ['order_list' => $finishSupplementOrderList->toArray()], 'supplementOrder');
  378. if($finishSupplementOrderList->count() + count($activeSupplementOrderIdList) != count($supplementOrderIdList)) {
  379. EmailQueue::rPush('订单停投处理结果异常 - 推广中订单及推广完成订单总数不等于选择订单总数', json_encode(['select_supplement_order_count' => count($supplementOrderIdList)
  380. , 'active_supplement_order_count' => count($activeSupplementOrderIdList), 'finish_supplement_order_count' => $finishSupplementOrderList->count()], 256)
  381. , ['song.shen@kuxuan-inc.com'], '聚星系统');
  382. }
  383. return $activeSupplementOrderIdList;
  384. }
  385. }