Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 4 additions & 3 deletions content/docs/ledger/getting-started/core-concepts.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ A **Wallet** is a digital balance tracked in Ledger. Wallets are polymorphic —

Wallet operations:
- **Credit** — manual credit, no gateway charge
- **Top-Up** — gateway-charged top-up via Stripe or QPay
- **Top-Up** — gateway-charged top-up via GNU Taler, Stripe, or QPay
- **Transfer** — move funds between two wallets — produces two transactions (`transfer_out` and `transfer_in`) and one journal entry between the two wallet liability accounts
- **Payout** — debit the wallet (e.g., driver earnings payout)
- **Freeze / Unfreeze** — toggle status. The `is_frozen` attribute is a **computed accessor** derived from `status === 'frozen'`
Expand Down Expand Up @@ -130,10 +130,11 @@ See [Transactions](/docs/ledger/payments/transactions).

## Payment Gateways

**Gateways** are payment processors with encrypted credentials. Ledger ships with three drivers:
**Gateways** are payment processors with encrypted credentials. Ledger ships with four drivers:

| Driver | Capabilities |
| :--- | :--- |
| `taler` | purchase, refund, wallet payment URI, refund URI, webhooks, diagnostics, settlement checks, sandbox |
| `stripe` | purchase, refund, tokenization, setup_intent, checkout_session, webhooks, sandbox, recurring |
| `qpay` | purchase, refund, webhooks, sandbox |
| `cash` | purchase, refund |
Expand Down Expand Up @@ -163,6 +164,6 @@ Storefront Checkout completes (order.type === 'storefront')

Wallet flows:
```
Customer top-up via Stripe → GatewayTransaction logged → Wallet Transaction (deposit, credit) → Journal entry (DEBIT Cash → CREDIT Wallet Liability)
Customer top-up via GNU Taler, Stripe, or QPay → GatewayTransaction logged → Wallet Transaction (deposit, credit) → Journal entry (DEBIT Cash → CREDIT Wallet Liability)
Driver earning payout → Wallet Transaction (payout, debit) → Journal entry (DEBIT Wallet Liability → CREDIT Cash)
```
5 changes: 3 additions & 2 deletions content/docs/ledger/getting-started/quickstart.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -51,10 +51,10 @@ See [Settings](/docs/ledger/settings/overview) for the full reference.
Navigate to **Ledger → Payments → Gateways**.
</Step>
<Step>
Click **New Gateway** and select **Stripe** (or **Cash** for offline / manual receipts).
Click **New Gateway** and select **GNU Taler**, **Stripe**, **Cash**, or **QPay**. Use Cash for offline or manual receipts.
</Step>
<Step>
Fill in the credentials shown by the form — for Stripe: **Publishable Key**, **Secret Key**, and **Webhook Signing Secret**.
Fill in the credentials shown by the form. GNU Taler requires a Merchant Backend URL, instance ID, API token, and supported currency; Stripe requires a publishable key, secret key, and webhook signing secret.
</Step>
<Step>
Set **Environment** to `sandbox` while testing.
Expand Down Expand Up @@ -129,6 +129,7 @@ When the customer pays:
## Next Steps

- [Chart of Accounts](/docs/ledger/accounting/chart-of-accounts) — review the seeded accounts and add custom ones
- [Payment Gateways](/docs/ledger/payments/gateways/overview) — configure GNU Taler, Stripe, Cash, or QPay
- [Wallets](/docs/ledger/payments/wallets) — manage driver, customer, company, and user wallets
- [Reports](/docs/ledger/reports/overview) — generate balance sheets, income statements, AR aging, and the wallet summary
- [Settings](/docs/ledger/settings/overview) — configure invoice prefixes, payment terms, default gateways, and fiscal year
4 changes: 2 additions & 2 deletions content/docs/ledger/index.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ description: Ledger is the accounting and invoicing extension for Fleetbase —
| **Invoicing** | Create, send, and collect payment on invoices |
| **Invoice Templates** | Customize the look of your invoices with company branding |
| **Digital Wallets** | Track balances for drivers, customers, your company, and individual users |
| **Payment Gateways** | Stripe, QPay, and Cash — purchases, refunds, and webhook idempotency |
| **Payment Gateways** | GNU Taler, Stripe, Cash, and QPay - purchases, refunds, wallet payment flows, and webhook idempotency |
| **Transactions** | Immutable audit trail for every wallet movement |
| **Financial Reports** | Balance sheet, income statement, cash flow, trial balance, AR aging, wallet summary |
| **Fleet-Ops Integration** | Auto-create draft invoices when a `PurchaseRate` is added to an order |
Expand All @@ -32,7 +32,7 @@ description: Ledger is the accounting and invoicing extension for Fleetbase —
- **Invoice** — a formal request for payment with line items, tax, and due date. Numbered `INV-` plus a 6-digit random integer (e.g. `INV-004821`). Lifecycle: draft → sent → viewed → partial / paid / overdue / cancelled / refunded / void
- **Wallet** — a digital balance tied to a driver, customer, company, or user. Supports `credit`, `topup`, `transfer`, `payout`, `freeze`, `unfreeze`, and `recalculate` operations
- **Transaction** — an immutable record of money moving relative to a wallet
- **Gateway** — a payment processor (Stripe, QPay, or Cash) with encrypted credentials, sandbox/live environment, and webhook idempotency via `GatewayTransaction`
- **Gateway** — a payment processor (GNU Taler, Stripe, Cash, or QPay) with encrypted credentials, sandbox/live environment, and webhook idempotency via `GatewayTransaction`

