Skip to content

Payments #

Use Payments to connect a customer charge to the service your product delivers. Product Applications can authorise payment, confirm delivery, capture the delivered amount and refund failed services. Laundry cycles and paid Wi-Fi sessions share the same order, settlement and recovery service.

Each order belongs to a customer Product Instance and can contain several priced services. Administrators review service outcomes, captured and refunded amounts, receipts and financial reports in the Customer Portal.

Adoption requirements #

The current payment integration uses Stripe Connect. Vendors configure their own regional Stripe platform accounts; each customer organisation that receives payments completes merchant onboarding with Stripe. People buying a wash or a Wi-Fi session are payers, not the customer organisations being onboarded.

Payment support currently covers US/USD, AU/AUD, GB/GBP and ES/EUR. A vendor needs a matching integration for each region it serves, with separate test and live configuration. The same merchant connection serves that organisation's product services; a new machine or service does not require another merchant account.

Before choosing Payments, confirm that this provider, country coverage and merchant model fit your business. Payments is optional: remote access, fleet operations, portals and other Product Application workflows can be adopted independently.

Qualification before live payments #

Live Stripe sandbox verification and physical reader qualification remain outstanding. Terminal card-present collection and the reader application require separate implementation and qualification. Treat payment-led equipment deployments as an integration and qualification project before accepting live customer payments.

Country routing and terminal setup records do not establish reader availability, unattended approval, custom reader UI or offline payment support. Confirm the supported reader, deployment country and Stripe programme with your vendor before commissioning equipment.

Country, regional integrations and currency #

A customer organisation administrator confirms Payment country in the portal's organisation configuration. Region and currency are derived on the server; customers do not select vendor Stripe accounts.

Customer countryPayment regionCurrency
United States (US)USUSD (usd)
Australia (AU)AUAUD (aud)
United Kingdom (GB)GBGBP (gbp)
Spain (ES)ESEUR (eur)

In the vendor's Integrations → Stripe panel, select a region and test/live mode, enter that region's platform credentials, and save. Stripe's platform account country must match the selected region. Configure one integration per region per mode; select one configured region as the default for each mode. The default helps initialise vendor setup and never overrides a customer's confirmed country. Each integration displays its own webhook URL and uses its own signing secret. Credentials remain write-only.

After confirming country, the customer administrator starts merchant onboarding in the required mode. Terminal locations use the same confirmed country and currency, and provisioning checks the merchant account's country and readiness. Pricing and application-authored checkout currency must match the derived currency. There is no automatic currency conversion: update prices explicitly when using an application in a different region.

If country is unconfirmed or unsupported, or a matching integration is missing or disabled, payment initiation is blocked. The portal displays:

Payments are not available from your vendor in this region. Contact your vendor.

The rest of the portal, previous transactions, financial reports and recovery remain available. Test-mode and live-mode integrations are isolated; neither mode nor another region supplies a fallback.

Existing customers must explicitly confirm country before new payments or onboarding. Migration preserves verified historical routing without treating a previous provider account's country as customer confirmation. Transactions with unproven legacy ownership require provider review.

Administrators can change country in organisation configuration. The change is audited and affects future payments only. Earlier orders and Connect payments retain their original region, currency, platform integration and connected account for retries, webhooks, reconciliation and refunds. Terminal recovery also uses its original regional context. Changing a default, onboarding in a new region or disabling an integration does not reroute historical payments. Disabling prevents new payment creation; historical recovery still requires valid original credentials and provider access. Reports retain separate currency partitions, and receipts retain the transaction's original currency.

Australia/AUD is a routing and currency example. It does not establish UX700 availability, unattended approval, custom reader UI or offline payment support.

Authorisation and service delivery #

Amounts use integer currency minor units: AUD 5.00 is 500. An immutable business key identifies the order; a stable operation key identifies each authorisation, capture, cancellation or refund. Reusing a key with changed parameters fails.

A cloud Payment step follows this service lifecycle:

  1. create_order: create immutable allocations for an existing instance.
  2. perform_operation(kind="authorize"): reserve an operation durably before requesting a manual-capture PaymentIntent.
  3. bind_fulfilment_command: attach an existing Command Invocation in that same instance to an allocation, once authorisation is confirmed.
  4. reconcile_fulfilment: inspect the existing command result, or record an identified administrator's delivery evidence.
  5. settle_order: capture the sum of confirmed fulfilled allocations, or cancel if every allocation definitely received no service.

A command accepted by equipment is not proof of delivery. Success must include an explicit service_delivered: true signal. A definite rejection proves non-delivery; a timeout after dispatch does not. Unknown allocations block both capture and cancellation until resolved. The ledger never issues or repeats machine commands: the application continues to use Product Processes, Operations and the existing command lifecycle.

A three-allocation order can therefore capture two delivered services while releasing the uncaptured third amount. Refunds are separate identified operations with a reason, bounded by the captured balance. Unknown refunds block further financial effects.

