跳到内容
开发者

几分钟内集成

一个无依赖的 PHP SDK:创建发票,重定向到托管结账页面,并验证签名的 webhook。REST 可用于任何语言。

API概览
  • 基础URLapi.payora.money
  • 身份验证HMAC-SHA256
  • 格式JSON · HTTPS
  • SDKPHP · Node.js · Python
  • 规范OpenAPI 3.0
快速入门

从发票到webhook

  1. 01

    创建发票

    一个API调用,带有订单ID和法币或加密货币金额,返回一个托管支付URL。

  2. 02

    客户支付

    他们选择一种币,扫描二维码或打开钱包,结账在最终确认时实时确认。

  3. 03

    您获得一个签名的Webhook

    验证HMAC签名,记入订单一次,然后观察付款到账您的余额。

PHP SDK

一个文件,无依赖。createInvoice()、getInvoice() 和 verifyWebhook() — 将其放入任何项目中。

HMAC 认证

请求和 webhook 使用 HMAC-SHA256 签名,带有时间戳偏差和幂等性密钥。

REST API

通过 HTTPS 传输的纯 JSON — 可从任何技术栈集成,而不仅仅是 PHP。

checkout
<?php
require 'Payora.php';
$payora = new Payora('https://api.payora.money', getenv('PAYORA_KEY'), getenv('PAYORA_SECRET'));

// 1 — create an invoice (fiat-priced; the payer picks a coin)
$inv = $payora->createInvoice([
  'order_id'   => 'ORDER-42',
  'mode'       => 'fiat',
  'amount'     => '9.99',
  'return_url' => 'https://shop.example/thanks',
  'lang'       => 'en',
], 'ORDER-42'); // Idempotency-Key: a retry never creates a second invoice
header('Location: ' . $inv['pay_url']);

// 2 — webhook endpoint: ALWAYS verify the signature first
$event = $payora->verifyWebhook(file_get_contents('php://input'), getallheaders());
if ($event === null) { http_response_code(400); exit; }
if ($event['status'] === 'paid') {
  creditOrderOnce($event['id'], $event['order_id'], $event['amount'], $event['currency']);
}
http_response_code(200); // 2xx stops retries

通过创建一个账户获取您的API密钥和秘密。完整的SDK在您的仪表板中。

身份验证

身份验证

除了 /v1/health 之外的每个调用都携带三个签名头。签名证明请求来自您的 api_secret 持有者,并且在传输过程中没有被更改。

头部值描述
X-Payora-Keypk_…您的公共api_key。标识商店。
X-Payora-Timestampunix seconds您签署请求的时刻,以Unix秒为单位。
X-Payora-Signaturehex · 64时间戳 + "." + 原始主体的小写十六进制HMAC-SHA256,使用您的api_secret进行加密。
X-Payora-Test1将发票标记为您集成的测试:它是真实的,可以接收币,但不计入需求和转换报告。
Idempotency-Keystring在POST /v1/invoice和POST /v1/payout上是可选的。使用相同密钥的重试返回第一个结果,而不是创建重复项;使用不同主体的相同密钥返回409。
Content-Typeapplication/json在携带主体的请求中是必需的。
X-Payora-Signature=hex( HMAC-SHA256( api_secret, timestamp + "." + raw_body ) )

签署您发送的确切字节。签名后重新编码JSON——即使重新排序键或添加空格——也会破坏签名。

对于GET请求,主体为空,因此签名字符串是时间戳后跟一个点。

API拒绝与其时钟相差超过120秒的时间戳。保持您的服务器与NTP同步。

将api_secret保留在您的服务器上。它对请求和Webhook进行签名:持有它的人可以以您的名义创建发票并伪造回调。

sign-request
<?php
$body = json_encode(['order_id' => 'ORDER-42', 'mode' => 'fiat', 'amount' => '9.99'], JSON_UNESCAPED_SLASHES);
$ts   = (string) time();
$sig  = hash_hmac('sha256', $ts . '.' . $body, $apiSecret); // lowercase hex

$ch = curl_init('https://api.payora.money/v1/invoice');
curl_setopt_array($ch, [
  CURLOPT_POST => true, CURLOPT_POSTFIELDS => $body, CURLOPT_RETURNTRANSFER => true,
  CURLOPT_HTTPHEADER => [
    'X-Payora-Key: ' . $apiKey,
    'X-Payora-Timestamp: ' . $ts,
    'X-Payora-Signature: ' . $sig,
    'Idempotency-Key: ORDER-42',
    'Content-Type: application/json',
  ],
]);
$invoice = json_decode(curl_exec($ch), true);
POST /v1/invoice

发票参数

