Przeglądaj źródła

add 保利威播放凭证

he2802 4 lat temu
rodzic
commit
238925bf0f

+ 15 - 17
zhongzheng-admin/src/main/java/com/zhongzheng/controller/polyv/PolyvVideoController.java

@@ -1,37 +1,25 @@
 package com.zhongzheng.controller.polyv;
 
-import java.util.List;
-import java.util.Arrays;
-
+import com.zhongzheng.common.core.domain.model.LoginUser;
+import com.zhongzheng.common.utils.ServletUtils;
+import com.zhongzheng.framework.web.service.TokenService;
 import com.zhongzheng.modules.polyv.vo.PolyvVideoQuerVo;
 import lombok.RequiredArgsConstructor;
 import org.springframework.security.access.prepost.PreAuthorize;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.web.bind.annotation.GetMapping;
-import org.springframework.web.bind.annotation.PostMapping;
-import org.springframework.web.bind.annotation.PutMapping;
-import org.springframework.web.bind.annotation.DeleteMapping;
 import org.springframework.web.bind.annotation.PathVariable;
-import org.springframework.web.bind.annotation.RequestBody;
 import org.springframework.web.bind.annotation.RequestMapping;
 import org.springframework.web.bind.annotation.RestController;
-import com.zhongzheng.common.annotation.Log;
 import com.zhongzheng.common.core.controller.BaseController;
 import com.zhongzheng.common.core.domain.AjaxResult;
-import com.zhongzheng.common.enums.BusinessType;
-import com.zhongzheng.modules.polyv.vo.PolyvVideoVo;
-import com.zhongzheng.modules.polyv.bo.PolyvVideoQueryBo;
-import com.zhongzheng.modules.polyv.bo.PolyvVideoAddBo;
-import com.zhongzheng.modules.polyv.bo.PolyvVideoEditBo;
 import com.zhongzheng.modules.polyv.service.IPolyvVideoService;
-import com.zhongzheng.common.utils.poi.ExcelUtil;
-import com.zhongzheng.common.core.page.TableDataInfo;
 import io.swagger.annotations.Api;
 import io.swagger.annotations.ApiOperation;
 
 /**
  * 保利威视频信息Controller
- * 
+ *
  * @author ruoyi
  * @date 2021-06-11
  */
