You need to enable JavaScript to run this app.
导航

User Profile API(SaaS查看)

最近更新时间2024.04.30 15:17:27

首次发布时间2024.04.30 15:17:27

本文档仅针对SaaS版本,不支持SaaS云原生版本和私有化版本;
SaaS云原生版本和私有化版本接入请参考HTTP API文档中的上报用户属性模块。

1.概述

由于通过客户端SDK(APP、网站及小程序)和服务端SDK设置的用户属性,默认的计算逻辑都是按最终值查询,我们不会将它们与事件记录在一起,并且只会记录该属性的最新值,历史时刻的旧值会因新值的上报而被覆盖,查询时将该属性与事件按照用户口径进行关联。
如果我们希望事件能关联上事件上报时刻对应的旧值,通常推荐将该属性定义为事件属性或事件公共属性。对于某些必须将其定义为用户属性的场景,我们提供了 User Profile API。
使用这个接口,我们可以指定某个用户属性按全部值或最终值进行查询。对于按全部值查询的属性,我们不仅会记录最新的值,还会提前将用户属性的当前值与该用户同一时刻上报的事件记录在一起,从而保留了旧值(对于历史数据只会保留当日的最后一条旧值,详见下文1.2.2)。
下面的表格对比了通过客户端SDK(APP、网站及小程序)、服务端SDK以及User Profile API上报的用户属性的区别,希望能有助于您的理解:

区别

客户端SDK、服务端SDK

User Profile API

是否需要鉴权

是否需要提前定义属性

属性查询逻辑

最终值

全部值和最终值

是否支持上报事件

是否支持单独上报属性

是否会作用于已上报的事件

仅按最终值查询时

本文档涉及的上报和查询api接口,接口采用RestAPI规范。

1.1 支持的版本

火山引擎增长分析「SaaS版本」,不支持「SaaS云原生版本」和「私有化版本」

1.2 快速开始

1.2.1 开通功能

您可以通过页面右下角的工单功能或者联系您的客户成功经理告诉我们您要使用 User Profile API。我们会为您开通此功能,并将上报数据所需的 ak/sk 发送到您指定的邮箱。
完成开通后,您再次进入数据管理 > 用户属性就可以看到页面右上角多出“新增用户属性”的按钮。
图片

1.2.2 配置属性

点击“新增用户属性”可以在弹框中对您想添加的属性进行配置。
图片
其中计算逻辑的说明如下:

  • 分析全部值:分析该属性变化过程中出现的所有取值。例如:属性为“会员类别”,用户a在某天从“普通会员”升级到“VIP”,“VIP”是最新取值,则用户a发生的访问、购买等事件改变前会被归到“普通用户”上,改变当天和改变后会被归到“VIP”上。
  • 分析最终值:仅分析该属性变化的最终取值。例如:属性为“会员类别”,用户a在某天从“普通会员”升级到“VIP”,“VIP”是最新取值,则用户a历史上发生的访问、购买等所有事件都会归到“VIP”上。

使用分析全部值时需要特别注意的数据变更
如果某个属性一天内有多个值,则实时数据中该属性会如实记录这些值而在次日构建时仅会取最后一个值构建到非实时数据当中。
例如:
“等级”是一个分析全部值的属性,某日有一个用户的“等级”从3级升到4级,之后又升级到5级。那么在当天查询包含这个属性的事件时可以查询到一些事件关联的值是“3”、“4”或“5”。在次日构建时,会取最新值“5”构建到当日所有数据当中,因此在构建完成后再发起同样的查询时,相关事件的这个属性值就只能查看到“5”这个值了。
另外,与事件公共属性相比,类型为分析全部值的用户属性会与所有事件相关联,而事件公共属性仅限于某一端上报的全部事件。
确认后,用户属性中会出现一个新的属性,接下来就可以上报数据了。
图片

1.2.3 上报数据

完成属性配置后,可以按下文中的鉴权以及API用法进行接口调用完成数据上报。注意数据类型一定正确,类型错误的数据会被丢弃。

1.2.4 进行分析

当已经完成数据上报,并且属性没有被禁用的情况下。就可以在属性筛选、分组等处使用这些属性了。
图片

1.2.5 注意事项

