21 Commits c264326af7 ... 5c35eae5b9

Tác giả SHA1 Thông báo Ngày
  zhaoyang 5c35eae5b9 异常上报 1 năm trước cách đây
  zhaoyang 7985ad00e7 异常上报 1 năm trước cách đây
  liuzejian 032c8635a9 REDIS_CLIENT=predis 1 năm trước cách đây
  liuzejian 8ee972bb23 短剧点击人数统计 1 năm trước cách đây
  liuzejian 36d036ce21 短剧点击人数统计 1 năm trước cách đây
  liuzejian e49db011dc 短剧点击人数统计 1 năm trước cách đây
  liuzejian 7bb23f3d00 删除测试条件 1 năm trước cách đây
  liuzejian c1f30195bb 更新回传比例 1 năm trước cách đây
  liuzejian a9561fc2bb 巨量2.0事件回传 1 năm trước cách đây
  liuzejian 53d8689344 修正代码导入和变量定义 1 năm trước cách đây
  liuzejian 5f960d8d5f Merge branch 'liuzj-wechat-check-dev' into stable 1 năm trước cách đây
  zhaoyang daecccc316 短剧统计 1 năm trước cách đây
  zhaoyang a9b2f9d6d5 短剧统计commadn 1 năm trước cách đây
  zhaoyang ee93cbd504 短剧统计 1 năm trước cách đây
  liuzejian fa7257fb27 log config 1 năm trước cách đây
  liuzejian e1b98debd1 Merge branch 'stable' into liuzj-test 1 năm trước cách đây
  liuzejian f453174477 Merge branch 'stable' into liuzj-test 1 năm trước cách đây
  liuzejian b18c6fc0b1 兼容推广被禁用的情况 1 năm trước cách đây
  liuzejian 5058133a0e remove log 1 năm trước cách đây
  liuzejian 97a8c16d0a log 1 năm trước cách đây
  liuzejian bf1712d1e8 创建 track 表 1 năm trước cách đây
29 tập tin đã thay đổi với 1408 bổ sung340 xóa
  1. 1 1
      app/Console/Commands/CallBack/CreateTrackTable.php
  2. 5 6
      app/Console/Commands/Miniprogram/WechatAccessToken.php
  3. 160 0
      app/Console/Commands/Stats/MiniprogramStats.php
  4. 87 0
      app/Console/Commands/Video/WechatCheck/GetTaskInfo.php
  5. 88 0
      app/Console/Commands/Video/WechatCheck/SyncDramaInfo.php
  6. 92 0
      app/Console/Commands/Video/WechatCheck/SyncMediaInfo.php
  7. 15 1
      app/Console/Kernel.php
  8. 1 1
      app/Exceptions/Handler.php
  9. 0 249
      app/Jobs/Callback/RechargeReport.php
  10. 15 1
      app/Jobs/Callback/ReportCharge.php
  11. 126 0
      app/Jobs/Video/WechatCheck.php
  12. 61 0
      app/Libs/Helpers.php
  13. 13 0
      app/Models/VideoStatByCompany.php
  14. 13 0
      app/Models/VideoStatByUser.php
  15. 375 0
      app/Service/Callback/JLEventReportChargeService.php
  16. 13 1
      app/Service/Callback/JuliangAccountReportChargeService.php
  17. 14 0
      app/Service/Callback/Tiktok/TiktokEventReportService.php
  18. 4 14
      app/Service/Miniprogram/Wechat/AccessTokenService.php
  19. 49 0
      app/Service/Stats/MiniprogramStatService.php
  20. 81 0
      app/Service/Util/Support/Http/HttpRequestService.php
  21. 19 0
      app/Service/Util/Support/Http/WechatURL.php
  22. 10 0
      app/Service/Video/WechatCheck/DramaInfoService.php
  23. 10 2
      config/database.php
  24. 1 1
      config/logging.php
  25. 6 0
      config/queue.php
  26. 8 0
      config/wechat.php
  27. 63 63
      tests/Jobs/Callback/ReportChargeTest.php
  28. 23 0
      tests/Jobs/Video/WechatCheckTest.php
  29. 55 0
      tests/Service/Callback/JLEventReportChargeServiceTest.php

+ 1 - 1
app/Console/Commands/CallBack/CreateTrackTable.php

@@ -42,7 +42,7 @@ class CreateTrackTable extends Command
         $month = $this->option('month');
         $month = $month ? $month : date('Ym', strtotime('+1 month'));
         $track_table = 'douyin_tracks' . $month;
