Func Stateful 客户端API接入指南
Func Stateful 客户端API接入指南
Func 客户端API授权
使用 Nonce Authorization 来进行鉴权 (推荐客户端程序使用)。步骤如下:
在 UOS 网站上获取当前需要使用的 UOS APP 的 AppId 和 AppSecret
注:此处 AppId 和 AppSecret,可在 UOS 网站上获取


在请求任意 Sync API 的 Request Header 中增加如下 Header:
- X-TIMESTAMP: 当前时间戳
- X-NONCE: 随机生成的UUID
- X-APPID: 当前需要使用的 UOS APP 的 AppId
- Authorization: nonce hexadecimal(sha256(appId + ":" + appSecret + ":" + X-TIMESTAMP + ":" + X-NONCE))
示例代码:
C## C# 使用示例 - Nonce 授权方式 using System; using System.Collections.Generic; using System.Net.Http; using System.Security.Cryptography; using System.Text; using System.Threading.Tasks; using Newtonsoft.Json; class Program { private static Dictionary<string, string GetNonceAuthorization(string appId, string appSecret) { string nonce = Guid.NewGuid().ToString(); long timestamp = DateTimeOffset.UtcNow.ToUnixTimeSeconds(); string signString = $"{appId}:{appSecret}:{timestamp}:{nonce}"; byte[] signBytes = Encoding.UTF8.GetBytes(signString); using (SHA256 sha256 = SHA256.Create()) { byte[] hashBytes = sha256.ComputeHash(signBytes); string token = BitConverter.ToString(hashBytes).Replace("-", "").ToLower(); return new Dictionary<string, string { { "X-APPID", appId }, { "X-TIMESTAMP", timestamp.ToString() }, { "X-NONCE", nonce }, { "Authorization", $"nonce {token}" } }; } } public static async Task Main(string[] args) { using (HttpClient client = new HttpClient()) { // 使用项目的 APP_ID, APP_SECRET 获取 headers var headers = GetNonceAuthorization(APP_ID, APP_SECRET); foreach (var header in headers) { client.DefaultRequestHeaders.Add(header.Key, header.Value); } // 以get方法为例,替换 url 为你需要请求的 url HttpResponseMessage response = await client.GetAsync(url); // 其他处理…… } } }Python# Python 使用示例 - Nonce 授权方式 import hashlib import time import uuid import binascii import requests def get_nonce_authorization(app_id, app_secret): """生成 nonce 授权 Headers""" nonce = str(uuid.uuid4()) timestamp = int(time.time()) calculated_check_sum = hashlib.sha256(f'{app_id}:{app_secret}:{timestamp}:{nonce}'.encode()).digest() token = binascii.hexlify(calculated_check_sum).decode() headers = { 'X-APPID': app_id, 'X-TIMESTAMP': str(timestamp), 'X-NONCE': nonce, 'Authorization': f'nonce {token}', 'Content-Type': 'application/json' } return headers # 使用项目的 APP_ID, APP_SECRET 获取 headers headers = get_nonce_authorization(APP_ID, APP_SECRET) # 替换 url 为你需要请求的 url response = requests.get(url, headers=headers)JavaScript// JavaScript - Nonce 授权方式 const axios = require('axios'); function getNonceAuthorization(appId, appSecret) { const nonce = crypto.randomUUID(); const timestamp = Math.floor(Date.now() / 1000); const signString = `${appId}:${appSecret}:${timestamp}:${nonce}`; const hash = crypto.createHash('sha256').update(signString).digest('hex'); return { 'X-APPID': appId, 'X-TIMESTAMP': timestamp.toString(), 'X-NONCE': nonce, 'Authorization': `nonce ${hash}` }; } // 使用 APP_ID, APP_SECRET 获取Nonce Token Header const headers = getNonceAuthorization(APP_ID, APP_SECRET); // 以get方法为例,替换 url 为你需要请求的 url const response = await axios.get(url, { headers });
使用 Basic Authorization 来进行鉴权 (推荐服务器端程序使用). 步骤如下:
在 UOS 网站上获取当前需要使用的 UOS APP 的 AppId 和 AppServiceSecret
注:此处 AppId 和 AppServiceSecret,可在 UOS 网站上获取


