tgpay cryptoAPI
crypto-payapiinvoicesrefunds

API 参考:账单和退款

阅读约 2 分钟最后更新: 2026年10月9日

账单相关的方法:createInvoice、getInvoices、deleteInvoice、refundInvoice。通用约定 (鉴权、外层结构、金额、spend_id)见商户 API 参考页面; 具体操作步骤见用账单收款。

createInvoice

POST /pay/api/createInvoice——权限范围 invoices,每分钟 60。

参数类型必填含义
currency_typestring否crypto(默认)或 fiat
assetstringcrypto 模式要收的币种,比如 USDT。不能和 fiat 同时给
fiatstringfiat 模式标价用的法币(getCurrencies 里 is_fiat 的那些行)
accepted_assetsstring / array否只在 fiat 模式下有效:付款人可以用来付的币种——逗号分隔的字符串("USDT,GRAM")或一个 JSON 数组。不给 = 全部支持的币种
amountstring是,除非设了 open_amount正的小数字符串:crypto 模式下是币种单位,fiat 模式下是法币单位(最多 2 位小数)
open_amountboolean否扩展,只在 crypto 模式下有效:不定额——付款人在付的时候自己填(打赏和捐款)。跟 amount 互斥
descriptionstring否最多 1024 个字符,显示给付款人
hidden_messagestring否最多 2048 个字符,付款人付完才看得到
payloadstring否最多 4096 个字符的您自己的数据,会在账单和 webhook 里原样回传
allow_commentsboolean否允许付款人附一条留言(默认 true)
allow_anonymousboolean否允许付款人隐藏身份(默认 true)
paid_btn_namestring否付款后的按钮:viewItem、openChannel、openBot 或 callback
paid_btn_urlstring否那个按钮的 http(s) URL——设了 paid_btn_name 就必须给
swap_tostring否把收到的付款自动换成这个币种。尽力而为:付款时换不成的话,付款照样成功,只是没换
expires_ininteger否多少秒之后账单过期,最大 2678400(31 天);省略或 0 = 使用默认有效期,请读取返回的 expiration_date
rate_lock_secondsinteger否扩展,只在 fiat 模式下有效:在开单时把折算汇率锁定这么长一段时间(见下)

说明、付款后内容和按钮在审核期间或未获批准时可能对付款人隐藏,但账单金额仍可支付。

返回的结果——也就是 invoice_paid webhook 的 payload——是账单对象。它的主要字段:

  • 标识和状态:invoice_id、hash(pay_url 里那个公开 ID)、status (active / paid / expired)、pay_url——您发给付款人的那条 t.me 链接 (bot_invoice_url、mini_app_invoice_url、web_app_invoice_url 都是它的别名)。
  • 金额:amount(票面金额——法币账单上是法币单位,否则是加密货币;不定额账单没付掉之前 是 null)、amount_minor,以及已付法币账单上的 paid_asset / paid_amount / paid_fiat_rate——实际收的加密货币和用的汇率。
  • 手续费:fee_asset / fee_amount,在付款时确定并记录——这是您记账时的权威数字 (fee 和 usd_rate 是已废弃的 Crypto Bot 别名)。见 费用和限额。
  • 付款人:paid_by_user_id(付款人选了匿名时是 null)、paid_anonymously、comment。
  • 退款(扩展):refunded_amount / refunded_minor(累计)和 refunded_at,全额退完 之后写入。
  • 汇率锁定(扩展):rate_lock_until 和 rate_lock_rates——记录下来的各币种汇率, 没申请锁定时是 null。
  • 开单时给的那些:description、hidden_message、payload、paid_btn_name / paid_btn_url、expiration_date(expires_at 是别名),以及兑换相关字段(swap_to、 is_swapped、swapped_to、swapped_rate、swapped_output 等等)。

错误:400 invalid_currency(asset 和 fiat 搞混了)、400 invalid_amount、 400 unknown_asset、400 unsupported_fiat、400 paid_btn_url_required,以及跟汇率锁定 有关的 400 rate_lock_fiat_only、409 ratelock_disabled、409 rate_unavailable (某个接受的币种取不到最新汇率——重试即可)。

账单是怎么被付掉的

付款人在 Mini App 中用自己的钱包余额付款,余额充足并确认后即时完成,不收网络手续费。该选项可用时,也可用外部钱包充值支付:应用显示充值地址和付款期限,充值进入付款人自己的钱包。自动付款要求该地址收到充值、可用余额充足、无转出限制,且付款请求和账单均未过期。迟到的充值会留在付款人钱包中,并不能证明账单已付。两种方式最终都表现为正常的 paid 账单;配置 webhook URL 后还会产生 invoice_paid 事件,无需处理额外参数或字段。

法币账单的加密货币金额在付款时计算,并向上取整到所选资产的最小单位,然后从该金额扣除商户手续费。若既没有有效的锁定汇率,也取不到最新汇率,付款会失败,而不会按过时汇率结算。

给法币账单锁汇率

传 rate_lock_seconds,就会在开单时把每一个接受币种当下的汇率固定下来。锁定有效期间, 付款人看到的正是固定下来的那几个数额,付款也按固定下来的汇率折算——这段窗口里的汇率风险由您 承担。服务器会将所请求的时长调整到支持的范围内。请读取结果中的 rate_lock_until,确认实际截止时间。

锁定失效后,尚未过期的账单仍可按付款时汇率支付。若希望两个期限一致,请在支持的锁定范围内设置 expires_in,并比较响应中的 expiration_date 和 rate_lock_until。

getInvoices

GET /pay/api/getInvoices——权限范围 read。过滤条件:asset、fiat、invoice_ids (逗号分隔)、status(active / paid / expired——expired 是扩展;active 不含已经 过了期限的账单),外加 offset / count。返回 {"items": [invoice, …]},按时间倒序。

deleteInvoice

POST /pay/api/deleteInvoice——权限范围 invoices。一个参数:invoice_id。取消一张 没付掉的账单,返回 true。错误:404 invoice_not_found、409 invoice_already_paid ——已付的账单删不掉,钱已经动了。

refundInvoice

POST /pay/api/refundInvoice——权限范围 refunds,每分钟 30。相对 Crypto Bot 的扩展:从应用余额向付款人退还实际支付的全部或部分加密货币。匿名付款也可退款,且不会暴露身份。法币账单使用 paid_asset 和 paid_amount,不会重新进行法币换算。

参数类型必填含义
invoice_idinteger是那张已付账单
amountstring否退款的加密货币金额,使用原付款资产(法币账单为 paid_asset)。省略 = 退还全部未退余额。累计部分退款不得超过原付的加密货币金额
spend_idstring否幂等键——请用上它,好让超时重试变成重放而不是退两次

返回的是更新后的账单对象,带累计的 refunded_amount / refunded_minor;账单全额退完之后 refunded_at 才写入。状态一直是 paid。平台手续费不退。即使 swap_to 已将收入换成其他资产,应用也须持有足够的原付款资产。每一次退款都会触发需要订阅的 refund_completed webhook。

错误:404 invoice_not_found、409 invoice_not_paid、409 already_refunded(没什么可退了)、 409 amount_too_big(超过还没退的余数)、409 insufficient_funds、400 invalid_amount, 以及 spend_id 那一对 409 idempotency_conflict / 409 idempotency_in_progress。