热土用户开发者文档
欢迎使用热土用户开发者文档。本文档将帮助您了解如何集成热土用户系统到您的应用中,包括API调用、Token管理和软件认证流程。
https://appapi.rtstudio.top/api。
env参数说明
登录页面支持env参数来指定授权模式:
| 参数值 | 说明 | port参数含义 | 回调地址格式 |
|---|---|---|---|
| app(默认) | 桌面应用模式 | 本地端口号 | http://127.0.0.1:端口 |
| web | Web应用模式 | 回调网址(不含http/https前缀) | https://网址 |
使用示例:
- 桌面应用:
https://apilogin.rtstudio.top/?port=3456&type=token&v=xxx&state=xxx&env=app - Web应用:
https://apilogin.rtstudio.top/?port=yourapp.com/callback&type=token&v=xxx&state=xxx&env=web
概览
热土用户系统提供了一套完整的用户认证和授权机制,支持第三方应用通过Token进行身份验证和授权。主要功能包括:
- 软件Token验证
- 用户授权Token管理
- 基于Token的用户信息获取
- 软件认证流程
API参考
第三方API提供了以下端点:
POST /verify-software-token
验证软件登录Token的有效性
请求参数:
| 参数名 | 类型 | 必填 | 描述 |
|---|---|---|---|
| token | string | 是 | 软件登录Token |
响应示例:
{"success": true, "data": {"id": 1, "name": "测试软件", "developer": "测试开发者"}}
POST /verify-access-token
验证用户授权Token的有效性
请求参数:
| 参数名 | 类型 | 必填 | 描述 |
|---|---|---|---|
| token | string | 是 | 用户授权Token |
响应示例:
{"success": true, "data": {"id": 1, "user_id": 1, "software_id": 1, "access_token": "...", "expires_at": "2027-03-22T12:00:00Z"}}
POST /get-user-by-token
根据用户授权Token获取用户信息
请求参数:
| 参数名 | 类型 | 必填 | 描述 |
|---|---|---|---|
| token | string | 是 | 用户授权Token |
响应示例:
{"success": true, "data": {"id": 1, "uuid": "...", "username": "testuser", "email": "test@example.com", "email_verified": true, "is_beta_user": false}}
POST /data-segments
创建数据段
请求参数:
| 参数名 | 类型 | 必填 | 描述 |
|---|---|---|---|
| string | 是 | 用户邮箱 | |
| token | string | 是 | 用户授权Token |
| name | string | 是 | 数据段名称 |
| content | string | 是 | 数据段内容 |
响应示例:
{"success": true, "message": "数据段创建成功", "data": {"id": 1, "name": "user_settings", "content": "{\"theme\": \"dark\", \"language\": \"zh-CN\"}"}}
PUT /data-segments
修改数据段
请求参数:
| 参数名 | 类型 | 必填 | 描述 |
|---|---|---|---|
| string | 是 | 用户邮箱 | |
| token | string | 是 | 用户授权Token |
| name | string | 是 | 数据段名称 |
| content | string | 是 | 数据段内容 |
响应示例:
{"success": true, "message": "数据段更新成功", "data": {"name": "user_settings", "content": "{\"theme\": \"light\", \"language\": \"zh-CN\"}"}}
DELETE /data-segments
删除数据段
请求参数:
| 参数名 | 类型 | 必填 | 描述 |
|---|---|---|---|
| string | 是 | 用户邮箱 | |
| token | string | 是 | 用户授权Token |
| name | string | 是 | 数据段名称 |
响应示例:
{"success": true, "message": "数据段删除成功"}
POST /data-segments/read
读取数据段
请求参数:
| 参数名 | 类型 | 必填 | 描述 |
|---|---|---|---|
| string | 是 | 用户邮箱 | |
| token | string | 是 | 用户授权Token |
| name | string | 是 | 数据段名称 |
响应示例:
{"success": true, "message": "数据段读取成功", "data": {"id": 1, "name": "user_settings", "content": "{\"theme\": \"dark\", \"language\": \"zh-CN\"}", "created_at": "2026-03-22T12:00:00Z", "updated_at": "2026-03-22T12:00:00Z"}}
Token授权流程
热土用户系统支持两种类型的软件授权:
1. 已认证软件授权流程
已认证软件是指通过热土工作室审核的软件,具有更高的安全性和可信度。
- 软件开发者向热土工作室申请软件认证,获取软件Token
- 软件启动时,生成安全的state参数
- 软件构造登录链接并打开浏览器:
https://apilogin.rtstudio.top/?port=${本地端口}&type=token&v=${软件Token}&state=${state}&env=app - 用户在浏览器中确认登录,输入账号密码
- 服务器验证用户凭据和软件Token
- 服务器生成用户授权Token并返回给软件
- 软件使用授权Token调用API获取用户信息
2. 未认证软件授权流程
未认证软件是指尚未通过热土工作室审核的软件,用户登录时会收到安全警告。
- 软件启动时,生成安全的state参数
- 软件构造登录链接并打开浏览器:
https://apilogin.rtstudio.top/?port=${本地端口}&type=name&v=${软件名称}&state=${state}&env=app - 用户在浏览器中确认登录,输入账号密码
- 服务器验证用户凭据
- 服务器生成用户授权Token并返回给软件
- 软件使用授权Token调用API获取用户信息
3. Web应用授权流程
对于Web应用,可以使用web模式进行授权,此时port参数为回调网址。
- Web应用生成安全的state参数
- 构造登录链接并跳转:
https://apilogin.rtstudio.top/?port=${回调网址}&type=token&v=${软件Token}&state=${state}&env=web - 用户在登录页面确认登录,输入账号密码
- 服务器验证用户凭据和软件Token
- 服务器生成用户授权Token并重定向到回调网址
- Web应用从URL参数中获取授权Token
4. 完整的登录流程实现(Go语言)
以下是实现完整登录流程的详细步骤(基于login_mod文件夹的Go语言代码):
步骤1:启动本地Web服务器
软件需要在本地启动一个Web服务器,用于接收登录结果回调。
// main.go
package main
import (
"bytes"
"crypto/rand"
"encoding/hex"
"encoding/json"
"fmt"
"io"
"log"
"net"
"net/http"
"os/exec"
"runtime"
"time"
)
// 配置常量
const apiBaseURL = "https://appapi.rtstudio.top"
// 命令行参数
var (
loginType string // token 或 name
value string // 软件token或软件名称
)
// 验证响应结构
type verifyResponse struct {
Success bool `json:"success"`
Data any `json:"data"`
Message string `json:"message"`
}
func main() {
// 启动登录流程
token, err := startLoginFlow(loginType, value)
if err != nil {
log.Fatalf("登录失败: %v", err)
}
// 验证token有效性
if err := verifyToken(token); err != nil {
log.Fatalf("token验证失败: %v", err)
}
fmt.Print(token)
}
步骤2:构造登录链接并打开浏览器
软件需要构造登录链接并打开浏览器,引导用户登录。
// startLoginFlow 启动完整的登录流程
func startLoginFlow(loginType, value string) (string, error) {
// 1. 生成state参数 (16字节随机数,防CSRF)
state, err := generateState()
if err != nil {
return "", fmt.Errorf("生成state失败: %v", err)
}
// 2. 寻找可用端口并启动本地服务器
port, err := findAvailablePort()
if err != nil {
return "", fmt.Errorf("无法找到可用端口: %v", err)
}
// 创建channel用于接收token或错误
tokenChan := make(chan string, 1)
errChan := make(chan error, 1)
// 启动HTTP服务器
server := &http.Server{
Addr: fmt.Sprintf(":%d", port),
ReadTimeout: 10 * time.Second,
WriteTimeout: 10 * time.Second,
}
// 注册路由处理器
http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
if r.Method != http.MethodGet {
http.Error(w, "Method not allowed", http.StatusMethodNotAllowed)
return
}
query := r.URL.Query()
callbackType := query.Get("type")
callbackValue := query.Get("v")
callbackState := query.Get("state")
if callbackType == "success" {
// 验证state参数,防止CSRF攻击
if callbackState != state {
errChan <- fmt.Errorf("state参数验证失败")
http.Error(w, "state验证失败", http.StatusBadRequest)
return
}
tokenChan <- callbackValue
w.Header().Set("Content-Type", "text/html; charset=utf-8")
w.WriteHeader(http.StatusOK)
w.Write([]byte(`登录成功 ✅ 登录完成
请关闭此窗口
`))
go func() {
time.Sleep(500 * time.Millisecond)
server.Close()
}()
} else if callbackType == "error" {
errChan <- fmt.Errorf("登录失败: %s", callbackValue)
http.Error(w, "登录失败", http.StatusBadRequest)
go func() {
time.Sleep(500 * time.Millisecond)
server.Close()
}()
} else {
http.Error(w, "无效的回调类型", http.StatusBadRequest)
}
})
// 在goroutine中启动服务器
go func() {
if err := server.ListenAndServe(); err != nil && err != http.ErrServerClosed {
errChan <- fmt.Errorf("HTTP服务器错误: %v", err)
}
}()
// 等待服务器启动
time.Sleep(100 * time.Millisecond)
// 3. 构造登录URL并打开浏览器
loginURL := fmt.Sprintf("https://apilogin.rtstudio.top/?port=%d&type=%s&v=%s&state=%s&env=app",
port, loginType, value, state)
log.Printf("构造的登录URL: %s", loginURL)
if err := openBrowser(loginURL); err != nil {
return "", fmt.Errorf("打开浏览器失败: %v", err)
}
log.Printf("已打开浏览器,请登录")
// 等待登录结果
select {
case token := <-tokenChan:
return token, nil
case err := <-errChan:
return "", err
case <-time.After(5 * time.Minute):
server.Close()
return "", fmt.Errorf("登录超时(5分钟)")
}
}
// generateState 生成16字节随机数作为state参数
func generateState() (string, error) {
bytes := make([]byte, 16)
if _, err := rand.Read(bytes); err != nil {
return "", err
}
return hex.EncodeToString(bytes), nil
}
// findAvailablePort 寻找一个可用的TCP端口
func findAvailablePort() (int, error) {
listener, err := net.Listen("tcp", ":0")
if err != nil {
return 0, err
}
defer listener.Close()
return listener.Addr().(*net.TCPAddr).Port, nil
}
// openBrowser 打开系统默认浏览器
func openBrowser(url string) error {
switch runtime.GOOS {
case "windows":
return exec.Command("rundll32", "url.dll,FileProtocolHandler", url).Start()
case "darwin":
return exec.Command("open", url).Start()
default:
return exec.Command("xdg-open", url).Start()
}
}
步骤3:使用获取到的token调用API
登录成功后,软件可以使用获取到的token调用API获取用户信息。
// verifyToken 验证token有效性
func verifyToken(token string) error {
reqBody := map[string]string{"token": token}
jsonBody, err := json.Marshal(reqBody)
if err != nil {
return err
}
resp, err := http.Post(apiBaseURL+"/verify-access-token", "application/json", bytes.NewBuffer(jsonBody))
if err != nil {
return fmt.Errorf("API请求失败: %v", err)
}
defer resp.Body.Close()
body, err := io.ReadAll(resp.Body)
if err != nil {
return err
}
var result verifyResponse
if err := json.Unmarshal(body, &result); err != nil {
return err
}
if !result.Success {
return fmt.Errorf("token无效: %s", result.Message)
}
return nil
}
// getUserByToken 根据token获取用户信息
func getUserByToken(token string) (*verifyResponse, error) {
reqBody := map[string]string{"token": token}
jsonBody, err := json.Marshal(reqBody)
if err != nil {
return nil, err
}
resp, err := http.Post(apiBaseURL+"/get-user-by-token", "application/json", bytes.NewBuffer(jsonBody))
if err != nil {
return nil, fmt.Errorf("API请求失败: %v", err)
}
defer resp.Body.Close()
body, err := io.ReadAll(resp.Body)
if err != nil {
return nil, err
}
var result verifyResponse
if err := json.Unmarshal(body, &result); err != nil {
return nil, err
}
return &result, nil
}
完整示例代码
// main.go
// 使用方法: go run main.go -type token -v your_software_token
// 或: go run main.go -type name -v your_software_name
package main
import (
"bytes"
"crypto/rand"
"encoding/hex"
"encoding/json"
"flag"
"fmt"
"io"
"log"
"net"
"net/http"
"os/exec"
"runtime"
"time"
)
const apiBaseURL = "https://appapi.rtstudio.top"
var loginType string
var value string
type verifyResponse struct {
Success bool `json:"success"`
Data any `json:"data"`
Message string `json:"message"`
}
func main() {
flag.StringVar(&loginType, "type", "", "登录类型: token (已认证软件) 或 name (未认证软件)")
flag.StringVar(&value, "v", "", "软件token (type=token时) 或软件名称 (type=name时)")
flag.Parse()
if loginType != "token" && loginType != "name" {
log.Fatal("错误: -type 必须是 'token' 或 'name'")
}
if value == "" {
log.Fatal("错误: -v 参数不能为空")
}
token, err := startLoginFlow(loginType, value)
if err != nil {
log.Fatalf("登录失败: %v", err)
}
if err := verifyToken(token); err != nil {
log.Fatalf("token验证失败: %v", err)
}
// 获取用户信息
userResult, err := getUserByToken(token)
if err != nil {
log.Fatalf("获取用户信息失败: %v", err)
}
if userResult.Success {
log.Printf("登录成功,用户信息: %+v", userResult.Data)
}
fmt.Print(token)
}
func startLoginFlow(loginType, value string) (string, error) {
state, err := generateState()
if err != nil {
return "", fmt.Errorf("生成state失败: %v", err)
}
port, err := findAvailablePort()
if err != nil {
return "", fmt.Errorf("无法找到可用端口: %v", err)
}
tokenChan := make(chan string, 1)
errChan := make(chan error, 1)
server := &http.Server{
Addr: fmt.Sprintf(":%d", port),
ReadTimeout: 10 * time.Second,
WriteTimeout: 10 * time.Second,
}
http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
if r.Method != http.MethodGet {
http.Error(w, "Method not allowed", http.StatusMethodNotAllowed)
return
}
query := r.URL.Query()
callbackType := query.Get("type")
callbackValue := query.Get("v")
callbackState := query.Get("state")
if callbackType == "success" {
if callbackState != state {
errChan <- fmt.Errorf("state参数验证失败")
http.Error(w, "state验证失败", http.StatusBadRequest)
return
}
tokenChan <- callbackValue
w.Header().Set("Content-Type", "text/html; charset=utf-8")
w.WriteHeader(http.StatusOK)
w.Write([]byte(`登录成功 ✅ 登录完成
请关闭此窗口
`))
go func() {
time.Sleep(500 * time.Millisecond)
server.Close()
}()
} else if callbackType == "error" {
errChan <- fmt.Errorf("登录失败: %s", callbackValue)
http.Error(w, "登录失败", http.StatusBadRequest)
go func() {
time.Sleep(500 * time.Millisecond)
server.Close()
}()
} else {
http.Error(w, "无效的回调类型", http.StatusBadRequest)
}
})
go func() {
if err := server.ListenAndServe(); err != nil && err != http.ErrServerClosed {
errChan <- fmt.Errorf("HTTP服务器错误: %v", err)
}
}()
time.Sleep(100 * time.Millisecond)
loginURL := fmt.Sprintf("https://apilogin.rtstudio.top/?port=%d&type=%s&v=%s&state=%s&env=app",
port, loginType, value, state)
log.Printf("构造的登录URL: %s", loginURL)
if err := openBrowser(loginURL); err != nil {
return "", fmt.Errorf("打开浏览器失败: %v", err)
}
log.Printf("已打开浏览器,请登录")
select {
case token := <-tokenChan:
return token, nil
case err := <-errChan:
return "", err
case <-time.After(5 * time.Minute):
server.Close()
return "", fmt.Errorf("登录超时(5分钟)")
}
}
func generateState() (string, error) {
bytes := make([]byte, 16)
if _, err := rand.Read(bytes); err != nil {
return "", err
}
return hex.EncodeToString(bytes), nil
}
func findAvailablePort() (int, error) {
listener, err := net.Listen("tcp", ":0")
if err != nil {
return 0, err
}
defer listener.Close()
return listener.Addr().(*net.TCPAddr).Port, nil
}
func openBrowser(url string) error {
switch runtime.GOOS {
case "windows":
return exec.Command("rundll32", "url.dll,FileProtocolHandler", url).Start()
case "darwin":
return exec.Command("open", url).Start()
default:
return exec.Command("xdg-open", url).Start()
}
}
func verifyToken(token string) error {
reqBody := map[string]string{"token": token}
jsonBody, err := json.Marshal(reqBody)
if err != nil {
return err
}
resp, err := http.Post(apiBaseURL+"/verify-access-token", "application/json", bytes.NewBuffer(jsonBody))
if err != nil {
return fmt.Errorf("API请求失败: %v", err)
}
defer resp.Body.Close()
body, err := io.ReadAll(resp.Body)
if err != nil {
return err
}
var result verifyResponse
if err := json.Unmarshal(body, &result); err != nil {
return err
}
if !result.Success {
return fmt.Errorf("token无效: %s", result.Message)
}
return nil
}
func getUserByToken(token string) (*verifyResponse, error) {
reqBody := map[string]string{"token": token}
jsonBody, err := json.Marshal(reqBody)
if err != nil {
return nil, err
}
resp, err := http.Post(apiBaseURL+"/get-user-by-token", "application/json", bytes.NewBuffer(jsonBody))
if err != nil {
return nil, fmt.Errorf("API请求失败: %v", err)
}
defer resp.Body.Close()
body, err := io.ReadAll(resp.Body)
if err != nil {
return nil, err
}
var result verifyResponse
if err := json.Unmarshal(body, &result); err != nil {
return nil, err
}
return &result, nil
}
软件认证流程
如果您希望您的软件成为已认证软件,需要按照以下流程申请:
已验证软件 vs 未验证软件
已验证软件:
- 通过热土工作室的安全审核
- 拥有唯一的软件Token
- 可以使用数据段功能(最多10个数据段)
- 用户登录时显示软件名称和开发者信息
- 在用户仪表盘中显示为已授权应用
未验证软件:
- 未通过热土工作室的安全审核
- 使用软件名称进行登录
- 无法使用数据段功能
- 用户登录时会显示风险警告和免责声明
- 在用户仪表盘中显示为未授权应用
申请已验证软件
- 准备以下材料:
- 软件名称
- 软件开发者信息
- 软件功能描述
- 软件截图
- 软件下载链接(如果有)
- 发送邮件到 miles@rtstu.com,主题为「软件认证申请」
- 等待热土工作室审核(通常1-3个工作日)
- 审核通过后,您将收到包含软件Token的邮件
示例代码
以下是使用第三方API的示例代码:
验证软件Token
// verifySoftwareToken 验证软件Token
func verifySoftwareToken(token string) (*verifyResponse, error) {
reqBody := map[string]string{"token": token}
jsonBody, err := json.Marshal(reqBody)
if err != nil {
return nil, err
}
resp, err := http.Post(apiBaseURL+"/verify-software-token", "application/json", bytes.NewBuffer(jsonBody))
if err != nil {
return nil, fmt.Errorf("API请求失败: %v", err)
}
defer resp.Body.Close()
body, err := io.ReadAll(resp.Body)
if err != nil {
return nil, err
}
var result verifyResponse
if err := json.Unmarshal(body, &result); err != nil {
return nil, err
}
return &result, nil
}
// 使用示例
func main() {
result, err := verifySoftwareToken("your_software_token")
if err != nil {
log.Printf("验证失败: %v", err)
return
}
if result.Success {
log.Printf("软件验证成功: %+v", result.Data)
} else {
log.Printf("软件验证失败: %s", result.Message)
}
}
验证用户授权Token
// verifyAccessToken 验证用户授权Token
func verifyAccessToken(token string) (*verifyResponse, error) {
reqBody := map[string]string{"token": token}
jsonBody, err := json.Marshal(reqBody)
if err != nil {
return nil, err
}
resp, err := http.Post(apiBaseURL+"/verify-access-token", "application/json", bytes.NewBuffer(jsonBody))
if err != nil {
return nil, fmt.Errorf("API请求失败: %v", err)
}
defer resp.Body.Close()
body, err := io.ReadAll(resp.Body)
if err != nil {
return nil, err
}
var result verifyResponse
if err := json.Unmarshal(body, &result); err != nil {
return nil, err
}
return &result, nil
}
// 使用示例
func main() {
result, err := verifyAccessToken("user_access_token")
if err != nil {
log.Printf("验证失败: %v", err)
return
}
if result.Success {
log.Printf("Token验证成功: %+v", result.Data)
} else {
log.Printf("Token验证失败: %s", result.Message)
}
}
获取用户信息
// getUserByToken 根据Token获取用户信息
func getUserByToken(token string) (*verifyResponse, error) {
reqBody := map[string]string{"token": token}
jsonBody, err := json.Marshal(reqBody)
if err != nil {
return nil, err
}
resp, err := http.Post(apiBaseURL+"/get-user-by-token", "application/json", bytes.NewBuffer(jsonBody))
if err != nil {
return nil, fmt.Errorf("API请求失败: %v", err)
}
defer resp.Body.Close()
body, err := io.ReadAll(resp.Body)
if err != nil {
return nil, err
}
var result verifyResponse
if err := json.Unmarshal(body, &result); err != nil {
return nil, err
}
return &result, nil
}
// 使用示例
func main() {
result, err := getUserByToken("user_access_token")
if err != nil {
log.Printf("获取失败: %v", err)
return
}
if result.Success {
log.Printf("用户信息: %+v", result.Data)
} else {
log.Printf("获取失败: %s", result.Message)
}
}
创建数据段
// createDataSegment 创建数据段
func createDataSegment(email, token, name, content string) (*verifyResponse, error) {
reqBody := map[string]string{
"email": email,
"token": token,
"name": name,
"content": content,
}
jsonBody, err := json.Marshal(reqBody)
if err != nil {
return nil, err
}
resp, err := http.Post(apiBaseURL+"/data-segments", "application/json", bytes.NewBuffer(jsonBody))
if err != nil {
return nil, fmt.Errorf("API请求失败: %v", err)
}
defer resp.Body.Close()
body, err := io.ReadAll(resp.Body)
if err != nil {
return nil, err
}
var result verifyResponse
if err := json.Unmarshal(body, &result); err != nil {
return nil, err
}
return &result, nil
}
// 使用示例
func main() {
result, err := createDataSegment(
"user@example.com",
"user_access_token",
"user_settings",
`{"theme": "dark", "language": "zh-CN"}`,
)
if err != nil {
log.Printf("创建数据段失败: %v", err)
return
}
if result.Success {
log.Printf("数据段创建成功: %+v", result.Data)
} else {
log.Printf("创建失败: %s", result.Message)
}
}
修改数据段
// updateDataSegment 修改数据段
func updateDataSegment(email, token, name, content string) (*verifyResponse, error) {
reqBody := map[string]string{
"email": email,
"token": token,
"name": name,
"content": content,
}
jsonBody, err := json.Marshal(reqBody)
if err != nil {
return nil, err
}
req, err := http.NewRequest("PUT", apiBaseURL+"/data-segments", bytes.NewBuffer(jsonBody))
if err != nil {
return nil, err
}
req.Header.Set("Content-Type", "application/json")
client := &http.Client{}
resp, err := client.Do(req)
if err != nil {
return nil, fmt.Errorf("API请求失败: %v", err)
}
defer resp.Body.Close()
body, err := io.ReadAll(resp.Body)
if err != nil {
return nil, err
}
var result verifyResponse
if err := json.Unmarshal(body, &result); err != nil {
return nil, err
}
return &result, nil
}
// 使用示例
func main() {
result, err := updateDataSegment(
"user@example.com",
"user_access_token",
"user_settings",
`{"theme": "light", "language": "zh-CN"}`,
)
if err != nil {
log.Printf("修改数据段失败: %v", err)
return
}
if result.Success {
log.Printf("数据段更新成功: %+v", result.Data)
} else {
log.Printf("更新失败: %s", result.Message)
}
}
删除数据段
// deleteDataSegment 删除数据段
func deleteDataSegment(email, token, name string) (*verifyResponse, error) {
reqBody := map[string]string{
"email": email,
"token": token,
"name": name,
}
jsonBody, err := json.Marshal(reqBody)
if err != nil {
return nil, err
}
req, err := http.NewRequest("DELETE", apiBaseURL+"/data-segments", bytes.NewBuffer(jsonBody))
if err != nil {
return nil, err
}
req.Header.Set("Content-Type", "application/json")
client := &http.Client{}
resp, err := client.Do(req)
if err != nil {
return nil, fmt.Errorf("API请求失败: %v", err)
}
defer resp.Body.Close()
body, err := io.ReadAll(resp.Body)
if err != nil {
return nil, err
}
var result verifyResponse
if err := json.Unmarshal(body, &result); err != nil {
return nil, err
}
return &result, nil
}
// 使用示例
func main() {
result, err := deleteDataSegment(
"user@example.com",
"user_access_token",
"user_settings",
)
if err != nil {
log.Printf("删除数据段失败: %v", err)
return
}
if result.Success {
log.Printf("数据段删除成功")
} else {
log.Printf("删除失败: %s", result.Message)
}
}
读取数据段
// readDataSegment 读取数据段
func readDataSegment(email, token, name string) (*verifyResponse, error) {
reqBody := map[string]string{
"email": email,
"token": token,
"name": name,
}
jsonBody, err := json.Marshal(reqBody)
if err != nil {
return nil, err
}
resp, err := http.Post(apiBaseURL+"/data-segments/read", "application/json", bytes.NewBuffer(jsonBody))
if err != nil {
return nil, fmt.Errorf("API请求失败: %v", err)
}
defer resp.Body.Close()
body, err := io.ReadAll(resp.Body)
if err != nil {
return nil, err
}
var result verifyResponse
if err := json.Unmarshal(body, &result); err != nil {
return nil, err
}
return &result, nil
}
// 使用示例
func main() {
result, err := readDataSegment(
"user@example.com",
"user_access_token",
"user_settings",
)
if err != nil {
log.Printf("读取数据段失败: %v", err)
return
}
if result.Success {
log.Printf("数据段读取成功: %+v", result.Data)
} else {
log.Printf("读取失败: %s", result.Message)
}
}
常见问题
Q: 软件Token和用户授权Token有什么区别?
A: 软件Token是用于标识软件身份的令牌,由热土工作室颁发给已认证的软件;用户授权Token是用户登录后生成的令牌,用于访问用户信息。
Q: 如何安全地存储软件Token?
A: 软件Token应该安全存储在软件中,避免硬编码在源代码中,建议使用环境变量或加密存储。
Q: 用户授权Token的有效期是多久?
A: 用户授权Token的有效期为1年,过期后需要重新登录。
Q: 如何申请软件认证?
A: 请发送邮件到 miles@rtstu.com 申请软件认证,包含软件名称、开发者信息、功能描述等。
Q: 第三方API的速率限制是多少?
A: 目前第三方API没有速率限制,但建议合理使用,避免过度请求。
Q: 数据段是什么?有什么用途?
A: 数据段是用户存储在热土用户系统中的数据,软件可以通过API创建、修改和删除这些数据段。数据段可以用于存储用户的设置、偏好、游戏存档等信息。
Q: 数据段的大小限制是多少?
A: 目前数据段的内容大小限制为1MB,超过这个限制的请求会被拒绝。
Q: 数据段的最大数量是多少?
A: 目前一个已授权的Token下可以存最多10个数据段。
Q: 数据段功能有哪些限制?
A: 数据段功能仅限已验证软件使用,未验证软件无法使用数据段功能。已验证软件需要通过热土工作室的认证,并拥有有效的软件Token。
Q: 数据段的访问权限如何控制?
A: 数据段的访问需要提供用户邮箱和有效的访问Token,确保只有授权的软件能够访问用户的数据。
Q: 如何安全地存储用户的敏感信息?
A: 数据段中不建议存储密码、银行卡号等敏感信息。如果需要存储敏感信息,建议在客户端进行加密后再存储。