Polyv Help Center

Help Center

Modify Account Points Donation Settings

Updated: 2022-09-02 18:08:07

Interface URL

http://api.polyv.net/live/v3/channel/donate/update-point

Interface Description

1、接口用于设置账号通用设置的积分打赏
2、通用参数通过普通url参数传递(timestamp, appId, sign),设置打赏参数的json通过请求体的方式传递
3、接口支持https

Supported Format

JSON

Request Method

POST

Request Parameters

Appended to the URL

Parameter Name Required Type Description
appId Yes string Obtained from API settings, the appId registered in the live streaming system
timestamp Yes long Current 13-digit timestamp
sign Yes String Signature, a 32-character uppercase MD5 value. The appSecret key used to generate the signature is critical for communication data security. It must never be saved or used directly on the client side. All APIs must be called through the customer's own server to relay requests to the POLYV server and obtain response data. For details, see Signature Generation Rules

Request Body Parameters

Parameter Name Required Type Description
donatePointEnabled Yes string Points donation toggle, values: Y/N
queryPointUrl Yes string API to retrieve viewer points donation
updatePointUrl Yes string API to modify viewer points donation
requestFailTips Yes string Prompt message when request fails
pointNotEnoughTips Yes string Prompt message when points are insufficient
pointUnit Yes string Points unit
goods Yes object[] List of donation items
goodName Yes string Item name, maximum 5 characters
goodImg Yes string Item image URL, maximum 120 characters (can use default URL or obtain via image upload API)
goodPrice Yes double Item donation price
goodEnabled Yes string Item toggle, values: Y/N, Y = enabled

Note: channelId, appId, timestamp, and sign must be passed as URL parameters, while JSON data is passed via the request body. Example: http://api.polyv.net/live/v3/channel/donate/update-point?appId={{appId}}&timestamp={{timestamp}}&sign={{sign}}

Request Body JSON Structure

{
    "donatePointEnabled": "Y",
    "queryPointUrl": "xxx",
    "updatePointUrl": "yyy",
    "requestFailTips": "请求失败了",
    "pointNotEnoughTips": "积分不足啊",
    "pointUnit": "Q币",
    "goods": [
        {
            "goodName": "鲜花123",
            "goodImg": "//livestatic.videocc.net/uploaded/images/webapp/channel/donate/01-flower.png",
            "goodPrice": 123,
            "goodEnabled": "N"
        },
        {
            "goodName": "大跑车",
            "goodImg": "//livestatic.videocc.net/uploaded/images/webapp/channel/donate/08-car.png",
            "goodPrice": 999,
            "goodEnabled": "Y"
        }
    ]
}

Successful Response JSON Example:

{
    "code": 200,
    "status": "success",
    "message": "",
    "data": ""
}

Failed Response JSON Example:

Parameter error

{
    "code": 400,
    "status": "error",
    "message": "param validate error",
    "data": 400
}

appId not provided

{
    "code": 400,
    "status": "error",
    "message": "appId is required.",
    "data": ""
}

Incorrect appId

{
    "code": 400,
    "status": "error",
    "message": "application not found.",
    "data": ""
}

Timestamp error

{
    "code": 400,
    "status": "error",
    "message": "invalid timestamp.",
    "data": ""
}

Signature error

{
    "code": 403,
    "status": "error",
    "message": "invalid signature.",
    "data": ""
}

JSON is empty or JSON parsing error

{
    "code": 400,
    "status": "error",
    "message": "param validate error",
    "data": ""
}

Goods count limit in JSON

{
    "code": 400,
    "status": "error",
    "message": "goods over limit",
    "data": ""
}

Goods name character limit in JSON

{
    "code": 400,
    "status": "error",
    "message": "goods name over limit",
    "data": ""
}

Goods image URL character limit in JSON

{
    "code": 400,
    "status": "error",
    "message": "goods image length over limit",
    "data": ""
}

Goods price data type error in JSON

{
    "code": 400,
    "status": "error",
    "message": "number range error",
    "data": ""
}

Field Description