@@ -43,7 +31,8 @@ public class PolyvVideoController extends BaseController {
 
     private final IPolyvVideoService iPolyvVideoService;
 
-
+    @Autowired
+    private TokenService tokenService;
     /**
      * 获取保利威视频信息详细信息
      */
@@ -54,6 +43,15 @@ public class PolyvVideoController extends BaseController {
         return AjaxResult.success(iPolyvVideoService.queryById(vid));
     }
 
+    @ApiOperation("获取保利威视频播放凭证")
+    @PreAuthorize("@ss.hasPermi('modules.polyv:video:query')")
+    @GetMapping("/sign/{vid}")
+    public AjaxResult<String> getPlayPcSign(@PathVariable("vid") String vid) throws Exception {
+        LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest());
+        String viewerId = String.valueOf(loginUser.getUser().getUserId());
+        String token = iPolyvVideoService.polyvbPcSignRequest(vid,viewerId);
+        return AjaxResult.success("成功",token);
+    }
 
 
    /* *//**

+ 125 - 0
zhongzheng-common/src/main/java/com/zhongzheng/common/utils/SnowflakeIdUtils.java

@@ -0,0 +1,125 @@
+package com.zhongzheng.common.utils;
+
+public class SnowflakeIdUtils {
+    // ==============================Fields===========================================
+    /** 开始时间截 (2015-01-01) */
+    private final long twepoch = 1420041600000L;
+
+    /** 机器id所占的位数 */
+    private final long workerIdBits = 5L;
+
+    /** 数据标识id所占的位数 */
+    private final long datacenterIdBits = 5L;
+
+    /** 支持的最大机器id,结果是31 (这个移位算法可以很快的计算出几位二进制数所能表示的最大十进制数) */
+    private final long maxWorkerId = -1L ^ (-1L << workerIdBits);
+
+    /** 支持的最大数据标识id,结果是31 */
+    private final long maxDatacenterId = -1L ^ (-1L << datacenterIdBits);
+
+    /** 序列在id中占的位数 */
+    private final long sequenceBits = 12L;
+
+    /** 机器ID向左移12位 */
+    private final long workerIdShift = sequenceBits;
+
+    /** 数据标识id向左移17位(12+5) */
+    private final long datacenterIdShift = sequenceBits + workerIdBits;
+
+    /** 时间截向左移22位(5+5+12) */
+    private final long timestampLeftShift = sequenceBits + workerIdBits + datacenterIdBits;
+
+    /** 生成序列的掩码,这里为4095 (0b111111111111=0xfff=4095) */
+    private final long sequenceMask = -1L ^ (-1L << sequenceBits);
+
+    /** 工作机器ID(0~31) */
+    private long workerId;
+
+    /** 数据中心ID(0~31) */
+    private long datacenterId;
+
+    /** 毫秒内序列(0~4095) */
+    private long sequence = 0L;
+
+    /** 上次生成ID的时间截 */
+    private long lastTimestamp = -1L;
+
+    //==============================Constructors=====================================
+    /**
+     * 构造函数
+     * @param workerId 工作ID (0~31)
+     * @param datacenterId 数据中心ID (0~31)
+     */
+    public SnowflakeIdUtils(long workerId, long datacenterId) {
+        if (workerId > maxWorkerId || workerId < 0) {
+            throw new IllegalArgumentException(String.format("worker Id can't be greater than %d or less than 0", maxWorkerId));
+        }
+        if (datacenterId > maxDatacenterId || datacenterId < 0) {
+            throw new IllegalArgumentException(String.format("datacenter Id can't be greater than %d or less than 0", maxDatacenterId));
+        }
+        this.workerId = workerId;
+        this.datacenterId = datacenterId;
+    }
+
+    // ==============================Methods==========================================
+    /**
+     * 获得下一个ID (该方法是线程安全的)
+     * @return SnowflakeId
+     */
+    public synchronized long nextId() {
+        long timestamp = timeGen();
+
+        //如果当前时间小于上一次ID生成的时间戳,说明系统时钟回退过这个时候应当抛出异常
+        if (timestamp < lastTimestamp) {
+            throw new RuntimeException(
+                    String.format("Clock moved backwards.  Refusing to generate id for %d milliseconds", lastTimestamp - timestamp));
+        }
+
+        //如果是同一时间生成的,则进行毫秒内序列
+        if (lastTimestamp == timestamp) {
+            sequence = (sequence + 1) & sequenceMask;
+            //毫秒内序列溢出
+            if (sequence == 0) {
+                //阻塞到下一个毫秒,获得新的时间戳
+                timestamp = tilNextMillis(lastTimestamp);
+            }
+        }
+        //时间戳改变,毫秒内序列重置
+        else {
+            sequence = 0L;
+        }
+
+        //上次生成ID的时间截
+        lastTimestamp = timestamp;
+
+        //移位并通过或运算拼到一起组成64位的ID
+        return ((timestamp - twepoch) << timestampLeftShift) //
+                | (datacenterId << datacenterIdShift) //
+                | (workerId << workerIdShift) //
+                | sequence;
+    }
+
+    /**
+     * 阻塞到下一个毫秒,直到获得新的时间戳
+     * @param lastTimestamp 上次生成ID的时间截
+     * @return 当前时间戳
+     */
+    protected long tilNextMillis(long lastTimestamp) {
+        long timestamp = timeGen();
+        while (timestamp <= lastTimestamp) {
+            timestamp = timeGen();
+        }
+        return timestamp;
+    }
+
+    /**
+     * 返回以毫秒为单位的当前时间
+     * @return 当前时间(毫秒)
+     */
+    protected long timeGen() {
+        return System.currentTimeMillis();
+    }
+
+
+
+}