1)该API使用qps上限500
2)uuid需要满足规则:[a-zA-Z_0-9\\-/]+
3)使用User Profile API进行属性上报时,对于未注册的用户,默认情况下不会进行自动注册,若需要开启自动注册功能,请联系您的客户成功经理进行配置。(注意:开启用户自动注册后,如该用户在客户端从匿名状态登录,可能会产生冗余的ssid,导致一个 uuid 对应多个 ssid,从而影响分析
4)使用User Profile API上报公共属性/用户属性时,请不要上报带"custom_"前缀的属性,也不要上报客户端SDK或服务端HTTP API支持的事件格式header里已有的属性;
5)对于datetime类型的数据,目前支持四种格式的datetime:

2020-07-07T13:46:08
2020-07-07 13:46:08

2020-07-07T13:46:08.342
2020-07-07 13:46:08.342

2020-07-07T13:46:08.342+08:00
2020-07-07 13:46:08.342+08:00

2020-07-07T13:46:08+08:00
2020-07-07 13:46:08+08:00

由于存在时区问题,所以:

  • 如果有特殊的时区要求,使用后4种格式上报,并指定正确的UTC;
    • 如果上报的UTC不对导致无法正确解析出时区,则先取接入app时配置的时区,若没有配置,则取Profile服务运行所在地的时区。
  • 对于使用前四种格式上报的时区默认先取接入app时配置的时区,若没有配置,则取Profile服务运行所在地的时区。

2.鉴权

通过提供AccessKey/SecretKey的方式鉴权,简写为ak/sk,AccessKey是app请求的唯一标识,SecretKey是app的密钥,它们相当于用户名和密码。注册app之后就会生成一个AccessKey和SecretKey,请妥善保存。在所有请求的header中包括如下鉴权信息:

Header

Type

Description

Required

Authorization

string

api鉴权使用(Global)

TRUE

  • 及appSecret的生成可联系客户经理
  • 可以使用我们提供的sdk帮助鉴权
  • Authorization的生成工具见示例代码-5.1
  • 生成Authorization示例代码见示例代码-5.2

3.API用法

3.1 域名

国内: https://analytics.volcengineapi.com
海外: https://analytics.byteplusapi.com

3.2 通过UUID上报

3.2.1 属性设置接口

Path: /dataprofile/openapi/v1/{app_id}/users/{user_id}?set_once=true
Method: PUT
Content-Type: application/json; charset=utf-8
Path-parameters:

Parameter

Type

Description

Required

app_id

int64

app_id

TRUE

user_id

string

用户id

TRUE

Query-parameters:

Parameter

Type

Description

Required

set_once

boolean

不存在则设置

TRUE

Body:

{
    "name":"name",
    "value":"zhangsan"
}

Request-example:

curl -X PUT -H 'Content-Type: application/json; charset=utf-8' -H 'Authorization: ******' -i https://analytics.volcengineapi.com/dataprofile/openapi/v1/751/users/185?set_once=true --data '{
        "name":"name","value":zhangsan
}'

Response-fields:

Field

Type

Description

code

int32

业务响应状态码

message

string

业务响应描述信息

Response-example:

{
        "code":2000,
        "message":"success"
}

3.2.2 更新单数属性值接口

Path: /dataprofile/openapi/v1/{app_id}/users/{user_id}/attributes/{attribute}
Method: PUT
Content-Type: application/json; charset=utf-8
Request-parameters:

Parameter

Type

Description

Required

app_id

int64

app_id

TRUE

user_id

string

用户id

TRUE

attribute

string

属性名称

TRUE

Body:

{
    "operation":"INCREASE",
    "value":1
}

operation可选值见下文 3.4 Operation
Request-example:

curl -X PUT -H 'Content-Type: application/json; charset=utf-8' -H 'Authorization: ******' -i https://analytics.volcengineapi.com/dataprofile/openapi/v1/54/users/185/attributes/age --data '{
        "operation":"INCREASE","value":1
}'

Response-fields:

Field

Type

Description

code

int32

业务响应状态码

message

string

业务响应描述信息

Response-example:

{
        "code":2000,
        "message":"success"
}

3.2.3 用户属性批量操作接口

批量指同一个用户的多个属性,而非多个用户
Path: /dataprofile/openapi/v1/{app_id}/users/{user_id}/attributes
Method: PUT
Content-Type: application/json; charset=utf-8
Request-parameters:

Parameter

Type

Description

Required

app_id

int64

app_id

TRUE

user_id

string

用户id

TRUE

