Bläddra i källkod

Merge branch 'liuzj-permission-dev' into test

liuzejian 1 år sedan
förälder
incheckning
ed54edb64f

+ 5 - 0
app/Console/Commands/Callback/JuliangAccountRateConfigRefresh.php

@@ -70,6 +70,11 @@ class JuliangAccountRateConfigRefresh extends Command
             DB::table('juliang_account_rate_config_log')
                 ->where(['company_uid' => $item->company_uid, 'account_id' => $item->account_id, 'is_enabled' => 1])
                 ->update(['is_enabled' => 0, 'updated_at' => $now]);
+            DB::table('juliang_account_promotion_protect_record')
+                ->where('optimizer_uid', $item->company_uid)
+                ->whereIn('advertiser_id', $item->account_id)
+                ->where('is_enabled', 1)
+                ->update(['is_enabled' => 0, 'updated_at' => $now]);
             DB::table('juliang_account_rate_config_log')
                 ->insert([
                     'company_uid' => $item->company_uid,

+ 116 - 0
modules/Callback/Http/Controllers/CallbackLogController.php

@@ -0,0 +1,116 @@
+<?php
+
+namespace Modules\Callback\Http\Controllers;
+
+use Catch\Base\CatchController;
+use Illuminate\Foundation\Validation\ValidatesRequests;
+use Illuminate\Http\Request;
+use Illuminate\Support\Facades\DB;
+use Modules\Callback\Services\TiktokEventReportService;
+use Modules\Common\Errors\Errors;
+use Modules\Common\Exceptions\CommonBusinessException;
+
+class CallbackLogController extends CatchController
+{
+    use ValidatesRequests;
+
+    /**
+     * 回传日志列表
+     * @param Request $request
+     * @return \Illuminate\Contracts\Pagination\LengthAwarePaginator|\Illuminate\Support\Collection
+     */
+    public function list(Request $request) {
+        $advertiserId = $request->input('advertiser_id');
+        $uid = $request->input('uid');
+        $advPromotionId = $request->input('adv_promotion_id');
+        $userRanseStartAtBeginTime = $request->input('user_ranse_start_at_begin_time');
+        $userRanseStartAtEndTime = $request->input('user_ranse_start_at_end_time');
+        $orderCreatedAtBeginTime = $request->input('order_created_at_begin_time');
+        $orderCreatedAtEndTime = $request->input('order_created_at_end_time');
+        $isExport = $request->input('is_export', false);
+
+        $sql = DB::table('callback_report_charge_record')
+            ->where([
+                'optimizer_uid' => $this->getLoginUserId()
+            ])->when($advertiserId, function ($query, $advertiserId) {
+                return $query->where('advertiser_id', $advertiserId);
+            })->when($uid, function ($query, $uid) {
+                return $query->where('uid', $uid);
+            })->when($advPromotionId, function ($query, $advPromotionId){
+                return $query->where('adv_promotion_id', $advPromotionId);
+            })->when($userRanseStartAtBeginTime, function ($query, $userRanseStartAtBeginTime){
+                return $query->where('user_ranse_start_at', '>=', $userRanseStartAtBeginTime);
+            })->when($userRanseStartAtEndTime, function ($query, $userRanseStartAtEndTime){
+                return $query->where('user_ranse_start_at', '<=', $userRanseStartAtEndTime);
+            })->when($orderCreatedAtBeginTime, function ($query, $orderCreatedAtBeginTime){
+                return $query->where('order_created_at', '>=', $orderCreatedAtBeginTime);
+            })->when($orderCreatedAtEndTime, function ($query, $orderCreatedAtEndTime) {
+                return $query->where('order_created_at', '<=', $orderCreatedAtEndTime);
+            });
+        if($isExport) {
+            $result = $sql->get();
+        } else {
+            $result = $sql->paginate($request->integer('limit', 15));
+        }
+        $advertisers = DB::table('juliang_account_callback_config')
+            ->where('company_uid', $this->getLoginUserId())
+            ->select('adv_account_id', 'adv_account_name')
+            ->get()->keyBy('adv_account_id');
+        $reportSuccessStr = [
+            0 => '回传失败',
+            1 => '回传成功',
+            2 => '补传成功',
+        ];
+        foreach ($result as $item) {
+            $item->advertiser_name = $advertisers->get($item->advertiser_id ?? -1)->adv_account_name ?? '';
+            if('ok' == $item->filter_type ) {
+                $item->filter_reason .= '-'. $reportSuccessStr[$item->report_success] ?? '';
+            }
+        }
+
+        return $result;
+    }
+
+    /**
+     * 补传
+     * @param Request $request
+     * @return string
+     * @throws \Illuminate\Validation\ValidationException
+     */
+    public function callbackAgain(Request $request) {
+        $this->validate($request, ['log_id' => 'required']);
+        $logId = $request->integer('log_id');
+
+        $record = DB::table('callback_report_charge_record')
+            ->where('id', $logId)
+            ->select('report_param')
+            ->first();
+        if(!$record || !$record->report_param) {
+            CommonBusinessException::throwError(Errors::CALLBACK_RECORD_NOT_EXISTS);
+        }
+
+        $requestInfo = \json_decode($record->report_param);
+        if(!$requestInfo) {
+            CommonBusinessException::throwError(Errors::CALLBACK_RECORD_LOG_ERROR);
+        }
+
+        $reportService = new TiktokEventReportService();
+        $result = $reportService->reportCharge($requestInfo);
+        $reportSuccess = 0;
+        if($result['result']) {
+            $resultContent = \json_decode($result['content'], true);
+            if(0 == $resultContent['code']) {
+                $reportSuccess = 2;
+            }
+        }
+        DB::table('callback_report_charge_record')
+            ->where('id', $logId)
+            ->update([
+                'report_result' => \json_encode($result),
+                'report_success' => $reportSuccess,
+                'updated_at' => date('Y-m-d H:i:s')
+            ]);
+
+        return 2 == $reportSuccess ? '补传成功' : '补传失败';
+    }
+}

+ 5 - 0
modules/Callback/Http/Controllers/JuliangAccountController.php

@@ -117,6 +117,11 @@ class JuliangAccountController extends CatchController
                 ->whereIn('account_id', $advAccountIds)
                 ->where('is_enabled', 1)
                 ->update(['is_enabled' => 0, 'updated_at' => $now]);
+            DB::table('juliang_account_promotion_protect_record')
+                ->where('optimizer_uid', $this->getOptimizerUid())
+                ->whereIn('advertiser_id', $advAccountIds)
+                ->where('is_enabled', 1)
+                ->update(['is_enabled' => 0, 'updated_at' => $now]);
             foreach ($advAccountIds as $accountId) {
                 DB::table('juliang_account_rate_config_log')
                     ->insert([

+ 152 - 0
modules/Callback/Services/TiktokEventReportService.php

@@ -0,0 +1,152 @@
+<?php
+
+namespace Modules\Callback\Services;
+
+use Exception;
+use GuzzleHttp\Client;
+
+/**
+ * 抖音数据回调---新版---使用事件管理模式
+ * ios加桌和普通抖音事件管理是一个回传逻辑
+ * 开发文档:https://event-manager.oceanengine.com/docs/8650/h5_api_docs/
+ */
+class TiktokEventReportService
+{
+    /**
+     * 充值用户事件类型
+     */
+    protected $charge_event_type = 'active_pay';
+    /**
+     * 注册用户事件类型
+     */
+    protected $register_event_type = 'active_register';
+    /**
+     * 激活事件类型
+     */
+    protected $active_event_type = 'active';
+    /**
+     * 次留事件类型
+     */
+    protected $rentention_event_type = 'next_day_open';
+    /**
+     * 付费ROI事件类型
+     */
+    protected $purchase_roi_event_type = 'purchase_roi';
+
+
+    /**
+     * 充值用户数据上报地址
+     */
+    protected $report_url = 'https://analytics.oceanengine.com/api/v2/conversion';
+
+    private $user;
+
+    public function __construct()
+    {
+
+    }
+
+    /**
+     * 付费上报
+     */
+    public function reportCharge($user, $amount=0)
+    {
+        return $this->report($this->report_url, [
+            'event_type' => $this->charge_event_type,
+            'context' => [
+                'ad' => [
+                    'callback' => $user->callback
+                ]
+            ],
+            'timestamp' => time()
+        ]);
+    }
+
+    /**
+     * 注册上报
+     */
+    public function reportRegister(DouyinUser $user)
+    {
+        return $this->report($this->report_url, [
+            'event_type' => $this->register_event_type,
+            'context' => [
+                'ad' => [
+                    'callback' => $user->callback
+                ]
+            ],
+            'timestamp' => time()
+        ]);
+    }
+
+    /**
+     * 次日留存上报
+     */
+    public function reportRentention()
+    {
+        return $this->report($this->report_url, [
+            'event_type' => $this->rentention_event_type,
+            'context' => [
+                'ad' => [
+                    'callback' => $this->user->callback
+                ]
+            ],
+            'timestamp' => time()
+        ]);
+    }
+
+    public function reportAddDesktop()
+    {
+        return [];
+    }
+
+    /**
+     * 激活上报
+     */
+    public function reportActive($user)
+    {
+        return $this->report($this->report_url, [
+            'event_type' => $this->active_event_type,
+            'context' => [
+                'ad' => [
+                    'callback' => $user->callback
+                ]
+            ],
+            'timestamp' => time()
+        ]);
+    }
+
+    /**
+     * 数据上报
+     */
+    public function report(string $url, array $query_params)
+    {
+        $result = false;
+        $content = '';
+        try {
+            myLog('tiktok_event_report')->info('report_param_event_tiktok:' . json_encode($query_params));
+
+            $client = new Client(['timeout' => 4]);
+            $response = $client->request('post', $url, ['json' => $query_params]);
+
+            $content = $response->getBody()->getContents();
+            myLog('tiktok_event_report')->info('report_result_event_tiktok:' . json_encode($content, true));
+
+            $status_code = $response->getStatusCode();
+            if ($status_code == 200) {
+                $result = true;
+            } else {
+                $result = false;
+            }
+        } catch (Exception $e) {
+            myLog('tiktok_event_report')->error('event_tiktok_ept:' . json_encode($query_params) . ' ept:' . $e->getMessage());
+        } finally {
+            $query_params['report_url'] = $url;
+            return [
+                'result' => $result,
+                'content' => $content,
+                'query_params' => $query_params,
+            ];
+        }
+    }
+
+}

+ 3 - 0
modules/Callback/routes/route.php

@@ -1,6 +1,7 @@
 <?php
 
 use Illuminate\Support\Facades\Route;
+use Modules\Callback\Http\Controllers\CallbackLogController;
 use Modules\Callback\Http\Controllers\JuliangAccountController;
 
 Route::prefix('callback')->group(function () {
@@ -8,6 +9,8 @@ Route::prefix('callback')->group(function () {
         Route::get('list', [JuliangAccountController::class, 'list']);
         Route::post('addAccount', [JuliangAccountController::class, 'addAccount']);
         Route::post('updateCallbackConfig', [JuliangAccountController::class, 'updateCallbackConfig']);
+        Route::get('log/list', [CallbackLogController::class, 'list']);
+        Route::post('log/callbackAgain', [CallbackLogController::class, 'callbackAgain']);
     });
 });
 

+ 2 - 0
modules/Common/Errors/Errors.php

@@ -19,4 +19,6 @@ class Errors
     public const  UPLOAD_IMAGE_ERROR= [500006, '上传图片不成功'];
     public const  JULIANG_ACCOUNT_EXISTS= [500101, '巨量广告账户已经存在'];
     public const  CALLBACK_RATE_TIME_RANGE_ERROR= [500102, '回传比例时间区间不合法'];
+    public const  CALLBACK_RECORD_NOT_EXISTS= [500103, '回传日志不存在'];
+    public const  CALLBACK_RECORD_LOG_ERROR= [500104, '回传日志补传信息缺失'];
 }

+ 28 - 0
tests/Callback/Http/Controllers/CallbackLogControllerTest.php

@@ -0,0 +1,28 @@
+<?php
+
+namespace Tests\Callback\Http\Controllers;
+
+use Modules\Callback\Http\Controllers\CallbackLogController;
+use PHPUnit\Framework\TestCase;
+use Tests\UsedTestCase;
+
+class CallbackLogControllerTest extends UsedTestCase
+{
+    public function testList()
+    {
+        $res = $this->withHeaders([
+            'Authorization' => 'Bearer '. $this->token,
+        ])->json('get','http://localhost/api/callback/juliangAccount/log/list', []);
+        $this->dumpJson($res);
+    }
+
+    public function testCallbackAgain() {
+        $id = 1004;
+        $res = $this->withHeaders([
+            'Authorization' => 'Bearer '. $this->token,
+        ])->json('post','http://localhost/api/callback/juliangAccount/log/callbackAgain', [
+            'log_id'=> $id,
+        ]);
+        $res->dump();
+    }
+}

+ 4 - 4
tests/Callback/Http/Controllers/JuliangAccountControllerTest.php

@@ -36,11 +36,11 @@ class JuliangAccountControllerTest extends UsedTestCase
         ])->json('post','http://localhost/api/callback/juliangAccount/updateCallbackConfig', [
             'ids' => [4],
             'state' => 0,
-            'protect_num' => 3,
-            'default_rate' => 44,
+            'protect_num' => 2,
+            'default_rate' => 30,
             'rate_time_config' => [
-                ['start_time' => '15:00', 'end_time' => '15:10', 'config_per' => 40],
-                ['start_time' => '15:20', 'end_time' => '15:30', 'config_per' => 56],
+                ['start_time' => '15:00', 'end_time' => '16:10', 'config_per' => 20],
+                ['start_time' => '16:20', 'end_time' => '19:30', 'config_per' => 50],
             ],
             'min_money' => 40,
             'max_money' => 60,

+ 2 - 2
tests/UsedTestCase.php

@@ -13,11 +13,11 @@ abstract class UsedTestCase extends BaseTestCase
     {
         parent::setUp(); // TODO: Change the autogenerated stub
         $tokenInfo = $this->post('http://localhost/api/login', [
-            'email' => 'catch@admin.com',
+//            'email' => 'catch@admin.com',
             'remember' => false,
 //            'email' => 'xiaoli@qq.com',
             'password' => 'catchadmin',
-//            'email' => 'aa@test.com',
+            'email' => 'aa@test.com',
         ])->json();
         $this->token = $tokenInfo['data']['token'];
     }