The repository, how to build, sign, test and release, and the merchant settings reference.
CloverWAVitPayments/; pipelines, scripts and the release template sit at the root.Azure DevOpsorg.gradle.java.home in your own %USERPROFILE%\.gradle\gradle.properties, or use Android Studio's bundled JBR 17.CloverWAVitPayments/ in an Android Studio that supports AGP 7.4. google-services.json is committed and covers both application ids.developmentDebug for day-to-day work against the Clover sandbox and dev MiPoint API.| Task | Output | Notes |
|---|---|---|
assembleDevelopmentDebug | app-development-debug.apk | The everyday build |
assembleProductionDebug | app-production-debug.apk | Production endpoints, debug signing |
assembleDevelopmentRelease | app-development-release[-unsigned].apk | Signed only when the WAVIT_* variables are set |
assembleProductionRelease | app-production-release[-unsigned].apk | What the production pipeline builds |
./gradlew assembleDevelopmentDebug
./gradlew installDevelopmentDebug # to a connected device
./gradlew testDevelopmentDebugUnitTest # JVM unit tests
./gradlew connectedDevelopmentDebugAndroidTest # Espresso, device onlineRelease 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.
v1SigningEnabled true, v2SigningEnabled false. The production and sandbox apps are signed with different keystores (ProductionWavItPayments.jks and SandboxWavItPayments.jks in the pipeline's secure files).
There is no instant rollback on the App Market, so the process is deliberately gated.
master through reviewed PRs. The PR build confirms assembleProductionRelease still signs.productionVersionName 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.release/prod/v{X.Y} (or X.Y.Z for a re-release) on the master commit. The tag message becomes the release summary.WAVitPayments-v{name}-{code}.apk, with sha256.txt), creates the Release Run page and posts to Slack.clover-prod environment. The pipeline appends the release record.apk artifact, check the SHA-256, upload it on the Developer Dashboard, set devices and release notes, submit, and publish once Clover approves.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.
| Class | Covers |
|---|---|
CalculationTest | Surcharge with and without tax, pre- and post-tax |
CalculationTipDiscountTest | Tip base under every post-surcharge / post-tax combination; discount on sale vs sale + tax |
CalculationTotalAssemblyTest | The production golden case, zero sale, rounding, discount ordering, second transactions |
CalculationCustomTipTest | Dollar tip to percent and back; split discounts |
CalculationLegacyMethodsTest | The cents-in contract of the two-argument calculatePercent |
GlobalUtilMoneyTest | Formatting and cents conversion, with four *_knownBug cases |
TransactionReviewParsingTest | Parsing the $-prefixed tax and discount fields |
| Class | Covers |
|---|---|
TransactionActivityTest | Keypad rules, the 7-digit cap, invoice and custom fields, Next carries the amount |
TipSelectionActivityTest | Percent and flat tiles, custom tip, No Tip, the maximum |
PartialPaymentActivityTest | Remaining-balance maths with tip and discount |
SettingsActivityTest | The read-only settings screen, including Pre-Auth hiding tips |
TransactionTypeSettingsTest | Sale, Auth and Pre-Auth |
InventoryActivityTest | Search and empty state |
AboutActivityTest | Smoke test |
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.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:
| Setting | Effect |
|---|---|
transactionType | Sale or Pre-Auth |
surchargePercent, surchargeCaption, surchargePostTax | The surcharge / service fee and its receipt label |
taxRate | One rate for the whole transaction |
isTipAllowed, isTipPostTax, isTipPostSurcharge | Whether to tip, and the tip base |
gratuityPercent1-3 | Tip tiles |
isDynamicTippingEnabled, tipThresholdAmount, gratuityFlat1-3 | Flat-dollar tiles above a threshold |
tenderTypes[] | Tender buttons: caption, enabled, discount %, open cash drawer, QR, invoice by text or email, custom caption |
amountDisplay, useDualPriceFormat | Per-tender prices on the buttons; dual-price receipts |
customFields[] | Up to five "Other information" fields, each optionally required |
| Setting | Effect |
|---|---|
integrated, terminalType, customerFacingTerminal | Merchant vs customer terminal, and the pairing |
integrationType | Standalone, Tethered, or a dealer management system |
enterpriseCode, companyNumber, serverName | The DealerTrack dealer |
subscriptionId, departmentCode | Fortellis |
bypassIntegration, bypassPIN | Run a dealership terminal as standalone |
unlockPIN, pinAlwaysPrompt | The app PIN on the idle screen and the menu |
askManagerRefundOverride, managerRefundOverridePIN, promptForRefundReason | Refund controls |
promptForEmployeeId, employeeIdCaption, employeeIdInvoice | Employee capture |
includeInvoice, invoiceRequired, invoiceCaption | The invoice-number field (on and required by default) |
includeInventory | The cart and the Orders menu |
disableSignature | Skip WAVit's signature pad |
forceTermsAcceptance | Terms & conditions at startup |
| Setting | Effect |
|---|---|
printMerchantReceipt, headerText, footerText, showCardTypeAuth, displaySurchargeDetails | Receipt content |
overrideMerchantAddress + address fields | Print a different address |
showCustomTipLineOnReceipt, enableDynamicTippingOnReceipt | Suggested tips on the customer copy |
rootFTPAddress | Where log files are uploaded |
enableWavitPro | WAVit Pro master switch; the rest of its settings start with wavitPro… or sit beside it (raisedAmountPercent, enableWavitProCashDiscount, discountCustomItems, cashPaymentDiscountCaption) |
enableFincretive + fincretive… credentials | SNAP/EBT and HBC; also shows the EBT menus |
The read-only Settings screen labels the surcharge percentage "Discount Percent", and its "Tip Pre-Tax" row is bound to isTipPostTax. Read those two rows with that in mind.
| Package (under `com/`) | What is in it |
|---|---|
base | WavItApplication and Calculation |
connectivity | CloverConnectivity (the SDK), WebApiCaller (HTTP), CitConConnectivity, FincretiveApi, OrdersApi, FTP, and retrofit/ with ApiUrl, the list of every path |
model | Gson and SimpleXML models, including Settings and the DMS envelopes |
room | The payment outbox |
singleton | Configuration (settings in memory), OrderState (the cart order in flight), Fincretive session and receipts, MagtekManager |
utils | Workers, printers, logging, scanning, DUKPT and TLV for MagTek, dialogs, the menu, and constant/ with every purpose code |
view, viewModel | One activity and one view model per screen; viewModel/helper holds dialog models |
wavitpro | WAVit 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.
getInstance(listener) gets every callback. Register before you call.onSuccess.double. Several bugs are exactly a factor of 100.Constants statics and runtime fields written into Settings (repair-order number, signature, custom caption) can leak from one sale into the next.wavitpro_prefs for that reason.