pushing stuff that was worked on

This commit is contained in:
twooey committed 2026-08-28 15:17:46 -04:00
1 parent 773883a0f3
commit 197938f482
22 files changed
+1251 -124

No files matched your search

+39 -28
View File
@@ -101,13 +101,18 @@ After that, the starter site's content and Customizer settings persist in
the database like any other WordPress content — a redeploy or a fresh
`deploy.sh` run doesn't touch it or need to repeat it.
### Payments: Helcim
### Payments: Helcim (preauth/capture)
`deploy.sh` installs and activates the free, wordpress.org-hosted **Helcim
for WooCommerce** plugin (`helcim-commerce-for-woocommerce`) automatically
in every environment — nothing to do here for that part.
The Helcim gateway is a **custom `WC_Payment_Gateway`** shipped inside
`bookstore-core` (`Payments\HelcimGateway`, built directly against
HelcimPay.js) — not the off-the-shelf `helcim-commerce-for-woocommerce`
plugin, which `deploy.sh` deliberately does not install (it only
supports immediate charges; see design doc Appendix B). Checkout
authorizes (holds) the card; the charge only actually happens once the
supplier order succeeds (`Order\SupplierOrderJob`) — see that class and
`Payments\HelcimClient`'s docblocks for the full sequence.
The plugin needs a Helcim **sandbox API token**, which isn't something a
The gateway needs a Helcim **sandbox API token**, which isn't something a
public API can hand out, so it's a one-time manual step per environment:
1. Sign up for a free Helcim account.
@@ -118,13 +123,17 @@ public API can hand out, so it's a one-time manual step per environment:
`deploy.sh` writes the token to a gitignored secrets file the same way it
already does for `HARDCOVER_API_TOKEN` (see `secrets/<env>/` above), and
`Payments\HelcimConfig::ensure_configured_from_env()` seeds the gateway's
WooCommerce settings (sandbox mode, disabled by default — a human still
enables it at checkout once ready) the first time it finds a token. Until a
token exists, the plugin is installed and inert; nothing else in this repo
is blocked on it. Go-live (switching the gateway from sandbox to Helcim's
live environment) is a deliberate manual step on the settings screen, not
something this repo automates.
`Payments\HelcimGatewayConfig::ensure_configured_from_env()` seeds the
gateway's WooCommerce settings (sandbox mode, disabled by default — a
human still enables it at checkout once ready) the first time it finds a
token. **Until a token exists, `Payments\HelcimClient` runs in fake
mode** — every preauth/capture/reverse call returns a synthetic approved
response instead of hitting the real API, so the whole checkout ->
preauth -> fraud review -> supplier order -> capture/reverse flow is
testable end-to-end without one (same pattern as the synthetic
`gutenberg_test` supplier). Go-live (switching from sandbox to Helcim's
live environment) is a deliberate manual step on the settings screen,
not something this repo automates.
### Admin access restriction (production)
@@ -201,28 +210,30 @@ with a bigger `--limit` continues forward instead of rescanning. Pricing
`includes/Pricing/PricingEngine.php` and
`includes/Shipping/BSC_Free_Shipping.php`.
## Checkout + order engine (Week 3)
## Checkout + order engine (Week 3, payment flow revised)
Helcim's WooCommerce plugin is installed (see "Payments: Helcim" above),
paired with a synchronous pre-charge supplier/margin recheck and a
fraud-check hook — both run right before the payment gateway is called
(`Order\CheckoutRecheck`), never after. A passing order moves through a
custom status sequence beyond WooCommerce's own pending/processing/
completed: `bsc-ordered` (submitted to the supplier via Action
Scheduler, `Order\SupplierOrderJob`) → `bsc-shipped` → `completed`. Any
failure at any stage — no sellable offer, margin no longer holds, fraud
check fails, or the supplier submission itself fails after charging — lands
the order in `bsc-exception` ("Needs Review"), which is the review queue:
just a filterable WooCommerce order status, not a separate table. A
post-charge failure also triggers an automatic refund
(`wc_create_refund(..., refund_payment: true)`), per the design doc's
Appendix B decision that an undo is always a refund, never a void.
A synchronous pre-authorization supplier/margin recheck runs right
before the card is held (`Order\CheckoutRecheck`, price/margin only —
never charges anything). The custom Helcim gateway (see "Payments:
Helcim" above) then holds the card and, once the fraud check
(`Payments\FraudCheck`) passes, moves the order to `bsc-authorized`
(held, not charged). `Order\SupplierOrderJob` picks it up from there:
submits to the supplier, and only on success **captures** the hold (the
card is actually charged for the first time here) before moving to
`bsc-ordered` → `bsc-shipped` → `completed`. Any failure at any stage —
no sellable offer, margin no longer holds, fraud check fails, or the
supplier submission itself fails — lands the order in `bsc-exception`
("Needs Review"), which is the review queue: just a filterable
WooCommerce order status, not a separate table. Because nothing is
charged until capture, most failures are a **void** (`AuditTrail::record_void()`,
zero cost) rather than a refund — a refund only happens for the rarer
case of something going wrong *after* a real capture.
`wp bookstore force-offer-status <isbn13> <active|stale|discontinued>` (see
`wp bookstore help`) forces a specific ISBN's synthetic offer into a
specific state — `SyntheticOfferGenerator`'s rolls are random, so this is
how to reliably exercise the recheck's failure paths (price-increase,
out-of-stock, discontinued-after-charge) in a real checkout.
out-of-stock, discontinued-after-supplier-submission) in a real checkout.
Real BooksRun/Ingram supplier adapters are still Week 4 — `SupplierOrderJob`
runs against the synthetic `gutenberg_test` supplier for now, deliberately