---
title: 为开放API创建JWT身份验证令牌
slug: world-sdk-guide-ch/apijwt
docTags: 
createdAt: 2024-09-02T08:34:13.134Z
---

## 开放API请求格式

ZEPETO开放API通过HTTP调用。

如果请求中存在主体，参数必须以JSON格式发送。
有效内容类型的示例如下，具体可能会根据各自的编程语言库略有不同。

```http
Content-Type: application/json; charset=utf-8
```



## 从ZEPETO Studio获取访问密钥和秘密密钥

在创建JWT身份验证令牌之前，您需要从ZEPETO Studio控制台获取访问密钥和秘密密钥。

:::hint{type="info"}
**📘&#x20;**&#x8BF7;参考以下指南。[管理开放 API](docId\:TEviE5E-km35X9Z5OEAMP)&#x20;
:::



## 创建JWT身份验证令牌

ZEPETO开放API生成基于访问密钥和为每个请求发放的秘密密钥的JWT（[https://jwt.io](https://jwt.io)）格式令牌，并在Authorization头中发送。

推荐使用HS256作为签名方法，签名所用的秘密是发放的秘密密钥。

JWT令牌有效载荷具有以下格式：

:::CodeblockTabs
JWT令牌有效载荷

```java
{
    "access_key": "发放的访问密钥（必填）",
    "nonce": "随机的UUID值（必填）",
    "uri_hash": "URI的哈希值，包括查询参数，排除基本路径（必填）",
    "body_hash": "请求体的哈希值"
}
```
:::



- uri\_hash是包含查询参数的uri的哈希值，排除基本路径。
- body\_hash是转换为json字符串并哈希的值，仅在请求体存在时插入到有效载荷中；如果没有请求体，则省略。
  - 在这种情况下，json字符串的键和值之间不应有空格。
- uri\_hash和body\_hash必须与发送到请求的查询参数和请求体哈希到相同的值。（值的顺序也必须相同。）

:::hint{type="danger"}
* API调用数量限制：每分钟最多可进行300次调用。
:::



## 没有请求体的示例

请根据您希望使用的API输入访问密钥、秘密密钥、世界ID、URI和查询参数。

下面的示例代码是基于数据存储类别的获取玩家数据API编写的。

### Java

```java
String accessKey = "accessKey";
String secretKey = "secretKey";
 
String worldId = "com.test.world";
String uri = "/datastorage/v1/worlds/" + worldId + "/player-data";
 
MessageDigest uriHash = MessageDigest.getInstance("SHA-256");
uriHash.update(uri.getBytes(StandardCharsets.UTF_8));
byte[] uriHashBytes = uriHash.digest();
 
ObjectMapper objectMapper = new ObjectMapper();
 
Map<String, Object> payload = new HashMap<>();
payload.put("access_key", accessKey);
payload.put("nonce", UUID.randomUUID().toString());
payload.put("uri_hash", new String(Base64.encodeBase64(uriHashBytes), StandardCharsets.UTF_8));
 
String jwtToken = Jwts.builder()
                    .setPayload(objectMapper.writeValueAsString(payload))
                    .signWith(SignatureAlgorithm.HS256, secretKey.getBytes(StandardCharsets.UTF_8))
                    .compact();
 
String authorization = "Bearer " + jwtToken;
```



### Python

```python
import jwt
import uuid
import hashlib
import base64
 
accessKey = 'accessKey'
secretKey = 'secretKey'
 
worldId = 'com.test.world'
uri = '/datastorage/v1/worlds/' + worldId + '/player-data?playerId=testplayerid&keys=test'
hash = hashlib.sha256()
hash.update(uri.encode())
 
payload = {
    'access_key': accessKey,
    'nonce': str(uuid.uuid4()),
    'uri_hash': base64.b64encode(hash.digest()).decode('utf8')
}
 
jwt_token = jwt.encode(payload, secretKey)
authorization = 'Bearer {}'.format(jwt_token)
```



### NodeJS

```typescript
import * as jwt from 'jsonwebtoken';
import * as uuid from 'uuid';
import * as crypto from 'crypto-js';
import { Buffer } from 'safe-buffer';

const accessKey = 'accessKey';
const secretKey = 'secretKey';
const worldId = 'com.test.world';
const uri = '/datastorage/v1/worlds/' + worldId + '/player-data?playerId=testplayerid&keys=test';
const hash = crypto.SHA256(uri);

const payload = {
  access_key: accessKey,
  nonce: uuid.v4(),
  uri_hash: Buffer.from(hash.toString(), 'hex').toString('base64')
};
const jwtToken = jwt.sign(payload, secretKey);
const authorization = `Bearer ${jwtToken}`;

```



## 请求体示例

请根据您希望使用的API输入访问密钥、秘密密钥、worldId、uri和body参数。

下面的示例代码是基于数据存储类别的设置玩家数据API编写的。

### Java

```java
String accessKey = "accessKey";
String secretKey = "secretKey";
 
String worldId = "com.test.world";
String uri = "/datastorage/v1/worlds/" + worldId + "/player-data";
 
MessageDigest uriHash = MessageDigest.getInstance("SHA-256");
uriHash.update(uri.getBytes(StandardCharsets.UTF_8));
byte[] uriHashBytes = uriHash.digest();
 
ObjectMapper objectMapper = new ObjectMapper();
 
PlayerData dataMap = new PlayerData("test", "test value");
 
List<PlayerData> dataList = new ArrayList<>();
dataList.add(dataMap);
 
PlayerDataSetParam param = new PlayerDataSetParam(dataList, "testplayerid");
 
 
MessageDigest paramHash = MessageDigest.getInstance("SHA-256");
paramHash.update(objectMapper.writeValueAsString(param).getBytes(StandardCharsets.UTF_8));
byte[] paramHashBytes = paramHash.digest();
 
Map<String, Object> payload = new HashMap<>();
payload.put("access_key", accessKey);
payload.put("nonce", UUID.randomUUID().toString());
payload.put("uri_hash", new String(Base64.encodeBase64(uriHashBytes), StandardCharsets.UTF_8));
payload.put("body_hash", new String(Base64.encodeBase64(paramHashBytes), StandardCharsets.UTF_8));
 
String jwtToken = Jwts.builder()
                    .setPayload(objectMapper.writeValueAsString(payload))
                    .signWith(SignatureAlgorithm.HS256, secretKey.getBytes(StandardCharsets.UTF_8))
                    .compact();
 
String authorization = "Bearer " + jwtToken;
```



### Python

```python
import jwt
import uuid
import hashlib
import base64
import simplejson as json
 
accessKey = 'accessKey' secretKey = 'secretKey'
 
worldId = 'com.test.world'
uri = '/datastorage/v1/worlds/' + worldId + '/player-data'
hash = hashlib.sha256()
hash.update(uri.encode())
 
param = {
    'playerId': 'testplayerid',
    'data':[
        {
            'key': 'test',
            'value': 'test value'
        }
    ]
}
 
param_hash = hashlib.sha256()
param_hash.update(json.dumps(param, ensure_ascii=False, encoding='surrogatepass').encode())
 
payload = {
    'access_key': accessKey,
    'nonce': str(uuid.uuid4()),
    'uri_hash': base64.b64encode(hash.digest()).decode('utf8'),
    'body_hash': base64.b64encode(param_hash.digest()).decode('utf8')
}
 
jwt_token = jwt.encode(payload, secretKey)
authorization = 'Bearer {}'.format(jwt_token)
```



### NodeJS

```typescript
import * as jwt from 'jsonwebtoken';
import * as uuid from 'uuid';
import * as crypto from 'crypto-js';
import { Buffer } from 'safe-buffer';

const accessKey = 'accessKey';
const secretKey = 'secretKey';
const worldId = 'com.test.world';
const uri = '/datastorage/v1/worlds/' + worldId + '/player-data';
const hash = crypto.SHA256(uri);

const param = {
  playerId: 'testplayerid',
  data: [
    {
      value: 'test value',
      key: 'test'
    }
  ]
};
const paramHash = crypto.SHA256(JSON.stringify(param,null,0));

const payload = {
  access_key: accessKey,
  nonce: uuid.v4(),
  uri_hash: Buffer.from(hash.toString(), 'hex').toString('base64'),
  body_hash: Buffer.from(paramHash.toString(), 'hex').toString('base64')
};
const jwtToken = jwt.sign(payload, secretKey);
const authorization = `Bearer ${jwtToken}`;
```



##

:::hint{type="danger"}
❗️ **注意**

- OpenAPI 是一个可用于单独的网页或应用程序的功能。
- 目前，ZEPETO 服务器脚本无法进行 ZEPETO Open API 调用。
- 如果您想在 ZEPETO 多人游戏中进行 Open API 调用，我们建议以下方法：
  - 设置一个单独的服务器，通过与 Open API 通信来执行必要的业务逻辑。
  - 在 ZEPETO 服务器中使用 httpService 包直接与您设置的服务器进行通信。
  - 在服务器之间实现相对简单的身份验证方法，例如使用 HTTP 授权头，以便在 ZEPETO 服务器支持的功能内进行调用。
:::

