多笔付款的 paymentDetails 含 paymentState、requiredAmountBase、confirmedAmountBase、remainingAmountBase、excessAmountBase、assetDecimals 及 payments[]。每条包含 txHash/state/payerAddress/toAddress/requiredConfirmations,已知时另含 amountBase/confirmations/failureCode。成功必须满足总额等于原单、remaining/excess 为零、没有待确认付款,并完整绑定原单精度和地址;部分付款、超付或人工核查保留预扣。不可因多笔成功没有单一顶层哈希而报失败。

提交前准备

玩家必须已经有平台的钱包主体。可以先用相同 playerId 成功获取充值地址来准备主体,不需要先发生充值。

在你的业务系统完成金额校验和预扣,保存订单及首次请求,然后提交提现。正文包含五个必填字段:withdrawOrderId、playerId、chainId、amount、toAddress。不要发送 chainName 或 tokenContract。缺少 playerId 会返回 422,不预留订单。

200 表示申请已受理,首次响应固定为 accepted=true、broadcast=false、status=manual_pending、route=manual,且不含 txHash/voucherTxHash。这不是提现完成证明;当前流程由人工审批并在链下完成出款,API 不自动转币。

手机的“新提现”订单号由 OG 自动生成,打开空表单不产生预扣。提交后,OG 后端须先核对成功响应的 accepted=true、原订单号、链/合约、金额及收款地址并持久保存,才允许手机清空输入、生成下一笔独立订单并刷新历史。本单显示处理中,后续通知或查询只更新原记录。下一笔仍按扣除所有已有预扣后的可用余额校验。

平台提现响应没有模拟器 /api/withdraw 的包装字段 action、held、queryOk。查询状态 held 仍然表示等待人工复核,与这些包装字段无关。前端清空条件应来自你们自己的后端确认结果,不能只检查 HTTP 200 或照抄模拟器包装字段。失败首查原请求、响应事实与本地提交结果;超时、事实不一致或未知结果保留原单和输入。

重试提交与查询不同

操作返回的内容你的处理
同单、同内容重试提交首次成功后,返回固定保存的首次受理响应保存受理结果,继续保持预扣,不用它判断最新状态
查询玩家提现记录当前认证接入方、玩家与指定链的已受理原单分页按订单号合并持久历史,不能用缺失记录释放预扣
查询提现该订单最新已同步状态,可能带交易哈希按提现状态表完成账务处理
取消未广播提现钱包仍待处理时,公开状态变为 refunded,并通知 withdrawal_refunded按原订单释放预扣一次;409 保持预扣
受理后manual_pending

人工提现处理中,保持预扣

处理中held / 进度状态

复核、发送中或凭证校验中都保持预扣

成功终态succeeded

确认扣款一次

失败或退款终态failed / refunded

释放原预扣一次

同一订单号绑定首次规范化内容:金额、收款地址、玩家或链不能随意改变。JSON 字段之间的排版空白不改变业务内容,字段值内的空白仍会被拒绝;签名按每次实际字节计算。查询只传路径里的订单号,不能带 query 或 body。已受理订单的响应不回传 playerId,应使用本地订单关联玩家;acceptedAt 是首次受理的 Unix 秒。

超时、断线或服务端错误时,用原订单号、原内容重试或查询,重新计算签名。提交 422 或查询 404/503 的含义不同,按错误码核实;不要换新订单号绕过未知结果,也不要因等待较久释放预扣。

“不换号重试”针对同一笔结果未知的提现,不禁止玩家按剩余可用余额发起另一笔独立业务申请。OG 必须同时保存旧单责任;历史里点击原单才查看冻结内容或原单重试,查询历史不覆盖正在编辑的新草稿。已受理列表不包含 OG 尚未明确受理的本地预扣单,不能用平台列表替换整个本地账本。

完成账务

付款流程只有 succeeded 确认扣款;failed 或 refunded 终态释放原预扣一次。每日上限的完整拒绝通知使用下述独立事务分支。其余状态保持预扣;voucher_failed 是非终态。进度通知 sending 表示提现处理中、等待链上观察,不表示平台正在自动广播。manual_pending 和 broadcast=false 都不能证明提现尚未广播。

通知与查询共用 withdrawOrderId 的本地预扣记录。同一终态先到的一方处理一次,后到的一方只记结果;终态互相冲突时暂停自动改账,先查询并联系平台核实,不能先确认扣款再因另一条消息释放预扣。释放预扣是恢复本地可用余额,不是向链上玩家地址转回 USDT。

预期一笔订单只确认扣款或释放预扣一次。结果不一致时先查原订单、预扣记录及最新查询;不能仅按 route、哈希或 broadcast 结账。

已确认部分付款时不得按失败退全额。 例如原单20已确认支付10,随后收到基础 failed/refunded,应视为与既有付款事实矛盾:保留已确认付款记录和整单 held,持久记录人工核查责任;不得进入通用释放分支、删除付款事实或把确认金额清零。预期重复通知与重启后仍不释放;失败先查原单持久付款记录、首次观察原文及核查任务。

用户每日提现上限

