orderDao = $orderDao; $this->openService = $openService; } public static function getByTradeNo($trade_no) { return Order::getByTradeNo($trade_no); } public static function getByTikTokOrderId($orderId) { return Order::getByTikTokOrderId($orderId); } public static function getOrderList($uid, $page_size) { return Order::getOrderList($uid, $page_size); } public static function getSuccessOrderList($uid, $page_size) { return Order::select('id', 'price', 'created_at', 'status', 'trade_no', 'order_type', 'pay_merchant_id')->where('uid', $uid)->where('status', 'PAID')->where('from_type', '!=', 'order_add')->orderBy('id', 'desc')->paginate($page_size); } /** * 获取充值订单 * * @param $uid * @return mixed */ public static function totalChargeList($uid) { return Order::join('products', 'orders.product_id', '=', 'products.id') ->select('products.price', 'products.given') ->where('orders.order_type', 'RECHARGE') ->where('orders.status', 'PAID') ->where('orders.uid', $uid) ->get(); } static function create_order($data) { $insert_data = array(); $insert_data['uid'] = isset($data['uid']) ? $data['uid'] : ''; $insert_data['price'] = isset($data['price']) ? $data['price'] : ''; $insert_data['status'] = isset($data['status']) ? $data['status'] : ''; $insert_data['pay_num'] = isset($data['pay_num']) ? $data['pay_num'] : ''; $insert_data['product_id'] = isset($data['product_id']) ? $data['product_id'] : ''; $insert_data['distribution_channel_id'] = isset($data['distribution_channel_id']) ? $data['distribution_channel_id'] : ''; $insert_data['trade_no'] = isset($data['trade_no']) ? $data['trade_no'] : ''; $insert_data['pay_merchant_source'] = isset($data['pay_merchant_source']) ? $data['pay_merchant_source'] : ''; $insert_data['pay_merchant_id'] = isset($data['pay_merchant_id']) ? $data['pay_merchant_id'] : ''; $insert_data['transaction_id'] = isset($data['transaction_id']) ? $data['transaction_id'] : ''; $insert_data['from_bid'] = isset($data['from_bid']) ? $data['from_bid'] : ''; $insert_data['order_type'] = isset($data['order_type']) ? $data['order_type'] : ''; $insert_data['pay_end_at'] = isset($data['pay_end_at']) ? $data['pay_end_at'] : null; $insert_data['create_ip'] = isset($data['create_ip']) ? $data['create_ip'] : ''; $insert_data['send_order_id'] = isset($data['send_order_id']) ? $data['send_order_id'] : ''; $result = Order::create_order($insert_data); return $result; } /** * 判断用户首充 */ public static function judgeUserFirstRecharge($uid) { $user_recharge = Order::where([ ['status', '=', 'PAID'], ['uid', '=', $uid] ])->first(); if (!$user_recharge) { return true; } return false; } /** * 是否是付费用户 * * @param $uid * @return bool */ public static function isPaidUser($uid) { if (empty($uid)) { return false; } $result = Order::select('id')->where('uid', $uid)->where('status', 'PAID')->first(); if ($result && $result->id) { return true; } return false; } /** * 是否是付费用户 * * @param $openid * @return bool */ public static function isPaidUserByOpenid($openid) { if (empty($openid)) { return false; } $result = Order::join('users', 'users.id', '=', 'orders.uid') ->select('orders.id') ->where('users.openid', $openid) ->where('orders.status', 'PAID') ->first(); if ($result && $result->id) { return true; } return false; } public static function getUserChargeTimes($uid) { return Order::getUserChargeTimes($uid); } public static function getChargeNum($uid) { return Order::where('uid', $uid)->where('status', 'PAID')->count(); } public static function getChargeNumByOpenId($openid) { $res = Order::join('users', 'orders.uid', 'users.id') ->where('users.openid', $openid) ->where('orders.status', 'PAID') ->sum('orders.price'); return $res ? $res : 0; } // 订单明细 public function getOrderData($data) { $send_order_id = getProp($data, 'send_order_id'); $trade_no = getProp($data, 'trade_no'); $transaction_id = getProp($data, 'transaction_id'); $date_range = getProp($data, 'date_range'); $query = Order::where('status', 'PAID')->select('uid', 'price', 'distribution_channel_id', 'trade_no', 'transaction_id', 'send_order_id', 'created_at', 'order_type'); if ($send_order_id) { $query->where('send_order_id', $send_order_id); } if ($trade_no) { $query->where('trade_no', $trade_no); } if ($transaction_id) { $query->where('transaction_id', $transaction_id); } //时间周期筛选 if ($date_range) { $date_range = explode(',', $date_range); if (count($date_range) == 2) { if ($date_range[0]) { $start = date('Y-m-d 00:00:00', strtotime($date_range[0])); $query->where('created_at', '>=', $start); } if ($date_range[1]) { $end = date('Y-m-d 23:59:59', strtotime($date_range[1])); $query->where('created_at', '<=', $end); } } } return $query->get(); } /** * @param $data * @return mixed * @throws ApiException */ public function orderList($data) { // 是否导出 $export = (int)getProp($data, 'export'); if ($export) { return $this->exportOrderList($data); } return $this->orderListData($data); } /** * @param $param * @return mixed * @throws ApiException */ public function exportOrderList($param) { $param['all'] = 1; $result = $this->orderListData($param); if ($result->isEmpty()) { Utils::throwError(ErrorConst::NO_DATA_FOR_EXPORT); } // 设置超时时间 set_time_limit(0); // 组装下载数据 $data = []; foreach ($result as $order) { // 支付状态说明 $status = getProp($order, 'status'); $statusDesc = $status === 'PAID' ? '已支付' : '未支付'; // 订单类型说明 $orderType = getProp($order, 'order_type'); switch ($orderType) { case 'YEAR': $orderTypeDesc = '包年'; break; case 'QUARTER': $orderTypeDesc = '包季'; break; case 'MONTH': $orderTypeDesc = '包月'; break; case 'WEEK': $orderTypeDesc = '包周'; break; case 'RECHARGE': $orderTypeDesc = '普通充值'; break; default: $orderTypeDesc = '其他充值'; break; } $data[] = [ getProp($order, 'distribution_channel_id'), getProp($order, 'trade_no'), getProp($order, 'uid'), getProp($order, 'register_ip'), getProp($order, 'register_time'), trim($orderTypeDesc), trim(getProp($order, 'book_name')), trim(getProp($order, 'send_order_name')), getProp($order, 'send_order_id'), getProp($order, 'price'), $statusDesc, $order->created_at->format('Y-m-d H:i:s'), $order->updated_at->format('Y-m-d H:i:s'), ]; } $headers = [ '站点ID', '订单编号', '用户ID', '注册IP', '注册时间', '充值类型', '充值书籍', '派单名称', '派单ID', '充值金额(元)', '订单状态', '创建时间', '更新时间' ]; // 导出csv格式 exportCsv('订单-' . date("YmdHis"), $headers, $data); // exportExcel($data, $headers, '订单-' . date("YmdHis")); // exit(); } /** * 订单数据 * * @param $data * @return mixed * @throws ApiException */ private function orderListData($data) { // 获取当前站点 $channelId = Site::getCurrentChannelId(); if (empty($channelId)) { Utils::throwError(ErrorConst::CHANNEL_ID_INVALID); } $uid = Site::getUid(); $sub_channel_ids = DB::table('channel_user_mappings')->where('master_uid', $uid)->select('sub_channel_id')->get()->pluck('sub_channel_id')->toArray(); if ($sub_channel_ids) { // 主账号 // 未筛选推广员则取全站数据 $channel_ids = array_merge([$channelId], $sub_channel_ids); $promote_user = getProp($data, 'promote_user'); if ($promote_user) { // 推广员筛选 // 如果推广员符合子账号条件则取对应子站点数据 $distribution_channel_id = DB::table('channel_users')->leftJoin('distribution_channels', 'distribution_channels.channel_user_id', 'channel_users.id') ->where('channel_users.nickname', 'like', '%' . $promote_user . '%')->value('distribution_channels.id'); if (in_array($distribution_channel_id, $channel_ids)) $channel_ids = [$distribution_channel_id]; else $channel_ids = [-1]; } } else { // 默认获取本站点数据 $channel_ids = [$channelId]; } // 站点对应 $data['channel_id'] = $channel_ids; // 返回数据 return $this->orderDao->orderList($data); } // 用户数据 public function getUserData($data) { $uid = getProp($data, 'uid'); $send_order_id = getProp($data, 'send_order_id'); $from_uid = getProp($data, 'from_uid'); $date_range = getProp($data, 'date_range'); $query = DB::table('users')->select('id', 'distribution_channel_id', 'send_order_id', 'from_uid', 'balance', 'charge_balance', 'reward_balance', 'nickname', 'vip_limit_date', 'token', 'created_at'); if ($uid) { $query->where('id', $uid); } if ($send_order_id) { $query->where('send_order_id', $send_order_id); } if ($from_uid) { $query->where('from_uid', $from_uid); } //时间周期筛选 if ($date_range) { $date_range = explode(',', $date_range); if (count($date_range) == 2) { if ($date_range[0]) { $start = date('Y-m-d 00:00:00', strtotime($date_range[0])); $query->where('created_at', '>=', $start); } if ($date_range[1]) { $end = date('Y-m-d 23:59:59', strtotime($date_range[1])); $query->where('created_at', '<=', $end); } } } return $query->get(); } // 回传日志 public function getReportData($data, $all = false) { $distribution_channel_id = Site::getCurrentChannelId(); $uid = getProp($data, 'uid'); $send_order_id = getProp($data, 'send_order_id'); $advertiserid = getProp($data, 'advertiser_id'); $promotionid = getProp($data, 'promotion_id'); $register_date_range = getProp($data, 'register_date_range'); $pay_date_range = getProp($data, 'pay_date_range'); // 列表 $query = DB::table('orders')->leftJoin('users', 'users.id', 'orders.uid') ->leftJoin('dy_report_logs', 'dy_report_logs.trade_no', 'orders.trade_no') ->leftJoin('send_orders', 'send_orders.id', 'orders.send_order_id') ->where('send_orders.distribution_channel_id', $distribution_channel_id) ->where('orders.status', 'PAID'); // 汇总 $query2 = DB::table('orders')->leftJoin('users', 'users.id', 'orders.uid') ->leftJoin('dy_report_logs', 'dy_report_logs.trade_no', 'orders.trade_no') ->leftJoin('send_orders', 'send_orders.id', 'orders.send_order_id') ->where('send_orders.distribution_channel_id', $distribution_channel_id) ->where('orders.status', 'PAID'); if ($uid) { $query->where('orders.uid', $uid); $query2->where('orders.uid', $uid); } if ($send_order_id) { $query->where('orders.send_order_id', $send_order_id); $query2->where('orders.send_order_id', $send_order_id); } if ($advertiserid) { $query->where('dy_report_logs.advertiserid', $advertiserid); $query2->where('dy_report_logs.advertiserid', $advertiserid); } if ($promotionid) { $query->where('dy_report_logs.promotionid', $promotionid); $query2->where('dy_report_logs.promotionid', $promotionid); } // 注册时间周期筛选 if ($register_date_range) { $date_range = explode(',', $register_date_range); if (count($date_range) == 2) { if ($date_range[0]) { $start = date('Y-m-d 00:00:00', strtotime($date_range[0])); $query->where('users.created_at', '>=', $start); $query2->where('users.created_at', '>=', $start); } if ($date_range[1]) { $end = date('Y-m-d 23:59:59', strtotime($date_range[1])); $query->where('users.created_at', '<=', $end); $query2->where('users.created_at', '<=', $end); } } } // 支付时间周期筛选 if ($pay_date_range) { $date_range = explode(',', $pay_date_range); if (count($date_range) == 2) { if ($date_range[0]) { $start = date('Y-m-d 00:00:00', strtotime($date_range[0])); $query->where('orders.pay_end_at', '>=', $start); $query2->where('orders.pay_end_at', '>=', $start); } if ($date_range[1]) { $end = date('Y-m-d 23:59:59', strtotime($date_range[1])); $query->where('orders.pay_end_at', '<=', $end); $query2->where('orders.pay_end_at', '<=', $end); } } } if ($all) return $query->get(); // 获取分页数据 $result = $query->select('dy_report_logs.id', 'dy_report_logs.advertiserid', 'dy_report_logs.promotionid', 'dy_report_logs.callback_result', 'dy_report_logs.remark', 'users.created_at as register_time', 'orders.send_order_id', 'orders.trade_no', 'orders.uid', 'users.register_ip', 'orders.pay_end_at as pay_time', 'orders.price', 'send_orders.report_percent', 'send_orders.report_receive_num', 'send_orders.report_post_num') ->orderBy('orders.pay_end_at', 'desc')->orderBy('users.created_at', 'desc')->paginate(); // 获取汇总数据 $all_result = $query2->selectRaw("sum(orders.price) as total_pay_amount, count(orders.id) as order_num, (select count(o.id) from orders as o where o.pay_num = 1 and o.trade_no = orders.trade_no) as first_order_num, (select sum(o.price) from orders as o where o.pay_num = 1 and o.trade_no = orders.trade_no) as first_total_pay_amount")->groupBy('orders.trade_no')->get(); $header = [ 'total_pay_amount' => 0, 'order_num' => 0, 'first_order_num' => 0, 'first_total_pay_amount' => 0, ]; foreach ($all_result as $item) { $header['total_pay_amount'] += getProp($item, 'total_pay_amount') ? getProp($item, 'total_pay_amount') : 0; $header['order_num'] += getProp($item, 'order_num'); $header['first_order_num'] += getProp($item, 'first_order_num'); $header['first_total_pay_amount'] += getProp($item, 'first_total_pay_amount') ? getProp($item, 'first_total_pay_amount') : 0; } $header['total_pay_amount'] = round($header['total_pay_amount'], 2); $header['first_total_pay_amount'] = round($header['first_total_pay_amount'], 2); $result->header = $header; return $result; } /** * 导出回传日志 * * @param $data * @throws ApiException */ public function exportReportData($data) { $list = $this->getReportData($data, true); if (empty($list)) { Utils::throwError(ErrorConst::RECORD_NOT_EXIST); } $result = []; foreach ($list as $item) { $callback_result = getProp($item, 'callback_result'); $remark = getProp($item, 'remark'); $remark = $remark == '' ? '比例回传' : $remark; $result[] = [ 'report_id' => getProp($item, 'id'), 'advertiserid' => getProp($item, 'advertiserid'), 'promotionid' => getProp($item, 'promotionid'), 'callback_result' => $callback_result, 'remark' => $remark, 'uid' => getProp($item, 'uid'), 'register_ip' => getProp($item, 'register_ip'), 'register_time' => transDate(getProp($item, 'register_time')), 'pay_time' => transDate(getProp($item, 'pay_time')), 'price' => getProp($item, 'price'), 'current_percent' => getProp($item, 'report_receive_num') ? sprintf('%.1f', getProp($item, 'report_post_num') / getProp($item, 'report_receive_num') * 100) : 0, 'report_percent' => getProp($item, 'report_percent'), ]; } $headers = ['ID', '广告账户ID', '广告ID', '回传状态', '备注', '用户ID', '注册IP', '注册时间', '充值时间', '充值金额', '已回传/待回传(%)', '应用回传比例(%)']; exportFileCsv($headers, $result, '回传日志-' . date('YmdHis')); } // 派单列表 public function getSendOrderData($data, $all = false) { $distribution_channel_id = Site::getCurrentChannelId(); $send_order_id = getProp($data, 'send_order_id'); $send_order_name = getProp($data, 'send_order_name'); $date_range = getProp($data, 'date_range'); $uid = Site::getUid(); $sub_channel_ids = DB::table('channel_user_mappings')->where('master_uid', $uid)->select('sub_channel_id')->get()->pluck('sub_channel_id')->toArray(); if ($sub_channel_ids) { // 主账号 // 未筛选推广员则取全站数据 $channel_ids = array_merge([$distribution_channel_id], $sub_channel_ids); $promote_user = getProp($data, 'promote_user'); if ($promote_user) { // 推广员筛选 // 如果推广员符合子账号条件则取对应子站点数据 $distribution_channel_id = DB::table('channel_users')->leftJoin('distribution_channels', 'distribution_channels.channel_user_id', 'channel_users.id') ->where('channel_users.nickname', 'like', '%' . $promote_user . '%')->value('distribution_channels.id'); if (in_array($distribution_channel_id, $channel_ids)) $channel_ids = [$distribution_channel_id]; else $channel_ids = [-1]; } } else { // 默认获取本站点数据 $channel_ids = [$distribution_channel_id]; } $query = DB::table('send_orders')->leftJoin('books', 'books.id', 'send_orders.book_id') ->leftJoin('distribution_channels', 'distribution_channels.id', 'send_orders.distribution_channel_id') ->leftJoin('channel_users', 'channel_users.id', 'distribution_channels.channel_user_id') ->leftJoin('channel_templates', 'channel_templates.id', 'send_orders.pay_id') ->whereIn('send_orders.distribution_channel_id', $channel_ids)->select('send_orders.*', 'books.cover', 'books.category_name', 'books.intro', 'channel_templates.template_name', 'channel_templates.id as template_id', 'channel_users.nickname'); if ($send_order_id) { $query->where('send_orders.id', $send_order_id); } if ($send_order_name) { $query->where('send_orders.name', 'like', '%' . $send_order_name . '%'); } // 支付时间周期筛选 if ($date_range) { $date_range = explode(',', $date_range); if (count($date_range) == 2) { if ($date_range[0]) { $start = date('Y-m-d 00:00:00', strtotime($date_range[0])); $query->where('send_orders.created_at', '>=', $start); } if ($date_range[1]) { $end = date('Y-m-d 23:59:59', strtotime($date_range[1])); $query->where('send_orders.created_at', '<=', $end); } } } if ($all) return $query->orderBy('send_orders.created_at', 'desc')->get(); $result = $query->orderBy('send_orders.created_at', 'desc')->paginate(); $result->channel_id = $distribution_channel_id; return $result; } // 导出派单数据 public function exportSendOrderData($data) { $list = $this->getSendOrderData($data, true); if (empty($list)) { Utils::throwError(ErrorConst::RECORD_NOT_EXIST); } $start = date('Y-m-d 00:00:00'); $result = []; foreach ($list as $item) { $send_order_id = getProp($item, 'id'); // 获取今日注册人数 $today_register_num = DB::table('users')->where('send_order_id', $send_order_id)->where('created_at', '>', $start)->count('id'); // 今日订单信息 $today_order = DB::table('orders')->leftJoin('users', 'orders.uid', 'users.id')->where('users.send_order_id', $send_order_id) ->where('orders.send_order_id', $send_order_id)->where('users.created_at', '>', $start) ->where('orders.status', 'PAID')->where('orders.created_at', '>', $start)->selectRaw("count(orders.pay_num = 1) as register_pay_num, sum(orders.price) as register_pay_amount")->get(); $today_register_pay_num = getProp($today_order[0], 'register_pay_num'); $today_register_pay_amount = getProp($today_order[0], 'register_pay_amount') ? getProp($today_order[0], 'register_pay_amount') : 0; // 派单uv $uv = Redis::scard('send_order_uv_' . $send_order_id); $uv = $uv ? $uv : 0; // 累计订单信息 $total_order = DB::table('orders')->where('orders.send_order_id', $send_order_id)->where('orders.status', 'PAID') ->selectRaw("count(distinct orders.uid) as pay_num, sum(orders.price) as pay_amount")->get(); $total_pay_num = getProp($total_order[0], 'pay_num'); $total_pay_amount = getProp($total_order[0], 'pay_amount') ? getProp($total_order[0], 'pay_amount') : 0; $result[] = [ 'send_order_id' => $send_order_id, 'send_order_name' => getProp($item, 'name'), 'book_name' => getProp($item, 'book_name'), 'chapter_name' => getProp($item, 'chapter_name'), 'today_register_num' => $today_register_num, 'today_register_pay_num' => $today_register_pay_num, 'today_register_pay_amount' => $today_register_pay_amount, 'total_register_num' => getProp($item, 'total_register_num') + $today_register_num, 'total_register_pay_num' => getProp($item, 'total_register_pay_num') + $today_register_pay_num, 'total_register_pay_amount' => getProp($item, 'total_register_pay_amount') + $today_register_pay_amount, 'uv' => $uv, 'total_pay_num' => $total_pay_num, 'total_pay_amount' => $total_pay_amount, 'total_cost' => getProp($item, 'cost'), 'total_profit' => getProp($item, 'total_profit'), 'total_profit_percent' => (float)getProp($item, 'cost') ? round($total_pay_amount / getProp($item, 'cost') * 100, 2) : 0, 'created_at' => transDate(getProp($item, 'created_at')), ]; } $headers = ['派单id', '派单名称', '书名', '章节名', '今日新增注册', '今日注册充值人数', '今日注册用户充值(元)', '累计注册', '累计注册充值人数', '累计注册用户充值(元)', 'UV', '累计充值人数', '累计充值金额(元)', '累计成本(元)', '累计盈利(元)', '累计回本(%)', '创建时间']; exportFileCsv($headers, $result, '派单数据-' . date('YmdHis')); } /** * 获取派单链接适用的模板 * * @param $data * @return array */ public function getSendOrderTemplates($data) { $distribution_channel_id = Site::getCurrentChannelId(); return DB::table('channel_templates')->where('distribution_channel_id', $distribution_channel_id)->where('is_enable', 1)->whereIn('user_scope', [1, 3]) ->select('id as template_id', 'template_name')->get()->map(function ($value) { return (array)$value; })->toArray(); } /** * 编辑派单链接 * * @param $data * @return mixed * @throws \App\Exceptions\ApiException * @throws \GuzzleHttp\Exception\GuzzleException */ public function editSendOrderUrl($data) { $send_order_id = getProp($data, 'send_order_id'); $send_order_name = getProp($data, 'send_order_name'); $report_percent = getProp($data, 'report_percent', 0); $template_id = getProp($data, 'template_id'); if (!is_numeric($report_percent)) { Utils::throwError(ErrorConst::DATA_EXCEPTION); } // 获取派单信息 $send_order = DB::table('send_orders')->where('id', $send_order_id)->first(); if (!$send_order) { Utils::throwError(ErrorConst::SEND_ORDER_NOT_EXIST); } $distribution_channel_id = getProp($send_order, 'distribution_channel_id'); if ((int)$distribution_channel_id !== (int)Site::getCurrentChannelId()) { Utils::throwError(ErrorConst::CHANNEL_NOT_EXIST); } if ($template_id) { $template = DB::table('channel_templates')->where('id', $template_id)->where('distribution_channel_id', $distribution_channel_id)->first(); if (!$template) { Utils::throwError('1002:该充值模板不存在!'); } } // 判断派单名称是否重复 $id = DB::table('send_orders')->where('name', $send_order_name)->value('id'); if ($id && $id != $send_order_id) { Utils::throwError(ErrorConst::SEND_ORDER_NAME_INVALID); } // 更新派单信息 $update_data = [ 'name' => $send_order_name, 'report_percent' => $report_percent, 'updated_at' => date('Y-m-d H:i:s') ]; if (getProp($send_order, 'report_percent') != $report_percent) { $update_data['report_receive_num'] = 0; $update_data['report_post_num'] = 0; } if ($template_id) { $update_data['pay_id'] = $template_id; } // 调用抖音三方库生成分享链接(非本地模式调用) if (env('APP_ENV') != 'local') { $bid = getProp($send_order, 'book_id'); $cid = getProp($send_order, 'chapter_id'); $distribution_channel_id = getProp($send_order, 'distribution_channel_id'); // 重新生成派单链接 $arr = [ 'bid' => $bid ? Hashids::encode($bid) : '', 'cid' => $cid ? Hashids::encode($cid) : '', 'send_order_id' => $send_order_id, 'distribution_channel_id' => $distribution_channel_id, 'jump' => 'no', ]; $json = json_encode($arr, 256); $path = 'pages/reader/index'; // 固定页面(阅读页) $instance = $this->openService->getInstance(['sandbox' => env('DOUYIN_APP_SANDBOX')]); $urlLink = $instance->generateShareLink($path, $json); if (!isset($urlLink['url_link'])) { Utils::throwError(ErrorConst::SYS_EXCEPTION); } $update_data['send_order_url'] = $urlLink['url_link']; } return DB::table('send_orders')->where('id', $send_order_id)->update($update_data); } // 派单日数据 public function getSendOrderDayData($data, $all = false) { $distribution_channel_id = Site::getCurrentChannelId(); $send_order_id = getProp($data, 'send_order_id'); $date_range = getProp($data, 'date_range'); // 获取主账号下的子账号站点 $uid = Site::getUid(); $sub_channel_ids = DB::table('channel_user_mappings')->where('master_uid', $uid)->select('sub_channel_id')->get()->pluck('sub_channel_id')->toArray(); $send_order_info = DB::table('send_orders')->leftJoin('books', 'books.id', 'send_orders.book_id') ->leftJoin('book_configs', 'book_configs.bid', 'send_orders.book_id') ->leftJoin('books as b1', 'b1.id', 'book_configs.origin_bid') ->where('send_orders.id', $send_order_id)->select('send_orders.id', 'send_orders.name', 'send_orders.distribution_channel_id', 'books.name as book_name', 'b1.name as origin_book_name')->first(); if (!$send_order_info) { Utils::throwError(ErrorConst::DATA_EXCEPTION); } $send_order_name = getProp($send_order_info, 'name'); $send_order_channel_id = getProp($send_order_info, 'distribution_channel_id'); if (!in_array($send_order_channel_id, $sub_channel_ids) && $send_order_channel_id != $distribution_channel_id) { Utils::throwError('1002: 没有该站点的查看权限!'); } $query = DB::table('send_order_day_stats')->where('send_order_id', $send_order_id); // 默认时间范围是最近一个月 $end = date('Y-m-d', strtotime('-1 day')); $start = date('Y-m-d', strtotime('-31 day')); if ($date_range) { $date_range = explode(',', $date_range); if (count($date_range) == 2) { $start = $date_range[0]; $end = $date_range[1]; if (strtotime($end) - strtotime($start) > 86400 * 30) { Utils::throwError(ErrorConst::DATE_RANGE_OVER_MONTH); } } } $query->whereBetween('day', [$start, $end]); if ($all) { $result = $query->orderBy('day', 'desc')->get(); return [$result, $start, $send_order_info]; } $result = $query->orderBy('day', 'desc')->paginate(5); $result->send_order_name = $send_order_name; $result->start_date = $start; $result->send_order_id = $send_order_id; return $result; } // 导出派单日数据 public function exportSendOrderDayData($data) { [$list, $start, $send_order_info] = $this->getSendOrderDayData($data, true); if (empty($list)) { Utils::throwError(ErrorConst::RECORD_NOT_EXIST); } $send_order_id = getProp($send_order_info, 'id'); $send_order_name = getProp($send_order_info, 'name'); $end = date('Y-m-d', strtotime($start . ' +120 day')); // 获取时间段内的数据 $period_data = DB::table('send_order_recharge_day_stats')->where('send_order_id', $send_order_id)->whereBetween('register_date', [$start, $end]) ->orderBy('pay_date')->get()->map(function ($value) { return (array)$value; })->toArray(); $day_stats = []; // 注册用户派单日数据初始化 foreach ($list as $item) { $day_stats[getProp($item, 'day')] = []; } // 将已有数据填充 foreach ($period_data as $item) { $day = $item['register_date']; $day_stats[$day]['t' . $item['day_num']] = [ 'register_pay_amount' => $item['pay_amount'], 'total_register_pay_amount' => $item['day_num'] == 0 ? $item['pay_amount'] : 0, // t0日有金额,其他日在下个循环累加 ]; } $i_arr = range(0, 29); // 第1~30天 $i_arr = array_merge($i_arr, [44, 59, 89]); // 第45、60、90天 // 将当日无数据的日期占位并计算累计值 foreach ($day_stats as $day => $value) { $today_start = date('Y-m-d 00:00:00'); $today_end = date('Y-m-d 23:59:59'); // 获取当日注册用户 if (Redis::exists('register_uids_' . $send_order_id . '_' . $day)) { //获取缓存 $day_register_uids = json_decode(Redis::get('register_uids_' . $send_order_id . '_' . $day), true); } else { $day_register_uids = DB::table('users')->where('send_order_id', $send_order_id) ->whereBetween('created_at', [date('Y-m-d 00:00:00', strtotime($day)), date('Y-m-d 23:59:59', strtotime($day))]) ->select('id')->get()->pluck('id')->toArray(); // 写入缓存 Redis::set('register_uids_' . $send_order_id . '_' . $day, json_encode($day_register_uids)); Redis::expire('register_uids_' . $send_order_id . '_' . $day, strtotime($today_end) - time()); } // 获取注册用户今日数据 $day_stats[$day]['today']['register_pay_amount'] = DB::table('orders')->where('send_order_id', $send_order_id)->where('status', 'PAID') ->whereIn('uid', $day_register_uids)->whereBetween('created_at', [$today_start, $today_end])->sum('price'); $day_stats[$day]['today']['total_register_pay_amount'] = DB::table('orders')->where('send_order_id', $send_order_id)->where('status', 'PAID') ->whereIn('uid', $day_register_uids)->where('created_at', '<=', $today_end)->sum('price'); // 获取注册用户总数据 $total_data = DB::table('orders')->where('send_order_id', $send_order_id)->where('status', 'PAID') ->whereIn('uid', $day_register_uids)->selectRaw("count(distinct uid) as pay_num, sum(price) as total_pay_amount")->get(); $day_stats[$day]['total']['pay_num'] = getProp($total_data[0], 'pay_num'); $day_stats[$day]['total']['total_pay_amount'] = getProp($total_data[0], 'total_pay_amount') ? getProp($total_data[0], 'total_pay_amount') : 0; for ($i = 0; $i <= 89; $i++) { $diff_day = (strtotime(date('Y-m-d')) - strtotime($day)) / 86400; if (isset($day_stats[$day]['t' . $i])) { if ($i != 0) $day_stats[$day]['t' . $i]['total_register_pay_amount'] = round($day_stats[$day]['t' . ($i - 1)]['total_register_pay_amount'] + $day_stats[$day]['t' . $i]['register_pay_amount'], 2); } else { if ($i == $diff_day) { // 如果是当日则取当日数据 $day_stats[$day]['t' . $i] = [ 'register_pay_amount' => $day_stats[$day]['today']['register_pay_amount'], 'total_register_pay_amount' => 0, ]; } else { $day_stats[$day]['t' . $i] = [ 'register_pay_amount' => 0, 'total_register_pay_amount' => 0, ]; } if ($i != 0) $day_stats[$day]['t' . $i]['total_register_pay_amount'] = round($day_stats[$day]['t' . ($i - 1)]['total_register_pay_amount'] + $day_stats[$day]['t' . $i]['register_pay_amount'], 2); } } } $result = []; foreach ($list as $item) { $send_order_id = getProp($item, 'send_order_id'); $day = getProp($item, 'day'); $cost = getProp($item, 'cost'); // 获取日统计数据 $stats = $day_stats[$day]; $arr = [ 'distribution_channel_id' => getProp($send_order_info, 'distribution_channel_id'), 'send_order_id' => $send_order_id, 'send_order_name' => $send_order_name, 'book_name' => getProp($send_order_info, 'book_name'), 'origin_book_name' => getProp($send_order_info, 'origin_book_name'), 'date' => $day, 'cost' => $cost, 'register_num' => getProp($item, 'register_num'), // 注册用户 'register_cost' => getProp($item, 'register_num') ? round($cost / getProp($item, 'register_num'), 2) : 0, // 注册成本 'register_pay_num' => getProp($item, 'register_pay_num'), // 当日注册充值人数 'register_pay_percent' => getProp($item, 'register_num') ? round(getProp($item, 'register_pay_num') / getProp($item, 'register_num') * 100, 2) : 0, // 当日注册付费率 'register_pay_cost' => getProp($item, 'register_pay_num') ? round($cost / getProp($item, 'register_pay_num'), 2) : 0, // 当日转化成本 'total_register_pay_amount' => getProp($stats, 'total')['total_pay_amount'], // 累计充值 'total_profit_percent' => (float)$cost ? round(getProp($stats, 'total')['total_pay_amount'] / $cost * 100, 2) : 0, //累计回本率 'total_profit_cost' => getProp($stats, 'total')['pay_num'] ? round($cost / getProp($stats, 'total')['pay_num'], 2) : 0, ]; foreach ($i_arr as $i) { $profit_percent = (float)$cost ? round($stats['t' . $i]['register_pay_amount'] / $cost * 100, 2) : 0; $total_profit_percent = (float)$cost ? round($stats['t' . $i]['total_register_pay_amount'] / $cost * 100, 2) : 0; $arr['t' . $i . '_register_pay_amount'] = $stats['t' . $i]['register_pay_amount']; $arr['t' . $i . '_total_register_pay_amount'] = $stats['t' . $i]['total_register_pay_amount']; $arr['t' . $i . '_profit_percent'] = $profit_percent; $arr['t' . $i . '_total_profit_percent'] = $total_profit_percent; // $arr['t'.$i] = '当日充值金额(元): ' . $stats['t'.$i]['register_pay_amount'] . PHP_EOL . // '累计充值金额(元): ' . $stats['t'.$i]['total_register_pay_amount'] . PHP_EOL . // '当日回本率(%): '. $profit_percent . PHP_EOL . // '累计回本率(%): ' . $total_profit_percent; } $result[] = $arr; } $headers = ['站点ID', '派单ID', '派单名称', '推广书籍', '原书名', '日期', '成本', '注册用户', '注册成本', '当日注册充值人数', '当日注册付费率(%)', '当日转化成本(元)', '累计充值', '累计回本率(%)', '累计转化成本(元)', 'T+0(当日)当日充值金额(元)', 'T+0(当日)累计充值金额(元)', 'T+0(当日)当日回本率(%)', 'T+0(当日)累计回本率(%)']; for ($i = 1; $i <= 29; $i++) { $headers[] = 'T+' . $i . '(第' . ($i + 1) . '日)当日充值金额(元)'; $headers[] = 'T+' . $i . '(第' . ($i + 1) . '日)累计充值金额(元)'; $headers[] = 'T+' . $i . '(第' . ($i + 1) . '日)当日回本率(%)'; $headers[] = 'T+' . $i . '(第' . ($i + 1) . '日)累计回本率(%)'; } $headers = array_merge($headers, ['T+44(第45日)当日充值金额(元)', 'T+44(第45日)累计充值金额(元)', 'T+44(第45日)当日回本率(%)', 'T+44(第45日)累计回本率(%)', 'T+59(第60日)当日充值金额(元)', 'T+59(第60日)累计充值金额(元)', 'T+59(第60日)当日回本率(%)', 'T+59(第60日)累计回本率(%)', 'T+89(第90日)当日充值金额(元)', 'T+89(第90日)累计充值金额(元)', 'T+89(第90日)当日回本率(%)', 'T+89(第90日)累计回本率(%)']); exportFileCsv($headers, $result, '派单日数据-' . $send_order_name . '-' . date('YmdHis')); } /** * 设置派单日成本 * * @param $data * @return mixed * @throws \App\Exceptions\ApiException * @throws \GuzzleHttp\Exception\GuzzleException */ public function setDayCost($data) { $id = getProp($data, 'id'); $cost = getProp($data, 'cost'); if (!is_numeric($cost)) { Utils::throwError(ErrorConst::DATA_EXCEPTION); } // 获取派单日信息 $send_order_day_stats = DB::table('send_order_day_stats')->where('id', $id)->first(); if (!$send_order_day_stats) { Utils::throwError(ErrorConst::SEND_ORDER_NOT_EXIST); } // 数据未变更则直接返回 if (getProp($send_order_day_stats, 'cost') == $cost) { return true; } // 获取派单信息 $send_order_id = getProp($send_order_day_stats, 'send_order_id'); $send_order = DB::table('send_orders')->where('id', $send_order_id)->first(); if (!$send_order) { Utils::throwError(ErrorConst::SEND_ORDER_NOT_EXIST); } try { DB::beginTransaction(); $boolen = DB::table('send_order_day_stats')->where('id', $id)->update([ 'cost' => $cost, 'updated_at' => date('Y-m-d H:i:s') ]); if (!$boolen) { DB::rollback(); Log::info('派单日数据更新失败: ' . json_encode([ 'id' => $id, 'cost' => $cost, 'updated_at' => date('Y-m-d H:i:s') ])); Utils::throwError(ErrorConst::DB_INVALID); } $total_cost = DB::table('send_order_day_stats')->where('send_order_id', $send_order_id)->sum('cost'); $total_profit = getProp($send_order, 'total_register_pay_amount') - $total_cost; $boolen1 = DB::table('send_orders')->where('id', $send_order_id)->update([ 'cost' => $total_cost, 'total_profit' => $total_profit, 'updated_at' => date('Y-m-d H:i:s') ]); if (!$boolen1) { DB::rollback(); Log::info('派单总数据更新失败: ' . json_encode([ 'send_order_id' => $send_order_id, 'cost' => $total_cost, 'total_profit' => $total_profit, 'updated_at' => date('Y-m-d H:i:s') ])); Utils::throwError(ErrorConst::DB_INVALID); } } catch (\Exception $e) { DB::rollback(); Utils::throwError(ErrorConst::STOP_TRANSACTION); } DB::commit(); return true; } /** * 充值模板 * * @param $data * @return mixed */ public function getTemplateList($data) { $distribution_channel_id = Site::getCurrentChannelId(); $template_id = getProp($data, 'template_id'); $query = DB::table('channel_templates')->where('distribution_channel_id', $distribution_channel_id); if ($template_id) { $query->where('id', $template_id); } return $query->orderBy('template_type')->orderBy('created_at', 'desc')->paginate(); } /** * 设置充值模板启用状态 * * @param $data * @return int * @throws ApiException */ public function setTemplateStatus($data) { $template_id = getProp($data, 'template_id'); $distribution_channel_id = Site::getCurrentChannelId(); $template = DB::table('channel_templates')->where('id', $template_id)->where('distribution_channel_id', $distribution_channel_id)->first(); if (!$template) { Utils::throwError(ErrorConst::DATA_EXCEPTION); } $is_enable = getProp($data, 'is_enable'); if ($is_enable === '' || !in_array($is_enable, [0, 1])) { Utils::throwError('1002:未知状态'); } if ((int)$is_enable === 0 && (int)getProp($template, 'template_type') === 1) { Utils::throwError('1002:默认模版不可被停用'); } return DB::table('channel_templates')->where('id', $template_id)->update([ 'is_enable' => $is_enable, 'updated_at' => date('Y-m-d H:i:s') ]); } /** * 新增模版 * * @param $data * @return bool * @throws ApiException */ public function addTemplate($data) { $distribution_channel_id = Site::getCurrentChannelId(); $user_scope = getProp($data, 'user_scope'); if ((int)$user_scope === 1) { Utils::throwError('1002:不可选择该适用人群'); } $template_arr = [ 'distribution_channel_id' => $distribution_channel_id, 'template_name' => getProp($data, 'template_name'), 'template_type' => 2, 'user_scope' => $user_scope, 'orders' => $user_scope == 3 ? 0 : getProp($data, 'orders', 0), 'is_enable' => getProp($data, 'is_enable', 0), 'template_cate' => getProp($data, 'template_cate', 1), 'created_at' => date('Y-m-d H:i:s'), 'updated_at' => date('Y-m-d H:i:s'), ]; $channel_type = DB::table('distribution_channels')->where('id', $distribution_channel_id)->value('channel_type'); if (DB::table('channel_templates')->where('distribution_channel_id', $distribution_channel_id)->where('template_name', getProp($data, 'template_name'))->value('id')) { Utils::throwError('1002:模板名称重复,请更换'); } try { DB::beginTransaction(); $template_id = DB::table('channel_templates')->insertGetId($template_arr); if (!$template_id) { DB::rollBack(); Log::info('创建模版失败: ' . json_encode($template_arr, 256)); Utils::throwError('1002:创建模版失败'); } $products = getProp($data, 'products', []); if (is_string($products)) { $products = json_decode($products, true); } $product_type = BaseConst::PRODUCT_TYPE; $type_valid = array_keys($product_type); $type_valid[] = 'RECHARGE'; $sequence = 1; $product_arr = []; $default_count = 0; foreach ($products as $product) { $type = getProp($product, 'type'); $price = sprintf('%.2f', getProp($product, 'price')); if (!$type || (!in_array($type, $type_valid)) || $price <= 0) { Utils::throwError('1002:档位类型或价格设置有误,请重新设置!'); } $given = getProp($product, 'given', 0); $angle_sign_text = getProp($product, 'angle_sign_text'); $price_desc = ''; $is_default = getProp($product, 'is_default', 0); // 是否默认 if ($is_default) $default_count += 1; switch ($type) { case 'RECHARGE': if ($channel_type == 'PERIOD') Utils::throwError('1002:会员制站点不得设置充值档位,只能设置包周期档位!'); $name = $price . '元'; $name_desc = ''; if ($given) $price_desc = '赠' . $given . '书币'; break; default: $name = $product_type[$type]; $name_desc = $name; break; } $product_arr[] = [ 'type' => $type, 'name' => $name, 'name_desc' => $name_desc, 'price' => $price, 'price_desc' => $price_desc, 'given' => $given, 'angle_sign_text' => $angle_sign_text, 'is_default' => $is_default, 'is_enabled' => 1, 'sequence' => $sequence, 'template_type' => $template_id, 'template_id' => $template_id, 'created_at' => date('Y-m-d H:i:s'), 'updated_at' => date('Y-m-d H:i:s'), ]; $sequence += 1; } if (count($product_arr) < 3 || count($product_arr) > 6) { Utils::throwError('1002:充值档位不得低于3个,也不得高于6个'); } if ((int)$default_count === 0) { Utils::throwError('1002:请设置默认档位'); } if ((int)$default_count > 1) { Utils::throwError('1002:只可设置一个默认档位'); } $boolen = DB::table('products')->insert($product_arr); if (!$boolen) { DB::rollBack(); Log::info('创建充值档位失败: ' . json_encode($product_arr, 256)); Utils::throwError('1002:创建充值档位失败'); } } catch (\Exception $e) { DB::rollback(); Utils::throwError('1002:' . $e->getMessage()); } DB::commit(); return true; } /** * 编辑模版 * * @param $data * @return bool * @throws ApiException */ public function editTemplate($data) { $distribution_channel_id = Site::getCurrentChannelId(); $user_scope = getProp($data, 'user_scope'); if ((int)$user_scope === 1) { Utils::throwError('1002:不可选择该适用人群'); } $template_id = getProp($data, 'template_id'); $template = DB::table('channel_templates')->where('distribution_channel_id', $distribution_channel_id)->where('id', $template_id)->first(); if (!$template) { Utils::throwError('1002:该模版不存在'); } $channel_type = DB::table('distribution_channels')->where('id', $distribution_channel_id)->value('channel_type'); $id = DB::table('channel_templates')->where('distribution_channel_id', $distribution_channel_id)->where('template_name', getProp($data, 'template_name'))->value('id'); if ($id && $id != getProp($template, 'id')) { Utils::throwError('1002:模板名称重复,请更换'); } $template_arr = [ 'distribution_channel_id' => $distribution_channel_id, 'template_name' => getProp($data, 'template_name'), 'orders' => $user_scope == 3 ? 0 : getProp($data, 'orders', 0), 'is_enable' => getProp($data, 'is_enable', 0), 'template_cate' => getProp($data, 'template_cate', 1), 'updated_at' => date('Y-m-d H:i:s'), ]; if (getProp($template, 'template_type') != 1) { $template_arr['user_scope'] = $user_scope; } $product_ids = DB::table('products')->where('template_id', $template_id)->select('id')->get()->pluck('id')->toArray(); try { DB::beginTransaction(); $boolen = DB::table('channel_templates')->where('id', $template_id)->update($template_arr); if (!$boolen) { DB::rollBack(); Log::info('更新模版失败: ' . json_encode($template_arr, 256)); Utils::throwError('1002:更新模版失败'); } $products = getProp($data, 'products', []); if (is_string($products)) { $products = json_decode($products, true); } $product_type = BaseConst::PRODUCT_TYPE; $type_valid = array_keys($product_type); $type_valid[] = 'RECHARGE'; $sequence = 1; $product_arr = []; $default_count = 0; $remain_product_ids = []; foreach ($products as $product) { $product_id = getProp($data, 'product_id'); if ($product_id) $remain_product_ids[] = $product_id; $type = getProp($product, 'type'); $price = sprintf('%.2f', getProp($product, 'price')); if (!$type || (!in_array($type, $type_valid)) || $price <= 0) { Utils::throwError('1002:档位类型或价格设置有误,请重新设置!'); } $given = getProp($product, 'given', 0); $angle_sign_text = getProp($product, 'angle_sign_text'); $price_desc = ''; $is_default = getProp($product, 'is_default', 0); // 是否默认 if ($is_default) $default_count += 1; switch ($type) { case 'RECHARGE': if ($channel_type == 'PERIOD') Utils::throwError('1002:会员制站点不得设置充值档位,只能设置包周期档位!'); $name = $price . '元'; $name_desc = ''; if ($given) $price_desc = '赠' . $given . '书币'; break; default: $name = $product_type[$type]; $name_desc = $name; break; } $tmp = [ 'type' => $type, 'name' => $name, 'name_desc' => $name_desc, 'price' => $price, 'price_desc' => $price_desc, 'given' => $given, 'angle_sign_text' => $angle_sign_text, 'is_default' => $is_default, 'is_enabled' => 1, 'sequence' => $sequence, 'template_type' => $template_id, 'template_id' => $template_id, 'updated_at' => date('Y-m-d H:i:s'), ]; if ($product_id) { // 更新已有的档位 $boolen1 = DB::table('product')->where('id', $product_id)->update($tmp); if (!$boolen1) { DB::rollBack(); Log::info('更新充值档位失败: ' . json_encode($tmp, 256)); Utils::throwError('1002:更新充值档位失败'); } } else { // 写入新的档位 $tmp['created_at'] = date('Y-m-d H:i:s'); $product_arr[] = $tmp; } $sequence += 1; } if (count($products) < 3 || count($products) > 6) { Utils::throwError('1002:充值档位不得低于3个,也不得高于6个'); } if ((int)$default_count === 0) { Utils::throwError('1002:请设置默认档位'); } if ((int)$default_count > 1) { Utils::throwError('1002:只可设置一个默认档位'); } // 执行写入 $boolen2 = DB::table('products')->insert($product_arr); if (!$boolen2) { DB::rollBack(); Log::info('创建充值档位失败: ' . json_encode($product_arr, 256)); Utils::throwError('1002:创建充值档位失败'); } // 执行删除档位 $delete_ids = array_diff($product_ids, $remain_product_ids); $boolen3 = DB::table('products')->whereIn('id', $delete_ids)->delete(); if (!$boolen3) { DB::rollBack(); Log::info('删除充值档位失败: ' . json_encode($delete_ids, 256)); Utils::throwError('1002:删除充值档位失败'); } } catch (\Exception $e) { DB::rollback(); Utils::throwError('1002:' . $e->getMessage()); } DB::commit(); return true; } // 推广数据 public function getPromotionData($data) { $promotionid = getProp($data, 'promotion_id'); $start_date = getProp($data, 'start_date'); $end_date = getProp($data, 'end_date'); if (!$promotionid) { Utils::throwError(ErrorConst::DATA_EXCEPTION); } $channel_id = DB::table('dy_report_logs')->leftJoin('send_orders', 'send_orders.id', 'dy_report_logs.send_order_id')->where('dy_report_logs.promotionid', $promotionid)->value('send_orders.distribution_channel_id'); $query = DB::table('dy_report_logs')->leftJoin('orders', 'orders.uid', 'dy_report_logs.uid')->where('orders.status', 'PAID') ->where('dy_report_logs.promotionid', $promotionid)->select('dy_report_logs.uid')->groupBY('dy_report_logs.uid'); $uids = $query->get()->pluck('uid')->toArray(); $result = [ 'distribution_channel_id' => $channel_id, 'promotion_id' => $promotionid, 'recharge_amount' => 0, 'first_recharge_amount' => 0, 'recharge_user_num' => count($uids), 'recharge_order_num' => 0, ]; $where = []; if ($start_date) { $start = date('Y-m-d 00:00:00', strtotime($start_date)); $where[] = [ 'created_at', '>=', $start ]; } if ($end_date) { $end = date('Y-m-d 23:59:59', strtotime($end_date)); $where[] = [ 'created_at', '<=', $end ]; } if (!$start_date && !$end_date) { $start = date('Y-m-d 00:00:00'); $end = date('Y-m-d 23:59:59'); $where = [ [ 'created_at', '>=', $start ], [ 'created_at', '<=', $end ] ]; } // 获取充值总额 $result['recharge_amount'] = DB::table('orders')->whereIn('uid', $uids)->where('status', 'PAID')->where($where)->sum('price'); $result['recharge_order_num'] = DB::table('orders')->whereIn('uid', $uids)->where('status', 'PAID')->where($where)->count('id'); $result['first_recharge_amount'] = DB::table('orders')->whereIn('uid', $uids)->where('status', 'PAID')->where($where)->where('pay_num', 1)->sum('price'); return $result; } // 补回传 public function reportPromotionOrder($data) { $report_id = getProp($data, 'report_id'); if (!$report_id) { Utils::throwError(ErrorConst::DATA_EXCEPTION); } $dy_report_log = DB::table('dy_report_logs')->where('id', $report_id)->where('callback_result', '失败')->where('remark', '比例过滤')->first(); if (!$dy_report_log) { Utils::throwError('1002:暂无可回传数据'); } $clickid = getProp($dy_report_log, 'clickid'); $post_data = [ 'clickid' => $clickid, 'event_type' => 'active_pay', 'context' => [ 'ad' => [ 'callback' => $clickid, ] ], 'timestamp' => (int)(microtime(true) * 1000), ]; try { $client = new Client(['verify' => false]); $response = $client->post('https://analytics.oceanengine.com/api/v2/conversion', ['json' => $post_data]); $response_json = $response->getBody()->getContents(); $result = json_decode($response_json, true); $update_data = [ 'callback_result' => (isset($result['message']) && $result['message'] == '成功') ? '成功' : '失败', 'callback_response' => $response_json, 'remark' => isset($result['message']) ? ($result['message'] == '成功' ? '手动回传' : $result['message']) : '回参错误', 'updated_at' => date('Y-m-d H:i:s') ]; // 写入抖音广告主投放回调日志表 $boolen = DB::table('dy_report_logs')->where('id', getProp($dy_report_log, 'id'))->update($update_data); if (!$boolen) { dLog('reportDy')->info('写入抖音广告主投放回调日志表失败: ', $update_data); Utils::throwError(ErrorConst::REPORT_FAILED); } return $boolen; } catch (\Exception $e) { dLog('reportDy')->info('上报异常: ', ['error' => $e->getMessage()]); } } }