+ 171 - 13
zhongzheng-common/src/main/java/com/zhongzheng/common/utils/http/HttpUtils.java

@@ -1,33 +1,41 @@
 package com.zhongzheng.common.utils.http;
 
-import java.io.BufferedReader;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.InputStreamReader;
-import java.io.PrintWriter;
-import java.net.ConnectException;
-import java.net.SocketTimeoutException;
-import java.net.URL;
-import java.net.URLConnection;
+import java.io.*;
+import java.net.*;
 import java.security.cert.X509Certificate;
+import java.util.*;
 import javax.net.ssl.HostnameVerifier;
 import javax.net.ssl.HttpsURLConnection;
 import javax.net.ssl.SSLContext;
 import javax.net.ssl.SSLSession;
 import javax.net.ssl.TrustManager;
 import javax.net.ssl.X509TrustManager;
+
+
+import org.apache.http.NameValuePair;
+import org.apache.http.client.entity.UrlEncodedFormEntity;
+import org.apache.http.client.methods.CloseableHttpResponse;
+import org.apache.http.client.methods.HttpPost;
+import org.apache.http.client.methods.HttpUriRequest;
+import org.apache.http.impl.client.CloseableHttpClient;
+import org.apache.http.impl.client.HttpClientBuilder;
+import org.apache.http.message.BasicNameValuePair;
+import org.apache.http.util.EntityUtils;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
-import com.zhongzheng.common.constant.Constants;
+import org.apache.http.HttpEntity;
+
 
 /**
  * 通用http发送方法
- * 
+ *
  * @author zhongzheng
  */
 public class HttpUtils
 {
     private static final Logger log = LoggerFactory.getLogger(HttpUtils.class);
+    private static final String UTF8 = "UTF-8";
+    private static final String APPLICATION_FORM_URLENCODED = "application/x-www-form-urlencoded; charset=UTF-8";
 
     /**
      * 向指定 URL 发送GET方法的请求
@@ -38,7 +46,7 @@ public class HttpUtils
      */
     public static String sendGet(String url, String param)
     {
-        return sendGet(url, param, Constants.UTF8);
+        return sendGet(url, param, UTF8);
     }
 
     /**
@@ -103,6 +111,12 @@ public class HttpUtils
         }
         return result.toString();
     }
+    public static String postFormBody(String url, Map<String, String> paramMap) throws IOException{
+        return post(url, paramMap, null);
+
+    }
+
+
 
     /**
      * 向指定 URL 发送POST方法的请求
@@ -259,4 +273,148 @@ public class HttpUtils
             return true;
         }
     }
-}
+
+    /**
+     * 公共数据解析接口
+     * @param <T>
+     */
+    private interface DataParse<T> {
+        /**
+         * 解析返回数据
+         * @param httpEntity 返回实体
+         * @param encoding 编码
+         * @return 实际解析返回内容
+         * @throws IOException io异常
+         */
+        T parseData(HttpEntity httpEntity, String encoding) throws IOException;
+
+    }
+
+    /**
+     * 将url与map拼接成HTTP查询字符串
+     * @param url 请求url
+     * @param paramMap 需要拼装的map
+     * @return 拼装好的url
+     */
+    public static String appendUrl(String url, Map<String, String> paramMap) throws UnsupportedEncodingException {
+        if (paramMap == null) {
+            return url;
+        }
+        StringBuffer paramStringBuffer = new StringBuffer();
+        Iterator<Map.Entry<String, String>> mapIterator = paramMap.entrySet().iterator();
+        while (mapIterator.hasNext()) {
+            Map.Entry<String, String> next = mapIterator.next();
+            paramStringBuffer.append(next.getKey()).append("=").append(URLEncoder.encode(next.getValue(), UTF8)).append("&");
+        }
+        String paramStr = paramStringBuffer.toString();
+//        String paramStr = mapJoinNotEncode(paramMap);
+        if (paramStr != null && !"".equals(paramStr)) {
+            if (url.indexOf("?") > 0) {
+                if (url.endsWith("&")) {
+                    url += paramStr.substring(0, paramStr.length() - 1);
+                } else {
+                    url += "&" + paramStr.substring(0, paramStr.length() - 1);
+                }
+            } else {
+                url += "?" + paramStr.substring(0, paramStr.length() - 1);
+            }
+        }
+        return url;
+    }
+
+    /**
+     * 向url发送post请求表单提交数据
+     * @param url 请求url
+     * @param paramMap 表单数据
+     * @param encoding 编码
+     * @return 请求返回的数据
+     * @throws IOException 读写异常
+     */
+    private static String post(String url, Map<String, String> paramMap, String encoding) throws IOException {
+        log.debug("http 请求 url: {} , 请求参数: {}", url, appendUrl("", paramMap).replace("?", ""));
+        encoding = encoding == null ? UTF8 : encoding;
+        // 创建post方式请求对象
+        HttpPost httpPost = new HttpPost(url);
+        // 装填参数
+        List<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>();
+        if (paramMap != null) {
+            for (Map.Entry<String, String> entry : paramMap.entrySet()) {
+                String value = entry.getValue();
+                //去掉如下判断会造成String类型的value为null时
+                if (value != null) {
+                    nameValuePairs.add(new BasicNameValuePair(entry.getKey(), value));
+                }
+            }
+        }
+        // 设置参数到请求对象中
+        httpPost.setEntity(new UrlEncodedFormEntity(nameValuePairs, encoding));
+        // 设置header信息
+        // 指定报文头【Content-type】、【User-Agent】
+        httpPost.setHeader("Content-type", APPLICATION_FORM_URLENCODED);
+        return post(url, httpPost, encoding, new DataParse<String>() {
+            @Override
+            public String parseData(HttpEntity httpEntity, String encoding) throws IOException {
+                return EntityUtils.toString(httpEntity, encoding);
+            }
+        });
+    }
+
+    /**
+     * 向url发送post请求
+     * @param url 请求url
+     * @param httpPost httpClient
+     * @return 请求返回的数据
+     * @throws IOException 读写异常
+     */
+    private static <T> T post(String url, HttpPost httpPost, String encoding, DataParse<T> dataParse)
+            throws IOException {
+        T result = null;
+        CloseableHttpResponse response = null;
+        // 创建httpclient对象
+        CloseableHttpClient httpClient = HttpClientBuilder.create().build();
+
+        // 执行请求操作,并拿到结果(同步阻塞)
+        response = sendRequestAndGetResult(url, httpClient, httpPost);
+        // 获取结果实体
+        // 判断网络连接状态码是否正常(0--200都数正常)
+        if (null != response) {
+            result = dataParse.parseData(response.getEntity(), encoding);
+            log.debug("http 请求结果: {}", result);
+        }
+        try {
+            if (null != response) {
+                response.close();
+            }
+        } catch (IOException ex) {
+            log.error(ex.getMessage(), ex);
+        }
+        return result;
+    }
+
+    /**
+     * 设置http头,发送http请求,打印请求耗时
+     * @param url 请求url
+     * @param httpClient httpClient
+     * @param httpUriRequest httpUriRequest
+     * @return 请求返回的数据
+     * @throws IOException 读写异常
+     */
+    private static CloseableHttpResponse sendRequestAndGetResult(String url, CloseableHttpClient httpClient,
+                                                                 HttpUriRequest httpUriRequest) throws IOException {
+        long startTime = System.currentTimeMillis();
+        CloseableHttpResponse response = httpClient.execute(httpUriRequest);
+        long endTime = System.currentTimeMillis();
+        collectAPISpendTime(url, startTime, endTime);
+        return response;
+    }
+
+    /**
+     * 打印请求信息
+     * @param url 请求url
+     * @param startTime 请求开始时间
+     * @param endTime 请求结束时间
+     */
+    private static void collectAPISpendTime(String url, long startTime, long endTime) {
+        log.debug("HTTP请求耗时分析,请求URL: {} , 耗时: {} ms", url, endTime - startTime);
+    }
+}

