Documentation
¶
Overview ¶
describe.go is commerce's PROSE. Every operation this subsystem serves is registered by the embedded hanzoai/commerce module — its own route tables, its own handlers, in another module — so there is no doc comment in this repo for zipdoc to lift and no typed op to lift it from. Left bare, all 75 published an operationId and NOTHING else: an SDK method that cannot explain itself, an MCP tool a model cannot pick, a CLI command with no help text.
openapi.Describe is the seam for exactly that operation. It carries the same drift-proof property Register has — a description whose route the router does not carry never renders — so this file cannot add an operation, only explain one that exists. The key is the fiber pattern VERBATIM, which is how the projector addresses a live route (openapi/openapi.go From).
The prose is written from the handlers, not from the paths: each summary is what the caller GETS, and each description states the gate, the tenant scope, what it fails closed on, and the one rule a reader would otherwise get wrong.
Package commerce is selling: checkout, subscriptions, invoices, spend alerts, payment webhooks and the storefront catalog.
It is the merchant half, embedded from hanzoai/commerce and mounted on cloud's own router. It is not the wallet — EmbedConfig.Ledger injects apps/finance, so a credit minted here lands in the one ledger of record.
This file mounts that MODULE into a cloud binary (HIP-0106) via the NATIVE co-residence contract: commerce registers its routes directly on the HOST's zip app (EmbedConfig.App) — one router, one specificity space, zero handler adaptation. This adapter narrows cloud.Deps, boots the embed, and wires the in-process seams. Direction is one-way: cloud → commerce.
PCI SCOPE. Commerce is a LIGHT ROUTER, NOT in PCI-DSS scope: tokens + intent IDs only, NEVER a PAN. PAN-touching paths call the out-of-process Payments / Vault (ZAP-RPC); when those clients are absent the payment handlers fail closed while tenant config + admin stay served — Mount warns loudly at startup.
FAIL-SOFT. A broken Embed does NOT crash the binary: commerce degrades to a 503 on its own prefixes while every co-resident subsystem stays up.
Index ¶
- Variables
- func BalanceCents(ctx context.Context, org, subject, currency string, test bool) (int64, error)
- func Mount(app cloud.Router, deps cloud.Deps) error
- func PublishEmbedded(e *commercemod.Embedded)
- type Client
- type CollectOut
- type InvoiceLineIn
- type InvoiceOut
- type InvoiceRefIn
- type PaymentIn
- type PaymentOut
- type PaymentRecord
- type PaymentRef
- type RaiseInvoiceIn
Constants ¶
This section is empty.
Variables ¶
var Prefixes = []string{
"/v1/commerce",
"/_/commerce",
"/v1/store",
"/v1/catalog",
"/v1/plans",
"/v1/billing/webhooks",
"/v1/billing/recharge",
paymentsPrefix,
}
Prefixes is every root path the commerce surface owns on the shared app. Under the native SharedApp contract most of these are registered by commerce's own setupRoutes; the list is the fail-closed 503 set AND the wire contract prefix_test pins — the route families a session gate or the AI /v1/* catch-all must never swallow.
It is exported because the composition root DECLARES it (apps.Wire's commerce entry, Prefixes: commerce.Prefixes), which is what puts commerce on the light host's manifest. Derived instead, the walk would read the `app.Group("/v1")` this file opens for the store/catalog/plan bundle as a claim on ALL of /v1 and hand commerce every request in the fleet. Same list, one owner, stated once.
Functions ¶
func BalanceCents ¶
BalanceCents returns subject's available prepaid balance (USD cents) in org, read DIRECTLY from the co-resident embedded commerce ledger — no HTTP hop. It is the native twin of the /v1/billing/balance read (billing.zapGetBalance): resolve the org's own datastore namespace, tally the subject's iam-user transactions in the currency, and return Balance - Holds clamped at zero. It reuses the SAME currentEmbedded seam the in-process entitlement client resolves through.
This is the read the money cutover (admin/finance backfill) and the admin cockpit's credit panels use when commerce runs in the SAME binary: the admin commerce HTTP client dials an unroutable in-proc address and reads $0, which would silently migrate/report nothing. When commerce is NOT co-resident this returns an ERROR (never 0), so a caller can tell "not wired" from a real zero balance and fail loud rather than move money on a phantom figure. Subject is lowercased + trimmed; an empty currency defaults to usd.
func Mount ¶
Mount boots commerce ON the shared zip app (native co-residence). commerce's own setupRoutes registers /v1/commerce/* and /_/commerce/* directly; the standalone-only surfaces (bare /healthz, legacy /admin SPA, checkout SPA root catch-all, Listen) are skipped by the SharedApp contract. This adapter registers the remaining wire-contract families with commerce's own gate chains (see Prefixes).
func PublishEmbedded ¶
func PublishEmbedded(e *commercemod.Embedded)
PublishEmbedded records the mounted Embedded as the in-process entitlement source. Mount calls it once; nil un-publishes (tests).
Types ¶
type Client ¶
type Client = types.CommerceClient
Client is the in-process inter-subsystem seam cloud's licensing/entitlements tier calls. It IS cloud's types.CommerceClient — one narrow interface (GetOrgConfig + the real CheckEntitlement), not a second copy — kept as an alias so a value satisfies both names with no adapter. Add methods here only when a consumer needs them; keep it narrow.
func InProcessClient ¶
InProcessClient returns the process-wide, lazily-resolved client cloud's pickCommerceClient wires as deps.Commerce. BuildDeps runs before MountAll, so it resolves the published Embedded per call rather than capturing one; brand answers OrgConfig even before Mount publishes.
type CollectOut ¶ added in v1.801.433
type CollectOut struct {
// Invoice is the invoice AFTER the attempt — its status is the authority on
// what happened, not this struct's other fields.
Invoice *InvoiceOut `json:"invoice"`
// Paid reports whether the invoice is now settled in full. A false here with
// no error is a DECLINE: the invoice stays open and may be collected again.
Paid bool `json:"paid"`
// CreditUsedCents is how much was covered by credit grants.
CreditUsedCents int64 `json:"creditUsedCents"`
// BalanceUsedCents is how much was covered by prepaid balance.
BalanceUsedCents int64 `json:"balanceUsedCents"`
// CardChargedCents is how much was charged to the card on file.
CardChargedCents int64 `json:"cardChargedCents"`
// ProcessorRef is the processor's reference for any card charge — the field
// that proves money moved at the gateway rather than only in our ledger.
ProcessorRef string `json:"processorRef,omitempty"`
// Reason explains a decline or partial collection. Empty on success.
Reason string `json:"reason,omitempty"`
}
CollectOut is the outcome of attempting to collect an invoice.
type InvoiceLineIn ¶ added in v1.801.433
type InvoiceLineIn struct {
// Description is the human-readable line, e.g. "Advisory retainer — August".
Description string `json:"description"`
// Amount is the line total in whole cents (250000 is $2,500.00).
Amount int64 `json:"amount"`
// Quantity is the number of units, when the line is metered. Optional.
Quantity int64 `json:"quantity,omitempty"`
// UnitPrice is the per-unit price in cents, when the line is metered. Optional.
UnitPrice int64 `json:"unitPrice,omitempty"`
}
InvoiceLineIn is one charge to put on an invoice.
type InvoiceOut ¶ added in v1.801.433
type InvoiceOut struct {
// ID is the invoice id — what the issue, collect and void ops address.
ID string `json:"id"`
// Number is the human-facing invoice number, e.g. "INV-0042". A draft has
// none; issuing assigns it.
Number string `json:"number,omitempty"`
// UserID is the customer billed.
UserID string `json:"userId"`
// CustomerEmail is where it is sent.
CustomerEmail string `json:"customerEmail,omitempty"`
// Status is draft, open, paid, void or uncollectible. A draft is not
// collectible; issuing moves it to open.
Status string `json:"status"`
// Currency is the ISO 4217 code.
Currency string `json:"currency"`
// SubtotalCents is the sum of the lines.
SubtotalCents int64 `json:"subtotalCents"`
// AmountDueCents is what remains collectible.
AmountDueCents int64 `json:"amountDueCents"`
// AmountPaidCents is what has been collected so far.
AmountPaidCents int64 `json:"amountPaidCents"`
// Lines are the charges on the invoice.
Lines []InvoiceLineIn `json:"lines,omitempty"`
// PaymentRef is the processor reference for the collection, once paid.
PaymentRef string `json:"paymentRef,omitempty"`
// CreatedAt is when the draft was raised, RFC3339.
CreatedAt string `json:"createdAt,omitempty"`
}
InvoiceOut is an invoice.
type InvoiceRefIn ¶ added in v1.801.433
type InvoiceRefIn struct {
// ID is the invoice id.
ID string `json:"id"`
}
InvoiceRefIn names one invoice to act on.
type PaymentIn ¶ added in v1.801.433
type PaymentIn struct {
// SourceID is the single-use payment token that stands in for the card: a
// Square Web Payments SDK nonce minted in the browser, or a Square sandbox
// test nonce when the org's credentials are sandbox ones. The card number
// itself never reaches this process, which is what keeps it out of PCI scope.
SourceID string `json:"sourceId"`
// AmountCents is the amount to charge, in whole cents (5000 is $50.00).
// Server-side bounds apply and are authoritative — the default floor is $1
// and the ceiling $5,000, so a fat-fingered or hostile amount is refused
// before any money moves.
AmountCents int64 `json:"amountCents"`
// Currency is the ISO 4217 code, lower-cased. Empty means usd.
Currency string `json:"currency,omitempty"`
// IdempotencyKey makes a retry safe: the same key never charges twice, it
// replays the first result. Sending one is strongly recommended for an agent,
// which retries by construction. Empty falls back to a windowed key derived
// from the amount and currency, so a double-submit inside 15 minutes still
// collapses onto one charge.
IdempotencyKey string `json:"idempotencyKey,omitempty"`
}
PaymentIn is a card payment to take. It carries WHAT to charge and nothing about WHO is paying — see the package note.
type PaymentOut ¶ added in v1.801.433
type PaymentOut struct {
// ID is the ledger transaction id for the credit. It is what getPayment
// reads back, and the customer-visible receipt for the money.
ID string `json:"id"`
// BalanceCents is the org's balance AFTER this payment, read back from the
// same key just credited so it matches what the balance endpoint reports.
BalanceCents int64 `json:"balanceCents"`
// Status is "ok" on a settled charge. A charge that did not settle is an
// error with the processor's reason, never a status field to inspect.
Status string `json:"status"`
// ProcessorRef is the payment processor's own reference for the charge
// (Square's payment id). It is the field that proves money actually moved at
// the gateway rather than only in our ledger — the thing to quote when
// reconciling against a processor dashboard.
ProcessorRef string `json:"processorRef,omitempty"`
// Test reports which bucket this credited: true is a SANDBOX charge crediting
// the test balance, false is live money. It is always stated so a receipt can
// never be mistaken for the other kind.
Test bool `json:"test"`
}
PaymentOut is the settled payment — the receipt.
type PaymentRecord ¶ added in v1.801.433
type PaymentRecord struct {
// ID is the ledger transaction id.
ID string `json:"id"`
// Subject is the billing key this payment credited.
Subject string `json:"subject"`
// AmountCents is the credited amount in whole cents.
AmountCents int64 `json:"amountCents"`
// Currency is the ISO 4217 code.
Currency string `json:"currency"`
// Status is the payment's state. This ledger writes a deposit only AFTER the
// processor settled, so a payment that can be read is one that succeeded.
Status string `json:"status"`
// Test reports whether this was a sandbox charge (test balance) or live money.
Test bool `json:"test"`
// Notes is the ledger memo, carrying the processor and its reference.
Notes string `json:"notes,omitempty"`
// CreatedAt is when the credit was written, RFC3339.
CreatedAt string `json:"createdAt,omitempty"`
}
PaymentRecord is a payment as the ledger holds it.
type PaymentRef ¶ added in v1.801.433
type PaymentRef struct {
// ID is the ledger transaction id a payment returned.
ID string `json:"id"`
}
PaymentRef names one payment to read.
type RaiseInvoiceIn ¶ added in v1.801.433
type RaiseInvoiceIn struct {
// UserID identifies the customer being billed, within the caller's own org.
// Required — an invoice with no addressee is not an invoice.
UserID string `json:"userId"`
// CustomerEmail is where the invoice is sent. Optional.
CustomerEmail string `json:"customerEmail,omitempty"`
// Currency is the ISO 4217 code, lower-cased. Empty means usd.
Currency string `json:"currency,omitempty"`
// Lines are the charges. The invoice subtotal and amount due are COMPUTED
// from these — there is no total field to send, because a total that
// disagreed with its own lines would bill a number nobody could derive.
Lines []InvoiceLineIn `json:"lines,omitempty"`
}
RaiseInvoiceIn is a draft invoice to raise against a customer.
Source Files
¶
Directories
¶
| Path | Synopsis |
|---|---|
|
Package transport is the ONE seam that lets every cloud subsystem that speaks the commerce billing S2S surface (clients/{billing,account,admin, referrals,authors,affiliates,usage} + the request-edge metering gate in build.go) reach the co-resident, in-process commerce handler with a DIRECT Go call instead of an HTTP hop to the standalone commerce pod (CLOUD_COMMERCE_HTTP_URL, commerce.hanzo.svc:8001).
|
Package transport is the ONE seam that lets every cloud subsystem that speaks the commerce billing S2S surface (clients/{billing,account,admin, referrals,authors,affiliates,usage} + the request-edge metering gate in build.go) reach the co-resident, in-process commerce handler with a DIRECT Go call instead of an HTTP hop to the standalone commerce pod (CLOUD_COMMERCE_HTTP_URL, commerce.hanzo.svc:8001). |