-        $trackConn = Schema::connection('track');
+        $trackConn = Schema::connection('track_record');
         if (!$trackConn->hasTable($track_table)) {
             $trackConn->create($track_table, function (Blueprint $table) {
                 $table->increments('id');

+ 5 - 6
app/Console/Commands/Miniprogram/WechatAccessToken.php

@@ -46,13 +46,12 @@ class WechatAccessToken extends Command
             if($ttl > 600) {
                 continue;
             }
-            try {
-                $accessTokenInfo = AccessTokenService::getAccessToken($miniprogram->appid, $miniprogram->appsecret);
-            } catch (\Exception $exception) {
-                myLog('wechat-miniprogram')->info('刷新小程序accessToken失败', [
+
+            $accessTokenInfo = AccessTokenService::getAccessToken($miniprogram->appid, $miniprogram->appsecret);
+            if(false === $accessTokenInfo || (0 != ($accessTokenInfo['errcode'] ?? 0))) {
+                myLog('WechatAccessToken')->info('刷新小程序accessToken失败', [
                     'appid' => $miniprogram->appid,
-                    'exceptionMessage' => $exception->getMessage(),
-                    'exceptionCode' => $exception->getCode()
+                    'result' => $accessTokenInfo,
                 ]);
                 continue;
             }

+ 160 - 0
app/Console/Commands/Stats/MiniprogramStats.php

@@ -0,0 +1,160 @@
+<?php
+namespace App\Console\Commands\Stats;
+
+
+use App\Models\User;
+use App\Models\VideoStatByCompany;
+use App\Models\VideoStatByUser;
+use App\Service\Stats\MiniprogramStatService;
+use Illuminate\Console\Command;
+use Illuminate\Support\Facades\DB;
+use Illuminate\Support\Facades\Redis;
+
+class MiniprogramStats extends Command{
+        /**
+     * The name and signature of the console command.
+     *
+     * @var string
+     */
+    protected $signature = 'Stats:MiniprogramStats {--day= : 日期}';
+
+    /**
+     * The console command description.
+     *
+     * @var string
+     */
+    protected $description = '短剧统计';
+
+    private $day;
+
+    /**
+     * Execute the console command.
+     */
+    public function handle(){
+        $day = $this->option('day');
+        if($day) {
+            $this->day = $day;
+        } else {
+            $this->day = date('Y-m-d',time()-86400);
+        }
+        $this->processUser();
+        $this->processCompany();
+    }
+
+    /**
+     * 公司级别统计
+     *
+     * @return void
+     */
+    private function processCompany(){
+        VideoStatByCompany::where('day',$this->day)->update(['is_delete'=>1]);
+        $sql = <<<EDF
+insert into video_stat_by_company(`day`,user_id,video_id,video_name,amount,charge_count,charge_user_num,play_count,created_at,updated_at)
+select '%s' as `date`,puser_id,video_id,video_name,sum(amount),sum(charge_count),sum(charge_user_num),sum(play_count),now(),now() FROM video_stat_by_user where `day`='%s' group by puser_id,video_id,video_name
+EDF;
+        $sql = sprintf($sql,$this->day,$this->day);
+        DB::insert($sql);
+
+        $iterator = 0;
+        $match = sprintf('djClickUv.%s.*', $this->day);
+        $now = date('Y-m-d H:i:s');
+        do {
+            list($iterator, $keys) = Redis::scan($iterator, 'match', $match, 'count', 1000);
+            foreach ($keys as $key) {
+                $arr = explode('.', $key);
+                $count = Redis::pfcount($key);
+                if(DB::table('video_stat_by_company')
+                    ->where([
+                        ['user_id', '=', $arr[3]],
+                        ['video_id', '=', $arr[2]],
+                        ['is_delete', '=', 0],
+                        ['day','=', $this->day]
+                    ])->exists()) {
+                    DB::table('video_stat_by_company')
+                        ->where([
+                            ['user_id', '=', $arr[3]],
+                            ['video_id', '=', $arr[2]],
+                            ['is_delete', '=', 0],
+                            ['day','=', $this->day]
+                        ])->update([
+                            'click_uv' => $count, 'updated_at' => $now,
+                        ]);
+                } else {
+                    DB::table('video_stat_by_company')
+                        ->insert([
+                            'user_id' => $arr[3],
+                            'video_id' => $arr[2],
+                            'video_name' => DB::table('videos')->where('id', $arr[2])->value('name') ?? '',
+                            'day' => $this->day,
+                            'click_uv' => $count,
+                            'created_at' => $now,
+                            'updated_at' => $now,
+                        ]);
+                }
+            }
+        }while($iterator > 0);
+
+    }
+
+    /**
+     * 投手级别统计
+     *
+     * @return void
+     */
+    private function processUser(){
+        $all_optimizer = User::join('user_has_roles','user_has_roles.user_id','=','users.id')
+        ->join('roles','roles.id','=','user_has_roles.role_id')
+        ->where('roles.identify','optimizer')
+        ->select('users.id','users.pid')
+        ->get();
+        $all_video = DB::table('videos')->select('id','name')->get();
+        foreach($all_optimizer as $optimizer_item){
+            foreach($all_video as $video){
+                $this->processUserDetail($optimizer_item->pid,$video->id,$optimizer_item->id,$video->name);
+            }
+        }
+        $all_company = User::join('user_has_roles','user_has_roles.user_id','=','users.id')
+        ->join('roles','roles.id','=','user_has_roles.role_id')
+        ->where('roles.identify','company')
+        ->select('users.id','users.pid')
+        ->get();
+
+        foreach($all_company as $company_item){
+            foreach($all_video as $video){
+                $this->processUserDetail($company_item->id,$video->id,$company_item->id,$video->name);
+            }
+        }
+
+        MiniprogramStatService::deleteAll($this->day);
+    }
+
+    /**
+     * 投手统计详情
+     *
+     * @param integer $puser_id
+     * @param integer $video_id
+     * @param integer $user_id
+     * @param string $video_name
+     * @return void
+     */
+    private function processUserDetail(int $puser_id, int $video_id,int $user_id,string $video_name){
+        $day = $this->day;
+        $stat_data = MiniprogramStatService::getOneItem($video_id,$user_id,$day);
+        if(!$stat_data['amount']  && !$stat_data['charge_count'] && !$stat_data['charge_user_num'] && !$stat_data['play_count']){
+            return ;
+        }
+        $stat_data['amount'] = ((int)($stat_data['amount']))/100;
+        $old_record = VideoStatByUser::where('user_id',$user_id)->where('day',$day)->where('video_id',$video_id)->select('id')->first();
+        if($old_record){
+            VideoStatByUser::where('id',$old_record->id)->update($stat_data);
+        }else{
+            $stat_data['day'] = $day;
+            $stat_data['user_id'] = $user_id;
+            $stat_data['video_name'] = $video_name;
+            $stat_data['video_id'] = $video_id;
+            $stat_data['puser_id'] = $puser_id;
+            VideoStatByUser::create($stat_data);
+        }
+       MiniprogramStatService::deleteCache($video_id,$user_id,$day);
+    }
+}

+ 87 - 0
app/Console/Commands/Video/WechatCheck/GetTaskInfo.php

@@ -0,0 +1,87 @@
+<?php
+
+namespace App\Console\Commands\Video\WechatCheck;
+
+use App\Service\Miniprogram\Wechat\AccessTokenService;
+use App\Service\Util\Support\Http\HttpRequestService;
+use App\Service\Util\Support\Http\WechatURL;
+use Illuminate\Console\Command;
+use Illuminate\Support\Facades\DB;
+use Illuminate\Support\Facades\Redis;
+use Modules\Common\Support\Http\HttpRequest;
+use Modules\Manage\Services\WechatMiniprogramService;
+use Modules\Video\Services\WechatCheckSyncService;
+
+class GetTaskInfo extends Command
+{
+    /**
+     * The name and signature of the console command.
+     *
+     * @var string
+     */
+    protected $signature = 'WechatCheck:GetTaskInfo {--task_ids= : 英文逗号分割的任务id}';
+
+    /**
+     * The console command description.
+     *
+     * @var string
+     */
+    protected $description = '查询短剧同步到微信的任务状态';
+
+    /**
+     * Execute the console command.
+     */
+    public function handle(): void
+    {
+        $task_ids = $this->option('task_ids');
+        $taskIdArr = null;
+        if($task_ids) {
+            $taskIdArr = explode(',', trim($task_ids, ','));
+        }
+        DB::table('video_series_wechat_check')
+            ->whereIn('sync_status', [1,2])
+            ->where('sync_task_id', '<>', '')
+            ->where('is_enabled', 1)
+            ->when($taskIdArr, function ($query, $taskIdArr) {
+                return $query->whereIn('sync_task_id', $taskIdArr);
+            })->orderBy('id')
+            ->chunk(100, function ($items) {
+                $now = date('Y-m-d H:i:s');
+                foreach ($items as $item) {
+                    $taskInfo = $this->getTask($item);
+                    if($taskInfo && 1 == $taskInfo['task_type']) {
+                        if(in_array($taskInfo['status'], [3,4])) {
+                            DB::table('video_series_wechat_check')
+                                ->where(['id' => $item->id])
+                                ->update([
+                                    'status' => $taskInfo['status'],
+                                    'remark' => $taskInfo['errmsg'] ?? '',
+                                    'media_id' => $taskInfo['media_id'] ?? '',
+                                    'updated_at' => $now,
+                                    'sync_task_info' => \json_encode($taskInfo),
+                                ]);
+                        }
+                    }
+                }
+            });
+    }
+
+    private function getTask($syncInfo) {
+        $appid = $syncInfo->appid ?: config('wechat.duanju.masterAppid');
+        $accessToken = Redis::get(AccessTokenService::getAccessTokenRedisKey($appid));
+        $parsedContent = HttpRequestService::simplePost(WechatURL::vod_gettask . $accessToken, [
+            'task_id' => $syncInfo->sync_task_id
+        ]);
+        if(false === $parsedContent || (0 != $parsedContent['errcode'] ?? 0)) {
+            return $parsedContent['task_info'];
+        } else {
+            myLog('GetTaskInfo')->error('拉取上传短剧任务查询失败', [
+                'task_id' => $syncInfo->sync_task_id,
+                'appid' => $appid,
+                'result' => $parsedContent,
+            ]);
+            return [];
+        }
+
+    }
+}

+ 88 - 0
app/Console/Commands/Video/WechatCheck/SyncDramaInfo.php

@@ -0,0 +1,88 @@
+<?php
+
+namespace App\Console\Commands\Video\WechatCheck;
+
+use App\Service\Miniprogram\Wechat\AccessTokenService;
+use App\Service\Util\Support\Http\WechatURL;
+use App\Service\Util\Support\Http\HttpRequestService;
+use Illuminate\Console\Command;
+use Illuminate\Support\Facades\DB;
+
+class SyncDramaInfo extends Command
+{
+    /**
+     * The name and signature of the console command.
+     *
+     * @var string
+     */
+    protected $signature = 'WechatCheck:SyncDramaInfo {--drama_ids= : 剧目ids}';
+
+    /**
+     * The console command description.
+     *
+     * @var string
+     */
+    protected $description = '微信剧目提审-获取剧目信息';
+
+    /**
+     * Execute the console command.
+     */
+    public function handle()
+    {
+        $drama_ids = $this->option('drama_ids');
+        $dramaIds = null;
+        if($drama_ids) {
+            $dramaIds = explode(',', $drama_ids);
+        }
+        DB::table('video_wechat_check')
+            ->when($dramaIds, function ($query, $dramaIds) {
+                return $query->whereIn('drama_id', $dramaIds);
+            })
+            ->where('drama_id', '<>', 0)
+            ->where([
+                'status' => 1,
+                'is_enabled' => 1
+            ])
+            ->select('drama_id', 'id', 'status', 'appid', 'video_id')
+            ->orderBy('id')
+            ->chunk(100, function ($items) {
+                foreach ($items as $item) {
+                    $accessToken = $this->getAccessToken($item->appid ?: config('wechat.duanju.masterAppid'));
+                    $result = HttpRequestService::simplePost(WechatURL::vod_getdrama. $accessToken, [
+                        'drama_id' => $item->drama_id
+                    ]);
+                    if(false === $result || (0 != ($result['errcode'] ?? 0))) {
+                        myLog('SyncDramaInfo')->error('获取剧目信息失败', [
+                            'id' => $item->id, 'drama_id' => $item->drama_id,
+                            'result' => $result,
+                        ]);
+                        continue;
+                    }
+                    $status = $result['drama_info']['audit_detail']['status'];
+                    $now = date('Y-m-d H:i:s');
+                    if($status != $item->status)
+                    {
+                        DB::table('video_wechat_check')
+                            ->where('id', $item->id)
+                            ->update([
+                                'check_at' => date('Y-m-d H:i:s', $result['drama_info']['audit_detail']['audit_time']),
+                                'status' => $status,
+                                'updated_at' => $now,
+                            ]);
+                    }
+                    if(3 == $status) {
+                        DB::table('videos')
+                            ->where('id', $item->video_id)
+                            ->update([
+                                'wechat_pass' => 1,
+                                'updated_at' => $now,
+                            ]);
+                    }
+                }
+            });
+    }
+
+    private function getAccessToken($appid) {
+        return Redis::get(AccessTokenService::getAccessTokenRedisKey($appid));
+    }
+}

+ 92 - 0
app/Console/Commands/Video/WechatCheck/SyncMediaInfo.php

@@ -0,0 +1,92 @@
+<?php
+
+namespace App\Console\Commands\Video\WechatCheck;
+
+use App\Service\Miniprogram\Wechat\AccessTokenService;
+use App\Service\Util\Support\Http\HttpRequestService;
+use App\Service\Util\Support\Http\WechatURL;
+use Illuminate\Console\Command;
+use Illuminate\Support\Facades\DB;
+use Illuminate\Support\Facades\Redis;
+
+class SyncMediaInfo extends Command
+{
+    /**
+     * The name and signature of the console command.
+     *
+     * @var string
+     */
+    protected $signature = 'WechatCheck:SyncMediaInfo {--video_ids= : videos.id}';
+
+    /**
+     * The console command description.
+     *
+     * @var string
+     */
+    protected $description = '获取短剧分集详细信息';
+
+    /**
+     * Execute the console command.
+     */
+    public function handle()
+    {
+        $video_ids = $this->option('video_ids');
+        $videoIds = [];
+        if($video_ids) {
+            $videoIds = explode(',', $video_ids);
+        }
+
+        DB::table('video_wechat_check')
+            ->where('status', '<>', 0)
+            ->where('is_enabled', 1)
+            ->where('drama_id', '<>', 0)
+            ->when($videoIds, function ($query, $videoIds) {
+                return $query->whereIn('video_id', $videoIds);
+            })->select('video_id', 'id', 'drama_id', 'appid')
+            ->orderBy('id')
+            ->chunk(10, function ($items) {
+                foreach ($items as $item) {
+                    $this->syncInfo($item);
+                }
+            });
+    }
+
+    public function syncInfo($item) {
+        $appid = $item->appid ?: config('wechat.duanju.masterAppid');
+        $accessToken = Redis::get(AccessTokenService::getAccessTokenRedisKey($appid));
+        $offset = 0;
+        while (true) {
+            $parsedContent = HttpRequestService::simplePost(WechatURL::vod_listmedia . $accessToken, [
+                'drama_id' => $item->drama_id,
+                'limit' => 100,
+                'offset' => $offset
+            ]);
+            $offset += 100;
+            if(false === $parsedContent || (0 != $parsedContent['errcode'] ?? 0)) {
+                myLog('SyncMediaInfo')->error('拉取短剧分集信息失败', [
+                    'appid' => $appid,
+                    'video_id' => $item->video_id, 'drama_id' => $item->drama_id,
+                ]);
+                break;
+            }
+
+            $media_info_list = $parsedContent['media_info_list'];
+            $now = date('Y-m-d H:i:s');
+            foreach ($media_info_list as $media_info) {
+                $audit_detail = $media_info['audit_detail'];
+                $media_id = $media_info['media_id'];
+                DB::table('video_series_wechat_check')
+                    ->where(['video_id' => $item->video_id, 'is_enabled' => 1, 'media_id' => $media_id])
+                    ->update([
+                        'check_status' => $audit_detail['status'],
+                        'check_at' => date('Y-m-d H:i:s', $audit_detail['audit_time']),
+                        'check_reason' => $audit_detail['check_reason'],
+                        'evidence_material_id_list' => \json_encode($audit_detail['evidence_material_id_list']),
+                        'updated_at' => $now,
+                    ]);
+            }
+
+        }
+
+    }
+}

+ 15 - 1
app/Console/Kernel.php

@@ -16,9 +16,23 @@ class Kernel extends ConsoleKernel
          * 刷新微信小程序的accessToken
          */
         $schedule->command('Miniprogram:WechatAccessToken')->everyMinute();
-        // $schedule->command('inspire')->hourly();
         //每月24号执行创建表
         $schedule->command('create_track_table')->monthlyOn(24);
+
+        //短剧统计
+        $schedule->command('Stats:MiniprogramStats')->dailyAt('03:01');
+        /**
+         * 同步短剧剧目信息
+         */
+        $schedule->command('WechatCheck:SyncDramaInfo')->daily();
+        /**
+         * 同步短剧分集信息
+         */
+        $schedule->command('WechatCheck:SyncMediaInfo')->everySixHours();
+        /**
+         * 检查短剧剧目拉取任务
+         */
+        $schedule->command('WechatCheck:GetTaskInfo')->everyTenMinutes();
     }
 
     /**

+ 1 - 1
app/Exceptions/Handler.php

@@ -24,7 +24,7 @@ class Handler extends ExceptionHandler
     public function register(): void
     {
         $this->reportable(function (Throwable $e) {
-            //
+            dingTalkAlertException($e);
         });
     }
 }

+ 0 - 249
app/Jobs/Callback/RechargeReport.php

@@ -1,249 +0,0 @@
-<?php
-
-namespace App\Jobs\OrangeSite;
-
-use App\Modules\Callback\Models\ChannelCallbackConfig;
-use App\Modules\Callback\Services\CallbackBaseService;
-use App\Modules\OrangeSite\Services\CheckReport\EnableReportCheck;
-use App\Modules\OrangeSite\Services\CheckReport\OrderAlreadyReportCheck;
-use App\Modules\OrangeSite\Services\CheckReport\PromotionProtectCheck;
-use App\Modules\OrangeSite\Services\CheckReport\RechargeAmountCheck;
-use App\Modules\OrangeSite\Services\CheckReport\ReportRateCheck;
-use App\Modules\OrangeSite\Services\CheckReport\ReportRechargeTypeCheck;
-use App\Modules\OrangeSite\Services\OrangeSitePromotionService;
-use App\Modules\OrangeSite\Services\OrangeSiteRechargeReportCheckContext;
-use App\Modules\OrangeSite\Services\OrangeSiteReportRateService;
-use App\Modules\Order\Models\ReportUserChargeRecord;
-use App\Modules\Trace\TraceContext;
-use Illuminate\Bus\Queueable;
-use Illuminate\Contracts\Queue\ShouldQueue;
-use Illuminate\Foundation\Bus\Dispatchable;
-use Illuminate\Pipeline\Pipeline;
-use Illuminate\Queue\InteractsWithQueue;
-use Illuminate\Queue\SerializesModels;
-use Illuminate\Support\Facades\DB;
-
-class RechargeReport implements ShouldQueue
-{
-    use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
-
-    public const QUEUE = '{orangeSite}.report.recharge';
-    public const CONNECTION = 'redis_queue';
-
-    public const PLATFORM = 'orange';
-    /**
-     * @var array
-     * <pre>
-     * [
-     *      'channelId' => 'xxx, // 站点id
-     *      'orderId' => 'xxx', // 订单id
-     *      'uid' => 'xxx', // 充值用户uid
-     * ]
-     * </pre>
-     */
-    private $reportInfo;
-
-    /**
-     * Create a new job instance.
-     *
-     * @return void
-     */
-    public function __construct(array $reportInfo)
-    {
-        $this->reportInfo = $reportInfo;
-    }
-
-    /**
-     * Execute the job.
-     *
-     * @return void
-     */
-    public function handle()
-    {
-        $traceContext = new TraceContext();
-        \Log::info('[orangeSiteRechargeReport]开始回传', [
-            'reportInfo' => $this->reportInfo,
-            'traceInfo' => $traceContext->getTraceInfo()
-        ]);
-        $user = DB::table('users')->find(($this->reportInfo['uid'] ?? -1));
-        $order = DB::table('orders')->where([
-            ['id', '=', ($this->reportInfo['orderId'] ?? -1)],
-            ['status', '=', 'PAID']
-        ])->first();
-        $channelCallbackConfig = ChannelCallbackConfig::where('channel_id', ($this->reportInfo['channelId'] ?? -1))
-            ->where('platform', self::PLATFORM)->first();
-
-        $channelSettingRate = OrangeSiteReportRateService::getChannelSettingReportRate($user->distribution_channel_id);
-        $reportCheckContext = new OrangeSiteRechargeReportCheckContext($user, $order, $channelCallbackConfig,
-            $traceContext, $channelSettingRate);
-
-        try {
-            $reportCheckContext->checkNecessaryInfo();
-        } catch (\Exception $exception) {
-            \Log::error('[orangeSiteRechargeReport]回传基础信息有误', [
-                'message' => $exception->getMessage(),
-                'traceInfo' => $traceContext->getTraceInfo()
-            ]);
-            dingTalkAlert(config('common.orangeSite.dingTalkUrl'), "[orangeSite]订单回传基础信息有误报警:\r\n" .
-                \json_encode([
-                    'reportInfo' => $this->reportInfo,
-                    'message' => $exception->getMessage(),
-                    'traceInfo' => $traceContext->getTraceInfo()
-                ], JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT));
-            return;
-        }
-
-
-        $pipes = [
-            EnableReportCheck::class,
-            OrderAlreadyReportCheck::class,
-            ReportRechargeTypeCheck::class,
-            RechargeAmountCheck::class,
-            PromotionProtectCheck::class,
-            ReportRateCheck::class
-        ];
-
-        $content = app(Pipeline::class)
-            ->send($reportCheckContext)
-            ->through($pipes)
-            ->then(function ($content) {
-                return $content;
-            });
-        $result = $content->result;
-        \Log::info('[orangeSiteRechargeReport]回传判定结果', [
-            'result' => $result,
-            'traceInfo' => $traceContext->getTraceInfo()]);
-        if ($result['needRecord'] ?? true) {
-            $this->saveReportUserChargeReportInfo($reportCheckContext, $result);
-        }
-        if ($result['result']) {
-            $this->reportRecharge($reportCheckContext, $result);
-        }
-    }
-
-    private function reportRecharge(OrangeSiteRechargeReportCheckContext $reportCheckContext, array $checkResult)
-    {
-        $params = [
-            'uid' => $reportCheckContext->user->id,
-            'source' => 'zsy',
-            'amount' => $reportCheckContext->order->price ?? 0,
-            'link_source' => 'tiktok_event',
-        ];
-
-
-        $result = $this->reprotResultDeal(CallbackBaseService::directlyCharge($params));
-
-        $resultContent = \json_decode(($result['content'] ?? '[]'), true);
-
-        $updateInfo = [
-            'status' => $result['status'] ?? 0,
-            'request_param' => $result['request_param'] ?? '',
-            'updated_at' => date('Y-m-d H:i:s'),
-            'content' => \json_encode(array_merge($resultContent,
-                ['log_content' => ($reportCheckContext->result['content'] ?? '')]))
-        ];
-
-        \Log::info('[orangeSiteRechargeReport]请求回传接口结果:' . ($updateInfo['status'] ? '成功' : '失败'), [
-            'status' => $updateInfo['status'],
-            'traceInfo' => $reportCheckContext->traceContext->getTraceInfo()]);
-
-        DB::transaction(function () use ($reportCheckContext, $updateInfo, $checkResult, $result) {
-            DB::table('report_user_charge_records')->where([
-                'order_no' => $reportCheckContext->order->trade_no,
-                'uid' => $reportCheckContext->order->uid,
-                'link_source' => $reportCheckContext->platform,
-            ])->update($updateInfo);
-
-            if (1 == $result['status']) {
-                /**
-                 * 如果是计划保护回传成功的,只增加 orange_site_recharge_report_protect_records.current_protect_num,
-                 * 而不增加 orange_site_recharge_report_records.rate_total_num 和 orange_site_recharge_report_records.rate_success_num
-                 */
-                if ('promotionProtect' == ($checkResult['result_ok_reason'] ?? '')) {
-                    \Log::debug('[orangeSiteRechargeReport]回传成功,增加对应计划的成功数', [
-                        'traceInfo' => $reportCheckContext->traceContext->getTraceInfo(),
-                        'promotionId' => $reportCheckContext->reportInfo['promotionId']]);
-
-                    OrangeSitePromotionService::setCurrentPromotionProtectNum($reportCheckContext->user->distribution_channel_id,
-                        $reportCheckContext->reportInfo['promotionId'],
-                        $reportCheckContext->channelCallbackConfig->eligible_count ?: 0);
-                } else {
-                    OrangeSiteReportRateService::increaseSuccessNum($reportCheckContext->user->distribution_channel_id,
-                        $reportCheckContext->reportInfo['configRate']);
-                }
-
-            } else {
-                if ('promotionProtect' != ($checkResult['result_ok_reason'] ?? '')) {
-                    \Log::error('[orangeSiteRechargeReport]订单回传失败', [
-                        'traceInfo' => $reportCheckContext->traceContext->getTraceInfo()]);
-                    OrangeSiteReportRateService::increaseFailNum($reportCheckContext->user->distribution_channel_id,
-                        $reportCheckContext->reportInfo['configRate']);
-                } else {
-                    \Log::error('[orangeSiteRechargeReport]计划保护订单回传失败', [
-                        'traceInfo' => $reportCheckContext->traceContext->getTraceInfo()]);
-                }
-            }
-        });
-    }
-
-
-    /**
-     * [调用tiktok 接口回传后,数据处理逻辑]
-     * @return [type]          [description]
-     */
-    public function reprotResultDeal($result)
-    {
-        $status = 0;
-        $content = '';
-        $result_data = isset($result['data']) ? $result['data'] : [];
-        if (!empty($result_data['content'])) {
-            $content = $result_data['content'];
-            $con_arr = json_decode($content, true);
-            $content = json_encode($con_arr);
-            if (isset($con_arr['code']) && 0 == $con_arr['code']) {
-                //tiktok_event
-                $status = 1;
-            }
-        }
-        //处理请求参数
-        $request_param = '';
-        if (isset($result_data['query_params'])) {
-            if (is_string($result_data['query_params'])) {
-                $request_param = $result_data['query_params'];
-            }
-            if (is_array($result_data['query_params'])) {
-                $request_param = json_encode($result_data['query_params']);
-            }
-        }
-        $data = [
-            'status' => $status,
-            'request_param' => $request_param,
-        ];
-        if ($content) {
-            $data['content'] = $content;
-        }
-        return $data;
-    }
-
-    private function saveReportUserChargeReportInfo(OrangeSiteRechargeReportCheckContext $reportCheckContext, array $result)
-    {
-        $data = [
-            'uid' => $this->reportInfo['uid'],
-            'config_percent' => round($reportCheckContext->reportInfo['configRate'] / 100, 4),
-            'report_percent' => round($reportCheckContext->reportInfo['reportRate'] / 100, 4),
-            'order_no' => $reportCheckContext->order->trade_no,
-            'timestamp' => time(),
-            'status' => 0,
-            'type' => $result['type'] ?? '',
-            'content' => $result['content'] ?? '',
-            'channel_id' => $reportCheckContext->user->distribution_channel_id,
-            'request_param' => '',
-            'link_source' => $reportCheckContext->platform,
-        ];
-        ReportUserChargeRecord::updateOrCreate([
-            'order_no' => $data['order_no'],
-            'uid' => $data['uid'],
-            'link_source' => $data['link_source'],
-        ], $data);
-    }
-}

+ 15 - 1
app/Jobs/Callback/ReportCharge.php

@@ -2,6 +2,7 @@
 
 namespace App\Jobs\Callback;
 
+use App\Service\Callback\JLEventReportChargeService;
 use App\Service\Callback\JuliangAccountReportChargeService;
 use App\Service\Util\Support\Trace\TraceContext;
 use Illuminate\Bus\Queueable;
@@ -48,7 +49,10 @@ class ReportCharge implements ShouldQueue
 
         $order = DB::table('orders')->where('id', $this->info['orderId'])->first();
         if($order && $order->promotion_id) {
-            $promotion = DB::table('promotions')->where('id', $order->promotion_id)->first();
+            $promotion = DB::table('promotions')->where([
+                'id'=> $order->promotion_id,
+                'is_enabled' => 1
+            ])->first();
             switch ($promotion->callback_type ?? 0) {
                 case 0:
                     myLog('reportCharge')->error('end:订单染色配置有问题', [
@@ -56,10 +60,20 @@ class ReportCharge implements ShouldQueue
                     ]);
                     break;
                 case 1:
+                    //巨量账户级别回传
                     $reportService = new JuliangAccountReportChargeService($this->info['uid'], $order, $this->info['traceInfo']);
                     $reportService->report();
                     break;
+                case 2:
+                    //巨量2.0事件回传
+                    $reportService = new JLEventReportChargeService($this->info['uid'], $order, $this->info['traceInfo']);
+                    $reportService->report();
+                    break;
             }
+        } else {
+            myLog('reportCharge')->error('end:订单不存在或订单没有推广信息', [
+                'traceInfo' => $traceContext->getTraceInfo()
+            ]);
         }
 
     }

+ 126 - 0
app/Jobs/Video/WechatCheck.php

@@ -0,0 +1,126 @@
+<?php
+
+namespace App\Jobs\Video;
+
+use App\Service\Miniprogram\Wechat\AccessTokenService;
+use App\Service\Util\Support\Http\WechatURL;
+use App\Service\Util\Support\Trace\TraceContext;
+use App\Service\Util\Support\Http\HttpRequestService;
+use Illuminate\Bus\Queueable;
+use Illuminate\Contracts\Queue\ShouldQueue;
+use Illuminate\Foundation\Bus\Dispatchable;
+use Illuminate\Queue\InteractsWithQueue;
+use Illuminate\Queue\SerializesModels;
+use Illuminate\Support\Arr;
+use Illuminate\Support\Facades\Redis;
+use Illuminate\Support\Facades\DB;
+
+class WechatCheck implements ShouldQueue
+{
+    use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
+
+    private $info;
+    /**
+     * Create a new job instance.
+     */
+    public function __construct($info)
+    {
+        $this->info = $info;
+    }
+
+    /**
+     * Execute the job.
+     */
+    public function handle(): void
+    {
+        myLog('WechatCheck')->info('开始处理微信提审', [
+            'info' => $this->info
+        ]);
+        $traceContext = TraceContext::newFromParent($this->info['traceInfo']);
+
+        $id = $this->info['id'];
+        $record = DB::table('video_wechat_check')
+            ->join('videos', 'videos.id', 'video_wechat_check.video_id')
+            ->where(['video_wechat_check.id' => $id,
+                'video_wechat_check.is_enabled' => 1, 'video_wechat_check.status' => 5])
+            ->select('video_wechat_check.*', 'videos.name as video_name', 'videos.cover_image as video_cover_image')
+            ->first();
+        if(!$record) {
+            myLog('WechatCheck')->info('当前状态不支持提审', [
+                'traceInfo' => $traceContext->getTraceInfo()
+            ]);
+            return;
+        }
+        $appid = $record->appid ?: config('wechat.duanju.masterAppid');
+        $accessToken = Redis::get(AccessTokenService::getAccessTokenRedisKey($appid));
+        $medias = DB::table('video_series_wechat_check')
+            ->where('video_id', $record->video_id)
+            ->where(['sync_status' => 4, 'is_enabled' => 1])
+            ->where('media_id', '<>', 0)
+            ->get();
+        $cover_material_id = $this->getMaterialId($record->video_cover_image, $accessToken);
+        $authorized_material_id = $this->getMaterialId($record->authorized_img, $accessToken);
+        if(!($cover_material_id && $authorized_material_id)) {
+            myLog('WechatCheck')->error('上传短剧封面和授权材料到临时素材失败, 请重新提审', [
+                'appid' => $appid,
+                'traceInfo' => $traceContext->getTraceInfo()
+            ]);
+            return ;
+        }
+        $postData = [
+            'name' => $record->video_name,
+            'media_count' => $medias->count(),
+            'media_id_list' => $medias->pluck('media_id')->toArray(),
+            'producer' => $record->producer,
+            'cover_material_id' =>$cover_material_id,
+            'authorized_material_id' => $authorized_material_id,
+            'registration_number' => $record->registration_number,
+        ];
+        if($record->drama_id) {
+            $postData['drama_id'] = $record->drama_id;
+        }
+        $result = HttpRequestService::simplePost(WechatURL::vod_auditdrama . $accessToken, $postData);
+        if(false === $result || (0 != ($result['errcode'] ?? 0)) || (! ($result['drama_id'] ?? ''))) {
+            myLog('WechatCheck')->error('提审请求失败', [
+                'appid' => $appid,
+                'post' => $postData,
+                'result' => $result,
+                'traceInfo' => $traceContext->getTraceInfo()
+            ]);
+            return;
+        }
+        $drama_id = $result['drama_id'];
+        $now = date('Y-m-d H:i:s');
+        DB::table('video_wechat_check')
+            ->where('id', $record->id)
+            ->update([
+                'status' =>1,
+                'apply_at' => $now,
+                'drama_id' => $drama_id,
+                'updated_at' => $now,
+            ]);
+    }
+
+    /**
+     * 上传临时图片素材
+     * @param string $url 图片http地址
+     * @param string $accessToken
+     * @return string media_id
+     */
+    public function getMaterialId($url, $accessToken){
+        $result = HttpRequestService::post(WechatURL::media_upload. $accessToken, [
+            'multipart' => [
+                [
+                    'name' => 'type',
+                    'contents' => 'image',
+                ],
+                [
+                    'name' => 'media',
+                    'contents' => file_get_contents($url),
+                    'filename' => Arr::last(explode('/', $url)),
+                ]
+            ]
+        ]);
+        return $result['media_id'] ?? '';
+    }
+}

+ 61 - 0
app/Libs/Helpers.php

@@ -5,6 +5,8 @@ use App\Service\Util\Support\Trace\CustomizeLogger;
 use Illuminate\Http\UploadedFile;
 use Modules\Common\Support\Upload\Uploader;
 use PHPMailer\PHPMailer\PHPMailer;
+use Illuminate\Support\Str;
+use Illuminate\Support\Facades\Http;
 
 if(!function_exists("str_decode")){
     /**
@@ -268,3 +270,62 @@ if (!function_exists("random")) {
         return $hash;
     }
 }
+
+
+function dingTalkAlertException(\Throwable $exception)
+{
+    $code = $exception->getCode();
+    if($code >0){
+        return ;
+    }
+    $url = 'https://oapi.dingtalk.com/robot/send?access_token=07829435258bf07c5f0b0a0a84c50c4bebc15e585b3040ad43c5e94e213a9bba';
+    $key = 'SEC74f8117d06ae59a7edde24cd9706334dbdd09b5d5734522f060272bdfbfb1abd';
+    $timestamp = time()*1000;
+    $string = $timestamp . "\n" . $key; 
+    $sign = hash_hmac('sha256',$string,$key,true);
+    $sign = urlencode(base64_encode($sign));
+    $url .= '&'.http_build_query(['timestamp'=>$timestamp,'sign'=>$sign]);
+
+    $class_name = get_class($exception);
+    $app_path = app_path();
+    $trace = $exception->getTraceAsString();
+    $trace_list = preg_split('/\n/',$trace);
+    $error = '- '.$exception->getFile().':'.$exception->getLine()."\n";
+    foreach($trace_list as $item){
+        if( Str::contains($item,$app_path)){
+            $error .= '- '.trim(preg_replace('/^(\#\d+)/','',$item))."\n";
+        }
+    }
+    $hostname = gethostname();
+
+    $ip = '';
+    $ssh = getenv('SSH_CONNECTION');
+    if($ssh){
+        $ssh_list = explode(' ',$ssh);
+        $ip = isset($ssh_list[2]) ? $ssh_list[2]:'';
+    }
+
+    $result = [
+        'message'=>$exception->getMessage(),
+        'class_name'=>$class_name,
+        'app_path'=>$app_path,
+        'error'=>$error,
+        'hostname'=>$hostname.' - '.$ip
+    ];
+
+    try{
+        $response = Http::post($url,[
+            'msgtype' => 'markdown',
+            'markdown' => [
+                'title'=>basename (base_path()).'异常',
+                'text' => sprintf("### 错误信息: \n%s\n ### 异常详情: \n%s\n### 项目路径: \n%s\n\n ### 主机名:\n%s\n",
+                $result['class_name'].':'.$result['message'],$result['error'],$result['app_path'],$result['hostname'])
+            ]
+        ]);
+    }catch(\Exception $e){
+
+    }
+    
+}
+
+

+ 13 - 0
app/Models/VideoStatByCompany.php

@@ -0,0 +1,13 @@
+<?php
+namespace App\Models;
+
+use Illuminate\Database\Eloquent\Model;
+
+class VideoStatByCompany extends Model{
+
+    protected $table = 'video_stat_by_company';
+    protected $fillable = [
+        'id','user_id','video_name','video_id','amount','charge_count','charge_user_num','play_count','created_at','updated_at'
+    ];
+
+}

+ 13 - 0
app/Models/VideoStatByUser.php

@@ -0,0 +1,13 @@
+<?php
+namespace App\Models;
+
+use Illuminate\Database\Eloquent\Model;
+
+class VideoStatByUser extends Model{
+
+    protected $table = 'video_stat_by_user';
+    protected $fillable = [
+        'id','day','user_id','puser_id','video_name','video_id','amount','charge_count','charge_user_num','play_count','created_at','updated_at'
+    ];
+
+}

+ 375 - 0
app/Service/Callback/JLEventReportChargeService.php

@@ -0,0 +1,375 @@
+<?php
+
+namespace App\Service\Callback;
+
+use App\Service\Callback\Tiktok\TiktokEventReportService;
+use App\Service\Util\Support\Trace\TraceContext;
+use Illuminate\Support\Facades\DB;
+
+/**
+ * 巨量2.0事件
+ */
+class JLEventReportChargeService
+{
+    private $uid;
+    /**
+     * @var TraceContext
+     */
+    private $traceContext;
+    private $order;
+    private $result;
+    private $trackRecord;
+    private $callbackConfig;
+    private $promotion;
+    private $configLog;
+    public function __construct($uid, $order, $traceInfo)
+    {
+        $this->order = $order;
+        $this->uid = $uid;
+        $this->traceContext = TraceContext::newFromParent($traceInfo);
+        $this->result = [
+            'need_report' => true,
+            'config_rate' => 0,
+            'current_rate' => 0,
+            'report_success' => false,
+            'info_type' => 'ok',
+            'continue_judge' => true,
+        ];
+    }
+
+    public function report() {
+        $this->fillRanseInfo();
+        $this->fillTrackInfo();
+        $this->judgeOrderAlreadyDeal();
+        $this->judgeIsRoi();
+        $this->judgeChargeType();
+        $this->judgeChargeMoney();
+        $this->reportJuliang();
+        $this->saveRecord();
+    }
+
+    /**
+     * 判断是否roi全量回传
+     */
+    private function judgeIsRoi() {
+        if(!$this->result['need_report']) {
+            return;
+        }
+        if(1 == $this->callbackConfig->is_roi) {
+            $this->result['continue_judge'] = false;
+            $this->result['info_type'] = 'roi_report_all';
+            $this->result['info_str']  = 'roi全量上报';
+        }
+    }
+
+    private function saveRecord() {
+        if($this->result['save_record'] ?? true) {
+            $now = date('Y-m-d H:i:s');
+            $chargeRecord = DB::table('callback_report_charge_record')->where([
+                'order_no' => $this->order->trade_no
+            ])->first();
+            if(!$chargeRecord) {
+                DB::table('callback_report_charge_record')
+                    ->insert([
+                        'uid' => $this->uid,
+                        'order_id' => $this->order->id,
+                        'order_no' => $this->order->trade_no,
+                        'optimizer_uid' => $this->promotion->uid,
+                        'filter_type' => $this->result['info_type'] ?? 'ok',
+                        'filter_reason' => $this->result['info_str'] ?? '允许回传',
+                        'report_success' => intval($this->result['report_success'] ?? false),
+                        'report_result' => \json_encode($this->result['report_result'] ?? []),
+                        'report_param' => \json_encode($this->result['report_param'] ?? []),
+                        'created_at' => $now,
+                        'updated_at' => $now,
+                        'advertiser_id' => $this->trackRecord->advertiser_id ?? '',
+                        'adv_promotion_id' => $this->trackRecord->adv_promotion_id ?? '',
+                        'config_rate' => $this->result['config_rate'],
+                        'current_rate' => $this->result['current_rate'],
+                        'user_ranse_start_at' => $this->trackRecord->ranse_start_at ?? null,
+                        'order_price' => $this->order->price,
+                        'order_created_at' => $this->order->created_at,
+                        'user_ranse_ip' => $this->trackRecord->ranse_ip ?? '',
+                        'miniprogram_id' => $this->promotion->miniprogram_id,
+                        'user_ranse_id' => $this->promotion->id,
+                        'callback_type' => $this->promotion->callback_type,
+                        'callback_config_id' => $this->promotion->callback_config_id,
+                        'ext_a' => $this->configLog->callback_param ?? '',
+                    ]);
+            } else {
+                DB::table('callback_report_charge_record')
+                    ->where(['id' => $chargeRecord->id])
+                    ->update([
+                        'uid' => $this->uid,
+                        'order_id' => $this->order->id,
+                        'order_no' => $this->order->trade_no,
+                        'optimizer_uid' => $this->promotion->uid,
+                        'filter_type' => $this->result['info_type'] ?? 'ok',
+                        'filter_reason' => $this->result['info_str'] ?? '允许回传',
+                        'report_success' => intval($this->result['report_success'] ?? false),
+                        'report_result' => \json_encode($this->result['report_result'] ?? []),
+                        'report_param' => \json_encode($this->result['report_param'] ?? []),
+                        'updated_at' => $now,
+                        'advertiser_id' => $this->trackRecord->advertiser_id ?? '',
+                        'adv_promotion_id' => $this->trackRecord->adv_promotion_id ?? '',
+                        'config_rate' => $this->result['config_rate'],
+                        'current_rate' => $this->result['current_rate'],
+                        'user_ranse_start_at' => $this->trackRecord->ranse_start_at ?? null,
+                        'order_price' => $this->order->price,
+                        'order_created_at' => $this->order->created_at,
+                        'user_ranse_ip' => $this->trackRecord->ranse_ip ?? '',
+                        'miniprogram_id' => $this->promotion->miniprogram_id,
+                        'user_ranse_id' => $this->promotion->id,
+                        'callback_type' => $this->promotion->callback_type,
+                        'callback_config_id' => $this->promotion->callback_config_id,
+                        'ext_a' => $this->configLog->callback_param ?? '',
+                    ]);
+            }
+
+            if($this->configLog) {
+                if('ok' == $this->result['info_type'] && $this->result['report_success']) {
+                    DB::table('jl_event_rate_config_log')
+                        ->where(['id' => $this->configLog->id])
+                        ->update([
+                            'report_count' => $this->configLog->report_count + 1,
+                            'updated_at' => $now,
+                        ]);
+                    if(3 == $this->configLog->callback_type) {
+                        DB::table('jl_event_rate_config_log')
+                            ->where(['id' => $this->configLog->id])
+                            ->update([
+                                'flag' => $this->configLog->flag,
+                                'flag_report' => $this->configLog->flag_report,
+                                'flag_unreport' => $this->configLog->flag_unreport,
+                                'updated_at' => $now,
+                            ]);
+                    }
+                } elseif ('rate_filter' == $this->result['info_type']) {
+                    DB::table('jl_event_rate_config_log')
+                        ->where(['id' => $this->configLog->id])
+                        ->update([
+                            'unreport_count' => $this->configLog->unreport_count + 1,
+                            'updated_at' => $now,
+                        ]);
+                    if(3 == $this->configLog->callback_type) {
+                        DB::table('jl_event_rate_config_log')
+                            ->where(['id' => $this->configLog->id])
+                            ->update([
+                                'flag' => $this->configLog->flag,
+                                'flag_report' => $this->configLog->flag_report,
+                                'flag_unreport' => $this->configLog->flag_unreport,
+                                'updated_at' => $now,
+                            ]);
+                    }
+                }
+
+                $newConfigLog = DB::table('jl_event_rate_config_log')
+                    ->where(['id' => $this->configLog->id])
+                    ->select('report_count', 'unreport_count')
+                    ->first();
+                if(($newConfigLog->report_count ?? 0 ) + ($newConfigLog->unreport_count ?? 0 )) {
+                    $currentRate = bcdiv(($newConfigLog->report_count ?? 0 ) * 100,
+                        (($newConfigLog->report_count ?? 0 ) + ($newConfigLog->unreport_count ?? 0 )), 2);
+                } else {
+                    $currentRate = 0;
+                }
+                DB::table('callback_report_charge_record')->where([
+                    'order_no' => $this->order->trade_no
+                ])->update([
+                    'current_rate' => $currentRate,
+                ]);
+            }
+        }
+    }
+
+    /**
+     * 判断订单是不是已经处理过了.如果处理过了,就不入库
+     */
+    private function judgeOrderAlreadyDeal() {
+        if(!$this->result['need_report']) {
+            return;
+        }
+        if(DB::table('callback_report_charge_record')
+            ->where(['order_id'  => $this->order->id])
+            ->exists()) {
+            $this->result['need_report'] = false;
+            $this->result['save_record'] = false;
+            $this->result['info_type'] = 'order_exists';
+            $this->result['info_str'] = '订单已经处理';
+        }
+    }
+
+    /**
+     * 判断充值的金额区间
+     */
+    private function judgeChargeMoney() {
+        if(!$this->result['need_report'] || !$this->result['continue_judge']) {
+            return;
+        }
+
+        $this->configLog = DB::table('jl_event_rate_config_log')
+            ->where([
+                'user_id' => $this->promotion->uid,
+                'config_id' => $this->callbackConfig->id,
+                'is_enabled' => 1,
+            ])->where('min_money', '<=', $this->order->price)
+            ->where('max_money', '>', $this->order->price)
+            ->orderBy('id', 'desc')
+            ->first();
+        if(!$this->configLog) {
+            $this->result['need_report'] = false;
+            $this->result['continue_judge'] = false;
+            $this->result['info_type'] = 'money_filter';
+            $this->result['info_str'] = '订单金额不在所有金额项区间内';
+            return;
+        } else {
+            if(1 == $this->configLog->callback_type) {
+                $this->result['continue_judge'] = false;
+            }elseif(2 == $this->configLog->callback_type) {
+                $this->result['continue_judge'] = false;
+                $this->result['need_report'] = false;
+                $this->result['info_type'] = 'money_filter';
+                $this->result['info_str'] = sprintf('订单金额在区间:[%s元-%s元]全部不回传',
+                    $this->configLog->min_money, $this->configLog->max_money);
+                return;
+            } elseif (3 == $this->configLog->callback_type) {
+                $sm = explode(':', $this->configLog->callback_param);
+                $this->chuanNkaM($this->configLog, $sm[0], $sm[1]);
+                if($this->configLog->flag) {
+                    $this->configLog->flag_report++;
+                } else {
+                    $this->configLog->flag_unreport++;
+                    $this->result['continue_judge'] = false;
+                    $this->result['need_report'] = false;
+                    $this->result['info_type'] = 'rate_filter';
+                    $this->result['info_str'] = '比率过滤';
+                }
+            }
+        }
+    }
+
+    /**
+     * 判断当前是回传还是不回传
+     * @param $obj
+     * @param $s 传几
+     * @param $m 卡几
+     */
+    private function chuanNkaM($obj, $s, $m)
+    {
+        if($obj->flag) {
+            if(($obj->flag_report)  < $s){
+                $obj->flag = 1;
+            } else {
+                $obj->flag_report = 0;
+                $obj->flag = 0;
+            }
+        } else {
+            if(($obj->flag_unreport) < $m) {
+                $obj->flag = 0;
+            } else {
+                $obj->flag_unreport = 0;
+                $obj->flag = 1;
+            }
+        }
+    }
+
+    /**
+     * 判断充值行为
+     */
+    private function judgeChargeType() {
+        if(!$this->result['need_report'] || !$this->result['continue_judge']) {
+            return;
+        }
+
+        if(1 == $this->callbackConfig->charge_type) {
+            $isFirstCharge = DB::table('orders')
+                    ->where([
+                        'uid' => $this->uid,
+                        'status' => 'paid',
+                        'promotion_id' => $this->trackRecord->ranse_id,
+                    ])->where('created_at', '>=', $this->trackRecord->ranse_start_at)
+                    ->where('created_at', '<=', $this->trackRecord->ranse_end_at)
+                    ->where('id', '<', $this->order->id)
+                    ->count() == 0;
+            if(!$isFirstCharge) {
+                $this->result['need_report'] = false;
+                $this->result['continue_judge'] = false;
+                $this->result['info_type'] = 'neq_first_charge';
+                $this->result['info_str'] = '非首充';
+            }
+        }
+    }
+
+    /**
+     * 获取订单的染色信息,回传配置信息, 推广被禁用,就按照没有回传配置处理
+     */
+    private function fillRanseInfo() {
+        $ranseId = $this->order->promotion_id;
+        $this->promotion = DB::table('promotions')->where('id', $ranseId)->first();
+        if(0 == $this->promotion->status || $this->promotion->callback_config_id < 1) {
+            $this->result['need_report'] = false;
+            $this->result['info_type'] = 'no_callback_config';
+            $this->result['info_str'] = '没有回传配置';
+            return;
+        }
+        $this->callbackConfig = DB::table('jl_event_callback_config')
+            ->where(['id' => $this->promotion->callback_config_id])
+            ->first();
+        if(!$this->callbackConfig) {
+            $this->result['need_report'] = false;
+            $this->result['info_type'] = 'no_callback_config';
+            $this->result['info_str'] = '没有回传配置';
+            return;
+        }
+
+    }
+    private function reportJuliang() {
+        if(!$this->result['need_report']) {
+            return;
+        }
+        $service = new TiktokEventReportService;
+        if('roi_report_all' == $this->result['info_type']) {
+            $reportResult = $service->roiReportCharge((object)[
+                'callback' => $this->trackRecord->callback
+            ]);
+        } else {
+            $reportResult = $service->reportCharge((object)[
+                'callback' => $this->trackRecord->callback
+            ]);
+        }
+
+        $reportContent = \json_decode($reportResult['content'], true);
+        if($reportResult['result']  && 0 == $reportContent['code']) {
+            $this->result['report_success'] = true;
+        } else {
+            $this->result['report_success'] = false;
+        }
+        $this->result['report_result'] = $reportResult;
+        $this->result['need_report'] = false;
+    }
+
+    /**
+     * 获取匹配的广告用户信息,主要是获取回传 callback
+     */
+    private function fillTrackInfo() {
+        if(!$this->result['need_report']) {
+            return;
+        }
+        $this->trackRecord = DB::table('callback_report_ranse_record')
+            ->where(['uid' => $this->uid, 'ranse_id' => $this->order->promotion_id])
+            ->where('ranse_start_at', '<=', $this->order->created_at)
+            ->where('ranse_end_at', '>=', $this->order->created_at)
+            ->orderBy('id', 'desc')
+            ->first();
+        if(!$this->trackRecord) {
+            $this->result['need_report'] = false;
+            $this->result['info_type'] = 'no_track_info';
+            $this->result['info_str'] = '无匹配用户';
+            return;
+        }
+
+        $this->result['report_param'] = [
+            'callback' => $this->trackRecord->callback,
+        ];
+    }
+}

+ 13 - 1
app/Service/Callback/JuliangAccountReportChargeService.php

@@ -105,6 +105,9 @@ class JuliangAccountReportChargeService
                         'order_created_at' => $this->order->created_at,
                         'user_ranse_ip' => $this->trackRecord->ranse_ip ?? '',
                         'miniprogram_id' => $this->promotion->miniprogram_id,
+                        'user_ranse_id' => $this->promotion->id,
+                        'callback_type' => $this->promotion->callback_type,
+                        'callback_config_id' => $this->promotion->callback_config_id,
                     ]);
             } else {
                 DB::table('callback_report_charge_record')
@@ -129,6 +132,9 @@ class JuliangAccountReportChargeService
                         'order_created_at' => $this->order->created_at,
                         'user_ranse_ip' => $this->trackRecord->ranse_ip ?? '',
                         'miniprogram_id' => $this->promotion->miniprogram_id,
+                        'user_ranse_id' => $this->promotion->id,
+                        'callback_type' => $this->promotion->callback_type,
+                        'callback_config_id' => $this->promotion->callback_config_id,
                     ]);
             }
 