## Getting Started

Expand Down
123 changes: 0 additions & 123 deletions content/docs/ledger/payments/gateways.mdx

This file was deleted.

21 changes: 21 additions & 0 deletions content/docs/ledger/payments/gateways/cash.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
---
title: Cash
description: Configure the Cash gateway for manual and offline payment collection in Ledger.
---

# Cash

The Cash gateway records manual or offline payment collection without contacting an external processor. Use it when an operator collects cash, bank transfer confirmation, cheque payment, or another offline receipt and needs Ledger to record the invoice payment.

## Configuration

| Field | Description |
| :--- | :--- |
| **Label** | Optional label shown to operators |
| **Instructions** | Optional payment instructions surfaced to customers or staff |

## Behavior

Cash supports purchases and refunds from Ledger's perspective, but it does not provide hosted checkout, webhooks, tokenization, or settlement verification. Operators are responsible for confirming that the money was collected before recording the payment.

The resulting Ledger transaction and journal entry are still created, so reports and invoice balances remain consistent with other gateways.
156 changes: 156 additions & 0 deletions content/docs/ledger/payments/gateways/gnu-taler.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,156 @@
---
title: GNU Taler
description: Configure the GNU Taler payment gateway for wallet payments, tenant-safe webhooks, refunds, diagnostics, and settlement checks.
---

# GNU Taler

GNU Taler is a wallet-based digital cash gateway for Ledger. Customers pay an invoice from a Taler wallet, the Taler Merchant Backend sends Ledger a tenant-scoped webhook, and Ledger updates the invoice, gateway transaction log, refund state, and settlement metadata.

Use GNU Taler when you need privacy-preserving wallet payments, a deployed Taler Merchant Backend, and auditable payment/refund records inside Ledger.

## Requirements

| Requirement | Description |
| :--- | :--- |
| **Merchant Backend URL** | Base URL for the Taler Merchant Backend, without private credentials in the URL |
| **Instance ID** | Taler merchant instance used by this Ledger gateway |
| **API Token** | Merchant Backend token with permission to create orders, read order status, issue refunds, and create/update webhooks |
| **Currency** | Currency accepted by the Taler exchange and configured for Ledger invoices |
| **HTTPS Webhook URL** | Public Ledger webhook URL reachable by the Taler Merchant Backend |

Keep sandbox and production credentials outside the repository. Use environment variables, secret storage, or the encrypted Ledger gateway configuration.

## Fleetbase Hosted Sandbox

Fleetbase provides hosted GNU Taler sandbox services for Ledger testing:

| Service | URL | Used For |
| :--- | :--- | :--- |
| **Merchant Backend** | `https://merchant.taler.fleetbase.io` | Ledger gateway API calls, order creation, refunds, webhooks, and settlement checks |
| **Exchange** | `https://exchange.taler.fleetbase.io` | Wallet exchange visibility and sandbox exchange diagnostics |
| **Bank** | `https://bank.taler.fleetbase.io` | Sandbox wallet funding and bank-side test operations |

Ledger talks directly to the Merchant Backend. The exchange and bank endpoints support wallet funding, wallet trust/exchange visibility, sandbox testing, and operator diagnostics.

When a GNU Taler gateway is in `sandbox` mode and the Merchant Backend URL is left blank, Ledger defaults to `https://merchant.taler.fleetbase.io`. Live gateways do not use this fallback and should always be configured with your production Merchant Backend URL.

## Configure The Gateway

<Steps>
<Step>
Navigate to **Ledger -> Payments -> Gateways**.
</Step>
<Step>
Click **New Gateway** and select the `taler` driver.
</Step>
<Step>
Enter the Merchant Backend URL, instance ID, API token, and the currencies this gateway should accept. For Fleetbase hosted sandbox testing, you can leave the Merchant Backend URL blank or use `https://merchant.taler.fleetbase.io`.
</Step>
<Step>
Set the environment to `sandbox` for test wallets or `live` for production wallets.
</Step>
<Step>
Save the gateway, then open the gateway details screen.
</Step>
<Step>
Run **Test Credentials**, **Create Test Order**, and **Register Webhook** before enabling the gateway for invoices.
</Step>
</Steps>

## Admin Diagnostics

