Skip to content
13Caso studioSW · 13 di 10

Commercio su ordinazione per un mercato che ha bisogno del proprio stack.

Gli stack ecommerce generici non riuscivano a modellare le primitive finanziarie e logistiche richieste da questo mercato. Pagamento frazionato Monobank, evasione Nova Post, multivaluta per singolo prodotto: costruiti da zero per un marchio artigianale ucraino che spedisce in 7 lingue.

ClienteRiservato
Anno2026
Durata1 yrs
StackTypeScript · Next.js · React · Postgres · Vercel · AWS
Hero image for maker-brand-commerce-platformFIG 01 · HERO

Il vincolo dell'artigiano.

Prodotti fatti a mano dall'Ucraina, spediti in sette Paesi. L'infrastruttura finanziaria e logistica su cui gira il mercato — Monobank per i pagamenti, Nova Post per l'evasione, i tassi di cambio giornalieri della Banca Nazionale dell'Ucraina per i prezzi — non ha alcun equivalente in uno stack ecommerce europeo generico.

Il solo modello di pagamento esclude Stripe. Il modello a pagamento frazionato di Monobank incassa un acconto alla conferma dell'ordine e attiva l'addebito del saldo quando l'ordine raggiunge lo stato «pronto per la spedizione». Sono due tranche di pagamento, scandite in base allo stato di produzione, con firme webhook ECDSA a ogni transizione. Stripe non ha una primitiva per questo. Dovresti simularlo con due addebiti scollegati e riconciliare lo stato da solo — e ogni scarto di riconciliazione è una superficie di frode.

Il modello logistico esclude Shippo. Nova Post, il corriere dominante in Ucraina, espone una directory di città, filiali e classificatori che vanno sincronizzati e interrogati in locale. Le lettere di vettura vengono generate via codice al momento della spedizione e il PDF dell'etichetta risultante deve risiedere da qualche parte recuperabile. Nulla nel mondo dell'astrazione del corriere generico mappa a tutto questo in modo pulito.

Il modello di prezzo esclude le impostazioni di valuta per regione. L'artigiano vende alcuni prodotti a livello globale in EUR, altri solo in UAH perché la catena di fornitura è locale. Alcuni prodotti portano override espliciti in UAH o USD che differiscono dalla base convertita al cambio. Le regole per regione non possono esprimere «questo specifico prodotto ha il proprio prezzo in UAH indipendentemente dalla lingua dell'acquirente». Gli override per singolo prodotto sì.

Una configurazione Stripe + Shippo + WooCommerce non può modellare «acconto ora in UAH, saldo al pronto in EUR, evaso da Nova Post» senza codice personalizzato a ogni giuntura. La build su misura non era una preferenza: era un requisito del mercato.

Cosa abbiamo costruito.

Una piattaforma: una vetrina rivolta al cliente in 7 lingue, un ciclo di vita di produzione (bozza → in lavorazione → pronto → spedito) e un cruscotto operativo che il fondatore gestisce da solo.

Il livello di pagamento gestisce l'intero flusso di pagamento frazionato di Monobank. Acconto incassato alla conferma dell'ordine. Addebito del saldo attivato quando lo stato dell'ordine passa a «pronto per la spedizione». Ogni webhook viene verificato rispetto a una chiave pubblica PEM Monobank in cache usando ECDSA SHA256 con rotazione. Le tranche di pagamento sono record nel database, collegati allo stato dell'ordine — non riconciliati a posteriori.

Il livello di prezzo legge gli override di valuta per singolo prodotto prima di ripiegare sulla base convertita al cambio. Ogni riga di prodotto ha un prezzo base in EUR e colonne di override opzionali in UAH e USD. Quando è presente un override, la vetrina lo usa. Quando è assente, il tasso di cambio giornaliero della Banca Nazionale dell'Ucraina converte la base in EUR. Il tasso NBU si sincronizza via cron ogni giorno.

Il livello logistico gira su una directory Nova Post sincronizzata. Città, filiali e classificatori vengono importati in pagine dall'API di Nova Post e archiviati in locale — la selezione dell'indirizzo al checkout interroga la copia locale, non l'API live. Al momento della spedizione, la piattaforma genera una lettera di vettura tramite l'API di Nova Post e archivia il PDF dell'etichetta risultante come oggetto firmato (presigned) in Cloudflare R2.

Il ciclo di vita di produzione è l'impalcatura che lega insieme le tranche di pagamento e la spedizione. La macchina a stati dell'ordine — cinque stati, un log eventi, una galleria di foto di avanzamento — esiste affinché la transizione da acconto a saldo abbia un trigger definito e la generazione della lettera di vettura abbia un momento definito. La macchina a stati non è il prodotto. È il telaio portante per i flussi finanziari e logistici.

