Skip to content

Run the laundry test checkout #

Build a working laundry checkout with a customer portal, a Linux controller and an Android app on a Stripe T600 DevKit. The patron selects a machine, taps a Stripe test card, and the application authorises payment, confirms the simulated vend and captures the delivered amount.

This path was exercised on 20 October 2026 with RinsePilot hosted in Dataplicity production, a Desk lab CM5 running equipment-gateway 0.2.7, and a physical T600 DevKit. Two £7 GBP checkouts completed automatically, including command results, fulfilment, capture and Stripe webhook delivery. The controller used local-simulator; no washing machine was actuated. Physical machine commissioning follows Compatibility and verification and Safety and commissioning.

Prepare the customer and payment integration #

You need a Commercial Laundry Product Application, a published version assigned to a customer Product Instance, a customer Network, a connected CM5 controller, and access to the vendor's Software catalogue. See Set up a customer portal and release a Product Application.

  1. In the vendor organisation, open Integrations → Stripe. Configure the matching region in test mode, using the platform sandbox's test API key and webhook signing secret. Use the webhook URL shown for that integration.
  2. Confirm the customer's payment country and complete its test merchant onboarding. For this example, the region is GB and the currency is GBP.
  3. Bind the Terminal Location to the customer's Network and register or attach the DevKit reader under that customer's connected test merchant. Retain its reader key for the application's checkout configuration.
  4. Issue a reader-scoped kiosk token and store its one-time value securely for the Android build.

The Stripe platform credentials belong to the vendor organisation's encrypted integration. Merchant, Location and reader bindings belong to the customer installation. Adding another organisation does not require shared deployment environment keys. The Android app and equipment gateway receive no Stripe API key.

Hosting environment and payment mode are separate. A production-hosted Dataplicity installation can use a Stripe sandbox, DevKit and test cards. Keep its integration, merchant, Terminal Location and reader in the same test account context. A production API address does not select live payments.

If Stripe shows No devices, check the selected platform account, sandbox and connected merchant. A reader registered to the connected merchant can be absent from the platform's own reader list. Inspect that merchant's Terminal resources before registering the reader again.

Configure and release the controller workload #

Use the managed gateway setup to register a verified release and build the Device Class Software bundle. The validated desk-lab version is equipment-gateway 0.2.7. Verify the release checksum and provenance, then promote the bundle through the normal Software lifecycle.

For the packaged GPIO site template used in this lab:

SettingValue
Gateway PRODUCT_INSTANCE_IDThe target customer's Product Instance ID
Gateway EQUIPMENT_SITEgpio
Device setting controller_protocollocal-simulator
Machine equipment IDwasher-1
Machine price700 minor units, GBP

Keep managed bootstrap enabled and confirm that an earlier lab configuration is not overriding the target instance. The machine record's equipment ID must match an endpoint in the gateway configuration. Confirm the reported controller protocol is local-simulator before checkout; EQUIPMENT_SITE=gpio alone does not establish simulation mode. Leave physical laundry outputs disconnected for this test.

Mount persistent gateway state as described in Managed runtime. Preserve its SQLite command/effect journal through updates and restarts. Version 0.2.7 reports command results before publishing outcome events and replays a matching durable result before applying deadlines for a new effect. A reporting retry therefore retains the successful result without repeating the vend.

Verify live controller connectivity and the actual running gateway version and health. An assigned bundle by itself does not prove that the device is running it.

Moving a controller from staging to production #

Move one controller deliberately: save its production agent and M2M endpoints, provision its production device binding, and restart the agent or reboot the controller. Confirm its live connection to production before checkout.

Keep staging and production Product Runtime queues separate. Preserve the old queue for audit and reconciliation; retain the gateway's physical-effect journal for duplicate prevention. Review any unresolved production command receipts before changing the runtime storage path. Never empty a full queue or discard a command journal to make a payment test pass. Recheck production instance routing, queue progress and gateway health after restart.

Build the Android app #

The Android project is apps/laundry-pos-aod in the Dataplicity platform source. The validated build uses JDK 21, Android SDK platform 34, build-tools 34.0.0 and the project's Gradle 8.11.1 wrapper. Install Android Studio, Android SDK command-line tools and platform-tools, then configure Android Studio's Gradle JDK to use JDK 21.

