首页 › 技术规格与 API
测试实现指南
📝 本页为参考译文(简体中文)。如与日文原版有出入,以日文版为准。
本文介绍在与Game8 Store对接时,如何通过简单的测试实现来试用请确认API规格文档,并准备必需API(购买可否检查(购买可否检查)和 POST /register(购买登记)。
预计所需时间:15分钟
1. 实现端点(预计:10分钟)
1.1 所需环境
- 使用 Node.js(Express)或 Python(FastAPI)
- 服务器可部署在本地或云端(AWS, GCP, Vercel, Render等)
1.2 使用 Node.js(Express)实现
const express = require("express");
const cors = require("cors");
const crypto = require("crypto");
const app = express();
app.use(express.json());
app.use(cors());
const VALID_ACCESS_TOKEN = "your_access_token";
const SECRET_KEY = "your_secret_key";
// 认证中间件
app.use((req, res, next) => {
const authHeader = req.headers.authorization;
if (!authHeader) {
return res.status(401).json({ result_code: "PUB1001", message: "缺少认证信息" });
}
const [scheme, token] = authHeader.split(" ");
if (scheme !== "Bearer" || token !== VALID_ACCESS_TOKEN) {
return res.status(401).json({ result_code: "PUB1002", message: "无效的访问令牌" });
}
next();
});
// X-Signature 验证中间件
const verifySignature = (req, res, next) => {
const signature = req.headers["x-signature"];
if (!signature) {
return res.status(400).json({ result_code: "PUB1004", message: "缺少签名" });
}
const requestData = req.method === "GET" ? req.query : req.body
const payload = JSON.stringify(requestData);
const computedSignature = crypto.createHmac("sha256", SECRET_KEY).update(payload).digest("base64");
if (signature !== computedSignature) {
return res.status(400).json({ result_code: "PUB1004", message: "签名无效" });
}
next();
};
// 购买可否检查(支持道具预留)
app.get("/check", verifySignature, (req, res) => {
const { game, user, item, price, transaction_id } = req.query;
if (!game || !user || !item || !price || !transaction_id || isNaN(price)) {
return res.status(400).json({ result_code: "PUB2001", message: "缺少必需参数或值无效" });
}
res.json({
request_id: "abc123",
timestamp: new Date().toISOString(),
result_code: "PUB0000",
message: "可以购买",
purchasable: "available",
age_category: "under_18",
account_limit: { total: 10000, remaining: 5000 },
requested_price: Number(price),
transaction_id: transaction_id
});
});
// 购买登记
app.post("/register", verifySignature, (req, res) => {
try {
const { game, user, item, transaction_id, item_name, price, quantity } = req.body;
if (!game || !user || !item || !transaction_id || !item_name || !price || !quantity || isNaN(price) || isNaN(quantity)) {
return res.status(400).json({ result_code: "PUB2001", message: "缺少必需参数或值无效" });
}
res.json({
request_id: "def456",
timestamp: new Date().toISOString(),
result_code: "PUB0000",
message: "已登记购买记录。",
item_granted: true,
transaction_id: transaction_id
});
} catch (error) {
res.status(500).json({ result_code: "PUB5000", message: "内部服务器错误" });
}
});
app.listen(3000, () => console.log("Server running on port 3000"));
1.3 使用 Python(FastAPI)实现
from fastapi import FastAPI, Request, HTTPException, Header, Depends
from fastapi.middleware.cors import CORSMiddleware
from pydantic import BaseModel
import hmac
import hashlib
import base64
import json
from datetime import datetime
from typing import Optional
from urllib.parse import urlencode
app = FastAPI()
# CORS中间件设置
app.add_middleware(
CORSMiddleware,
allow_origins=["*"],
allow_credentials=True,
allow_methods=["*"],
allow_headers=["*"],
)
SECRET_KEY = "your_secret_key"
VALID_ACCESS_TOKEN = "your_access_token"
# 请求模型
class RegisterRequest(BaseModel):
game: str
user: str
item: str
transaction_id: str
item_name: str
price: int
quantity: int
# 认证依赖函数
async def verify_auth(authorization: Optional[str] = Header(None)):
if not authorization:
raise HTTPException(
status_code=401,
detail={"result_code": "PUB1001", "message": "缺少认证信息"}
)
if authorization != f"Bearer {VALID_ACCESS_TOKEN}":
raise HTTPException(
status_code=401,
detail={"result_code": "PUB1002", "message": "无效的访问令牌"}
)
return True
# 签名验证依赖函数(用于GET请求)
async def verify_signature_get(request: Request, x_signature: Optional[str] = Header(None)):
if not x_signature:
raise HTTPException(
status_code=400,
detail={"result_code": "PUB1004", "message": "缺少签名"}
)
# 获取查询参数
query_params = dict(request.query_params)
payload = urlencode(query_params)
# 计算签名
computed_signature = base64.b64encode(
hmac.new(SECRET_KEY.encode(), payload.encode(), hashlib.sha256).digest()
).decode()
if x_signature != computed_signature:
raise HTTPException(
status_code=400,
detail={"result_code": "PUB1004", "message": "签名无效"}
)
return True
# 签名验证依赖函数(用于POST请求)
async def verify_signature_post(request: Request, x_signature: Optional[str] = Header(None)):
if not x_signature:
raise HTTPException(
status_code=400,
detail={"result_code": "PUB1004", "message": "缺少签名"}
)
# 获取请求体
body_bytes = await request.body()
if not body_bytes:
raise HTTPException(
status_code=400,
detail={"result_code": "PUB2001", "message": "缺少必需参数或值无效"}
)
# JSON格式解析
try:
body_json = json.loads(body_bytes)
payload = json.dumps(body_json)
except json.JSONDecodeError:
raise HTTPException(
status_code=400,
detail={"result_code": "PUB2001", "message": "无效的JSON格式"}
)
# 计算签名
computed_signature = base64.b64encode(
hmac.new(SECRET_KEY.encode(), payload.encode(), hashlib.sha256).digest()
).decode()
if x_signature != computed_signature:
raise HTTPException(
status_code=400,
detail={"result_code": "PUB1004", "message": "签名无效"}
)
return True
@app.get("/check")
async def check(
game: str,
user: str,
item: str,
price: int,
transaction_id: str,
_auth: bool = Depends(verify_auth),
_sig: bool = Depends(verify_signature_get)
):
return {
"request_id": "abc123",
"timestamp": datetime.utcnow().isoformat(),
"result_code": "PUB0000",
"message": "可以购买",
"purchasable": "available",
"age_category": "under_18",
"account_limit": {"total": 10000, "remaining": 5000},
"requested_price": price,
"transaction_id": transaction_id
}
@app.post("/register")
async def register(
request: RegisterRequest,
_auth: bool = Depends(verify_auth),
_sig: bool = Depends(verify_signature_post)
):
try:
return {
"request_id": "def456",
"timestamp": datetime.utcnow().isoformat(),
"result_code": "PUB0000",
"message": "已登记购买记录。",
"item_granted": True,
"transaction_id": request.transaction_id
}
except Exception as e:
raise HTTPException(
status_code=500,
detail={"result_code": "PUB5000", "message": "内部服务器错误"}
)
if __name__ == "__main__":
import uvicorn
uvicorn.run(app, host="0.0.0.0", port=3000)2. 使用Postman进行测试(预计:5分钟)
在Authorization标头中设置 Bearer your_access_token ,并在X-Signature中设置计算出的签名,然后尝试以下请求
※本页面的示例为连通性确认用的最小配置。实际请求与响应的全部字段请参阅API规格文档。
2.1 GET /check 的请求示例
GET http://localhost:3000/check
X-Signature: <SIGNED_DATA>
{
"game": "game123",
"user": "user456",
"item": "item789",
"transaction_id": "txn_123456",
"price": 500
}响应示例:
{
"request_id": "abc123",
"timestamp": "2025-02-27T12:00:00Z",
"result_code": "PUB0000",
"message": "可以购买",
"purchasable": true,
"transaction_id": "txn_123456"
}
2.2 POST /register 的请求示例
POST http://localhost:3000/register
Content-Type: application/json
X-Signature: <SIGNED_DATA>
{
"game": "game123",
"user": "user456",
"item": "item789",
"transaction_id": "txn_123456",
"item_name": "100宝石",
"price": 500,
"quantity": 1
}
响应示例:
{
"request_id": "def456",
"timestamp": "2025-02-27T12:00:00Z",
"result_code": "PUB0000",
"message": "已登记购买记录。",
"item_granted": true,
"transaction_id": "txn_123456"
}