Parameter Name Description
code Status code: 200 for success, 403 for signature failure, 400 for parameter error, 500 for server error
status "success" on success, "error" on error
message Empty string on success, error description on failure
data Currently has no function

Java Request Example

import com.live.util.EncryptionUtils;
import org.apache.http.HttpEntity;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;

import java.io.IOException;
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class Demo {

    private static RequestConfig requestConfig = RequestConfig.custom().setSocketTimeout(15000).setConnectTimeout(15000)
            .setConnectionRequestTimeout(15000).build();

    public static void main(String[] args) {
        
        String url = "http://api.polyv.net/live/v3/channel/donate/update-point";
        String appId = "XXXXXX";
        String key = "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX";
        Map<String, String> map = new HashMap<>();
        long timestamp = System.currentTimeMillis();
        map.put("appId", appId);
        map.put("timestamp", String.valueOf(timestamp));

        String sign = getSign(map, key);
        map.put("sign", sign);
        String body = "{\"goods\":[{\"goodName\":\"鲜花333\",\"goodImg\":\"//livestatic.videocc.net/uploaded/images/webapp/channel/donate/01-flower.png\",\"goodPrice\":0,\"goodEnabled\":\"Y\"},{\"goodName\":\"咖啡\",\"goodImg\":\"//livestatic.videocc.net/uploaded/images/webapp/channel/donate/02-coffee.png\",\"goodPrice\":0.99,\"goodEnabled\":\"Y\"},{\"goodName\":\"点赞\",\"goodImg\":\"//livestatic.videocc.net/uploaded/images/webapp/channel/donate/03-good.png\",\"goodPrice\":1.99,\"goodEnabled\":\"Y\"},{\"goodName\":\"掌声\",\"goodImg\":\"//livestatic.videocc.net/uploaded/images/webapp/channel/donate/04-applaud.png\",\"goodPrice\":2.99,\"goodEnabled\":\"Y\"},{\"goodName\":\"666\",\"goodImg\":\"//livestatic.videocc.net/uploaded/images/webapp/channel/donate/05-666.png\",\"goodPrice\":6.66,\"goodEnabled\":\"Y\"},{\"goodName\":\"小星星\",\"goodImg\":\"//livestatic.videocc.net/uploaded/images/webapp/channel/donate/06-star.png\",\"goodPrice\":9.99,\"goodEnabled\":\"Y\"},{\"goodName\":\"钻石\",\"goodImg\":\"//livestatic.videocc.net/uploaded/images/webapp/channel/donate/07-diamond.png\",\"goodPrice\":19.99,\"goodEnabled\":\"Y\"},{\"goodName\":\"跑车\",\"goodImg\":\"//livestatic.videocc.net/uploaded/images/webapp/channel/donate/08-car.png\",\"goodPrice\":29.99,\"goodEnabled\":\"Y\"},{\"goodName\":\"火箭233\",\"goodImg\":\"//livestatic.videocc.net/uploaded/images/webapp/channel/donate/09-rocket.png\",\"goodPrice\":66.66,\"goodEnabled\":\"Y\"}]}";
        String content = sendHttpPost(url, map, body);
        System.out.println(content);

    }

    /**
     * 发送 post请求
     * @param httpUrl 地址
     * @param maps 参数
     */
    public static String sendHttpPost(String httpUrl, Map<String, String> maps, String body) {
        StringBuilder url = new StringBuilder();
        url.append(httpUrl).append("?");
        for (Map.Entry<String, String> map : maps.entrySet()) {
            url.append(map.getKey()).append("=").append(map.getValue()).append("&");
        }
        String urlStr = url.toString().substring(0, url.length() - 1);
        // 创建httpPost
        HttpPost httpPost = new HttpPost(urlStr);
        try {
            StringEntity entity = new StringEntity(body, Charset.forName("UTF-8"));
            httpPost.setEntity(entity);
        } catch (Exception e) {
            // ...
        }
        return sendHttpPost(httpPost);
    }

    /**
     * 发送Post请求
     * @param httpPost
     * @return
     */
    private static String sendHttpPost(HttpPost httpPost) {
        CloseableHttpClient httpClient = null;
        CloseableHttpResponse response = null;
        HttpEntity entity;
        String responseContent = null;
        try {
            // 创建默认的httpClient实例.
            httpClient = HttpClients.createDefault();
            httpPost.setConfig(requestConfig);
            // 执行请求
            response = httpClient.execute(httpPost);
            entity = response.getEntity();
            responseContent = EntityUtils.toString(entity, "UTF-8");
        } catch (Exception e) {
            // ...
        } finally {
            try {
                // 关闭连接,释放资源
                if (response != null) {
                    response.close();
                }
                if (null != httpPost) {
                    httpPost.releaseConnection();
                }
                if (httpClient != null) {
                    httpClient.close();
                }
            } catch (IOException e) {
                // ...
            }
        }
        return responseContent;
    }

    /**
     * 根据map里的参数构建加密串
     * @param map
     * @param secretKey
     * @return
     */
    protected static String getSign(Map<String, String> map, String secretKey) {
        Map<String, String> params = paraFilter(map);
        // 处理参数,计算MD5哈希值
        String concatedStr = concatParams(params);
        String plain = secretKey + concatedStr + secretKey;
        String encrypted = EncryptionUtils.md5Hex(plain);

        // 32位大写MD5值
        return encrypted.toUpperCase();
    }

    /**
     * 对params根据key来排序并且以key1=value1&key2=value2的形式拼接起来
     * @param params
     * @return
     */
    private static String concatParams(Map<String, String> params) {
        List<String> keys = new ArrayList<>(params.keySet());
        Collections.sort(keys);

        StringBuilder sb = new StringBuilder();

        for (int i = 0; i < keys.size(); i++) {
            String key = keys.get(i);
            String value = params.get(key);

            sb.append(key).append(value);
        }

        return sb.toString();
    }

    /**
     * 除去数组中的空值和签名参数
     * @param sArray 签名参数组
     * @return 去掉空值与签名参数后的新签名参数组
     */
    private static Map<String, String> paraFilter(Map<String, String> sArray) {

        Map<String, String> result = new HashMap<>();

        if (sArray == null || sArray.size() <= 0) {
            return result;
        }

        for (String key : sArray.keySet()) {
            String value = sArray.get(key);
            if (value == null || value.equals("") || key.equalsIgnoreCase("sign")
                    || key.equalsIgnoreCase("sign_type")) {
                continue;
            }
            result.put(key, value);
        }

        return result;
    }

}

