直接调用阿里云视频点播API实现视频播放

时间:2022-08-31 22:53:14

前言:公司最近要实现一个视频播放的功能,正常是不需要移动端调用阿里云视频API的,这件事是由后台来完成的。但是既然需求交给我了,就要想办法完成。

先来看一眼官方的API调用文档
https://help.aliyun.com/document_detail/44435.html?spm=5176.product29932.6.618.DUYkdb

有人会说了你直接扔出个阿里云的API你这不是搞笑吗?少侠勿急,且听我细细道来。

调用流程
你要想GET请求网络,请求需要你一些参数,参数的第一位便是签名其余的便是一些公共参数,或者请求特定接口的一些参数。接下来我就要说一下签名的生成过程。

生成签名的过程
就以阿里云获取视频列表的接口为例

final String HTTP_METHOD = "GET";
final String SEPARATOR = "&";
final String EQUAL = "=";

private static final String ENCODE_TYPE = "UTF-8";
String Timestamp = formatIso8601Date(new Date());
String SignatureNonce = UUID.randomUUID().toString();
 Map<String, String> parameterMapX = new HashMap<String, String>();
        //=============7大公共参数==================================
        parameterMapX.put("Format", "JSON");
        parameterMapX.put("Version", "2017-03-21");
        parameterMapX.put("SignatureMethod", "HMAC-SHA1");
        parameterMapX.put("SignatureVersion", "1.0");
        parameterMapX.put("AccessKeyId", WJ_Home_AccessKey);
        parameterMapX.put("Timestamp", Timestamp); 
        parameterMapX.put("SignatureNonce", SignatureNonce);//随机数
        //=============分割线下的是特有参数==================================
        parameterMapX.put("Action", "GetVideoList");
        parameterMapX.put("PageNo", "1");
        parameterMapX.put("PageSize", "10");
        parameterMapX.put("CateId", CateId);//视频分类id可以不用传,默认是-1
        List<String> sortedKeys = new ArrayList<String>(parameterMapX.keySet());
        Collections.sort(sortedKeys);
         //开始生成签名
        String PuR8IfTyWIan = GoToSign(sortedKeys, parameterMapX);
        //拼接url请求网络了,我这里用的是nohttp的get请求 3.X
          NetworkRequestX(PuR8IfTyWIan);
   //计算ISO8601时间方法
    private static String formatIso8601Date(Date date) {
        SimpleDateFormat df = new SimpleDateFormat(ISO8601_DATE_FORMAT);
        df.setTimeZone(new SimpleTimeZone(0, "GMT"));
        return df.format(date);
    }
  //转码工具类
    private static String percentEncode(String value) {
        if (value == null) return null;
        try {
            return URLEncoder.encode(value, ENCODE_TYPE).replace("+", "%20").replace("*", "%2A").replace("%7E", "~");
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }
        return value;
    }

这里我把获取签名封装成了一个方法,更方便大家的使用

   private String GoToSign(List<String> sortedKeys, Map<String, String> parameterMap) {
        StringBuilder stringToSign = new StringBuilder();
        stringToSign.append(HTTP_METHOD).append(SEPARATOR);
        stringToSign.append(percentEncode("/")).append(SEPARATOR); //拼接的时候要进行转码
        StringBuilder QueryString = new StringBuilder();
        for (String key : sortedKeys) {
            // 此处需要对key和value进行编码
            String value = parameterMap.get(key);
            QueryString.append(SEPARATOR).append(percentEncode(key)).
            append(EQUAL).append(percentEncode(value));
        }
   //获取拼接的字符串 **拼接样式见1.X** 
  StringBuilder append = stringToSign.append(percentEncode(QueryString.toString().substring(1)));

      //**hmac_sha1算法的第一个参数是密钥+&** 一定要加&
        String PuR8IfTyWIan = hmac_sha1(AccessSecret+&, append.toString()).trim();
      //通过Hmac_sha1算法计算出的 **拼接样式见2.X**
        return PuR8IfTyWIan;
    }
 private String hmac_sha1(String key, String datas) {
        String reString = "";

        try {
            byte[] data = key.getBytes("UTF-8");
            //根据给定的字节数组构造一个密钥,第二参数指定一个密钥算法的名称
            SecretKey secretKey = new SecretKeySpec(data, "HmacSHA1");
            //生成一个指定 Mac 算法 的 Mac 对象
            Mac mac = Mac.getInstance("HmacSHA1");
            //用给定密钥初始化 Mac 对象
            mac.init(secretKey);

            byte[] text = datas.getBytes("UTF-8");
            //完成 Mac 操作
            byte[] text1 = mac.doFinal(text);

            reString = Base64.encodeToString(text1, Base64.DEFAULT);

        } catch (Exception e) {
            // TODO: handle exception
        }

        return reString;
    }