除 order_id 和 amount 外,所有均为可选。法定货币模式允许付款人选择您账户上启用的任何币种;加密货币模式还需要 currency。

参数类型描述
order_idstring · required您的唯一订单参考(≤190 个字符)。重复提交将被拒绝,状态码为 409——防止重复提交。
amountstring · required法定金额(mode=fiat)或确切的加密金额(mode=crypto)。
modefiat | crypto默认法币:结账时每个币的汇率被锁定。加密模式提前固定币种+金额。
fiat_currencystring法定模式的ISO法定代码(默认USD)。
currencystring加密模式的币(例如:TON,TRX,USDT_TRON)。
return_urlhttps URL结账的 “返回商店” 按钮将客户发送回——您的网站。仅限绝对 http(s)。
langen·ru·uk·es·de结账语言,因此来自您俄罗斯商店的客户看到的是俄语结账——而不是英语。也可以在支付 URL 上设置为 ?lang=ru。
ttlseconds发票可支付的时间(120–86400 秒,默认 1800)。
customer_emailemail可选——收据 + 发送给付款人。
notesstring存储在发票上的自由格式备注。

return_url 和 lang 也可以作为查询参数附加到 API 提供的 pay_url — <pay_url>&lang=ru&return_url=https://shop.example/thanks。始终将买家发送到 API 返回的 pay_url:它携带一个每发票唯一的访问令牌,因此无法通过猜测发票号码访问结账页面。请勿从发票 ID 重建链接。

请求构建器

构建一个签名的发票请求

填写字段并复制一个准备好的 cURL 命令。它在您的 shell 中使用 $PAYORA_KEY 和 $PAYORA_SECRET 自行签名——此页面从未看到您的密钥并且不发送任何内容。

mode
POST /v1/invoice
BODY='{"order_id":"ORDER-42","mode":"fiat","amount":"9.99","fiat_currency":"USD","return_url":"https://shop.example/thanks","lang":"zh","ttl":1800}'
TS=$(date +%s)
SIG=$(printf '%s.%s' "$TS" "$BODY" | openssl dgst -sha256 -hmac "$PAYORA_SECRET" | cut -d' ' -f2)

curl -X POST https://api.payora.money/v1/invoice \
  -H "X-Payora-Key: $PAYORA_KEY" \
  -H "X-Payora-Timestamp: $TS" \
  -H "X-Payora-Signature: $SIG" \
  -H 'Idempotency-Key: ORDER-42' \
  -H 'Content-Type: application/json' \
  -d "$BODY"

此页面不发送任何内容。

webhooks

Webhooks

当发票或支付状态发生变化时,Payora 会向您的回调 URL 发送一个签名的 JSON 事件。首先验证签名,确认订单一次,返回 2xx。

事件status触发时
invoice.paidpaid支付在链上确认。携带金额、币种和 tx_hash。
invoice.underpaidunderpaid发票在收到的金额少于预期后过期。
invoice.expiredexpired发票在未收到任何内容的情况下过期。
invoice.cancelledcancelled发票已被取消。已到达的资金(如果有)在事件中描述。
invoice.cancel_settled—在已取消的发票上到达的资金已被处理:已记入或退回。
invoice.late_payment—在发票被取消后到达的款项。每个此类存款发送一次;结果说明它是被记入还是正在退回。
payout.sentsent一个支付批次已被签名并广播。携带每个项目及其 tx_hash。

每次交付的头部

头部值描述
X-Payora-Iduuid唯一事件 ID,与正文中的 ID 相同。存储它以忽略重复。
X-Payora-Eventinvoice.paid事件名称。
X-Payora-Timestampunix seconds当此尝试被签名时。
X-Payora-Signaturehex · 64与请求相同的方案:使用时间戳 + "." + 原始主体与您的 api_secret 进行 HMAC-SHA256。

invoice.paid 负载

字段类型描述
iduuid用于去重的事件 ID。
eventstring事件名称。
invoice_idintPayora 发票号码。
order_idstring您的订单参考,在发票创建时发送。
statusstringpaid 用于 invoice.paid。
currencystring付款人使用的币种,例如 USDT_TRON。
amountdecimal string收到的金额。
amount_unitsinteger string以币种的最小单位表示的相同金额 — 用于精确比较。
expecteddecimal string发票要求的金额。
fiat_amountdecimal string | null您创建的发票的法定货币价格;加密模式发票为 null。
fiat_currencystring | null法定货币金额的 ISO 代码;加密模式发票为 null。
tx_hashstring链上交易哈希。
paid_atunix seconds事件创建时间。
testbooltrue 用于沙盒发票。
invoice.paid
{
    "id": "6f1c2a4e-8b0d-4c1e-9a57-2f3d9e1b7c40",
    "event": "invoice.paid",
    "invoice_id": 1042,
    "order_id": "ORDER-42",
    "status": "paid",
    "currency": "USDT_TRON",
    "amount": "9.99",
    "amount_units": "9990000",
    "expected": "9.99",
    "fiat_amount": "9.99",
    "fiat_currency": "USD",
    "tx_hash": "3f9a…c21e",
    "paid_at": 1758038400,
    "test": false
}

