Browse Source

Merge branch 'master' of qk:zy_duanju/duanju_manage into test

admin 1 year ago
parent
commit
077ef97243

+ 62 - 0
app/Console/Commands/Video/WechatCheckGetTask.php

@@ -0,0 +1,62 @@
+<?php
+
+namespace App\Console\Commands\Video;
+
+use Illuminate\Console\Command;
+use Illuminate\Support\Facades\DB;
+use Modules\Video\Services\WechatCheckSyncService;
+
+class WechatCheckGetTask extends Command
+{
+    /**
+     * The name and signature of the console command.
+     *
+     * @var string
+     */
+    protected $signature = 'Video:WechatCheckGetTask {--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('task_id', $taskIdArr);
+            })->orderBy('id', 'asc')
+            ->chunk(100, function ($items) {
+                $now = date('Y-m-d H:i:s');
+                foreach ($items as $item) {
+                    $taskInfo = WechatCheckSyncService::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),
+                                ]);
+                        }
+                    }
+                }
+            });
+    }
+}

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

@@ -9,6 +9,9 @@ use Illuminate\Foundation\Bus\Dispatchable;
 use Illuminate\Queue\InteractsWithQueue;
 use Illuminate\Queue\SerializesModels;
 
+/**
+ * 剧目提审,真实处理逻辑在 duanju_crontab_script 项目
+ */
 class WechatCheck implements ShouldQueue
 {
     use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;

+ 5 - 1
modules/Common/Errors/Errors.php

@@ -10,7 +10,7 @@ class Errors
     public const  PARAM_ERROR= [500004, '参数错误'];
     public const  NO_OPERATE_PERMISSION= [500007, '用户无操作权限'];
     public const  VIDEO_NOT_EXISTS= [500008, '视频不存在'];
-    public const  MINIPROGRAM_STATUS_ERROR= [500005, '小程序未启用'];
+    public const  MINIPROGRAM_STATUS_ERROR= [50005, '小程序未启用'];
     public const  PAY_TEMPLATE_EXISTS_ERROR= [500006, '充值模板已经存在'];
     public const  PAY_TEMPLATE_GIVEN_TOO_MUCH= [500007, '赠送不能超过金额3倍'];
     public const  PAY_TEMPLATE_NOT_EXISTS_ERROR= [500008, '充值模板不存在'];
@@ -28,4 +28,8 @@ class Errors
     public const  TIXIAN_RECORD_NOT_EXISTS = [500203, '提现记录不存在'];
     public const  TIXIAN_ONLY_ONCE_EVERY_DAY = [500204, '每天只能提现一次'];
     public const  OPERATION_FIRST_PAGE_LIST_NOT_EXISTS = [500301, '首页列表配置项不存在'];
+    public const  VIDEO_SERIES_NOT_EXISTS = [500302, '剧集不存在'];
+    public const REQUEST_HTTP_STATUS_ERROR = [500401, '请求上游接口返回http状态码有误'];
+    public const REQUEST_CODE_STATUS_ERROR = [500402, '请求上游接口返回code状态码有误'];
+    public const SYNC_WECHAT_NOT_OK = [500302, '剧集没有成功同步到微信'];
 }

+ 4 - 4
modules/Common/config/common.php

@@ -2,14 +2,14 @@
 
 return [
     'logos' => [
-        '2' => 'https://zhuishuyun.oss-cn-hangzhou.aliyuncs.com/channel/logo/DOUYIN.png',
-        '1' => 'https://zhuishuyun.oss-cn-hangzhou.aliyuncs.com/channel/logo/WEIXIN.png',
-        'QQ' => 'https://zhuishuyun.oss-cn-hangzhou.aliyuncs.com/channel/logo/QQ.png',
+        '2' => 'https://minifile-cdn.zvyhjkx.com/logo/DOUYIN.png',
+        '1' => 'https://minifile-cdn.zvyhjkx.com/logo/WEIXIN.png',
+        'QQ' => 'https://minifile-cdn.zvyhjkx.com/logo/QQ.png',
     ],
     /**
      * 短剧管理后台的域名
      */
-    'duanjuManageDomain' => env('COMMON_DUANJU_MANAGE_DOMAIN', 'http://m.test.duanju.dududus.com'),
+    'duanjuManageDomain' => env('COMMON_DUANJU_MANAGE_DOMAIN', 'https://manage.zhiyupa.com'),
     /**
      * 模块和小程序type值的映射
      */

+ 1 - 1
modules/Manage/Http/Controllers/MiniprogramController.php

@@ -110,7 +110,7 @@ class MiniprogramController extends CatchController
             $validate_result['pay_merchant_id'] = 0;
             $validate_result['pay_merchant_info'] = [];
         }
