{"id":47009363,"url":"https://github.com/internetee/eis_billing_system","last_synced_at":"2026-03-11T20:39:46.230Z","repository":{"id":209451985,"uuid":"435450440","full_name":"internetee/eis_billing_system","owner":"internetee","description":null,"archived":false,"fork":false,"pushed_at":"2026-03-09T17:20:30.000Z","size":862,"stargazers_count":0,"open_issues_count":21,"forks_count":0,"subscribers_count":3,"default_branch":"master","last_synced_at":"2026-03-09T17:59:24.904Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Ruby","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/internetee.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2021-12-06T10:19:35.000Z","updated_at":"2026-03-09T15:44:17.000Z","dependencies_parsed_at":"2023-12-04T13:27:45.659Z","dependency_job_id":"d685c5f6-a136-436a-89f2-d63e47a1e935","html_url":"https://github.com/internetee/eis_billing_system","commit_stats":null,"previous_names":["internetee/eis_billing_system"],"tags_count":28,"template":false,"template_full_name":null,"purl":"pkg:github/internetee/eis_billing_system","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/internetee%2Feis_billing_system","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/internetee%2Feis_billing_system/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/internetee%2Feis_billing_system/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/internetee%2Feis_billing_system/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/internetee","download_url":"https://codeload.github.com/internetee/eis_billing_system/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/internetee%2Feis_billing_system/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":30399657,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-03-11T18:46:22.935Z","status":"ssl_error","status_checked_at":"2026-03-11T18:46:17.045Z","response_time":84,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2026-03-11T20:39:46.174Z","updated_at":"2026-03-11T20:39:46.221Z","avatar_url":"https://github.com/internetee.png","language":"Ruby","readme":"[![Maintainability](https://qlty.sh/gh/internetee/projects/eis_billing_system/maintainability.svg)](https://qlty.sh/gh/internetee/projects/eis_billing_system)\n[![Code Coverage](https://qlty.sh/gh/internetee/projects/eis_billing_system/coverage.svg)](https://qlty.sh/gh/internetee/projects/eis_billing_system)\n\n# EIS Billing System\n\n📚 **[API Documentation](https://internetee.github.io/eis_billing_system/)** | [GitHub Repository](https://github.com/internetee/eis_billing_system)\n\nCentralized invoice management and payment processing system for Estonian Internet Services infrastructure. Provides invoice generation, payment processing, and integration with external payment systems for Registry, Auction, and EEID services.\n\n## Table of Contents\n\n- [System Overview](#system-overview)\n- [Technology Stack](#technology-stack)\n- [Architecture](#architecture)\n- [Requirements](#requirements)\n- [Installation and Setup](#installation-and-setup)\n- [Configuration](#configuration)\n- [Integrations](#integrations)\n- [API Documentation](#api-documentation)\n- [Invoice Types](#invoice-types)\n- [Deployment](#deployment)\n- [Testing](#testing)\n- [Development](#development)\n\n## System Overview\n\nEIS Billing System is the central component for billing management in the Estonian Internet Services infrastructure. The system processes requests from three main services:\n\n- **Registry** - domain management system\n- **Auction** - domain auction system\n- **EEID** - unified identity system\n\n### Core Features\n\n- Invoice and payment link generation\n- Payment processing via EveryPay\n- Refunds for auction deposits\n- Bulk payments for auction\n- Integration with Directo accounting system\n- E-invoice delivery via Omniva\n- Automatic transaction detection via LHV Connect\n- Web interface for administrators\n\n## Technology Stack\n\n### Backend\n- **Ruby** 3.4.5\n- **Rails** 7.2.2.0\n- **PostgreSQL** (primary database)\n- **Redis** (caching and background jobs)\n\n### Frontend\n- **Hotwire** (Turbo + Stimulus)\n- **Importmap** (JS dependency management)\n- **Sprockets** (asset pipeline)\n\n### External Dependencies\n- **Puma** - application server\n- **Sidekiq/ActiveJob** - background jobs\n- **PDFKit** + wkhtmltopdf - PDF generation\n- **PgSearch** - full-text search\n- **Pagy** - pagination\n\n## Architecture\n\n### Service Communication\n\n```\n┌─────────────┐     ┌──────────────┐     ┌─────────────┐\n│   Registry  │────▶│              │◀────│   Auction   │\n└─────────────┘     │              │     └─────────────┘\n                    │  EIS Billing │\n┌─────────────┐     │   System     │     ┌─────────────┐\n│    EEID     │────▶│              │────▶│  EveryPay   │\n└─────────────┘     └──────┬───────┘     └─────────────┘\n                           │\n                    ┌──────┴──────┐\n                    │             │\n                ┌───▼───┐    ┌────▼────┐    ┌───────────┐\n                │Directo│    │ Omniva  │    │LHV Connect│\n                └───────┘    └─────────┘    └───────────┘\n```\n\n### Communication\n- **REST API** - all service-to-service interactions\n- **Webhooks** - callbacks from EveryPay for payment status updates\n- **Background Jobs** - asynchronous processing for integrations\n\n## Requirements\n\n### System Requirements\n- Ruby 3.4.5\n- PostgreSQL 12+\n- Redis 5+\n- Docker \u0026 Docker Compose (for development)\n\n### For PDF Generation\n- wkhtmltopdf\n\n## Installation and Setup\n\n### Docker (recommended for development)\n\n1. Clone the repository:\n```bash\ngit clone \u003crepository-url\u003e\ncd eis_billing_system\n```\n\n2. Copy configuration examples:\n```bash\ncp config/application.yml.sample config/application.yml\n```\n\n3. Start the application via Docker:\n```bash\ndocker-compose up\n```\n\n4. Create the database:\n```bash\ndocker-compose exec app rails db:create db:migrate\n```\n\n### Local Installation (alternative)\n\n1. Install dependencies:\n```bash\nbundle install\n```\n\n2. Setup the database:\n```bash\nrails db:create\nrails db:migrate\nrails db:seed\n```\n\n3. Start the server:\n```bash\nrails server\n```\n\n## Configuration\n\n### Main Settings (config/application.yml)\n\n#### Base Service URLs\n```yaml\nbase_registry: \"http://registry:3000\"\nbase_auction: \"http://auction_center:3000\"\nbase_eeid: \"http://eeid:3000\"\n\n# Callback URLs for payment status updates\nregistry_update_payment_url: \"http://registry:3000/eis_billing/payment_status\"\nauction_update_payment_url: \"http://auction_center:3000/eis_billing/payment_status\"\neeid_update_payment_url: \"http://eeid:3000/eis_billing/payment_status\"\n```\n\n#### EveryPay Configuration\n```yaml\neverypay_key: \"your_api_key\"\neverypay_base: \"https://igw-demo.every-pay.com/api/v4\"\nlinkpay_prefix: \"https://igw-demo.every-pay.com/lp\"\nlinkpay_token: \"your_linkpay_token\"\napi_username: \"your_username\"\naccount_name: \"your_account\"\n```\n\n#### Directo Configuration\n```yaml\ndirecto_invoice_url: \"https://your-directo-instance.com/api/invoice.asp\"\n```\n\n#### LHV Connect Configuration\n```yaml\nlhv_keystore: \"./eestiInternetiSa/eestiInternetiSa.p12\"\nlhv_keystore_password: \"your_password\"\nlhv_keystore_alias: \"your_alias\"\nlhv_ca_file: \"path/to/ca/file\" # development only\nlhv_dev_mode: \"true\" # for development\n```\n\n#### E-Invoice (Omniva) Configuration\n```yaml\ne_invoice_provider_test_mode: \"true\" # for testing\n```\n\n#### EEID (Authentication)\n```yaml\ndevelopment:\n  allowed_base_urls: \"https://registry.test, https://auction_center.test, https://eeid.test\"\n  tara_redirect_uri: \"https://eis_billing_system.test/auth/tara/callback\"\n  tara_identifier: \"your_client_id\"\n  tara_secret: \"your_client_secret\"\n```\n\n#### Deposit Number Range\n```yaml\ndeposit_min_num: \"10001\"\ndeposit_max_num: \"14001\"\n```\n\n### Email Configuration\n```yaml\nsmtp_address: \"smtp.example.com\"\nsmtp_port: \"587\"\nsmtp_user_name: \"your_username\"\nsmtp_password: \"your_password\"\nsmtp_domain: \"example.com\"\nsmtp_authentication: \"plain\"\naction_mailer_default_from: \"no-reply@example.com\"\n```\n\n## Integrations\n\n### 1. EveryPay\n\n**Purpose**: Online payment processing\n\n**Functionality**:\n- **Linkpay** - payment link generation for embedding in PDF/Email\n- **One-off payments** - single payments for account top-ups and invoice payments\n- **Refunds** - refund processing for auction deposits\n- **Webhooks** - payment status update notifications\n\n**Endpoints**:\n- `POST /api/v1/invoice_generator/invoice_generator` - create linkpay link\n- `POST /api/v1/invoice_generator/oneoff` - create one-off payment\n- `GET /api/v1/callback_handler/callback` - webhook for EveryPay updates\n\n**Webhook Events** (event_name):\n- `status_updated` - payment status updated\n- `refunded` - refund completed\n- `voided` - payment cancelled\n- `chargebacked` - chargeback initiated\n- `abandoned` - payment failed\n\n### 2. Directo\n\n**Purpose**: Accounting system integration\n\n**Functionality**:\n- Invoice forwarding to accounting\n- Payment data synchronization\n- Background processing via `DirectoInvoiceForwardJob`\n\n**Endpoints**:\n- `POST /api/v1/directo/directo` - forward invoice to Directo\n\n**Data Schema**:\nInvoices contain `in_directo` (boolean) and `directo_data` (jsonb) fields for synchronization status tracking.\n\n### 3. E-Invoice (Omniva)\n\n**Purpose**: Electronic invoice delivery\n\n**Functionality**:\n- E-invoice delivery via Omniva operator\n- Background processing via `SendEInvoiceJob` and `EInvoiceResponseSenderJob`\n- Delivery time tracking in `sent_at_omniva` field\n\n**Endpoints**:\n- `POST /api/v1/e_invoice/e_invoice` - send e-invoice\n\n### 4. LHV Connect\n\n**Purpose**: Automatic bank transaction detection\n\n**Functionality**:\n- Automatic matching of incoming payments with invoices\n- Processing via `PaymentLhvConnectJob`\n- Certificate-based secure connection\n\n**Technical Details**:\n- Keystore: PKCS12 format (.p12)\n- CA certificate support for validation\n- Dev mode for testing without real transactions\n\n### 5. EEID Integration\n\n**Purpose**: Administrator authentication\n\n**Functionality**:\n- OAuth2 authentication via EEID (wrapper over TARA)\n- User session management\n- White-list access codes\n\n**Endpoints**:\n- `GET /auth/tara/callback` - OAuth callback\n- `DELETE /logout` - session termination\n\n**Models**:\n- `User` - system administrators\n- `AppSession` - active sessions\n- `WhiteCode` - access codes\n\n## API Documentation\n\n### Online Documentation\n\n📚 **[View API Documentation on GitHub Pages](https://internetee.github.io/eis_billing_system/)**\n\nThe complete API documentation is automatically generated and published to GitHub Pages on every push to the main branch.\n\n### Interactive Documentation (Local)\n\nThe system uses [Apipie](https://github.com/Apipie/apipie-rails) for interactive API documentation generation.\n\n**Local Access**: `http://localhost:3000/apipie` (when running the application)\n\n**Authentication** (for local documentation viewing):\n```yaml\napipie_login: test\napipie_password: test\n```\n\n### Generating Static Documentation\n\nTo generate static HTML documentation locally:\n\n```bash\nbundle exec rake apipie:static\n```\n\nGenerated files will be available in `public/apipie/`\n\n### Main API Endpoints\n\n#### Invoice Generation\n\n**POST /api/v1/invoice_generator/invoice_generator**\n\nCreate linkpay link for payment\n\n```json\n{\n  \"transaction_amount\": \"100.00\",\n  \"reference_number\": \"RF123456\",\n  \"order_reference\": \"Account #12345\",\n  \"customer_name\": \"John Doe\",\n  \"customer_email\": \"john@example.com\",\n  \"custom_field_1\": \"Domain renewal\",\n  \"custom_field2\": \"registry\",\n  \"linkpay_token\": \"generated_token\",\n  \"invoice_number\": \"INV-2025-001\"\n}\n```\n\n**Response**:\n```json\n{\n  \"message\": \"Link created\",\n  \"everypay_link\": \"https://pay.every-pay.eu/...\"\n}\n```\n\n#### One-off Payment\n\n**POST /api/v1/invoice_generator/oneoff**\n\nCreate a one-off payment\n\n```json\n{\n  \"transaction_amount\": \"50.00\",\n  \"customer_url\": \"https://registry.test/payment/callback\",\n  \"description\": \"Account top-up\",\n  \"custom_field2\": \"registry\"\n}\n```\n\n#### Bulk Payment (Auction only)\n\n**POST /api/v1/invoice_generator/bulk_payment**\n\n```json\n{\n  \"transaction_amount\": \"500.00\",\n  \"customer_url\": \"https://auction.test/payment/callback\",\n  \"description\": \"Multiple domain deposits\",\n  \"custom_field2\": \"auction\"\n}\n```\n\n#### Refund\n\n**POST /api/v1/refund/auction**\n\n```json\n{\n  \"params\": {\n    \"invoice_number\": \"INV-2025-001\"\n  }\n}\n```\n\n#### Invoice Status\n\n**POST /api/v1/invoice_generator/invoice_status**\n\nGet invoice status by number\n\n#### Data Import\n\n**POST /api/v1/import_data/invoice_data**\n\nImport invoice data from external systems\n\n**POST /api/v1/import_data/reference_data**\n\nImport reference data (reference numbers)\n\n#### Synchronization\n\n**PATCH /api/v1/invoice/invoice_synchronize**\n\nSynchronize invoice status with external system\n\n## Invoice Types\n\n### 1. Regular\n\n**Purpose**: Standard payments\n\n**Usage**:\n- Account top-ups\n- Invoice payments\n- Typically used with one-off payment\n\n**Characteristics**:\n- `affiliation: :regular`\n- Does not support refunds\n- Used by all services (Registry, Auction, EEID)\n\n### 2. Auction Deposit\n\n**Purpose**: Auction participation deposits\n\n**Usage**:\n- Fund blocking for auction participation\n- Refunds for unsuccessful bidders\n\n**Characteristics**:\n- `affiliation: :auction_deposit`\n- **Supports refunds** via EveryPay\n- Used only by Auction service\n- Special invoice number range (10001-14001)\n\n**Refund process**:\n```ruby\n# Check if refund is possible\ninvoice.auction_deposit_prepayment? # =\u003e true\n\n# API for refund\nPOST /api/v1/refund/auction\n{\n  \"params\": {\n    \"invoice_number\": \"10523\"\n  }\n}\n```\n\n### 3. Linkpay\n\n**Purpose**: Embeddable payment links\n\n**Usage**:\n- Links for PDF invoices\n- Links in email notifications\n- Payment via link with payment method selection\n\n**Characteristics**:\n- `affiliation: :linkpay`\n- Stores additional information in `linkpay_info` (jsonb)\n- Used by all services\n\n**Additional data**:\n```json\n{\n  \"linkpay_info\": {\n    \"link\": \"https://pay.every-pay.eu/...\",\n    \"token\": \"...\",\n    \"created_at\": \"2025-01-01T12:00:00Z\"\n  }\n}\n```\n\n## Deployment\n\n### Docker Environments\n\n#### Development\n```bash\ndocker-compose up\n```\n\n#### Staging\n```bash\ndocker-compose -f docker-compose.staging.yml up\n```\n\n### AWS Production Deployment\n\nSystem is deployed on AWS using Docker.\n\n**Deployment process**:\n\n1. **Capistrano** - deployment automation\n2. **GitHub Actions** - CI/CD pipeline\n3. **rbenv** - Ruby version management\n4. **Passenger** - application server in production\n\n**Running deployment**:\n```bash\n# Staging\ncap staging deploy\n\n# Production\ncap production deploy\n```\n\n### Environments\n\nThe system supports three environments:\n- **development** - local development (Docker)\n- **staging** - testing environment (AWS + Docker)\n- **production** - production environment (AWS + Docker)\n\n### Environment Variables\n\nEnsure these are configured in each environment:\n- Database (DATABASE_URL)\n- Redis (REDIS_URL)\n- Secret keys (SECRET_KEY_BASE)\n- External service API keys\n- SMTP settings\n\n## Testing\n\n### Running Tests\n\n```bash\n# All tests\nbundle exec rspec\n\n# Specific file\nbundle exec rspec spec/models/invoice_spec.rb\n\n# Specific test\nbundle exec rspec spec/models/invoice_spec.rb:15\n```\n\n### Test Coverage\n\nProject uses SimpleCov for test coverage measurement.\n\n```bash\n# Run tests with coverage report\nCOVERAGE=true bundle exec rspec\n\n# Report available in coverage/index.html\nopen coverage/index.html\n```\n\n### Testing Tools\n\n- **RSpec** - testing framework\n- **FactoryBot** - test data factories\n- **Faker** - test data generation\n- **WebMock** - HTTP request mocking\n- **Selenium/Webdriver** - integration tests\n- **DatabaseCleaner** - database cleanup between tests\n\n### Linters and Security Checks\n\n```bash\n# RuboCop - code style\nbundle exec rubocop\n\n# Brakeman - security scanning\nbundle exec brakeman\n\n# Bundle Audit - dependency vulnerabilities\nbundle exec bundle-audit check --update\n```\n\n## Development\n\n### Project Structure\n\n```\napp/\n├── controllers/\n│   ├── api/v1/              # API endpoints\n│   │   ├── invoice_generator/\n│   │   ├── callback_handler/\n│   │   ├── e_invoice/\n│   │   ├── directo/\n│   │   └── refund/\n│   ├── dashboards/          # Admin UI\n│   └── invoice_details/     # Invoice details\n├── models/\n│   ├── invoice.rb           # Main invoice model\n│   ├── reference.rb         # Reference numbers\n│   ├── user.rb              # Administrators\n│   └── white_code.rb        # Access codes\n├── jobs/\n│   ├── directo_invoice_forward_job.rb\n│   ├── send_e_invoice_job.rb\n│   ├── payment_lhv_connect_job.rb\n│   └── save_invoice_data_job.rb\n├── contracts/               # Parameter validation (dry-validation)\n├── mailers/                 # Email notifications\n└── services/                # Business logic\n```\n\n### Database Schema\n\n**Invoices** (main table):\n- `invoice_number` - unique invoice number\n- `initiator` - source (registry/auction/eeid/billing_system)\n- `payment_reference` - EveryPay reference\n- `transaction_amount` - payment amount\n- `status` - status (unpaid/paid/cancelled/failed/refunded/overdue)\n- `affiliation` - type (regular/auction_deposit/linkpay)\n- `everypay_response` - EveryPay response (jsonb)\n- `directo_data` - Directo data (jsonb)\n- `linkpay_info` - linkpay data (jsonb)\n- `in_directo` - sent to Directo flag\n- `transaction_time` - transaction timestamp\n- `sent_at_omniva` - Omniva delivery timestamp\n\n**References**:\n- `reference_number` - payment reference\n- `initiator` - source\n- `owner` - owner\n- `email` - owner email\n\n### Background Jobs\n\nAll integrations with external services are processed asynchronously:\n\n```ruby\n# Directo\nDirectoInvoiceForwardJob.perform_later(invoice_id)\n\n# E-Invoice\nSendEInvoiceJob.perform_later(invoice_id)\n\n# LHV Connect\nPaymentLhvConnectJob.perform_later\n\n# Data saving\nSaveInvoiceDataJob.perform_later(invoice_data)\nSaveReferenceDataJob.perform_later(reference_data)\n```\n\n### Useful Commands\n\n```bash\n# Rails console\nrails console\n\n# Database console\nrails dbconsole\n\n# Routes\nrails routes | grep invoice\n\n# Clear logs\nrails log:clear\n\n# Migration status\nrails db:migrate:status\n```\n\n### Logging\n\nLogs are available in:\n- `log/development.log`\n- `log/staging.log`\n- `log/production.log`\n\n### Debugging\n\n```ruby\n# Use byebug in code\ndef some_method\n  byebug  # debugger will stop here\n  # your code\nend\n```\n\n## Support\n\n### Code Quality Monitoring\n\n- **Maintainability**: [![Maintainability](https://qlty.sh/gh/internetee/projects/eis_billing_system/maintainability.svg)](https://qlty.sh/gh/internetee/projects/eis_billing_system)\n- **Code Coverage**: [![Code Coverage](https://qlty.sh/gh/internetee/projects/eis_billing_system/coverage.svg)](https://qlty.sh/gh/internetee/projects/eis_billing_system)\n\n### CI/CD\n\nGitHub Actions are configured for:\n- Automated test runs\n- Code style checks (RuboCop)\n- Security scanning (Brakeman)\n- Dependency checks (Bundle Audit)\n\n### Renovate\n\nAutomated dependency updates are configured via Renovate (see `renovate.json`)\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Finternetee%2Feis_billing_system","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Finternetee%2Feis_billing_system","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Finternetee%2Feis_billing_system/lists"}