PC SOFT

GRUPOS DE DISCUSSÃO PROFISSIONAL
WINDEVWEBDEV e WINDEV Mobile

Inicio → WINDEV 25 → Classe WX Send SMS v5 (Windev, Webdev e Windev Mobile)
Classe WX Send SMS v5 (Windev, Webdev e Windev Mobile)
Iniciado por Boller, jun., 21 2025 4:18 PM - Sem resposta
Membro registado
4.520 mensagems
Publicado em junho, 21 2025 - 4:18 PM
Bom dia

Segue abaixo a ClasseWxSendSMS_v5

//##############################
// CLASSE WX SEND SMS v5.0 - TÉCNICAS AVANÇADAS WLANGUAGE
// Autor: Adriano - Seguindo Diretivas WX
// Data: 21/06/2025
// Recursos: EvaluateExpression + Indirection + Operadores Ternários
//##############################

// Estrutura avançada com configuração dinâmica
t001_sms_message_v5 is Structure
t001_id is string // ID único da mensagem
t001_phone_number is string // Número de telefone destino
t001_message_text is string // Texto da mensagem
t001_provider_name is string // Nome do provedor
t001_status is string // Status atual
t001_sent_date is DateTime // Data/hora do envio
t001_delivery_date is DateTime // Data/hora da entrega
t001_error_message is string // Mensagem de erro
t001_cost is real // Custo do envio
t001_segments is int // Número de segmentos
t001_priority is int // Prioridade
t001_retry_count is int // Contador de tentativas
t001_external_id is string // ID do provedor externo
t001_queue_id is string // ID da fila
t001_metadata is string // JSON com metadados dinâmicos
t001_validation_rules is string // Regras de validação dinâmicas
t001_routing_expression is string // Expressão para roteamento
END

// Estrutura de configuração dinâmica dos provedores
t002_sms_provider_v5 is Structure
t002_provider_id is string // ID do provedor
t002_provider_name is string // Nome amigável
t002_api_config is string // JSON com configuração da API
t002_validation_expression is string // Expressão de validação
t002_routing_weight is real // Peso para roteamento (0.0-1.0)
t002_is_active is boolean // Provedor ativo
t002_priority_expression is string // Expressão para calcular prioridade
t002_cost_formula is string // Fórmula para calcular custo
t002_rate_limit_config is string // Configuração de rate limiting
t002_failover_rules is string // Regras de failover
t002_dynamic_headers is string // Headers dinâmicos (JSON)
t002_response_parser is string // Parser de resposta customizado
END

// Estrutura de resposta avançada
t003_sms_response_v5 is Structure
t003_success is boolean // Sucesso da operação
t003_message_id is string // ID da mensagem
t003_external_id is string // ID do provedor
t003_status is string // Status retornado
t003_error_code is string // Código de erro
t003_error_message is string // Mensagem de erro
t003_cost is real // Custo calculado
t003_segments is int // Segmentos utilizados
t003_provider_used is string // Provedor utilizado
t003_response_time is int // Tempo de resposta em ms
t003_metadata is string // Metadados da resposta (JSON)
t003_routing_decision is string // Decisão de roteamento tomada
t003_validation_results is string // Resultados das validações
END

// Classe principal SMS v5 com técnicas avançadas
ClasseWxSendSMS_v5 is Class
// Propriedades privadas usando arrays associativos para flexibilidade
m_providers is associative array of t002_sms_provider_v5 // Provedores indexados por ID
m_config_cache is associative array of string // Cache de configurações
m_validation_cache is associative array of boolean // Cache de validações
m_routing_rules is associative array of string // Regras de roteamento
m_dynamic_properties is associative array of Variant // Propriedades dinâmicas
m_expression_cache is associative array of Variant // Cache de expressões avaliadas

// Configurações avançadas
m_debug_mode is boolean = False
m_auto_failover is boolean = True
m_smart_routing is boolean = True
m_cache_enabled is boolean = True
m_expression_timeout is int = 5000 // Timeout para expressões (ms)