-        
+
         return $this->miniprogram->create($validate_result)->toArray();
 
     }

+ 31 - 0
modules/Manage/Services/WechatMiniprogramService.php

@@ -0,0 +1,31 @@
+<?php
+
+namespace Modules\Manage\Services;
+
+use Illuminate\Support\Facades\Redis;
+
+class WechatMiniprogramService
+{
+    /**
+     * 微信短剧提审appid
+     * @return string
+     */
+    public static function getDuanjuCheckAppid() {
+        return config('manage.miniprogram.duanjuWechatCheck.appid');
+    }
+
+    /**
+     * 微信短剧提审小程序 accessToken
+     * @param string|null $appid
+     * @return string
+     */
+    public static function getDuanjuCheckAccessToken($appid=null) {
+        $checkAppid = $appid ?: self::getDuanjuCheckAppid();
+
+        return Redis::get(self::getAccessTokenRedisKey($checkAppid));
+    }
+
+    private static function getAccessTokenRedisKey($appid) {
+        return 'dj.miniWechat.at.' . $appid;
+    }
+}

+ 7 - 2
modules/Manage/config/miniprogram.php

@@ -4,9 +4,14 @@
  * 小程序配置
  */
 return [
-    
+
     'typelist'=>[
         'WEIXIN','BYTECODE'
     ],
-    
+    /**
+     * 微信短剧提审小程序
+     */
+    'duanjuWechatCheck' => [
+        'appid' => env('MINIPROGRAM_DUANJU_WECHATCHEECK_APPID', 'wx86822355ccd03a78')
+    ]
 ];

+ 1 - 1
modules/Operation/Http/Controllers/FirstPageController.php

@@ -27,7 +27,7 @@ class FirstPageController extends CatchController
             ->paginate($request->input('limit', 15));
         foreach ($result as $item) {
             $item->type_str = $firstPageListTypeMap[$item->type]['label'] ?? '';
-            $item->duanjus = collect(\json_decode($item->duanjus, true))->sortBy('sort');
+            $item->duanjus = collect(\json_decode($item->duanjus, true))->sortBy('sort')->values();
             $item->miniprogram_type_str = $miniprogramTypeMap[$item->miniprogram_type]['label'] ?? '';
         }
         return $result;

+ 80 - 0
modules/Video/Http/Controllers/VideoSeriesWechatCheckController.php

