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.
Configuration → Payments (super-admin only). Direct URL: /admin/super/payments./pay/{token} — unguessable per-invoice token, no menu link, no login. This is what the link/QR points to.create_invoice_payment_link / list_invoices on the helpinghand-bulk-actions MCP server.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.
Configuration → Payments → New invoice.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.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.
request.status_updated=paid or payment.status_updated=successful), matched on the invoice's merchant_identifier. The browser polling is only a convenience; the webhook is the source of truth.The helpinghand-bulk-actions MCP server exposes:
create_invoice_payment_link — create an invoice and return its pay link. Example arguments:
{
"channelCode": "hh",
"payerName": "WildDad Limited",
"description": "Managed cloud hosting - June & July",
"gstPercent": 15,
"lines": [
{ "description": "Cloud infrastructure and backups", "quantity": 2, "unitPriceDollars": 50 },
{ "description": "Monitoring and on-call cover", "quantity": 2, "unitPriceDollars": 45 }
]
}
Returns the invoice number, totals and the payUrl. Line prices are GST-inclusive by default; pass pricesIncludeGst: false for GST-exclusive amounts (or set priceIncludesGst per line). GST is broken out at 15%.list_invoices — recent invoices for a channel with totals, status and pay links.The tool drives the admin API POST/GET /api/v2/admin/channels/{channelCode}/invoices (JWT admin auth, ROLE_API_ACCESS).
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).
billing_invoice — one row per invoice: channel, number (INV-NNNNN), public token, GST-exclusive subtotal_cents, gst_cents, total_cents, status, and the Volley request_id / merchant_identifier.billing_invoice_line — line items (description, quantity, unit_price_cents, position).Money is stored in integer cents throughout.