平台可在管理后台按链设置“用户每日提现上限”。同一条链上的所有用户使用同一个上限数值,但每个用户分别累计;同一用户在该链的全部收款地址共用额度,换地址不能绕过。以太坊与波场分别计算,未设置或已清空上限的链不受这项限制。

平台操作人员在资金总览选中当前链,按该链 USDT 精度输入正数并保存,随后回读核对链和金额;要恢复不限额,使用“清空上限”,不要保存 0。回读不一致时先核对当前链、精度和保存结果。

周期是北京时间每天 00:00 至次日 00:00,以钱包服务端记录的提现申请时间所属日期累计,不使用 OG 创建订单、手机点击或请求签名的时间。首次保存上限后新申请的、仍在处理中或已成功的提现计入当天;取消、明确失败或已拒绝的申请不计入。昨天尚未完成的提现不占今天额度。再次保存上限只修改金额,不清零当天已计入金额;清空后重新保存,才从新的保存时刻起算。以上规则不改变原提现审批和付款流程。

超限时,当前接口会返回什么

超限申请不会创建可付款订单,平台保存拒绝结果并投递 withdrawal_rejected。当前普通通道的同步响应与通知正文不同:

来源当前结果接入方动作
POST /v1/withdrawalsHTTP 422,{"error":"rejected"}这是通用错误,不能据此确认超限,也不能释放预扣;保留原单等待明确结果
GET /v1/withdrawals/{withdrawOrderId}已保存完整每日上限拒绝时返回 HTTP 200,与 Webhook 完全相同的原文;旧泛化拒单或损坏/身份不匹配回执为 503可信查询与已验签通知共用下述严格绑定和一次释放事务;GET 只读,不重算额度或重开原单
玩家提现列表仅列出已受理提现,不包含这类超限拒单OG 自行保留原单与拒绝历史,不因平台列表缺单而释放预扣
已验签的 withdrawal_rejected Webhook完整拒绝正文,包含 code、quota、原单身份及 final=true按下述规则严格校验,持久记录拒绝并释放原预扣一次

通用 422 并不一定伴随通知:字段不合法、链未开放等预校验失败不生成 withdrawal_rejected。先保留原单并核实请求;不能因为收不到通知就一直等下去,也不能自行认定超限或退款。

通知可能早于同步响应到达。OG 应在提交前保存原单和预扣;完整拒绝已处理后,迟到的通用 422 或 503 不得把订单改回“结果未知”。长期没有通知时,先查接收端日志、回签和通知配置,再请平台核对该原单的拒绝及投递记录。先用原单 GET 补回已保存的完整拒绝原文;若仍为 503 或回执不完整,保留预扣和持久核查任务,交平台核对,不能人工猜测退款。

显示拒绝原因与等待时间

code含义建议展示与下一步
USER_DAILY_WITHDRAWAL_LIMIT_EXCEEDED当天已计入金额加本次申请将超过上限“已超过每日提现上限,请等待额度重置。”展示 quota.resetAt 和剩余时间;当前普通通道的 retryAt=resetAt
REQUEST_AMOUNT_EXCEEDS_DAILY_LIMIT本笔金额已经大于整日上限“本次金额超过每日上限,请调整金额。”retryAt 和 retryAfterSeconds 为 null,不能承诺等到明天即可提交相同金额

完整通知字段与示例见接收交易通知。当前普通通道的 quota 快照按以下含义展示:

字段当前含义
limitBase本次判断使用的该链每日上限
spentBase本次申请之前,当天已计入的申请金额,包含处理中和已成功订单;不是仅已确认付款金额
reservedBase、blocked当前分别为字符串 "0" 和 false;不表示存在旧版跨日占用或人工阻断
availableBase、requestedBase当时剩余额度与本次申请金额;剩余值最低为 0
evaluatedAt、resetAt本次判断时间、下一次北京时间 00:00;以 UTC 时间字符串返回
resetInSeconds判断时距离重置的秒数,向上取整;不是从收到通知开始计时
retryAt、retryAfterSeconds普通累计超限时为重置时间及对应秒数;单笔超过上限时均为 null
policyVersion兼容协议字段;当前保存上限不会递增,不能用它判断配置是否刚更新

金额始终是最小单位整数字符串,按 decimals 换算,不用浮点。quota 是拒绝当时的快照,不是实时余额或再次受理保证;配置后来变更时,旧通知内容不会重写。剩余等待时间使用 max(0, ceil(resetAt - 可信服务端当前时间)),手机以 OG 后端校准后的时钟展示,不能依赖用户设备时钟,也不能将迟到通知的 resetInSeconds 再倒数一遍。到点只能提示“额度重置时间已到,可重新申请”,不得自动付款或重发申请。retryAt 只是这份快照中的重置提示,不是禁止在此之前申请的冷却时间;已计入订单后来取消或明确失败、平台提高上限等情况可能使额度提前恢复,仍须由玩家明确发起新申请并重新校验。

旧拒绝订单在跨日、提额或清空上限后都不会重新受理。只有玩家明确发起新的业务申请时,才生成新的 withdrawOrderId,重新校验余额并预扣;不能给旧单换号自动重试。