PHP Request Example

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

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

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

$json = '{"queryPointUrl": "xxx","updatePointUrl": "yyy","requestFailTips": "请求失败了","pointNotEnoughTips": "积分不足啊","pointUnit": "Q币","goods": [{"goodName": "鲜花123","goodImg": "//livestatic.videocc.net/uploaded/images/webapp/channel/donate/01-flower.png","goodPrice": 123,"goodEnabled": "N"},{"goodName": "大跑车","goodImg": "//livestatic.videocc.net/uploaded/images/webapp/channel/donate/08-car.png","goodPrice": 999,"goodEnabled": "Y"}]}';

$params["sign"] = $sign;
$url="http://api.polyv.net/live/v3/channel/donate/update-point?".http_build_query($params);

function post($url, $post_data = '', $timeout = 5){
   $ch = curl_init();
   curl_setopt ($ch, CURLOPT_URL, $url);
   curl_setopt ($ch, CURLOPT_POST, 1);
   if($post_data != ''){
      curl_setopt($ch, CURLOPT_POSTFIELDS, $post_data);
   }

   curl_setopt ($ch, CURLOPT_RETURNTRANSFER, 1);
   curl_setopt ($ch, CURLOPT_CONNECTTIMEOUT, $timeout);
   curl_setopt($ch, CURLOPT_HEADER, false);
   curl_setopt($ch, CURLOPT_HTTPHEADER, array('Content-Type: application/json', 'Content-Length: ' . strlen($post_data)));
   $file_contents = curl_exec($ch);
   curl_close($ch);
   return $file_contents;
}

echo post($url,$json);
?>
联系客服,在线咨询