tgpay cryptoAPI
crypto-payapiinvoicesrefunds

API 参考:账单和退款

阅读约 2 分钟最后更新: 2026年8月22日

账单相关的方法:createInvoicegetInvoicesdeleteInvoicerefundInvoice。通用约定 (鉴权、外层结构、金额、spend_id)见商户 API 参考页面; 手把手的走一遍在用账单收款

createInvoice

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

参数类型必填含义
currency_typestringcrypto(默认)或 fiat
assetstringcrypto 模式要收的币种,比如 USDT。不能和 fiat 同时给
fiatstringfiat 模式标价用的法币(getCurrenciesis_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付款后的按钮:viewItemopenChannelopenBotcallback
paid_btn_urlstring那个按钮的 http(s) URL——设了 paid_btn_name 就必须给
swap_tostring把收到的付款自动换成这个币种。尽力而为:付款时换不成的话,付款照样成功,只是没换
expires_ininteger多少秒之后账单过期,最大 2678400(31 天);不给或 0 = 永不过期
rate_lock_secondsinteger扩展,只在 fiat 模式下有效:在开单时把折算汇率锁定这么长一段时间(见下)

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

  • 标识和状态invoice_idhashpay_url 里那个公开 ID)、statusactive / paid / expired)、pay_url——您发给付款人的那条 t.me 链接 (bot_invoice_urlmini_app_invoice_urlweb_app_invoice_url 都是它的别名)。
  • 金额amount(票面金额——法币账单上是法币单位,否则是加密货币;不定额账单没付掉之前 是 null)、amount_minor,以及已付法币账单上的 paid_asset / paid_amount / paid_fiat_rate——实际收的加密货币和用的汇率。
  • 手续费fee_asset / fee_amount,在付款时确定并记录——这是您记账时的权威数字 (feeusd_rate 是已废弃的 Crypto Bot 别名)。见 费用和限额
  • 付款人paid_by_user_id(付款人选了匿名时是 null)、paid_anonymouslycomment
  • 退款(扩展):refunded_amount / refunded_minor(累计)和 refunded_at,全额退完 之后写入。
  • 汇率锁定(扩展):rate_lock_untilrate_lock_rates——记录下来的各币种汇率, 没申请锁定时是 null
  • 开单时给的那些descriptionhidden_messagepayloadpaid_btn_name / paid_btn_urlexpiration_dateexpires_at 是别名),以及兑换相关字段(swap_tois_swappedswapped_toswapped_rateswapped_output 等等)。

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

账单是怎么被付掉的

付款人在 Mini App 里用自己的钱包余额付——瞬间完成,没有网络手续费。付款人也可以 用外部钱包充值来支付这张账单:应用给他一个充值地址,他的转账落进他自己的钱包,钱一到账单就 自动结清。两种方式您看到的都一样:一张正常的 paid 账单和一个 invoice_paid webhook ——没有额外的参数或字段要处理。

法币账单上的加密货币数额是在付款时算的,向上取整,取整方向对您有利,所以您拿到的绝不会少于法币 票面值。要是取不到最新汇率,付款会在付款人那一侧失败,而不是按一个过时的汇率成交。

给法币账单锁汇率

rate_lock_seconds,就会在开单时把每一个接受币种当下的汇率固定下来。锁定有效期间, 付款人看到的正是固定下来的那几个数额,付款也按固定下来的汇率折算——这段窗口里的汇率风险由您 承担。服务器会把这个窗口夹在 60 秒和平台上限(目前是 15 分钟)之间。

锁定失效之后,账单照样能付,只是自动回到按付款时折算。您要是希望报价一过账单就作废, 把 expires_in 设成同样的值。

getInvoices

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

deleteInvoice

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

refundInvoice

POST /pay/api/refundInvoice——权限范围 refunds,每分钟 30 次。相对 Crypto Bot 的扩展: 把一张已付账单的票面金额——或其中一部分——从您的应用余额退还给付款人,匿名付款的也能退, 而且不会暴露他是谁。

参数类型必填含义
invoice_idinteger那张已付账单
amountstring要退的数额,用账单的币种。不给 = 还没退的余数全退。部分退款可以累加到票面金额为止
spend_idstring幂等键——请用上它,好让超时重试变成重放而不是退两次

返回的是更新后的账单对象,带累计的 refunded_amount / refunded_minor;账单全额退完之后 refunded_at 才写入。状态一直是 paid。平台手续费不退。每一次退款都会触发需要订阅的 refund_completed webhook

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