Ver código fonte

短视频同步到微信

liuzejian 1 ano atrás
pai
commit
a33ea82840

+ 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),
+                                ]);
+                        }
+                    }
+                }
+            });
+    }
+}

+ 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, '充值模板不存在'];
@@ -27,4 +27,8 @@ class Errors
     public const  BANK_CARD_STATUS_ERROR = [500202, '银行卡不存在或当前状态不可提现'];
     public const  TIXIAN_RECORD_NOT_EXISTS = [500203, '提现记录不存在'];
     public const  TIXIAN_ONLY_ONCE_EVERY_DAY = [500204, '每天只能提现一次'];
+    public const  VIDEO_SERIES_NOT_EXISTS = [500301, '剧集不存在'];
+    public const REQUEST_HTTP_STATUS_ERROR = [500401, '请求上游接口返回http状态码有误'];
+    public const REQUEST_CODE_STATUS_ERROR = [500402, '请求上游接口返回code状态码有误'];
+    public const SYNC_WECHAT_NOT_OK = [500302, '剧集没有成功同步到微信'];
 }

+ 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')
+    ]
 ];

+ 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;
+    }
+}

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

@@ -0,0 +1,117 @@
+<?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) {
+        $client = new Client(['timeout' => 3]);
+        $httpResult = $client->post('https://api.weixin.qq.com/wxa/sec/vod/pullupload?access_token='.$accessToken, [
+            'media_name' => $item->media_name,
+            'media_url' => $item->video_url
+        ]);
+
+        $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('拉取上传异常', [
+                'series_id' => $item->id,
+                'errMsg' => $httpContent
+            ]);
+            CommonBusinessException::throwError(Errors::REQUEST_HTTP_STATUS_ERROR);
+        }
+        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_HTTP_STATUS_ERROR);
+        }
+
+        return $parsedContent;
+    }
+}