PayStars Unified API · v3.0
Telegram Stars API · Fragment API。
与 StarKerak 共用同一余额。
网站、Telegram WebApp 和外部 API 使用同一个 StarKerak 余额和履约引擎。API 从 USD 余额付款,价格为 Fragment 价格 + 5%。响应为 JSON 格式。
认证
在控制台创建 API 密钥。完整密钥只显示一次。请保存在服务器环境变量中,切勿写入前端 JavaScript 或 Git 仓库。
X-API-Key: ps_your_secret_api_key Content-Type: application/json Idempotency-Key: order_20260719_0001
限流、校验与幂等
- 每个 API 密钥每秒 3 次请求。
- API 收款人校验上限:每个账号每分钟 120 次;网站/WebApp 为 12 次。
- 购买前必须调用
/check-username,获取 180 秒有效的verification_token。 - 每个 verification token 只绑定一笔逻辑订单;可使用相同幂等键安全重试。
- 购买星星和 Premium 时请发送唯一的 8–128 位
Idempotency-Key。 - 相同
Idempotency-Key与相同 payload 重复发送不会再次扣款,会返回原订单。 - 相同幂等键搭配不同 payload 会返回
409 Conflict。
API 状态
/statuscurl https://paystars.uz/api/v1/status
USD 余额与价格
账号和美元余额来自 StarKerak。价格以美元计:每笔订单为 Fragment 价格 + 5%。
/accountcurl https://paystars.uz/api/v1/account \
-H "X-API-Key: $PAYSTARS_API_KEY"{
"ok": true,
"user": { "telegram_id": 123456789 },
"balances": { "USD": "12.50" },
"currency_pref": "USD"
}/prices美元价格请使用下方的 POST /usd/quote:价格 = Fragment + 5%。
用户名校验
该接口通过 Fragment 获取名称、头像和 Premium 状态。只有可以购买的收款人才会返回 verification_token。
/check-usernamecurl -X POST https://paystars.uz/api/v1/check-username \ -H "X-API-Key: $PAYSTARS_API_KEY" \ -H "Content-Type: application/json" \ -d '{"username":"telegram","kind":"premium"}'
{
"valid": true,
"username": "telegram",
"nickname": "Telegram User",
"photo_url": "https://cdn4.telesco.pe/...",
"premium_active": false,
"verification_token": "...",
"verification_expires_in": 180
}kind 为 stars 或 premium。如果已开通 Premium,会返回 premium_active: true、valid: false,token 为 null。
星星订单
/stars/buycurl -X POST https://paystars.uz/api/v1/stars/buy \ -H "X-API-Key: $PAYSTARS_API_KEY" \ -H "Idempotency-Key: order_20260719_0001" \ -H "Content-Type: application/json" \ -d '{"username":"telegram","quantity":100,"verification_token":"TOKEN_FROM_CHECK","currency":"USD","max_usd":1.58}'
{
"ok": true,
"order_id": 1842,
"status": "processing",
"quantity": 100,
"cost": 1.58,
"balance": 10.92,
"currency": "USD"
}美元(USD)余额与 USDT
API 从美元余额付款,使用 TON 或 BEP20 网络的 USDT 充值(最低 1 USDT),不支持 TRC20(TRON)。美元价格 = Fragment 价格 + 5%(按美分向上取整)。
/usd/wallet美元余额、TON 地址与个人备注、BEP20 地址(含二维码图片)。
{
"ok": true,
"usd": { "balance": "12.50", "micros": 12500000 },
"min_deposit": "1.00",
"ton": { "address": "UQ...", "memo": "...", "enabled": true, "ttl_min": 30 },
"bsc": { "address": "0x...", "contract": "0x55d398326f99059fF775485246999027B3197955", "enabled": true, "ttl_min": 30 }
}usd.balance 为美元余额(字符串);usd.micros:1 USD = 1,000,000 micros。
/usd/invoice{"amount": 10, "chain": "ton"} 或 "chain": "bsc" → 30 分钟内有效的精确金额(例如 10.0437)。请向所选网络的地址转入完全相同金额的 USDT(TON 无需备注)。/usd/bsc-invoice 作为旧别名仍可使用(默认:bsc)。
/usd/invoice/{id}/cancel取消待支付账单(例如更改金额)。已取消的精确金额 24 小时内不会分配给他人,期间到账的付款仍会计入您的余额。
/usd/invoice/{id}状态:pending, paid, expired 或 cancelled。
/usd/quote{"kind":"stars","username":"durov","quantity":100} 或 {"kind":"premium","username":"durov","months":3} → {"usd": 1.58}.
如需从美元余额付款,请在 /stars/buy 或 /premium/buy 的 payload 中加入 "currency": "USD" 和来自 /usd/quote 的 "max_usd": 1.58。若 Fragment 价格超过 max_usd,不扣款并返回 409 price_changed —— 请重新报价。若省略 currency,将使用账号保存的币种偏好(/usd/wallet 中的 pref),因此请始终发送 "currency": "USD"。响应中的 cost 和 balance 以 currency 字段的币种计。
curl -X POST https://paystars.uz/api/v1/stars/buy \
-H "X-API-Key: $PAYSTARS_API_KEY" -H "Idempotency-Key: stars_8f2c1a9b" \
-H "Content-Type: application/json" \
-d '{"username":"durov","quantity":100,"verification_token":"...","currency":"USD","max_usd":1.58}'订单
/orders返回通过网站、WebApp 和 API 下的最近 50 笔订单。
/order/{order_id}curl https://paystars.uz/api/v1/order/1842 \
-H "X-API-Key: $PAYSTARS_API_KEY"错误码
| Status | 含义 | 处理方式 |
|---|---|---|
| 400 | payload 或幂等键无效 | 检查请求格式 |
| 401 | API 密钥无效 | 创建新密钥 |
| 402 | USD 余额不足 | 用 USDT 充值 |
| 409 | 校验已过期/已使用或幂等冲突 | 重新校验收款人 |
| 422 | 用户名或服务不可用 | 检查收款人 |
| 402 | insufficient_balance(USD) | 用 USDT 充值美元余额 |
| 409 | price_changed —— USD 价格超过 max_usd | 重新获取 /usd/quote |
| 429 | 超出请求限制 | 按 Retry-After 重试 |
| 503 | 服务暂时不可用 | 使用指数退避 |
{
"detail": {
"code": "insufficient_balance",
"message": "StarKerak balance is insufficient"
}
}可运行示例
多种编程语言示例
每个示例都会校验收款人、获取短期 token,并使用幂等键以便安全重试同一订单。所有示例均从 USD 余额付款。
API="https://paystars.uz/api/v1"
ORDER_KEY="stars_$(uuidgen)"
VERIFY=$(curl --fail-with-body -sS -X POST "$API/check-username" \
-H "X-API-Key: $PAYSTARS_API_KEY" \
-H "Content-Type: application/json" \
-d '{"username":"telegram","kind":"stars"}')
TOKEN=$(printf '%s' "$VERIFY" | jq -r '.verification_token')
curl --fail-with-body -sS -X POST "$API/stars/buy" \
-H "X-API-Key: $PAYSTARS_API_KEY" \
-H "Idempotency-Key: $ORDER_KEY" \
-H "Content-Type: application/json" \
-d "{\"username\":\"telegram\",\"quantity\":100,\"verification_token\":\"$TOKEN\",\"currency\":\"USD\"}"import { randomUUID } from 'node:crypto';
const base = 'https://paystars.uz/api/v1';
const headers = { 'X-API-Key': process.env.PAYSTARS_API_KEY, 'Content-Type': 'application/json' };
const verify = await fetch(`${base}/check-username`, {
method: 'POST', headers, body: JSON.stringify({ username: 'telegram', kind: 'stars' })
}).then(async r => { if (!r.ok) throw new Error(await r.text()); return r.json(); });
const order = await fetch(`${base}/stars/buy`, {
method: 'POST', headers: { ...headers, 'Idempotency-Key': `stars_${randomUUID()}` },
body: JSON.stringify({ username: verify.username, quantity: 100, verification_token: verify.verification_token, currency: 'USD' })
}).then(async r => { if (!r.ok) throw new Error(await r.text()); return r.json(); });
console.log(order.order_id, order.status);import os, uuid, requests
base = "https://paystars.uz/api/v1"
headers = {"X-API-Key": os.environ["PAYSTARS_API_KEY"]}
verify = requests.post(f"{base}/check-username", headers=headers,
json={"username": "telegram", "kind": "premium"}, timeout=15)
verify.raise_for_status()
recipient = verify.json()
order = requests.post(f"{base}/premium/buy", headers={
**headers, "Idempotency-Key": f"premium_{uuid.uuid4()}"
}, json={"username": recipient["username"], "months": 3,
"verification_token": recipient["verification_token"], "currency": "USD"}, timeout=20)
order.raise_for_status()
print(order.json())<?php
$base = 'https://paystars.uz/api/v1';
$key = getenv('PAYSTARS_API_KEY');
function postJson($url, $headers, $body) {
$ch = curl_init($url);
curl_setopt_array($ch, [CURLOPT_RETURNTRANSFER => true, CURLOPT_POST => true,
CURLOPT_HTTPHEADER => $headers, CURLOPT_POSTFIELDS => json_encode($body), CURLOPT_TIMEOUT => 20]);
$raw = curl_exec($ch); $status = curl_getinfo($ch, CURLINFO_HTTP_CODE); curl_close($ch);
if ($status < 200 || $status >= 300) throw new RuntimeException($raw);
return json_decode($raw, true, flags: JSON_THROW_ON_ERROR);
}
$common = ["X-API-Key: $key", 'Content-Type: application/json'];
$user = postJson("$base/check-username", $common, ['username' => 'telegram', 'kind' => 'stars']);
$order = postJson("$base/stars/buy", [...$common, 'Idempotency-Key: stars_'.bin2hex(random_bytes(16))],
['username' => $user['username'], 'quantity' => 100, 'verification_token' => $user['verification_token'], 'currency' => 'USD']);
print_r($order);package main
import ("bytes"; "encoding/json"; "fmt"; "io"; "net/http"; "os"; "github.com/google/uuid")
func post(path string, body any, idempotency string, out any) error {
data, _ := json.Marshal(body)
req, _ := http.NewRequest("POST", "https://paystars.uz/api/v1"+path, bytes.NewReader(data))
req.Header.Set("X-API-Key", os.Getenv("PAYSTARS_API_KEY")); req.Header.Set("Content-Type", "application/json")
if idempotency != "" { req.Header.Set("Idempotency-Key", idempotency) }
res, err := http.DefaultClient.Do(req); if err != nil { return err }; defer res.Body.Close()
if res.StatusCode >= 300 { raw, _ := io.ReadAll(res.Body); return fmt.Errorf("API %d: %s", res.StatusCode, raw) }
return json.NewDecoder(res.Body).Decode(out)
}
func main() {
var user struct { Username string `json:"username"`; VerificationToken string `json:"verification_token"` }
if err := post("/check-username", map[string]any{"username":"telegram", "kind":"stars"}, "", &user); err != nil { panic(err) }
var order map[string]any
if err := post("/stars/buy", map[string]any{"username":user.Username, "quantity":100,
"verification_token":user.VerificationToken, "currency":"USD"}, "stars_"+uuid.NewString(), &order); err != nil { panic(err) }
fmt.Println(order)
}一个提示词完成对接
AI 提示词
把下面的提示词发给 Codex、ChatGPT 或其他编程智能体,并把方括号中的内容替换为您的项目信息。
你是一名资深后端与应用安全工程师。请为我构建一个完整的、可直接用于生产环境的 PayStars API 集成。
项目类型:[Telegram 机器人 / Web 后端 / 移动应用后端]
语言与框架:[例如:Python 3.12 + aiogram 3 + FastAPI]
项目名称:[名称]
PayStars base URL: https://paystars.uz/api/v1
API 密钥只能从 PAYSTARS_API_KEY 环境变量读取,绝不能暴露给前端、日志、Git 或错误信息。所有请求必须走 HTTPS 并在服务端发起。请加入超时、结构化日志(不含密钥)、输入校验和测试。
完整实现以下流程:
1. 通过 GET /usd/wallet 获取 USD 余额。不要硬编码价格:每次购买前通过 POST /usd/quote 获取美元价格(Fragment 价格 + 5%)。
2. 购买星星或 Premium 前,向 POST /check-username 发送 {"username":"...","kind":"stars|premium"}。
3. 检查响应中的 valid、nickname、photo_url、premium_active 和 verification_token。向用户展示头像、名称、@username 和 Premium 状态,并获得明确确认。未经确认不得创建订单。
4. verification_token 有效期 180 秒。过期或返回 409 时重新校验用户名。
5. 星星:向 POST /stars/buy 发送 username、quantity 和 verification_token;Premium:向 POST /premium/buy 发送 username、months(3、6 或 12)和 verification_token。每次购买都要发送 "currency": "USD",并把报价作为 "max_usd";遇到 409 price_changed 重新报价,遇到 402 insufficient_balance 提示用户用 USDT(TON 或 BEP20)充值 USD 余额。
6. 每笔逻辑订单基于加密安全的 UUID 生成 8–128 位 Idempotency-Key。网络重试时复用完全相同的键和 payload,绝不用于其他订单。
7. 通过 GET /order/{order_id} 轮询状态,通过 GET /orders 展示历史。正确处理 processing/pending/completed/failed 状态。
8. API 限流为每个密钥每秒 3 次。遇到 429 遵守 Retry-After;遇到 503 和临时网络错误使用带抖动的有限指数退避。对 400、401、402、409、422、429 和 503 给用户安全、清晰的提示。
9. 不要盲目信任 API 响应:按 schema 校验、规范化用户名、在服务端检查 quantity/months 限制。photo_url 只能作为允许的 HTTPS 图片展示。绝不记录 verification token、API 密钥或完整请求头。
10. 处理同一用户的并发点击、重放、重复订单、伪造回调、竞态条件、超时和进程重启。用事务把状态持久化到数据库,并把用户确认与订单绑定。
如果项目是 Telegram 机器人:创建 /start、“购买星星”、“购买 Premium”、“余额”、“订单”菜单;分步收集用户名和数量;校验后显示内联“确认/取消”按钮;检查回调归属和 TTL;配置 webhook secret 或 long-polling 的安全设置。
请交付可运行的真实代码而非伪代码:明确的目录结构、依赖文件、.env.example(不含真实密钥)、数据库迁移、Dockerfile、健康检查、README、本地运行与部署说明、单元/集成测试。把 API 客户端放在独立模块中。所有价格、余额和订单以 PayStars API 为唯一可信来源,绝不直接连接 StarKerak 数据库。先用简短列表询问缺失的业务信息,其余技术决策用安全的默认值自行完成。