+ 74 - 0
zhongzheng-common/src/main/java/com/zhongzheng/common/utils/polyv/PolyvUtils.java

@@ -3,6 +3,7 @@ package com.zhongzheng.common.utils.polyv;
 import com.alibaba.fastjson.JSONObject;
 import com.zhongzheng.common.utils.http.HttpUtils;
 
+import java.io.UnsupportedEncodingException;
 import java.nio.charset.StandardCharsets;
 import java.security.MessageDigest;
 import java.security.NoSuchAlgorithmException;
@@ -15,6 +16,8 @@ import java.util.*;
  */
 public class PolyvUtils {
 
+    private static final String UTF8 = "UTF-8";
+
 /*    public static void main(String[] args) throws Exception {
 
         Long ptime = System.currentTimeMillis();
@@ -57,7 +60,78 @@ public class PolyvUtils {
         return sb.toString();
     }
 
+    /**
+     * 获取直播加密字符串,并且假如到参数params中
+     * @param params 加密参数
+     * @param appSecret 保利威用户签名密钥
+     * @return  MD5签名字符串
+     * @throws NoSuchAlgorithmException 签名异常
+     *  @throws UnsupportedEncodingException 编码异常
+     */
+    public static String getSignMd5(Map<String, String> params, String appSecret)
+            throws NoSuchAlgorithmException, UnsupportedEncodingException {
+        // 处理参数,计算MD5哈希值
+        String concatStr = concatParams(params);
+        String plain = appSecret + concatStr + appSecret;
+        String encrypted = md5Hex(plain).toUpperCase();
+        // 32位大写MD5值
+        return encrypted;
+    }
 
+    /**
+     * 把数组所有元素排序,并按照“参数参数值”的模式成字符串,用于计算MD5哈希值
+     * @param params 需要排序并参与字符拼接的参数组
+     * @return 拼接后字符串
+     */
+    public static String concatParams(Map<String, String> params) {
+        List<String> keys = new ArrayList<String>(params.keySet());
+        Collections.sort(keys);
 
+        StringBuilder sb = new StringBuilder();
+        for (String key : keys) {
+            String value = params.get(key);
+            if (value == null || "".equals(value.trim())) {
+                continue;
+            }
+            sb.append(key).append(value);
+        }
+        return sb.toString();
+    }
+
+    /**
+     * 对字符串做MD5加密,返回加密后的字符串。
+     * @param text 待加密的字符串。
+     * @return 加密后的字符串。
+     * @throws NoSuchAlgorithmException 签名异常
+     *  @throws UnsupportedEncodingException 编码异常
+     */
+    public static String md5Hex(String text) throws NoSuchAlgorithmException, UnsupportedEncodingException {
+
+        MessageDigest messageDigest = MessageDigest.getInstance("MD5");
+        byte[] inputByteArray = text.getBytes(UTF8);
+        messageDigest.update(inputByteArray);
+        byte[] resultByteArray = messageDigest.digest();
+        return byteArrayToHex(resultByteArray).toLowerCase();
 
+    }
+
+    /**
+     * 将字节数组换成成16进制的字符串
+     * @param byteArray 字节
+     * @return 字符串
+     */
+    public static String byteArrayToHex(byte[] byteArray) {
+        // 初始化一个字符数组用来存放每个16进制字符
+        char[] hexDigits = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'};
+        // new一个字符数组,这个就是用来组成结果字符串的(一个byte是八位二进制,也就是2位十六进制字符(2的8次方等于16的2次方))
+        char[] resultCharArray = new char[byteArray.length * 2];
+        // 遍历字节数组,通过位运算(位运算效率高),转换成字符放到字符数组中去
+        int index = 0;
+        for (byte b : byteArray) {
+            resultCharArray[index++] = hexDigits[b >>> 4 & 0xf];
+            resultCharArray[index++] = hexDigits[b & 0xf];
+        }
+        // 字符数组组合成字符串返回
+        return new String(resultCharArray);
+    }
 }