In the project directory, create the ignored app/src/main/assets/desk_lab.json with the target installation's values. Obtain the kiosk API origin from your vendor; the hostname below is a placeholder:

json
{
  "api_base": "https://kiosk-api.example.com",
  "instance_id": "YOUR_CUSTOMER_PRODUCT_INSTANCE_ID",
  "kiosk_token": "YOUR_READER_SCOPED_KIOSK_TOKEN",
  "currency": "GBP"
}

Set JAVA_HOME to JDK 21 and ANDROID_HOME to your Android SDK directory. Create an ignored local.properties containing sdk.dir=/absolute/path/to/android-sdk if the IDE has not already created it. Then build:

bash
./gradlew :app:assembleDebug

The APK is app/build/outputs/apk/debug/app-debug.apk. The asset and APK contain the kiosk credential: keep them out of source control, public artifacts and support attachments. This prototype embeds a reader-scoped token in its build; use a controlled credential-provisioning and rotation process for wider deployment.

Install on the T600 DevKit #

Connect the DevKit by USB and accept Allow USB debugging on the reader. Check that adb devices -l shows it as device, rather than unauthorized. Use its serial in these commands:

bash
adb -s YOUR_USB_SERIAL install -r app/build/outputs/apk/debug/app-debug.apk
adb -s YOUR_USB_SERIAL shell am start -n com.dataplicity.laundry.pos/.MainActivity

If a clean workstation has generated a different Android signing key, Android rejects replacement of the existing package. Retain the original signing key or back up the lab installation and explicitly uninstall it before installing the new build. Uninstalling removes its local app data.

The app should show only machines from the bound customer Network, including Desk washer 1 - £7.00 for this fixture. An empty or demo list does not confirm an authenticated production connection. Verify the API origin, instance, kiosk token, reader binding and device network access before proceeding.

Run and verify the checkout #

  1. Select Desk washer 1, confirm the £7 total and press PAY & START.
  2. When the T600 displays £7.00 - Tap or insert, tap the Stripe test card promptly. The provider waits up to 90 seconds for card collection.
  3. Confirm Approved on the reader, then inspect the Product Process execution and payment order in the application and customer payment review.
  4. Check the evidence below for the same order and command identities.
EvidenceExpected result
Purchase Processcompleted, with no reconciliation required
Vend commandsucceeded, with adapter_result.service_delivered: true
Lab adapter evidencesimulated: true, with the local simulator pulse acknowledged
Payment allocationfulfilled
Stripe orderlivemode: false, captured, captured_minor: 700
Stripe deliveriesReader action, PaymentIntent success and charge capture webhooks received

The reader's Approved screen proves payment authorisation, not the complete service workflow. Completion requires the command result, confirmed fulfilment and capture. This server-driven app uses Stripe's Reader app to collect the card; the Android kiosk polls the Dataplicity execution result.

If the prompt expires, inspect the existing PaymentIntent and reader action before starting another checkout. The provider attempts cancellation on timeout, but an uncertain response leaves the Process awaiting reconciliation. Confirm cancellation and zero capture with Stripe, clear any remaining reader action, and retain the original identifiers. An unknown payment or vend outcome must be resolved before retrying; a UI timeout is not proof of non-delivery.

Keep RinsePilot in the foreground after payment #

A USB-sideloaded DevKit app returns to Stripe's default app after a transaction. Bring RinsePilot forward manually during USB testing. This behaviour alone does not indicate an Android crash.

For automatic return, use Terminal → Software in the correct Stripe sandbox, deploy the app through a deploy group, select it as the preferred kiosk app and restart the DevKit. Follow Stripe's DevKit testing instructions and Dashboard deployment guide. If the Software tab is absent, ask Stripe to enable Apps on Devices for that account or sandbox. RinsePilot's enablement request is pending; preferred-app return has not yet been validated in this lab.

Production reader rollout also requires Stripe's applicable app review, signing and deployment process. The DevKit test establishes the payment and simulated-service workflow; real-machine interfaces and live unattended payment operation require their own commissioning.