NEXUS
Resources

WAVit Resources

The repository, how to build, sign, test and release, and the merchant settings reference.

WAVitPaymentsThe Android app. The Gradle project is CloverWAVitPayments/; pipelines, scripts and the release template sit at the root.Azure DevOps
WAVit-Systems wikiWhere the release pipeline writes a Release Run page for every production release.Azure DevOps wiki
Clover Developer DashboardWhere signed APKs are uploaded, submitted for Clover's approval and published to the App Market.CloverClover developer docsThe Android SDK, connectors and REST API the app is built on.Clover
Test suitesSeven JUnit classes pinning the money maths, and seven Espresso classes driving the keypad, tip, partial-payment, settings and inventory screens.JUnit 4 · Espresso
Crashlytics and ClarityCrash reporting and session replay. Part of the post-release check: both should look normal compared with before the release.Firebase · Microsoft

Build it locally

  1. 1
    PrerequisitesJDK 17 — newer JDKs cannot run Gradle 7.6.4 — and the Android SDK with platform 31. Point Gradle at JDK 17 with org.gradle.java.home in your own %USERPROFILE%\.gradle\gradle.properties, or use Android Studio's bundled JBR 17.
  2. 2
    Open the projectOpen CloverWAVitPayments/ in an Android Studio that supports AGP 7.4. google-services.json is committed and covers both application ids.
  3. 3
    Pick a variantdevelopmentDebug for day-to-day work against the Clover sandbox and dev MiPoint API.
  4. 4
    Run on a devicePayments need a real Clover device. A sideloaded build needs a developer or sandbox device; merchant devices get the app from the App Market.
Build variants
TaskOutputNotes
assembleDevelopmentDebugapp-development-debug.apkThe everyday build
assembleProductionDebugapp-production-debug.apkProduction endpoints, debug signing
assembleDevelopmentReleaseapp-development-release[-unsigned].apkSigned only when the WAVIT_* variables are set
assembleProductionReleaseapp-production-release[-unsigned].apkWhat the production pipeline builds
From CloverWAVitPayments/
./gradlew assembleDevelopmentDebug
./gradlew installDevelopmentDebug                 # to a connected device
./gradlew testDevelopmentDebugUnitTest            # JVM unit tests
./gradlew connectedDevelopmentDebugAndroidTest    # Espresso, device online

Signing

Release builds are signed only when WAVIT_KEYSTORE_PATH is set; WAVIT_KEYSTORE_PASSWORD, WAVIT_KEY_ALIAS (default WAVit) and WAVIT_KEY_PASSWORD complete it. The pipelines set them from a secure file and the wavit-release-secrets variable group. Without them, release builds come out unsigned and Android Studio's Generate Signed APK wizard works as before — choose V1 only.

Releasing to production

There is no instant rollback on the App Market, so the process is deliberately gated.

  1. 1
    MergeAll changes reach master through reviewed PRs. The PR build confirms assembleProductionRelease still signs.
  2. 2
    Bump the versionproductionVersionName and productionVersionCode in the root build.gradle. The versionCode must be greater than the last APK uploaded to Clover — Clover rejects it otherwise, and the pipeline does not check.
  3. 3
    TagAn annotated tag release/prod/v{X.Y} (or X.Y.Z for a re-release) on the master commit. The tag message becomes the release summary.
  4. 4
    PipelineBuilds and verifies the signed APK (WAVitPayments-v{name}-{code}.apk, with sha256.txt), creates the Release Run page and posts to Slack.
  5. 5
    Go / no-goThe developer completes the page — QA sign-off, business owner notified, standby person, rollback sentence — and the approver approves the clover-prod environment. The pipeline appends the release record.
  6. 6
    Upload to CloverDownload the apk artifact, check the SHA-256, upload it on the Developer Dashboard, set devices and release notes, submit, and publish once Clover approves.
  7. 7
    VerifyA real transaction on a merchant or test device, Crashlytics and Clarity normal, release notes announced.

Rolling back means re-uploading the previous release's APK rebuilt with a higher versionCode and going through Clover's review again. Sandbox builds follow the same shape with a release/dev/v* tag and the apk-dev artifact, without the approval gate.

Tests

JVM unit tests — app/src/test/java/com/micamp/wavitpayments/
ClassCovers
CalculationTestSurcharge with and without tax, pre- and post-tax
CalculationTipDiscountTestTip base under every post-surcharge / post-tax combination; discount on sale vs sale + tax
CalculationTotalAssemblyTestThe production golden case, zero sale, rounding, discount ordering, second transactions
CalculationCustomTipTestDollar tip to percent and back; split discounts
CalculationLegacyMethodsTestThe cents-in contract of the two-argument calculatePercent
GlobalUtilMoneyTestFormatting and cents conversion, with four *_knownBug cases
TransactionReviewParsingTestParsing the $-prefixed tax and discount fields
Espresso tests — app/src/androidTest/java/com/view/
ClassCovers
TransactionActivityTestKeypad rules, the 7-digit cap, invoice and custom fields, Next carries the amount
TipSelectionActivityTestPercent and flat tiles, custom tip, No Tip, the maximum
PartialPaymentActivityTestRemaining-balance maths with tip and discount
SettingsActivityTestThe read-only settings screen, including Pre-Auth hiding tips
TransactionTypeSettingsTestSale, Auth and Pre-Auth
InventoryActivityTestSearch and empty state
AboutActivityTestSmoke test
  • Most unit tests are characterisation tests: they pin today's behaviour, bugs included, so a change in money maths shows up as a failing test rather than a support call.
  • Espresso tests seed Configuration with settings and a TEST-DEVICE serial before launching a screen. The keypad test needs the device online, because the keypad is gated on connectivity.
  • CI runs neither suite — the pipelines only assemble. Run them before opening a PR.

