在您的网站上收款 — SCI

买家进入支付页面,用任意钱包付款,您的服务器会收到带有结果的签名通知。本页包含接入所需的全部内容。

工作原理

  1. 买家在您的网站上点击“付款”,浏览器将签名表单发送到支付页面。
  2. 系统创建账单:买家选择币种,看到金额、地址、二维码和倒计时。
  3. 买家转账。我们等待网络确认,并核对金额、币种和时间。
  4. 您的服务器收到带有结果的通知,买家返回您的网站。

分步接入

  1. 在账户中:“项目” → “添加项目”,填写名称和网站地址。您将获得商店 ID、表单密钥(sk_…)和 Webhook 密钥(whsec_…)。密钥只显示一次,请保存在商店服务器上。
  2. “币种” — 开启您接受的币种和网络。
  3. “支付页面” — 账单有效期、金额容差、语言、返回地址和面向买家的客服邮箱。
  4. “通知” — Webhook 地址和“发送测试”。
  5. “接入” — 验证域名并将项目切换到“测试”模式。
  6. 用测试账单检查您这一侧,然后将项目切换到“运行中”模式。
打开项目

付款表单

在商店服务器上生成表单:买家的浏览器以 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未付款或付款不符时将买家送回的地址。未指定时使用项目设置,否则使用商店网站。
metadataJSON 对象或数组,最多 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);
签名只覆盖商店、订单、金额和货币。其余字段买家可在浏览器中修改:不要信任 metadata 和返回地址,请按 order_id 查找订单,并只根据通知确认付款。

表单错误

如果表单未通过校验,买家会看到带有错误代码和返回您网站链接的页面。

错误代码含义
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 状态码错误代码含义
400S002字段或请求正文无效;字段名见 error.fields。
401S003X-CVC-Shop 未知,或签名无效、已过期。
403S004项目不接受付款:处于草稿状态、处于“运行中”但域名未验证,或套餐不含收款功能。仅在创建账单时出现。
404S008项目中没有该编号或 order_id 的账单。
409S005该 order_id 的账单已以不同金额或货币创建。
409S009无法取消:账单已有转账,或状态既不是 new 也不是 waiting。
429S007项目每小时新建账单超过 300 个。
500S006创建账单时发生内部错误,请稍后重试。

通知(Webhook)

在“通知”标签中设置:https 地址,必要时填写服务器 IP 和 Host。修改地址需要来自身份验证器应用或邮件的验证码。“发送测试”会发送 ping;未成功送达 ping 的项目无法切换到“运行中”。

通知为带 JSON 正文的 POST 请求。10 秒内任何 2xx 响应即为成功。否则分别在 1 分钟、5 分钟、30 分钟、2 小时、6 小时和 24 小时后重试。不跟随重定向,响应最多读取 64 KB。

通知来自不同地址,请勿按 IP 限制,务必校验签名。
请求头说明
X-CVC-Event事件名称,与正文中的 event 相同。
X-CVC-Deliveryevent_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"
    }
}
字段说明
testtrue 表示账单在“测试”模式下创建。
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转账在账单截止后才出现在网络中。
情形状态validationwarnings
金额在容差内、按时、币种正确paidtrue—
少付,仍在期限内partialfalseincorrect amount
按时补足paidtrue—
少付,补付期限已过receivedfalseincorrect amount
超出容差多付receivedfalseincorrect amount
同一币种但网络不同,金额恰为应付receivedfalseincorrect network or token
截止后转账,金额恰为应付receivedfalseincorrect time
其他币种、零金额转账、向已付款账单的任何转账、截止后金额与应付不符不变,无通知——

同一账单的多笔转账会累计;金额容差在“支付页面”标签中设置。

账单并未等待的转账不算作付款:没有通知,状态也不变;通过资金池结算时,这类款项不会支付给商店。“地址投毒”垃圾转账就是这样到达账单地址的。如果买家转错币种或重复付款,请携带账单号和交易联系 CVC 支持。

测试模式与模拟

在“测试”模式下,账单带有 test: true 标记,支付页面接受与运行时相同的币种。测试账单页面底部有“模拟付款”:足额付款、部分付款或多付、使账单过期、回滚区块并恢复,全部无需转账。账单流程与真实付款相同,商店会收到带有 test: true 的相同通知。

任何拥有测试账单链接的人都可以点击模拟。项目运行后,请拒绝带有 test: true 的通知。

域名验证

要切换到“运行中”,需证明网站归您所有:将包含“接入”标签中那一行的 cvc-sci.txt 文件放到网站根目录,然后点击“检查”。如果域名尚未指向您的服务器,请填写服务器 IP,检查请求会发往该 IP。

自有域名

在支持自有域名的套餐中,买家在您的地址(例如 pay.example.com)上付款,看不到 CoinVertus 的地址。支付页面前面是您的服务器(前置服务器):它持有您的证书,并将支付页面代理到 sci.coinvertus.net。服务器和证书由您负责。

  1. 将域名指向您的服务器,并为其签发证书。
  2. 按下面的示例配置 nginx:服务器自行提供 /cvc-sci.txt、您的样式和图标,将支付页面路径代理到 sci.coinvertus.net,其余请求返回 404。
  3. 在项目的“接入”标签中填写域名以及您的服务器访问 sci.coinvertus.net 时使用的 IP 地址。修改需要验证码。
  4. 在 /cvc-sci.txt 中提供与项目网站相同的那一行,然后点击“检查”。
  5. 验证通过后,新账单的链接(无论来自表单还是 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;
    }
}
您的所有买家都通过所填 IP 访问我们:防暴力破解机制不会封禁这些地址,单个 IP 的账单数量限制也不适用于它们。因此请在您的服务器上拦截多余的路径。如果套餐不再包含自有域名,在您更换套餐或移除域名之前,商店将不接受新账单。

页面样式

在您的域名上,支付页面会在我们的样式之后加载 /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。