@@ -0,0 +1,80 @@
+<?php
+
+namespace Modules\Video\Http\Controllers;
+
+use Catch\Base\CatchController;
+use Illuminate\Foundation\Validation\ValidatesRequests;
+use Illuminate\Http\Request;
+use Illuminate\Support\Facades\DB;
+use Illuminate\Support\Facades\Redis;
+use Modules\Common\Errors\Errors;
+use Modules\Common\Exceptions\CommonBusinessException;
+use Modules\Manage\Services\WechatMiniprogramService;
+use Modules\Video\Services\WechatCheckSyncService;
+
+class VideoSeriesWechatCheckController extends CatchController
+{
+    use ValidatesRequests;
+    /**
+     * 剧集同步到微信
+     * @param Request $request
+     */
+    public function syncWechat(Request $request) {
+        $this->validate($request, [
+            'series_ids' => 'required|array'
+        ]);
+        $series_ids = $request->input('series_ids');
+        $series = DB::table('video_series')
+            ->join('videos', 'video_series.video_id', 'videos.id')
+            ->whereIn('video_series.id', $series_ids)
+            ->where(['video_series.is_enabled' => 1])
+            ->select('videos.name', 'video_series.series_sequence','video_series.id', 'video_series.video_key')
+            ->get();
+        if(collect($series_ids)->count() != $series->count()) {
+            CommonBusinessException::throwError(Errors::VIDEO_SERIES_NOT_EXISTS);
+        }
+        $appid = WechatMiniprogramService::getDuanjuCheckAppid();
+        $accessToken = WechatMiniprogramService::getDuanjuCheckAccessToken($appid);
+        $now = date('Y-m-d H:i:s');
+        foreach ($series as $item) {
+            $item->video_url = config('common.qiniu.publicVideoLinkDomain') . DIRECTORY_SEPARATOR . $item->video_key;
+            $item->media_name = sprintf('%s - 第%s集', $item->name, $item->series_sequence);
+            $taskId = WechatCheckSyncService::pullupload($item, $accessToken);
+            DB::table('video_series_wechat_check')
+                ->where(['series_id' => $item->id, 'is_enabled' => 1])
+                ->update(['is_enabled' => 0, 'updated_at' => $now]);
+            DB::table('video_series_wechat_check')
+                ->insert([
+                    'series_id' => $item->id,
+                    'sync_task_id' => $taskId, 'appid' => $appid,
+                    'created_at' => $now, 'updated_at' => $now
+                ]);
+        }
+
+        return 'ok';
+    }
+
+    /**
+     * 获取微信那边的剧集播放链接
+     * @param Request $request
+     * @return mixed
+     * @throws \Illuminate\Validation\ValidationException
+     */
+    public function medialink(Request $request) {
+        $this->validate($request, [
+            'series_id' => 'required'
+        ]);
+
+        $seriesId = $request->input('series_id');
+        $redisKey = WechatCheckSyncService::getWechatMediaLinkRedisKey($seriesId);
+        $link = Redis::get($redisKey);
+        if($link) {
+            return $link;
+        }
+
+        $medialinkInfo = WechatCheckSyncService::getMedialinkInfo($seriesId);
+        $link = $medialinkInfo['mp4_url'];
+        Redis::setex($redisKey, 6000, $link);
+        return $link;
+    }
+}

+ 103 - 0
modules/Video/Services/WechatCheckSyncService.php

