高級
Offers Refunds BOLT12 退款
了解 BOLT12 的退款機制,如何實現可退款的閃電支付和商家退款流程。
10 分鐘
什麼是 BOLT12 退款?
BOLT12 引入了原生的退款機制,允許商家向買家發起支付。 這解決了傳統閃電支付「發送後無法退回」的限制。
雙向互動: 退款利用 BOLT12 的互動式協議,商家可以向買家請求發票, 然後支付該發票完成退款。
退款流程
BOLT12 Refund Flow:
Complete Flow (Purchase -> Refund):
Buyer Merchant
| |
| ======= Normal Purchase Flow ======= |
| |
|---- invoice_request ------------------>|
| (contains payer_key) |
| |
|<--- invoice ---------------------------|
| (records payer_key) |
| |
|==== HTLC Payment =====================>|
| | [Store order info]
| |
| ======= Refund Flow ======= |
| |
|<--- invoice_request -------------------|
| (merchant requests buyer invoice) | [Initiate refund]
| |
|---- invoice -------------------------->|
| (buyer provides payment invoice) |
| |
|<=== HTLC Payment (refund) =============|
| | 退款 Offer 結構
send_invoice Offer (for refunds): Offer Type Comparison: Normal Offer (receiving payment): • Merchant publishes, buyer scans • Buyer requests invoice -> Merchant provides invoice -> Buyer pays • send_invoice = false (default) Refund Offer (sending payment): • Merchant sends to specific buyer • Buyer provides invoice -> Merchant pays • send_invoice = true Refund Offer TLV Fields: send_invoice (54): Present indicates this is a refund Offer amount (8): Refund amount (fixed) description (10): "Refund for order #12345" paths (16): Merchant's blinded paths Merchant needs to receive buyer's invoice refund_for (38): 32 bytes Original payment's payment_hash Links refund to original order Example encoding: lno1... (Offer containing send_invoice flag)
payer_key 的重要性
payer_key Enables Refundable Payments:
During Original Purchase:
Buyer sends invoice_request:
{
offer_id: <Merchant's Offer ID>,
payer_key: 0x02abc...def, <- Buyer's public key
payer_signature: <signature>
}
Merchant stores:
order_12345 = {
payment_hash: 0x123...abc,
payer_key: 0x02abc...def, <- Remember buyer's public key
amount: 100000 msat,
timestamp: 1699999999
}
Using payer_key for Refund:
Merchant creates refund Offer:
{
send_invoice: true,
amount: 100000 msat,
refund_for: 0x123...abc,
payer_key: 0x02abc...def <- Specify recipient
}
Only buyer with corresponding private key can:
• Decrypt messages sent to that payer_key
• Prove they are the original buyer
• Provide valid payment invoice 實現細節
Merchant-side Refund Implementation:
Initiating Refund:
1. Query original order
order = database.get_order(order_id)
2. Create refund Offer
refund_offer = {
send_invoice: true,
amount: order.amount,
description: f"Refund for {order_id}",
refund_for: order.payment_hash,
paths: generate_blinded_paths()
}
3. Send to buyer
send_onion_message(
destination: order.payer_key,
content: refund_offer
)
4. Wait for buyer's invoice
invoice = await receive_invoice()
5. Verify invoice
verify(invoice.payer_key == order.payer_key)
verify(invoice.amount == refund_offer.amount)
6. Pay invoice
pay(invoice)
Buyer-side Processing:
1. Receive refund Offer
offer = receive_onion_message()
verify(offer.send_invoice == true)
2. Verify refund validity
original_payment = database.get_payment(offer.refund_for)
verify(original_payment exists)
3. Create payment invoice
invoice = create_invoice(
amount: offer.amount,
payment_paths: generate_paths()
)
4. Send invoice
send_onion_message(
destination: offer.paths[0],
content: invoice
)
5. Wait for payment
await receive_payment() 安全考量
Refund Security Mechanisms: Preventing Fraudulent Refunds: 1. payer_key Binding • Refund can only go to original buyer • Cannot impersonate buyer to request refund • Requires possession of corresponding private key 2. refund_for Association • Explicitly linked to original payment • Auditable refund records • Prevents duplicate refunds 3. Merchant Control • Merchant decides whether to refund • Merchant sets refund amount • Merchant verifies buyer identity Buyer Protection: Verify Refund Offer: • Confirm send_invoice = true • Confirm refund_for corresponds to real payment • Confirm amount is reasonable • Confirm source is trusted (via paths) Precautions: • Don't provide invoices to unknown Offers • Verify merchant identity • Keep payment records
應用場景
電商退貨、服務取消、超額支付退回、 獎勵發放等商業場景。
vs LNURL-withdraw
BOLT12 退款是原生協議,不需要 HTTP 服務。 更好的隱私和可靠性。
在線需求: 買家需要在線才能接收退款 Offer 並提供發票。 離線買家可能錯過退款窗口。
相關資源
下一步: 了解 Invoice Request 的詳細協議流程。
已複製連結