JAVA调用直播接口详述

一、userId、appId、appSecret值的获取

developer
在直播管理后台,点击开发设置,在显示的页面中获取userId、appId、appSecret值。

二、sign生成规则

将请求所需所有参数按照参数名字典顺序排列,连接参数名与参数值,并在首尾加上appSecret,然后计算MD5,将MD5结果转为16进制、大写字母,作为sign。

三、Java 接口调用示例

1、接口请求示例

private static void testBasic() {
        String url = "http://api.polyv.net/live/v3/channel/basic/get";
        // 用户对应的appId和加密串
        String appId = "xxxxxxx";
        String appSecret = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx";
        // 查询频道号
        String channelId = "415174";

        Map<String, String> params = new HashMap<>();
        params.put("channelId", channelId);
        // 调用Polyv的工具类方法设置sign
        PolyvTool.setLiveSign(params, appId, appSecret);
        // 调用Polyv的httpClient工具类发送请求
        String content = HttpClientUtil.getInstance()
                .sendHttpGet(url + "?" + PolyvTool.mapJoinNotEncode(params));
        System.out.println(content);
    }

2、生成sign结果示例

// 请求参数(这里为频道号)
channelId = "415174";
// appId和appSecret
appId = "egyszbtsd58";
appSecret = "6ef8d34c08f44e91a18e28d42ff0da7e";
// 时间戳
timeStamp = "1594369061376";
// 拼接后字符串
6ef8d34c08f44e91a18e28d42ff0da7eappIdegyszbtsd58channelId415174timestamp15943690613766ef8d34c08f44e91a18e28d42ff0da7e
// 加密串
7DEDD50579ECB5E5062954DBA10ADCA1

四、Java sign签名生成工具类

import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;

/**
 * polyv工具类
 */
public class PolyvTool {

    /**
     * 获取加密串
     */
    public static void setLiveSign(Map<String, String> params, String appId, String key) {
        params.put("sign", getSign(params, appId, key));
    }

    /**
     * 获取加密串
     */
    public static String getSign(Map<String, String> params, String appId, String key) {
        params.put("appId", appId);
        params.put("timestamp", String.valueOf(System.currentTimeMillis()));
        // 处理参数,计算MD5哈希值
        String concatStr = concatParams(params);
        String plain = key + concatStr + key;
        System.out.println("request signStr=" + plain);
        String encrypted = md5Hex(plain);
        // 32位大写MD5值
        return encrypted.toUpperCase();
    }

    /**
     * 把数组所有元素排序,并按照“参数参数值”的模式成字符串,用于计算MD5哈希值
     * @param params 需要排序并参与字符拼接的参数组
     * @return 拼接后字符串
     */
    public static String concatParams(Map<String, String> params) {
        List<String> keys = new ArrayList<>(params.keySet());
        Collections.sort(keys);

        StringBuilder sb = new StringBuilder();
        for (String key : keys) {
            String value = params.get(key);
            if (isBlank(value)) {
                continue;
            }
            sb.append(key).append(value);
        }
        return sb.toString();
    }

    /**
     * 对字符串做MD5加密,返回加密后的字符串。
     * @param text 待加密的字符串。
     * @return 加密后的字符串。
     */
    public static String md5Hex(String text) {
        try {
            MessageDigest messageDigest = MessageDigest.getInstance("MD5");
            byte[] inputByteArray = text.getBytes();
            messageDigest.update(inputByteArray);
            byte[] resultByteArray = messageDigest.digest();
            return byteArrayToHex(resultByteArray).toLowerCase();
        } catch (NoSuchAlgorithmException e) {
            return null;
        }
    }

    /**
     * 将字节数组换成成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);
    }


    /**
     * url 参数串连但是不进行参数Encode
     * @param map map
     * @return string
     */
    public static String mapJoinNotEncode(Map<String, String> map) {
        StringBuilder stringBuilder = new StringBuilder();
        int i = 0;
        for (Map.Entry<String, String> entry : map.entrySet()) {
            String key = entry.getKey();
            String value = entry.getValue();
            if (isBlank(value)) {
                continue;
            }
            if (0 != i) {
                stringBuilder.append("&");
            }
            stringBuilder.append(key).append("=").append(map.get(key));
            i++;
        }
        return stringBuilder.toString();
    }