@@ -0,0 +1,103 @@
+<?php
+
+namespace Modules\Video\Services;
+
+use GuzzleHttp\Client;
+use Illuminate\Support\Facades\DB;
+use Modules\Common\Errors\Errors;
+use Modules\Common\Exceptions\CommonBusinessException;
+use Modules\Manage\Services\WechatMiniprogramService;
+
+
+class WechatCheckSyncService
+{
+    /**
+     * 拉取上传
+     * @param $item 剧集信息
+     * @param $accessToken 小程序accessToken
+     * @return  string task_id
+     * @throws \GuzzleHttp\Exception\GuzzleException
+     */
+    public static function pullupload($item, $accessToken) {
+        $url = 'https://api.weixin.qq.com/wxa/sec/vod/pullupload?access_token='.$accessToken;
+        $parsedContent = self::postWechat($url, [
+            'media_name' => $item->media_name,
+            'media_url' => $item->video_url
+        ]);
+        return $parsedContent['task_id'];
+    }
+
+    /**
+     * 获取微信短剧剧集的播放链接信息
+     * @param $seriesId
+     * @return mixed
+     * @throws \GuzzleHttp\Exception\GuzzleException
+     */
+    public static function getMedialinkInfo($seriesId) {
+        $syncInfo = DB::table('video_series_wechat_check')
+            ->where([
+                'series_id'=> $seriesId,
+                'sync_status' => 3,
+                'is_enabled' => 1,
+            ])->first();
+
+        if(!$syncInfo || !$syncInfo->media_id) {
+            CommonBusinessException::throwError(Errors::SYNC_WECHAT_NOT_OK);
+        }
+        $mediaId = $syncInfo->media_id;
+        $accessToken = WechatMiniprogramService::getDuanjuCheckAccessToken($syncInfo->appid);
+        $url = 'https://api.weixin.qq.com/wxa/sec/vod/getmedialink?access_token='.$accessToken;
+
+        $parsedContent = self::postWechat($url, [
+            'media_id' => $mediaId,
+            't' => time() + 7200,
+        ]);
+        return $parsedContent['media_info'];
+    }
+
+    public static function getWechatMediaLinkRedisKey($seriesId) {
+        return 'wechat.medialink.'.$seriesId;
+    }
+
+    public static function getTask($syncInfo) {
+        try {
+            $accessToken = WechatMiniprogramService::getDuanjuCheckAccessToken($syncInfo->appid);
+            $url = 'https://api.weixin.qq.com/wxa/sec/vod/gettask?access_token='.$accessToken;
+            $parsedContent = self::postWechat($url, [
+                'task_id' => $syncInfo->sync_task_id
+            ]);
+            return $parsedContent['task_info'];
+        } catch (\Exception $exception) {
+            return [];
+        }
+
+    }
+
+    /**
+     *  post 请求微信上游
+     * @param $url
+     * @param $data
+     * @throws \GuzzleHttp\Exception\GuzzleException
+     */
+    public static function postWechat($url, $data) {
+        $client = new Client(['timeout' => 3]);
+        $httpResult = $client->post($url, $data);
+
+        $httpStatus = $httpResult->getStatusCode();
+        if(200 != $httpStatus) {
+            CommonBusinessException::throwError(Errors::REQUEST_HTTP_STATUS_ERROR);
+        }
+        $httpContent = $httpResult->getBody()->getContents();
+        $parsedContent = \json_decode($httpContent, true);
+        if(0 != ($parsedContent['errcode'] ?? 0)) {
+            myLog('WechatCheckSync')->error('请求微信异常', [
+                'url' => $url,
+                'data' => $data,
+                'errMsg' => $httpContent
+            ]);
+            CommonBusinessException::throwError(Errors::REQUEST_CODE_STATUS_ERROR);
+        }
+
+        return $parsedContent;
+    }
+}

+ 5 - 0
modules/Video/routes/route.php

@@ -4,6 +4,7 @@ use Illuminate\Support\Facades\Route;
 use Modules\Video\Http\Controllers\EpisodeController;
 use Modules\Video\Http\Controllers\VideoCategoryController;
 use Modules\Video\Http\Controllers\VideoController;
+use Modules\Video\Http\Controllers\VideoSeriesWechatCheckController;
 use Modules\Video\Http\Controllers\WechatCheckController;
 
 Route::prefix('videoStock')->group(function () {
@@ -22,6 +23,10 @@ Route::prefix('videoStock')->group(function () {
         Route::post('add', [WechatCheckController::class, 'add']);
         Route::get('list', [WechatCheckController::class, 'list']);
         Route::post('delete', [WechatCheckController::class, 'delete']);
+        Route::prefix('videoSeries')->group(function(){
+            Route::post('syncWechat', [VideoSeriesWechatCheckController::class, 'syncWechat']);
+        });
     });
+
 });
 

+ 22 - 0
tests/Video/Http/Controllers/VideoSeriesWechatCheckControllerTest.php

@@ -0,0 +1,22 @@
+<?php
+
+namespace Tests\Video\Http\Controllers;
+
+use Modules\Video\Http\Controllers\VideoSeriesWechatCheckController;
+use PHPUnit\Framework\TestCase;
+use Tests\UsedTestCase;
+
+class VideoSeriesWechatCheckControllerTest extends UsedTestCase
+{
+
+    public function testSyncWechat()
+    {
+        $res = $this->withHeaders([
+            'Authorization' => 'Bearer '. $this->token,
+        ])->json('post','http://localhost/api/videoStock/wechatCheck/videoSeries/syncWechat', [
+            'series_ids' => [81,82,83,84,85],
+        ]);
+        $res->dump();
+        $this->dumpJson($res);
+    }
+}