Body:

{
    "attributes": [
        {
          "name": "name",
          "value": "zhangsan",
          "operation": "SET"
        },
        {
          "name": "height",
          "value": 10,
          "operation": "INCREASE"
        },
        {
          "name": "gendar",
          "operation": "UNSET"
        }
    ]
}

operation可选值见下文 3.4 Operation
Request-example:

curl -X PUT -H 'Content-Type: application/json; charset=utf-8' -H 'Authorization: ******' -i https://analytics.volcengineapi.com/dataprofile/openapi/v1/778/users/185/attributes --data '{
        "attributes": [
            {
              "name": "name",
              "value": "zhangsan",
              "operation": "SET"
            },
            {
              "name": "height",
              "value": 10,
              "operation": "INCREASE"
            },
            {
              "name": "gendar",
              "operation": "UNSET"
            }
        ]
}'

Response-fields:

Field

Type

Description

code

int32

业务响应状态码

message

string

业务响应描述信息

Response-example:

{
        "code":2000,
        "message":"success"
}

3.2.4 用户属性查询接口

Path: /dataprofile/openapi/v1/{app_id}/users/{user_id}
Method: GET
Content-Type: application/json; charset=utf-8
Request-parameters:

Parameter

Type

Description

Required

app_id

int64

app_id

TRUE

user_id

string

用户id

TRUE

Request-example:

curl -X GET -H 'Authorization: ******' -i https://analytics.volcengineapi.com/dataprofile/openapi/v1/42/users/185

Response-fields:

Field

Type

Description

code

int32

业务响应状态码

message

string

业务响应描述信息

data

object

属性值信息

data.appId

int64

应用id

data.attributes

list

具体信息

data.attributes[i].name

string

属性名称

data.attributes[i].value

根据注册类型而定

值信息

Response-example:

{
    "code": 2000,
    "message": "success",
    "data": {
        "appId": 183706,
        "attributes": [
            {
                "name": "vip_last",
                "value": 8
            },
            {
                "name": "trip_all",
                "value": "地铁"
            },
            {
                "name": "weight_last",
                "value": 123
            },
            {
                "name": "trip_last",
                "value": "地铁"
            },
            {
                "name": "weight_all",
                "value": 123
            }
        ]
    }
}

3.3 通过SSID上报

3.3.1 属性设置接口

Path: /dataprofile/openapi/v1/{app_id}/users/ssid/{ssid}?set_once=true
Method: PUT
Content-Type: application/json; charset=utf-8
Request-parameters:

Parameter

Type

Description

Required

app_id

int64

app_id

TRUE

ssid

string

ssid

TRUE

Query-parameters:

Parameter

Type

Description

Required

set_once

boolean

不存在则设置

TRUE

Body:

{
    "name":"name",
    "value":"zhangsan"
}

Request-example:

curl -X PUT -H 'Content-Type: application/json; charset=utf-8' -H 'Authorization: ******' -i https://analytics.volcengineapi.com/dataprofile/openapi/v1/819/users/ssid/185?set_once=true --data '{
        "name":"name","value":"zhangsan"
}'

Response-fields:

Field

Type

Description

code

int32

业务响应状态码

message

string

业务响应描述信息

Response-example:

{
        "code":2000,
        "message":"success"
}

3.3.2 更新单数属性值接口

Path: /dataprofile/openapi/v1/{app_id}/users/ssid/{ssid}/attributes/{attribute}
Method: PUT
Content-Type: application/json; charset=utf-8
Request-parameters:

Parameter

Type

Description

Required

app_id

int64

app_id

TRUE

ssid

string

ssid

TRUE

attribute

string

属性名

TRUE

Body:

{
    "operation":"INCREASE",
    "value":1
}

operation可选值见下文 3.4 Operation
Request-example:

curl -X PUT -H 'Content-Type: application/json; charset=utf-8' -H 'Authorization: ******' -i https://analytics.volcengineapi.com/dataprofile/openapi/v1/256/users/ssid/185/attributes/age --data '{
        "operation":"INCREASE","value":1
}'

Response-fields:

Field

Type

Description

code

int32

业务响应状态码

message

string

业务响应描述信息

Response-example:

{
        "code":2000,
        "message":"success"
}

3.3.3 用户属性批量操作接口

