Developer notes
Architecture
Section titled “Architecture”- Add-on (
app/addons/kv_mobile_app/): configuration per storefront company (?:kv_mapp_config; Multi-Vendor uses company 0), devices (?:kv_mapp_devices), campaigns (?:kv_mapp_campaigns), one queue row per campaign and device (?:kv_mapp_queue, also the inbox), devices of orders (?:kv_mapp_order_devices). - Native shells (
app/addons/kv_mobile_app/resources/shell/): templates of the Android (Java, AndroidX, Material, Firebase Messaging, Play In-App Review) and iOS (Swift, UIKit, WKWebView, Firebase via Swift Package Manager) projects.Tygh\Addons\KvMobileApp\Builderfills the{{KV:...}}tokens (escaped per file type), renames the Java package folder, renders icons with GD and writesconfig.json. - Push:
Fcmsigns a JWT (RS256, OpenSSL) with the service account, exchanges it for an OAuth token (cached encrypted until 5 minutes before it expires) and sends one FCM HTTP v1 request per device.UNREGISTEREDdrops the token,429/5xxleave the rest of the queue for the next run.
Storefront
Section titled “Storefront”hooks/index/links.post.tplprints a small inline script and the hide CSS. The script addskv-mapp,kv-mapp--android|iosanddata-kv-mapp-dispatchto<html>when the user agent containsKvMobileApp/(or in the admin preview frame). The markup is the same for every visitor, so the full page cache (4.21) stays shared.js/addons/kv_mobile_app/func.js(only inside the app):window.KvMapp.send(type, data)posts to the shell (KvMappAndroid.postMessage/webkit.messageHandlers.kvmapp). Messages:ready(url, title, dispatch),cart(count),share(url, title),rate. The shell callsKvMapp.onDevice(device)after each page load; the script registers the device withkv_mobile_app.registerat most once a day or when something changed, and stores the device ID in thekv_mapp_didcookie (used to link guest orders).- Theme CSS for the app only:
html.kv-mapp .your-selector { ... }.
Endpoints (index.php?dispatch=...)
Section titled “Endpoints (index.php?dispatch=...)”| Dispatch | Method | Answer |
|---|---|---|
kv_mobile_app.config |
GET | {ok, config} live configuration (tabs, colours, hosts, rules, required versions) |
kv_mobile_app.register |
POST | device_id (32 hex), platform, token, push, app_version, build, os_version; links the signed-in customer |
kv_mobile_app.state |
GET | {ok, cart, signed_in} for the badges |
kv_mobile_app.inbox |
GET | device_id, limit: {ok, items: [{id, title, body, image, url, time, opened}]} |
kv_mobile_app.opened |
POST | device_id, campaign_id |
/.well-known/assetlinks.json, /.well-known/apple-app-site-association |
GET | routed by schemas/routes/objects.post.php |
All answers are JSON with Cache-Control: no-store (association files: 1 hour). None of these dispatches is cached by
the full page cache. With the add-on switched off or unlicensed the app endpoints answer {ok: false} and the apps
keep working as plain store apps.
place_order (links the app that placed the order), change_order_status (order pushes),
init_templater_post (upgrade synchronizer). Admin console cron: php admin.php --dispatch=kv_mobile_app.cron
(--limit, --seconds).
Test seams
Section titled “Test seams”KV_MAPP_FCM_TOKEN_URL and KV_MAPP_FCM_SEND_URL (in local_conf.php) point the FCM client at a test server. The
Android debug build has DebugPushActivity to show a notification without Firebase.