在请求任意 API 的 Request Header 中增加 Header:
- Authorization: Basic base64(appId:appServiceSecret)
示例代码
C## C# 使用示例 - Basic 授权方式 using System; using System.Collections.Generic; using System.Net.Http; using System.Security.Cryptography; using System.Text; using System.Threading.Tasks; using Newtonsoft.Json; class Program { private static string GetBasicAuthorization(string appId, string appServiceSecret) { string credentials = $"{appId}:{appServiceSecret}"; byte[] credentialsBytes = Encoding.UTF8.GetBytes(credentials); string encodedCredentials = Convert.ToBase64String(credentialsBytes); return $"Basic {encodedCredentials}"; } public static async Task Main(string[] args) { using (HttpClient client = new HttpClient()) { // 使用项目的 APP_ID, APP_SERVICE_SECRET 获取 headers client.DefaultRequestHeaders.Add("Authorization", GetBasicAuthorization(APP_ID, APP_SERVICE_SECRET)); // 以get方法为例,替换 url 为你需要请求的 url HttpResponseMessage response = await client.GetAsync(url); response.EnsureSuccessStatusCode(); // 其他处理…… } } }Python# Python 使用示例 - Basic 授权方式 import base64 import requests def get_basic_authorization(app_id, app_service_secret): """ 获取basic auth的Header """ credentials = f'{app_id}:{app_service_secret}' encoded_credentials = base64.b64encode(credentials.encode("utf-8")).decode("utf-8") return {'Authorization': f'Basic {encoded_credentials}'} # 使用 APP_ID, APP_SERVICE_SECRET 获取Basic Token Header headers = get_basic_authorization(APP_ID, APP_SERVICE_SECRET) # 以get方法为例,替换 url 为你需要请求的 url response = requests.get(url, headers=headers)JavaScript// JavaScript 使用示例 - Basic 授权方式 const axios = require('axios'); function getBasicAuthorization(appId, appServiceSecret) { /** 获取 basic auth 的 Header */ const credentials = `${appId}:${appServiceSecret}`; const encodedCredentials = btoa(credentials); return { 'Authorization': `Basic ${encodedCredentials}` }; } // 使用 APP_ID, APP_SERVICE_SECRET 获取Basic Token Header const headers = getBasicAuthorization(APP_ID, APP_SERVICE_SECRET); // 以get方法为例,替换 url 为你需要请求的 url const response = await axios.get(url, { headers });Go// Go 使用示例 - Basic 授权方式 import ( "bytes" "encoding/base64" "encoding/json" "fmt" "io" "net/http" ) func GetBasicAuthorization(appID, appServiceSecret string) string { credentials := appID + ":" + appServiceSecret encodedCredentials := base64.StdEncoding.EncodeToString([]byte(credentials)) return "Basic " + encodedCredentials } func main() { // 以get方法为例,替换 url 为你需要请求的 url req, err := http.NewRequest("GET", url, nil) if err != nil { return nil, err } // 使用 APP_ID, APP_SERVICE_SECRET 获取Basic Token Header req.Header.Set("Authorization", GetBasicAuthorization(APP_ID, APP_SERVICE_SECRET)) client := &http.Client{} response, err := client.Do(req) if err != nil { return nil, err } defer resp.Body.Close() // ……其他处理 }
Func 客户端API列表
1. 客户端连接
概述:客户端通过调用此方法来获得服务器的地址,随后与其建立连接,api会返回服务器的 endpoint 信息。endpoint是描述Func Stateful的server的IP和端口信息的数据结构; 通常由一个IP地址和一组端口信息,由端口名称 / 端口号 / 端口协议组成。
如果使用多Profile,需要加上profileId参数
基本信息
| URL | Method | Content-Type |
|---|---|---|
https://func.unity.cn/v1/functions/{appId}/connect | POST | application/json |
请求参数:
{
"playerId": "string",
"name": "string",
"tags": [
"string"
],
"properties": {
"prop1": "string"
},
"serverId": "string",
"profileId": "string"
}参数说明
| 参数名 | 描述 | 类型 | 必填 | 默认值 |
|---|---|---|---|---|
| appId | UOS应用的id (UOS AppId) | string | 是 | |
| playerId | 获取endpoint的玩家 id | string | 是 | |
| name | 用于筛选的服务器名称 | string | 否 | |
| tags | 用于筛选的标签 | string[] | 否 | |
| properties | 用于筛选的自定义变量 | map<string,string> | 否 | |
| serverId | 需要连接服务器的Id, 不填则根据规则自动连接服务器 | string | 否 | |
| profileId | 需要连接服务的配置Id, 不填则默认连接主配置的服务器 | string | 否 |
输出示例
{
"appId": "string",
"ip": "string",
"ports": [
{
"port": "int",
"protocol": "string",
"name": "string"
}
]
}输出示例说明
| 参数名 | 描述 | 类型 |
|---|---|---|
| appId | UOS AppId | string |
| ip | 根据策略得到的服务器IP (ipv4) | string |
| port | 端口信息数组,由端口号/协议/名称组成 | object[] |
2. 获取servers信息
概述:客户端调用此 API可以获得所有运行中的服务器信息。
基本信息
| URL | Method | Content-Type |
|---|---|---|
https://func.unity.cn/v1/functions/{UosAppId}/servers | GET | application/json |
调用方式:
https://func.unity.cn/v1/functions/{UosAppId}/servers?name={name}&tags={tags1}&tags={tags2}&profileId={profileId}&evicted={evicted}...参数说明
| 参数名 | 描述 | 类型 | 必填 | 默认值 |
|---|---|---|---|---|
| name | server name 用于筛选 | string | 否 | |
| tags | tags 用于筛选 | string[] | 否 | |
| profileId | profileId 用于筛选 | string | 否 | |
| evicted | 是否返回被驱逐的 server;不传默认不返回被驱逐的 server;传入时返回对应状态的 server | boolean | 否 |
输出示例
{
"servers": [
{
"serverId": "string",
"name": "string",
"endpoint": {
"appId": "string",
"ip": "string",
"ports": [
{
"port": "int",
"protocol": "string",
"name": "string"
}
]
},
"tags": [
"string"
],
"properties": {
"prop1": "value1",
"prop2": "value2",
"prop3": "value3"
},
"playerCount": "int",
"createdAt": "2024-05-31T07:57:24.626789Z",
"profileId": "string",
"isEvicted": false
}
]
}输出示例说明
| 参数名 | 描述 | 类型 |
|---|---|---|
| servers | Func servers 信息数组 | object[] |
| serverId | server 的 uuid | string |
| name | server 的名称 | string |
| endpoint | 参考客户端连接 API 的返回信息 | object |
| tags | server 的标签 | string[] |
| properties | server 的自定义变量 | map<string, string> |
| playerCount | server 上连接的玩家数量 | int |
| createdAt | server 的创建时间 | string |
| profileId | 服务配置 Id | string |
| isEvicted | 是否已被驱逐 | boolean |
3. 客户端断开连接
概述:客户端登出后调用此API, 通知 Func Stateful 此 Player 已经下线。
建议在Server端调用disconnect方法, 如果使用多Profile,需要加上profileId参数
基本信息
| URL | Method | Content-Type |
|---|---|---|
https://func.unity.cn/v1/functions/{UosAppId}/disconnect | POST | application/json |
请求参数:
{
"playerId": "string",
"profileId": "string"
}请求参数说明
| 参数名 | 描述 | 类型 | 必填 | 默认值 |
|---|---|---|---|---|
| playerId | 玩家 id | string | 是 | |
| profileId | 服务配置 Id,如果func使用多配置需要填写 | string | 否 |
返回HTTP状态码说明
| 状态码 | 说明 |
|---|---|
| 200 | 登出成功 |
| 401 | 请求的auth失败 |
| 500 | 登出失败 |
4. 获取指定servers信息
概述:客户端调用此API可以根据serverId获得指定运行中的服务器信息。
基本信息
| URL | Method | Content-Type |
|---|---|---|
https://func.unity.cn/v1/functions/{UosAppId}/servers/{serverId} | GET | application/json |
输出示例
{
"serverId": "string",
"name": "string",
"endpoint": {
"appId": "string",
"ip": "string",
"ports": [
{
"port": "int",
"protocol": "string",
"name": "string"
}
]
},
"tags": [
"string"
],
"properties": {
"prop1": "value1",
"prop2": "value2",
"prop3": "value3"
},
"createdAt": "2024-05-31T07:57:24.626789Z",
"profileId": "string",
"isEvicted": false
}输出示例说明
| 参数名 | 描述 | 类型 |
|---|---|---|
| serverId | server 的 uuid | string |
| name | server 的名称 | string |
| endpoint | 参考客户端连接 API 的返回信息 | object |
| tags | server 的标签 | string[] |
| properties | server 的自定义变量 | map<string, string> |
| createdAt | server 的创建时间 | string |
| profileId | 服务配置 Id | string |
| isEvicted | 是否已被驱逐 | boolean |
5. 获取玩家server信息
概述:客户端调用此API可以根据playerId获得指定运行中的服务器信息。
基本信息
| URL | Method | Content-Type |
|---|---|---|
https://func.unity.cn/v1/functions/{UosAppId}/player-server/{playerId} | GET | application/json |
调用方式:
https://func.unity.cn/v1/functions/{UosAppId}/player-server/{playerId}?&profileId={profileId}参数说明
| 参数名 | 描述 | 类型 | 必填 | 默认值 |
|---|---|---|---|---|
| profileId | profileId 用于筛选 | string | 否 |
输出示例
{
"serverId": "string",
"name": "string",
"endpoint": {
"appId": "string",
"ip": "string",
"ports": [
{
"port": "int",
"protocol": "string",
"name": "string"
}
]
},
"tags": [],
"properties": {},
"profileId": "string",
"isEvicted": false
}输出示例说明
| 参数名 | 描述 | 类型 |
|---|---|---|
| serverId | server 的 uuid | string |
| name | server 的名称 | string |
| endpoint | 参考客户端连接 API 的返回信息 | object |
| tags | server 的标签 | string[] |
| properties | server 的自定义变量 | map<string, string> |
| profileId | 服务配置 Id | string |
| isEvicted | 是否已被驱逐 | boolean |