Path: /dataprofile/openapi/v1/{app_id}/users/ssid/{ssid}/attributes
Method: PUT
Content-Type: application/json; charset=utf-8
Request-parameters:

Parameter

Type

Description

Required

app_id

int64

app_id

TRUE

ssid

string

ssid

TRUE

Body:

{
    "attributes": [
        {
          "name": "name",
          "value": "zhangsan",
          "operation": "SET"
        },
        {
          "name": "height",
          "value": 10,
          "operation": "INCREASE"
        },
        {
          "name": "gendar",
          "operation": "UNSET"
        }
    ]
}

operation可选值见下文 3.4 Operation
Request-example:

curl -X PUT -H 'Content-Type: application/json; charset=utf-8' -H 'Authorization: ******' -i https://analytics.volcengineapi.com/dataprofile/openapi/v1/790/users/ssid/185/attributes --data '{
        "attributes": [
            {
              "name": "name",
              "value": zhangsan,
              "operation": "SET"
            },
            {
              "name": "height",
              "value": 10,
              "operation": "INCREASE"
            },
            {
              "name": "gendar",
              "operation": "UNSET"
            }
        ]
}'

Response-fields:

Field

Type

Description

code

int32

业务响应状态码

message

string

业务响应描述信息

Response-example:

{
        "code":2000,
        "message":"success"
}

3.3.4 用户属性查询接口

Path: /dataprofile/openapi/v1/{app_id}/users/ssid/{ssid}
Method: GET
Content-Type: application/json; charset=utf-8
Request-parameters:

Parameter

Type

Description

Required

app_id

int64

app_id

TRUE

ssid

string

ssid

TRUE

Request-example:

curl -X GET -H 'Authorization: ******' -i https://analytics.volcengineapi.com/dataprofile/openapi/v1/942/users/ssid/185

Response-fields:

Field

Type

Description

code

int32

业务响应状态码

message

string

业务响应描述信息

data

object

属性值信息

data.appId

int64

应用id

data.attributes

list

具体信息

data.attributes[i].name

string

属性名称

data.attributes[i].value

根据注册类型而定

值信息

Response-example:

{
    "code": 2000,
    "message": "success",
    "data": {
        "appId": 183706,
        "attributes": [
            {
                "name": "vip_last",
                "value": 8
            },
            {
                "name": "trip_all",
                "value": "地铁"
            },
            {
                "name": "weight_last",
                "value": 123
            },
            {
                "name": "trip_last",
                "value": "地铁"
            },
            {
                "name": "weight_all",
                "value": 123
            }
        ]
    }
}

3.4 Operation

Operation

说明

SET

为属性设置一个值

SET_ONCE

属性不存在则设置

UNSET

删除一个属性

INCREASE

对数值类型的属性执行累加操作

APPEND

在list类型的属性值里插入一个值

REMOVE

在list类型的属性值里删除一个值

4.错误码列表

Error code

Error Message

Description

备注

400

transmission content is tampered or authorization is invalid

生成的Authorization信息不对

检查生成Authorization的代码,注意params格式;每个请求的鉴权信息都是动态生成的

400

invalid accesskey

AK/SK无效

4000

The user ${uuid} not exists

使用未注册的uuid上报

若需要自动注册,可联系产品在RA上配置auto_create_ssid

4000

Type conversion failed, property ${property_name} type is ${property_type}, if you modify the property type, please try again in 5 minutes.

上报数据类型与定义类型不一致

string和list类型:可接所有类型的值
float类型:可接收int/float类型的值
int类型:只能接收int类型的值
datetime:只能接收时间格式的字符串
修改类型有5分钟延迟

4000

Type conversion failed, if you modify the property type, please try again in 5 minutes

4000

Make sure to successfully define when using this property: ${property_name} or try again in 5 minutes!

使用未定义过的属性上报

检查是否在平台预先定义过该属性,确认定义过则5分钟之后重试

4000

property ${property_name} is ${property_type}, don't support ${operation_name} operation.

属性类型不支持的上报操作

例如:对float类型进行append操作

4000

The datetime should be between 1900 and 2099

datetime类型value值的年份范围不在[1900,2099]之间

4000

invalid identifier for ${property_name

uuid

ssid}

属性名、uuid、ssid不满足正则规则 "[a-zA-Z_0-9-]+"

4000

attributes is empty

上报数据body中attributes为空

4000

name is blank

上报数据body中属性name不存在

4000

operation is null

