Payments — Volley invoice links

Generate a one-off invoice and get a shareable bank-transfer pay link + QR code (powered by Volley open banking) to attach to it. The payer opens a standalone page, pays by bank transfer, and the invoice is marked Paid automatically once Volley confirms the transfer. No card, no login for the payer.

This is for operator-raised invoices (e.g. Prosper Technologies billing a client for hosting), separate from shop-order checkout.

Where it lives

Prerequisites — the channel's Volley settings

Payments settle into the bank account configured on the channel that raises them. Before using this, the channel must have Volley set up (Admin → channel settings → payments):

| Setting | Field | Notes | |---|---|---| | Open banking enabled | useOpenBanking | Must be on | | Volley API key | volleyApiKey | Live key, or a MOCK… / mock_… key for testing (no real money) | | Bank account number | bankAccountNumber | Where the money lands (sent to Volley as bank_account_id) | | Webhook secret | volleyWebhookSecret | Used to verify Volley's webhook signature |

In the Volley dashboard, point the webhook at POST https://<host>/volley/webhook (the same endpoint checkout already uses) and register the request.status_updated and payment.status_updated events.

Create an invoice (admin)

  1. Configuration → Payments → New invoice.
  2. Fill in Bill to (name/email, optional) and a Description (shown to the payer and used as the Volley payment message).
  3. Add line items — each has a description, quantity (supports decimals, e.g. 4.5 hours), a unit price, and a "Price includes GST" toggle. When a line's price includes GST, its GST is broken out on the invoice (net + GST shown); when it excludes GST, GST is added on top. Use + Add line for more. The top-level "New lines include GST" switch sets the default each new line adopts (defaults to includes); flip any individual line as needed.
  4. Leave GST at 15% (PTL is GST-registered) or choose No GST for an exempt invoice.
  5. Create invoice. You land on the invoice page showing the totals, the pay link and the QR code.

Attach the QR image or the pay link to the invoice you send (e.g. in the emailed PDF). Anyone with the link can pay; they cannot see any other invoice.

How the payer pays

  1. They open the pay link (or scan the QR).
  2. They see the invoice summary and Pay with bank transfer.
  3. On click, the app creates a Volley payment request and shows Volley's QR + a Continue to Volley button (on mobile it goes straight through). They authorise the transfer in their banking app.
  4. The pay page polls and updates to Paid once Volley confirms. The admin invoice status flips to Paid via the webhook.

Marking paid / cancelling

Using the MCP tool

The helpinghand-bulk-actions MCP server exposes:

The tool drives the admin API POST/GET /api/v2/admin/channels/{channelCode}/invoices (JWT admin auth, ROLE_API_ACCESS).

Testing without real money

Set the channel's volleyApiKey to a value starting MOCK (e.g. MOCK_test). VolleyService then returns a fake request URL and makes no real API call, so you can exercise the whole admin + pay-page flow safely. The pay page shows a "Test mode" note. To simulate the webhook marking it paid, POST a Volley-shaped payload to /volley/webhook with the invoice's merchant_identifier (or flip the status in the DB for a quick check).

Data model

Money is stored in integer cents throughout.