// Constantes avançadas usando operadores ternários
CONSTANT
SMS_STATUS_PENDING = "PENDING"
SMS_STATUS_SENT = "SENT"
SMS_STATUS_DELIVERED = "DELIVERED"
SMS_STATUS_FAILED = "FAILED"

PROVIDER_TWILIO = "TWILIO"
PROVIDER_ZENVIA = "ZENVIA"
PROVIDER_AWS_SNS = "AWS_SNS"
PROVIDER_NEXMO = "NEXMO"
PROVIDER_MESSAGEBIRD = "MESSAGEBIRD"
PROVIDER_CLICKSEND = "CLICKSEND"
PROVIDER_PLIVO = "PLIVO"

PRIORITY_CRITICAL = 0
PRIORITY_HIGH = 1
PRIORITY_NORMAL = 2
PRIORITY_LOW = 3
PRIORITY_BULK = 4

ROUTING_ROUND_ROBIN = "ROUND_ROBIN"
ROUTING_COST_OPTIMIZED = "COST_OPTIMIZED"
ROUTING_PERFORMANCE = "PERFORMANCE"
ROUTING_SMART = "SMART"
ROUTING_CUSTOM = "CUSTOM"
END
END

// Construtor avançado com inicialização dinâmica
Procedure Constructor()
// Inicializar propriedades usando operadores ternários
m_debug_mode = (fFileExist(fCurrentDir() + "\debug.flag") ? True : False)
m_auto_failover = (GetEnvironmentVariable("SMS_AUTO_FAILOVER") = "false" ? False : True)
m_smart_routing = (GetEnvironmentVariable("SMS_SMART_ROUTING") = "false" ? False : True)
m_cache_enabled = (GetEnvironmentVariable("SMS_CACHE_ENABLED") = "false" ? False : True)

// Configurar propriedades dinâmicas usando Indirection
{m_dynamic_properties, "log_file"} = fCurrentDir() + "\logs\sms_v5.log"
{m_dynamic_properties, "thread_pool_size"} = 10
{m_dynamic_properties, "max_concurrent_sends"} = 50
{m_dynamic_properties, "retry_delay"} = 2000
{m_dynamic_properties, "default_timeout"} = 30

// Inicializar cache de configurações
InitializeConfigurationCache()

// Carregar provedores usando configuração dinâmica
LoadProvidersFromConfiguration()

// Log de inicialização usando EvaluateExpression
log_message is string = EvaluateExpression([
"ClasseWxSendSMS_v5 inicializada - Debug: " + (m_debug_mode ? "ON" : "OFF") +
", Failover: " + (m_auto_failover ? "ON" : "OFF") +
", Smart Routing: " + (m_smart_routing ? "ON" : "OFF")
])

LogAdvanced(log_message, "INIT")
END

// Procedure para inicializar cache de configurações usando Indirection
Procedure InitializeConfigurationCache()
config_keys is array of string = [
"twilio_base_url", "zenvia_base_url", "aws_sns_region",
"nexmo_base_url", "messagebird_base_url", "clicksend_base_url", "plivo_base_url",
"default_sender_id", "max_message_length", "unicode_support",
"rate_limit_global", "cost_threshold", "performance_threshold"
]

// Usar Indirection para configurar valores padrão
FOR i = 1 TO ArrayCount(config_keys)
config_key is string = config_keys[i]
default_value is string = GetDefaultConfigValue(config_key)

// Indirection para acessar cache dinamicamente
{m_config_cache, config_key} = default_value
END//For

LogAdvanced("Cache de configuração inicializado com " + ArrayCount(config_keys) + " chaves", "CONFIG")
END

