# Getting Started with Lightning Payments in Ruby

By [icebaker](https://paragraph.com/@icebaker) · 2023-03-12

---

This article will explore how to use Ruby with the [Lighstorm](https://github.com/icebaker/lighstorm) gem to create and verify Lightning payments. We'll cover the steps from both the buyer's and seller's perspectives, including generating _invoices_, making _payments_, and verifying transactions using _Proof of Payment_.

The Lightning Network is a layer two payment protocol built on top of the Bitcoin blockchain. It is designed to enable fast, low-cost, and secure transactions. Lightning payments use smart contracts to facilitate instant payments between parties without requiring confirmation from the Bitcoin network.

Suppose we have a buyer and a seller who want to engage in a financial transaction, such as the buyer purchasing a cup of coffee from the seller. How would this process unfold on the Lightning Network?

Seller's Perspective
--------------------

First, you generate an _Invoice_:

    require 'lighstorm'
    
    invoice = Lighstorm::Invoice.create(
      description: '1 Cup of Coffee',
      amount: { millisatoshis: 1000 },
      payable: 'once'
    ).result
    

Once you have created the _Invoice_, you can share the _Invoice Code_ with the individual who will be making the purchase:

    invoice.code # => 'lnbc10...gfn9yd'
    

It's common practice to share the _Invoice_ code via a [QR code](https://en.wikipedia.org/wiki/QR_code). There are several methods for generating a QR code, and one option is to use the [RQRCode](https://github.com/whomwah/rqrcode) gem to create an SVG image:

    require 'rqrcode'
    
    code = RQRCode::QRCode.new("lightning:#{invoice.code}")
    code.as_svg(
      color: '000', shape_rendering: 'crispEdges',
      module_size: 11, standalone: true,
      use_path: true, viewbox: true
    )
    

After generating the Invoice, the individual who wants to purchase can use their mobile camera to scan the QR code.

Let's switch to the buyer's perspective now:

Buyer's Perspective
-------------------

As a buyer, you will receive the _Invoice Code_ through a message or scanning a QR code. To view additional details about the Invoice you have received, you can:

    require 'lighstorm'
    
    invoice = Lighstorm::Invoice.decode(
      'lnbc10n1pjqux8spp5e5vr8d2f50et6y2mgvltyynecxzun22y2urzmxuhvwcp9877u4nsdqcxysyxatsyphkvgzrdanxvet9cqzpgxqyz5vqsp5ku00sl5p5r76eu9aw6n7mzny9d94r03hpr69r9uvh9yc074pepds9qyyssq0q79336f9qpdfztfflmkfyzweucsphw008mhh2nmtz2m27vugpsnjay5q5p5p5d0dl2gvakzplg757xw8efu4734lpgr88z2y9t3rjqqgfn9yd'
    )
    
    invoice.amount.millisatoshis # => 1000
    invoice.description.memo # => '1 Cup of Coffee'
    

Great! You have reviewed the amount and description and confirmed it's the correct Invoice. The next step is to pay the Invoice:

    payment = invoice.pay.result
    

If you encounter an error when attempting to make a payment, such as a `NoRouteFoundError` error, one common reason for this issue is that you do not have a direct channel with the seller. You may need to use third-party channels to complete the payment in this case.

While the Lightning Network handles this process automatically, it's worth noting that third-party channels may not be free to use. Fees may apply to utilize these channels, as those facilitating the payment would like to be compensated for helping you. As such, adding extra money to cover possible fees is necessary.

    payment = invoice.pay(
      fee: { maximum: { millisatoshis: 10 } }
    ).result
    

To verify that the payment has been successfully made and to check the amount paid, including possible fees, you can:

    payment.state # => 'succeeded'
    payment.amount.millisatoshis #=> 1000
    payment.fee.millisatoshis #=> 0
    

Validating the Transaction
--------------------------

It seems that we're all set. However, how can the seller be sure that the buyer has paid the Invoice? To verify the payment status, the seller can locate the Invoice and check its current state:

    invoice = Lighstorm::Invoice.find_by_code(
      'lnbc10n1pjqux8spp5e5vr8d2f50et6y2mgvltyynecxzun22y2urzmxuhvwcp9877u4nsdqcxysyxatsyphkvgzrdanxvet9cqzpgxqyz5vqsp5ku00sl5p5r76eu9aw6n7mzny9d94r03hpr69r9uvh9yc074pepds9qyyssq0q79336f9qpdfztfflmkfyzweucsphw008mhh2nmtz2m27vugpsnjay5q5p5p5d0dl2gvakzplg757xw8efu4734lpgr88z2y9t3rjqqgfn9yd'
    )
    
    invoice.state # => 'settled'
    

Similarly, the buyer can also double-check the payment status:

    payment = Lighstorm::Payment.find_by_invoice_code(
      'lnbc10n1pjqux8spp5e5vr8d2f50et6y2mgvltyynecxzun22y2urzmxuhvwcp9877u4nsdqcxysyxatsyphkvgzrdanxvet9cqzpgxqyz5vqsp5ku00sl5p5r76eu9aw6n7mzny9d94r03hpr69r9uvh9yc074pepds9qyyssq0q79336f9qpdfztfflmkfyzweucsphw008mhh2nmtz2m27vugpsnjay5q5p5p5d0dl2gvakzplg757xw8efu4734lpgr88z2y9t3rjqqgfn9yd'
    )
    
    payment.state # => 'succeeded'
    

Although you know that the Invoice has been paid, it's important to ensure that the buyer truly is the one who made the payment. Someone else could have paid the Invoice, or the buyer could be presenting a fake payment. To address this issue, the seller can request _Proof of Payment_ from the buyer that is only accessible to the legitimate payer of the Invoice.

The buyer can access its _Proof of Payment_ to share with the seller:

    payment.secret.proof
    

Then, the seller can verify if it is legitimate:

    invoice.secret.valid_proof?(
        '0c9e04be6034655f19cd1b9a771dcb6600dc28f4adb058ae1885c8c766f81296'
    ) # => true
    

There we ago, now we are 100% confident and the seller can deliver the cup of coffee to the buyer.

Although _Proof of Payment_ may not be necessary for in-person transactions, as the seller can verify the payment on the spot, it becomes crucial in remote transactions or e-commerce. It's important to ensure that the person claiming to have paid for the product is the legitimate payer before delivering the product.

Two Stories
-----------

Let's explore some short stories that showcase how the concepts we just learned can be applied in real-world scenarios:

### A simple cup of coffee

> Buyer: _Hey, I would like a coffee, please._ Seller: _Sure, it's one satoshi. Here's the invoice:_

    invoice = Lighstorm::Invoice.create(
      description: '1 Cup of Coffee',
      amount: { millisatoshis: 1000 },
      payable: 'once'
    ).result
    
    invoice.code
    

> Buyer: _Great, let me pay for it:_

    payment = Lighstorm::Invoice.decode(
      'lnbc10n1pjqus8jpp5td8cjd7y0za7x22asl7yee585s6vd4776nqnutv4vdu0hq6n54msdqcxysyxatsyphkvgzrdanxvet9cqzpgxqyz5vqsp5a2fhccxzwm0mva8g9nrr3l04rzp4vvycj4xj9dj9zagv2qg5l3ms9qyyssqg426awt2svu2eak5dm4sendryc42lz9czqs7ztlwkxetd43nhkg5eflegad0ll683t08xxfw87369cv48wkm4w9877vzlxfkwjrywjcq7sgdg6'
    ).pay(
      fee: { maximum: { millisatoshis: 1000 } }
    ).result
    
    payment.state # => 'succeeded'
    

> Buyer: _Done!_ Seller: _Just one second:_

     Lighstorm::Invoice.find_by_code(
      'lnbc10n1pjqux8spp5e5vr8d2f50et6y2mgvltyynecxzun22y2urzmxuhvwcp9877u4nsdqcxysyxatsyphkvgzrdanxvet9cqzpgxqyz5vqsp5ku00sl5p5r76eu9aw6n7mzny9d94r03hpr69r9uvh9yc074pepds9qyyssq0q79336f9qpdfztfflmkfyzweucsphw008mhh2nmtz2m27vugpsnjay5q5p5p5d0dl2gvakzplg757xw8efu4734lpgr88z2y9t3rjqqgfn9yd'
    ).state # => 'settled'
    

> Seller: _All good, here's your coffee, have a nice day!_ Buyer: _Thank you!_

### The fraudulent buyer

> Buyer: _Hey, I'm the one who just bought the keyboard you sold. Can I share an address so you can deliver the product?_ Seller: _Sure. May you please share the proof of payment?_ Buyer: _Here it is:_

> Seller: _Great, just a second:_

    Lighstorm::Invoice.find_by_code(
      'lnbc10n1pjqux8spp5e5vr8d2f50et6y2mgvltyynecxzun22y2urzmxuhvwcp9877u4nsdqcxysyxatsyphkvgzrdanxvet9cqzpgxqyz5vqsp5ku00sl5p5r76eu9aw6n7mzny9d94r03hpr69r9uvh9yc074pepds9qyyssq0q79336f9qpdfztfflmkfyzweucsphw008mhh2nmtz2m27vugpsnjay5q5p5p5d0dl2gvakzplg757xw8efu4734lpgr88z2y9t3rjqqgfn9yd'
    ).secret.valid_proof?(
        '66d408901c89d0038e1630b67ac494f7bc35038374e42e5793bc985bce4ceecf'
    ) # => false
    

> Seller: _So, I'm afraid there's something wrong. This proof isn't valid..._ Buyer: _(became offline)_

Wrapping Up
-----------

Creating and paying invoices is a crucial part of using the Lightning Network, and I hope this article has provided you with a helpful starting point.

There are numerous other ways to exchange money using Lightning beyond what showed here, and I plan to delve into those topics in future articles. So, stay tuned!

Thank you for taking the time to read this article. Happy coding!

---

*Originally published on [icebaker](https://paragraph.com/@icebaker/getting-started-with-lightning-payments-in-ruby)*