    /**
     * url 参数串连
     * @param map map
     * @param keyLower keyLower
     * @param valueUrlEncode valueUrlEncode
     * @return string
     */
    public static String mapJoin(Map<String, String> map, boolean keyLower, boolean valueUrlEncode) {
        StringBuilder stringBuilder = new StringBuilder();
        for (Map.Entry<String, String> entry : map.entrySet()) {
            String key = entry.getKey();
            String value = entry.getValue();
            if (isBlank(value)){
                continue;
            }

            try {
                String temp = (key.endsWith("_") && key.length() > 1) ? key.substring(0, key.length() - 1) : key;
                stringBuilder.append(keyLower ? temp.toLowerCase() : temp)
                        .append("=")
                        .append(valueUrlEncode ? URLEncoder.encode(value, "utf-8").replace("+", "%20") : value)
                        .append("&");
            } catch (UnsupportedEncodingException e) {
                System.out.println(e.getMessage());
            }
        }
        if (stringBuilder.length() > 0) {
            stringBuilder.deleteCharAt(stringBuilder.length() - 1);
        }
        return stringBuilder.toString();
    }

    /**
     * 判断字符是否为空
     * @param cs 字符
     * @return true/false
     */
    public static boolean isBlank(CharSequence cs) {
        int strLen;
        if (cs != null && (strLen = cs.length()) != 0) {
            for(int i = 0; i < strLen; ++i) {
                if (!Character.isWhitespace(cs.charAt(i))) {
                    return false;
                }
            }

            return true;
        } else {
            return true;
        }
    }
}

五、Java http请求调用工具类

注:该工具类仅为示例(非必须),客户可以按照自己的方式进行接口请求,如需在生产环境使用该工具类,客户需按需进行httpClient的一些配置优化

1、使用该工具类需要引入apache的工具包,下面提供该工具包的maven引用方式

<dependency>
   <groupId>org.apache.httpcomponents</groupId>
   <artifactId>httpclient</artifactId>
   <version>4.5</version>
</dependency>
<dependency>
  <groupId>org.apache.httpcomponents</groupId>
  <artifactId>httpmime</artifactId>
  <version>4.5</version>
</dependency>

2、http请求工具类代码

import java.io.File;
import java.security.KeyManagementException;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import javax.net.ssl.SSLContext;

import org.apache.http.Header;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.NameValuePair;
import org.apache.http.client.HttpClient;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpDelete;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.methods.HttpRequestBase;
import org.apache.http.client.utils.HttpClientUtils;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.entity.ContentType;
import org.apache.http.entity.StringEntity;
import org.apache.http.entity.mime.HttpMultipartMode;
import org.apache.http.entity.mime.MultipartEntityBuilder;
import org.apache.http.entity.mime.content.FileBody;
import org.apache.http.entity.mime.content.StringBody;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.ssl.SSLContextBuilder;
import org.apache.http.util.EntityUtils;
import org.springframework.http.MediaType;

/**
 * httpclient的操作实现类
 */
public class HttpClientUtil {

    private static final String QUESTION_MARK = "?";
    private static final String DEFAULT_ENCODING = "UTF-8";

    // 需根据接口调用情况设置不同的超时时间
    private final RequestConfig requestConfig = RequestConfig.custom().setSocketTimeout(10000).setConnectTimeout(10000)
            .setConnectionRequestTimeout(10000).build();

    private static HttpClientUtil instance = null;

    private HttpClient ignoreSslClient;

    private HttpClient client;

    private HttpClientUtil() {
        this.ignoreSslClient = createHttpsClient(true);
        this.client = createHttpsClient(false);
    }

    public static HttpClientUtil getInstance() {
        if (instance == null) {
            instance = new HttpClientUtil();
        }
        return instance;
    }

    private HttpClient getHttpClient(boolean ignoreSsl) {
        return ignoreSsl ? ignoreSslClient : client;
    }

    /**
     * 发送 post请求
     * @param httpUrl 地址
     * @return 请求结果
     */
    public String sendHttpPost(String httpUrl) {
        HttpPost httpPost = new HttpPost(httpUrl);
        return sendHttpPost(httpPost);
    }

    /**
     * 发送 post请求
     * @param httpUrl 地址
     * @param params 参数(格式:json格式的内容)
     * @param headers 请求头
     * @return 请求结果
     */
    public String sendHttpPostJson(String httpUrl, String params, Map<String, String> headers) {
        return sendHttpPostJson(httpUrl, params, headers, false);
    }