当收到的金额与发票不同,amount_received 和 amount_expected 会被加起来。

交付和重试

任何非 2xx 的响应,或在 15 秒内没有响应,将以指数退避的方式重试,重试之间的时间限制为一小时 — 最多 12 次尝试。每次尝试都将使用新的时间戳重新签名;主体和事件 ID 保持不变,因此按 ID 去重。

在最后一次尝试后,事件被标记为失败,商店所有者会收到一封电子邮件。重定向永远不会被跟随,回调 URL 必须可以从互联网访问 — 不允许使用 localhost 或私有地址。

在您记账之前

  • 在任何 JSON 解析之前读取原始主体。
  • 重新计算签名并在恒定时间内比较:hash_equals, crypto.timingSafeEqual, hmac.compare_digest。
  • 拒绝超出您窗口的时间戳 — SDK 接受 ±300 秒。
  • 检查状态和金额与您的订单是否匹配,然后每个事件 ID 只记一次款。
  • 快速响应 2xx,并在响应后进行慢工作。
webhook
<?php
require 'Payora.php';
$payora = new Payora('https://api.payora.money', getenv('PAYORA_KEY'), getenv('PAYORA_SECRET'));

$raw   = file_get_contents('php://input');           // raw, before any parsing
$event = $payora->verifyWebhook($raw, getallheaders()); // HMAC + ±300 s window, constant-time
if ($event === null) { http_response_code(400); exit; } // bad / forged / stale

if ($event['event'] === 'invoice.paid' && !alreadyProcessed($event['id'])) {
  creditOrder($event['order_id'], $event['amount'], $event['currency'], $event['tx_hash']);
  rememberProcessed($event['id']);
}
http_response_code(200); // 2xx stops retries
Playground

Webhook签名演示

输入一个密钥、时间戳和原始主体,以查看 Payora 将发送的确切签名——或检查您收到的签名。

在您的浏览器中使用 WebCrypto 运行。您输入的内容不会离开此页面。在共享计算机上使用测试密钥,而不是实时密钥。

X-Payora-Timestamp
签名字符串
1758038400.{…}
Payora 发送的头部
headers
X-Payora-Timestamp: 1758038400
X-Payora-Signature: …

粘贴一个签名进行比较

大额支付

大规模支付API

通过一次签名的幂等请求将加密货币发送到多达 500 个钱包——用于 payroll、联盟支付或提款。批次总额加上每项费用会立即保留在您的 internal balance 中;operator signs and broadcasts,然后触发一个签名的 payout.sent webhook。与其他所有内容相同的 HMAC 认证。

payout
# create a payout batch — funds held instantly, sent by the operator
curl -X POST https://api.payora.money/v1/payout \
  -H 'X-Payora-Key: pk_…' -H 'X-Payora-Timestamp: 1700000000' \
  -H 'X-Payora-Signature: <hmac-sha256>' -H 'Idempotency-Key: payroll-2026-01' \
  -d '{"currency":"USDT_TRON","items":[
        {"address":"TR7…","amount":"250.00"},
        {"address":"TX9…","amount":"99.50","tag":"batch-A"}]}'

# → 201 Created
{ "batch_id": 812, "status": "pending", "currency": "USDT_TRON",
  "item_count": 2, "total": "349.50", "fee": "…", "items": [ … ] }

# poll status, or receive a signed payout.sent webhook when it is sent
curl https://api.payora.money/v1/payout/812 -H 'X-Payora-Key: …' …

验证是严格的:任何错误地址或过于精确的金额都会拒绝整个批次(HTTP 422),并附带有问题的项目索引——工资单运行绝不会默默丢弃收件人。使用POST /v1/payout/{id}/cancel取消仍在待处理的批次以释放保留。请参阅架构写作。

参考

端点参考

每个端点通过HTTPS以普通JSON格式在api.payora.money上进行通信。除了/v1/health,其他都使用相同的HMAC-SHA256请求认证。机器可读的规范位于openapi.json。