// Procedure para obter valor padrão de configuração usando operadores ternários
Procedure GetDefaultConfigValue(config_key is string) : string
// Usar operadores ternários para configurações condicionais
SWITCH config_key
CASE "twilio_base_url"
Result "https://api.twilio.com/2010-04-01/Accounts/"
CASE "zenvia_base_url"
Result "https://api.zenvia.com/v2/channels/sms/messages"
CASE "aws_sns_region"
Result (GetEnvironmentVariable("AWS_REGION") <> "" ? GetEnvironmentVariable("AWS_REGION") : "us-east-1")
CASE "default_sender_id"
Result (GetEnvironmentVariable("SMS_SENDER_ID") <> "" ? GetEnvironmentVariable("SMS_SENDER_ID") : "SMS_SYSTEM")
CASE "max_message_length"
Result "1600" // 10 segmentos padrão
CASE "unicode_support"
Result "true"
CASE "rate_limit_global"
Result "100" // 100 SMS por minuto
CASE "cost_threshold"
Result "0.10" // R$ 0.10 por SMS
CASE "performance_threshold"
Result "2000" // 2 segundos
OTHER CASE
Result ""
END
END

// Procedure para carregar provedores usando configuração dinâmica
Procedure LoadProvidersFromConfiguration()
provider_configs is array of string = [
"TWILIO", "ZENVIA", "AWS_SNS", "NEXMO", "MESSAGEBIRD", "CLICKSEND", "PLIVO"
]

FOR i = 1 TO ArrayCount(provider_configs)
provider_id is string = provider_configs[i]

// Usar EvaluateExpression para verificar se provedor deve ser carregado
should_load is boolean = EvaluateExpression([
GetEnvironmentVariable("SMS_ENABLE_" + provider_id) <> "false" AND
GetEnvironmentVariable("SMS_API_KEY_" + provider_id) <> ""
])

IF should_load
LoadProviderConfiguration(provider_id)
END//If
END//For

LogAdvanced("Provedores carregados: " + ArrayCount(m_providers), "CONFIG")
END

// Procedure para carregar configuração de um provedor específico
Procedure LoadProviderConfiguration(provider_id is string)
provider is t002_sms_provider_v5

// Configuração básica
provider.t002_provider_id = provider_id
provider.t002_provider_name = GetProviderDisplayName(provider_id)

// Usar Indirection para acessar configurações dinamicamente
api_key_env is string = "SMS_API_KEY_" + provider_id
api_secret_env is string = "SMS_API_SECRET_" + provider_id
sender_id_env is string = "SMS_SENDER_ID_" + provider_id

// Configuração da API usando JSON dinâmico
api_config is string = StringBuild([
{
"api_key": "%1",
"api_secret": "%2",
"sender_id": "%3",
"base_url": "%4",
"timeout": %5,
"max_retries": %6
}],
GetEnvironmentVariable(api_key_env),
GetEnvironmentVariable(api_secret_env),
(GetEnvironmentVariable(sender_id_env) <> "" ? GetEnvironmentVariable(sender_id_env) : {m_config_cache, "default_sender_id"}),
{m_config_cache, Lower(provider_id) + "_base_url"},
30,
3)

provider.t002_api_config = api_config

// Expressões dinâmicas usando EvaluateExpression
provider.t002_validation_expression = GetProviderValidationExpression(provider_id)
provider.t002_priority_expression = GetProviderPriorityExpression(provider_id)
provider.t002_cost_formula = GetProviderCostFormula(provider_id)

// Configurações avançadas
provider.t002_routing_weight = GetProviderRoutingWeight(provider_id)
provider.t002_is_active = True
provider.t002_rate_limit_config = GetProviderRateLimitConfig(provider_id)
provider.t002_failover_rules = GetProviderFailoverRules(provider_id)

// Adicionar ao array associativo usando Indirection
{m_providers, provider_id} = provider

LogAdvanced("Provedor " + provider_id + " configurado com sucesso", "CONFIG")
END

