Skip to content

Developer notes

Technical reference for developers who customize Vipps MobilePay Payments. Every endpoint, header, field and state with its official source is listed in Conformance.

Item Value
Add-on id kv_vipps_mobilepay
Function prefix fn_kv_vipps_mobilepay_
Language variables kv_vipps_mobilepay.*
CSS scope .kv-vipps-mobilepay
PHP namespace Tygh\Addons\KvVippsMobilepay
Payment processor Vipps MobilePay (script kv_vipps_mobilepay.php, registered on install, removed on uninstall)
Dispatches backend kv_vipps_mobilepay.manage / connection / test_connection / register_webhook / log / log_csv / jobs / run_now / job_retry / job_discard / capture / refund / release / sync / cron; frontend kv_vipps_mobilepay.webhook, kv_vipps_mobilepay.cron; return payment_notification.return&payment=kv_vipps_mobilepay
Class Role
Client\BaseClient HTTP (cURL, TLS verification, timeouts), JSON, access token cache (sealed), error mapping, masked logging
Client\Api The ePayment, Webhooks and Access Token calls: createPayment, getPayment, capture, refund, cancel, webhooks, registerWebhook, deleteWebhook, ping; sends the common headers and the four Vipps-System-* headers (cscart, the CS-Cart version, plugin name kaviolabs-cscart-vipps, the add-on version)
Client Client per account, the connection test
Accounts, Secret Credentials per mode, sealed with AES-256-GCM (key derived from the store’s crypt key); one account per store owner (0) or per vendor
Config Settings, owner mode, hosts, events, local brand, webhook address, cron key
Access Who may see and manage which account, payment, order and job (vendors: own company only; money actions need the owner or the paying vendor)
Money Minor units (ISO 4217 exponents), limits, reference and description formats, Idempotency-Key
PaymentService Start, read-back (sync), apply (applyRemote), capture / refund / release, settle unanswered operations (resolve), webhook handling, cron, Multi-Vendor shares
Transactions Payment rows, operations, locks per order / payment, shares of child orders, search
Transition The state machine: API state and aggregate to local status; which statuses are open, settled or unpaid
Webhook HMAC verification, header reading with the PHP-FPM fallbacks, signing (for tests)
Idempotency Keys, named database locks (GET_LOCK, shop scoped), atomic claims
Queue, Jobs, JobException Job queue with back-off 5 / 15 / 60 / 180 / 720 minutes; job types sync and refund; Jobs::schedule() runs the payment cron
Log Event log with masking, filters, CSV, retention
OrderTax, Upgrade\Synchronizer, License\Client Shared house components (tax shapes, self-healing upgrades, domain-bound license)
Table Purpose
?:kv_vipps_mobilepay_accounts Credentials per company and mode (secrets sealed), webhook id / url / secret (sealed), cached token (sealed), last connection check
?:kv_vipps_mobilepay_transactions One row per payment attempt: reference, Idempotency-Key, MSN, mode, status, state, currency, amount, stored order total, authorized / captured / refunded / cancelled amounts, flag, PSP reference, capture deadline
?:kv_vipps_mobilepay_ops One row per capture, refund or release with its own Idempotency-Key, written before the call, with the aggregate value before the call (base_minor)
?:kv_vipps_mobilepay_jobs Queue
?:kv_vipps_mobilepay_log Log

PHP hooks (registered in init.php):

Hook Handler Use
change_order_status_post fn_kv_vipps_mobilepay_change_order_status_post Capture at the capture status, release at the release status, queue the refund at the refund status (a Multi-Vendor child order refunds its own share; the parent is skipped)
prepare_checkout_payment_methods fn_kv_vipps_mobilepay_prepare_checkout_payment_methods Hides the method when there is no usable sales unit, no license, a currency or amount Vipps MobilePay cannot take, or a cart the sales unit mode cannot serve; sets the local brand name
init_templater_post fn_kv_vipps_mobilepay_init_templater_post Only while the Upgrade Synchronizer is pending

Template hooks (admin): orders:tabs_extra (the Vipps MobilePay tab), addons:manage and addons:tabs_content (license card), index:styles (CSS). The storefront payment template is views/orders/components/payments/kv_vipps_mobilepay.tpl of the responsive theme (inherited by Nova and bright_theme).

The order tab is prepared in controllers/backend/orders.post.php; the payment script payments/kv_vipps_mobilepay.php creates the payment and handles the return.

  • PaymentService::sync() reads the payment (GET) and applyRemote() applies it under the payment lock: AUTHORIZED is accepted only when the amount equals the attempt and the order total equals the stored one; otherwise the attempt is flagged mismatch and released. A second approval of a paid order is duplicate; an approval for an order in the release status is late. Automatic actions run after the lock is released.
  • Payment start: an earlier attempt of the order is settled first (paid = success, open = cancelled with cancelTransactionOnly). The row with reference and key is written before POST /epayment/v1/payments; no clear answer = lookup by reference, adopt, or resend with the same key.
  • Operations: creating to done / failed / unknown. Before a resend the payment is read back; done = marked done; not done and younger than 24 hours = resent with its key; older = closed as not confirmed.
  • Locks: GET_LOCK names carry a hash of the database and the table prefix; the order lock is taken before the payment lock; the webhook waits at most 5 seconds (Vipps MobilePay waits 10).
  • Multi-Vendor owner mode: every lookup goes through Transactions::payingOrderId() (child to parent); a child order refunds and captures only its share (Transactions::shareLeft()).
  • The webhook and cron dispatches are served by a front controller, are POST or secret-key requests and print no template, so the 4.21 full page cache never caches them.
  • Vendor schema: cron, run_now and backfill are admin only; every vendor-reachable action compares the company of the order, payment or job with runtime.company_id.

Test the HTTP layer without Vipps MobilePay

Section titled “Test the HTTP layer without Vipps MobilePay”

The base URL can be overridden for tests in config.local.php (development only, loopback hosts only; an http:// return address is then allowed):

$config['kv_vipps_mobilepay_base_url'] = 'http://127.0.0.1:11981';

node tests/mock-server/server.js 11981 starts a local stand-in of the ePayment, Webhooks and Access Token APIs built from the published specifications; node tests/e2e/e2e.mjs and node tests/e2e/vendor.mjs run the HTTP end-to-end tests against it; php81 tests/unit.php and php83 tests/unit.php run the unit tests. See tests/test-plan.md.

Admin templates live in design/backend/templates/addons/kv_vipps_mobilepay/, the storefront payment template in the responsive theme. Do not edit them in a store; they are replaced on update.

  • The webhook answers within Vipps MobilePay’s 10 seconds: the read-back uses an 8 second HTTP timeout and 5 second lock waits; automatic capture / release and the settling of unanswered operations are stored as jobs (after, sync) and run right after the answer (fastcgi_finish_request() where available) or by the cron.
  • Stop statuses: the release status and Declined (D). An order in a stop status is never revived by a late approval, its open payment is withdrawn, its reservation released, and manual capture is refused for stopped, failed and incomplete orders.
  • Capture “at once” of a Multi-Vendor parent payment captures child by child (a stopped vendor order’s share is never captured) and releases the rest.
  • Named locks are counted per request (Idempotency::lock()), and the lock names include the database and the table prefix.
  • A payment is only handled with the sales unit (MSN) it was created on; changing the MSN of a mode with open or reserved payments is refused.
  • Payment records survive an uninstall; the debug log masks key= (the customer’s return key).