支付
概述
StablePay 支付接口提供完整的加密货币支付能力,支持多种稳定币(USDT、USDC)和多种区块链网络(TRON、Ethereum、BSC、Solana)。
基础信息
- Base URL:
https://api.stablepay.co(生产环境) - API路径前缀:
/api/v1 - 协议: HTTPS
- 数据格式: JSON
- 字符编码: UTF-8
端点
| 方法 | 端点 | 描述 |
|---|---|---|
| POST | /api/v1/checkout/sessions/create | 创建支付会话 |
| GET | /api/v1/checkout/sessions/:session_id | 获取支付会话详情 |
| POST | /api/v1/checkout/sessions/:session_id/cancel | 取消支付会话 |
认证方式
所有API请求都需要在HTTP请求头中包含以下认证信息:
必需请求头
Authorization: Bearer {api_key}
请求头说明
| 请求头 | 类型 | 必填 | 说明 |
|---|---|---|---|
| Content-Type | string | 是 | 固定为 application/json ,GET请求不必携带 |
| Authorization | string | 是 | API密钥,格式:Bearer {api_key} |
| X-StablePay-Timestamp | string | 是 | 请求时间戳(Unix时间戳,秒级) |
| X-StablePay-Nonce | string | 是 | 随机数(用于防重放攻击) |
| X-StablePay-Signature | string | 是 | 请求签名(HMAC-SHA256) |
注意:
- API密钥由StablePay平台分配,请妥善保管,不要泄露
- API密钥格式:
Bearer sk_live_xxx(生产环境)或Bearer sk_test_xxx(测试环境)
请求签名
为了确保请求的安全性,所有API请求都需要包含签名信息。签名使用HMAC-SHA256算法计算。
签名计算步骤
准备签名参数:
timestamp: 当前Unix时间戳(秒级)nonce: 随机字符串(建议使用UUID)requestBody: 请求体的JSON字符串(GET请求为空字符串)
构建签名字符串:
signString = timestamp + "." + nonce + "." + requestBody计算签名:
signature = HMAC-SHA256(api_secret, signString)其中
api_secret是API密钥对应的密钥(从API密钥中提取或单独提供)设置请求头:
X-StablePay-Timestamp: {timestamp} X-StablePay-Nonce: {nonce} X-StablePay-Signature: {signature}
签名示例代码
JavaScript/Node.js:
const crypto = require('crypto');
function calculateSignature(apiSecret, timestamp, nonce, requestBody) {
const signString = `${timestamp}.${nonce}.${requestBody}`;
const signature = crypto
.createHmac('sha256', apiSecret)
.update(signString)
.digest('hex');
return signature;
}
// 使用示例 / Usage example
const timestamp = Math.floor(Date.now() / 1000).toString();
const nonce = require('uuid').v4();
const requestBody = JSON.stringify({
amount: '100.00',
currency: 'USD',
order_id: 'order_20250101001'
});
const signature = calculateSignature(apiSecret, timestamp, nonce, requestBody);
// 设置请求头 / Set request headers
headers['X-StablePay-Timestamp'] = timestamp;
headers['X-StablePay-Nonce'] = nonce;
headers['X-StablePay-Signature'] = signature;
Python:
import hmac
import hashlib
import time
import uuid
import json
def calculate_signature(api_secret, timestamp, nonce, request_body):
"""计算请求签名 / Calculate request signature"""
sign_string = f"{timestamp}.{nonce}.{request_body}"
signature = hmac.new(
api_secret.encode('utf-8'),
sign_string.encode('utf-8'),
hashlib.sha256
).hexdigest()
return signature
# 使用示例 / Usage example
timestamp = str(int(time.time()))
nonce = str(uuid.uuid4())
request_body = json.dumps({
'amount': '100.00',
'currency': 'USD',
'order_id': 'order_20250101001'
})
signature = calculate_signature(api_secret, timestamp, nonce, request_body)
# 设置请求头 / Set request headers
headers['X-StablePay-Timestamp'] = timestamp
headers['X-StablePay-Nonce'] = nonce
headers['X-StablePay-Signature'] = signature
Go:
import (
"crypto/hmac"
"crypto/sha256"
"encoding/hex"
"fmt"
"time"
"github.com/google/uuid"
)
func calculateSignature(apiSecret, timestamp, nonce, requestBody string) string {
signString := fmt.Sprintf("%s.%s.%s", timestamp, nonce, requestBody)
mac := hmac.New(sha256.New, []byte(apiSecret))
mac.Write([]byte(signString))
return hex.EncodeToString(mac.Sum(nil))
}
// 使用示例 / Usage example
timestamp := fmt.Sprintf("%d", time.Now().Unix())
nonce := uuid.New().String()
requestBody := `{"amount":"100.00","currency":"USD","order_id":"order_20250101001"}`
signature := calculateSignature(apiSecret, timestamp, nonce, requestBody)
// 设置请求头 / Set request headers
headers["X-StablePay-Timestamp"] = timestamp
headers["X-StablePay-Nonce"] = nonce
headers["X-StablePay-Signature"] = signature
签名验证说明
- 服务端会验证时间戳是否在允许的范围内(通常为5分钟)
- 服务端会验证nonce是否已被使用(防重放攻击)
- 服务端会重新计算签名并与请求头中的签名进行比对
接口列表
1. 创建支付会话
创建新的支付会话,系统会自动生成收款地址、二维码和钱包深度链接。
接口地址
POST /api/v1/checkout/sessions/create
请求头
Content-Type: application/json
Authorization: Bearer sk_live_xxxxxxxxxx
X-StablePay-Timestamp: 1735123456
X-StablePay-Nonce: 550e8400-e29b-41d4-a716-446655440000
X-StablePay-Signature: 3c8f9d2a7b6e5d4c3b2a1f0e9d8c7b6a5f4e3d2c1b0a9f8e7d6c5b4a3f2e1d0
请求参数
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
| amount | string | 是 | 支付金额(面额字符串,如 "10.50") |
| currency | string | 是 | 货币代码(如 "USD") |
| order_id | string | 是 | 订单号(商户系统的订单ID,需唯一) |
| merchant_domain_id | string | 否 | 商户域名ID |
| description | string | 否 | 订单描述 |
| line_items | array | 否 | 商品明细列表 |
| line_items[].price_data | object | 是 | 价格数据(当提供 line_items 时必填) |
| line_items[].price_data.currency | string | 是 | 货币代码(如 "USD", "CNY") |
| line_items[].price_data.unit_amount | string | 是 | 单价(面额字符串,如 "10.50") |
| line_items[].price_data.product_data | object | 是 | 商品数据 |
| line_items[].price_data.product_data.name | string | 是 | 商品名称 |
| line_items[].price_data.product_data.description | string | 否 | 商品描述 |
| line_items[].quantity | number | 否 | 数量,默认为1 |
| tax_amount | string | 否 | 税费金额(面额字符串,如 "10.00") |
| shipping_amount | string | 否 | 运费金额(面额字符串,如 "5.00") |
| success_url | string | 否 | 支付成功后的跳转URL |
| cancel_url | string | 否 | 支付取消后的跳转URL |
| metadata | object | 否 | 元数据(键值对) |
请求示例
{
"amount": "100.00",
"currency": "USD",
"order_id": "order_20250101001",
"description": "Purchase goods",
"line_items": [
{
"price_data": {
"currency": "USD",
"unit_amount": "50.00",
"product_data": {
"name": "Product A",
"description": "This is a description of Product A"
}
},
"quantity": 1
}
],
"tax_amount": "10.00",
"shipping_amount": "5.00",
"success_url": "https://example.com/success",
"cancel_url": "https://example.com/cancel",
"metadata": {
"customer_id": "customer_123",
"product_id": "product_456"
}
}
响应示例
{
"id": "sess_xxxxxxxxxxxx",
"amount_total": "100.00",
"currency": "usd",
"payment_status": "unpaid",
"created": 1735123456,
"expires_at": 1735127056,
"url": "https://cashier.stablepay.co/pay/sess_xxxxxxxxxxxx",
"line_items": [
{
"price_data": {
"currency": "usd",
"unit_amount": "50.00",
"product_data": {
"name": "Product A",
"description": "This is a description of Product A"
}
},
"quantity": 1
}
],
"tax_amount": "10.00",
"shipping_amount": "5.00",
"exchange_rate": "7.2500",
"target_currency": "USDT",
"target_amount_total": "725.00",
"rate_locked_at": 1735123456,
"metadata": {
"customer_id": "customer_123",
"product_id": "product_456",
"order_id": "order_20250101001"
}
}
响应字段说明
| 字段 | 类型 | 说明 |
|---|---|---|
| id | string | 支付会话ID(格式:sess_xxx) |
| amount_total | string | 总金额(面额字符串,如:"100.00") |
| currency | string | 货币代码(小写,如:usd) |
| payment_status | string | 支付状态:unpaid(未支付)、paid(已支付) |
| created | number | 创建时间戳(Unix时间戳) |
| expires_at | number | 过期时间戳(Unix时间戳) |
| url | string | 支付页面URL |
| exchange_rate | string | 汇率值(如果存在汇率转换,如:"7.2500")。当商户币种与支付币种不同时返回 |
| target_currency | string | 支付结算币种(如:"USDT"),即用户实际支付的加密货币。当存在汇率转换时返回 |
| target_amount_total | string | 目标支付金额(面额字符串,如:"725.00"),即用户需要支付的实际加密货币金额。当存在汇率转换时返回 |
| rate_locked_at | number | 汇率锁定时间戳(Unix时间戳)。当存在汇率转换时返回 |
| metadata | object | 元数据(可选) |
汇率和加密货币支付说明:
- 当商户订单币种(
currency)与支付币种(target_currency)不同时,系统会自动进行汇率转换 exchange_rate表示商户币种到支付币种的汇率(如:1 USD = 7.25 USDT)target_currency表示用户实际需要支付的加密货币(通常为 USDT 或 USDC)target_amount_total表示用户需要支付的实际加密货币金额rate_locked_at表示汇率锁定的时间,汇率在锁定期间保持不变- 如果商户币种与支付币种相同(如:商户使用 USDT,用户也支付 USDT),则不会返回汇率相关字段
状态码
200 OK: 创建成功400 Bad Request: 请求参数错误401 Unauthorized: 认证失败503 Service Unavailable: 服务不可用(汇率服务不可用)
2. 获取支付会话
根据支付会话ID获取支付会话详情。
接口地址
GET /api/v1/checkout/sessions/{session_id}
请求头
Authorization: Bearer sk_live_xxxxxxxxxx
路径参数
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
| session_id | string | 是 | 支付会话ID |
请求示例
curl -X GET "https://api.stablepay.co/api/v1/checkout/sessions/cs_xxxxxxxxxxxx" \
-H "Authorization: Bearer sk_live_xxxxxxxxxx" \
-H "X-StablePay-Timestamp: 1735123456" \
-H "X-StablePay-Nonce: 550e8400-e29b-41d4-a716-446655440000" \
-H "X-StablePay-Signature: 3c8f9d2a7b6e5d4c3b2a1f0e9d8c7b6a5f4e3d2c1b0a9f8e7d6c5b4a3f2e1d0"
响应示例
{
"id": "sess_xxxxxxxxxxxx",
"amount_total": "100.00",
"currency": "usd",
"payment_status": "paid",
"created": 1735123456,
"expires_at": 1735127056,
"url": "https://cashier.stablepay.co/pay/cs_xxxxxxxxxxxx",
"line_items": [
{
"price_data": {
"currency": "usd",
"unit_amount": "50.00",
"product_data": {
"name": "商品A",
"description": "这是商品A的描述"
}
},
"quantity": 1
},
{
"price_data": {
"currency": "usd",
"unit_amount": "50.00",
"product_data": {
"name": "商品B",
"description": "这是商品B的描述"
}
},
"quantity": 1
}
],
"tax_amount": "10.00",
"shipping_amount": "5.00",
"exchange_rate": "7.2500",
"target_currency": "USDT",
"target_amount_total": "725.00",
"rate_locked_at": 1735123456,
"metadata": {
"order_id": "order_20250101001"
}
}
状态码
200 OK: 查询成功400 Bad Request: 请求参数错误401 Unauthorized: 认证失败404 Not Found: 支付会话不存在或无权访问
3. 取消支付会话
取消(使过期)指定的支付会话。
接口地址
POST /api/v1/checkout/sessions/{session_id}/cancel
请求头
Content-Type: application/json
Authorization: Bearer sk_live_xxxxxxxxxx
路径参数
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
| session_id | string | 是 | 支付会话ID |
请求示例
curl -X POST "https://api.stablepay.co/api/v1/checkout/sessions/cs_xxxxxxxxxxxx/cancel" \
-H "Content-Type: application/json" \
-H "Authorization: Bearer sk_live_xxxxxxxxxx" \
-H "X-StablePay-Timestamp: 1735123456" \
-H "X-StablePay-Nonce: 550e8400-e29b-41d4-a716-446655440000" \
-H "X-StablePay-Signature: 3c8f9d2a7b6e5d4c3b2a1f0e9d8c7b6a5f4e3d2c1b0a9f8e7d6c5b4a3f2e1d0"
响应示例
{
"id": "cs_xxxxxxxxxxxx",
"amount_total": "100.00",
"currency": "usd",
"payment_status": "unpaid",
"created": 1735123456,
"expires_at": 1735123456,
"url": "https://cashier.stablepay.co/pay/cs_xxxxxxxxxxxx",
"tax_amount": "10.00",
"shipping_amount": "5.00",
"exchange_rate": "7.2500",
"target_currency": "USDT",
"target_amount_total": "725.00",
"rate_locked_at": 1735123456
}
状态码
200 OK: 取消成功400 Bad Request: 请求参数错误或会话已过期401 Unauthorized: 认证失败404 Not Found: 支付会话不存在或无权访问
数据结构
PaymentSession 支付会话对象
interface PaymentSession {
id: string; // Payment session ID, format: cs_xxxxxxxxxxxx
amount_total: string; // Total amount (decimal string, e.g., "100.00")
currency: string; // Currency code (uppercase)
payment_status: "unpaid" | "paid"; // Payment status
created: number; // Creation timestamp (Unix timestamp)
expires_at: number; // Expiration timestamp (Unix timestamp)
url?: string; // Payment page URL
line_items?: LineItem[]; // Line items list
tax_amount?: string; // Tax amount (decimal string)
shipping_amount?: string; // Shipping amount (decimal string)
exchange_rate?: string; // Exchange rate value (if currency conversion exists)
target_currency?: string; // Payment settlement currency (e.g., "USDT")
target_amount_total?: string; // Target payment amount (decimal string, e.g., "725.00")
rate_locked_at?: number; // Exchange rate lock timestamp (Unix timestamp)
metadata?: Record<string, string>; // Metadata
}
interface LineItem {
price_data: PriceData; // Price data
quantity: number; // Quantity
}
interface PriceData {
currency: string; // Currency code
unit_amount: string; // Unit price (decimal string)
product_data: ProductData; // Product data
}
interface ProductData {
name: string; // Product name
description?: string; // Product description
}