QRNBUEx

Build StatusHex.pmDocumentationLicense

Elixir library for generating NBU-compliant QR codes for Ukrainian payment systems.

Generate QR codes compatible with the National Bank of Ukraine (NBU) standards for money transfers to Ukrainian IBANs. Compatible with all major Ukrainian banking apps including PrivatBank, Monobank, Sense Bank, Ukrgazbank (EcoBank), PUMB, SportBank, IZIBank, and others.

Features

Installation

Add qr_nbu_ex to your list of dependencies in mix.exs:

def deps do
  [
    {:qr_nbu_ex, "~> 0.2.1"},
    {:decimal, "~> 2.0"}
  ]
end

Quick Start

Simple Payment (V001 - Plain Text)

{:ok, qr_data} = QRNBU.generate(:v001, %{
  recipient: "ТОВ Компанія Приклад",
  iban: "UA213223130000026007233566001",
  recipient_code: "12345678",
  purpose: "Оплата за послуги"
})

# Returns plain text QR data compatible with EPC QR codes

Payment with Amount (V002 - Base64URL)

{:ok, qr_url} = QRNBU.generate(:v002, %{
  recipient: "ФОП Іваненко І.І.",
  iban: "UA213223130000026007233566001",
  recipient_code: "1234567890",  # ITIN (10 digits for individuals)
  purpose: "Оплата товарів згідно рахунку №123",
  amount: Decimal.new("1500.50"),
  encoding: :utf8
})

# Returns: "https://qr.bank.gov.ua/[base64url_encoded_data]"

Advanced Payment (V003 - Extended Features)

{:ok, qr_url} = QRNBU.generate(:v003, %{
  recipient: "ТОВ Інтернет-магазин",
  iban: "UA213223130000026007233566001",
  recipient_code: "12345678",
  purpose: "Оплата замовлення #ORD-2024-001",
  amount: Decimal.new("2450.00"),
  category_purpose: "SUPP/REGU",  # ISO 20022 category
  reference: "INV-2024-001",
  display: "Оплата до 31.12.2024",
  invoice_validity: ~N[2024-12-31 23:59:59],
  invoice_creation: ~N[2024-01-09 10:00:00],
  field_lock: 0x0001  # Lock specific fields
})

Version Selection Guide

Version Use Case Format Features
V001 Simple payments, EPC compatibility Plain text Basic fields only
V002 Modern payments Base64URL + References
V003 Advanced payments Base64URL + ISO 20022, field locking, timestamps

Field Reference

Required Fields (All Versions)

Optional Common Fields

V002/V003 Additional Fields

V003 Exclusive Fields

Validation

The library automatically validates all fields:

# Invalid IBAN checksum
{:error, message} = QRNBU.generate(:v001, %{
  recipient: "Test",
  iban: "UA213223130000026007233566002",  # Wrong checksum
  recipient_code: "12345678",
  purpose: "Test"
})
# Returns: {:error, "Invalid IBAN checksum"}

# Invalid tax ID format
{:error, message} = QRNBU.generate(:v002, %{
  recipient: "Test",
  iban: "UA213223130000026007233566001",
  recipient_code: "123",  # Too short
  purpose: "Test"
})
# Returns: {:error, "Tax ID must be 8 digits (EDRPOU) or 10 digits (ITIN)"}

Error Handling

All functions return {:ok, result} or {:error, reason} tuples:

case QRNBU.generate(:v003, payment_data) do
  {:ok, qr_url} ->
    # Success: use qr_url
    Logger.info("Generated QR: #{qr_url}")
    
  {:error, reason} ->
    # Handle error
    Logger.error("QR generation failed: #{reason}")
end

Character Encoding

UTF-8 (Default)

{:ok, qr} = QRNBU.generate(:v002, %{
  # ... fields ...
  purpose: "Оплата товарів українською",
  encoding: :utf8
})

CP1251 (Windows-1251)

{:ok, qr} = QRNBU.generate(:v002, %{
  # ... fields ...
  purpose: "Оплата товарів",
  encoding: :cp1251
})

QR Code Rendering

The library includes built-in QR code rendering functionality through QRNBU.Renderer:

Render as PNG

# Generate QR data
{:ok, qr_string} = QRNBU.generate(:v001, payment_data)

# Render as PNG binary
{:ok, png_binary} = QRNBU.Renderer.to_png(qr_string)
File.write!("payment.png", png_binary)

# With custom options
{:ok, png} = QRNBU.Renderer.to_png(qr_string, 
  width: 500,
  error_correction: :h  # :l, :m, :q, or :h
)

Render as SVG

# Render as SVG string (with default UAH logo)
{:ok, svg_string} = QRNBU.Renderer.to_svg(qr_string)
File.write!("payment.svg", svg_string)

# With custom size
{:ok, svg} = QRNBU.Renderer.to_svg(qr_string, width: 400)

# Without logo
{:ok, svg} = QRNBU.Renderer.to_svg(qr_string, logo: false)

# With custom logo (no white circle background)
{:ok, svg} = QRNBU.Renderer.to_svg(qr_string, logo: "/path/to/custom-logo.svg")

# With inline SVG logo
{:ok, svg} = QRNBU.Renderer.to_svg(qr_string, logo: {:svg, "<svg>...</svg>"})

Display in Terminal

# Display QR code in terminal
:ok = QRNBU.Renderer.to_terminal(qr_string)

# With higher error correction
:ok = QRNBU.Renderer.to_terminal(qr_string, error_correction: :h)

Convenience Functions

# Generate and save as PNG in one step
:ok = QRNBU.Renderer.save_png(:v002, payment_data, "payment.png")

# Generate and save as SVG
:ok = QRNBU.Renderer.save_svg(:v003, payment_data, "payment.svg",
  width: 600,
  error_correction: :q
)

# Generate and display in terminal
:ok = QRNBU.Renderer.display(:v001, payment_data)

Error Correction Levels

Higher error correction creates larger QR codes but increases resistance to damage.

Testing

The library includes comprehensive testing:

# Run all tests
mix test

# Run tests with coverage
mix test --cover

# Current coverage: 90.35% (495 tests)

Documentation

Full documentation is available on HexDocs.

Generate local documentation:

mix docs
open doc/index.html

References

License

MIT License - see LICENSE.md for details.

Contributing

Contributions are welcome! Please:

  1. Fork the repository
  2. Create a feature branch
  3. Add tests for new functionality
  4. Ensure all tests pass: mix test
  5. Submit a pull request

Support