|
@@ -0,0 +1,408 @@
|
|
|
|
+<?php
|
|
|
|
+
|
|
|
|
+namespace App\Services\LandingPage;
|
|
|
|
+
|
|
|
|
+use App\Consts\BaseConst;
|
|
|
|
+use General\Models\User\QappUser;
|
|
|
|
+use General\Models\Order\Order;
|
|
|
|
+use Exception;
|
|
|
|
+use General\Models\LandingPage\LandingPageDomain;
|
|
|
|
+use General\Models\LandingPage\LandingPageLink;
|
|
|
|
+use General\Models\LandingPage\LandingPageLinkLog;
|
|
|
|
+use App\Modules\OfficialAccount\Models\OfficialAccount;
|
|
|
|
+use General\Models\Report\BaiDuAdAccount;
|
|
|
|
+use General\Models\Report\ReportUserBindRecord;
|
|
|
|
+use General\Models\Report\ReportUserChargeRecord;
|
|
|
|
+use General\Services\Report\BaseReport;
|
|
|
|
+use General\Services\Config\ConfigService;
|
|
|
|
+use GuzzleHttp\Client;
|
|
|
|
+use Illuminate\Support\Collection;
|
|
|
|
+use Illuminate\Support\Facades\DB;
|
|
|
|
+use Redis;
|
|
|
|
+
|
|
|
|
+class LandingPageLinkService
|
|
|
|
+{
|
|
|
|
+ /**
|
|
|
|
+ * 新建状态
|
|
|
|
+ */
|
|
|
|
+ const NEW_STATUS = 1;
|
|
|
|
+ /**
|
|
|
|
+ * 待审核
|
|
|
|
+ */
|
|
|
|
+ const WAITTING_APPROVE_STATUS = 2;
|
|
|
|
+ /**
|
|
|
|
+ * 审核通过
|
|
|
|
+ */
|
|
|
|
+ const APPROVED_STATUS = 3;
|
|
|
|
+ /**
|
|
|
|
+ * 审核未通过
|
|
|
|
+ */
|
|
|
|
+ const UNAPPROVED_STATUS = 4;
|
|
|
|
+
|
|
|
|
+ /**
|
|
|
|
+ * 按付费时间回传
|
|
|
|
+ */
|
|
|
|
+ const COMMON = 'common';
|
|
|
|
+ /**
|
|
|
|
+ * 回传关注当天注册且充值用户
|
|
|
|
+ */
|
|
|
|
+ const CURRENT_DAY_REGISTER = 'current_day_register';
|
|
|
|
+ /**
|
|
|
|
+ * 按注册时间回传
|
|
|
|
+ */
|
|
|
|
+ const REGISTER_TIME_RETURN = 'register_time_return';
|
|
|
|
+ /**
|
|
|
|
+ * 注册24小时之内充值
|
|
|
|
+ */
|
|
|
|
+ const REGISTER_24_CHARGE = 'register_24_charge';
|
|
|
|
+ /**
|
|
|
|
+ * 回传类型
|
|
|
|
+ */
|
|
|
|
+ const REPORT_TYPE = [
|
|
|
|
+ self::COMMON,
|
|
|
|
+ self::CURRENT_DAY_REGISTER,
|
|
|
|
+ self::REGISTER_TIME_RETURN,
|
|
|
|
+ self::REGISTER_24_CHARGE,
|
|
|
|
+ ];
|
|
|
|
+
|
|
|
|
+ const tiktok = 'tiktok';
|
|
|
|
+ const iqiyi = 'iqiyi';
|
|
|
|
+ const uc = 'uc';
|
|
|
|
+ const weibo = 'weibo';
|
|
|
|
+ const tencent = 'tencent';
|
|
|
|
+ const kuaishou = 'kuaishou';
|
|
|
|
+ const vivo = 'vivo';
|
|
|
|
+ const baidu = 'baidu';
|
|
|
|
+
|
|
|
|
+ const link_source_array = [
|
|
|
|
+ self::tiktok,
|
|
|
|
+ self::iqiyi,
|
|
|
|
+ self::uc,
|
|
|
|
+ self::weibo,
|
|
|
|
+ self::tencent,
|
|
|
|
+ self::kuaishou,
|
|
|
|
+ self::vivo,
|
|
|
|
+ self::baidu,
|
|
|
|
+ ];
|
|
|
|
+
|
|
|
|
+ public static function saveLink(array $data)
|
|
|
|
+ {
|
|
|
|
+ if (isset($data['id'])) {
|
|
|
|
+ $data['updated_at'] = now();
|
|
|
|
+ return LandingPageLink::updateOrCreate(['id' => $data['id']], $data);
|
|
|
|
+ } else {
|
|
|
|
+ return LandingPageLink::create($data);
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ public static function deleteLink(int $id)
|
|
|
|
+ {
|
|
|
|
+ LandingPageLink::where('id', $id)->delete();
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ public static function updateLinkStatus(int $id, int $status, string $remark)
|
|
|
|
+ {
|
|
|
|
+ if ($status) {
|
|
|
|
+ self::saveLink(['id' => $id, 'status' => $status, 'remark' => $remark]);
|
|
|
|
+ LandingPageLinkLog::create(['link_id' => $id, 'status' => $status, 'remark' => $remark]);
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ public static function findLinks(array $query_params = [], bool $is_page = false)
|
|
|
|
+ {
|
|
|
|
+ $sql = LandingPageLink::orderBy('id', 'desc');
|
|
|
|
+ if (isset($query_params['name']) && $query_params['name']) {
|
|
|
|
+ $sql->where('name', 'like', $query_params['name'] . '%');
|
|
|
|
+ }
|
|
|
|
+ if (isset($query_params['gzh_name']) && $query_params['gzh_name']) {
|
|
|
|
+ $sql->where('gzh_name', 'like', $query_params['gzh_name'] . '%');
|
|
|
|
+ }
|
|
|
|
+ if (isset($query_params['gzh_code']) && $query_params['gzh_code']) {
|
|
|
|
+ $sql->where('gzh_code', $query_params['gzh_code']);
|
|
|
|
+ }
|
|
|
|
+ if (isset($query_params['status']) && $query_params['status']) {
|
|
|
|
+ $sql->where('status', $query_params['status']);
|
|
|
|
+ }
|
|
|
|
+ if (isset($query_params['channel_id']) && $query_params['channel_id']) {
|
|
|
|
+ $sql->where('channel_id', $query_params['channel_id']);
|
|
|
|
+ }
|
|
|
|
+ if ($is_page) {
|
|
|
|
+ return $sql->paginate(20);
|
|
|
|
+ } else {
|
|
|
|
+ return $sql->get();
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ public static function findDomains()
|
|
|
|
+ {
|
|
|
|
+ return LandingPageDomain::where('is_enabled', 1)->get();
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ public static function findOfficialAccounts(int $distribution_channel_id)
|
|
|
|
+ {
|
|
|
|
+ return OfficialAccount::select('nickname', 'appid', 'alias', 'head_img')
|
|
|
|
+ ->where('distribution_channel_id', $distribution_channel_id)
|
|
|
|
+ ->where('is_auth', 1)
|
|
|
|
+ ->where('is_enabled', 1)
|
|
|
|
+ ->get();
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ /**
|
|
|
|
+ * 获取付费回传配置信息
|
|
|
|
+ */
|
|
|
|
+ public static function getChargeFeedBackConfig(int $channel_id, int $channel_user_id)
|
|
|
|
+ {
|
|
|
|
+ $switch_status = (new NormalChargeFeedBack)->getSwitchStatus($channel_id);
|
|
|
|
+ $orange_switch_status = (new OrangeChargeFeedBack)->getSwitchStatus($channel_id);
|
|
|
|
+ $type = Redis::hGet('channel:setting:' . $channel_id, 'tiktok_report_type') ?? self::CURRENT_DAY_REGISTER;
|
|
|
|
+ $service = new ConfigService;
|
|
|
|
+ $source = BaseConst::Platform;
|
|
|
|
+ $result = [
|
|
|
|
+ 'orange_switch_status' => $orange_switch_status,
|
|
|
|
+ 'switch_status' => $switch_status,
|
|
|
|
+ 'type' => $type,
|
|
|
|
+ 'weibo_monitor_link' => "https://newtrack.zhuishuyun.com/?dycallback=3&channel_id={$channel_id}&source={$source}&ip={ip}&ua={ua}&clicktime={clicktime}&IMP={IMP}&ad_id={ad_id}&creative_id={creative_id}",
|
|
|
|
+ 'kuaishou_monitor_link' => "https://newtrack.zhuishuyun.com/?dycallback=6&channel_id={$channel_id}&source={$source}&aid=__AID__&dname=__DNAME__&cid=__CID__&imei=__IMEI__&androidid=__ANDROIDID2__&oaid=__OAID__&mac=__MAC__&ip=__IP__&ua=__UA__&ts=__TS__&callback=__CALLBACK__&imei=__IMEI2__&os=__OS__&did=__DID__&accountid=__ACCOUNTID__&csite=__CSITE__"
|
|
|
|
+ ];
|
|
|
|
+ $is_open = $service->hasAuth($channel_user_id, 'platform_charge_percent_report');
|
|
|
|
+ if ($is_open) {
|
|
|
|
+ $percent = Redis::hGet('channel:setting:' . $channel_id, 'tiktok_report_percent');
|
|
|
|
+ if ($percent) {
|
|
|
|
+ $percent = json_decode($percent, true);
|
|
|
|
+ $molecule = round($percent['molecule'] / $percent['denominator'] * 100);
|
|
|
|
+ } else {
|
|
|
|
+ $molecule = (int) Redis::hGet('channel:setting:' . $channel_id, 'new_tiktok_report_percent');
|
|
|
|
+ }
|
|
|
|
+ $eligible_count = Redis::hGet('channel:setting:' . $channel_id, 'tiktok_report_eligible_count');
|
|
|
|
+ return array_merge([
|
|
|
|
+ 'molecule' => $molecule,
|
|
|
|
+ 'eligible_count' => $eligible_count,
|
|
|
|
+ ], $result);
|
|
|
|
+ }
|
|
|
|
+ return $result;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ private static function getService(bool $is_orange)
|
|
|
|
+ {
|
|
|
|
+ return $is_orange ? new OrangeChargeFeedBack : new NormalChargeFeedBack;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ public static function setSwitchStatus(int $channel_id, int $status, bool $is_orange = false)
|
|
|
|
+ {
|
|
|
|
+ self::getService($is_orange)->setSwitchStatus($channel_id, $status);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ public static function syncSwitchStatus(array $channel_ids, int $status, bool $is_orange = false)
|
|
|
|
+ {
|
|
|
|
+ self::getService($is_orange)->syncSwitchStatus($channel_ids, $status);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ public static function findUserReportInfos(int $channel_id, array $params, bool $is_page = true)
|
|
|
|
+ {
|
|
|
|
+ $sql = Order::where('distribution_channel_id', $channel_id)
|
|
|
|
+ ->where('status', 'PAID')
|
|
|
|
+ ->orderBy('id', 'desc');
|
|
|
|
+ if (isset($params['begin_time']) && $params['begin_time']) {
|
|
|
|
+ $sql->where('created_at', '>=', $params['begin_time']);
|
|
|
|
+ }
|
|
|
|
+ if (isset($params['end_time']) && $params['begin_time']) {
|
|
|
|
+ $sql->where('created_at', '<=', $params['end_time']);
|
|
|
|
+ }
|
|
|
|
+ if (isset($params['uid']) && $params['uid']) {
|
|
|
|
+ $sql->where('uid', $params['uid']);
|
|
|
|
+ }
|
|
|
|
+ if (isset($params['adid']) && $params['adid']) {
|
|
|
|
+ $sql->whereExists(function ($query) use ($params) {
|
|
|
|
+ $query->select(DB::raw(1))
|
|
|
|
+ ->from('report_user_bind_records')
|
|
|
|
+ ->whereRaw('report_user_bind_records.uid = orders.uid')
|
|
|
|
+ ->where('report_user_bind_records.adid', $params['adid']);
|
|
|
|
+ });
|
|
|
|
+ }
|
|
|
|
+ if ($is_page) {
|
|
|
|
+ return $sql->paginate();
|
|
|
|
+ } else {
|
|
|
|
+ return $sql->get();
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ public static function setReportType(int $channel_id, string $type, int $molecule, int $eligible_count)
|
|
|
|
+ {
|
|
|
|
+ if (in_array($type, LandingPageLinkService::REPORT_TYPE)) {
|
|
|
|
+ Redis::hset('channel:setting:' . $channel_id, 'tiktok_report_type', $type);
|
|
|
|
+ Redis::hDel('channel:setting:' . $channel_id, 'tiktok_report_percent');
|
|
|
|
+ Redis::hset('channel:setting:' . $channel_id, 'new_tiktok_report_percent', $molecule);
|
|
|
|
+ Redis::hset('channel:setting:' . $channel_id, 'tiktok_report_eligible_count', $eligible_count);
|
|
|
|
+ $service = new Report;
|
|
|
|
+ $service->report('api/report/config', [
|
|
|
|
+ 'source' => BaseConst::Platform,
|
|
|
|
+ 'channel_id' => $channel_id,
|
|
|
|
+ 'type' => $type,
|
|
|
|
+ 'molecule' => $molecule,
|
|
|
|
+ 'denominator' => 100,
|
|
|
|
+ 'eligible_count' => $eligible_count,
|
|
|
|
+ ]);
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ public static function addBaiduAdAccount(array $data, int $channel_user_id)
|
|
|
|
+ {
|
|
|
|
+ $model = BaiDuAdAccount::create(
|
|
|
|
+ [
|
|
|
|
+ 'account_name' => $data['account_name'],
|
|
|
|
+ 'token' => $data['token'],
|
|
|
|
+ 'channel_user_id' => $channel_user_id,
|
|
|
|
+ 'is_enabled' => 1,
|
|
|
|
+ ]
|
|
|
|
+ );
|
|
|
|
+ self::baiDuAdAccountReport($model);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ public static function delBaiduAdAccount(int $id, int $channel_user_id)
|
|
|
|
+ {
|
|
|
|
+ $model = BaiDuAdAccount::where('id', $id)->where('channel_user_id', $channel_user_id)->first();
|
|
|
|
+ if ($model) {
|
|
|
|
+ $model->is_enabled = 0;
|
|
|
|
+ $model->save();
|
|
|
|
+ self::baiDuAdAccountReport($model);
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ private static function baiDuAdAccountReport(BaiDuAdAccount $model)
|
|
|
|
+ {
|
|
|
|
+ $service = new Report;
|
|
|
|
+ $service->report('api/report/baidu/token', [
|
|
|
|
+ 'source' => BaseConst::Platform,
|
|
|
|
+ 'adid' => $model->id,
|
|
|
|
+ 'token' => $model->token,
|
|
|
|
+ 'is_enabled' => $model->is_enabled,
|
|
|
|
+ ]);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ public static function findBaiduAdAccounts(int $channel_user_id): Collection
|
|
|
|
+ {
|
|
|
|
+ return BaiDuAdAccount::where('is_enabled', 1)->where('channel_user_id', $channel_user_id)->get();
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ public static function reportInstance(bool $is_qapp, string $link_source): BaseReport
|
|
|
|
+ {
|
|
|
|
+ $name = $is_qapp ? 'Qapp' . ucfirst($link_source) . 'Report' : ucfirst($link_source) . 'Report';
|
|
|
|
+ $namespace = "\\General\\Services\\Report\\{$name}";
|
|
|
|
+ $instance = new $namespace;
|
|
|
|
+ return $instance;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ public static function reReport(int $bind_id, float $amount, string $order_no)
|
|
|
|
+ {
|
|
|
|
+ $report_user = ReportUserBindRecord::find($bind_id);
|
|
|
|
+ if ($report_user) {
|
|
|
|
+ $is_qapp = QappUser::where('uid', $report_user->uid)->exists();
|
|
|
|
+ $instance = self::reportInstance($is_qapp, $report_user->platform);
|
|
|
|
+ $result = $instance->reportCharge($report_user, $amount);
|
|
|
|
+ ReportUserChargeRecord::updateOrCreate(
|
|
|
|
+ [
|
|
|
|
+ 'order_no' => $order_no,
|
|
|
|
+ ],
|
|
|
|
+ [
|
|
|
|
+ 'uid' => $report_user->uid,
|
|
|
|
+ 'status' => $result['result'],
|
|
|
|
+ 'content' => $result['result'] ? '手动回传' : $result['content'],
|
|
|
|
+ ]
|
|
|
|
+ );
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+/**
|
|
|
|
+ * 橙子建站回传
|
|
|
|
+ */
|
|
|
|
+class OrangeChargeFeedBack extends ChargeFeedBack
|
|
|
|
+{
|
|
|
|
+ public function __construct()
|
|
|
|
+ {
|
|
|
|
+ $this->type = 'orange_site_report';
|
|
|
|
+ parent::__construct();
|
|
|
|
+ }
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+/**
|
|
|
|
+ * 一般回传
|
|
|
|
+ */
|
|
|
|
+class NormalChargeFeedBack extends ChargeFeedBack
|
|
|
|
+{
|
|
|
|
+ public function __construct()
|
|
|
|
+ {
|
|
|
|
+ $this->type = 'tiktok_report';
|
|
|
|
+ parent::__construct();
|
|
|
|
+ }
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+/**
|
|
|
|
+ * 付费回传
|
|
|
|
+ */
|
|
|
|
+class ChargeFeedBack
|
|
|
|
+{
|
|
|
|
+ protected $service;
|
|
|
|
+ protected $type;
|
|
|
|
+
|
|
|
|
+ public function __construct()
|
|
|
|
+ {
|
|
|
|
+ $this->service = new ConfigService;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ /**
|
|
|
|
+ * 设置开关状态
|
|
|
|
+ */
|
|
|
|
+ public function setSwitchStatus(int $channel_id, int $status)
|
|
|
|
+ {
|
|
|
|
+ $this->service->saveConfig($channel_id, $this->type, $status);
|
|
|
|
+ Redis::hSet('channel:setting:' . $channel_id, $this->type, $status);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ /**
|
|
|
|
+ * 获取开关状态
|
|
|
|
+ */
|
|
|
|
+ public function getSwitchStatus(int $channel_id)
|
|
|
|
+ {
|
|
|
|
+ $status = Redis::hGet('channel:setting:' . $channel_id, $this->type);
|
|
|
|
+ if (!$status) {
|
|
|
|
+ $status = $this->service->hasAuth($channel_id, $this->type);
|
|
|
|
+ if ($status) {
|
|
|
|
+ $this->setSwitchStatus($channel_id, $status);
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ return $status;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ /**
|
|
|
|
+ * 同步开关状态
|
|
|
|
+ */
|
|
|
|
+ public function syncSwitchStatus(array $channel_ids, int $status)
|
|
|
|
+ {
|
|
|
|
+ foreach ($channel_ids as $channel_id) {
|
|
|
|
+ $this->setSwitchStatus($channel_id, $status);
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+class Report
|
|
|
|
+{
|
|
|
|
+ public function report(string $path, array $query_params)
|
|
|
|
+ {
|
|
|
|
+ $client = new Client(['timeout' => 3]);
|
|
|
|
+ $query_params['sign'] = _sign($query_params, BaseConst::TIKTOK_KEY);
|
|
|
|
+ try {
|
|
|
|
+ $response = $client->post(env('TRACK_API_DOMAIN') . '/' . $path, ['form_params' => $query_params]);
|
|
|
|
+ if ($response->getStatusCode() == 200) {
|
|
|
|
+ $result = $response->getBody()->getContents();
|
|
|
|
+ myLog('track_api')->info($result);
|
|
|
|
+ return json_decode($result, true);
|
|
|
|
+ } else {
|
|
|
|
+ return [];
|
|
|
|
+ }
|
|
|
|
+ } catch (Exception $e) {
|
|
|
|
+ myLog('track_api')->error($e->getMessage());
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+}
|