LNURL-pay 付款码里的 metadata 与 successAction:扫闪电码时该显示什么 图 1
LNURL-pay 付款码里的 metadata 与 successAction:扫闪电码时该显示什么 · 图 1

扫闪电码时,钱之外还交换了什么

闪电网络的标准付款码(BOLT11 发票)把金额、收款路径、有效期编死在一串字符里,扫之前解不开。LNURL-pay(LUD-06)把模型反过来:二维码只装一个 bech32 编码的 https 地址(tag 为 payRequest),真正的信息在扫码后现场协商。钱包 GET 那个地址,拿回一份 JSON:callback 回调地址、maxSendable 与 minSendable 两个金额边界(单位 millisatoshi)、metadata 一段必须原样展示给用户的元数据文本,以及 tag。用户在钱包界面上选一个落在边界内的金额,钱包生成一张该金额的 BOLT11 发票,带 callback 加 pr 参数(外加可选 comment)再发一次请求,服务器回一张正式发票,钱包核对金额后走闪电路由付款。

和发票码相比,这套流程多了两处”人机接口”:金额边界和元数据。它们既是功能,也是攻击面。

LNURL-pay 付款码里的 metadata 与 successAction:扫闪电码时该显示什么 图 2
LNURL-pay 付款码里的 metadata 与 successAction:扫闪电码时该显示什么 · 图 2

metadata 的义务:一段必须”原样呈现”的文本

规范对 metadata 有硬性形状要求:JSON 数组,第一项必须是 text/plain(比如商户名、订单号),图片类(image/png;base64 或 image/jpeg;base64)最多带一种、也可以都不带;数组里的每一项又必须是数组,第一项是类型串,后面才是内容。关键是语义:这段文本必须作为裸字符串原样放进响应,且钱包”必须”把它呈现给用户。它的设计意图是让扫码的人亲眼看见钱要去哪儿、买什么,弥补”金额之外信息都被折叠进链接”的缺陷。

钱包实现差异是用户能感知的最大风险。有的钱包完整展示 text/plain,有的只把商户名拼在标题里,图片类元数据则常被忽略——遇到收款方用图片嵌链接引流时,不显示图片的钱包反而更安全。规范还特别提醒:不要假设数组项一定是字符串,实现要能容错。对用户实操的意义:大额付款前优先选完整显示 metadata 的钱包;显示为空、格式怪异或内容与页面宣称不符时,等于这道防线没有生效,先找收款方核对。

successAction:付款成功之后显示什么

LUD-09 补的是”回执”环节。服务器在第二次 callback 响应里可以带一个 successAction 对象,钱包必须存储它并在支付成功后立即展示。规范定义了几种 tag:message(一段纯文本回执,上限 144 字符,比如”你的单车已解锁”)和 url(一个带描述与链接的页面,且规范硬性要求 url 的域名必须与第三层 callback 的域名一致——这条限制正是为了阻止回执页把用户带去第三方站点)。回执显示是义务而不是可选项:规范要求钱包在支付完成后立即以弹窗或页面展示 successAction,并把数据存进交易记录;遇到自己不支持的 tag 类型时,钱包必须拒绝继续付款,以免用户付了钱却看不到应有回执。

边界要看清:url 类回执打开的是收款方站点的页面,钱包通常给出描述加”打开”按钮由用户决定。把它当普通链接复制出去、在系统浏览器里继续操作,就把”支付后页面”变成普通入口——域名一致性只约束了钱包内打开的行为。合理用法:核对回执页域名与商户域名一致后再继续;message 型回执当小票保存即可。

排障视角:LNURL 付款失败先看哪一步

LNURL 的失败常卡在协议层而不是路由层。第一次 GET 报错:域名解析或证书问题,多为收款服务器下线或 LNURL 被劫持。第二次带 pr 的 callback 返回 ERROR:金额越界(min/max 边界)、comment 与 metadata 合规问题、或服务器返回的发票与钱包所选金额不符。这两步都过了但支付失败:回到普通闪电排障逻辑——入向流动性不足、路由不可达、金额超通道上限,与 LNURL 无关。用这个”两跳四分法”能把客服对话从”扫了没反应”升级成可定位的段落。

风险提示:本文为协议机制科普,不构成投资建议。任何把收款信息藏在链接里现场协商的协议,都要求用户在确认页上多停留三秒。