@@ -289,11 +295,17 @@ class JuliangAccountReportChargeService
     }
 
     /**
-     * 获取订单的染色信息,回传配置信息
+     * 获取订单的染色信息,回传配置信息, 推广被禁用,就按照没有回传配置处理
      */
     private function fillRanseInfo() {
         $ranseId = $this->order->promotion_id;
         $this->promotion = DB::table('promotions')->where('id', $ranseId)->first();
+        if(0 == $this->promotion->status) {
+            $this->result['need_report'] = false;
+            $this->result['info_type'] = 'no_callback_config';
+            $this->result['info_str'] = '没有回传配置';
+            return;
+        }
         $this->callbackConfig = DB::table('juliang_account_callback_config')
             ->where(['id' => $this->promotion->callback_config_id])
             ->first();

+ 14 - 0
app/Service/Callback/Tiktok/TiktokEventReportService.php

@@ -46,6 +46,18 @@ class TiktokEventReportService
 
     }
 
+    public function roiReportCharge($user) {
+        return $this->report($this->report_url, [
+            'event_type' => $this->purchase_roi_event_type,
+            'context' => [
+                'ad' => [
+                    'callback' => $user->callback
+                ]
+            ],
+            'timestamp' => time()
+        ]);
+    }
+
     /**
      * 付费上报
      */