上报数据body中属性operation不存在

5030

request frequency

服务限流

5000

something wrong, please retry later

系统内部服务错误

重试仍然失败的情况下,一般是系统未兼容的问题,可以联系客服

5.示例代码

5.1 鉴权

5.1.1 Java (AuthUtil.class)

import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.util.Map;

public class AuthUtils {

        /**
     * 
     * @param ak accessKey
     * @param sk secretKey
     * @param expirationSeconds 过期时间,单位秒
     * @param method 方法,GET, POST, PUT
     * @param path 请求的path,非完整的url(不需要加域名和查询参数)
     *        例如:属性设置接口:/dataprofile/openapi/v1/213123/users/user_1234 这样即可
     * @param params 请求参数
     * @param body 请求的json体
     * @return
     */
    public static String sign(String ak, String sk, int expirationSeconds, String method, String path, Map<String, String> params, String body) {
        String cm = canonicalMethod(method);
        String cu = canonicalUrl(path);
        String cp = canonicalParam(params);
        String cb = canonicalBody(body);
        String text = cm + "\n" + cu + "\n" + cp + "\n" + cb;
        return doSign(ak, sk, expirationSeconds, text);
    }

    private static String canonicalMethod(String method) {
        return "HTTPMethod:" + method;
    }

    private static String canonicalUrl(String url) {
        return "CanonicalURI:" + url;
    }

    private static String canonicalParam(Map<String, String> params) {
        String res = "CanonicalQueryString:";
        if (params == null || params.isEmpty()) {
            return res;
        }
        for (String key : params.keySet()) {
            res += formatKeyValue(key, params.get(key)) + "&";
        }
        return res.substring(0, res.length() - 1);
    }

    private static String formatKeyValue(String key, String value) {
        return key + "=" + value;
    }

    private static String canonicalBody(String body) {
        String res = "CanonicalBody:";
        if (body == null) {
            return res;
        } else {
            return res + body;
        }
    }

    private static String doSign(String ak, String sk, int expiration, String text) {
        String signKeyInfo = "ak-v1/" + ak + "/" + (int) (System.currentTimeMillis() / 1000) + "/" + expiration;
        String signKey = sha256Hmac(signKeyInfo, sk);
        String signResult = sha256Hmac(text, signKey);
        return signKeyInfo + "/" + signResult;
    }

    private static String sha256Hmac(String message, String secret) {
        String hash = "";
        try {
            Mac sha256_HMAC = Mac.getInstance("HmacSHA256");
            SecretKeySpec secret_key = new SecretKeySpec(secret.getBytes(), "HmacSHA256");
            sha256_HMAC.init(secret_key);
            byte[] bytes = sha256_HMAC.doFinal(message.getBytes());
            hash = byteArrayToHexString(bytes);
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        } catch (InvalidKeyException e) {
            e.printStackTrace();
        }
        return hash;
    }

    private static String byteArrayToHexString(byte[] b) {
        StringBuilder hs = new StringBuilder();
        String stmp;
        for (int n = 0; b != null && n < b.length; n++) {
            stmp = Integer.toHexString(b[n] & 0XFF);
            if (stmp.length() == 1) {
                hs.append('0');
            }
            hs.append(stmp);
        }
        return hs.toString().toLowerCase();
    }
}

5.1.2 Python (auth_util.py)

import time
import hashlib
import hmac

def _do_sign(ak, sk, expiration, text):
    sign_key_info = 'ak-v1/%s/%d/%d' % (ak, time.time(), expiration)
    sign_key = _sha256_hmac(sk, sign_key_info)
    sign_result = _sha256_hmac(sign_key, text)
    return '%s/%s' % (sign_key_info, sign_result)

def _canonical_method(method):
    return "HTTPMethod:" + method

def _canonical_url(url):
    return "CanonicalURI:" + url

def _canonical_param(params):
    res = 'CanonicalQueryString:'
    if not params:
        return res
    kvs = []
    for k, v in params.items():
        kvs.append('{}={}'.format(k, v))
    return res + '&'.join(kvs)

def _canonical_body(body):
    res = "CanonicalBody:"
    if not body:
        return res
    return res + body

def _sha256_hmac(key, data):
    return hmac.new(str.encode(key, 'utf-8'), str.encode(data, 'utf-8'), hashlib.sha256).hexdigest()

