接入文档
本文档介绍如何将量云AI支付集成到您的网站或应用中,实现安全、可靠的在线收款。
安全提醒
您必须验证回调签名,否则存在被伪造支付通知的风险!
接入流程
-
申请 API Key
发送邮件到pay@lyg.ai申请 -
创建应用
使用 API Key 自助创建应用,获取app_id和app_secret -
对接支付 API
调用创建订单接口,获取支付链接 -
处理回调
实现回调接口,验证签名并更新订单状态
创建订单
调用此接口创建支付订单,获取支付链接后引导用户完成支付。
请求地址
POST https://pay.lt-ai.com/api/v1/payment/create
请求参数
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
app_id |
string | 是 | 应用ID |
out_trade_no |
string | 是 | 商户订单号(您系统中的唯一标识) |
amount |
int | 是 | 金额,单位:分(100 = 1元) |
subject |
string | 是 | 商品描述 |
timestamp |
int | 是 | 请求时间戳(秒) |
nonce |
string | 是 | 随机字符串(16-32位) |
signature |
string | 是 | HMAC-SHA256 签名 |
可选参数
| 参数 | 类型 | 默认值 | 说明 |
|---|---|---|---|
body |
string | - | 商品详情描述 |
expire_minutes |
int | 30 | 订单过期时间(分钟) |
extra_data |
object | - | 附加数据(回调时原样返回) |
签名规则
- 将所有参数(除 signature)按字典序排列
- 拼接为
key1=value1&key2=value2格式 - 使用
app_secret进行 HMAC-SHA256 签名
签名示例
假设参数如下:
app_id = "APP123456"
out_trade_no = "ORDER_001"
amount = 100
subject = "测试商品"
timestamp = 1736489400
nonce = "abc123xyz"
按字典序拼接后的签名字符串:
amount=100&app_id=APP123456&nonce=abc123xyz&out_trade_no=ORDER_001&subject=测试商品×tamp=1736489400
使用 app_secret 计算 HMAC-SHA256 即为 signature。
响应示例
{
"success": true,
"message": "订单创建成功",
"data": {
"order_id": "LY1768021783839...",
"payment_url": "https://pay.lt-ai.com/pay/xxxxx",
"expire_at": "2026-01-10T06:00:00"
}
}
错误响应
{
"success": false,
"message": "签名验证失败",
"data": null
}
常见错误信息:
签名验证失败- signature 不正确请求已过期- timestamp 超过5分钟请求已处理,请勿重复提交- nonce 重复使用应用不存在或已禁用- app_id 无效订单号已存在- out_trade_no 重复
查询订单
POST https://pay.lt-ai.com/api/v1/payment/query
请求参数
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
app_id |
string | 是 | 应用ID |
order_id |
string | 二选一 | 量云订单号(LY开头) |
out_trade_no |
string | 二选一 | 商户订单号 |
timestamp |
int | 是 | 请求时间戳(秒) |
nonce |
string | 是 | 随机字符串(16-32位) |
signature |
string | 是 | HMAC-SHA256 签名 |
响应示例
{
"success": true,
"message": "查询成功",
"data": {
"order_id": "LY1768021783839...",
"out_trade_no": "YOUR_ORDER_123",
"status": "paid",
"amount": 100,
"paid_at": "2026-01-10T05:30:00"
}
}
订单状态 status 可能的值:
pending- 待支付paid- 已支付expired- 已过期closed- 已关闭
回调通知
当用户支付成功后,系统会向您配置的回调地址发送 POST 请求。
HTTP Headers
| Header | 说明 |
|---|---|
Content-Type |
application/json |
X-LyPay-Signature |
HMAC-SHA256 签名 |
X-LyPay-Timestamp |
请求时间戳 |
回调数据
{
"order_id": "LY1768021783839...",
"out_trade_no": "YOUR_ORDER_123",
"app_id": "APP176798...",
"amount": 100,
"status": "paid",
"paid_at": "2026-01-10T05:30:00",
"timestamp": 1736489400,
"nonce": "a1b2c3d4e5f6",
"signature": "e5d4c3b2a1..."
}
签名验证
签名算法
HMAC-SHA256(签名字符串, app_secret)
签名字符串
amount={amount}&nonce={nonce}&order_id={order_id}&status={status}×tamp={timestamp}
注意:参数必须按字母顺序排列!
验证步骤
-
检查时间戳
确保 timestamp 在 5 分钟有效期内 -
检查 Nonce
确保该 nonce 未被处理过(防重放攻击) -
计算签名
使用相同算法计算签名并比较 -
验证订单
确认金额与您系统中的订单一致
代码示例
创建订单 - Python
import hmac import hashlib import time import secrets import requests APP_ID = "your_app_id" APP_SECRET = "your_app_secret" API_URL = "https://pay.lt-ai.com/api/v1/payment/create" def create_order(out_trade_no, amount, subject): # 1. 准备参数 timestamp = int(time.time()) nonce = secrets.token_urlsafe(16) params = { "app_id": APP_ID, "out_trade_no": out_trade_no, "amount": amount, "subject": subject, "timestamp": timestamp, "nonce": nonce } # 2. 按字典序排列并拼接签名字符串 sign_str = "&".join( f"{k}={v}" for k, v in sorted(params.items()) ) # 3. 计算 HMAC-SHA256 签名 signature = hmac.new( APP_SECRET.encode(), sign_str.encode(), hashlib.sha256 ).hexdigest() params["signature"] = signature # 4. 发送请求 response = requests.post(API_URL, json=params) result = response.json() if result["success"]: print(f"支付链接: {result['data']['payment_url']}") return result["data"] else: raise Exception(result["message"]) # 使用示例 order = create_order("ORDER_12345", 100, "测试商品") # 将 order["payment_url"] 返回给前端,引导用户支付Python
创建订单 - Node.js
const crypto = require('crypto'); const axios = require('axios'); const APP_ID = 'your_app_id'; const APP_SECRET = 'your_app_secret'; const API_URL = 'https://pay.lt-ai.com/api/v1/payment/create'; async function createOrder(outTradeNo, amount, subject) { // 1. 准备参数 const timestamp = Math.floor(Date.now() / 1000); const nonce = crypto.randomBytes(16).toString('base64url'); const params = { app_id: APP_ID, out_trade_no: outTradeNo, amount: amount, subject: subject, timestamp: timestamp, nonce: nonce }; // 2. 按字典序排列并拼接签名字符串 const signStr = Object.keys(params) .sort() .map(k => `${k}=${params[k]}`) .join('&'); // 3. 计算 HMAC-SHA256 签名 const signature = crypto .createHmac('sha256', APP_SECRET) .update(signStr) .digest('hex'); params.signature = signature; // 4. 发送请求 const response = await axios.post(API_URL, params); if (response.data.success) { console.log(`支付链接: ${response.data.data.payment_url}`); return response.data.data; } else { throw new Error(response.data.message); } } // 使用示例 createOrder('ORDER_12345', 100, '测试商品') .then(order => { // 将 order.payment_url 返回给前端 });Node.js
创建订单 - PHP
<?php define('APP_ID', 'your_app_id'); define('APP_SECRET', 'your_app_secret'); define('API_URL', 'https://pay.lt-ai.com/api/v1/payment/create'); function createOrder($outTradeNo, $amount, $subject) { // 1. 准备参数 $timestamp = time(); $nonce = bin2hex(random_bytes(16)); $params = [ 'app_id' => APP_ID, 'out_trade_no' => $outTradeNo, 'amount' => $amount, 'subject' => $subject, 'timestamp' => $timestamp, 'nonce' => $nonce ]; // 2. 按字典序排列并拼接签名字符串 ksort($params); $signStr = http_build_query($params); // 3. 计算 HMAC-SHA256 签名 $signature = hash_hmac('sha256', $signStr, APP_SECRET); $params['signature'] = $signature; // 4. 发送请求 $ch = curl_init(API_URL); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); curl_setopt($ch, CURLOPT_POST, true); curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($params)); curl_setopt($ch, CURLOPT_HTTPHEADER, [ 'Content-Type: application/json' ]); $response = curl_exec($ch); curl_close($ch); $result = json_decode($response, true); if ($result['success']) { return $result['data']; } else { throw new Exception($result['message']); } } // 使用示例 $order = createOrder('ORDER_12345', 100, '测试商品'); // 将 $order['payment_url'] 返回给前端 ?>PHP
回调验证 - Python
import hmac import hashlib import time from flask import Flask, request, jsonify app = Flask(__name__) APP_SECRET = "your_app_secret" processed_nonces = set() # 生产环境用 Redis def verify_signature(data, app_secret): # 1. 检查时间戳 if abs(time.time() - data['timestamp']) > 300: return False # 2. 检查 nonce if data['nonce'] in processed_nonces: return False # 3. 计算签名 sign_str = ( f"amount={data['amount']}&" f"nonce={data['nonce']}&" f"order_id={data['order_id']}&" f"status={data['status']}&" f"timestamp={data['timestamp']}" ) expected = hmac.new( app_secret.encode(), sign_str.encode(), hashlib.sha256 ).hexdigest() return hmac.compare_digest(data['signature'], expected) @app.route('/callback', methods=['POST']) def callback(): data = request.json if not verify_signature(data, APP_SECRET): return jsonify({"success": False}), 400 # 标记 nonce 已处理 processed_nonces.add(data['nonce']) # TODO: 更新订单状态 return jsonify({"success": True})Python
Node.js
const crypto = require('crypto'); const express = require('express'); const app = express(); app.use(express.json()); const APP_SECRET = 'your_app_secret'; const processedNonces = new Set(); function verifySignature(data, appSecret) { // 1. 检查时间戳 const now = Math.floor(Date.now() / 1000); if (Math.abs(now - data.timestamp) > 300) return false; // 2. 检查 nonce if (processedNonces.has(data.nonce)) return false; // 3. 计算签名 const signStr = `amount=${data.amount}&nonce=${data.nonce}&order_id=${data.order_id}&status=${data.status}×tamp=${data.timestamp}`; const expected = crypto .createHmac('sha256', appSecret) .update(signStr) .digest('hex'); return crypto.timingSafeEqual( Buffer.from(data.signature), Buffer.from(expected) ); } app.post('/callback', (req, res) => { if (!verifySignature(req.body, APP_SECRET)) { return res.status(400).json({ success: false }); } processedNonces.add(req.body.nonce); // TODO: 更新订单状态 res.json({ success: true }); });Node.js
回调验证 - PHP
<?php define('APP_SECRET', 'your_app_secret'); $processedNonces = []; // 生产环境用 Redis function verifySignature($data, $appSecret) { // 1. 检查时间戳 if (abs(time() - $data['timestamp']) > 300) { return false; } // 2. 检查 nonce global $processedNonces; if (in_array($data['nonce'], $processedNonces)) { return false; } // 3. 计算签名 $signStr = sprintf( "amount=%d&nonce=%s&order_id=%s&status=%s×tamp=%d", $data['amount'], $data['nonce'], $data['order_id'], $data['status'], $data['timestamp'] ); $expected = hash_hmac('sha256', $signStr, $appSecret); return hash_equals($data['signature'], $expected); } // 接收回调 $data = json_decode(file_get_contents('php://input'), true); if (!verifySignature($data, APP_SECRET)) { http_response_code(400); echo json_encode(['success' => false]); exit; } // 标记 nonce 已处理 $processedNonces[] = $data['nonce']; // TODO: 更新订单状态 echo json_encode(['success' => true]); ?>PHP
安全要点
必须验证
- 签名验证 - 防止伪造通知
- 时间戳检查 - 5分钟有效期,防重放
- Nonce 去重 - 同一 nonce 只处理一次
- 金额核对 - 回调金额与订单金额一致
- 幂等处理 - 已处理订单不重复处理
响应格式
您的回调接口必须返回 JSON:
// 成功
{"success": true}
// 失败
{"success": false, "message": "错误原因"}
重试机制
如果您的接口未返回成功,系统会自动重试:
| 重试次数 | 间隔时间 |
|---|---|
| 第 1 次 | 1 分钟后 |
| 第 2 次 | 5 分钟后 |
| 第 3 次 | 15 分钟后 |
申请 API Key
接入量云AI支付,您需要先申请 API Key,然后使用 API Key 自助创建和管理应用。
申请流程
-
发送申请邮件
发送邮件到pay@lyg.ai -
等待审核
我们会在 1-2 个工作日内审核并回复 -
获取 API Key
审核通过后,您将收到专属的 API Key -
自助创建应用
使用 API Key 调用管理接口创建应用
邮件内容
申请时请提供以下信息:
- 项目/公司名称
- 项目描述(简要说明用途)
- 联系人姓名及电话
- IP 白名单(可选,限制 API 调用来源)
安全提醒
API Key 只会发送一次,请妥善保管!如不慎丢失,需要重新申请。
自助管理应用
获取 API Key 后,您可以通过管理接口自助创建和管理应用,无需再联系平台方。
认证方式
所有管理接口都需要在请求头中携带 API Key:
Authorization: Bearer lypay_live_xxxxxx
创建应用
POST https://pay.lt-ai.com/api/v1/admin/applications
请求参数
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
name |
string | 是 | 应用名称(1-50字符) |
callback_url |
string | 是 | 支付结果回调URL(建议HTTPS) |
请求示例
curl -X POST https://pay.lt-ai.com/api/v1/admin/applications \ -H "Authorization: Bearer lypay_live_xxxxxx" \ -H "Content-Type: application/json" \ -d '{"name": "我的应用", "callback_url": "https://example.com/callback"}'cURL
响应示例
{
"success": true,
"message": "应用创建成功",
"data": {
"app_id": "APP1768027932487...",
"app_secret": "NrbgY-nrZgIgS0vH...",
"name": "我的应用",
"callback_url": "https://example.com/callback",
"warning": "app_secret 只显示一次,请立即安全保存!"
}
}
重要提醒
app_secret 只在创建时返回一次,之后无法查看!请立即安全保存。如果丢失,需要重新生成密钥。
查询应用列表
GET https://pay.lt-ai.com/api/v1/admin/applications
响应示例
{
"success": true,
"message": "查询成功",
"data": [
{
"app_id": "APP1768027932487...",
"name": "我的应用",
"callback_url": "https://example.com/callback",
"is_active": true,
"created_at": "2026-01-10T06:52:12"
}
]
}
其他管理接口
| 方法 | 端点 | 说明 |
|---|---|---|
GET |
/api/v1/admin/applications/{app_id} | 查询单个应用详情 |
PUT |
/api/v1/admin/applications/{app_id}/callback | 更新回调地址 |
POST |
/api/v1/admin/applications/{app_id}/regenerate-secret | 重新生成密钥(旧密钥立即失效) |
DELETE |
/api/v1/admin/applications/{app_id} | 禁用应用 |
Python 示例
import requests API_KEY = "lypay_live_xxxxxx" BASE_URL = "https://pay.lt-ai.com/api/v1/admin" headers = { "Authorization": f"Bearer {API_KEY}", "Content-Type": "application/json" } # 创建应用 response = requests.post( f"{BASE_URL}/applications", headers=headers, json={ "name": "我的应用", "callback_url": "https://example.com/callback" } ) result = response.json() if result["success"]: app_id = result["data"]["app_id"] app_secret = result["data"]["app_secret"] print(f"App ID: {app_id}") print(f"App Secret: {app_secret}") # 立即保存! # 查询应用列表 response = requests.get(f"{BASE_URL}/applications", headers=headers) apps = response.json()["data"] for app in apps: print(f"{app['app_id']} - {app['name']}")Python
联系我们
如有任何问题,欢迎通过以下方式联系:
- 邮箱:
pay@lyg.ai
快速接入
发送邮件申请 API Key 后,您可以自助完成所有应用的创建和管理,无需等待人工审核。