在您的网站上收款 — SCI
买家进入支付页面,用任意钱包付款,您的服务器会收到带有结果的签名通知。本页包含接入所需的全部内容。
目录
工作原理
- 买家在您的网站上点击“付款”,浏览器将签名表单发送到支付页面。
- 系统创建账单:买家选择币种,看到金额、地址、二维码和倒计时。
- 买家转账。我们等待网络确认,并核对金额、币种和时间。
- 您的服务器收到带有结果的通知,买家返回您的网站。
分步接入
- 在账户中:“项目” → “添加项目”,填写名称和网站地址。您将获得商店 ID、表单密钥(sk_…)和 Webhook 密钥(whsec_…)。密钥只显示一次,请保存在商店服务器上。
- “币种” — 开启您接受的币种和网络。
- “支付页面” — 账单有效期、金额容差、语言、返回地址和面向买家的客服邮箱。
- “通知” — Webhook 地址和“发送测试”。
- “接入” — 验证域名并将项目切换到“测试”模式。
- 用测试账单检查您这一侧,然后将项目切换到“运行中”模式。
付款表单
在商店服务器上生成表单:买家的浏览器以 POST 方式将字段提交到支付页面地址。表单密钥不会进入浏览器,表单中只有签名。
<form method="post" action="https://sci.coinvertus.net">
<input type="hidden" name="shop" value="P4K7Q2A9">
<input type="hidden" name="order_id" value="10482">
<input type="hidden" name="amount" value="49.90">
<input type="hidden" name="currency" value="USD">
<input type="hidden" name="sign" value="<?= $sign ?>">
<input type="hidden" name="success_url" value="https://shop.example/orders/10482">
<button type="submit">Pay with crypto</button>
</form>表单字段
| 字段 | 说明 |
|---|---|
shop必填 | 账户中的商店 ID,8 个字符。 |
order_id必填 | 商店订单号:1–64 个字符,不含空格。以相同金额和货币重复提交会打开同一账单,否则返回错误 S005。 |
amount必填 | 金额使用小数点,最多两位小数:49.90、49.9 或 50。须大于零。 |
currency必填 | 金额货币:USD、EUR、RUB、CNY 或 INR。买家选择币种时按当时汇率计算币种金额。 |
sign必填 | 表单签名,见下文。 |
asset | 代买家选择的币种,格式为“符号:网络”,与通知中的 asset 和 network 相同,例如 DOGE:dogecoin-mainnet 或 USDT:bsc。若该币种已在项目中启用,买家将直接看到付款信息。 |
description | 订单描述,最多 255 个字符,显示在支付页面上。 |
email | 买家邮箱,最多 254 个字符。 |
lang | 页面语言:ru、en 或 cn。未指定时使用项目设置的语言,否则使用浏览器语言。买家可以自行切换语言。 |
success_url | 付款后将买家送回的 http(s) 地址。未指定时使用项目设置,否则使用商店网站。 |
fail_url | 未付款或付款不符时将买家送回的地址。未指定时使用项目设置,否则使用商店网站。 |
metadata | JSON 对象或数组,最多 4 KB,原样返回在通知中。 |
签名
sign 是以项目表单密钥对字符串 shop:order_id:amount:currency 计算的十六进制 HMAC-SHA256。取值须与表单中提交的完全一致:49.90 与 49.9 的签名不同。
$shop = 'P4K7Q2A9';
$formKey = getenv('CVC_SCI_FORM_KEY');
$orderId = '10482';
$amount = '49.90';
$currency = 'USD';
$sign = hash_hmac('sha256', $shop . ':' . $orderId . ':' . $amount . ':' . $currency, $formKey);表单错误
如果表单未通过校验,买家会看到带有错误代码和返回您网站链接的页面。
| 错误代码 | 含义 |
|---|---|
S002 | 某字段未通过校验,字段名见错误文本。 |
S003 | 签名不匹配。 |
S004 | 未找到商店或商店不收款:项目处于草稿状态、处于“运行中”但域名未验证,或套餐不含收款功能。 |
S005 | 该 order_id 的账单已以不同金额或货币创建。 |
S006 | 创建账单时发生内部错误,请稍后重试。 |
S007 | 新账单过多:每个项目每小时最多 300 张,每个买家地址每小时最多 30 张。 |
账单与状态
账单有效期为 15 到 120 分钟,在“支付页面”标签中设置。买家选择币种时锁定币种金额;最多可更换三次币种。所需确认数由网络决定。
| 状态 | 说明 |
|---|---|
new | 账单已创建,尚未选择币种。 |
waiting | 已选择币种,等待转账。 |
confirming | 转账已在网络中,等待确认。 |
partial | 已收到部分金额,等待补付,自第一笔起至少 15 分钟。 |
paid | 已付款:金额在容差内、按时、币种正确。 |
received | 款项已到,但有不符之处,原因见 warnings。 |
expired | 已过期且无转账。之后到账且金额恰为账单金额的转账仍会计入:账单变为 received 并带有 incorrect time。 |
cancelled | 商店在付款前通过 API 取消了账单。 |
返回商店
付款后“继续”按钮指向 success_url,其他情况指向 fail_url。返回本身不能证明付款:买家可以直接打开该地址。请仅根据通知更改订单状态。
商店服务器 API
当由买家的浏览器打开账单时,使用表单即可。如果订单由您的服务器创建,请通过 API 创建账单,并将买家引导至响应中的 url。通过 API 还可以在通知未送达时查询账单、取消未付款的账单,以及获取带金额的币种列表。
| 方法和地址 | 说明 |
|---|---|
POST https://sci.coinvertus.net/api/v1/invoices | 创建账单。 |
GET https://sci.coinvertus.net/api/v1/invoices/{number} | 按账单编号查询,例如 CVC-7F3K2A。 |
GET https://sci.coinvertus.net/api/v1/invoices?order_id=… | 按商店订单号查询账单。 |
POST https://sci.coinvertus.net/api/v1/invoices/{number}/cancel | 在尚无转账时取消账单。 |
GET https://sci.coinvertus.net/api/v1/assets?currency=USD&amount=49.90 | 付款页面当前提供的币种,含汇率和金额。 |
请求签名
每个请求都用项目表单密钥签名——与表单使用的密钥相同;密钥本身不会被发送。v1 是对字符串“t.方法.路径.正文”计算的十六进制 HMAC-SHA256:路径从 /v1/ 开始,包含查询字符串,须与实际发送的完全一致;正文为请求中发送的原始字节,GET 请求为空字符串。t 与我们的时钟相差超过 5 分钟的请求将被拒绝。
| 请求头 | 说明 |
|---|---|
X-CVC-Shop | 商店 ID,与表单字段 shop 的值相同。 |
X-CVC-Signature | 签名:t=<Unix 时间>,v1=<签名>。 |
<?php
function cvcSignature(string $method, string $path, string $body): string
{
$t = time();
$v1 = hash_hmac('sha256', $t . '.' . $method . '.' . $path . '.' . $body, getenv('CVC_SCI_FORM_KEY'));
return 't=' . $t . ',v1=' . $v1;
}
$body = json_encode([
'order_id' => '10482',
'amount' => '49.90',
'currency' => 'USD',
'success_url' => 'https://shop.example/orders/10482',
]);
$response = $http->request('POST', 'https://sci.coinvertus.net/api/v1/invoices', $body, [
'Content-Type: application/json',
'X-CVC-Shop: P4K7Q2A9',
'X-CVC-Signature: ' . cvcSignature('POST', '/v1/invoices', $body),
]);
if ($response->status === 200 || $response->status === 201) {
header('Location: ' . json_decode($response->body, true)['url'], true, 303);
}
$path = '/v1/invoices?order_id=' . rawurlencode('10482');
$response = $http->request('GET', 'https://sci.coinvertus.net/api' . $path, '', [
'X-CVC-Shop: P4K7Q2A9',
'X-CVC-Signature: ' . cvcSignature('GET', $path, ''),
]);$http 是您的 HTTP 客户端:它带上这些请求头发送请求,并返回响应状态码和正文。
通过 API 创建账单
正文为 JSON,字段与表单相同,但不含 shop 和 sign:order_id、amount 和 currency 为必填,其余可选。amount 和 order_id 可以是数字,metadata 可以是对象。新账单返回状态码 201;以相同金额和货币重复提交同一 order_id 会以 200 返回同一账单。每个项目每小时最多创建 300 个新账单。
{
"test": false,
"validation": null,
"warnings": [],
"invoice": {
"number": "CVC-7F3K2A",
"order_id": "10482",
"status": "new",
"amount": "49.90",
"currency": "USD",
"asset": null,
"network": null,
"rate": null,
"amount_crypto": null,
"received_crypto": null,
"remaining_crypto": null,
"overpaid_crypto": null,
"expires_at": "2026-09-17T12:22:00Z",
"metadata": {
"cart": "a17"
}
},
"settlement": {
"mode": "direct",
"fee_percent": "0.00"
},
"url": "https://sci.coinvertus.net/pY3kQ9vT2mXc8LwR1nZb4A"
}响应中的账单字段与通知相同:invoice、settlement 和 test。validation 和 warnings 是账单当前的结果:到账前分别为 null 和空列表。url 是付款页面,请将买家引导至此。查询账单和取消的响应格式相同。
取消账单
只能取消尚无款项的账单:状态为 new 或 waiting,且没有任何转账(包括未确认的)。账单状态变为 cancelled,您的服务器会收到 invoice.cancelled;再次取消将返回同一账单。如果买家仍然转入与账单金额完全一致的款项,该转账会被计入:将收到 validation 为 false 的 payment.received;其他金额不会产生通知。
币种列表
付款页面此刻会提供的币种:已在项目中启用且汇率为最新。currency 为汇率货币,默认 USD;传入 amount 时,响应中还包含按账单方式计算的币种金额。asset 和 network 可直接用于 asset 字段:DOGE:dogecoin-mainnet。
API 错误
错误以 HTTP 状态码和正文 {"error": {"code": "S002", "message": "…"}} 返回;S002 还带有 fields——无效字段的名称。message 供人阅读,语言取自 Accept-Language;程序中请以 code 为准。
| HTTP 状态码 | 错误代码 | 含义 |
|---|---|---|
400 | S002 | 字段或请求正文无效;字段名见 error.fields。 |
401 | S003 | X-CVC-Shop 未知,或签名无效、已过期。 |
403 | S004 | 项目不接受付款:处于草稿状态、处于“运行中”但域名未验证,或套餐不含收款功能。仅在创建账单时出现。 |
404 | S008 | 项目中没有该编号或 order_id 的账单。 |
409 | S005 | 该 order_id 的账单已以不同金额或货币创建。 |
409 | S009 | 无法取消:账单已有转账,或状态既不是 new 也不是 waiting。 |
429 | S007 | 项目每小时新建账单超过 300 个。 |
500 | S006 | 创建账单时发生内部错误,请稍后重试。 |
通知(Webhook)
在“通知”标签中设置:https 地址,必要时填写服务器 IP 和 Host。修改地址需要来自身份验证器应用或邮件的验证码。“发送测试”会发送 ping;未成功送达 ping 的项目无法切换到“运行中”。
通知为带 JSON 正文的 POST 请求。10 秒内任何 2xx 响应即为成功。否则分别在 1 分钟、5 分钟、30 分钟、2 小时、6 小时和 24 小时后重试。不跟随重定向,响应最多读取 64 KB。
| 请求头 | 说明 |
|---|---|
X-CVC-Event | 事件名称,与正文中的 event 相同。 |
X-CVC-Delivery | event_id 和尝试次数。 |
X-CVC-Signature | 签名:t=<Unix 时间>,v1=<签名>。 |
v1 是以项目 Webhook 密钥对字符串“t.正文”计算的十六进制 HMAC-SHA256。请使用收到的原始正文字节(解析 JSON 之前),若 t 与您的时钟相差超过 5 分钟则拒绝该通知。
同一通知可能到达两次,每个 event_id 只处理一次。不保证送达顺序:不要因较早的通知回退已付款订单。
通知事件
| 事件 | 发送时机 |
|---|---|
payment.received | 转入账单地址的转账已获得足够确认。包含 validation 和 warnings。交易的每个输出各发一条通知。 |
invoice.expired | 账单已过期:无转账(status expired)或未补足(status received)。 |
invoice.cancelled | 账单已通过 API 取消。 |
payment.reversed | 已计入的转账因区块重组从链上消失,由我们负责处理。 |
payment.restored | 包含该转账的区块已回到链上,付款不会重复计入。 |
ping | 来自账户的测试通知。 |
除 ping 外,所有事件都可以在“通知”标签中通过复选框关闭。
通知正文
金额为带小数点的字符串,不含多余的零。选择币种前,币种相关字段为 null。时间均为 UTC。
{
"event": "payment.received",
"event_id": "evt_0123456789abcdef01234567",
"created_at": "2026-09-17T12:10:00Z",
"test": false,
"validation": true,
"warnings": [],
"invoice": {
"number": "CVC-7F3K2A",
"order_id": "10482",
"status": "paid",
"amount": "49.90",
"currency": "USD",
"asset": "DOGE",
"network": "dogecoin-mainnet",
"rate": "0.275",
"amount_crypto": "181.45",
"received_crypto": "181.45",
"remaining_crypto": "0",
"overpaid_crypto": "0",
"expires_at": "2026-09-17T12:22:00Z",
"metadata": {
"cart": "a17"
}
},
"payment": {
"txid": "c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0",
"output": 1,
"asset": "DOGE",
"network": "dogecoin-mainnet",
"amount_crypto": "181.45",
"confirmations": 6,
"seen_at": "2026-09-17T11:59:02Z"
},
"settlement": {
"mode": "direct",
"fee_percent": "0.00"
}
}| 字段 | 说明 |
|---|---|
test | true 表示账单在“测试”模式下创建。 |
validation, warnings | 付款校验结果,仅出现在 payment.received 中。 |
invoice.number | 支付页面上显示的账单号。 |
invoice.status | 事件发生后的账单状态。 |
invoice.amount_crypto, received_crypto, remaining_crypto, overpaid_crypto | 账单的币种金额、已收、待补付、多付。 |
invoice.rate | 选择币种时该币种对账单货币的汇率。 |
invoice.metadata | 表单中的 metadata,原样返回。 |
payment.output | 输出序号:UTXO 网络为指向账单地址的交易输出(一笔交易可能有多个);EVM 网络中 0 为网络币的直接转账,1 及以上为同一交易中由合约发出的网络币转账,代币转账为 1000000 加上其在区块中的日志序号(logIndex)。EVM 的 txid 以 0x 开头。TRON 同理,但内部网络币转账从 1 开始编号。Solana 为交易内的转账序号,代币为 1000000 加上该序号;txid 为交易签名。XRP 为 0,txid 为交易哈希;账单通过目标标签识别。TON 为 0,txid 为项目地址的交易哈希;账单通过转账备注识别。TON Jetton 代币为 1000000 加上交易内的事件序号,txid 为 Jetton 钱包的交易哈希。 对于 XRPL 代币,为 1000000,txid 为交易哈希;账单同样通过目标标签识别。 |
payment.seen_at | 转账出现在网络中的时间,按此时间判断是否超期。 |
settlement | 资金去向:direct 直接进入您的钱包,pool 经资金池并收取 fee_percent 手续费。 |
validation 与 warnings
仅在 validation 为 true 时发货。validation 为 false 时款项仍已计入商店,由您决定:发货、退还差额或联系买家。
| warnings 中的值 | 含义 |
|---|---|
incorrect amount | 金额超出容差:少付、多付或向已关闭账单补款。 |
incorrect network or token | 收到的币种或网络不符。 |
incorrect time | 转账在账单截止后才出现在网络中。 |
| 情形 | 状态 | validation | warnings |
|---|---|---|---|
| 金额在容差内、按时、币种正确 | paid | true | — |
| 少付,仍在期限内 | partial | false | incorrect amount |
| 按时补足 | paid | true | — |
| 少付,补付期限已过 | received | false | incorrect amount |
| 超出容差多付 | received | false | incorrect amount |
| 同一币种但网络不同,金额恰为应付 | received | false | incorrect network or token |
| 截止后转账,金额恰为应付 | received | false | incorrect time |
| 其他币种、零金额转账、向已付款账单的任何转账、截止后金额与应付不符 | 不变,无通知 | — | — |
同一账单的多笔转账会累计;金额容差在“支付页面”标签中设置。
账单并未等待的转账不算作付款:没有通知,状态也不变;通过资金池结算时,这类款项不会支付给商店。“地址投毒”垃圾转账就是这样到达账单地址的。如果买家转错币种或重复付款,请携带账单号和交易联系 CVC 支持。
测试模式与模拟
在“测试”模式下,账单带有 test: true 标记,支付页面接受与运行时相同的币种。测试账单页面底部有“模拟付款”:足额付款、部分付款或多付、使账单过期、回滚区块并恢复,全部无需转账。账单流程与真实付款相同,商店会收到带有 test: true 的相同通知。
域名验证
要切换到“运行中”,需证明网站归您所有:将包含“接入”标签中那一行的 cvc-sci.txt 文件放到网站根目录,然后点击“检查”。如果域名尚未指向您的服务器,请填写服务器 IP,检查请求会发往该 IP。
自有域名
在支持自有域名的套餐中,买家在您的地址(例如 pay.example.com)上付款,看不到 CoinVertus 的地址。支付页面前面是您的服务器(前置服务器):它持有您的证书,并将支付页面代理到 sci.coinvertus.net。服务器和证书由您负责。
- 将域名指向您的服务器,并为其签发证书。
- 按下面的示例配置 nginx:服务器自行提供 /cvc-sci.txt、您的样式和图标,将支付页面路径代理到 sci.coinvertus.net,其余请求返回 404。
- 在项目的“接入”标签中填写域名以及您的服务器访问 sci.coinvertus.net 时使用的 IP 地址。修改需要验证码。
- 在 /cvc-sci.txt 中提供与项目网站相同的那一行,然后点击“检查”。
- 验证通过后,新账单的链接(无论来自表单还是 API)都指向您的域名。支付表单可以提交到您域名的根路径。如果商店网站设置了 CSP form-action,请将您的支付域名加入其中:提交表单后买家会被重定向到该域名。
您的服务器的 nginx 示例:
server {
listen 443 ssl;
server_name pay.example.com;
ssl_certificate /etc/ssl/pay.example.com/fullchain.pem;
ssl_certificate_key /etc/ssl/pay.example.com/privkey.pem;
location = /cvc-sci.txt {
default_type text/plain;
return 200 "cvc-sci=P4K7Q2A9-0123456789abcdef0123456789abcdef\n";
}
location = /cvc-sci.css {
root /srv/pay;
}
location = /favicon.ico {
root /srv/pay;
}
location ~ "^/(?:$|[A-Za-z0-9_-]{22}$|sci/|api/v1/|language$|css/|js/|fonts/|webfonts/|images/|coin-icon/)" {
proxy_pass https://sci.coinvertus.net;
proxy_set_header Host sci.coinvertus.net;
proxy_ssl_server_name on;
proxy_ssl_name sci.coinvertus.net;
proxy_redirect https://sci.coinvertus.net/ /;
}
location / {
return 404;
}
}页面样式
在您的域名上,支付页面会在我们的样式之后加载 /cvc-sci.css。该文件由您的服务器提供;空文件则保持默认外观。CoinVertus 的标志、图标和名称不会在您的域名上显示。请以表中的类为准:其余标记可能会变化。
| 选择器 | 说明 |
|---|---|
.cvc-sci-own | 您域名上的整个页面:背景、字体,主色通过变量 --cvc-color-primary 设置。 |
.cvc-sci-bar | 带语言切换的顶部栏。 |
.cvc-sci-brand | 顶部栏左侧放置您标志的位置:一个空块,请为其设置尺寸和背景。 |
.cvc-sci-column | 居中栏:顶部栏和卡片的宽度。 |
.cvc-sci-card | 账单卡片。 |
.cvc-sci-shop-avatar | 账单页眉中商店名称的首字母。 |
.cvc-sci-coin-box .cvc-sci-asset-icon | 所选币种以及币种和网络图标。 |
.cvc-sci-copy-value .cvc-sci-address | 买家复制的金额、地址及其他付款信息。 |
.cvc-sci-qr | 付款二维码。 |
.btn-login | 主要按钮:“从钱包付款”、“继续”。 |
.cvc-sci-action | 次要按钮:收据、联系商店。 |
.cvc-sci-waiting .cvc-sci-found .cvc-sci-outcome-icon | 等待付款、已找到的付款以及结果图标。 |
.cvc-sci-progress | 确认数和补付进度条。 |
.cvc-sci-rows | 结果页面上的付款详情行。 |
/cvc-sci.css 示例:
.cvc-sci-own {
--cvc-color-primary: #1d4ed8;
background: #f4f1ea;
}
.cvc-sci-brand {
width: 140px;
height: 40px;
background: url(/logo.svg) no-repeat left center / contain;
}
.cvc-sci-card {
border-radius: 4px;
}页面安全策略只允许来自您域名文件的样式,图片和字体只能来自您的域名或 data:。外部 CDN 无法加载。
PHP 示例
签名与表单:
<?php
$shop = 'P4K7Q2A9';
$formKey = getenv('CVC_SCI_FORM_KEY');
$orderId = '10482';
$amount = '49.90';
$currency = 'USD';
$sign = hash_hmac('sha256', $shop . ':' . $orderId . ':' . $amount . ':' . $currency, $formKey);
?>
<form method="post" action="https://sci.coinvertus.net">
<input type="hidden" name="shop" value="P4K7Q2A9">
<input type="hidden" name="order_id" value="10482">
<input type="hidden" name="amount" value="49.90">
<input type="hidden" name="currency" value="USD">
<input type="hidden" name="sign" value="<?= $sign ?>">
<input type="hidden" name="success_url" value="https://shop.example/orders/10482">
<button type="submit">Pay with crypto</button>
</form>接收通知:
<?php
$secret = getenv('CVC_SCI_WEBHOOK_SECRET');
$body = file_get_contents('php://input');
$t = null;
$signatures = [];
foreach (explode(',', $_SERVER['HTTP_X_CVC_SIGNATURE'] ?? '') as $pair) {
[$name, $value] = array_pad(explode('=', trim($pair), 2), 2, '');
if ($name === 't') {
$t = $value;
} elseif ($name === 'v1') {
$signatures[] = strtolower($value);
}
}
$expected = hash_hmac('sha256', $t . '.' . $body, $secret);
$valid = $t !== null && ctype_digit($t) && abs(time() - (int) $t) <= 300
&& array_filter($signatures, fn (string $v1): bool => hash_equals($expected, $v1)) !== [];
if (!$valid) {
http_response_code(400);
exit;
}
$hook = json_decode($body, true);
if (($hook['test'] && $liveMode) || !$events->remember($hook['event_id'])) {
http_response_code(200);
exit;
}
$orderId = $hook['invoice']['order_id'];
switch ($hook['event']) {
case 'payment.received':
$hook['validation']
? $orders->markPaid($orderId)
: $orders->markForReview($orderId, $hook['warnings']);
break;
case 'invoice.expired':
$hook['invoice']['status'] === 'expired'
? $orders->cancel($orderId)
: $orders->markForReview($orderId, ['incorrect amount']);
break;
case 'payment.reversed':
$orders->markForReview($orderId, ['reversed']);
break;
}
http_response_code(200);$orders、$events 和 $liveMode 分别是您的订单存储、已处理 event_id 的记录以及“运行中”模式标志。仅在通知处理完成后才返回 200。