def sign(ak, sk, expiration_seconds, method, path, params, body):
        """
    :param ak:accessKey
    :param sk:secretKey
    :param expiration_seconds:过期时间,单位秒
    :param method:方法,GET, POST, PUT
    :param path:请求的path,非完整的url(不需要加域名和查询参数)
           例如:属性设置接口:/dataprofile/openapi/v1/213123/users/user_1234 这样即可
    :param params:请求参数
    :param body:请求的json体
    :return:
    """
    canonical_method = _canonical_method(method)
    canonical_url = _canonical_url(path)
    canonical_param = _canonical_param(params)
    canonical_body = _canonical_body(body)
    text = '{}\n{}\n{}\n{}'.format(canonical_method, canonical_url, canonical_param, canonical_body)
    return _do_sign(ak, sk, expiration_seconds, text)

5.1.3 Js

const crypto = require('crypto');
function hash(ak, sk, expiration_seconds, method, path, params, body) {
    const timestamp = (+new Date() / 1000).toFixed(0);
    const signKeyInfo = `ak-v1/${ak}/${timestamp}/${expiration_seconds}`;
    const signKey = sha256HMAC(sk, signKeyInfo);
    const data = canonicalRequest(method, path, params, body);
    const signResult = sha256HMAC(signKey, data);
    return signKeyInfo + '/' + signResult;
}

function sha256HMAC(sk, data) {
    const hmac = crypto.createHmac('sha256', sk)
    return hmac.update(data).digest('hex')
}

function canonicalRequest(method, url, params, body) {
    let cm = canonicalMethod(method);
    let cu = canonicalUrl(url);
    let cp = canonicalParam(params);
    let cb = canonicalBody(body);
    return cm + '\n' + cu + '\n' + cp + '\n' + cb;
}

function canonicalMethod(method) {
    return 'HTTPMethod:' + method;
}

function canonicalUrl(url) {
    return 'CanonicalURI:' + url;
}

function canonicalParam(params) {
    let res = 'CanonicalQueryString:'
    if (!params) {
        return res;
    }
    return res + queryString(params);
}

function canonicalBody(body) {
    let res = "CanonicalBody:"
    if (!body){
        return res;
    }
    return res + body;
}

5.2 Authorization

5.2.1 Java

import java.util.HashMap;
import java.util.Map;

public class AuthGenDemo {

    //分配的accessKey和secretKey
    private static String accessKey = "****";
    private static String secretKey = "****";
    // 单位秒
    private static Integer expirationSeconds = 300;

    public static void main(String[] args) {
        String method = "PUT";
        String host = "https://analytics.volcengineapi.com";
        String path = "/dataprofile/openapi/v1/751/users/185";

        // 请求参数,对于没有请求参数的接口,在生成authorization code的时候对应的参数传null即可
        HashMap<String, String> exampleQueryParams = new HashMap<>();
        exampleQueryParams.put("set_once", "true");

        String exampleQueryBodyJson = "{\"name\":\"name\",\"value\":\"zhangsan\"}";

        String authorization = AuthUtils.sign(accessKey, secretKey, expirationSeconds,
                method, path, exampleQueryParams, exampleQueryBodyJson);
        System.out.println("authorization: " + authorization);

        Map<String, String> headers = new HashMap<>();
        headers.put("Authorization", authorization);

        String url = host + path;
        JSONObject result = HttpUtil.put(url, exampleQueryBodyJson, exampleQueryParams, headers);
    }
}

5.2.2 Python

import auth_util
import json
import requests

if __name__=="__main__":

    expiration_seconds = 300
    method = "PUT"
    host = "https://analytics.volcengineapi.com"
    path = "/dataprofile/openapi/v1/751/users/185"
    # 请求参数,对于没有请求参数的接口,在生成authorization code的时候对应的参数传None即可
    params = {
        "set_once": "true"   
    }
    request_body = {
        "name": "name",
        "value": "zhangsan"
    }
    authorization = auth_util.sign(ak, sk, expiration_seconds, method, path, params, json.dumps(request_body))
    print(authorization)

    headers = {"Authorization": authorization}
    url = host + path
    print(requests.put(url, data=json.dumps(request_body), params = params, headers = headers).json())

注意

计算authorization_code传进去的params以及body和发送请求时的params和body格式必须保持一致(例如空格);特别是在代码中计算authorization_code然后使用curl来请求的时候。