// Procedure para obter nome de exibição do provedor usando operadores ternários
Procedure GetProviderDisplayName(provider_id is string) : string
Result (provider_id = "TWILIO" ? "Twilio SMS" :
(provider_id = "ZENVIA" ? "Zenvia Brasil" :
(provider_id = "AWS_SNS" ? "Amazon SNS" :
(provider_id = "NEXMO" ? "Vonage (Nexmo)" :
(provider_id = "MESSAGEBIRD" ? "MessageBird" :
(provider_id = "CLICKSEND" ? "ClickSend" :
(provider_id = "PLIVO" ? "Plivo SMS" : provider_id)))))))
END

// Procedure para obter expressão de validação do provedor
Procedure GetProviderValidationExpression(provider_id is string) : string
// Expressões customizadas por provedor usando EvaluateExpression
SWITCH provider_id
CASE "TWILIO"
Result [Length(phone_number) >= 10 AND Left(phone_number, 1) = "+" AND Length(message_text) <= 1600]
CASE "ZENVIA"
Result [MatchRegularExpression(phone_number, "^\\+55[0-9]{10,11}$") AND Length(message_text) <= 4096]
CASE "AWS_SNS"
Result [Length(phone_number) >= 10 AND Length(message_text) <= 1600]
OTHER CASE
Result [Length(phone_number) >= 10 AND Length(message_text) <= 1600 AND Length(message_text) > 0]
END
END

// Procedure para obter expressão de prioridade do provedor
Procedure GetProviderPriorityExpression(provider_id is string) : string
// Prioridade dinâmica baseada em performance e custo
SWITCH provider_id
CASE "TWILIO"
Result [(response_time < 1000 ? 1 : 2) + (cost < 0.01 ? 0 : 1)]
CASE "ZENVIA"
Result [(response_time < 2000 ? 1 : 3) + (cost < 0.05 ? 0 : 2)]
OTHER CASE
Result [2 + (response_time > 3000 ? 2 : 0) + (cost > 0.02 ? 1 : 0)]
END
END

// Procedure para obter fórmula de custo do provedor
Procedure GetProviderCostFormula(provider_id is string) : string
// Fórmulas de custo dinâmicas
SWITCH provider_id
CASE "TWILIO"
Result [segments * 0.0075 * (priority = 0 ? 1.5 : 1.0)]
CASE "ZENVIA"
Result [segments * 0.05 * (Length(message_text) > 160 ? 1.2 : 1.0)]
CASE "AWS_SNS"
Result [segments * 0.006 * (region = "us-east-1" ? 1.0 : 1.1)]
OTHER CASE
Result [segments * 0.01]
END
END

// Procedure para obter peso de roteamento usando operadores ternários
Procedure GetProviderRoutingWeight(provider_id is string) : real
// Pesos baseados em confiabilidade e performance
Result (provider_id = "TWILIO" ? 0.9 :
(provider_id = "ZENVIA" ? 0.8 :
(provider_id = "AWS_SNS" ? 0.85 :
(provider_id = "NEXMO" ? 0.75 :
(provider_id = "MESSAGEBIRD" ? 0.7 :
(provider_id = "CLICKSEND" ? 0.65 :
(provider_id = "PLIVO" ? 0.7 : 0.5)))))))
END

// Procedure para configuração de rate limiting
Procedure GetProviderRateLimitConfig(provider_id is string) : string
// Configuração JSON para rate limiting
SWITCH provider_id
CASE "TWILIO"
Result [{"requests_per_second": 10, "burst_limit": 50, "window_size": 60}]
CASE "ZENVIA"
Result [{"requests_per_second": 5, "burst_limit": 25, "window_size": 60}]
OTHER CASE
Result [{"requests_per_second": 3, "burst_limit": 15, "window_size": 60}]
END
END

// Procedure para regras de failover
Procedure GetProviderFailoverRules(provider_id is string) : string
// Regras de failover em JSON
Result StringBuild([
{
"max_consecutive_failures": %1,
"failure_window_minutes": %2,
"recovery_test_interval": %3,
"fallback_providers": %4
}],
(provider_id = "TWILIO" ? 3 : 5),
(provider_id = "ZENVIA" ? 10 : 15),
(provider_id = "AWS_SNS" ? 5 : 10),
GetFallbackProviders(provider_id))
END