    /**
     * 发送 post请求
     * @param httpUrl 地址
     * @param params 参数(格式:json格式的内容)
     * @param headers 请求头
     * @param ignoreSsl 是否跳过证书校验,true为跳过 false为不跳过
     * @return 请求结果
     */
    public String sendHttpPostJson(String httpUrl, String params, Map<String, String> headers, boolean ignoreSsl) {
        // 创建httpPost
        HttpPost httpPost = new HttpPost(httpUrl);
        try {
            // 设置参数
            StringEntity stringEntity = new StringEntity(params, DEFAULT_ENCODING);
            stringEntity.setContentType(MediaType.APPLICATION_JSON_UTF8_VALUE);
            httpPost.setEntity(stringEntity);
            if (null != headers && headers.size() > 0) {
                for (String name : headers.keySet()) {
                    httpPost.addHeader(name, headers.get(name));
                }
            }
        } catch (Exception e) {
            System.out.println(e.getMessage());
        }
        return sendHttpRequest(httpPost, ignoreSsl);
    }

    /**
     * 发送 post请求
     * @param httpUrl 地址
     * @param maps 参数
     * @param body 请求体
     * @return 请求结果
     */
    public String sendHttpPost(String httpUrl, Map<String, String> maps, String body) {
        String paramStr = PolyvTool.mapJoinNotEncode(maps);
        if (null != paramStr) {
            paramStr = QUESTION_MARK + paramStr;
        }
        String urlStr = httpUrl + paramStr;
        HttpPost httpPost = new HttpPost(urlStr);
        try {
            StringEntity entity = new StringEntity(body, DEFAULT_ENCODING);
            entity.setContentType(MediaType.APPLICATION_JSON_UTF8_VALUE);
            httpPost.setEntity(entity);
        } catch (Exception e) {
            System.out.println(e.getMessage());
        }
        return sendHttpRequest(httpPost, true);
    }

    /**
     * 发送 post请求
     * @param httpUrl 地址
     * @param params 参数(格式:key1=value1&key2=value2)
     * @return 请求结果
     */
    public String sendHttpPost(String httpUrl, String params) {
        return sendHttpPostWithHeader(httpUrl, params, null);
    }

    /**
     * 发送 post请求
     * @param httpUrl 地址
     * @param headers 头
     * @param params 参数(格式:key1=value1&key2=value2)
     * @return 请求结果
     */
    public String sendHttpPostWithHeader(String httpUrl, String params, Header[] headers) {
        HttpPost httpPost = new HttpPost(httpUrl);
        try {
            if (null != headers) {
                httpPost.setHeaders(headers);
            }
            // 设置参数
            StringEntity stringEntity = new StringEntity(params, DEFAULT_ENCODING);
            stringEntity.setContentType(MediaType.APPLICATION_FORM_URLENCODED_VALUE);
            httpPost.setEntity(stringEntity);
        } catch (Exception e) {
            System.out.println(e.getMessage());
        }
        return sendHttpPost(httpPost);
    }

    /**
     * 发送 post请求
     * @param httpUrl 地址
     * @param maps 参数
     * @return 请求结果
     */
    public String sendHttpPost(String httpUrl, Map<String, String> maps) {
        return sendHttpPostWithHeader(httpUrl, maps, null);
    }

    /**
     * 发送 post请求
     * @param httpUrl 地址
     * @param maps 参数
     * @return 请求结果
     */
    public String sendHttpPostWithHeader(String httpUrl, Map<String, String> maps, Header[] headers) {
        HttpPost httpPost = new HttpPost(httpUrl);
        if (null != headers) {
            httpPost.setHeaders(headers);
        }
        // 创建参数队列
        List<NameValuePair> nameValuePairs = new ArrayList<>();
        for (String key : maps.keySet()) {
            nameValuePairs.add(new BasicNameValuePair(key, maps.get(key)));
        }
        try {
            httpPost.setEntity(new UrlEncodedFormEntity(nameValuePairs, DEFAULT_ENCODING));
        } catch (Exception e) {
            System.out.println(e.getMessage());
        }
        return sendHttpPost(httpPost);
    }

    /**
     * 发送 get请求
     * @param httpUrl 地址
     * @param headers 请求头
     * @return 请求结果
     */
    public String sendHttpGet(String httpUrl, Map<String, String> headers) {
        // 创建httpGet
        HttpGet httpGet = new HttpGet(httpUrl);
        try {
            if (null != headers && headers.size() > 0) {
                for (String name : headers.keySet()) {
                    httpGet.addHeader(name, headers.get(name));
                }
            }
        } catch (Exception e) {
            System.out.println(e.getMessage());
        }
        return sendHttpGet(httpGet);
    }