+ 8 - 2
zhongzheng-framework/src/main/java/com/zhongzheng/framework/web/service/WxLoginService.java

@@ -7,6 +7,8 @@ import com.zhongzheng.common.core.bo.WxLoginResultBo;
 import com.zhongzheng.common.exception.CustomException;
 
 import com.zhongzheng.common.utils.AES;
+import com.zhongzheng.common.utils.SnowflakeIdUtils;
+import com.zhongzheng.common.utils.TelPhoneUtils;
 import com.zhongzheng.modules.user.bo.UserAddBo;
 import com.zhongzheng.modules.user.domain.User;
 import com.zhongzheng.modules.user.entity.ClientLoginUser;
@@ -68,7 +70,11 @@ public class WxLoginService
         bo.setOpenId(openId);
         bo.setUnionId(unionId);
         bo.setTelphone(tel);
-
+        //隐藏手机号作为初始昵称
+        bo.setNickname(TelPhoneUtils.hideTelPhone(tel));
+        //雪花算法产生账号ID
+        SnowflakeIdUtils idWorker = new SnowflakeIdUtils(3, 1);
+        bo.setUserAccout(String.valueOf(idWorker.nextId()));
         return null;
     }
 
@@ -87,7 +93,7 @@ public class WxLoginService
                     Base64.decodeBase64(iv));
 
             userInfo = new String(resultByte, "UTF-8");