拒绝通知:完整校验后释放一次

withdrawal_rejected 使用独立的 v2 格式正文;`schemaVersion=2` 表示通知格式,不表示当前普通通道已启用下面的三渠道能力。必须保留原始 bytes,严格校验完整包络:schemaVersion/type/status/accepted/broadcast/final/paymentInitiated/retryMode/decisionId/eventId/withdrawOrderId/playerId/chainName/chainId/tokenContract/amount/toAddress/code/quota。其中 status=rejected,accepted/broadcast/paymentInitiated=false,final=true,retryMode=new_order。不得缺字段、增加字段、使用错误 nullable、重复键、非法 UTF-8、超过 32 层或数字金额;可复用下载示例附带的严格解析器。

在真实持久事务中,从既有可信配置取得身份范围 environment/accessNamespace(scope),核对原订单、玩家、登记链与合约、按链规范比较的地址、金额和 decisionId/eventId,并要求 quota.decimals 等于该资产可信配置的 tokenDecimals;不能只采信通知自带精度。事件 ID 按共享编码数组 ["withdraw-intake-rejection-v2",environment,accessNamespace,withdrawOrderId] 派生 SHA-256;不能从通知自行决定 scope,也不能仅因 eventId 或 code 正确就跳过原请求绑定。

只有没有受理、凭证或付款证据的原预扣 held 才可转为 released,并且只转一次;恢复可用余额,不额外加款。原文、摘要、首次决定、业务状态与账务同次提交后才 ACK。同 ID 异 bytes、不同决定、身份不符或与已有付款事实矛盾时,保留首次证据和原账,持久记录异常后核查。拒绝后的进度或付款消息不能覆盖原拒绝或再次释放。不要把 rejected 加入通用 RELEASE:泛化 {"error":"rejected"}、不完整通知、404/409/503、超时与额度查询均不能触发释放。

预期重复投递、并发处理、重启后重投都只记录一次拒绝和释放;保存失败不 ACK。失败先查原始正文、完整字段、可信 scope 与原请求绑定,再查已有受理/付款证据和事务提交。

查询当前每日提现上限

玩家打开提现页、切换网络或刷新时,后端可调用查询每日上限 GET /v1/withdrawal-quota?playerId=…&chainId=…,与管理后台保存的“用户每日提现上限”使用同一规则。两个 query 各一次、GET body 为空,按原路径与 query 签名;从登录态确定玩家,不能接受前端任意指定其他玩家身份。

200 的 quota 为对象时,limitBase 是上限,spentBase 是当日已计入的申请额,包含处理中和成功订单,排除取消、拒绝和失败;availableBase=max(0,limitBase-spentBase)。按申请所属北京时间自然日统计,昨日未完成订单不占今天;首次保存前申请不计入,再次保存保留起点,清空后重存重新起算,等于起点的申请计入。reservedBase="0"、blocked=false,不表示没有在途单。

quota 必返,显式 `null` 表示尚未设置或已清空,即不限额,不是上限为 0,也不是读取失败;此时不展示已用、剩余或重置倒计时。金额均为基础单位整数字符串,decimals=6 时 1000000000 表示 1000 USDT,不能转浮点。requestedBase/retryAt/retryAfterSeconds 在查询对象中均为 null。

核对玩家、链名/ID、登记合约和 serverNow;有上限时 serverNow=quota.evaluatedAt,按 resetAt 与可信当前时间展示。所有数据来自同一只读快照,下一次查询可因保存或新申请变化。查询不创建玩家、不受理提现、不改账、不重开拒单,当前剩余额度不是随后受理承诺。schemaVersion=2 仅为 JSON 格式版本。

401 查签名;422 查两个 query、登记链与空 body;404 表示当前玩家不存在;503/超时保持未知、稍后重查,先查服务版本、目录、配置及数据库只读权限。不能伪造零或 quota:null,不能据此释放旧单预扣。

历史特殊通道兼容

仅处理历史特殊通道原单时需要本节。对于已经保存完整拒绝回执的这类原单,POST 422、原单 GET 200 与 withdrawal_rejected 返回同一份冻结拒绝正文,三渠道共用上述一次释放事务;后来暂停该能力,也不会把这份历史拒绝改成通用错误。原单响应按首次保存的通道处理,不能只看当前开关。管理后台保存“用户每日提现上限”不会自动启用这项能力。

该兼容模式可能保留跨日未决占用,并返回 USER_WITHDRAWAL_QUOTA_BLOCKED;这不是上面当前配置的计算规则。活动阻断及单笔超过总上限时 retryAt=null;累计超限也只有次日扣除未决占用后仍足以容纳申请时才给出重试时间。retryAt 只提供时间提示,没有 HTTP Retry-After,不保证届时受理。真实 PHP 或其他语言接入方启用此兼容能力前,须验证完整契约、三渠道乱序/重复仅释放一次、未知结果保留及持久提交后回签;本地示例不能代替业务账本验收。

输入关键词搜索指南、接口和字段。