// Procedure para obter provedores de fallback
Procedure GetFallbackProviders(provider_id is string) : string
// Lista de fallback baseada no provedor principal
SWITCH provider_id
CASE "TWILIO"
Result [["ZENVIA", "AWS_SNS", "NEXMO"]]
CASE "ZENVIA"
Result [["TWILIO", "PLIVO", "CLICKSEND"]]
CASE "AWS_SNS"
Result [["TWILIO", "MESSAGEBIRD", "NEXMO"]]
OTHER CASE
Result [["TWILIO", "ZENVIA"]]
END
END

// Procedure de log avançado usando Indirection
Procedure LogAdvanced(message is string, level is string = "INFO")
timestamp is string = DateTimeToString(DateTimeSys(), "YYYY-MM-DD HH:MM:SS.CCC")
log_entry is string = StringBuild("[%1] [%2] %3", timestamp, level, message)

// Usar Indirection para acessar arquivo de log dinamicamente
log_file is string = {m_dynamic_properties, "log_file"}

// Escrever no arquivo usando operador ternário para verificação
(fDirectoryExist(fExtractPath(log_file)) ? True : fMakeDir(fExtractPath(log_file)))
fWriteLine(log_file, log_entry)

// Debug usando operador ternário
(m_debug_mode ? Trace(log_entry) : Null)
END

// Procedure para configurar propriedade dinâmica usando Indirection
Procedure SetDynamicProperty(property_name is string, property_value is Variant)
// Usar Indirection para acesso dinâmico
{m_dynamic_properties, property_name} = property_value

LogAdvanced(StringBuild("Propriedade dinâmica '%1' configurada", property_name), "CONFIG")
END

// Procedure para obter propriedade dinâmica usando Indirection
Procedure GetDynamicProperty(property_name is string, default_value is Variant = Null) : Variant
// Usar operador ternário com Indirection
Result ({m_dynamic_properties, property_name} <> Null ? {m_dynamic_properties, property_name} : default_value)
END

// Procedure para validação avançada usando EvaluateExpression
Procedure ValidateMessageAdvanced(phone_number is string, message_text is string, provider_id is string = "") : boolean
// Cache de validação usando Indirection
cache_key is string = MD5(phone_number + "|" + message_text + "|" + provider_id)

// Verificar cache primeiro usando operador ternário
IF m_cache_enabled AND {m_validation_cache, cache_key} <> Null
Result {m_validation_cache, cache_key}
END//If

// Validação básica usando EvaluateExpression
basic_validation is string = [
Length(Trim(phone_number)) >= 10 AND
Length(Trim(message_text)) > 0 AND
Length(message_text) <= 4096 AND
MatchRegularExpression(phone_number, "^\\+?[0-9\\s\\-\\(\\)]+$")
]

is_valid is boolean = EvaluateExpression(basic_validation)

// Validação específica do provedor se especificado
IF is_valid AND provider_id <> "" AND {m_providers, provider_id} <> Null
provider_validation is string = {m_providers, provider_id}.t002_validation_expression

// Substituir variáveis na expressão
provider_validation = Replace(provider_validation, "phone_number", "\"" + phone_number + "\"")
provider_validation = Replace(provider_validation, "message_text", "\"" + message_text + "\"")

is_valid = is_valid AND EvaluateExpression(provider_validation)
END//If

// Armazenar no cache usando Indirection
IF m_cache_enabled
{m_validation_cache, cache_key} = is_valid
END//If

Result is_valid
END

//Final do Arquivo


--
Adriano José Boller
______________________________________________
Consultor e Representante Oficial da
PcSoft no Brasil
+55 (41) 99949 1800
adrianoboller@gmail.com
skype: adrianoboller
http://wxinformatica.com.br/