端点访问描述
GET/v1/healthno auth服务状态以及启用货币的列表。
POST/v1/invoiceauth创建发票(法币或加密模式)。支持Idempotency-Key。返回201,包含invoice_id,status,pay_url和expires;加密模式添加地址、金额和深度链接。
GET/v1/invoice/{id}auth发票状态(仅限自己的发票):status,remaining,以及charge——货币、地址、预期/收到的金额和tx_hash。
POST/v1/payoutauth · Pro+创建一个大额支付批次(严格验证,资金立即被占用)。支持Idempotency-Key。返回201,批次视图:batch_id,status,总计,费用,项目。
GET/v1/payoutauth列出您最近的支付批次(?limit=,默认50)。
GET/v1/payout/{id}auth支付批次状态和项目(仅限自己的批次)。
POST/v1/payout/{id}/cancelauth取消仍在待处理的批次并释放被占用的余额。如果批次不再可取消,则返回409。
下载

SDK和下载

无依赖的单个文件。每个SDK以相同的方式签署请求并验证Webhook。

phpPHPPayora.php

PHP 7.4+ 与 cURL,单个文件。createInvoice、getInvoice 和 verifyWebhook。

2 KB下载
jsNode.jspayora.js

仅使用内置 https 和 crypto 的 Node.js。发票、余额、支付和 verifyWebhook。

6 KB下载
pyPythonpayora.py

仅使用 Python 标准库。发票、余额、支付和 verify_webhook。

5 KB下载
{ }Postmanpayora.postman_collection.json

一个为您签署每个调用的 Postman 集合。

3 KB下载
{…}OpenAPI 3.0openapi.json

每个端点的机器可读规范,供代码生成器和API客户端使用。

api.payora.money打开
正在运行WooCommerce、WHMCS、Magento或其他CMS吗?

一个现成的模块为您完成上述所有操作:发票、重定向和经过验证的Webhook。

浏览插件
常见问题

常见问题

直接的答案,包括不太舒服的内容:保管、费用以及当出现问题时会发生什么。

帮助中心

我如何集成 Payora?

安装单文件 PHP SDK(无依赖)或直接调用 REST API。使用 createInvoice() 创建发票,将客户重定向到其 pay_url,并处理一个 webhook 事件:status=paid。一个合格的开发者在 30-60 分钟内可以上线。

是否有适用于非 PHP 堆栈的 REST API?

是的。一切都是通过 HTTPS 的普通 JSON,因此您可以使用任何语言进行集成。PHP SDK 是对相同端点的便利封装——创建发票、获取发票和验证 webhook 签名。

客户在支付后可以以正确的语言返回我的网站吗?

是的。在您创建发票时传递 return_url(或在支付链接上使用 ?return_url=),结账时在成功屏幕上显示“返回商店”按钮,客户在支付时也会看到。传递 lang(en、ru、uk、es、de),或在链接上使用 ?lang=,这样来自您俄罗斯商店的客户就会进入俄语结账页面,而不是英语页面。两者都是可选的;return_url 必须是绝对的 http(s) URL。

API 身份验证是如何处理的?

请求和 webhook 使用您的 api_secret 通过时间戳和原始主体进行 HMAC-SHA256 身份验证,具有 ±120 秒的偏差窗口和幂等性密钥。签名在恒定时间内进行比较,以防止时间攻击。

我如何获取 API 密钥?

创建一个免费账户。您的公共 api_key 和秘密 api_secret 会出现在仪表板中,以及可下载的 SDK 和完整的 webhook 参考。可以随时从设置中轮换密钥。

webhook 负载包含什么?

一个带有发票 ID、您的 order_id、状态(例如已支付)、金额和货币,以及一个用于幂等性的唯一事件 ID 的签名 JSON 事件。在记入订单之前始终验证签名,然后记录事件 ID 以避免在重试时重复处理。

是否有用于大规模加密货币支付的 API?

是的。POST /v1/payout可以在一个请求中将加密货币发送到多达500个钱包——每个项目一个{地址,金额,选填标签},支持您账户上启用的任何币种。它使用与发票API相同的HMAC-SHA256身份验证和幂等性密钥,因此重试请求不会创建重复的批次。批次总额加上每项费用会立即保留在您的余额上;运营商签名并广播,然后触发已签名的payout.sent webhook。验证非常严格——任何无效地址或过于精确的金额都会拒绝整个批次(422),因此工资运行不会静默丢失收件人。

我如何自动化加密工资或联盟支付?

在您的系统中构建收件人列表,然后每次运行时调用 POST /v1/payout,使用稳定的 Idempotency-Key(例如 payroll-2026-01)。轮询 GET /v1/payout/{id} 或等待 payout.sent webhook 确认交付并记录每个 tx hash。提交批次保留资金,但不会单独移动它们——操作员签名并广播,因此仅通过 API 调用不会有任何资金流出。

获取您的 API 密钥

一个无依赖的 PHP SDK:创建发票,重定向到托管结账页面,并验证签名的 webhook。REST 可用于任何语言。

此页面回答的问题