@@ -141,6 +153,8 @@ class TiktokEventReportService
             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,

+ 4 - 14
app/Service/Miniprogram/Wechat/AccessTokenService.php

@@ -2,24 +2,14 @@
 
 namespace App\Service\Miniprogram\Wechat;
 
-use GuzzleHttp\Client;
+use App\Service\Util\Support\Http\WechatURL;
+use App\Service\Util\Support\Http\HttpRequestService;
 
 class AccessTokenService
 {
     public static function getAccessToken($appid, $secret) {
-        $client = new Client(['timeout' => 3]);
-        $httpResult = $client->get('https://api.weixin.qq.com/cgi-bin/token', [
-            'query' => ['grant_type' => 'client_credential', 'appid' => $appid, 'secret' => $secret]
-        ]);
-
-        if(200 != $httpResult->getStatusCode()) {
-            throw new \RuntimeException('请求微信上游失败', '500001');
-        }
-        $parsedContent = \json_decode($httpResult->getBody()->getContents(), true);
-        if(0 != ($parsedContent['errcode'] ?? 0)) {
-            throw new \RuntimeException('请求微信上游失败:'. ($parsedContent['errmsg'] ?? ''), '500002');
-        }
-        return $parsedContent;
+        return HttpRequestService::simpleGet(WechatURL::access_token, ['grant_type' => 'client_credential',
+            'appid' => $appid, 'secret' => $secret]);
     }
 
     public static function getAccessTokenRedisKey($appid) {

+ 49 - 0
app/Service/Stats/MiniprogramStatService.php

@@ -0,0 +1,49 @@
+<?php
+namespace App\Service\Stats;
+
+use Illuminate\Support\Facades\Redis;
+
+/**
+ * 短剧统计
+ */
+class MiniprogramStatService{
+    
+
+    public static function  getOneItem(int $video_id,int $user_id,string $day){
+        $playNumkey = 'VideoStat:palyNum:'.$day;
+        $field = sprintf('UserId:%s:MinId:%s',$user_id,$video_id);
+        $play_count =  Redis::hget($playNumkey,$field);
+
+        $amountKey = 'VideoStat:chargeAmount:'.$day; //充值金额
+        $amount = Redis::hget($amountKey,$field);
+
+        $chargeCountkey = 'VideoStat:chargeCount:'.$day; 
+        $charge_count = Redis::hget($chargeCountkey,$field);
+
+        //充值人数
+        $chargeUserNumKey = 'VideoStat:chargeUserNum:'.$day.':';
+        $charge_user_num = Redis::scard($chargeUserNumKey.$field);
+
+        return compact('amount','play_count','charge_count','charge_user_num');
+    }
+
+
+    public static function deleteCache(int $video_id,int $user_id,string $day){
+        $field = sprintf('UserId:%s:MinId:%s',$user_id,$video_id);
+        $playNumkey = 'VideoStat:palyNum:'.$day;
+        $amountKey = 'VideoStat:chargeAmount:'.$day;
+        $chargeCountkey = 'VideoStat:chargeCount:'.$day; 
+        $chargeUserNumKey = 'VideoStat:chargeUserNum:'.$day.':'.$field;
+        Redis::hdel( $playNumkey,$field);
+        Redis::hdel( $amountKey,$field);
+        Redis::hdel( $chargeCountkey,$field);
+        Redis::del($chargeUserNumKey);
+    }
+
+    public static function deleteAll(string $day){
+        $playNumkey = 'VideoStat:palyNum:'.$day;
+        $amountKey = 'VideoStat:chargeAmount:'.$day;
+        $chargeCountkey = 'VideoStat:chargeCount:'.$day; 
+        Redis::del($playNumkey,$amountKey,$chargeCountkey);
+    }
+}

+ 81 - 0
app/Service/Util/Support/Http/HttpRequestService.php

@@ -0,0 +1,81 @@
+<?php
+namespace App\Service\Util\Support\Http;
+
+use GuzzleHttp\Client;
+
+class HttpRequestService
+{
+
+    /**
+     * 发送post请求
+     * @param $url 请求地址
+     * @param $accessToken 请求access_token
+     * @param $postMessage 请求体
+     * @return array
+     */
+    public static function simplePost($url, $postMessage) {
+        $client = new Client(['timeout' => 10]);
+        try {
+            $res = $client->post(
+                $url,
+                [
+                    'json' => $postMessage
+                ]);
+            $httpStatusCode = $res->getStatusCode();
+            $httpContent = $res->getBody()->getContents();
+            $parsedContent = json_decode($httpContent, true);
+            if (200 == $httpStatusCode) {
+                return $parsedContent;
+            }
+        } catch (\Exception $exception) {
+            myLog('HttpRequest')->error('请求上游失败:', [
+                'url' => $url,
+                'postJson' => $postMessage,
+                'exceptionMessage' => $exception->getMessage(),
+            ]);
+        }
+        return false;
+    }
+
+    public static function post($url, $options) {
+        $client = new Client(['timeout' => 10]);
+        try {
+            $res = $client->request('POST', $url, $options);
+            $httpStatusCode = $res->getStatusCode();
+            $httpContent = $res->getBody()->getContents();
+            $parsedContent = json_decode($httpContent, true);
+            if (200 == $httpStatusCode) {
+                return $parsedContent;
+            }
+        } catch (\Exception $exception) {
+            myLog('HttpRequest')->error('请求上游失败:', [
+                'url' => $url,
+                'postOptions' => $options,
+                'exceptionMessage' => $exception->getMessage(),
+            ]);
+        }
+        return false;
+    }
+
+    public static function simpleGet($url, $query) {
+        $client = new Client(['timeout' => 10]);
+        try {
+            $response = $client->get($url, [
+                'query' => $query
+            ]);
+            $httpStatusCode = $response->getStatusCode();
+            $httpContent = $response->getBody()->getContents();
+            $parsedContent = json_decode($httpContent, true);
+            if (200 == $httpStatusCode)  {
+                return $parsedContent;
+            }
+        } catch (\Exception $exception) {
+            myLog('HttpRequest')->error('请求上游失败:', [
+                'url' => $url,
+                'query' => $query,
+                'exceptionMessage' => $exception->getMessage(),
+            ]);
+        }
+        return false;
+    }
+}

+ 19 - 0
app/Service/Util/Support/Http/WechatURL.php

@@ -0,0 +1,19 @@
+<?php
+
+namespace App\Service\Util\Support\Http;
+
+class WechatURL
+{
+    // 获取剧目信息
+    public const vod_getdrama = 'https://api.weixin.qq.com/wxa/sec/vod/getdrama?access_token=';
+    // accessToken
+    public const access_token = 'https://api.weixin.qq.com/cgi-bin/token';
+    // 剧目提审
+    public const vod_auditdrama = 'https://api.weixin.qq.com/wxa/sec/vod/auditdrama?access_token=';
+    // 新增临时素材
+    public const media_upload = 'https://api.weixin.qq.com/cgi-bin/media/upload?access_token=';
+    // 媒资上传-查询任务
+    public const vod_gettask = 'https://api.weixin.qq.com/wxa/sec/vod/gettask?access_token=';
+    // 获取媒资列表
+    public const vod_listmedia = 'https://api.weixin.qq.com/wxa/sec/vod/listmedia?access_token=';
+}

+ 10 - 0
app/Service/Video/WechatCheck/DramaInfoService.php

@@ -0,0 +1,10 @@
+<?php
+
+namespace App\Service\Video\WechatCheck;
+
+class DramaInfoService
+{
+    public static function syncDramaInfo($dramaId, $accessToken) {
+
+    }
+}

+ 10 - 2
config/database.php

@@ -160,7 +160,7 @@ return [
 
     'redis' => [
 
-        'client' => env('REDIS_CLIENT', 'phpredis'),
+        'client' => env('REDIS_CLIENT', 'predis'),
 
         'options' => [
             'cluster' => env('REDIS_CLUSTER', 'redis'),
@@ -184,12 +184,20 @@ return [
             'port' => env('REDIS_PORT', '6379'),
             'database' => env('REDIS_CACHE_DB', '1'),
         ],
-        'report-redis' => [//专门处理回传队列的服务器
+        //专门处理回传队列的服务器
+        'report-redis' => [
             'host' => env('REPORT_QUEUE_REDIS_HOST', 'localhost'),
             'password' => env('REPORT_QUEUE_REDIS_PASSWORD', null),
             'port' => env('REPORT_QUEUE_REDIS_PORT', 6379),
             'database' => 2,
         ],
+        // 普通redis队列
+        'queue-redis' => [
+            'host' => env('COMMON_QUEUE_REDIS_HOST', 'localhost'),
+            'password' => env('COMMON_QUEUE_REDIS_PASSWORD', null),
+            'port' => env('COMMON_QUEUE_REDIS_PORT', 6379),
+            'database' => 2,
+        ],
     ],
 
 ];

+ 1 - 1
config/logging.php

@@ -54,7 +54,7 @@ return [
     'channels' => [
         'stack' => [
             'driver' => 'stack',
-            'channels' => ['single'],
+            'channels' => ['daily'],
             'ignore_exceptions' => false,
         ],
 

+ 6 - 0
config/queue.php

@@ -75,6 +75,12 @@ return [
             'connection' => 'report-redis',
             'queue' => 'default',
             'expire' => 60,
+        ],
+        'queue-redis' => [
+            'driver' => 'redis',
+            'connection' => 'queue-redis',
+            'queue' => 'default',
+            'expire' => 60,
         ]
     ],
 

+ 8 - 0
config/wechat.php

@@ -0,0 +1,8 @@
+<?php
+
+return [
+    'duanju' => [
+        // 短剧主小程序
+        'masterAppid' => env('WECHAT_DUANJU_MASTER_APPID', 'wx86822355ccd03a78'),
+    ]
+];

+ 63 - 63
tests/Jobs/Callback/ReportChargeTest.php

@@ -20,43 +20,43 @@ class ReportChargeTest extends \Tests\TestCase
             $reportCharge->handle();
         }
 
-        foreach (range(151, 163) as $i) {
-            $traceContext = new TraceContext();
-            $reportCharge = new ReportCharge(['uid' => 1000 + $i -150, 'orderId' => 10000 + $i,
-                'traceInfo' => $traceContext->getTraceInfo()]);
-            $reportCharge->handle();
-        }
-
-        foreach (range(164, 180) as $i) {
-            $traceContext = new TraceContext();
-            $reportCharge = new ReportCharge(['uid' => 1000 + $i, 'orderId' => 10000 + $i,
-                'traceInfo' => $traceContext->getTraceInfo()]);
-            $reportCharge->handle();
-        }
+//        foreach (range(151, 163) as $i) {
+//            $traceContext = new TraceContext();
+//            $reportCharge = new ReportCharge(['uid' => 1000 + $i -150, 'orderId' => 10000 + $i,
+//                'traceInfo' => $traceContext->getTraceInfo()]);
+//            $reportCharge->handle();
+//        }
+//
+//        foreach (range(164, 180) as $i) {
+//            $traceContext = new TraceContext();
+//            $reportCharge = new ReportCharge(['uid' => 1000 + $i, 'orderId' => 10000 + $i,
+//                'traceInfo' => $traceContext->getTraceInfo()]);
+//            $reportCharge->handle();
+//        }
     }
 
     private function prepareData() {
-        $promotionId = 100;
-        $optimizerId = 5;
+        $promotionId = 5;
+        $optimizerId = 10;
         foreach(range(1, 150) as $i) {
             $orders[] = [
                 'id' => 10000 + $i,
                 'uid' => 1000 + $i,
                 'promotion_id' => $promotionId,
                 'user_id' => $optimizerId,
-                'price' => rand(10, 60),
+                'price' => rand(60, 70),
                 'pay_product_id' => 1,
                 'status' => 'PAID',
                 'trade_no' => uniqid(),
-                'created_at' => '2023-05-19 14:44:01',
+                'created_at' => '2023-07-04 13:'.(44 + rand(5, 10)),
                 'updated_at' => date('Y-m-d H:i:s'),
             ];
             $ranses[] = [
                 'uid' => 1000 + $i,
-                'ranse_id' => 100,
+                'ranse_id' => $promotionId,
                 'callback' => uniqid(),
-                'ranse_start_at' => '2023-05-19 14:44:01',
-                'ranse_end_at' => '2023-05-19 15:44:01',
+                'ranse_start_at' => '2023-07-04 13:44:01',
+                'ranse_end_at' => '2023-07-04 15:44:01',
                 'advertiser_id' => '1234568',
                 'adv_promotion_id' => '234',
                 'report_result' => '[]',
@@ -67,53 +67,53 @@ class ReportChargeTest extends \Tests\TestCase
             ];
         }
 
-        foreach (range(151, 163) as $i) {
-            $orders[] = [
-                'id' => 10000 + $i,
-                'uid' => 1000 + $i - 150,
-                'promotion_id' => $promotionId,
-                'user_id' => $optimizerId,
-                'price' => rand(40, 70),
-                'pay_product_id' => 1,
-                'status' => 'PAID',
-                'trade_no' => uniqid(),
-                'created_at' => '2023-05-19 14:'.(44 + rand(5, 10)),
-                'updated_at' => date('Y-m-d H:i:s'),
-            ];
-        }
+//        foreach (range(151, 163) as $i) {
+//            $orders[] = [
+//                'id' => 10000 + $i,
+//                'uid' => 1000 + $i - 150,
+//                'promotion_id' => $promotionId,
+//                'user_id' => $optimizerId,
+//                'price' => rand(40, 70),
+//                'pay_product_id' => 1,
+//                'status' => 'PAID',
+//                'trade_no' => uniqid(),
+//                'created_at' => '2023-07-04 13:'.(44 + rand(5, 10)),
+//                'updated_at' => date('Y-m-d H:i:s'),
+//            ];
+//        }
 
-        foreach(range(164, 180) as $i) {
-            $orders[] = [
-                'id' => 10000 + $i,
-                'uid' => 1000 + $i,
-                'promotion_id' => $promotionId,
-                'user_id' => $optimizerId,
-                'price' => rand(40, 70),
-                'pay_product_id' => 1,
-                'status' => 'PAID',
-                'trade_no' => uniqid(),
-                'created_at' => '2023-05-19 14:44:01',
-                'updated_at' => date('Y-m-d H:i:s'),
-            ];
-            $ranses[] = [
-                'uid' => 1000 + $i,
-                'ranse_id' => 100,
-                'callback' => uniqid(),
-                'ranse_start_at' => '2023-05-19 14:44:01',
-                'ranse_end_at' => '2023-05-19 15:44:01',
-                'advertiser_id' => '1234568',
-                'adv_promotion_id' => '234',
-                'report_result' => '[]',
-                'created_at' => date('Y-m-d H:i:s'),
-                'updated_at' => date('Y-m-d H:i:s'),
-                'ranse_ip' =>'192.168.1.123',
-                'optimizer_uid' => 5
-            ];
-        }
+//        foreach(range(164, 180) as $i) {
+//            $orders[] = [
+//                'id' => 10000 + $i,
+//                'uid' => 1000 + $i,
+//                'promotion_id' => $promotionId,
+//                'user_id' => $optimizerId,
+//                'price' => rand(40, 70),
+//                'pay_product_id' => 1,
+//                'status' => 'PAID',
+//                'trade_no' => uniqid(),
+//                'created_at' => '2023-05-19 14:44:01',
+//                'updated_at' => date('Y-m-d H:i:s'),
+//            ];
+//            $ranses[] = [
+//                'uid' => 1000 + $i,
+//                'ranse_id' => 100,
+//                'callback' => uniqid(),
+//                'ranse_start_at' => '2023-05-19 14:44:01',
+//                'ranse_end_at' => '2023-05-19 15:44:01',
+//                'advertiser_id' => '1234568',
+//                'adv_promotion_id' => '234',
+//                'report_result' => '[]',
+//                'created_at' => date('Y-m-d H:i:s'),
+//                'updated_at' => date('Y-m-d H:i:s'),
+//                'ranse_ip' =>'192.168.1.123',
+//                'optimizer_uid' => 5
+//            ];
+//        }
         DB::table('orders')->where('id', '>=', 10001)->delete();
         DB::table('orders')->insert($orders);
         DB::table('callback_report_ranse_record')->delete();
-        DB::table('callback_report_charge_record')->delete();
+//        DB::table('callback_report_charge_record')->delete();
         DB::table('callback_report_ranse_record')->insert($ranses);
     }
 }

+ 23 - 0
tests/Jobs/Video/WechatCheckTest.php

@@ -0,0 +1,23 @@
+<?php
+
+namespace Tests\Jobs\Video;
+
+use App\Jobs\Video\WechatCheck;
+use GuzzleHttp\Psr7\Utils;
+use PHPUnit\Framework\TestCase;
+
+class WechatCheckTest extends \Tests\TestCase
+{
+
+    public function testGetMaterialId()
+    {
+        $wechatCheck = new WechatCheck([]);
+        $url  = 'https://minifile-cdn.zvyhjkx.com/uploads/images/20230531/9NUcrj2Dfz1685513143.png';
+//        dump(fopen($url, 'r'));
+//        $url = '/Users/liuzejian/Pictures/images.png';
+//        dump(Utils::tryFopen($url, 'r'));
+        $accessToken = '70_8irXfqI0X-CVZh_2kd5UylnUIaAONdTv9AglcuYqNXwUdhiPylun0aNlOPTNl3nXamPo_WJEcu9XstHMSVtRZh4PQw0SAKxrKOKDL2VvxIvaCpnzSw54DWs95b8VUYcAIARQU';
+        $result = $wechatCheck->getMaterialId($url, $accessToken);
+        dump($result);
+    }
+}

+ 55 - 0
tests/Service/Callback/JLEventReportChargeServiceTest.php

@@ -0,0 +1,55 @@
+<?php
+
+namespace Tests\Service\Callback;
+
+use App\Service\Callback\JLEventReportChargeService;
+use PHPUnit\Framework\TestCase;
+
+class JLEventReportChargeServiceTest extends \Tests\TestCase
+{
+    public function  testRate() {
+        $report = 0;
+        $unreport = 0;
+        $sm = explode(':', '1:4');
+        $s = $sm[0];
+        $m = $sm[1];
+
+        $obj = (object)[
+            'f' => true,
+            'report' => 0,
+            'unreport' => 0,
+        ];
+
+        foreach (range(1, 35) as $i) {
+            $this->insertR($obj, $s, $m);
+            if($obj->f) {
+                dump('回传');
+                $obj->report++;
+            } else {
+                dump('不回传');
+                $obj->unreport++;
+            }
+//            dump($obj);
+        }
+
+
+    }
+
+    public function insertR($obj, $s, $m) {
+        if($obj->f) {
+            if(($obj->report)  < $s){
+                $obj->f = true;
+            } else {
+                $obj->report = 0;
+                $obj->f = false;
+            }
+        } else {
+            if(($obj->unreport) < $m) {
+                $obj->f = false;
+            } else {
+                $obj->unreport = 0;
+                $obj->f = true;
+            }
+        }
+    }
+}