拼接样式1.X

GET&%2F&AccessKeyId%3DLTAIPuR8IfTyWIan%26Action%3DGetVideoPlayAuth%26Format%3DJSON%26SignatureMethod%3DHMAC-SHA1%26SignatureNonce%3D578a50c1-280d-4a34-bffc-e0sda6b2df76%26SignatureVersion%3D1.0%26Timestamp%3D2017-08-11T08%253A56%253A39Z%26Version%3D2017-03-21%26VideoId%3D86d0a02dfccc46bab045d954e6b70036

拼接样式2.X

9or7epLWdsgMIvtRlJZm57HpBGs=

样式3.X
直接调用阿里云视频点播API实现视频播放

最后我强调一点 就是拼接URL这一点(我在拼接的时候没有进行转码,也能请求成功!)

我的URL

 http://vod.cn-shanghai.aliyuncs.com?Signature=7K0h2pa/JS4KdC6XEKiYrw7a3EU=&SignatureNonce=bb8d6d93-e56c-4e76-b7d8-f4be3490b7e6&Format=JSON&CateId=133999353&SignatureMethod=HMAC-SHA1&Timestamp=2017-08-13T13%3A15%3A22Z&SignatureVersion=1.0&Action=GetVideoList&Version=2017-03-21&PageNo=1&PageSize=10&AccessKeyId=LTAIPuR8IfTyWIan

阿里云的URL

http://vod.cn-shanghai.aliyuncs.com?Signature=UI%2FwKfuvTtphzCKHwPhP0ErtLnc%3D&SignatureVersion=1.0&Action=GetVideoPlayAuth&Format=JSON&VideoId=68a4d2629a339db3207963ac073a88cd&SignatureNonce=578a50c1-280d-4a34-bffc-e06aa6b2df76&Version=2017-03-21&AccessKeyId=testId&SignatureMethod=HMAC-SHA1&Timestamp=2017-03-29T12%3A09%3A11Z

有人就会说了为什么你不跟着阿里爸爸方法走呢?
经过hmac_sha1我的转码后的签名,

UI%2QcKDaeGtplzCJHwPhP0ErtLnc%3DOA

阿里云的转码后的签名

UI%2FwKfuvTtphzCKHwPhP0ErtLnc%3D

为什么没有跟阿里爸爸的方法走,是因为我转码过后就多出个0A,如果按照阿里云的调用方式最后等待我的结果只有SignatureDoesNotMatch


API给的方法是这样的

 // 生成请求URL
    StringBuilder requestURL;
    requestURL = new StringBuilder("http://vod.cn-shanghai.aliyuncs.com?");
    requestURL.append(URLEncoder.encode("Signature", ENCODE_TYPE)).append("=").append(signature);
    for (Map.Entry<String, String> e : parameterMap.entrySet()) {
    requestURL.append("&").append(percentEncode(e.getKey())).append("=").append(percentEncode(e.getValue()));

因为它把集合中的数据进行了转码,当生成了URL,你对这个url进行请求的时候InvalidTimeStamp.Format时间戳格式不对

解决办法

requestURL.append("&").append(e.getKey()).append("=").append(e.getValue());

希望这篇博客可以帮助到你