The Taler gateway details screen includes operational checks for:

| Diagnostic | Meaning |
| :--- | :--- |
| **Credential status** | Ledger can reach the Merchant Backend with the configured token |
| **Webhook registration** | Ledger registered or updated the Merchant Backend webhook callback |
| **Last webhook received** | Most recent Taler webhook accepted by Ledger |
| **Last payment event** | Most recent Taler payment event recorded in `GatewayTransaction` |
| **Last refund event** | Most recent Taler refund event, including wallet refund URI data |
| **Last settlement check** | Most recent reconciliation check against Taler order status or wire metadata |

Non-Taler gateways may not expose every diagnostic action. Unsupported actions return an unsupported response instead of changing gateway state.

## Webhook Payload

Provisioned GNU Taler webhooks must post enough data for exact tenant-safe routing:

```json
{
"order_id": "order_123",
"company_uuid": "company_uuid",
"gateway_id": "gateway_public_id",
"event_type": "pay"
}
```

`gateway_uuid` can be used instead of `gateway_id` when the UUID is the identifier available to the provisioning flow. For provisioned webhooks, `order_id`, `company_uuid`, and one gateway identifier are required.

Ledger rejects ambiguous multi-company Taler callbacks rather than selecting the first active gateway. Failed resolution is recorded as a failed gateway transaction so operators can diagnose unknown gateway, wrong company, or missing routing metadata.

Duplicate Taler notifications are idempotent. Ledger keeps the gateway transaction key and includes gateway/company scope in duplicate handling and logs.

## Payment Flow

1. Ledger creates a Taler order for the invoice amount and stores the order reference.
2. The public invoice page shows the Taler payment URI or QR code.
3. The customer pays with a Taler wallet.
4. The Merchant Backend posts the tenant-scoped webhook to Ledger.
5. Ledger verifies the order state, records the gateway transaction, and marks the invoice paid or partially paid according to the normalized amount.
6. A Ledger transaction and journal entry are created for the invoice payment.

If the webhook reports an unpaid or unknown order, Ledger records the event and leaves the invoice unpaid.

## Refunds

Taler refunds have two separate stages:

| Stage | Ledger Behavior |
| :--- | :--- |
| Backend refund requested or approved | Ledger records the refund gateway transaction and normalized refund amount |
| Wallet refund URI returned | The internal refund response includes `taler_refund_uri` and `refund_url` for customer wallet processing |
| Wallet accepted | Ledger updates refund status when the accepted state is observable |
| Failed or expired | Ledger records the failed or expired outcome and keeps the invoice/payment history auditable |

Partial refunds reduce the paid balance without forcing the invoice to fully refunded. Full refunds move the invoice to a refunded state once cumulative refunded amount reaches the paid amount. Refund reversals are linked to Ledger transactions and journal entries.

## Settlement And Reconciliation

Settlement verification checks paid Taler orders against the Merchant Backend order status. Ledger records the last settlement status, check timestamp, deposit totals, wire transfer identifiers, and raw Taler settlement fields when the backend exposes them.

Some sandbox or backend responses may not include a stable wire transfer identifier. In that case Ledger marks the record as settlement checked rather than wire reconciled and stores the best available Taler fields for audit.

## Sandbox E2E Validation

Live sandbox validation is opt-in and should not run in normal CI. Configure the sandbox from environment variables or an encrypted gateway record:

```bash
TALER_E2E_ENABLED=true
TALER_E2E_BACKEND_URL=https://merchant.taler.fleetbase.io
TALER_E2E_INSTANCE_ID=default
TALER_E2E_API_TOKEN=...
TALER_E2E_COMPANY_UUID=...
```

The acceptance flow is:

1. Create or select a Taler gateway.
2. Create an invoice.
3. Start payment and pay with a sandbox wallet.
4. Receive the webhook and confirm the invoice moves to paid.
5. Issue a partial or full refund.
6. Confirm the refund URI is returned and the Ledger reversal is created.
7. Verify settlement or reconciliation metadata after the settlement check runs.

Never commit real sandbox URLs, API tokens, wallet secrets, or private Merchant Backend credentials.

## Production Runbook

- Use HTTPS for the Ledger webhook URL.
- Scope the Merchant Backend token to only the permissions needed by Ledger.
- Register webhooks from the Ledger gateway details screen so `company_uuid` and gateway identifiers are included.
- Confirm diagnostics before enabling the gateway for public invoices.
- Keep gateway records company-scoped and avoid sharing one Merchant Backend instance across companies without tenant-safe webhook metadata.
- Monitor `GatewayTransaction` rows for failed webhooks, duplicate delivery, refund state, and settlement status.
10 changes: 10 additions & 0 deletions content/docs/ledger/payments/gateways/meta.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
{
"title": "Payment Gateways",
"pages": [
"overview",
"gnu-taler",
"stripe",
"cash",
"qpay"
]
}
Loading