-            System.out.println("userInfo:" + userInfo);
+
             userInfoJSON = JSON.parseObject(userInfo);
         } catch (Exception e) {
             e.printStackTrace();

+ 13 - 0
zhongzheng-system/src/main/java/com/zhongzheng/modules/polyv/domain/TokenResponse.java

@@ -0,0 +1,13 @@
+package com.zhongzheng.modules.polyv.domain;
+
+import lombok.Data;
+
+import java.io.Serializable;
+
+@Data
+public class TokenResponse implements Serializable {
+    int code;
+    String status;
+    String message;
+    Object data;
+}

+ 2 - 0
zhongzheng-system/src/main/java/com/zhongzheng/modules/polyv/service/IPolyvVideoService.java

@@ -50,4 +50,6 @@ public interface IPolyvVideoService extends IService<PolyvVideo> {
 	 * @return
 	 */
 	Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid);
+
+	String polyvbPcSignRequest(String VId,String viewerId) throws Exception;
 }

+ 65 - 2
zhongzheng-system/src/main/java/com/zhongzheng/modules/polyv/service/impl/PolyvVideoServiceImpl.java

@@ -3,16 +3,18 @@ package com.zhongzheng.modules.polyv.service.impl;
 import cn.hutool.core.bean.BeanUtil;
 import cn.hutool.core.convert.Convert;
 import cn.hutool.core.util.StrUtil;
-import cn.hutool.http.ContentType;
 import cn.hutool.http.HttpStatus;
 import com.alibaba.fastjson.JSONArray;
 import com.alibaba.fastjson.JSONObject;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.zhongzheng.common.core.redis.RedisCache;
 import com.zhongzheng.common.utils.DateUtils;
 import com.zhongzheng.common.utils.http.HttpUtils;
 import com.zhongzheng.common.utils.polyv.PolyvUtils;
 import com.zhongzheng.modules.polyv.domain.PolyvVideDo;
 import com.zhongzheng.modules.polyv.vo.PolyvVideoQuerVo;
