saveinmed/backend-old/cmd/verify_split/main.go
NANDO9322 78a95e3263 feat: reestruturação do checkout, correções de pagamento e melhorias visuais
Backend:
- Renomeado BACKEND_URL para BACKEND_HOST no .env e nas configs para consistência.
- Atualizado MercadoPagoGateway para usar o BACKEND_HOST correto na notification_url.
- Atualizado payment_handler para receber e processar informações do Pagador (email/doc).
- Corrigido erro 500 ao buscar dados de compradores B2B.

Frontend:
- Criado componente Header reutilizável e aplicado nas páginas internas.
- Implementada nova página "Meus Pedidos" com lógica de listagem correta.
- Implementada página de "Detalhes do Pedido" (/pedidos/[id]) com alto contraste visual.
- Melhorada a legibilidade da página de detalhes (textos pretos/escuros).
- Corrigido bug onde pagamentos rejeitados eram tratados como sucesso (agora verifica status 'rejected' no serviço).
- Adicionado componente <Toaster /> ao layout principal para corrigir notificações invisíveis.
- Adicionado feedback visual persistente de erro na tela de checkout para falhas de pagamento.
2026-01-28 16:37:21 -03:00

330 lines
9.7 KiB
Go

package main
import (
"bytes"
"database/sql"
"encoding/json"
"fmt"
"io"
"log"
"net/http"
"time"
"github.com/gofrs/uuid/v5"
_ "github.com/jackc/pgx/v5/stdlib"
)
const (
baseURL = "http://localhost:8214/api/v1"
dbURL = "postgres://postgres:123@localhost:55432/saveinmed?sslmode=disable"
)
type LoginResponse struct {
Token string `json:"access_token"`
}
type PaymentPreferenceResponse struct {
PaymentURL string `json:"payment_url"`
MarketplaceFee int64 `json:"marketplace_fee"`
SellerReceivable int64 `json:"seller_receivable"`
}
func main() {
log.Println("Starting Split Payment Verification...")
db, err := sql.Open("pgx", dbURL)
if err != nil {
log.Fatalf("Failed to connect to DB: %v", err)
}
defer db.Close()
// 1. Login as Admin
adminToken := login("andre.fr93@gmail.com", "teste1234")
log.Println("Logged in as Admin.")
// 2. Create Seller Company & Account
sellerID := createCompany(adminToken, "Farmácia Vendedora")
log.Printf("Created Seller Company: %s", sellerID)
dummyAccountID := "1942948243"
_, err = db.Exec(`
INSERT INTO seller_payment_accounts (seller_id, gateway, account_id, account_type, status, created_at)
VALUES ($1, 'mercadopago', $2, 'standard', 'active', now())
ON CONFLICT (seller_id, gateway) DO UPDATE
SET account_id = $2, status = 'active'
`, sellerID, dummyAccountID)
if err != nil {
log.Fatalf("Failed to inject SellerPaymentAccount: %v", err)
}
// 3. Create Product & Inventory (As Admin acting for Seller)
productID := createProduct(adminToken, sellerID)
log.Printf("Created Product: %s", productID)
createInventory(adminToken, sellerID, productID)
// 4. Create Buyer Company & User
buyerCompanyID := createCompany(adminToken, "Farmácia Compradora")
buyerEmail := fmt.Sprintf("buyer_%d@test.com", time.Now().Unix())
createUser(adminToken, buyerCompanyID, buyerEmail, "Dono")
log.Printf("Created Buyer User: %s", buyerEmail)
// 5. Login as Buyer
buyerToken := login(buyerEmail, "123456")
log.Println("Logged in as Buyer.")
// 6. Buyer adds to Cart
addToCart(buyerToken, productID)
log.Println("Added to Cart.")
// 7. Buyer creates Address (Shipping)
// Note: CreateOrder requires Shipping Object. We can construct it.
// But usually we pick from existing addresses.
// Let's passed mocked shipping data in CreateOrder directly.
// 8. Create Order
orderID := createOrder(buyerToken, sellerID, productID)
log.Printf("Created Order: %s", orderID)
// 9. Payment Preference
pref := createPaymentPreference(buyerToken, orderID)
log.Printf("✅ SUCCESS! Payment URL generated: %s", pref.PaymentURL)
log.Printf(" Marketplace Fee: %d cents", pref.MarketplaceFee)
log.Printf(" Seller Receivable: %d cents", pref.SellerReceivable)
}
func login(email, password string) string {
payload := map[string]string{
"email": email,
"password": password,
}
body, _ := json.Marshal(payload)
resp, err := http.Post(baseURL+"/auth/login", "application/json", bytes.NewBuffer(body))
if err != nil {
log.Fatalf("Login failed: %v", err)
}
defer resp.Body.Close()
if resp.StatusCode != 200 {
b, _ := io.ReadAll(resp.Body)
log.Fatalf("Login failed status %d: %s", resp.StatusCode, string(b))
}
var res LoginResponse
json.NewDecoder(resp.Body).Decode(&res)
return res.Token
}
func createCompany(token, name string) uuid.UUID {
cnpj := fmt.Sprintf("%d", time.Now().UnixNano())[:14]
payload := map[string]interface{}{
"corporate_name": name,
"cnpj": cnpj,
"category": "farmacia",
"email": "comp" + cnpj + "@test.com",
}
body, _ := json.Marshal(payload)
req, _ := http.NewRequest("POST", baseURL+"/companies", bytes.NewBuffer(body))
req.Header.Set("Authorization", "Bearer "+token)
req.Header.Set("Content-Type", "application/json")
client := &http.Client{}
resp, err := client.Do(req)
if err != nil {
log.Fatalf("CreateCompany failed: %v", err)
}
defer resp.Body.Close()
if resp.StatusCode != 200 && resp.StatusCode != 201 {
b, _ := io.ReadAll(resp.Body)
log.Fatalf("CreateCompany failed status %d: %s", resp.StatusCode, string(b))
}
var m map[string]interface{}
json.NewDecoder(resp.Body).Decode(&m)
idStr, _ := m["id"].(string)
return uuid.FromStringOrNil(idStr)
}
func createUser(token string, companyID uuid.UUID, email, role string) {
payload := map[string]interface{}{
"company_id": companyID.String(),
"role": role,
"name": "User Test",
"username": email, // simple username
"email": email,
"password": "123456",
"cpf": fmt.Sprintf("%d", time.Now().UnixNano())[:11],
}
body, _ := json.Marshal(payload)
req, _ := http.NewRequest("POST", baseURL+"/users", bytes.NewBuffer(body))
req.Header.Set("Authorization", "Bearer "+token)
req.Header.Set("Content-Type", "application/json")
client := &http.Client{}
resp, err := client.Do(req)
if err != nil {
log.Fatalf("CreateUser failed: %v", err)
}
defer resp.Body.Close()
if resp.StatusCode != 201 {
b, _ := io.ReadAll(resp.Body)
log.Fatalf("CreateUser failed status %d: %s", resp.StatusCode, string(b))
}
}
func createProduct(token string, sellerID uuid.UUID) uuid.UUID {
payload := map[string]interface{}{
"name": "Produto Teste Split",
"price_cents": 10000,
"seller_id": sellerID.String(),
"manufacturer": "Lab Test",
"ean_code": fmt.Sprintf("%d", time.Now().Unix()),
"category": "Medicamentos",
"subcategory": "Analgesicos",
"description": "Produto teste",
"internal_code": "TEST-" + fmt.Sprintf("%d", time.Now().Unix()),
}
body, _ := json.Marshal(payload)
req, _ := http.NewRequest("POST", baseURL+"/products", bytes.NewBuffer(body))
req.Header.Set("Authorization", "Bearer "+token)
req.Header.Set("Content-Type", "application/json")
client := &http.Client{}
resp, err := client.Do(req)
if err != nil {
log.Fatalf("CreateProduct failed: %v", err)
}
defer resp.Body.Close()
if resp.StatusCode != 200 && resp.StatusCode != 201 {
b, _ := io.ReadAll(resp.Body)
log.Fatalf("CreateProduct failed status %d: %s", resp.StatusCode, string(b))
}
var m map[string]interface{}
json.NewDecoder(resp.Body).Decode(&m)
idStr, _ := m["id"].(string)
return uuid.FromStringOrNil(idStr)
}
func createInventory(token string, sellerID, productID uuid.UUID) {
payload := map[string]interface{}{
"product_id": productID.String(),
"seller_id": sellerID.String(),
"sale_price_cents": 10000,
"stock_quantity": 100,
"expires_at": time.Now().Add(24 * time.Hour).Format(time.RFC3339),
"observations": "Stock test",
}
body, _ := json.Marshal(payload)
req, _ := http.NewRequest("POST", baseURL+"/inventory", bytes.NewBuffer(body))
req.Header.Set("Authorization", "Bearer "+token)
req.Header.Set("Content-Type", "application/json")
client := &http.Client{}
resp, err := client.Do(req)
if err != nil {
log.Fatalf("CreateInventory failed: %v", err)
}
defer resp.Body.Close()
if resp.StatusCode != 200 && resp.StatusCode != 201 {
b, _ := io.ReadAll(resp.Body)
log.Fatalf("CreateInventory failed status %d: %s", resp.StatusCode, string(b))
}
}
func addToCart(token string, productID uuid.UUID) {
payload := map[string]interface{}{
"product_id": productID.String(),
"quantity": 1,
}
body, _ := json.Marshal(payload)
req, _ := http.NewRequest("POST", baseURL+"/cart", bytes.NewBuffer(body))
req.Header.Set("Authorization", "Bearer "+token)
req.Header.Set("Content-Type", "application/json")
client := &http.Client{}
resp, err := client.Do(req)
if err != nil {
log.Fatalf("AddToCart failed: %v", err)
}
defer resp.Body.Close()
if resp.StatusCode != 200 && resp.StatusCode != 201 {
b, _ := io.ReadAll(resp.Body)
log.Fatalf("AddToCart failed status %d: %s", resp.StatusCode, string(b))
}
}
func createOrder(token string, sellerID, productID uuid.UUID) uuid.UUID {
payload := map[string]interface{}{
"seller_id": sellerID.String(),
"items": []map[string]interface{}{
{
"product_id": productID.String(),
"quantity": 1,
"unit_cents": 10000,
},
},
"shipping": map[string]interface{}{
"titulo": "Casa",
"zip_code": "01001000",
"street": "Praça da Sé",
"number": "1",
"district": "Sé",
"city": "São Paulo",
"state": "SP",
"country": "BR",
},
"payment_method": map[string]interface{}{
"type": "credit_card",
"installments": 1,
},
}
body, _ := json.Marshal(payload)
req, _ := http.NewRequest("POST", baseURL+"/orders", bytes.NewBuffer(body))
req.Header.Set("Authorization", "Bearer "+token)
req.Header.Set("Content-Type", "application/json")
client := &http.Client{}
resp, err := client.Do(req)
if err != nil {
log.Fatalf("CreateOrder failed: %v", err)
}
defer resp.Body.Close()
if resp.StatusCode != 200 && resp.StatusCode != 201 {
b, _ := io.ReadAll(resp.Body)
log.Fatalf("CreateOrder failed status %d: %s", resp.StatusCode, string(b))
}
var m map[string]interface{}
json.NewDecoder(resp.Body).Decode(&m)
idStr, _ := m["id"].(string)
return uuid.FromStringOrNil(idStr)
}
func createPaymentPreference(token string, orderID uuid.UUID) PaymentPreferenceResponse {
req, _ := http.NewRequest("POST", fmt.Sprintf("%s/orders/%s/payment", baseURL, orderID.String()), nil)
req.Header.Set("Authorization", "Bearer "+token)
client := &http.Client{}
resp, err := client.Do(req)
if err != nil {
log.Fatalf("CreatePaymentPreference failed: %v", err)
}
defer resp.Body.Close()
bodyBytes, _ := io.ReadAll(resp.Body)
if resp.StatusCode != 200 && resp.StatusCode != 201 {
log.Fatalf("CreatePaymentPreference failed status %d: %s", resp.StatusCode, string(bodyBytes))
}
var res PaymentPreferenceResponse
if err := json.Unmarshal(bodyBytes, &res); err != nil {
log.Fatalf("Failed to decode response: %v, body: %s", err, string(bodyBytes))
}
return res
}