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. That holds for the derived families at the bottom of this file too — they are derived from the ROUTE TABLE'S OWN gate wiring, so a sentence is generated rather than repeated, and the generator is still reading the handler.
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 Cart
- type CartItem
- type CartItemSet
- type CartOpen
- type CartRef
- 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,
cartPrefix,
}
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 Cart ¶ added in v1.801.477
type Cart struct {
// ID is the cart's id — what every other cart op addresses it by, and what a
// storefront persists against the browser session.
ID string `json:"id"`
// Status is "active" for a cart still being filled, "ordered" once checkout
// turned it into an order, and "discarded" when the shopper abandoned it.
Status string `json:"status"`
// Currency is the ISO 4217 code every amount below is denominated in.
Currency string `json:"currency"`
// Email is the shopper's address, when the cart carries one.
Email string `json:"email,omitempty"`
// User is the signed-in shopper this cart belongs to, empty for a guest cart.
User string `json:"user,omitempty"`
// Store is the storefront the cart is being filled on.
Store string `json:"store,omitempty"`
// Order is the order this cart became, once checkout completed it. Empty
// until then, and its presence is what makes a cart final.
Order string `json:"order,omitempty"`
// Items are the cart's lines, in the order they were added.
Items []CartItem `json:"items"`
// LineTotalCents is the sum of the lines before any discount, in whole cents.
LineTotalCents int64 `json:"lineTotalCents"`
// DiscountCents is what coupons and promotions took off, in whole cents.
DiscountCents int64 `json:"discountCents"`
// SubtotalCents is LineTotalCents less DiscountCents, in whole cents.
SubtotalCents int64 `json:"subtotalCents"`
// ShippingCents is the shipping charge, in whole cents. It stays zero until a
// shipping option is priced at checkout.
ShippingCents int64 `json:"shippingCents"`
// TaxCents is the sales tax, in whole cents. It stays zero until checkout
// resolves the shopper's tax region.
TaxCents int64 `json:"taxCents"`
// TotalCents is what the shopper pays: subtotal plus shipping plus tax, in
// whole cents.
TotalCents int64 `json:"totalCents"`
// CreatedAt is when the cart was opened, RFC3339.
CreatedAt string `json:"createdAt,omitempty"`
// UpdatedAt is when the cart was last amended, RFC3339.
UpdatedAt string `json:"updatedAt,omitempty"`
}
Cart is a shopper's basket: what is in it, and what it comes to.
type CartItem ¶ added in v1.801.477
type CartItem struct {
// ID is the line's identity — the variant id when the line is a variant,
// otherwise the product id. It is what a subsequent set call addresses.
ID string `json:"id"`
// Kind is "variant" when this line is a specific sellable variant and
// "product" when it is the product itself.
Kind string `json:"kind"`
// Name is the item's display name, cached onto the line when it was added so
// a cart renders without a second read.
Name string `json:"name,omitempty"`
// SKU is the line's stock-keeping unit — the variant's when it has one,
// otherwise the product's. Empty when neither carries one.
SKU string `json:"sku,omitempty"`
// Quantity is how many units of this item the cart holds.
Quantity int `json:"quantity"`
// PriceCents is the unit price in whole cents, cached at the moment the line
// was added. The line's contribution to the cart is this times Quantity.
PriceCents int64 `json:"priceCents"`
// Free reports a line that costs nothing because a coupon or a promotion made
// it so, rather than because its price is zero.
Free bool `json:"free,omitempty"`
}
CartItem is one line of a cart, as the cart holds it.
type CartItemSet ¶ added in v1.801.477
type CartItemSet struct {
// ID is the cart to amend, from the path.
ID string `json:"id"`
// Product names the catalog product to set, by its id or its URL slug. Give
// this or Variant, never both; a request naming neither is refused.
Product string `json:"product,omitempty" url:"-"`
// Variant names the specific sellable variant to set, by its id or its SKU.
// Prefer it over Product for anything sold in sizes, colours or tiers — the
// price and the stock are the variant's, not the product's.
Variant string `json:"variant,omitempty" url:"-"`
// Quantity is how many of that item the cart should hold AFTER this call — it
// is the resulting count, not a delta, so sending 3 twice leaves 3 and not 6.
// ZERO REMOVES the line, which is the only way to take an item out.
Quantity int `json:"quantity" url:"-"`
}
CartItemSet sets one line's quantity. It is the whole vocabulary for changing a cart's contents — add, change and remove are the same act at three quantities.
type CartOpen ¶ added in v1.801.477
type CartOpen struct {
// Email is the shopper's address, for a cart that belongs to someone who has
// not signed in. It is what a guest checkout and an abandoned-cart follow-up
// key on. Empty is fine.
Email string `json:"email,omitempty" url:"-"`
// User is the id of the signed-in shopper this cart belongs to, when there is
// one. Empty means a guest cart identified only by its own id.
User string `json:"user,omitempty" url:"-"`
// Store is the storefront this cart is being filled on. Empty uses the org's
// default store, which is what a single-storefront merchant always wants.
Store string `json:"store,omitempty" url:"-"`
// Currency is the ISO 4217 code the cart is priced in, lower-cased. Empty
// means usd.
Currency string `json:"currency,omitempty" url:"-"`
}
CartOpen is a new cart to open. Every field is optional: a cart with nothing on it is a legitimate empty basket, and the fields below only pre-fill what the caller already knows about the shopper.
type CartRef ¶ added in v1.801.477
type CartRef struct {
// ID is the cart's id, as the open call answered it.
ID string `json:"id"`
}
CartRef names one cart to read or discard. The id is the path segment: the URL is the addressing authority, so it binds from there whatever else arrives.
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). |