Piattaforma ITI TECHNOLOGY: monorepo, Medusa, API, sito, area riservata e deploy
Deploy stack su Proxmox / deploy (push) Failing after 3s
Deploy stack su Proxmox / deploy (push) Failing after 3s
Monorepo npm con apps/public (Angular SSR), apps/private (Angular SPA), apps/api (Fastify), packages/shared e packages/styles; Medusa 2.21 in medusa/; infrastruttura Docker (Postgres PostGIS+pgvector, Redis, Caddy, backup) e workflow Gitea Actions per il deploy via SSH a ogni push su master. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_018jQyT6dR9czzGwqb7FkG6u
This commit is contained in:
@@ -0,0 +1,7 @@
|
||||
{
|
||||
"dev": {
|
||||
"baseUrl": "http://localhost:3000",
|
||||
"productHandle": "pompa-di-calore-aria-acqua-8kw",
|
||||
"guestEmail": "checkout-guest@example.com"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
{
|
||||
"dev": {
|
||||
"installerEmail": "installatore-approvato@example.com",
|
||||
"installerPassword": "password-dell-installatore",
|
||||
"stripeSecretKey": "sk_test_..."
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,147 @@
|
||||
### Proxy shop (/shop/*) — HTTP Client JetBrains/WebStorm, ambiente "dev".
|
||||
### Variabili: http-client.env.json + http-client.private.env.json (non committato, modello in
|
||||
### http-client.private.env.example.json). Il client conserva i cookie (cart_id) tra le richieste.
|
||||
### Prerequisiti: infra su, Medusa avviato con una chiave Stripe di TEST reale (STRIPE_API_KEY), apps/api avviata.
|
||||
### Eseguire in ordine. Parte A: checkout guest completo. Parte B: installatore approvato (prezzi riservati).
|
||||
|
||||
### A0. Catalogo
|
||||
GET {{baseUrl}}/shop/products?limit=12
|
||||
|
||||
### A1. Dettaglio prodotto (prezzo standard in centesimi: 549000)
|
||||
GET {{baseUrl}}/shop/products/{{productHandle}}
|
||||
|
||||
> {%
|
||||
client.global.set("variantId", response.body.variants[0].id)
|
||||
client.test("prezzo standard", () => client.assert(response.body.variants[0].price === 549000))
|
||||
%}
|
||||
|
||||
### A2. Categorie
|
||||
GET {{baseUrl}}/shop/categories
|
||||
|
||||
### A3. Crea il carrello (cookie cart_id httpOnly)
|
||||
POST {{baseUrl}}/shop/cart
|
||||
|
||||
### A4. Aggiungi il prodotto
|
||||
POST {{baseUrl}}/shop/cart/items
|
||||
Content-Type: application/json
|
||||
|
||||
{ "variantId": "{{variantId}}", "quantity": 1 }
|
||||
|
||||
> {% client.global.set("itemId", response.body.items[0].id) %}
|
||||
|
||||
### A5. Cambia quantità
|
||||
PATCH {{baseUrl}}/shop/cart/items/{{itemId}}
|
||||
Content-Type: application/json
|
||||
|
||||
{ "quantity": 1 }
|
||||
|
||||
### A6. Email (obbligatoria per il guest) e indirizzo; fatturazione = spedizione
|
||||
POST {{baseUrl}}/shop/cart/address
|
||||
Content-Type: application/json
|
||||
|
||||
{
|
||||
"email": "{{guestEmail}}",
|
||||
"shippingAddress": {
|
||||
"firstName": "Mario", "lastName": "Rossi", "address1": "Via Roma 1",
|
||||
"city": "Milano", "postalCode": "20100", "province": "MI", "phone": "3330000000"
|
||||
},
|
||||
"invoice": { "companyName": "Rossi Srl", "vatNumber": "00743110157", "sdiCode": "0000000" },
|
||||
"acceptPrivacy": true
|
||||
}
|
||||
|
||||
### A7. Opzioni di spedizione
|
||||
GET {{baseUrl}}/shop/cart/shipping-options
|
||||
|
||||
> {% client.global.set("shippingOptionId", response.body[0].id) %}
|
||||
|
||||
### A8. Scegli la spedizione → readyForPayment = true
|
||||
POST {{baseUrl}}/shop/cart/shipping
|
||||
Content-Type: application/json
|
||||
|
||||
{ "optionId": "{{shippingOptionId}}" }
|
||||
|
||||
> {% client.test("pronto per il pagamento", () => client.assert(response.body.readyForPayment === true)) %}
|
||||
|
||||
### A9. Payment session Stripe → client_secret
|
||||
POST {{baseUrl}}/shop/cart/payment
|
||||
|
||||
> {%
|
||||
client.global.set("clientSecret", response.body.clientSecret)
|
||||
client.global.set("paymentIntentId", response.body.clientSecret.split("_secret_")[0])
|
||||
%}
|
||||
|
||||
### A10. Conferma con carta di test (al posto di Stripe.js nel browser): API Stripe con la chiave segreta di TEST
|
||||
POST https://api.stripe.com/v1/payment_intents/{{paymentIntentId}}/confirm
|
||||
Authorization: Bearer {{stripeSecretKey}}
|
||||
Content-Type: application/x-www-form-urlencoded
|
||||
|
||||
payment_method=pm_card_visa&return_url=https%3A%2F%2Fexample.com%2Fcheckout
|
||||
|
||||
### A11. Completa → ordine creato, cookie cart_id cancellato
|
||||
POST {{baseUrl}}/shop/cart/complete
|
||||
|
||||
> {% client.test("ordine creato", () => client.assert(response.status === 200 && response.body.number > 0)) %}
|
||||
|
||||
### A12. Dopo il completamento non c'è più un carrello → 404
|
||||
GET {{baseUrl}}/shop/cart
|
||||
|
||||
### B1. Carrello guest prima del login (prezzo standard)
|
||||
POST {{baseUrl}}/shop/cart/items
|
||||
Content-Type: application/json
|
||||
|
||||
{ "variantId": "{{variantId}}", "quantity": 1 }
|
||||
|
||||
### B2. Login installatore approvato: il carrello guest aperto viene associato
|
||||
POST {{baseUrl}}/auth/login
|
||||
Content-Type: application/json
|
||||
|
||||
{ "email": "{{installerEmail}}", "password": "{{installerPassword}}" }
|
||||
|
||||
> {% client.global.set("accessToken", response.body.accessToken) %}
|
||||
|
||||
### B3. Carrello riprezzato col listino installatori (465000)
|
||||
GET {{baseUrl}}/shop/cart
|
||||
Authorization: Bearer {{accessToken}}
|
||||
|
||||
> {% client.test("prezzo installatore", () => client.assert(response.body.items[0].unitPrice === 465000)) %}
|
||||
|
||||
### B4. Catalogo con prezzi riservati (priceType "installer", originalPrice = listino pubblico)
|
||||
GET {{baseUrl}}/shop/products/{{productHandle}}
|
||||
Authorization: Bearer {{accessToken}}
|
||||
|
||||
### B5. Indirizzo (email dell'account, non serve inviarla)
|
||||
POST {{baseUrl}}/shop/cart/address
|
||||
Authorization: Bearer {{accessToken}}
|
||||
Content-Type: application/json
|
||||
|
||||
{
|
||||
"shippingAddress": {
|
||||
"firstName": "Ina", "lastName": "Stallatore", "company": "Impianti Srl", "address1": "Via Milano 10",
|
||||
"city": "Torino", "postalCode": "10100", "province": "TO"
|
||||
},
|
||||
"acceptPrivacy": true
|
||||
}
|
||||
|
||||
### B6. Spedizione
|
||||
POST {{baseUrl}}/shop/cart/shipping
|
||||
Authorization: Bearer {{accessToken}}
|
||||
Content-Type: application/json
|
||||
|
||||
{ "optionId": "{{shippingOptionId}}" }
|
||||
|
||||
### B7. Pagamento
|
||||
POST {{baseUrl}}/shop/cart/payment
|
||||
Authorization: Bearer {{accessToken}}
|
||||
|
||||
> {% client.global.set("paymentIntentId", response.body.clientSecret.split("_secret_")[0]) %}
|
||||
|
||||
### B8. Conferma carta di test
|
||||
POST https://api.stripe.com/v1/payment_intents/{{paymentIntentId}}/confirm
|
||||
Authorization: Bearer {{stripeSecretKey}}
|
||||
Content-Type: application/x-www-form-urlencoded
|
||||
|
||||
payment_method=pm_card_visa&return_url=https%3A%2F%2Fexample.com%2Fcheckout
|
||||
|
||||
### B9. Completa → ordine con prezzi installatore, collegato al customer dell'account
|
||||
POST {{baseUrl}}/shop/cart/complete
|
||||
Authorization: Bearer {{accessToken}}
|
||||
Reference in New Issue
Block a user