Skip to content

Feature/reserve invoice bank transfer - #2972

Open
OlegPhenomenon wants to merge 3 commits into
masterfrom
feature/reserve-invoice-bank-transfer
Open

OlegPhenomenon wants to merge 3 commits into
masterfrom
feature/reserve-invoice-bank-transfer

Conversation

@OlegPhenomenon

@OlegPhenomenon OlegPhenomenon commented Oct 19, 2026 •

Copy link
Copy Markdown
Contributor

Business Registry users could pay for a long-term domain reservation only by card (EveryPay), because the invoice PDF was available only after payment and had no reference number. This PR lets them pay by direct bank transfer to the EIS IBAN. The invoice is available before payment, and the bank payment is matched by reference number in EIS billing (LHV Connect).

Billing side: internetee/eis_billing_system#268
API docs: internetee/domain-reservation-api-docs#7

Invoice

  • Each ReserveDomainInvoice gets its own reference number (generated by billing with initiator business_registry, owner = user_unique_id) and a due date (Setting.days_to_keep_invoices_active, as for registrar invoices). Both are stored (migration) and sent to billing with the invoice
  • POST /api/v1/business_registry/long_reserve_domains returns reference_no and due_date
  • GET /api/v1/business_registry/reserved_domains_invoice_pdf returns the PDF for pending invoices too; cancelled/failed invoices return 422
  • The PDF shows invoice number, invoice date, due date (Maksetähtaeg), reference number (Viitenumber) and payment status. Unpaid: "Tasumata", row status "Ootab tasumist", "Tasuda" instead of "Tasutud summa". Old invoices without reference number/due date still render
  • Unpaid PDF contains a notice (ET/EN): issuing the invoice does not guarantee the reservation, reservation is first-come-first-served, and if it is no longer possible when the payment arrives the invoice is cancelled and the payment refunded

Bank payment

  • New PUT /eis_billing/business_registry_payment (JWT from billing, same as other eis_billing endpoints). Looks up the invoice by reference_number:
    • 200 Payment processed: domains reserved, invoice paid, pending invoices with intersecting domains cancelled
    • 200 Invoice already paid: nothing done
    • 404 Invoice not found: unknown or missing reference number
    • 422 Invoice is cancelled: invoice was cancelled before (e.g. someone else paid for the same domain first)
    • 422 Failed to reserve domains: some domain is no longer available, invoice is cancelled
      Billing cancels its invoice on 422 and asks admin to refund the payment
  • Reservation completion (availability check, reserve, mark paid, cancel intersecting) is shared by the EveryPay callback and the bank payment endpoint and runs under a row lock

Fixes

  • The EveryPay callback passed the invoice record instead of domain names to cancel_intersecting_invoices, so the query became ARRAY[<id>] and intersecting invoices were never cancelled
  • test/integration/eis_billing/invoices_test.rb replaced EisBilling::BaseController with a stub, which disabled JWT checks for every billing controller loaded after it in the test run

Not changed

  • EveryPay: if the domains are taken when the card payment comes in, the callback still returns 422 and the invoice is not cancelled
  • Refunds are manual; admin gets an email from billing

Rollout

  1. Run migrations
  2. Deploy together with eis_billing_system#268 and set business_registry_payment_url there
  3. Check that Setting.registry_iban (printed on the PDF) is the account LHV Connect reads in billing (registry_bank_account_iban_lhv), otherwise transfers will not be found

- Generate a reference number and due date for each reservation invoice
- Render invoice PDF before payment with reference number, due date and amount due
- Add JWT-protected PUT /eis_billing/business_registry_payment for billing to confirm bank payments
- Share reservation completion between EveryPay callback and bank payment
- Fix cancelling intersecting invoices after paid callback (record was bound instead of domain names)
- Stop invoices_test from replacing EisBilling::BaseController for all tests
Reservation is first-come-first-served: unpaid invoice PDF says the invoice
does not guarantee the reservation, and a bank payment for domains that are
no longer available cancels the invoice so billing can refund it.
@github-actions

Copy link
Copy Markdown
Contributor

🚀 Deploy Complete!

Property Value
App registry
Slot 1
URL https://registry1-dev.cloud.tld.ee
Namespace registry1-dev

(Environment ready for testing)

2 similar comments
@github-actions

Copy link
Copy Markdown
Contributor

🚀 Deploy Complete!

Property Value
App registry
Slot 1
URL https://registry1-dev.cloud.tld.ee
Namespace registry1-dev

(Environment ready for testing)

@github-actions

Copy link
Copy Markdown
Contributor

🚀 Deploy Complete!

Property Value
App registry
Slot 1
URL https://registry1-dev.cloud.tld.ee
Namespace registry1-dev

(Environment ready for testing)

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants