package main import ( "fmt" "os" "strconv" "strings" "time" ) type config struct { ServerAddr string FrontendOrigin string ZarinHubEndpoint string ZarinHubAuthEndpoint string ZarinHubUsername string ZarinHubPassword string ZarinHubTimeout time.Duration ZarinHubRetries int DatabasePath string } func loadConfig() (config, error) { return readConfig(os.Getenv) } func readConfig(getenv func(string) string) (config, error) { username := strings.TrimSpace(getenv("ZARINHUB_API_USERNAME")) if username == "" { return config{}, fmt.Errorf("ZARINHUB_API_USERNAME is required") } password := strings.TrimSpace(getenv("ZARINHUB_API_PASSWORD")) if password == "" { return config{}, fmt.Errorf("ZARINHUB_API_PASSWORD is required") } timeoutText := valueOrDefault( getenv("ZARINHUB_TIMEOUT"), "5s", ) timeout, err := time.ParseDuration(timeoutText) if err != nil || timeout <= 0 { return config{}, fmt.Errorf( "ZARINHUB_TIMEOUT must be a positive duration", ) } retriesText := valueOrDefault( getenv("ZARINHUB_RETRIES"), "2", ) retries, err := strconv.Atoi(retriesText) if err != nil || retries < 0 { return config{}, fmt.Errorf( "ZARINHUB_RETRIES must be a non-negative integer", ) } return config{ ServerAddr: valueOrDefault( getenv("SERVER_ADDR"), "127.0.0.1:8080", ), FrontendOrigin: valueOrDefault( getenv("FRONTEND_ORIGIN"), "http://127.0.0.1:3000", ), ZarinHubEndpoint: valueOrDefault( getenv("ZARINHUB_ENDPOINT"), "https://zarin-hub.com/api/v5/KYC/CardToIban", ), ZarinHubAuthEndpoint: valueOrDefault( getenv("ZARINHUB_AUTH_ENDPOINT"), "https://zarin-hub.com/api/v5/Authentication/GetToken", ), ZarinHubUsername: username, ZarinHubPassword: password, ZarinHubTimeout: timeout, ZarinHubRetries: retries, DatabasePath: valueOrDefault( getenv("DATABASE_PATH"), "./card-to-iban.db", ), }, nil } func valueOrDefault(value string, fallback string) string { if strings.TrimSpace(value) == "" { return fallback } return strings.TrimSpace(value) }