F · 01Pagamento frazionato Monobank
Acconto incassato alla conferma dell'ordine; il saldo si attiva al «pronto per la spedizione». Le tranche di pagamento sono record di database collegati allo stato dell'ordine. Verifica dei webhook ECDSA SHA256 con rotazione della chiave PEM.
F · 02Multivaluta per singolo prodotto
Prezzo base in EUR con colonne di override opzionali in UAH e USD per ciascun prodotto. Il risolutore dei prezzi legge l'override prima di ripiegare sul tasso di cambio giornaliero NBU. Controllo a livello di artigiano, non di regione.
F · 03Integrazione Nova Post
Directory di città e filiali sincronizzata in locale tramite job pianificato. Lettere di vettura generate al momento della spedizione tramite l'API di Nova Post. PDF delle etichette archiviati come oggetti firmati (presigned) in Cloudflare R2.
F · 04Ciclo di vita di produzione
Macchina d'ordine a cinque stati (bozza → in lavorazione → pronto → spedito → annullato) con log eventi e galleria di foto di avanzamento. Impalcatura per le tranche di pagamento e la generazione delle lettere di vettura — non l'oggetto centrale.
F · 05Vetrina in 7 lingue
Negozio rivolto al cliente in sette lingue. Gli override di valuta per singolo prodotto e il ripiego sul cambio NBU fanno sì che ogni lingua veda prezzi corretti per il contesto senza configurazione per regione.
F · 06Cruscotto operativo su misura
Kanban di produzione, sparkline dei ricavi a 30 giorni in EUR, pillole di stato delle integrazioni (Monobank / Nova Post / R2 / email), indicazione della freschezza dei cron e una fascia di attenzione. Un'unica schermata per l'intera operazione.

Le scelte di ingegneria fintech.

Verifica dei webhook ECDSA. Monobank firma i webhook di pagamento con una chiave privata; il ricevente deve verificarli rispetto a una chiave pubblica in cache, ruotare la cache quando Monobank ne pubblica una nuova e rifiutare qualsiasi webhook che non superi il controllo della firma. Un'autenticazione giocattolo sarebbe il valore di un header verificato. L'autenticazione vera è ECDSA SHA256 rispetto a una chiave PEM con rotazione.

Tranche di pagamento al livello dati. Il modello a pagamento frazionato non è una configurazione del gateway di pagamento. È un modello dati: un ordine ha una o più tranche di pagamento, ciascuna con un importo, una valuta, uno stato e un trigger. La tranche di acconto si attiva alla conferma dell'ordine. La tranche di saldo si attiva alla transizione di stato. Il log eventi porta la traccia di audit. Riconciliare due addebiti API scollegati a posteriori significherebbe che la fonte di verità è il cruscotto di Monobank, non il tuo database. Abbiamo rifiutato quel compromesso.

Override di valuta per singolo prodotto. La tabella dei prezzi ha tre colonne di prezzo opzionali oltre alla base in EUR: UAH, USD e un flag «prezzo su richiesta». Il risolutore dei prezzi le legge in ordine di priorità: override esplicito → base convertita al cambio → richiesta. L'artigiano controlla i prezzi a livello di prodotto, non a livello di regione.

La specificità del mercato locale è il fossato difensivo. Un concorrente può copiare il design della vetrina. Non può far girare lo stesso modello di pagamento senza riscrivere il livello di pagamento per l'API specifica di Monobank.

Sincronizzazione della directory Nova Post. Chiamare l'API live di Nova Post a ogni inserimento di indirizzo al checkout accoppierebbe il flusso di acquisto a una dipendenza esterna priva di un SLA che la piattaforma controlla. La sincronizzazione della directory gira come job pianificato: pagine di città, filiali e classificatori scritte in locale, il checkout interroga la copia locale. L'unica chiamata live a Nova Post nel percorso critico di acquisto è la generazione della lettera di vettura al momento della spedizione — e accade dopo che l'ordine è già stato pagato.

Il risultato.

Il fondatore gestisce l'intera operazione da un'unica schermata. Kanban di produzione per stato dell'ordine, una sparkline dei ricavi a 30 giorni in EUR, pillole di stato delle integrazioni per Monobank, Nova Post, R2 ed email, indicazione della freschezza dei cron e una fascia di attenzione che fa emergere tutto ciò che richiede un intervento. Circa 1–2K righe di componente per il cruscotto — costruito su misura, non generico.

145 commit in 3 settimane. 659 file di test che coprono il percorso ECDSA di Monobank, la riconciliazione della directory Nova Post, la semantica dei bundle del carrello, lo snapshot delle valute e le transizioni di stato delle tranche di pagamento. Tracce Sentry al 5% in produzione con uno scrubber dei dati personali (PII). Axiom per gli eventi strutturati di heartbeat dei cron. L'osservabilità di livello produttivo non è stata aggiunta a posteriori: faceva parte del primo sprint.

Citazione / 04
Lo stack non è su misura perché volevamo scrivere codice su misura. È su misura perché il mercato non ha binari pronti all'uso.
FondatoreCommercio per marchio artigianale
Outcome
Build time
3 weeks
Locales
7
Test files
659
Commits
145
NEXTCaso studio 01SW · 01 di 10
Real estate2022 — 2024

Un'app di visione immobiliare in AR per acquirenti che non possono essere nella stanza.