    /**
     * 发送 post请求(带文件)
     * @param httpUrl 地址
     * @param maps 参数
     * @param fileLists 附件
     * @return 请求结果
     */
    public String sendHttpPost(String httpUrl, Map<String, String> maps, List<File> files, String fileParamName) {
        HttpPost httpPost = new HttpPost(httpUrl);
        MultipartEntityBuilder meBuilder = MultipartEntityBuilder.create();
        // 设置此参数后可以保证服务器拿到的文件名不会出现乱码
        meBuilder.setMode(HttpMultipartMode.RFC6532);
        for (String key : maps.keySet()) {
            meBuilder.addPart(key, new StringBody(maps.get(key), ContentType.TEXT_PLAIN));
        }
        for (File file : files) {
            FileBody fileBody = new FileBody(file);
            fileParamName = (null == fileParamName) ? "files" : fileParamName;
            meBuilder.addPart(fileParamName, fileBody);
        }
        HttpEntity reqEntity = meBuilder.build();
        httpPost.setEntity(reqEntity);
        return sendHttpPost(httpPost);
    }

    /**
     * 发送 post请求(带文件)
     * @param httpUrl 地址
     * @param maps 参数
     * @param file 上传文件
     * @param fileParamName 上传文件参数名
     */
    private static String sendHttpPost(String httpUrl, Map<String, String> maps, File file, String fileParamName) {
        fileParamName = (null == fileParamName) ? "file" : fileParamName;
        return sendHttpPost(httpUrl, maps, file, fileParamName);
    }

    /**
     * 发送Post请求
     * @param httpPost post请求
     * @return 请求结果
     */
    private String sendHttpPost(HttpPost httpPost) {
        return sendHttpRequest(httpPost);
    }

    /**
     * 发送 get请求
     * @param httpUrl 请求的路径
     * @return 成功时为响应内容,失败时为 null
     */
    public String sendHttpGet(String httpUrl) {
        // 创建get请求
        HttpGet httpGet = new HttpGet(httpUrl);
        return sendHttpGet(httpGet);
    }

    /**
     * 发送DELETE请求
     * @param httpUrl 请求的路径
     * @return 成功时为响应内容,失败时为 null
     */
    public String sendHttpDelete(String httpUrl) {
        HttpDelete httpDelete = new HttpDelete(httpUrl);
        return sendHttpRequest(httpDelete);
    }

    /**
     * 发送 get请求Https
     * @param httpUrl 请求的路径
     * @param ignoreSSLCerts 是否忽略证书校验
     */
    public String sendHttpsGet(String httpUrl, boolean ignoreSslCerts) {
        HttpGet httpGet = new HttpGet(httpUrl);
        return sendHttpsGet(httpGet, ignoreSslCerts);
    }

    /**
     * 发送Get请求
     * @param httpGet 请求
     * @return 成功时为响应内容,失败时为 null
     */
    private String sendHttpGet(HttpGet httpGet) {
        return sendHttpRequest(httpGet);
    }

    /**
     * 发送Get请求
     * @param requestBase 请求
     * @return 成功时为响应内容,失败时为 null
     */
    private String sendHttpRequest(HttpRequestBase requestBase) {
        return sendHttpRequest(requestBase, false);
    }

    /**
     * 发送请求
     * @param requestBase 请求
     * @param ignoreSslCerts 忽略证书和域名校验
     * @return 成功时为响应内容,失败时为 null
     */
    private String sendHttpRequest(HttpRequestBase requestBase, boolean ignoreSslCerts) {
        HttpResponse response = null;
        HttpEntity entity;
        try {
            // 创建默认的httpClient实例.
            requestBase.setConfig(requestConfig);
            // 执行请求
            response = getHttpClient(ignoreSslCerts).execute(requestBase);
            entity = response.getEntity();
            return EntityUtils.toString(entity, DEFAULT_ENCODING);
        } catch (Exception e) {
            System.out.println(e.getMessage());
        } finally {
            HttpClientUtils.closeQuietly(response);
        }
        return null;
    }

    /**
     * 发送Get请求Https
     * ignoreSSLCerts参数为true可以忽略证书和域名的校验,可以避免 {@link sun.security.validator.ValidatorException}
     * @param httpGet 使用https发送get请求
     * @param ignoreSSLCerts 忽略证书和域名校验
     * @return 返回内容
     */
    private String sendHttpsGet(HttpGet httpGet, boolean ignoreSslCerts) {
        HttpResponse response = null;
        String responseContent = null;
        try {
            httpGet.setConfig(requestConfig);
            // 执行请求
            response = getHttpClient(ignoreSslCerts).execute(httpGet);
            HttpEntity entity = response.getEntity();
            responseContent = EntityUtils.toString(entity, DEFAULT_ENCODING);
        } catch (Exception e) {
            System.out.println(e.getMessage());
        } finally {
            HttpClientUtils.closeQuietly(response);
        }
        return responseContent;
    }

