Skip to content

Developer notes

Technical reference for developers who customize QuickBooks Online Sync.

Item Value
Add-on id kv_quickbooks
Function prefix fn_kv_quickbooks_
Language variables kv_quickbooks.*
CSS scope .kv-quickbooks
PHP namespace Tygh\Addons\KvQuickbooks
Preset accounting (generated by kv new --kind integration)
Class Role
Client\BaseClient HTTP (cURL, TLS verification, timeouts), JSON, Retry-After, error mapping, masked logging
Client\Api OAuth 2.0 (authorization code, rolling refresh token under a database lock) and the Accounting API v3 calls
Client Client per company, the connection test
Sync Customer, item, invoice / sales receipt, payment, credit memo / refund receipt sync; line and tax building; the map table
Accounts, Secret Credentials (test and live) sealed with AES-256-GCM; one account per store owner or per vendor
Config, Access Settings, owner mode, who may see and manage what
Queue, Jobs, JobException Job queue: back-off 5 min / 15 min / 1 h / 3 h / 12 h, per-job isolation, overlap lock; handlers in Jobs::handle(), recurring work in Jobs::schedule()
Log Event log with masking, filters, CSV, retention
Table Purpose
?:kv_quickbooks_accounts Credentials per company (secrets sealed), last connection check, token cache, realm id, mapping
?:kv_quickbooks_log Log
?:kv_quickbooks_jobs Queue
?:kv_quickbooks_map What was sent to QuickBooks (QuickBooks ids, payload hash)

PHP hook change_order_status_post (queues the invoice, payment and refund jobs). Template hooks: only the License card in the add-on settings. Nothing is printed on the storefront, so full page cache and Varnish are unaffected.

The base URL can be overridden for tests in config.local.php (development only):

$config['kv_quickbooks_base_url'] = 'http://127.0.0.1:11947';

node tests/mock-server/server.js 11947 starts a local stand-in of the Intuit OAuth service and the Accounting API; node tests/e2e/e2e.mjs runs the end-to-end test (real orders, OAuth flow, refunds, sales receipt mode, non-US tax) against it; php tests/unit.php runs the unit tests. The mock proves the add-on against its own reading of the API, not against the real service.

Admin templates live in design/backend/templates/addons/kv_quickbooks/. Do not edit them in a store; they are replaced on update.

  • API sources: Intuit’s published OAuth client (github.com/intuit/oauth-jsclient: endpoints, Basic authentication, realmId) and the data classes of Intuit’s official QuickBooks V3 PHP SDK (entity and field names). developer.intuit.com renders only in a browser app, so the rate limit (500 requests a minute per company), the access token lifetime (1 hour), the refresh token lifetime (100 days, rolling), the minorversion and requestid parameters and the Fault codes (6240 duplicate name, 6140 duplicate document number, 5010 stale SyncToken) come from Intuit’s developer documentation as published at the time of writing: check them against developer.intuit.com before a release.
  • Entities: Customer (found by PrimaryEmailAddr with the query language; updates are sparse and need the SyncToken), Item (found by name; created as Service with an IncomeAccountRef), Invoice + Payment (Line.LinkedTxn), SalesReceipt, CreditMemo (applied with a zero-total Payment that links the invoice and the credit memo), RefundReceipt (DepositToAccountRef is the account the money leaves).
  • Tax: US companies (CompanyInfo.Country) get TaxCodeRef TAX/NON per line and TxnTaxDetail.TotalTax from the order; other countries get tax code ids and GlobalTaxCalculation TaxInclusive / TaxExcluded.
  • Refresh tokens roll. Accounts::locked() serialises the refresh with GET_LOCK, and a second process re-reads the account after the lock, so cron and an admin click never use the same token twice.
  • Request ids (max 50 characters): kv-inv-<order>-<hash>, kv-sr-<order>-<hash>, kv-pay-<order>, kv-cm-<order>, kv-rr-<order>, kv-al-<order>, kv-cu-<hash>-<id>, kv-item-<hash>.
  • Map table entities: customer, invoice (the invoice or sales receipt), payment, credit (credit memo or refund receipt), refund (the application or the refund), item.
  • CS-Cart stores taxes either per line (applies P_) or per order (subtotal calculation); Sync::allocate() handles both.