From 6657525815e7e6521ad3fefac08b366b93ffe713 Mon Sep 17 00:00:00 2001 From: AI Bot Date: Sat, 5 Sep 2026 15:35:37 -0500 Subject: [PATCH] feat(domain): configurar soporte oficial para dominio drip-zone.online en Traefik, Bold y App Android --- .../java/co/dripzone/app/api/ApiClient.kt | 32 +++++++++++++----- .../main/res/xml/network_security_config.xml | 1 + dripzone-app/docker-compose.prod.yml | 4 +-- .../src/app/api/bold/create-payment/route.ts | 2 +- scripts/deploy_vps.py | 33 ++++++++++--------- 5 files changed, 45 insertions(+), 27 deletions(-) diff --git a/dripzone-app/android/app/src/main/java/co/dripzone/app/api/ApiClient.kt b/dripzone-app/android/app/src/main/java/co/dripzone/app/api/ApiClient.kt index d91cc79..1afd9cc 100644 --- a/dripzone-app/android/app/src/main/java/co/dripzone/app/api/ApiClient.kt +++ b/dripzone-app/android/app/src/main/java/co/dripzone/app/api/ApiClient.kt @@ -21,10 +21,24 @@ import java.util.concurrent.TimeUnit object ApiClient { private const val TAG = "DripApiClient" - private const val PRIMARY_URL = "https://dripzone.almeira.com.co/api/products" - private const val FALLBACK_URL = "https://news.almeira.com.co/api/products" private const val CACHE_KEY_PRODUCTS = "cached_products_json" + fun getBaseUrl(): String { + return try { + val addr = java.net.InetAddress.getByName("drip-zone.online") + if (addr != null && !addr.hostAddress.isNullOrBlank()) { + "https://drip-zone.online" + } else { + "https://dripzone.almeira.com.co" + } + } catch (e: Exception) { + "https://dripzone.almeira.com.co" + } + } + + private fun getPrimaryProductsUrl(): String = "${getBaseUrl()}/api/products" + private const val FALLBACK_URL = "https://news.almeira.com.co/api/products" + private val gson = Gson() // OkHttpClient enforcing TLS 1.3 and TLS 1.2 modern cipher suites @@ -48,7 +62,7 @@ object ApiClient { suspend fun getProducts(context: Context, forceRefresh: Boolean = false): List = withContext(Dispatchers.IO) { // 1. Try primary URL - val primaryResult = fetchFromUrl(PRIMARY_URL) + val primaryResult = fetchFromUrl(getPrimaryProductsUrl()) if (primaryResult != null && primaryResult.isNotEmpty()) { saveCache(context, primaryResult) return@withContext primaryResult @@ -208,7 +222,7 @@ object ApiClient { val requestBody = jsonPayload.toRequestBody(mediaType) val request = Request.Builder() - .url("https://dripzone.almeira.com.co/api/auth/send-otp") + .url("${getBaseUrl()}/api/auth/send-otp") .post(requestBody) .header("Content-Type", "application/json") .header("Accept", "application/json") @@ -256,7 +270,7 @@ object ApiClient { val requestBody = jsonPayload.toRequestBody(mediaType) val request = Request.Builder() - .url("https://dripzone.almeira.com.co/api/auth/verify-otp") + .url("${getBaseUrl()}/api/auth/verify-otp") .post(requestBody) .header("Content-Type", "application/json") .header("Accept", "application/json") @@ -289,7 +303,7 @@ object ApiClient { val requestBody = jsonPayload.toRequestBody(mediaType) val request = Request.Builder() - .url("https://dripzone.almeira.com.co/api/orders") + .url("${getBaseUrl()}/api/orders") .post(requestBody) .header("Content-Type", "application/json") .header("Accept", "application/json") @@ -324,7 +338,7 @@ object ApiClient { val requestBody = jsonPayload.toRequestBody(mediaType) val request = Request.Builder() - .url("https://dripzone.almeira.com.co/api/custom-requests") + .url("${getBaseUrl()}/api/custom-requests") .post(requestBody) .header("Content-Type", "application/json") .header("Accept", "application/json") @@ -370,7 +384,7 @@ object ApiClient { val requestBody = jsonPayload.toRequestBody(mediaType) val request = Request.Builder() - .url("https://dripzone.almeira.com.co/api/bold/create-payment") + .url("${getBaseUrl()}/api/bold/create-payment") .post(requestBody) .header("Content-Type", "application/json") .header("Accept", "application/json") @@ -403,7 +417,7 @@ object ApiClient { withContext(Dispatchers.IO) { try { val request = Request.Builder() - .url("https://dripzone.almeira.com.co/api/bold/status?linkId=$linkId&orderId=$orderId") + .url("${getBaseUrl()}/api/bold/status?linkId=$linkId&orderId=$orderId") .get() .header("Accept", "application/json") .build() diff --git a/dripzone-app/android/app/src/main/res/xml/network_security_config.xml b/dripzone-app/android/app/src/main/res/xml/network_security_config.xml index 40712b1..ae81e57 100644 --- a/dripzone-app/android/app/src/main/res/xml/network_security_config.xml +++ b/dripzone-app/android/app/src/main/res/xml/network_security_config.xml @@ -12,6 +12,7 @@ almeira.com.co dripzone.almeira.com.co + drip-zone.online news.almeira.com.co cloud.appwrite.io wa.me diff --git a/dripzone-app/docker-compose.prod.yml b/dripzone-app/docker-compose.prod.yml index 0cc8bbf..3dc049a 100644 --- a/dripzone-app/docker-compose.prod.yml +++ b/dripzone-app/docker-compose.prod.yml @@ -35,11 +35,11 @@ services: - "traefik.http.middlewares.redirect-to-https.redirectscheme.scheme=https" - "traefik.http.routers.dripzone-http.entryPoints=http" - "traefik.http.routers.dripzone-http.middlewares=redirect-to-https" - - "traefik.http.routers.dripzone-http.rule=Host(`dripzone.almeira.com.co`) && PathPrefix(`/`)" + - "traefik.http.routers.dripzone-http.rule=Host(`drip-zone.online`) || Host(`www.drip-zone.online`) || Host(`dripzone.almeira.com.co`)" - "traefik.http.routers.dripzone-http.service=dripzone-svc" - "traefik.http.routers.dripzone-https.entryPoints=https" - "traefik.http.routers.dripzone-https.middlewares=gzip" - - "traefik.http.routers.dripzone-https.rule=Host(`dripzone.almeira.com.co`) && PathPrefix(`/`)" + - "traefik.http.routers.dripzone-https.rule=Host(`drip-zone.online`) || Host(`www.drip-zone.online`) || Host(`dripzone.almeira.com.co`)" - "traefik.http.routers.dripzone-https.service=dripzone-svc" - "traefik.http.routers.dripzone-https.tls=true" - "traefik.http.routers.dripzone-https.tls.certresolver=letsencrypt" diff --git a/dripzone-app/src/app/api/bold/create-payment/route.ts b/dripzone-app/src/app/api/bold/create-payment/route.ts index 9f3c539..f7fa218 100644 --- a/dripzone-app/src/app/api/bold/create-payment/route.ts +++ b/dripzone-app/src/app/api/bold/create-payment/route.ts @@ -21,7 +21,7 @@ export async function POST(request: Request) { amount: Number(amount), description, payerEmail, - redirectionUrl: redirectionUrl || `https://dripzone.almeira.com.co/checkout?orderId=${orderId}`, + redirectionUrl: redirectionUrl || `https://drip-zone.online/checkout?orderId=${orderId}`, type, }); diff --git a/scripts/deploy_vps.py b/scripts/deploy_vps.py index 1802336..2dd54df 100644 --- a/scripts/deploy_vps.py +++ b/scripts/deploy_vps.py @@ -84,7 +84,7 @@ def main(): print(" [OK] Archivos sincronizados en VPS.") print("[3/5] Reconstruyendo y reiniciando contenedor en VPS (docker compose build)...") - cmd_build = f"cd {REMOTE_BASE} && docker compose -f docker-compose.prod.yml up -d --build" + cmd_build = f"cd {REMOTE_BASE} && echo {PASSWORD} | sudo -S docker compose -f docker-compose.prod.yml build && echo {PASSWORD} | sudo -S docker compose -f docker-compose.prod.yml up -d" stdin, stdout, stderr = ssh.exec_command(cmd_build) out = stdout.read().decode('utf-8', errors='replace') err = stderr.read().decode('utf-8', errors='replace') @@ -115,20 +115,23 @@ def main(): print("[5/5] Enviando notificación detallada y archivo APK al WhatsApp de Carlos (+57 316 745 5877)...") message_text = ( - "🚀 *DripZone v1.5 - Pasarela de Pagos Bold & QR Bre-B Integrados*\n\n" - "Hola Carlos, se ha completado e implementado en producción la integración integral de la pasarela oficial *Bold*:\n\n" - "💳 *1. Cobro de Separación con QR Bre-B y Pasarela Bold:*\n" - "• Al registrar el primer pedido, la plataforma genera automáticamente una orden de cobro en Bold por *$10.000 COP*.\n" - "• Tanto en la Web como en la App Nativa se renderiza en vivo el *Código QR Bre-B*, permitiendo escanear y pagar al instante desde Bancolombia, Nequi, Daviplata, Dale o cualquier app bancaria interoperable.\n" - "• Incluye botón directo para pagar con tarjeta de crédito/débito o PSE en el checkout alojado seguro de Bold.\n\n" - "⚡ *2. Acreditación Automática en Tiempo Real:*\n" - "• El sistema cuenta con sondeo continuo (polling de 3 segundos) y Webhook (`/api/webhook/bold`) para capturar la aprobación del pago inmediatamente.\n" - "• En cuanto el cliente paga, la pantalla confirma el abono en verde al instante, la orden pasa a estado `deposit_received`, se resta automáticamente el saldo a pagar contraentrega y se te envía notificación inmediata con los datos del pago.\n\n" - "🔑 *3. Modo de Pruebas Activo (Sandbox):*\n" - "• La pasarela está operando actualmente con las llaves de prueba de la API (`GatyXH...` / `BAFlCP...`) para validar el ciclo completo con transacciones simuladas sin costo.\n" - "• Las llaves de producción ya quedaron preconfiguradas en el servidor y listas para encender en cuanto des la orden.\n\n" - "📲 *4. App Nativa Android v1.5 Sincronizada:*\n" - "• Nuevo APK compilado con el módulo de lectura de QR Bre-B, botón a Bold y confirmación reactiva en vivo.\n\n" + "🚀 *DripZone v1.5 - Dominio drip-zone.online & Pasarela Bold Bre-B*\n\n" + "Hola Carlos, se ha implementado en producción la configuración completa:\n\n" + "🌐 *1. Dominio Oficial drip-zone.online:*\n" + "• Configurado el servidor de producción (Traefik y Docker) para responder en *drip-zone.online*, *www.drip-zone.online* y el alias de respaldo `dripzone.almeira.com.co`.\n" + "• Certificados SSL automáticos (Let's Encrypt) habilitados.\n" + "• *Paso restante en tu registrador:* Asegúrate de apuntar los registros A de `drip-zone.online` y `www.drip-zone.online` a la IP del VPS: `161.97.93.156`.\n\n" + "💳 *2. Cobro de Separación con QR Bre-B y Pasarela Bold:*\n" + "• Al registrar el pedido, se genera la orden de cobro en Bold por *$10.000 COP*.\n" + "• En la Web y en la App Nativa se renderiza en tiempo real el *Código QR Bre-B*, permitiendo escanear y pagar al instante desde Bancolombia, Nequi, Daviplata o cualquier banco.\n" + "• Incluye botón directo al checkout seguro de Bold para tarjetas de crédito/débito o PSE.\n\n" + "⚡ *3. Acreditación Automática en Tiempo Real:*\n" + "• Detección inmediata en vivo con Webhook (`/api/webhook/bold`) y sondeo reactivo.\n" + "• Cuando el cliente paga, la orden pasa a `deposit_received`, se descuenta el anticipo del saldo contraentrega y se te envía notificación inmediata con los datos del pago.\n\n" + "🔑 *4. Modo Sandbox Activo para Pruebas:*\n" + "• Operando con las llaves de prueba de la API (`GatyXH...` / `BAFlCP...`) para pruebas sin costo. Las llaves de producción ya están listas para activarse.\n\n" + "📲 *5. App Nativa Android v1.5:*\n" + "• Compilada con soporte dinámico para `drip-zone.online` y QR Bre-B.\n\n" f"🔗 *Descarga Directa:* {APK_URL}\n\n" "Te adjunto el APK compilado para que puedas instalarlo y probar la experiencia de usuario." )