    /**
     * 初始化https请求Client
     * @param ignoreSSLCerts 忽略证书
     */
    private CloseableHttpClient createHttpsClient(boolean ignoreSslCerts) {
        CloseableHttpClient httpClient;
        if (ignoreSslCerts) {
            SSLContext ctx = null;
            try {
                // 忽略客户端证书校验
                ctx = new SSLContextBuilder().loadTrustMaterial(null, (chain, authType) -> true).build();
            } catch (NoSuchAlgorithmException | KeyManagementException | KeyStoreException e) {
                System.out.println("create ssl context error");
            }

            // 忽略证书和hostName校验
            httpClient = HttpClients.custom()
                    .setSSLHostnameVerifier((host, session) -> true)
                    .setSSLSocketFactory(new SSLConnectionSocketFactory(ctx)).build();
        } else {
            httpClient = HttpClients.createDefault();
        }
        return httpClient;
    }
}
以上内容是否对您有帮助?根本没有帮助文档较差文档一般文档不错文档很好
Loading...

签名生成规则

一、userId、appId、appSecret值的获取

developer
在直播管理后台,点击开发设置,在显示的页面中获取userId、appId、appSecret值。

二、sign生成规则

将请求所需所有参数按照参数名字典顺序排列,连接参数名与参数值,并在首尾加上appSecret,然后计算MD5,将MD5结果转为16进制、大写字母,作为sign。

三、Java sign生成示例

String appId = "XXXXXXXX";
String userId = "XXXXXXXX";
String appSecret = "XXXXXXXXXXXXXXXXXXXXXXXX";

long ts = System.currentTimeMillis();
// 创建参数表 (创建接口需要传递的所有参数表)
Map<String, String> paramMap = new HashMap<String, String>();
paramMap.put("appId", appId);
paramMap.put("timestamp", Long.toString(ts));

//对参数名进行字典排序
String[] keyArray = paramMap.keySet().toArray(new String[0]);
Arrays.sort(keyArray);

//拼接有序的参数串
StringBuilder stringBuilder = new StringBuilder();
stringBuilder.append(appSecret);
for (String key : keyArray) {
    stringBuilder.append(key).append(paramMap.get(key));
}

stringBuilder.append(appSecret);
String signSource = stringBuilder.toString();

String sign = org.apache.commons.codec.digest.DigestUtils.md5Hex(signSource).toUpperCase();
System.out.println("http://api.polyv.net/live/v1/users/" + userId + "/channels?appId=" + appId + "&timestamp=" + ts + "&sign=" + sign);

四、PHP sign生成示例

1、config.php文件代码

<?php
//签名验证必需参数
$appId = "XXXXXXXXX";
$timestamp = time()*1000;
$appSecret = "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX";

//获取sign函数
function getSign($params){
    global $appSecret;
    // 1. 对加密数组进行字典排序
    foreach ($params as $key=>$value){
     $arr[$key] = $key;
    }
    sort($arr);
    $str = $appSecret;
    foreach ($arr as $k => $v) {
     $str = $str.$arr[$k].$params[$v];
    }
    $restr = $str.$appSecret;
    $sign = strtoupper(md5($restr));
    return $sign;
}
?>

2、接口请求示例

<?php

//引用config.php
include 'config.php';

//接口需要的参数(非sign)赋值
$userId = "XXXXXXXXX";

$params = array(
    'appId'=>$appId,
    'timestamp'=>$timestamp
  );

//生成sign
$sign = getSign($params); //详细查看config.php文件的getSign方法

//接口请求url
$url ="http://api.polyv.net/live/v1/users/".$userId."/channels?appId=".$appId."&timestamp=".$timestamp."&sign=".$sign;

//输出接口请求结果
$ch = curl_init() or die ( curl_error() );
curl_setopt( $ch, CURLOPT_URL, $url);
curl_setopt ($ch, CURLOPT_CUSTOMREQUEST, "GET");
curl_setopt( $ch, CURLOPT_RETURNTRANSFER, 1 );
curl_setopt( $ch, CURLOPT_CONNECTTIMEOUT, 360);
$response = curl_exec ( $ch );
curl_close ( $ch );
//打印获得的数据
print_r($response);

?>
以上内容是否对您有帮助?根本没有帮助文档较差文档一般文档不错文档很好
Loading...