15 Commits

Author SHA1 Message Date
2c12ba586e feat(sca): charge checkout as customer-initiated transaction (#57)
Drop off_session from the initial PaymentIntent so the checkout charge is a Customer-Initiated Transaction (the customer is present in the TUI), not a Merchant-Initiated Transaction. MIT exemptions require a stored mandate we never capture; as a CIT, an SCA challenge surfaces as status=requires_action, the path the handler already had. The re-confirm in respondRequiresAction and the authentication_required error branch remain as defensive fallbacks. Source: stripe-samples accept-a-payment custom-payment-flow (no off_session on customer-present confirms).

Also clarify the MAX_ORDER_CENTS TRA-ceiling anchor comment as an approximate USD/EUR figure (config.go), and carry an unrelated 1-line spend-limit input width fix in pkg/tui/account.go.

Tests: add paymentIntentNewFn stub seam, TestConvertCartIsCustomerInitiated (asserts no off_session) and TestConvertCartRequiresAction (202 + redirect + audit row).

Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-18 10:48:00 +02:00
e85dc7fd4d fix(webhook): fail closed when stripe webhook secret is not set (#45) 2026-06-14 22:12:36 +02:00
ff562c7427 docs(docs): update docs to get rid of gopls warnings. update some code to newer standards (#49) 2026-06-14 21:42:02 +02:00
53e934be3b chore(cap): raise per-order spend cap default from 200 to 500 (#39) 2026-06-07 23:47:43 +02:00
bb960c31f8 feat(sca): sweep abandoned 3ds requires_action orders to failed (#37)
* feat(sca): sweep abandoned 3ds requires_action orders to failed

* fix(sca): address pr review on abandoned 3ds sweep

- Drop stripe.Key write in ReconcileStale3DSOrders; wire once in api/main.go after cfg.Load so concurrent reconcilers don't
race the SDK global.
- Add empty-PI short-circuit before paymentintent.Get to bury a future regression in a slog.Warn instead of a Stripe 4xx.
- Swap fmt.Printf for slog.Warn with k/v attrs in loadAbandoned3DSThresholdMinutes so Loki sees structured fields instead of
 literal %q/%d.
- Comment the updated_at predicate (RetryAuth bumps it via GORM auto-stamp, intentional grace-window extension) + the
conditional-UPDATE/map-form choice.
- Tests: processing/requires_capture skip, unknown-status skip, stripe-error skip, empty-PI skip, full env-parse table for
loadAbandoned3DSThresholdMinutes.

* fix(stripe): wire key once at init drop per-call writes

* refactor(stripe): drop dead stripeKey fields and pre-call sdk params
2026-06-07 18:16:33 +02:00
2f65cf0d90 feat(sca): cap per-order total ro prevent oversize charges (#26) 2026-06-01 22:40:20 +02:00
c1b3ccf302 feat(notify): add buy label button via slack 2026-05-15 10:57:23 +02:00
ee6e14a424 feat(shipping): shippo webhook fro tracking status updates 2026-05-14 13:30:37 +02:00
387758aa13 feat(shipping): add Bring booking client and country dispatch for label purchase 2026-05-13 22:14:32 +02:00
b92132474b various error checks and formatting 2026-04-14 15:26:36 +02:00
6094e05b6f feat: shorten checkout URLs via in-memory redirect for smaller QR codes
Stripe checkout URLs are too long to produce a scannable QR code in a
terminal. Add an in-memory token→URL store and a /pay/{token} redirect
endpoint so the TUI shows a short URL (e.g. localhost:8080/pay/a3f1c2b4)
that fits in a QR. APP_URL config controls the base URL (defaults to
API_URL). Revert to returning sess.URL directly in CollectCard if this
approach needs to be abandoned.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-07 21:55:52 +02:00
f6ca8836c9 feat: added Bring address validation for Norwegian addresses 2026-03-01 20:52:36 +01:00
6097b8c863 rework: added shipping validation at address creation
the last implementation just accepted any input for the shipping
validation and then only validated the address on payment. this is now
changed to validation upon creation upon finishing the shipping address
form.

when a user completes the shipping form, a client-side check is first
made to just simply check if there are any empty fields, if this check
passes it gets check server-side by shippo. If the address is not found
it will return an address not found error, and the user will not be able
to continue to the payment form. The invalid address will also not be
saved to the database.

if the check pass, we simply save the address to the database with an
ID. this ID is then passe in when doing the payment, instead of
validating at the payment phase.

this implementation currently only uses Shippo, which i have come to
realize does NOT support shipping in countries outside of the US (i
should have read the friendly manual before using Shippo). This means
that a huge rewrite is due.

i will focus on adding address validation for Norway first since thats
where i live. i plan on using Bring's api for this validation. i will
still keep Shippo for US based address verification even though this
project is focused fon nordic shipping - just for a rainy day if some
poor soul decides to order from AMERICA
2026-02-26 16:32:48 +01:00
7ebc5b24de updating the ui fr 2026-02-26 10:16:57 +01:00
f62b28d29b first commit after chaning git structure on pc 2026-02-16 11:42:43 +01:00