Merchant settings reference

Settings come only from GET api/SqlConfig and are edited in the Configurator. The JSON keys are the Java field names in model/Settings.java. The most consequential ones:

Pricing, tax and tips
SettingEffect
transactionTypeSale or Pre-Auth
surchargePercent, surchargeCaption, surchargePostTaxThe surcharge / service fee and its receipt label
taxRateOne rate for the whole transaction
isTipAllowed, isTipPostTax, isTipPostSurchargeWhether to tip, and the tip base
gratuityPercent1-3Tip tiles
isDynamicTippingEnabled, tipThresholdAmount, gratuityFlat1-3Flat-dollar tiles above a threshold
tenderTypes[]Tender buttons: caption, enabled, discount %, open cash drawer, QR, invoice by text or email, custom caption
amountDisplay, useDualPriceFormatPer-tender prices on the buttons; dual-price receipts
customFields[]Up to five "Other information" fields, each optionally required
Terminal, integration and controls
SettingEffect
integrated, terminalType, customerFacingTerminalMerchant vs customer terminal, and the pairing
integrationTypeStandalone, Tethered, or a dealer management system
enterpriseCode, companyNumber, serverNameThe DealerTrack dealer
subscriptionId, departmentCodeFortellis
bypassIntegration, bypassPINRun a dealership terminal as standalone
unlockPIN, pinAlwaysPromptThe app PIN on the idle screen and the menu
askManagerRefundOverride, managerRefundOverridePIN, promptForRefundReasonRefund controls
promptForEmployeeId, employeeIdCaption, employeeIdInvoiceEmployee capture
includeInvoice, invoiceRequired, invoiceCaptionThe invoice-number field (on and required by default)
includeInventoryThe cart and the Orders menu
disableSignatureSkip WAVit's signature pad
forceTermsAcceptanceTerms & conditions at startup
Receipts, add-ons and partners
SettingEffect
printMerchantReceipt, headerText, footerText, showCardTypeAuth, displaySurchargeDetailsReceipt content
overrideMerchantAddress + address fieldsPrint a different address
showCustomTipLineOnReceipt, enableDynamicTippingOnReceiptSuggested tips on the customer copy
rootFTPAddressWhere log files are uploaded
enableWavitProWAVit Pro master switch; the rest of its settings start with wavitPro… or sit beside it (raisedAmountPercent, enableWavitProCashDiscount, discountCustomItems, cashPaymentDiscountCaption)
enableFincretive + fincretive… credentialsSNAP/EBT and HBC; also shows the EBT menus

Finding your way around the code

Package (under `com/`)What is in it
baseWavItApplication and Calculation
connectivityCloverConnectivity (the SDK), WebApiCaller (HTTP), CitConConnectivity, FincretiveApi, OrdersApi, FTP, and retrofit/ with ApiUrl, the list of every path
modelGson and SimpleXML models, including Settings and the DMS envelopes
roomThe payment outbox
singletonConfiguration (settings in memory), OrderState (the cart order in flight), Fincretive session and receipts, MagtekManager
utilsWorkers, printers, logging, scanning, DUKPT and TLV for MagTek, dialogs, the menu, and constant/ with every purpose code
view, viewModelOne activity and one view model per screen; viewModel/helper holds dialog models
wavitproWAVit Pro

Screens talk to their activity through one MutableLiveData<Parameter> per view model: a purpose code plus payloads, switched on in onDataObserve. Several purpose codes in AppConstants share a value, so check for collisions before adding one.

Traps that cost real time

  • `CloverConnectivity` has one listener: whichever view model last called getInstance(listener) gets every callback. Register before you call.
  • The next API call cancels yours. If a flow needs two calls, chain the second in the first's onSuccess.
  • Money crosses units at the Clover boundary. Clover amounts are cents; the rest of the app is dollars in double. Several bugs are exactly a factor of 100.
  • Global state is not reset between transactions: Constants statics and runtime fields written into Settings (repair-order number, signature, custom caption) can leak from one sale into the next.
  • Settings live in memory only. After process death they are gone until Splash runs again; WAVit Pro keeps its own copy in wavitpro_prefs for that reason.
  • Room schema changes wipe unsent payments until the migrations are registered.
  • The root `InventoryViewModel.java`, `citcon_version.java`, `previous_verify.java` and the Clarity `.aar` files are not part of the build. They are leftovers; do not edit them by mistake.
Found a security issue?Report it through the bug bounty program instead of public channels.