Skip to Content

Maksekeskus payment provider

Accept Estonian bank links and card payments via Maksekeskus / MakeCommerce inside Odoo's native payment framework.

Current provider state: disabled — follow the setup steps below to enable it.

What this addon does

  • Adds Maksekeskus as a redirect-flow payment provider in Settings → Payment Providers.
  • Sends customers to Maksekeskus's hosted checkout (bank link or card) and receives them back signed.
  • Verifies the MAC signature on every callback before changing any transaction state.
  • Re-fetches the authoritative payment status from Maksekeskus's API as defense in depth — the customer's browser cannot lie about whether they paid.

Refunds, tokenisation and manual capture are out of scope for v1. The framework's feature flags are left off; add them only when needed.

How the payment flow works

  1. Customer clicks Pay on an invoice, order, or payment link.
  2. Odoo creates a payment.transaction and calls POST /v1/transactions on the Maksekeskus API.
  3. Maksekeskus returns a hosted-checkout URL; the customer's browser is auto-submitted to it.
  4. The customer pays at the bank or with a card.
  5. Maksekeskus sends two messages: a browser return (/payment/maksekeskus/return) and a server-to-server notification (/payment/maksekeskus/webhook). Both carry json + mac.
  6. Odoo verifies the MAC, re-fetches the transaction status from Maksekeskus, and updates the payment.transaction state (done, cancel, pending, …).

Setup — five steps

1. Get a Maksekeskus account

Sign up at merchant.maksekeskus.ee for production credentials, or use the shared sandbox credentials for development.

2. Copy three keys

From the merchant portal, copy:

  • Shop ID (UUID)
  • Secret Key — signs MAC + HTTP Basic password
  • Publishable Key — currently reserved for future use
3. Open the provider form

Go to Settings → Payment Providers → Maksekeskus .

Requires the Administration / Settings group.

4. Enter the credentials

Paste the three keys into the Maksekeskus credentials group. The Shop ID and Secret Key are required to enable the provider; the field group becomes visible only when the provider's code is maksekeskus.

5. Switch state and verify

Choose one:

  • Test mode — uses https://api.test.maksekeskus.ee. Safe to drive a few sandbox payments end-to-end. Use the shared test cards (e.g. Visa 4505131234000011).
  • Enabled — uses https://api.maksekeskus.ee. Real money. Only flip after a successful test-mode round-trip.

Before going live: set web.base.url (in ir.config_parameter) to the public HTTPS URL of this Odoo instance, otherwise the return and notification URLs sent to Maksekeskus will point at the wrong host.

Use case examples

A. Pay a single invoice

Open a confirmed customer invoice, click Send & Print with the portal link, or share the invoice's customer-portal URL. The portal's Pay button creates a transaction via the framework, redirects the customer to Maksekeskus, and lands them on /payment/confirmation when done.

B. Generate a one-off payment link

On any record that supports payment links (sale order, invoice, etc.), use Action → Generate Payment Link. The wizard produces a URL like /payment/pay?amount=…¤cy_id=…&partner_id=…&access_token=…. Share it with the customer; they click and pay.

C. Website checkout

With website_sale installed, Maksekeskus appears alongside other configured providers in the cart's Pay step. The customer picks Maksekeskus, gets redirected, pays, and lands on the order's confirmation page.

D. Subscription renewals (with OCA contract)

OCA's contract module generates invoices on a schedule; each invoice can be paid via Maksekeskus through the customer portal. Combine with Odoo's email reminder cron for an automated billing loop.

E. Refund a customer (full or partial)

Open the original payment.transaction in state done, click Refund, enter an amount (defaults to full). A refund-child transaction is created with a negative amount and a SETTLED state once the gateway confirms. Sandbox returns SETTLED synchronously; production typically settles on the next banking day. Status PART_REFUNDED on the parent transaction is informational — the framework tracks aggregate refunds via the child transactions.

F. Card-on-file recurring billing

Customers can save their card during a first payment: the Maksekeskus card iframe shows a Recurring consent checkbox; ticking it stores a token after the payment completes. Subsequent merchant-initiated charges use the saved token via a server-to-server POST /v1/transactions/{id}/payments — no customer redirect, no 3DS step. Combine with OCA contract for fully automated subscription billing.

Shipping+ (carrier integration)

If the merchant also uses Maksekeskus Shipping+, the addon ships a delivery.carrier integration covering rate quotes, label generation, and tracking links across Omniva, DPD, Venipak, Unisend and SmartPosti.

  1. Ask Maksekeskus support to activate Shipping+ on your shop (paid service: €1.99 / shipment with Maksekeskus rates, or €5/month + €0.05/shipment with merchant carrier contracts).
  2. In Odoo, open Inventory → Configuration → Shipping Methods and create a new method with Provider = Maksekeskus Shipping+.
  3. Link the new method to the same Maksekeskus payment provider record — it reuses the Shop ID + Secret Key and the test/live state.
  4. At checkout the cart fetches a rate via POST /rates; at delivery confirmation the addon calls POST /shipments to generate a label and tracking number, then shows the tracking link in the picking's chatter.

The shipping API lives at shipping[.test].makecommerce.net — a different host from the payment API. The shared sandbox shop does NOT have Shipping+ activated; first real-bytes validation happens after the merchant requests activation.

Test mode — shared sandbox credentials

Maksekeskus publishes shared test credentials at makecommerce.net/test-environment. Safe to paste into state=test on the provider form — they only work against api.test.maksekeskus.ee.

Field Value
Shop IDf7741ab2-7445-45f9-9af4-0d0408ef1e4c
Secret KeypfOsGD9o…IWAOcBeqt (full value on the makecommerce.net page)
Test Visa card4505131234000011 · 06/28 · CVC 123
Test MasterCard5191631234000016 · 06/28 · CVC 123
Decline testUse either card with amount 99.99 EUR

Troubleshooting

Tried to flip the provider to Test or Enabled without filling both credential fields. Enter them and try again — the framework will not let the state change otherwise.

The Shop ID / Secret Key combination is wrong, or the provider state (test vs enabled) does not match the environment those keys belong to. Sandbox keys only work against api.test.maksekeskus.ee; live keys only against api.maksekeskus.ee.

Usually means the redirect form submitted without the ?trx=… query parameter. The addon's redirect template echoes query params as hidden inputs to avoid this. If you've customised the template, ensure those hidden inputs are preserved.

Generic framework message that shows when /payment/status cannot find the transaction in the session. Happens when a transaction was created via API / ORM scripting rather than the framework's payment form. Real customer journeys (Pay button on invoice / order / website checkout) set the session key correctly and land on /payment/confirmation with the right message.

Maksekeskus retries the webhook exactly once after 10 minutes if your server does not return 2xx within 30 seconds. Confirm: (a) web.base.url points to a public HTTPS URL Maksekeskus can reach, (b) reverse proxy / firewall allows POST to /payment/maksekeskus/webhook with no CSRF check, (c) Odoo logs show the inbound POST. The browser return path covers most state transitions even when the webhook is slow.

Security model — in one paragraph

Every callback (return and webhook) is signed by Maksekeskus with UPPERCASE(HEX(SHA-512(json + secret))). The addon verifies that MAC on the byte-for-byte raw JSON before any state mutation, with a constant-time comparison. If verification passes, the addon then re-fetches the authoritative transaction status from Maksekeskus's API over HTTPS+Basic auth — the customer's browser never decides the final state. Amount and currency are re-validated against the stored Odoo transaction; mismatches drive the transaction to error. csrf=False is required on the public callback routes (external caller cannot send an Odoo CSRF token) and is justified exclusively by these checks.