For workflows that capture before fulfilment, a definite non-delivery creates a durable allocation refund instruction. The existing Payments worker drains it without depending on the original process remaining alive. Successful allocations keep their charge. Manual refunds and automatic refunds share allocation balances, so they cannot refund the same captured amount twice. Unknown service or refund results require reconciliation and never cause an automatic repeat.

Provider accounts and recovery #

New ledger orders default to Stripe direct charges, with every provider request scoped to the customer's connected account. Existing Stripe integration bindings retain destination-charge behavior. A ledger order can explicitly select destination; its refunds reverse the corresponding transfer. This initial ledger adapter does not add an application fee.

Requests use the vendor's encrypted Integration credentials, with no fallback to a deployment-wide Stripe key. No provider secrets, client secrets or provider exception bodies appear in ledger responses. Direct charges require charges_enabled. Recipient-only onboarding used by existing destination-charge applications does not establish that direct merchant charges are ready; merchant onboarding must be completed with Stripe.

Provider outages, invalid responses and acknowledgement loss leave an unresolved operation. Capture and cancellation can be reconciled by retrieving the current PaymentIntent. Webhooks record verified evidence scoped by account and test/live mode; delayed events do not overwrite current balances.

An organisation administrator can explicitly retry an unresolved provider operation with its original idempotency key and immutable request, within 23 hours of reservation. This never retries physical service. Recovery waits at least five minutes for a still-pending request. After the window expires, use Stripe review and the original operation reference; the backend refuses a new financial effect. Unknown authorisation and refund outcomes require this original-key recovery or provider review, rather than a new order.

Customer payment APIs #

These routes sit beneath the existing portal API prefix:

RouteBehavior
GET products/{instance_id}/payments/Orders, allocation delivery states and reconciliation flags; limit up to 100 and before pagination
GET products/{instance_id}/payments/{order_id}/Order and non-secret operation history
POST products/{instance_id}/payments/{order_id}/Administrator refund, settlement, provider recovery or delivery evidence
GET products/{instance_id}/payments/export/CSV of the latest 10,000 orders in that instance

Payment review and financial actions require organisation administrator access, including administrators granted that role through a portal group. Device operator or arbitrary network write access does not grant finance permission. All order, allocation and provider operation lookups remain within the customer's active instance. Audit events use the existing Product Event envelope.

Action bodies use action with one of:

  • refund: operation_key, amount_minor, reason.
  • settle: operation_key.
  • reconcile: retrieve current provider payment evidence.
  • retry_provider_operation: operation_id.
  • resolve_fulfilment: allocation_id, boolean delivered, evidence_reference.

Order creation and authorisation are backend service entry points. The portal review APIs do not accept card data or create payment orders.

Authoring and owner review #

Product Process authors can add a cloud Payment step with order creation, authorisation, command binding, fulfilment resolution, settlement or refund. Configure failure and timeout paths explicitly. Edge command execution continues to use the existing command mechanism; payment credentials stay in the cloud. Test execution stubs provider effects.

The customer portal Payments page presents each service outcome beside the order's captured and refunded amounts. Administrators can export the order ledger, record concrete delivery evidence, settle resolved service and issue bounded refunds. If a refund response is lost, retrying retains the same operation identity rather than creating another refund. An authored business navigation mode gives the reference application its customer-facing navigation.

Confirmed provider bookings supply immutable payment-confirmation receipts and bounded reports, grouped by currency, provider and payment mode. Financial reports use a selected IANA timezone and a half-open date window of at most 366 days; unresolved orders are reported separately from confirmed money.

Terminal setup records locations, registration, health and recovery in the durable provider journal. Commissioning still requires the qualification described above.

The financial features include immutable quote discounts, non-cash service credits using the platform resource ledger, and rebates through the existing refund outbox. Settlement, payout and dispute references are recorded evidence; they never create or change a confirmed cash booking. Bounded native financial queries and paginated CSV exports retain tenant scope and partition monetary sums by currency, provider, mode and entry kind where applicable.

Authored overview-page reports can use kind: "financial" and a native query source (orders, entries, merchants, adjustments, settlements, disputes or credits). The existing report endpoint runs the published query for customer organisation administrators. At runtime the owner can choose dates, timezone and pagination; they cannot replace its source, filters, selected fields or money dimensions. Publishing rejects unpartitioned money sums. For example:

json
{
  "kind": "financial",
  "key": "confirmed-bookings",
  "title": "Payment bookings by outcome",
  "query": {
    "source": "entries",
    "group_by": ["currency", "provider", "livemode", "kind"],
    "metrics": [{"name": "amount", "fn": "sum", "field": "amount_minor"}]
  }
}

The overview and laundry Today screens render the authored result beside the existing payment report, preserving currency and live/test mode. Failed requests show an error rather than zero income. Payout/dispute references and service credits remain distinct from confirmed provider bookings.