-import net.bytebuddy.asm.Advice;
+import com.zhongzheng.modules.polyv.domain.TokenResponse;
+import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.beans.factory.annotation.Value;
 import org.springframework.stereotype.Service;
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
@@ -28,7 +30,9 @@ import com.zhongzheng.modules.polyv.vo.PolyvVideoVo;
 import com.zhongzheng.modules.polyv.service.IPolyvVideoService;
 import org.springframework.transaction.annotation.Transactional;
 
+import java.io.IOException;
 import java.util.*;
+import java.util.concurrent.TimeUnit;
 import java.util.stream.Collectors;
 
 /**
@@ -52,6 +56,9 @@ public class PolyvVideoServiceImpl extends ServiceImpl<PolyvVideoMapper, PolyvVi
     @Value("${poliv.token.secretkey}")
     private String poliv_token_secretkey;
 
+    @Autowired
+    private RedisCache redisCache;
+
     @Override
     @Transactional(rollbackFor = Exception.class)
     public PolyvVideoQuerVo queryById(String VId) throws Exception {
@@ -75,6 +82,60 @@ public class PolyvVideoServiceImpl extends ServiceImpl<PolyvVideoMapper, PolyvVi
         return polyvVideoQuerVo;
     }
 
+    /**
+     * PC播放加密视频
+     * @param VId
+     * @return
+     * @throws Exception
+     */
+    @Override
+    public String polyvbPcSignRequest(String VId,String viewerId) throws Exception {
+        viewerId = "ADMIN_"+ viewerId;
+        String redsKey = "PL_VIDEO_"+viewerId+VId;
+        String token = redisCache.getCacheObject(redsKey);
+        if(token!=null){
+            return token;
+        }
+        String secretKey = poliv_token_secretkey;
+        String userId = poliv_token_userid;
+        //业务参数
+        String url = "http://hls.videocc.net/service/v1/token";
+        String videoId = VId;
+        String ts = Long.toString(System.currentTimeMillis());
+        int expireTime = 30;//分钟
+        String disposable = "false"; //true:token仅一次有效
+        String iswxa = "0"; //是否微信小程序播放
+
+        Map<String, String> requestMap = new HashMap<>();
+        requestMap.put("userId", userId);
+        requestMap.put("videoId", videoId);
+        requestMap.put("ts", ts);
+        requestMap.put("viewerId", viewerId);
+        requestMap.put("expires", String.valueOf((expireTime*60))); //令牌有效期半小时
+        requestMap.put("disposable", disposable);
+        requestMap.put("iswxa", iswxa);
+
+        //用md5进行签名
+        requestMap.put("sign", PolyvUtils.getSignMd5(requestMap, secretKey));
+
+        String response = HttpUtils.postFormBody(url, requestMap);
+        try {
+            //解析json
+            ObjectMapper objectMapper = new ObjectMapper();
+            TokenResponse tokenResponse = objectMapper.readValue(response, TokenResponse.class);
+            // 响应代码,200为成功,403为ts过期或签名错误,400为参数错误(例如缺少 userId 或 videoId)
+            if (tokenResponse.getCode() == 200) {
+                Map data = (Map) tokenResponse.getData();
+                token = data.get("token").toString();
+                redisCache.setCacheObject(redsKey, token, expireTime, TimeUnit.MINUTES);
+                return token;
+            }
+        } catch (IOException e) {
+            e.printStackTrace();
+        }
+        return null;
+    }
+
 
 
     public void polyvbRequest(String VId) throws Exception {
@@ -208,4 +269,6 @@ public class PolyvVideoServiceImpl extends ServiceImpl<PolyvVideoMapper, PolyvVi
         }
         return this.removeByIds(ids);
     }
+
+
 }