这里的想法是,钱包可以扫描静态二维码或点击静态 LNURL 地址,并获取关于预期付款的详细信息。这些详细信息可能包含比普通闪电网络发票更广泛的元数据。金额可以是固定的,也可以在一个范围内。
然后,一旦用户接受条款(并选择一个金额,如果金额不是固定的),钱包将调用服务并获得一个针对该付款的特定闪电网络发票,其中包含元数据的哈希值作为其 并继续支付发票,如果它与预期的金额和哈希值匹配。
支付到静态二维码/NFC/链接
钱包与服务交互流程:
- 用户扫描一个 LNURL 二维码或粘贴/分享一个 lightning:LNURL.. 链接给 LN 钱包,LN 钱包 解码 LNURL。
- LN 钱包 使用解码后的 LNURL 向 LN 服务 发起一个 GET 请求。
- LN 钱包 从 LN 服务 获得 JSON 响应,格式如下: json { "callback": string, // LN 服务 将接受支付请求参数的 URL "maxSendable": number, // LN 服务 愿意接收的最大毫聪金额 "minSendable": number, // LN 服务 愿意接收的最小毫聪金额,不能小于 1 或大于 `maxSendable` "metadata": string, // 元数据 json,必须在此处作为原始字符串呈现,这是稍后通过签名验证所必需的 "tag": "payRequest" // LNURL 的类型 } 或者 json {"status": "ERROR", "reason": "错误详情..."} metadata json 数组必须包含一个 text/plain 条目,所有其他类型的条目都是可选的。 metadata json 数组必须包含一个 image/png;base64 条目或一个 image/jpeg;base64 条目,或者两者都不包含。
metadata
json 数组只允许包含数组。metadata
数组内部的数组的第一项始终是一个表示元数据类型的字符串,而后面的任何项可以是任何 JSON 类型。实现者不能假定它始终是一个字符串。json [ [ "text/plain", // 必需 string // 支付时和交易记录中显示的简短描述 ], [ "text/long-desc", // 可选 string // 支付的较长描述,可能包含换行符 ], [ "image/png;base64", // 可选 string // base64 字符串,可选的 512x512px PNG 缩略图,将在列表或网格中表示此 lnurl。最多 136536 个字符(base-64 编码的 100Kb 图像数据) ], [ "image/jpeg;base64", // 可选 string // base64 字符串,512x512px JPG 缩略图,将在列表或网格中表示此 lnurl。最多 136536 个字符(base-64 编码的 100Kb 图像数据) ], // 未来的条目: [ string, any ] ]
并作为字符串发送:json "[[\"text/plain\", \"lorem ipsum blah blah\"]]"
LN 钱包
显示一个支付对话框,用户可以在其中指定要发送的确切金额,该金额将受以下限制:max 可以发送 = min(maxSendable, 本地估计的钱包可以发送的最大金额) min 可以发送 = max(minSendable, 钱包允许的本地最小金额)
此外,支付对话框必须包括:- 从
LNURL
查询字符串中提取的域名。 - 一种查看
text/plain
格式的已发送元数据的方式。
并且可能包括:
- 一个包含 image/png
或 image/jpeg
内容的图像元素。
- LN 钱包 使用以下方式发起一个 GET 请求 <callback><?|&>amount=<milliSatoshi> amount 是用户以毫聪为单位指定的金额。
- LN 服务 接收到 GET 请求,并返回 JSON 响应,格式如下: json { pr: string, // bech32 序列化的闪电网络发票 routes: [] // 一个空数组 } 或者 json {"status":"ERROR", "reason":"错误详情..."}
- LN 钱包 验证提供的发票中的 h 标签是 metadata 字符串转换为 UTF-8 编码的字节数组的哈希值。
- LN 钱包 验证提供的发票中的金额等于用户先前指定的金额。
- LN 钱包 支付发票,此时不需要额外的用户确认。
关于服务端 LNURL-PAY 的元数据的说明
当客户端发起第一次调用时:
构造一个元数据对象,将其转换为 json,然后将其作为字符串包含到父 json 中。
当客户端发起第二次调用时
- 如下创建一个哈希:
sha256(utf8ByteArray(unescaped_metadata_string))
. - 使用获得的哈希生成一个支付请求。