Bexy for Craft CMS

Craft Commerce 5 · Switzerland

The half that happens after the push

Getting an order into bexio is the easy part. Bexy does the rest: it posts the payment so the invoice does not sit open, pulls bexio's status back into Commerce, checks the total before it sends, and keeps a connection that does not quietly expire after 60 days.

Bexy

See it before you send it

The preview runs the same builder as the real push, so what it prints is byte-for-byte what bexio receives. There is one place in the code where a Commerce order becomes a bexio document, which is what makes that guarantee true rather than aspirational.

bash
$ php craft bexy/sync/preview 1042

  contact      Bühler AG · #4471 (matched on email)
  positions    3 × KbPositionCustom, 1 × KbPositionArticle
  shipping     CHF 12.00   MWST 8.1%   → 3400
  discount     CHF 25.00   magnitude, is_percentual: false
  mwst_type    0  (prices include tax, read from Commerce)

  document     CHF 486.35
  order        CHF 486.35
  ✓ totals agree — nothing to round

  Nothing was sent. Run bexy/sync/order 1042 to send it.

What it actually does

Six things the alternative does not.

A connection that stays connected

OAuth 2.0 with PKCE and rotating refresh tokens, not a personal access token that bexio expires 60 days after it was made, silently.

  • PATs are supported too, for a trial company
  • The rotated refresh token is stored every time, or the next refresh fails
  • Tokens are encrypted with Craft's security key

Payments, not just invoices

Every successful Commerce charge is posted against the bexio invoice, so paid orders do not sit open in your books waiting for somebody to tick them off.

  • Unique on the Commerce transaction, so a charge is never posted twice
  • Falls back to the default bank account
  • Invoices only — bexio orders cannot take a payment

The totals are checked first

Bexy works out what bexio will make the document come to, compares it with Commerce, and catches the disagreement here rather than during a VAT return.

  • A cent-sized gap gets an untaxed rounding position
  • A larger one is refused and explained
  • The upper bound is the point: a mis-mapped 7.7% charge must not be closed by a line called "Rounding"

bexio's verdict comes back

Reconciliation pulls the document's status out of bexio and moves the Commerce order to match, so an invoice marked paid by your accountant is not news to your shop.

  • Bexy moves the order status and nothing else
  • It never fabricates a Commerce transaction to make an order look paid
  • Paid and cancelled documents drop out of the window automatically

Swiss VAT, mapped properly

Each Commerce tax category maps to a bexio tax and a revenue account. mwst_type is read off the order, so a rate flagged "included in price" makes the prices gross without you saying so twice.

  • Only bexio's active sales taxes are offered — it rejects anything else
  • Shipping gets its own tax and account
  • An unmapped category is a warning on the document, not a silent default

It cannot push twice

api_reference is written on every document and searched for before anything is created, on top of a local table that is unique on the order.

  • Push the same order twice and the second push adopts the first document
  • A document created in bexio before Bexy knew about it is adopted too
  • Refunds cancel where bexio permits it and are flagged where it does not — never a faked negative payment

Bexy in the control panel

The settings screen from a Craft 5 install — the connection to bexio, what a paid order becomes, and when it gets sent.

The Bexy settings screen in the Craft control panel, showing the bexio connection fields, the document type a paid order becomes, and when it is sent

Screenshot from a live install, not a mockup.

Questions

Stop reconciling by hand

$99, once. Install it, connect a bexio trial company, and push one order to see the whole thing work.