Compare commits
No commits in common. "542565942849ed36a8839092c148ec7cd8d95b62" and "96d7fe6b27798f5bb1deaa200ae416315d270a02" have entirely different histories.
5425659428
...
96d7fe6b27
5
.gitignore
vendored
5
.gitignore
vendored
@ -1,8 +1,5 @@
|
|||||||
*.pdf
|
*.pdf
|
||||||
*.log
|
*.log
|
||||||
*.png
|
*.png
|
||||||
*.jpeg
|
|
||||||
.vscode/
|
.vscode/
|
||||||
*.zip
|
*.zip
|
||||||
vouchers_oxxo/
|
|
||||||
comprobantes/
|
|
||||||
61
CHANGELOG.md
61
CHANGELOG.md
@ -1,61 +0,0 @@
|
|||||||
# CHANGELOG - siip-whatsapp-notifications
|
|
||||||
|
|
||||||
## VERSIÓN 2.9.3 - 23-12-2025
|
|
||||||
### 🟢 Novedades
|
|
||||||
1️⃣ Resolución dinámica del ID del método de pago ("Transferencia bancaria") mediante consulta a la API de UISP, mejorando la portabilidad del plugin entre distintos servidores.
|
|
||||||
2️⃣ Implementación de registro de pago automático desde Webhook Stripe para eventos de tipo `customer_cash_balance_transaction.created` (Saldo aplicado).
|
|
||||||
|
|
||||||
### 🟡 Bugs Resueltos
|
|
||||||
1️⃣ Se corrigió el error de validación de la API de UCRM (422) mediante el cast explícito de `clientId` a integer y el uso de `methodId` como string.
|
|
||||||
|
|
||||||
## VERSIÓN 2.9.2
|
|
||||||
### 🟡 Bugs Resueltos
|
|
||||||
1️⃣ Se solucionó un bug que impedía obtener la contraseñas de la bóveda, ya que el response de la API cambió en la última actualización y la esstructura nueva impedía acceder al dato del password
|
|
||||||
|
|
||||||
## VERSIÓN 2.8.8
|
|
||||||
### 🟡 Bugs Resueltos
|
|
||||||
1️⃣ Se solucionó un bug que impedía al BOT del CallBell mostrar el monto de la referencia de OXXO en el mensaje donde se le entrega el voucher al cliente, para el caso donde el cliente elegía crear su referencia con la CANTIDAD TOTAL.
|
|
||||||
|
|
||||||
## VERSIÓN 2.8.7
|
|
||||||
### 🟢 Novedades
|
|
||||||
1️⃣ Ahora las referencias de **OXXO Pago** han cambiado, en lugar de enviarse la URL o link de pago al cliente será la imagen del código de barras y la información que aparece en el link directamente en el mensaje, de esta manera será más cómodo para el cliente tener la imagen en su chat a tener que abrir una URL o link externo.
|
|
||||||
|
|
||||||
### 🔵 Mejoras
|
|
||||||
1️⃣ Se modificaron nodos del bot ***OXXO_BOT*** para poder adaptar esta actualización correctamente.
|
|
||||||
2️⃣ Mejoras en el código fuente del flujo de trabajo para las referencias de OXXO PAGO.
|
|
||||||
|
|
||||||
## VERSIÓN 2.8.6
|
|
||||||
### 🔵 Mejoras
|
|
||||||
1️⃣ Se modificó la información para el envío de notificaciones a llos instaladores en el flujo de trabajo para la desasignación de tareas que hacía que no se viera correctamente la información
|
|
||||||
|
|
||||||
## VERSIÓN 2.8.5
|
|
||||||
### 🔵 Mejoras
|
|
||||||
1️⃣ Se modificó la información para el envío de notificaciones a los clientes para su visita técnica: ahora ya no se envían las horas en que serán las visitas, SOLO LA FECHA.
|
|
||||||
2️⃣ Se crearon nuevas plantillas de tipo utilidad y se adaptaron al flujo de trabajo en el código.
|
|
||||||
|
|
||||||
### 🟡 Bugs Resueltos
|
|
||||||
1️⃣ Se soluciono el bug que impedía enviar notificaciones a los instaladores para nuevas tareas.
|
|
||||||
|
|
||||||
## VERSIÓN 2.8.2
|
|
||||||
### 🟡 Bugs Resueltos
|
|
||||||
1️⃣ No se enviaban las notificaciones de las tareas al instalador. Se cambió la plantilla de CallBell o WhatsApp con 3 variables en lugar de 8.
|
|
||||||
2️⃣ Se agregó un nuevo tipo de pago ("applied_to_payment") en las propiedades de los Webhooks recibidos mediante Stripe por concepto de transferencias bancarias. Ya que sólo se revisaba el tipo de pago "funded" y eso hacía que no enviara los comprobantes de pago a los clientes para todos los casos.
|
|
||||||
|
|
||||||
## VERSIÓN 2.8.1
|
|
||||||
### 🟡 Bugs Resueltos
|
|
||||||
1️⃣ No se enviaban las notificaciones de las tareas al instalador.
|
|
||||||
|
|
||||||
## VERSIÓN 2.8.0
|
|
||||||
### 🟢 Novedades
|
|
||||||
1️⃣ Envío de contraseña de antena en el mensaje que se manda al instalador cuando se le asigna una tarea/servicio.
|
|
||||||
2️⃣ Para clientes nuevos o que no tengan el campo personalizado de “Password Antena Cliente” al actualizarlos se les asignará ese campo o cuando se les actualice su servicio.
|
|
||||||
3️⃣ Ahora se puede modificar tantas veces sea necesaria una tarea o servicio como su fecha o el instalador mientras la tarea permanezca en estado “Abiertos” SIN que se envíen notificaciones a los clientes o instaladores.
|
|
||||||
4️⃣ Se agregó un prefijo al título de la tarea/servicio agendado cuando recién se da de alta para identificar que esta no ha sido notificada aún y se pueden realizar ajustes.
|
|
||||||
|
|
||||||
### 🔵 Mejoras
|
|
||||||
1️⃣ Se modificó el flujo de trabajo para el envío de notificaciones a los clientes para su visita técnica, ahora son cuatro distintos tipos de flujo, anteriormente tres.
|
|
||||||
2️⃣ Se reemplazaron algunas plantillas de mensajes de CallBell.
|
|
||||||
3️⃣ Se renombró el uso de la etiqueta “CREARCLABESTRIPE” por “CREAR CLABE STRIPE” para un mejor entendimiento de su uso.
|
|
||||||
|
|
||||||
### 🟡 Bugs Resueltos
|
|
||||||
1️⃣ Envío de notificaciones a los clientes y a los instaladores al CERRAR una tarea/servicio (Se mandaban mensajes de asignación y de visita del técnico ) haciendo no posible cerrar las tareas.
|
|
||||||
249
README.md
249
README.md
@ -1,73 +1,210 @@
|
|||||||
# SIIP - WhatsApp Notifications & Stripe Payments for UCRM
|
# SIIP - Procesador de Pagos en línea con Stripe, Oxxo y Transferencia, Sincronizador de CallBell y Envío de Notificaciones y comprobantes vía WhatsApp
|
||||||
|
|
||||||
Este plugin es una solución integral para automatizar la comunicación con clientes y la gestión de pagos en UISP/UCRM. Actúa como puente entre el CRM, Stripe y la plataforma de mensajería CallBell.
|
Este plugin sincroniza los clientes del sitema UISP CRM con los contactos de WhatsApp en CallBell, además procesa pagos de Stripe como las trasferencias bancarias y genera referencias de pago vía OXXO, además envía comprobantes de pago en formato imagen PNG o texto vía Whatsapp a los clientes
|
||||||
|
|
||||||
## 🚀 Funcionalidades Principales
|
|
||||||
|
|
||||||
- **Notificaciones Dinámicas**: Envío automático de mensajes por WhatsApp para facturas, pagos, suspensiones y reactivaciones.
|
## Configuration
|
||||||
- **Gestión de Agenda (Jobs/Tasks)**: Notificación inteligente a técnicos e instaladores sobre nuevas tareas, reprogramaciones y desasignaciones.
|
|
||||||
- **Pagos con Stripe & OXXO**: Generación automatizada de referencias de OXXO con captura de pantalla (Puppeteer) y alojamiento en la nube (WordPress).
|
|
||||||
- **Sincronización CallBell**: Mantenimiento de la información del cliente actualizada en la plataforma de chat CallBell.
|
|
||||||
- **Resolución Dinámica**: Detección automática de métodos de pago y atributos personalizados para máxima portabilidad.
|
|
||||||
|
|
||||||
---
|
* Install the plugin into UCRM and enable it. I.e. download the plugin [zip file](https://github.com/Ubiquiti-App/UCRM-plugins/raw/master/plugins/sms-twilio/sms-twilio.zip) and upload it to UCRM in System > Plugins.
|
||||||
|
* Keep execution period at "don't execute automatically" - the plugin will react to webhook events.
|
||||||
|
* Set up with data which you obtain from [Twilio Console](https://twilio.com/console):
|
||||||
|
* Account SID
|
||||||
|
* Auth Token
|
||||||
|
* SMS number to send from
|
||||||
|
|
||||||
|
Note: there are two sets of credentials available, the default ("LIVE credentials") for actual use and [test credentials](https://www.twilio.com/console/project/settings) for development.
|
||||||
|
|
||||||
|
* Customize the texts you wish to send to a client when an event happens
|
||||||
|
* Each event has its own row
|
||||||
|
* Empty row means "do not send SMS for this"
|
||||||
|
* It is possible to replace predefined variables: `%%some.variable%%`, see full list below
|
||||||
|
* If a variable is not set for a client, it is replaced with an empty string
|
||||||
|
* Save the configuration
|
||||||
|
* Enable the plugin
|
||||||
|
* Add webhook (button next to Public URL)
|
||||||
|
* Select events about which to notify clients and save the webhook endpoint
|
||||||
|
|
||||||
## 🏗️ Arquitectura del Sistema
|
## Usage
|
||||||
|
* In UCRM admin, go to System / Webhooks / Endpoints
|
||||||
|
* Click Test Endpoint
|
||||||
|
* Go to System / Plugins / SIIP - Procesador de Pagos en línea con Stripe, Oxxo y Transferencia, Sincronizador de CallBell y Envío de Notificaciones y comprobantes vía WhatsApp
|
||||||
|
* In the log output, you'll see `Webhook test successful.`
|
||||||
|
|
||||||
El plugin utiliza un patrón de diseño basado en **Facades** para desacoplar la lógica de despacho de los servicios externos.
|
## Variables replaced
|
||||||
|
|
||||||
### Componentes Clave
|
These are loaded from UCRM API, and reflect the structure returned.
|
||||||
|
Client variables are replaced always; payment invoice and service only with the applicable events.
|
||||||
|
|
||||||
- **Despachador Central (`Plugin.php`)**: Gestiona tanto los webhooks internos de UCRM como los externos (Stripe). Controla el estado de las notificaciones de tareas mediante prefijos en los títulos (`[NOTIFICACION-PENDIENTE]`).
|
### Client variables
|
||||||
- **Fachada de Mensajería (`AbstractMessageNotifierFacade`)**: Contiene la lógica de negocio para decidir qué notificar, cuándo y a quién.
|
|
||||||
- **Interfaz CallBell (`ClientCallBellAPI`)**: Encapsula las llamadas a la API de CallBell, manejando plantillas y mensajes multimedia.
|
|
||||||
- **Operaciones OXXO (`AbstractOxxoOperationsFacade`)**: Orquesta el flujo de pago: Stripe (Referencia) -> Puppeteer (Screenshot) -> WordPress (Hosting) -> CallBell (WhatsApp).
|
|
||||||
|
|
||||||
---
|
* `%%client.id%%` => 20
|
||||||
|
* `%%client.userIdent%%` => '18'
|
||||||
|
* `%%client.previousIsp%%` => ''
|
||||||
|
* `%%client.isLead%%` => false
|
||||||
|
* `%%client.clientType%%` => 1
|
||||||
|
* `%%client.companyName%%` => ''
|
||||||
|
* `%%client.companyRegistrationNumber%%` => ''
|
||||||
|
* `%%client.companyTaxId%%` => ''
|
||||||
|
* `%%client.companyWebsite%%` => ''
|
||||||
|
* `%%client.street1%%` => '2544 Hillview Drive'
|
||||||
|
* `%%client.street2%%` => ''
|
||||||
|
* `%%client.city%%` => 'San Jose'
|
||||||
|
* `%%client.countryId%%` => 249
|
||||||
|
* `%%client.stateId%%` => 5
|
||||||
|
* `%%client.zipCode%%` => '95113'
|
||||||
|
* `%%client.invoiceStreet1%%` => ''
|
||||||
|
* `%%client.invoiceStreet2%%` => ''
|
||||||
|
* `%%client.invoiceCity%%` => ''
|
||||||
|
* `%%client.invoiceStateId%%` => ''
|
||||||
|
* `%%client.invoiceCountryId%%` => ''
|
||||||
|
* `%%client.invoiceZipCode%%` => ''
|
||||||
|
* `%%client.invoiceAddressSameAsContact%%` => true
|
||||||
|
* `%%client.note%%` => ''
|
||||||
|
* `%%client.sendInvoiceByPost%%` => false
|
||||||
|
* `%%client.invoiceMaturityDays%%` => 14
|
||||||
|
* `%%client.stopServiceDue%%` => true
|
||||||
|
* `%%client.stopServiceDueDays%%` => 7
|
||||||
|
* `%%client.organizationId%%` => 1
|
||||||
|
* `%%client.tax1Id%%` => 1
|
||||||
|
* `%%client.tax2Id%%` => ''
|
||||||
|
* `%%client.tax3Id%%` => ''
|
||||||
|
* `%%client.registrationDate%%` => '2016-04-26 00:00'
|
||||||
|
* `%%client.companyContactFirstName%%` => ''
|
||||||
|
* `%%client.companyContactLastName%%` => ''
|
||||||
|
* `%%client.isActive%%` => false
|
||||||
|
* `%%client.firstName%%` => 'Tyson'
|
||||||
|
* `%%client.lastName%%` => 'Doe'
|
||||||
|
* `%%client.username%%` => 'tyson.doe@example.com'
|
||||||
|
* `%%client.accountBalance%%` => 0
|
||||||
|
* `%%client.accountCredit%%` => 0
|
||||||
|
* `%%client.accountOutstanding%%` => 0
|
||||||
|
* `%%client.currencyCode%%` => 'USD'
|
||||||
|
* `%%client.organizationName%%` => 'UBNT ISP'
|
||||||
|
* `%%client.invitationEmailSentDate%%` => ''
|
||||||
|
* `%%client.avatarColor%%` => '#e53935'
|
||||||
|
* `%%client.addressGpsLat%%` => 37.401482000001
|
||||||
|
* `%%client.addressGpsLon%%` => -121.966545
|
||||||
|
* `%%client.message%%` => 'This is an example message sent from the Messaging feature.'
|
||||||
|
|
||||||
## 🛠️ Requisitos e Integraciones
|
### Invoice variables
|
||||||
|
* `%%invoice.id%%` => 4
|
||||||
|
* `%%invoice.clientId%%` => 20
|
||||||
|
* `%%invoice.number%%` => '2016050002'
|
||||||
|
* `%%invoice.createdDate%%` => '2016-05-03 00:00'
|
||||||
|
* `%%invoice.dueDate%%` => '2016-05-17 00:00'
|
||||||
|
* `%%invoice.emailSentDate%%` => '2018-08-24 00:00'
|
||||||
|
* `%%invoice.maturityDays%%` => 14
|
||||||
|
* `%%invoice.notes%%` => ''
|
||||||
|
* `%%invoice.adminNotes%%` => ''
|
||||||
|
* `%%invoice.subtotal%%` => 7.88
|
||||||
|
* `%%invoice.discount%%` => ''
|
||||||
|
* `%%invoice.discountLabel%%` => ''
|
||||||
|
* `%%invoice.total%%` => 7.88
|
||||||
|
* `%%invoice.amountPaid%%` => 7.88
|
||||||
|
* `%%invoice.currencyCode%%` => 'USD'
|
||||||
|
* `%%invoice.status%%` => 3
|
||||||
|
* `%%invoice.invoiceTemplateId%%` => 1
|
||||||
|
* `%%invoice.organizationName%%` => 'UBNT ISP'
|
||||||
|
* `%%invoice.organizationRegistrationNumber%%` => ''
|
||||||
|
* `%%invoice.organizationTaxId%%` => ''
|
||||||
|
* `%%invoice.organizationStreet1%%` => '2580 Orchard Parkway'
|
||||||
|
* `%%invoice.organizationStreet2%%` => ''
|
||||||
|
* `%%invoice.organizationCity%%` => 'New York'
|
||||||
|
* `%%invoice.organizationStateId%%` => 1
|
||||||
|
* `%%invoice.organizationCountryId%%` => 249
|
||||||
|
* `%%invoice.organizationZipCode%%` => '10017'
|
||||||
|
* `%%invoice.organizationBankAccountName%%` => ''
|
||||||
|
* `%%invoice.organizationBankAccountField1%%` => ''
|
||||||
|
* `%%invoice.organizationBankAccountField2%%` => ''
|
||||||
|
* `%%invoice.clientFirstName%%` => 'Tyson'
|
||||||
|
* `%%invoice.clientLastName%%` => 'Doe'
|
||||||
|
* `%%invoice.clientCompanyName%%` => ''
|
||||||
|
* `%%invoice.clientCompanyRegistrationNumber%%` => ''
|
||||||
|
* `%%invoice.clientCompanyTaxId%%` => ''
|
||||||
|
* `%%invoice.clientStreet1%%` => '685 Third Avenue'
|
||||||
|
* `%%invoice.clientStreet2%%` => ''
|
||||||
|
* `%%invoice.clientCity%%` => 'New York'
|
||||||
|
* `%%invoice.clientCountryId%%` => 249
|
||||||
|
* `%%invoice.clientStateId%%` => 5
|
||||||
|
* `%%invoice.clientZipCode%%` => '10017'
|
||||||
|
* `%%invoice.uncollectible%%` => false
|
||||||
|
|
||||||
Para un funcionamiento óptimo, el plugin requiere:
|
### Payment variables
|
||||||
|
* `%%payment.id%%` => 28
|
||||||
|
* `%%payment.clientId%%` => 20
|
||||||
|
* `%%payment.invoiceId%%` => ''
|
||||||
|
* `%%payment.method%%` => 2
|
||||||
|
* `%%payment.checkNumber%%` => ''
|
||||||
|
* `%%payment.createdDate%%` => '2018-08-24 11:36'
|
||||||
|
* `%%payment.amount%%` => 1
|
||||||
|
* `%%payment.currencyCode%%` => 'USD'
|
||||||
|
* `%%payment.note%%` => ''
|
||||||
|
* `%%payment.receiptSentDate%%` => ''
|
||||||
|
* `%%payment.providerName%%` => ''
|
||||||
|
* `%%payment.providerPaymentId%%` => ''
|
||||||
|
* `%%payment.providerPaymentTime%%` => ''
|
||||||
|
* `%%payment.creditAmount%%` => 0
|
||||||
|
* `%%payment.applyToInvoicesAutomatically%%` => false
|
||||||
|
|
||||||
1. **UISP/UCRM**: Versión compatible con el SDK de Ubiquiti.
|
### Service variables
|
||||||
2. **Stripe API**: Token y Webhooks configurados para transacciones en tiempo real.
|
* `%%service.id%%` => 23
|
||||||
3. **CallBell API**: Token de acceso para el envío de mensajes a través de plantillas de WhatsApp.
|
* `%%service.clientId%%` => 20
|
||||||
4. **Microservicio Puppeteer**: Un contenedor Docker con la API de Puppeteer para capturar vouchers.
|
* `%%service.status%%` => 1
|
||||||
5. **Hosting WordPress (FTP)**: Para alojar temporalmente las imágenes de los vouchers enviadas a los clientes.
|
* `%%service.name%%` => 'Mini'
|
||||||
|
* `%%service.street1%%` => '622 Hide A Way Road'
|
||||||
|
* `%%service.street2%%` => ''
|
||||||
|
* `%%service.city%%` => 'San Jose'
|
||||||
|
* `%%service.countryId%%` => 249
|
||||||
|
* `%%service.stateId%%` => 5
|
||||||
|
* `%%service.zipCode%%` => '95135'
|
||||||
|
* `%%service.note%%` => ''
|
||||||
|
* `%%service.addressGpsLat%%` => 37.232849
|
||||||
|
* `%%service.addressGpsLon%%` => -121.752502
|
||||||
|
* `%%service.servicePlanId%%` => 1
|
||||||
|
* `%%service.servicePlanPeriodId%%` => 2
|
||||||
|
* `%%service.price%%` => 25
|
||||||
|
* `%%service.hasIndividualPrice%%` => false
|
||||||
|
* `%%service.totalPrice%%` => 25
|
||||||
|
* `%%service.currencyCode%%` => 'USD'
|
||||||
|
* `%%service.invoiceLabel%%` => ''
|
||||||
|
* `%%service.contractId%%` => ''
|
||||||
|
* `%%service.contractLengthType%%` => 1
|
||||||
|
* `%%service.minimumContractLengthMonths%%` => ''
|
||||||
|
* `%%service.activeFrom%%` => '2016-05-03T00:00:00+0000'
|
||||||
|
* `%%service.activeTo%%` => ''
|
||||||
|
* `%%service.contractEndDate%%` => ''
|
||||||
|
* `%%service.discountType%%` => 0
|
||||||
|
* `%%service.discountValue%%` => ''
|
||||||
|
* `%%service.discountInvoiceLabel%%` => ''
|
||||||
|
* `%%service.discountFrom%%` => ''
|
||||||
|
* `%%service.discountTo%%` => ''
|
||||||
|
* `%%service.tax1Id%%` => ''
|
||||||
|
* `%%service.tax2Id%%` => ''
|
||||||
|
* `%%service.tax3Id%%` => ''
|
||||||
|
* `%%service.invoicingStart%%` => '2016-05-03T00:00:00+0000'
|
||||||
|
* `%%service.invoicingPeriodType%%` => 1
|
||||||
|
* `%%service.invoicingPeriodStartDay%%` => 1
|
||||||
|
* `%%service.nextInvoicingDayAdjustment%%` => 0
|
||||||
|
* `%%service.invoicingProratedSeparately%%` => true
|
||||||
|
* `%%service.invoicingSeparately%%` => false
|
||||||
|
* `%%service.sendEmailsAutomatically%%` => false
|
||||||
|
* `%%service.useCreditAutomatically%%` => true
|
||||||
|
* `%%service.servicePlanName%%` => 'Mini'
|
||||||
|
* `%%service.servicePlanPrice%%` => 25
|
||||||
|
* `%%service.servicePlanPeriod%%` => 3
|
||||||
|
* `%%service.downloadSpeed%%` => 10
|
||||||
|
* `%%service.uploadSpeed%%` => 10
|
||||||
|
* `%%service.hasOutage%%` => true
|
||||||
|
* `%%service.stopReason%%` => 'Payments overdue'
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 🏷️ Configuración de UCRM
|
## Developers
|
||||||
|
* This plugin is MIT-licensed and can be used by developers as a template for integrating with a different messaging solution:
|
||||||
|
* Create a new plugin based on this one
|
||||||
|
* Replace the TwilioNotifierFacade and any references to it with a different class which extends AbstractMessageNotifierFacade
|
||||||
|
* Update libraries in composer.json as needed
|
||||||
|
* Communicate with the remote system in the sendMessage() function
|
||||||
|
|
||||||
### Contactos y Etiquetas
|
|
||||||
El plugin selecciona los números de destino basándose en el **Tipo de Contacto** definido en UCRM:
|
|
||||||
- `WhatsApp`: Recibe notificaciones y actualizaciones de datos.
|
|
||||||
- `WhatsNotifica`: Recibe solo notificaciones.
|
|
||||||
- `WhatsActualiza`: Utilizado solo para sincronizar datos con CallBell.
|
|
||||||
|
|
||||||
### Atributos Personalizados
|
Read more about creating your own plugin in the [Developer documentation](https://github.com/Ubiquiti-App/UCRM-plugins/blob/master/docs/index.md).
|
||||||
Es necesario configurar los siguientes atributos en UCRM:
|
|
||||||
- `stripeCustomerId`: ID del cliente en Stripe.
|
|
||||||
- `clabeInterbancaria`: CLABE personalizada para transferencias.
|
|
||||||
- `passwordAntenaCliente`: Almacena la contraseña del equipo del cliente (sincronizada con la bóveda).
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 🔄 Flujos de Trabajo Destacados
|
|
||||||
|
|
||||||
### 📅 Notificación de Visitas Técnicas
|
|
||||||
Cuando se asigna o reprograma una tarea:
|
|
||||||
1. El plugin detecta el cambio en el `assignedUserId` o la fecha.
|
|
||||||
2. Envía un mensaje al cliente con el nombre del técnico y la fecha (sin hora, por privacidad/logística).
|
|
||||||
3. Envía un mensaje al técnico con la dirección, ubicación en Google Maps y la contraseña de la antena obtenida de la bóveda de UISP.
|
|
||||||
|
|
||||||
### 💳 Registro de Pagos por Transferencia
|
|
||||||
1. Stripe envía un webhook de saldo aplicado (`customer_cash_balance_transaction.created`).
|
|
||||||
2. El plugin resuelve dinámicamente el ID del método "Transferencia bancaria".
|
|
||||||
3. Registra el pago automáticamente en UCRM vinculado al `clientId` en los metadatos.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 📝 Registro de Cambios
|
|
||||||
|
|
||||||
Para consultar la evolución del proyecto, ver el archivo [CHANGELOG.md](./CHANGELOG.md).
|
|
||||||
BIN
comprobantes/Comprobante_Daniel_Humberto_Soto_Villegas.pdf
Executable file
BIN
comprobantes/Comprobante_Daniel_Humberto_Soto_Villegas.pdf
Executable file
Binary file not shown.
BIN
comprobantes/Comprobante_Daniel_Humberto_Soto_Villegas.png
Executable file
BIN
comprobantes/Comprobante_Daniel_Humberto_Soto_Villegas.png
Executable file
Binary file not shown.
|
After Width: | Height: | Size: 104 KiB |
@ -1 +1 @@
|
|||||||
{"ipserver":"172.16.5.134","apitoken":"gvcnIJqXdUjneVSjhl6THLlQcYXJyIFCcwHKVba2bvIrNraanCTb5VeoWuJ0TFZ9","unmsApiToken":"079c28f5-888c-457d-bd7a-0a4202590f75","tokencallbell":"g8thcZkXGd3xBj2g3TtYNYFMH1fuesbJ.b6a940ea7d78cf6c9e42f067b21c8ddf96e9fa2a9e307bfd0c7c7c4d7fa38f79","tokenstripe":"sk_test_51OkG0REFY1WEUtgRH6UxBK5pu80Aq5Iy8EcdPnf0cOWzuVLQTpyLCd7CbPzqMsWMafZOHElCxhEHF7g8boURjWlJ00tBwE0W1M","hostServerFTP":"siip.mx","usernameServerFTP":"siip0001","passServerFTP":"$spGiT,[wa)n","ipPuppeteer":"172.16.5.134","portPuppeteer":"3000","idPaymentAdminCRM":"1180","cashPaymentMethodId":false,"courtesyPaymentMethodId":false,"bankTransferPaymentMethodId":true,"paypalPaymentMethodId":true,"creditCardPaypalPaymentMethodId":true,"creditCardStripePaymentMethodId":true,"stripeSubscriptionCreditCardPaymentMethodId":true,"paypalSubscriptionPaymentMethodId":true,"mercadopagoPaymentMethodId":true,"checkPaymentMethodId":true,"customPaymentMethodId":true,"notificationTypeText":true,"installersDataWhatsApp":"{\r\n \"instaladores\": [\r\n {\r\n \"id\": 1019,\r\n \"nombre\": \"Mucio Robledo\",\r\n \"whatsapp\": \"4181878106\"\r\n },\r\n {\r\n \"id\": 1173,\r\n \"nombre\": \"Ángel Arvizu\",\r\n \"whatsapp\": \"4181878106\"\r\n },\r\n {\r\n \"id\": 1172,\r\n \"nombre\": \"Juan Rostro\",\r\n \"whatsapp\": \"4181878106\"\r\n },\r\n {\r\n \"id\": 1015,\r\n \"nombre\": \"Daniel Humberto\",\r\n \"whatsapp\": \"4181878106\"\r\n },\r\n {\r\n \"id\": 1131,\r\n \"nombre\": \"Gricelda Avalos\",\r\n \"whatsapp\": \"4181817609\"\r\n }\r\n ]\r\n}","debugMode":true,"logging_level":true}
|
{"ipserver":"172.16.5.134","apitoken":"6abef18c-783d-4dd0-b530-be6e6a7bbd1d","tokencallbell":"g8thcZkXGd3xBj2g3TtYNYFMH1fuesbJ.b6a940ea7d78cf6c9e42f067b21c8ddf96e9fa2a9e307bfd0c7c7c4d7fa38f79","tokenstripe":"sk_test_51OkG0REFY1WEUtgRH6UxBK5pu80Aq5Iy8EcdPnf0cOWzuVLQTpyLCd7CbPzqMsWMafZOHElCxhEHF7g8boURjWlJ00tBwE0W1M","unmsApiToken":null,"hostServerFTP":"siip.mx","usernameServerFTP":"siip0001","passServerFTP":"$spGiT,[wa)n","cashPaymentMethodId":false,"courtesyPaymentMethodId":false,"bankTransferPaymentMethodId":true,"paypalPaymentMethodId":true,"creditCardPaypalPaymentMethodId":true,"creditCardStripePaymentMethodId":true,"stripeSubscriptionCreditCardPaymentMethodId":true,"paypalSubscriptionPaymentMethodId":true,"mercadopagoPaymentMethodId":true,"checkPaymentMethodId":true,"customPaymentMethodId":true,"notificationTypeText":false,"installersDataWhatsApp":"{\r\n \"instaladores\": [\r\n {\r\n \"id\": 1019,\r\n \"nombre\": \"Mucio Robledo\",\r\n \"whatsapp\": \"4181878106\"\r\n },\r\n {\r\n \"id\": 1173,\r\n \"nombre\": \"Angel Arvizu\",\r\n \"whatsapp\": \"4181878106\"\r\n },\r\n {\r\n \"id\": 1172,\r\n \"nombre\": \"Juan Rostro\",\r\n \"whatsapp\": \"4181878106\"\r\n },\r\n {\r\n \"id\": 1015,\r\n \"nombre\": \"Daniel Humberto\",\r\n \"whatsapp\": \"4181878106\"\r\n }\r\n ]\r\n}","debugMode":true,"logging_level":true}
|
||||||
20100
data/plugin.log
20100
data/plugin.log
File diff suppressed because one or more lines are too long
@ -5,7 +5,7 @@
|
|||||||
"displayName": "SIIP - Procesador de Pagos en línea con Stripe, Oxxo y Transferencia, Sincronizador de CallBell y Envío de Notificaciones y comprobantes vía WhatsApp",
|
"displayName": "SIIP - Procesador de Pagos en línea con Stripe, Oxxo y Transferencia, Sincronizador de CallBell y Envío de Notificaciones y comprobantes vía WhatsApp",
|
||||||
"description": "Este plugin sincroniza los clientes del sistema UISP CRM con los contactos de WhatsApp en CallBell, además procesa pagos de Stripe como las trasferencias bancarias y genera referencias de pago vía OXXO, además envía comprobantes de pago en formato imagen PNG o texto vía Whatsapp a los clientes",
|
"description": "Este plugin sincroniza los clientes del sistema UISP CRM con los contactos de WhatsApp en CallBell, además procesa pagos de Stripe como las trasferencias bancarias y genera referencias de pago vía OXXO, además envía comprobantes de pago en formato imagen PNG o texto vía Whatsapp a los clientes",
|
||||||
"url": "https://siip.mx/",
|
"url": "https://siip.mx/",
|
||||||
"version": "2.9.2",
|
"version": "2.7.0",
|
||||||
"unmsVersionCompliancy": {
|
"unmsVersionCompliancy": {
|
||||||
"min": "2.1.0",
|
"min": "2.1.0",
|
||||||
"max": null
|
"max": null
|
||||||
@ -23,17 +23,10 @@
|
|||||||
{
|
{
|
||||||
"key": "apitoken",
|
"key": "apitoken",
|
||||||
"label": "Token de la API UCRM",
|
"label": "Token de la API UCRM",
|
||||||
"description": "Token de autenticación necesario para el uso de la API del sistema UISP UCRM, se utiliza para gestionar cualquier información de los clientes. Contiene 64 caracteres y se genera desde el módulo de Ajustes del UISP CRM en la opción de 'Seguridad' y en la sección de 'Claves app'.",
|
"description": "Token de autenticación para el uso de la API del sistema UISP UCRM. Contiene 36 caracteres, ejemplo: 3d3fa6c9-e268-6e8b-b4d5-aae394d99d7d",
|
||||||
"required": 1,
|
"required": 1,
|
||||||
"type": "text"
|
"type": "text"
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"key": "unmsApiToken",
|
|
||||||
"label": "Token de la API UNMS",
|
|
||||||
"description": "Token de autenticación necesario para el uso de la API del sistema UISP UNMS, se utiliza para gestionar información de antenas u otros dispositivos de red. Contiene 34 caracteres y se genera desde el módulo de Ajustes del UISP Network en la opción de 'Usuarios' y en apartado de 'API tokens'.",
|
|
||||||
"required": 0,
|
|
||||||
"type": "text"
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"key": "tokencallbell",
|
"key": "tokencallbell",
|
||||||
"label": "Token de la API de CallBell",
|
"label": "Token de la API de CallBell",
|
||||||
@ -44,10 +37,17 @@
|
|||||||
{
|
{
|
||||||
"key": "tokenstripe",
|
"key": "tokenstripe",
|
||||||
"label": "Token de la API de Stripe",
|
"label": "Token de la API de Stripe",
|
||||||
"description": "Token de autenticación para el uso de la API de Stripe que maneja las funciones realacionadas con los pagos en línea (Transferencia y OXXO PAGO). ",
|
"description": "Token de autenticación para el uso de la API de Stripe que maneja las funciones realacionadas con los pagos en línea. ",
|
||||||
"required": 1,
|
"required": 1,
|
||||||
"type": "text"
|
"type": "text"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"key": "unmsApiToken",
|
||||||
|
"label": "Token de la API UNMS",
|
||||||
|
"description": "Token API creado para este plugin en la seccion Network de UNMS, solo necesario cuando se utiliza UNMS v1",
|
||||||
|
"required": 0,
|
||||||
|
"type": "text"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"key": "hostServerFTP",
|
"key": "hostServerFTP",
|
||||||
"label": "IP o dominio del servidor FTP",
|
"label": "IP o dominio del servidor FTP",
|
||||||
@ -58,35 +58,14 @@
|
|||||||
{
|
{
|
||||||
"key": "usernameServerFTP",
|
"key": "usernameServerFTP",
|
||||||
"label": "Usuario FTP",
|
"label": "Usuario FTP",
|
||||||
"description": "Nombre de usuario para inicio de sesión el servidor FTP, necesario para la carga de comprobantes de pago del sistema y su posterior envío",
|
"description": "Nombre de usuario para inicio de sesión el servidor FTP",
|
||||||
"required": 1,
|
"required": 1,
|
||||||
"type": "text"
|
"type": "text"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"key": "passServerFTP",
|
"key": "passServerFTP",
|
||||||
"label": "Password FTP",
|
"label": "Password FTP",
|
||||||
"description": "Contraseña para inicio de sesión en el servidor FTP, necesario para la carga de comprobantes de pago del sistema y su posterior envío",
|
"description": "Contraseña para inicio de sesión en el servidor FTP",
|
||||||
"required": 1,
|
|
||||||
"type": "text"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"key": "ipPuppeteer",
|
|
||||||
"label": "Dirección IP del servicio de Puppeteer",
|
|
||||||
"description": "Dirección IP del contenedor docker que ejecuta el servicio de Puppeteer para la generación de comprobantes de pago en formato imagen PNG",
|
|
||||||
"required": 1,
|
|
||||||
"type": "text"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"key": "portPuppeteer",
|
|
||||||
"label": "Puerto del servicio de Puppeteer",
|
|
||||||
"description": "Puerto del contenedor docker que ejecuta el servicio de Puppeteer, por defecto es el 3000",
|
|
||||||
"required": 1,
|
|
||||||
"type": "text"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"key": "idPaymentAdminCRM",
|
|
||||||
"label": "ID del usuario para pagos en línea",
|
|
||||||
"description": "ID del usuario administrador del CRM asigando para realizar pagos en línea con Stripe. Todos los pagos que llegan desde Stripe se asignan a este usuario. Se recomienda crear un usuario exclusivo para este fin.",
|
|
||||||
"required": 1,
|
"required": 1,
|
||||||
"type": "text"
|
"type": "text"
|
||||||
},
|
},
|
||||||
@ -202,6 +181,18 @@
|
|||||||
"label": "Borrar comprobantes Wordpress",
|
"label": "Borrar comprobantes Wordpress",
|
||||||
"type": "admin",
|
"type": "admin",
|
||||||
"target": "iframe"
|
"target": "iframe"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"key": "Reports",
|
||||||
|
"label": "Generador de Clabes CBM en Stripe",
|
||||||
|
"type": "admin",
|
||||||
|
"target": "iframe"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"key": "Reports",
|
||||||
|
"label": "Obtener datos del Network de Cliente",
|
||||||
|
"type": "admin",
|
||||||
|
"target": "iframe"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"supportsWebhookEvents": true
|
"supportsWebhookEvents": true
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@ -11,8 +11,6 @@ use SmsNotifier\Service\SmsNumberProvider;
|
|||||||
use GuzzleHttp\Client;
|
use GuzzleHttp\Client;
|
||||||
use GuzzleHttp\Exception\RequestException;
|
use GuzzleHttp\Exception\RequestException;
|
||||||
use Ubnt\UcrmPluginSdk\Service\UcrmApi;
|
use Ubnt\UcrmPluginSdk\Service\UcrmApi;
|
||||||
use Ubnt\UcrmPluginSdk\Service\PluginConfigManager;
|
|
||||||
use Ubnt\UcrmPluginSdk\Service\PluginLogManager;
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -62,30 +60,27 @@ abstract class AbstractOxxoOperationsFacade
|
|||||||
* @throws \Stripe\Exception\ApiErrorException
|
* @throws \Stripe\Exception\ApiErrorException
|
||||||
* @throws Exception
|
* @throws Exception
|
||||||
*/
|
*/
|
||||||
public function createOxxoPaymentIntent($event_json, $amount = null): array
|
public function createOxxoPaymentIntent($event_json, $amount = null): array
|
||||||
{
|
{
|
||||||
//declarar un array asociativo de strings pero no asignarle nada aun
|
//declarar un array asociativo de strings pero no asignarle nada aun
|
||||||
$arrayOxxoPayment = array();
|
$arrayOxxoPayment = array();
|
||||||
$integerAmount = $amount;
|
$integerAmount = $amount;
|
||||||
|
|
||||||
$this->logger->info("Creando referencia del cliente para OXXO: " . PHP_EOL);
|
$this->logger->info("Creando referencia del cliente para OXXO: " . PHP_EOL);
|
||||||
$configManager = PluginConfigManager::create();
|
$configManager = \Ubnt\UcrmPluginSdk\Service\PluginConfigManager::create();
|
||||||
$config = $configManager->loadConfig();
|
$config = $configManager->loadConfig();
|
||||||
$StripeToken = $config['tokenstripe'];
|
$StripeToken = $config['tokenstripe'];
|
||||||
$IPServer = $config['ipserver'];
|
$IPServer = $config['ipserver'];
|
||||||
$tokenCRM = $config['apitoken'];
|
$tokenCRM = $config['apitoken'];
|
||||||
$ipPuppeteer = $config['ipPuppeteer'];
|
|
||||||
$portPuppeteer = $config['portPuppeteer'];
|
|
||||||
|
|
||||||
$baseUri = 'https://' . $IPServer . '/crm/api/v1.0/';
|
$baseUri = 'https://' . $IPServer . '/crm/api/v1.0/';
|
||||||
$this->ucrmApi = UcrmApi::create();
|
$this->ucrmApi = UcrmApi::create();
|
||||||
$currentUserAdmin = $this->ucrmApi->get('users/admins', []);
|
$currentUserAdmin = $this->ucrmApi->get('users/admins', []);
|
||||||
$clientID = $event_json['client_id'];
|
$clientID = $event_json['client_id'];
|
||||||
|
|
||||||
$stripeCustomerId = null;
|
$stripeCustomerId = null;
|
||||||
$clientEmail = '';
|
$clientEmail = '';
|
||||||
$clientFullName = '';
|
|
||||||
|
|
||||||
$clientGuzzleHttp = new Client([
|
$clientGuzzleHttp = new Client([
|
||||||
'base_uri' => $baseUri,
|
'base_uri' => $baseUri,
|
||||||
'headers' => [
|
'headers' => [
|
||||||
@ -95,7 +90,7 @@ abstract class AbstractOxxoOperationsFacade
|
|||||||
'verify' => false,
|
'verify' => false,
|
||||||
'timeout' => 5, // Timeout de 5 segundos
|
'timeout' => 5, // Timeout de 5 segundos
|
||||||
]);
|
]);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
$response = $clientGuzzleHttp->request('GET', "clients/" . $clientID);
|
$response = $clientGuzzleHttp->request('GET', "clients/" . $clientID);
|
||||||
$arrayClientCRM = json_decode($response->getBody()->getContents(), true);
|
$arrayClientCRM = json_decode($response->getBody()->getContents(), true);
|
||||||
@ -112,39 +107,34 @@ abstract class AbstractOxxoOperationsFacade
|
|||||||
$arrayOxxoPayment['clientID'] = $clientID;
|
$arrayOxxoPayment['clientID'] = $clientID;
|
||||||
$arrayOxxoPayment['clientFullName'] = $clientFullName;
|
$arrayOxxoPayment['clientFullName'] = $clientFullName;
|
||||||
$arrayOxxoPayment['amount'] = $integerAmount;
|
$arrayOxxoPayment['amount'] = $integerAmount;
|
||||||
$arrayOxxoPayment['voucher_image_url'] = '';
|
|
||||||
return $arrayOxxoPayment;
|
return $arrayOxxoPayment;
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
//timeout
|
//timeout
|
||||||
if ($e->getCode() === 408) {
|
if ($e->getCode() === 408) {
|
||||||
$this->logger->error("Timeout al obtener el cliente en CRM: " . $clientID . PHP_EOL);
|
$this->logger->error("Timeout al obtener el cliente en CRM: " . $clientID . PHP_EOL);
|
||||||
//devolver un array con los campos del codigo error, descripción de la falla, clientID y amount
|
//devolver un array con los campos del codigo error, descripción de la falla, clientID y amount
|
||||||
$arrayOxxoPayment['oxxo_reference'] = '';
|
$arrayOxxoPayment['oxxo_reference'] = '';
|
||||||
$arrayOxxoPayment['url'] = '';
|
|
||||||
$arrayOxxoPayment['error'] = 'errorTimeoutGetClient';
|
$arrayOxxoPayment['error'] = 'errorTimeoutGetClient';
|
||||||
$arrayOxxoPayment['failDescription'] = 'Timeout al obtener el cliente en CRM: ' . $clientID;
|
$arrayOxxoPayment['failDescription'] = 'Timeout al obtener el cliente en CRM: ' . $clientID;
|
||||||
$arrayOxxoPayment['clientID'] = $clientID;
|
$arrayOxxoPayment['clientID'] = $clientID;
|
||||||
$arrayOxxoPayment['clientFullName'] = $clientFullName;
|
$arrayOxxoPayment['clientFullName'] = $clientFullName;
|
||||||
$arrayOxxoPayment['amount'] = $integerAmount;
|
$arrayOxxoPayment['amount'] = $integerAmount;
|
||||||
$arrayOxxoPayment['voucher_image_url'] = '';
|
|
||||||
return $arrayOxxoPayment;
|
return $arrayOxxoPayment;
|
||||||
}
|
}
|
||||||
$this->logger->error("Error al obtener el cliente en CRM (Error {$e->getCode()}): " . $e->getMessage() . PHP_EOL);
|
$this->logger->error("Error al obtener el cliente en CRM (Error {$e->getCode()}): " . $e->getMessage() . PHP_EOL);
|
||||||
//devolver un array con los campos del codigo error, descripción de la falla, clientID y amount
|
//devolver un array con los campos del codigo error, descripción de la falla, clientID y amount
|
||||||
$arrayOxxoPayment['oxxo_reference'] = '';
|
$arrayOxxoPayment['oxxo_reference'] = '';
|
||||||
$arrayOxxoPayment['url'] = '';
|
|
||||||
$arrayOxxoPayment['error'] = 'errorGetClient';
|
$arrayOxxoPayment['error'] = 'errorGetClient';
|
||||||
$arrayOxxoPayment['failDescription'] = 'Error al obtener el cliente en CRM: ' . $clientID;
|
$arrayOxxoPayment['failDescription'] = 'Error al obtener el cliente en CRM: ' . $clientID;
|
||||||
$arrayOxxoPayment['clientID'] = $clientID;
|
$arrayOxxoPayment['clientID'] = $clientID;
|
||||||
$arrayOxxoPayment['clientFullName'] = $clientFullName;
|
$arrayOxxoPayment['clientFullName'] = $clientFullName;
|
||||||
$arrayOxxoPayment['amount'] = $integerAmount;
|
$arrayOxxoPayment['amount'] = $integerAmount;
|
||||||
$arrayOxxoPayment['voucher_image_url'] = '';
|
|
||||||
return $arrayOxxoPayment;
|
return $arrayOxxoPayment;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Obtener email del cliente
|
// Obtener email del cliente
|
||||||
foreach ($arrayClientCRM['contacts'] as $contact) {
|
foreach ($arrayClientCRM['contacts'] as $contact) {
|
||||||
if (!empty($contact['email'])) {
|
if (!empty($contact['email'])) {
|
||||||
@ -154,7 +144,7 @@ abstract class AbstractOxxoOperationsFacade
|
|||||||
$clientEmail = 'siip8873@gmail.com'; // Default
|
$clientEmail = 'siip8873@gmail.com'; // Default
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
// Obtener stripeCustomerId
|
// Obtener stripeCustomerId
|
||||||
foreach ($arrayClientCRM['attributes'] as $attribute) {
|
foreach ($arrayClientCRM['attributes'] as $attribute) {
|
||||||
@ -163,7 +153,7 @@ abstract class AbstractOxxoOperationsFacade
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->logger->info("Stripe Customer ID obtenido: " . $stripeCustomerId . PHP_EOL);
|
$this->logger->info("Stripe Customer ID obtenido: " . $stripeCustomerId . PHP_EOL);
|
||||||
} catch (Exception $e) {
|
} catch (Exception $e) {
|
||||||
$this->logger->error("Error al obtener el Customer ID de Stripe (Error {$e->getCode()}): " . $e->getMessage() . PHP_EOL);
|
$this->logger->error("Error al obtener el Customer ID de Stripe (Error {$e->getCode()}): " . $e->getMessage() . PHP_EOL);
|
||||||
@ -174,33 +164,28 @@ abstract class AbstractOxxoOperationsFacade
|
|||||||
$arrayOxxoPayment['clientID'] = $clientID;
|
$arrayOxxoPayment['clientID'] = $clientID;
|
||||||
$arrayOxxoPayment['clientFullName'] = $clientFullName;
|
$arrayOxxoPayment['clientFullName'] = $clientFullName;
|
||||||
$arrayOxxoPayment['amount'] = $integerAmount;
|
$arrayOxxoPayment['amount'] = $integerAmount;
|
||||||
$arrayOxxoPayment['voucher_image_url'] = '';
|
|
||||||
return $arrayOxxoPayment;
|
return $arrayOxxoPayment;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($amount === null) {
|
if ($amount === null) {
|
||||||
$amount = abs($arrayClientCRM['accountOutstanding']); //Monto adeudado del cliente
|
$amount = abs($arrayClientCRM['accountOutstanding']);
|
||||||
} else {
|
} else {
|
||||||
//la variable $amount debe ser numérica pero en ocasiones la solicitud puede traer signos o alguna letra ingresada mal por el cliente, se debe analizar para limpiar cualquier caracter que no sea numérico
|
$this->logger->info("Monto proporcionado directamente: $amount " . PHP_EOL);
|
||||||
if(!is_numeric($amount)) {
|
|
||||||
$amount = preg_replace('/[^\d.]/', '', $amount); // Eliminar todo lo que no sea dígito o punto decimal
|
|
||||||
}
|
|
||||||
$this->logger->debug("Monto proporcionado directamente: $amount " . PHP_EOL);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($amount > 10) {
|
if ($amount > 10) {
|
||||||
$amountInCents = intval($amount * 100); // Convertir a centavos
|
$amount = intval($amount * 100);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
$this->logger->debug("Creando referencia en Stripe por $amount para el cliente $stripeCustomerId" . PHP_EOL);
|
$this->logger->info("Creando referencia en Stripe por $amount para el cliente $stripeCustomerId" . PHP_EOL);
|
||||||
$guzzleClient = new Client([
|
$guzzleClient = new Client([
|
||||||
'timeout' => 5, // Timeout de 5 segundos
|
'timeout' => 5,
|
||||||
]);
|
]);
|
||||||
|
|
||||||
$response = $guzzleClient->post('https://api.stripe.com/v1/payment_intents', [
|
$response = $guzzleClient->post('https://api.stripe.com/v1/payment_intents', [
|
||||||
'auth' => [$StripeToken, ''],
|
'auth' => [$StripeToken, ''],
|
||||||
'form_params' => [
|
'form_params' => [
|
||||||
'amount' => $amountInCents,
|
'amount' => $amount,
|
||||||
'currency' => 'mxn',
|
'currency' => 'mxn',
|
||||||
'payment_method_types' => ['customer_balance', 'card', 'oxxo'],
|
'payment_method_types' => ['customer_balance', 'card', 'oxxo'],
|
||||||
'description' => 'Pago de servicio de SIIP Internet',
|
'description' => 'Pago de servicio de SIIP Internet',
|
||||||
@ -219,9 +204,9 @@ abstract class AbstractOxxoOperationsFacade
|
|||||||
],
|
],
|
||||||
]
|
]
|
||||||
]);
|
]);
|
||||||
|
|
||||||
$paymentIntent = json_decode($response->getBody()->getContents(), true);
|
$paymentIntent = json_decode($response->getBody()->getContents(), true);
|
||||||
|
|
||||||
} catch (\Stripe\Exception\ApiConnectionException $e) {
|
} catch (\Stripe\Exception\ApiConnectionException $e) {
|
||||||
$this->logger->error("Error de conexión con Stripe (Error {$e->getCode()}): " . $e->getMessage() . PHP_EOL);
|
$this->logger->error("Error de conexión con Stripe (Error {$e->getCode()}): " . $e->getMessage() . PHP_EOL);
|
||||||
//devolver un array con los campos del codigo error, descripción de la falla, clientID y amount
|
//devolver un array con los campos del codigo error, descripción de la falla, clientID y amount
|
||||||
@ -231,10 +216,9 @@ abstract class AbstractOxxoOperationsFacade
|
|||||||
$arrayOxxoPayment['failDescription'] = 'Error de conexión con Stripe: ' . $clientID;
|
$arrayOxxoPayment['failDescription'] = 'Error de conexión con Stripe: ' . $clientID;
|
||||||
$arrayOxxoPayment['clientID'] = $clientID;
|
$arrayOxxoPayment['clientID'] = $clientID;
|
||||||
$arrayOxxoPayment['clientFullName'] = $clientFullName;
|
$arrayOxxoPayment['clientFullName'] = $clientFullName;
|
||||||
$arrayOxxoPayment['amount'] = $amount;
|
$arrayOxxoPayment['amount'] = $integerAmount;
|
||||||
$arrayOxxoPayment['voucher_image_url'] = '';
|
|
||||||
return $arrayOxxoPayment;
|
return $arrayOxxoPayment;
|
||||||
|
|
||||||
} catch (\Stripe\Exception\ApiErrorException $e) {
|
} catch (\Stripe\Exception\ApiErrorException $e) {
|
||||||
$this->logger->error("Error de la API de Stripe: " . $e->getMessage() . PHP_EOL);
|
$this->logger->error("Error de la API de Stripe: " . $e->getMessage() . PHP_EOL);
|
||||||
//devolver un array con los campos del codigo error, descripción de la falla, clientID y amount
|
//devolver un array con los campos del codigo error, descripción de la falla, clientID y amount
|
||||||
@ -244,36 +228,27 @@ abstract class AbstractOxxoOperationsFacade
|
|||||||
$arrayOxxoPayment['failDescription'] = 'Error de la API de Stripe: ' . $clientID;
|
$arrayOxxoPayment['failDescription'] = 'Error de la API de Stripe: ' . $clientID;
|
||||||
$arrayOxxoPayment['clientID'] = $clientID;
|
$arrayOxxoPayment['clientID'] = $clientID;
|
||||||
$arrayOxxoPayment['clientFullName'] = $clientFullName;
|
$arrayOxxoPayment['clientFullName'] = $clientFullName;
|
||||||
$arrayOxxoPayment['amount'] = $amount;
|
$arrayOxxoPayment['amount'] = $integerAmount;
|
||||||
$arrayOxxoPayment['voucher_image_url'] = '';
|
|
||||||
return $arrayOxxoPayment;
|
return $arrayOxxoPayment;
|
||||||
|
|
||||||
} catch (Exception $e) {
|
} catch (Exception $e) {
|
||||||
$this->logger->error("Error inesperado al crear PaymentIntent (Error {$e->getCode()}): " . $e->getMessage() . PHP_EOL);
|
$this->logger->error("Error inesperado al crear PaymentIntent (Error {$e->getCode()}): " . $e->getMessage() . PHP_EOL);
|
||||||
//si e->getMessage incluye el mensaje: You must provide a customer when creating or updating a PaymentIntent with a `customer_ba (truncated...) declarar una variable y ahi poner "Este cliente no tiene cuenta de Stripe"
|
|
||||||
if ($e->getMessage() == 'You must provide a customer when creating or updating a PaymentIntent with a `customer_ba (truncated...)') {
|
|
||||||
$this->logger->error("Este cliente no tiene cuenta de Stripe" . PHP_EOL);
|
|
||||||
$arrayOxxoPayment['failDescription'] = 'Este cliente no tiene cuenta de Stripe: ' . $clientID;
|
|
||||||
} else {
|
|
||||||
$this->logger->error("Error inesperado al crear PaymentIntent: " . $e->getMessage() . PHP_EOL);
|
|
||||||
$arrayOxxoPayment['failDescription'] = 'Error inesperado al crear PaymentIntent: ' . $clientID;
|
|
||||||
}
|
|
||||||
//devolver un array con los campos del codigo error, descripción de la falla, clientID y amount
|
//devolver un array con los campos del codigo error, descripción de la falla, clientID y amount
|
||||||
$arrayOxxoPayment['oxxo_reference'] = '';
|
$arrayOxxoPayment['oxxo_reference'] = '';
|
||||||
$arrayOxxoPayment['url'] = '';
|
$arrayOxxoPayment['url'] = '';
|
||||||
$arrayOxxoPayment['error'] = 'errorCreatePaymentIntent';
|
$arrayOxxoPayment['error'] = 'errorCreatePaymentIntent';
|
||||||
|
$arrayOxxoPayment['failDescription'] = 'Error inesperado al crear PaymentIntent: ' . $clientID;
|
||||||
$arrayOxxoPayment['clientID'] = $clientID;
|
$arrayOxxoPayment['clientID'] = $clientID;
|
||||||
|
$arrayOxxoPayment['amount'] = $integerAmount;
|
||||||
$arrayOxxoPayment['clientFullName'] = $clientFullName;
|
$arrayOxxoPayment['clientFullName'] = $clientFullName;
|
||||||
$arrayOxxoPayment['amount'] = $amount;
|
|
||||||
$arrayOxxoPayment['voucher_image_url'] = '';
|
|
||||||
return $arrayOxxoPayment;
|
return $arrayOxxoPayment;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
$firstName = isset($arrayClientCRM['firstName']) ? trim($arrayClientCRM['firstName']) : '';
|
$firstName = isset($arrayClientCRM['firstName']) ? trim($arrayClientCRM['firstName']) : '';
|
||||||
$lastName = isset($arrayClientCRM['lastName']) ? trim($arrayClientCRM['lastName']) : '';
|
$lastName = isset($arrayClientCRM['lastName']) ? trim($arrayClientCRM['lastName']) : '';
|
||||||
|
|
||||||
if (strlen($firstName) < 2 || strlen($lastName) < 2) {
|
if (strlen($firstName) < 2 || strlen($lastName) < 2) {
|
||||||
$this->logger->error("Nombre/apellido inválido: ' . $firstName . ' ' . $lastName" . PHP_EOL);
|
$this->logger->error("Nombre/apellido inválido: ' . $firstName . ' ' . $lastName" . PHP_EOL);
|
||||||
//devolver un array con los campos del codigo error, descripción de la falla, clientID y amount
|
//devolver un array con los campos del codigo error, descripción de la falla, clientID y amount
|
||||||
@ -283,12 +258,11 @@ abstract class AbstractOxxoOperationsFacade
|
|||||||
$arrayOxxoPayment['failDescription'] = "Nombre/apellido inválido: ' . $firstName . ' ' . $lastName";
|
$arrayOxxoPayment['failDescription'] = "Nombre/apellido inválido: ' . $firstName . ' ' . $lastName";
|
||||||
$arrayOxxoPayment['clientID'] = $clientID;
|
$arrayOxxoPayment['clientID'] = $clientID;
|
||||||
$arrayOxxoPayment['clientFullName'] = $clientFullName;
|
$arrayOxxoPayment['clientFullName'] = $clientFullName;
|
||||||
$arrayOxxoPayment['amount'] = $amount;
|
$arrayOxxoPayment['amount'] = $integerAmount;
|
||||||
$arrayOxxoPayment['voucher_image_url'] = '';
|
|
||||||
return $arrayOxxoPayment;
|
return $arrayOxxoPayment;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
$responsePaymentMethod = $guzzleClient->post('https://api.stripe.com/v1/payment_methods', [
|
$responsePaymentMethod = $guzzleClient->post('https://api.stripe.com/v1/payment_methods', [
|
||||||
'auth' => [$StripeToken, ''],
|
'auth' => [$StripeToken, ''],
|
||||||
'form_params' => [
|
'form_params' => [
|
||||||
@ -299,18 +273,18 @@ abstract class AbstractOxxoOperationsFacade
|
|||||||
],
|
],
|
||||||
]
|
]
|
||||||
]);
|
]);
|
||||||
|
|
||||||
$paymentMethod = json_decode($responsePaymentMethod->getBody()->getContents(), true);
|
$paymentMethod = json_decode($responsePaymentMethod->getBody()->getContents(), true);
|
||||||
|
|
||||||
$responseConfirmPaymentIntent = $guzzleClient->post('https://api.stripe.com/v1/payment_intents/' . $paymentIntent['id'] . '/confirm', [
|
$responseConfirmPaymentIntent = $guzzleClient->post('https://api.stripe.com/v1/payment_intents/' . $paymentIntent['id'] . '/confirm', [
|
||||||
'auth' => [$StripeToken, ''],
|
'auth' => [$StripeToken, ''],
|
||||||
'form_params' => [
|
'form_params' => [
|
||||||
'payment_method' => $paymentMethod['id'],
|
'payment_method' => $paymentMethod['id'],
|
||||||
]
|
]
|
||||||
]);
|
]);
|
||||||
|
|
||||||
$paymentIntentConfirm = json_decode($responseConfirmPaymentIntent->getBody()->getContents(), true);
|
$paymentIntentConfirm = json_decode($responseConfirmPaymentIntent->getBody()->getContents(), true);
|
||||||
|
|
||||||
} catch (Exception $e) {
|
} catch (Exception $e) {
|
||||||
$this->logger->error("Error al confirmar PaymentIntent: " . $e->getMessage() . PHP_EOL);
|
$this->logger->error("Error al confirmar PaymentIntent: " . $e->getMessage() . PHP_EOL);
|
||||||
//devolver un array con los campos del codigo error, descripción de la falla, clientID y amount
|
//devolver un array con los campos del codigo error, descripción de la falla, clientID y amount
|
||||||
@ -320,112 +294,27 @@ abstract class AbstractOxxoOperationsFacade
|
|||||||
$arrayOxxoPayment['failDescription'] = 'Error al confirmar PaymentIntent: ' . $e->getMessage();
|
$arrayOxxoPayment['failDescription'] = 'Error al confirmar PaymentIntent: ' . $e->getMessage();
|
||||||
$arrayOxxoPayment['clientID'] = $clientID;
|
$arrayOxxoPayment['clientID'] = $clientID;
|
||||||
$arrayOxxoPayment['clientFullName'] = $clientFullName;
|
$arrayOxxoPayment['clientFullName'] = $clientFullName;
|
||||||
$arrayOxxoPayment['amount'] = $amount;
|
$arrayOxxoPayment['amount'] = $integerAmount;
|
||||||
$arrayOxxoPayment['voucher_image_url'] = '';
|
|
||||||
return $arrayOxxoPayment;
|
return $arrayOxxoPayment;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!empty($paymentIntentConfirm['next_action']) && isset($paymentIntentConfirm['next_action']['oxxo_display_details'])) {
|
if (!empty($paymentIntentConfirm['next_action']) && isset($paymentIntentConfirm['next_action']['oxxo_display_details'])) {
|
||||||
$oxxoPayment = $paymentIntentConfirm['next_action']['oxxo_display_details'];
|
$oxxoPayment = $paymentIntentConfirm['next_action']['oxxo_display_details'];
|
||||||
$oxxo_reference = $oxxoPayment['number'];
|
$oxxo_reference = $oxxoPayment['number'];
|
||||||
$oxxo_receipt_url = $oxxoPayment['hosted_voucher_url'];
|
$oxxo_receipt_url = $oxxoPayment['hosted_voucher_url'];
|
||||||
|
|
||||||
$this->logger->info("Referencia OXXO: " . $oxxo_reference . PHP_EOL);
|
$this->logger->info("Referencia OXXO: " . $oxxo_reference . PHP_EOL);
|
||||||
$this->logger->info("URL del recibo: " . $oxxo_receipt_url . PHP_EOL);
|
$this->logger->info("URL del recibo: " . $oxxo_receipt_url . PHP_EOL);
|
||||||
//$this->captureScreenshot($oxxo_receipt_url);
|
$this->captureScreenshot($oxxo_receipt_url);
|
||||||
//devolver un array con los campos de url de oxxo, descripción de la falla, clientID y amount
|
//devolver un array con los campos de url de oxxo, descripción de la falla, clientID y amount
|
||||||
$arrayOxxoPayment['oxxo_reference'] = $oxxo_reference;
|
$arrayOxxoPayment['oxxo_reference'] = $oxxo_reference;
|
||||||
$arrayOxxoPayment['url'] = $oxxo_receipt_url;
|
$arrayOxxoPayment['url'] = $oxxo_receipt_url;
|
||||||
$arrayOxxoPayment['error'] = '';
|
|
||||||
$arrayOxxoPayment['failDescription'] = '';
|
|
||||||
$arrayOxxoPayment['clientID'] = $clientID;
|
$arrayOxxoPayment['clientID'] = $clientID;
|
||||||
$arrayOxxoPayment['clientFullName'] = $clientFullName;
|
$arrayOxxoPayment['clientFullName'] = $clientFullName;
|
||||||
$arrayOxxoPayment['amount'] = $amount;
|
$arrayOxxoPayment['amount'] = $integerAmount;
|
||||||
|
$arrayOxxoPayment['failDescription'] = '';
|
||||||
|
$arrayOxxoPayment['error'] = '';
|
||||||
$this->logger->info("Referencia OXXO creada correctamente." . PHP_EOL);
|
$this->logger->info("Referencia OXXO creada correctamente." . PHP_EOL);
|
||||||
|
|
||||||
|
|
||||||
// Configuración de la API de tu servicio Docker de Puppeteer
|
|
||||||
$api_url = 'http://'.$ipPuppeteer.':'.$portPuppeteer.'/screenshot'; // Asegúrate que esta URL sea accesible
|
|
||||||
|
|
||||||
// --- Datos para la petición ---
|
|
||||||
$request_data = [
|
|
||||||
'url' => $oxxo_receipt_url, // URL del recibo de OXXO
|
|
||||||
// Opcional: Si quieres recortar la imagen, descomenta y ajusta el 'clip'
|
|
||||||
|
|
||||||
'clip' => [
|
|
||||||
'x' => 325,
|
|
||||||
'y' => 30,
|
|
||||||
'width' => 550,
|
|
||||||
'height' => 550
|
|
||||||
]
|
|
||||||
|
|
||||||
];
|
|
||||||
|
|
||||||
// Nombre del archivo donde se guardará la imagen
|
|
||||||
$clientFullNameWithoutSpaces = str_replace(' ', '_', $clientFullName); // Reemplazar espacios por guiones bajos
|
|
||||||
$voucherFileName = 'voucher_'.$clientFullNameWithoutSpaces.'_' . time() . '.jpeg'; // Usamos .jpeg por defecto
|
|
||||||
$output_filename = __DIR__ . '/../../vouchers_oxxo/' . $voucherFileName; // Usamos .jpeg por defecto
|
|
||||||
$output_filename = realpath(__DIR__ . '/../../vouchers_oxxo') . '/'. $voucherFileName; // Mejor: ruta absoluta y verifica que el directorio exista
|
|
||||||
//$output_filename = '/path/to/vouchers_oxxo/voucher_' . time() . '.jpeg'; // Mejor aún: ruta absoluta y fija, si es posible
|
|
||||||
|
|
||||||
$guzzleClient = new Client([
|
|
||||||
'timeout' => 5, // Timeout de 5 segundos
|
|
||||||
]);
|
|
||||||
// Descargar el recibo de OXXO
|
|
||||||
try {
|
|
||||||
// --- Realizar la petición POST ---
|
|
||||||
$response = $guzzleClient->post($api_url, [
|
|
||||||
'json' => $request_data, // Guzzle codifica automáticamente el array a JSON y establece Content-Type: application/json
|
|
||||||
'headers' => [
|
|
||||||
'Accept' => 'image/jpeg, image/png', // Indicar que esperamos una imagen
|
|
||||||
],
|
|
||||||
// Opcional: para depuración si necesitas ver el cuerpo de la respuesta en caso de error
|
|
||||||
// 'http_errors' => false // Desactiva las excepciones para códigos de estado 4xx/5xx y maneja la respuesta manualmente
|
|
||||||
]);
|
|
||||||
|
|
||||||
// --- Procesar la respuesta ---
|
|
||||||
$statusCode = $response->getStatusCode();
|
|
||||||
$contentType = $response->getHeaderLine('Content-Type');
|
|
||||||
|
|
||||||
$this->logger->debug("Status Code: " . $statusCode);
|
|
||||||
$this->logger->debug("Content Type: " . $contentType);
|
|
||||||
|
|
||||||
if ($statusCode === 200 && str_contains($contentType, 'image/')) {
|
|
||||||
// La respuesta es una imagen y el código de estado es 200 OK
|
|
||||||
$image_content = $response->getBody()->getContents();
|
|
||||||
|
|
||||||
// *** VERIFICACIÓN IMPORTANTE: ***
|
|
||||||
if (file_put_contents($output_filename, $image_content)) {
|
|
||||||
$this->logger->debug("¡Imagen guardada exitosamente en: " . $output_filename);
|
|
||||||
$url_file = $this->UploadVoucherToWordpressByImageFileName($voucherFileName); //Carga del comprobante PDF a Wordpress para su posterior envío
|
|
||||||
$arrayOxxoPayment['voucher_image_url'] = $url_file; // Agregar la URL del archivo de imagen al array
|
|
||||||
} else {
|
|
||||||
$this->logger->error("Error: No se pudo guardar la imagen en " . $output_filename);
|
|
||||||
$this->logger->error("Ruta del archivo: " . $output_filename); // Agregado para depuración
|
|
||||||
$this->logger->error("Directorio del script: " . __DIR__); // Agregado para depuración
|
|
||||||
$this->logger->error("Error de PHP: " . error_get_last()['message']); // Agregado para depuración
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// No es una imagen o hubo un error en el servicio
|
|
||||||
$this->logger->debug("Error: La respuesta no es una imagen o el código de estado no es 200 OK.");
|
|
||||||
$this->logger->debug("Cuerpo de la respuesta: " . $response->getBody()->getContents());
|
|
||||||
}
|
|
||||||
|
|
||||||
} catch (RequestException $e) {
|
|
||||||
// Manejo de errores de red o del servidor (ej. timeouts, 4xx, 5xx si http_errors no es false)
|
|
||||||
$this->logger->error("Error en la petición: " . $e->getMessage());
|
|
||||||
if ($e->hasResponse()) {
|
|
||||||
$this->logger->error("Cuerpo de la respuesta de error: " . $e->getResponse()->getBody()->getContents());
|
|
||||||
$this->logger->error("Código de estado HTTP de error: " . $e->getResponse()->getStatusCode());
|
|
||||||
}
|
|
||||||
} catch (Exception $e) {
|
|
||||||
// Otros errores inesperados
|
|
||||||
$this->logger->error("Error inesperado: " . $e->getMessage());
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
return $arrayOxxoPayment;
|
return $arrayOxxoPayment;
|
||||||
} else {
|
} else {
|
||||||
$this->logger->info("El PaymentIntent no tiene detalles de OXXO disponibles. Estado: " . $paymentIntentConfirm['status'] . PHP_EOL);
|
$this->logger->info("El PaymentIntent no tiene detalles de OXXO disponibles. Estado: " . $paymentIntentConfirm['status'] . PHP_EOL);
|
||||||
@ -436,12 +325,11 @@ abstract class AbstractOxxoOperationsFacade
|
|||||||
$arrayOxxoPayment['failDescription'] = 'El PaymentIntent no tiene detalles de OXXO disponibles. Estado: ' . $paymentIntentConfirm['status'];
|
$arrayOxxoPayment['failDescription'] = 'El PaymentIntent no tiene detalles de OXXO disponibles. Estado: ' . $paymentIntentConfirm['status'];
|
||||||
$arrayOxxoPayment['clientID'] = $clientID;
|
$arrayOxxoPayment['clientID'] = $clientID;
|
||||||
$arrayOxxoPayment['clientFullName'] = $clientFullName;
|
$arrayOxxoPayment['clientFullName'] = $clientFullName;
|
||||||
$arrayOxxoPayment['amount'] = $amount;
|
$arrayOxxoPayment['amount'] = $integerAmount;
|
||||||
$arrayOxxoPayment['voucher_image_url'] = '';
|
|
||||||
return $arrayOxxoPayment;
|
return $arrayOxxoPayment;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
$this->logger->info("Este cliente no tiene adeudos." . PHP_EOL);
|
$this->logger->info("Este cliente no tiene adeudos." . PHP_EOL);
|
||||||
//devolver un array con los campos del codigo error, descripción de la falla, clientID y amount
|
//devolver un array con los campos del codigo error, descripción de la falla, clientID y amount
|
||||||
@ -451,8 +339,7 @@ abstract class AbstractOxxoOperationsFacade
|
|||||||
$arrayOxxoPayment['failDescription'] = 'Este cliente no tiene adeudos.';
|
$arrayOxxoPayment['failDescription'] = 'Este cliente no tiene adeudos.';
|
||||||
$arrayOxxoPayment['clientID'] = $clientID;
|
$arrayOxxoPayment['clientID'] = $clientID;
|
||||||
$arrayOxxoPayment['clientFullName'] = $clientFullName;
|
$arrayOxxoPayment['clientFullName'] = $clientFullName;
|
||||||
$arrayOxxoPayment['amount'] = $amount;
|
$arrayOxxoPayment['amount'] = $integerAmount;
|
||||||
$arrayOxxoPayment['voucher_image_url'] = '';
|
|
||||||
return $arrayOxxoPayment;
|
return $arrayOxxoPayment;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -475,7 +362,7 @@ abstract class AbstractOxxoOperationsFacade
|
|||||||
|
|
||||||
function validarEmail($email)
|
function validarEmail($email)
|
||||||
{
|
{
|
||||||
$this->logger->debug('SE VALIDA EL EMAIL!!! ' . PHP_EOL);
|
$this->logger->info('SE VALIDA EL EMAIL!!! ' . PHP_EOL);
|
||||||
// Utilizar la función filter_var con el filtro FILTER_VALIDATE_EMAIL para validar el email
|
// Utilizar la función filter_var con el filtro FILTER_VALIDATE_EMAIL para validar el email
|
||||||
if (filter_var($email, FILTER_VALIDATE_EMAIL)) {
|
if (filter_var($email, FILTER_VALIDATE_EMAIL)) {
|
||||||
// Si el email es válido, devolver el email
|
// Si el email es válido, devolver el email
|
||||||
@ -594,145 +481,37 @@ abstract class AbstractOxxoOperationsFacade
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Función para capturar una pantalla de una URL usando el servicio Puppeteer.
|
||||||
|
*
|
||||||
|
* @param string $url La URL de la página web que se desea capturar.
|
||||||
|
* @return string La ruta del archivo de la captura de pantalla.
|
||||||
|
*/
|
||||||
|
function captureScreenshot($url) {
|
||||||
|
// URL del servicio Puppeteer
|
||||||
|
$puppeteerUrl = 'http://172.16.5.134:4000';
|
||||||
|
|
||||||
function UploadVoucherToWordpressByImageFileName($imageFileName): string
|
// Datos a enviar
|
||||||
{
|
$data = http_build_query(['url' => $url]);
|
||||||
|
|
||||||
$log = PluginLogManager::create(); //Initialize Logger
|
// Configurar la solicitud POST
|
||||||
$configManager = PluginConfigManager::create();
|
$options = [
|
||||||
$config = $configManager->loadConfig();
|
'http' => [
|
||||||
|
'header' => "Content-type: application/x-www-form-urlencoded\r\n",
|
||||||
|
'method' => 'POST',
|
||||||
|
'content' => $data,
|
||||||
|
],
|
||||||
|
];
|
||||||
|
|
||||||
// Configuración de conexión FTP
|
// Ejecutar la solicitud
|
||||||
$ftp_server = $config['hostServerFTP'];
|
$context = stream_context_create($options);
|
||||||
$ftp_username = $config['usernameServerFTP'];
|
$response = file_get_contents($puppeteerUrl, false, $context);
|
||||||
$ftp_password = $config['passServerFTP'];
|
|
||||||
$remote_folder = "/public_html/wp/wp-content/uploads/vouchers_oxxo/";
|
|
||||||
|
|
||||||
$log->appendLog("Subiendo voucher a worpdpress " . PHP_EOL);
|
if ($response === false) {
|
||||||
// Configuración de conexión FTP
|
throw new Exception("Error al comunicarse con el servicio Puppeteer.");
|
||||||
// $ftp_server = "siip.mx";
|
|
||||||
// $ftp_username = "siip0001";
|
|
||||||
// $ftp_password = '$spGiT,[wa)n';
|
|
||||||
$remote_file = "/public_html/wp/wp-content/uploads/vouchers_oxxo/" . $imageFileName;
|
|
||||||
$file_to_upload = __DIR__ . '/../../vouchers_oxxo/' . $imageFileName;
|
|
||||||
$url = 'https://siip.mx/wp/wp-content/uploads/vouchers_oxxo/' . $imageFileName;
|
|
||||||
|
|
||||||
$log->appendLog("file_to_upload: " . $file_to_upload . PHP_EOL);
|
|
||||||
|
|
||||||
// Conexión FTP
|
|
||||||
$ftp_conn = ftp_connect($ftp_server) or die("No se pudo conectar al servidor FTP");
|
|
||||||
$login = ftp_login($ftp_conn, $ftp_username, $ftp_password);
|
|
||||||
ftp_pasv($ftp_conn, true);
|
|
||||||
// Verificar conexión y login
|
|
||||||
if ($ftp_conn && $login) {
|
|
||||||
$log->appendLog("Conexión FTP exitosa" . PHP_EOL);
|
|
||||||
|
|
||||||
// Cargar archivo
|
|
||||||
if (ftp_put($ftp_conn, $remote_file, $file_to_upload, FTP_BINARY)) {
|
|
||||||
$log->appendLog("El archivo ha sido cargado exitosamente." . PHP_EOL);
|
|
||||||
$log->appendLog("La URL es: " . $url . PHP_EOL);
|
|
||||||
|
|
||||||
$this->deleteFilesWordpressExceptLastHundred($log, $ftp_conn, $remote_file);
|
|
||||||
// Cerrar conexión FTP
|
|
||||||
ftp_close($ftp_conn); //COMENTAR AQUÍ SI SE BORRAN LOS ARCHIVOS DE WORDPRESS DESCOMENTANDO EL CÓDIGO DE MÁS ABAJO
|
|
||||||
return $url; //COMENTAR AQUÍ SI SE BORRAN LOS ARCHIVOS DE WORDPRESS DESCOMENTANDO EL CÓDIGO DE MÁS ABAJO
|
|
||||||
|
|
||||||
} else {
|
|
||||||
$log->appendLog("Error al cargar el archivo " . PHP_EOL);
|
|
||||||
ftp_close($ftp_conn);
|
|
||||||
return '';
|
|
||||||
}
|
|
||||||
|
|
||||||
//SI SE DECIDE VOLVER A ELIMINAR LOS COMPROBANTES ENTONCES DESCOMENTAR ESTA PARTE DE ABAJO Y COMENTAR LA SECCIÓN DE ARRIBA
|
|
||||||
|
|
||||||
// Obtener lista de archivos en la carpeta
|
|
||||||
// $files = ftp_nlist($ftp_conn, $remote_folder);
|
|
||||||
// if (is_array($files)) {
|
|
||||||
// // Eliminar la ruta del directorio de los archivos
|
|
||||||
// $files = array_map(function ($file) use ($remote_folder) {
|
|
||||||
// return str_replace($remote_folder, '', $file);
|
|
||||||
// }, $files);
|
|
||||||
|
|
||||||
// // Obtener fechas de modificación
|
|
||||||
// $filesWithTime = [];
|
|
||||||
// foreach ($files as $file) {
|
|
||||||
// $modifiedTime = ftp_mdtm($ftp_conn, $remote_folder . $file);
|
|
||||||
// if ($modifiedTime != -1) {
|
|
||||||
// $filesWithTime[$file] = $modifiedTime;
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
// // Ordenar archivos por fecha de modificación, más recientes primero
|
|
||||||
// arsort($filesWithTime);
|
|
||||||
|
|
||||||
// // Obtener los archivos a eliminar (todos menos los 50 más recientes)
|
|
||||||
// $filesToDelete = array_slice(array_keys($filesWithTime), 50);
|
|
||||||
|
|
||||||
// // Eliminar archivos antiguos
|
|
||||||
// foreach ($filesToDelete as $file) {
|
|
||||||
// if (ftp_delete($ftp_conn, $remote_folder . $file)) {
|
|
||||||
// $log->appendLog("Comprobante eliminado de Wordpress: " . $file . PHP_EOL);
|
|
||||||
// } else {
|
|
||||||
// $log->appendLog('Error al borrar comprobante' . $file . PHP_EOL);
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// $log->appendLog("Archivos eliminados" . PHP_EOL);
|
|
||||||
// ftp_close($ftp_conn);
|
|
||||||
// return $url;
|
|
||||||
// } else {
|
|
||||||
// $log->appendLog("No se pudo obtener la lista de archivos de la carpeta FTP" . PHP_EOL);
|
|
||||||
// ftp_close($ftp_conn);
|
|
||||||
// return $url;
|
|
||||||
// }
|
|
||||||
|
|
||||||
} else {
|
|
||||||
$log->appendLog("No se pudo conectar o iniciar sesión en el servidor FTP." . PHP_EOL);
|
|
||||||
return '';
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function deleteFilesWordpressExceptLastHundred($log, $ftp_conn, $remote_folder): bool
|
return trim($response);
|
||||||
{
|
}
|
||||||
|
|
||||||
// Obtener lista de archivos en la carpeta
|
|
||||||
$files = ftp_nlist($ftp_conn, $remote_folder);
|
|
||||||
if (is_array($files)) {
|
|
||||||
// Eliminar la ruta del directorio de los archivos
|
|
||||||
$files = array_map(function ($file) use ($remote_folder) {
|
|
||||||
return str_replace($remote_folder, '', $file);
|
|
||||||
}, $files);
|
|
||||||
|
|
||||||
// Obtener fechas de modificación
|
|
||||||
$filesWithTime = [];
|
|
||||||
foreach ($files as $file) {
|
|
||||||
$modifiedTime = ftp_mdtm($ftp_conn, $remote_folder . $file);
|
|
||||||
if ($modifiedTime != -1) {
|
|
||||||
$filesWithTime[$file] = $modifiedTime;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Ordenar archivos por fecha de modificación, más recientes primero
|
|
||||||
arsort($filesWithTime);
|
|
||||||
|
|
||||||
// Obtener los archivos a eliminar (todos menos los 50 más recientes)
|
|
||||||
$filesToDelete = array_slice(array_keys($filesWithTime), 50);
|
|
||||||
|
|
||||||
// Eliminar archivos antiguos
|
|
||||||
foreach ($filesToDelete as $file) {
|
|
||||||
if (ftp_delete($ftp_conn, $remote_folder . $file)) {
|
|
||||||
$log->appendLog("Voucher eliminado de Wordpress: " . $file . PHP_EOL);
|
|
||||||
} else {
|
|
||||||
$log->appendLog('Error al borrar voucher' . $file . PHP_EOL);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
$log->appendLog("Archivos eliminados" . PHP_EOL);
|
|
||||||
ftp_close($ftp_conn);
|
|
||||||
return true;
|
|
||||||
} else {
|
|
||||||
$log->appendLog("No se pudo obtener la lista de archivos de la carpeta FTP" . PHP_EOL);
|
|
||||||
ftp_close($ftp_conn);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -4,7 +4,6 @@ declare(strict_types=1);
|
|||||||
|
|
||||||
namespace SmsNotifier\Facade;
|
namespace SmsNotifier\Facade;
|
||||||
|
|
||||||
use Attribute;
|
|
||||||
use Exception;
|
use Exception;
|
||||||
use GuzzleHttp\Exception\GuzzleException;
|
use GuzzleHttp\Exception\GuzzleException;
|
||||||
use SmsNotifier\Data\NotificationData;
|
use SmsNotifier\Data\NotificationData;
|
||||||
@ -58,12 +57,11 @@ abstract class AbstractStripeOperationsFacade
|
|||||||
*/
|
*/
|
||||||
public function createPaymentIntent($event_json)
|
public function createPaymentIntent($event_json)
|
||||||
{
|
{
|
||||||
$this->logger->info("Iniciando creación de PaymentIntent en Stripe." . PHP_EOL);
|
$this->logger->info("Evento recibido: " . json_encode($event_json) . PHP_EOL);
|
||||||
|
|
||||||
$configManager = \Ubnt\UcrmPluginSdk\Service\PluginConfigManager::create();
|
$configManager = \Ubnt\UcrmPluginSdk\Service\PluginConfigManager::create();
|
||||||
$config = $configManager->loadConfig();
|
$config = $configManager->loadConfig();
|
||||||
$StripeToken = $config['tokenstripe'];
|
$StripeToken = $config['tokenstripe'];
|
||||||
$idPaymentAdmin = $config['idPaymentAdminCRM']; //ID del administrador que crea el PaymentIntent
|
|
||||||
$stripe = new \Stripe\StripeClient($StripeToken); //Token de clave privada para la API de Stripe
|
$stripe = new \Stripe\StripeClient($StripeToken); //Token de clave privada para la API de Stripe
|
||||||
|
|
||||||
// Asegurarse de que 'customer' esté presente en la estructura del evento
|
// Asegurarse de que 'customer' esté presente en la estructura del evento
|
||||||
@ -83,23 +81,13 @@ abstract class AbstractStripeOperationsFacade
|
|||||||
$this->logger->info("Error: net_amount not found in event data." . PHP_EOL);
|
$this->logger->info("Error: net_amount not found in event data." . PHP_EOL);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
$amount = $event_json['data']['object']['net_amount'];
|
$amount = $event_json['data']['object']['net_amount'];
|
||||||
//convertir en positivo
|
|
||||||
if ($event_json['data']['object']['net_amount'] < 0) {
|
|
||||||
$this->logger->warning("Error: net_amount es negativo." . PHP_EOL);
|
|
||||||
return;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//imprimir la cantidad del PaymentIntent
|
|
||||||
$this->logger->info("Cantidad del PaymentIntent: " . $amount . PHP_EOL);
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
// Obtener información del cliente desde Stripe
|
// Obtener información del cliente desde Stripe
|
||||||
$stripeQuery = $stripe->customers->retrieve($customerId, []);
|
$stripeQuery = $stripe->customers->retrieve($customerId, []);
|
||||||
$UCRM_clientID = $stripeQuery['metadata']['ucrm_client_id']; // ID del cliente en Ubiquiti UISP
|
$UCRM_clientID = $stripeQuery['metadata']['ucrm_client_id'];
|
||||||
|
|
||||||
// Obtener información del administrador actual
|
// Obtener información del administrador actual
|
||||||
$this->ucrmApi = UcrmApi::create();
|
$this->ucrmApi = UcrmApi::create();
|
||||||
@ -123,7 +111,7 @@ abstract class AbstractStripeOperationsFacade
|
|||||||
'clientId' => $UCRM_clientID, // ID del cliente en Ubiquiti
|
'clientId' => $UCRM_clientID, // ID del cliente en Ubiquiti
|
||||||
'createdBy' => 'UCRM',
|
'createdBy' => 'UCRM',
|
||||||
'paymentType' => 'card.one_time',
|
'paymentType' => 'card.one_time',
|
||||||
'signedInAdminId' => $idPaymentAdmin, // ID del administrador que crea el PaymentIntent
|
'signedInAdminId' => $currentUserAdmin[0]['id'],
|
||||||
'tipoPago' => 'Transferencia Bancaria'
|
'tipoPago' => 'Transferencia Bancaria'
|
||||||
],
|
],
|
||||||
]);
|
]);
|
||||||
@ -135,59 +123,6 @@ abstract class AbstractStripeOperationsFacade
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public function registerPaymentFromWebhook($event_json)
|
|
||||||
{
|
|
||||||
$this->logger->info("Procesando pago funded desde webhook..." . PHP_EOL);
|
|
||||||
$configManager = \Ubnt\UcrmPluginSdk\Service\PluginConfigManager::create();
|
|
||||||
$config = $configManager->loadConfig();
|
|
||||||
$StripeToken = $config['tokenstripe'];
|
|
||||||
$stripe = new \Stripe\StripeClient($StripeToken);
|
|
||||||
|
|
||||||
$data = $event_json['data']['object'];
|
|
||||||
|
|
||||||
if (isset($data['applied_to_payment']['payment_intent'])) {
|
|
||||||
$piId = $data['applied_to_payment']['payment_intent'];
|
|
||||||
try {
|
|
||||||
$pi = $stripe->paymentIntents->retrieve($piId);
|
|
||||||
$clientId = $pi->metadata->clientId ?? null;
|
|
||||||
$amount = abs($data['net_amount']) / 100;
|
|
||||||
|
|
||||||
if ($clientId) {
|
|
||||||
$this->ucrmApi = UcrmApi::create();
|
|
||||||
|
|
||||||
// Dynamic lookup for payment method ID
|
|
||||||
$methodId = null;
|
|
||||||
$methods = $this->ucrmApi->get('payment-methods');
|
|
||||||
foreach ($methods as $method) {
|
|
||||||
if ($method['name'] === 'Transferencia bancaria') {
|
|
||||||
$methodId = $method['id'];
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!$methodId) {
|
|
||||||
$this->logger->error("Error registrando pago: No se encontró el método 'Transferencia bancaria'");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
$this->ucrmApi->post('payments', [
|
|
||||||
'clientId' => (int)$clientId,
|
|
||||||
'amount' => $amount,
|
|
||||||
'currencyCode' => strtoupper($pi->currency),
|
|
||||||
'methodId' => $methodId,
|
|
||||||
'note' => "Pago via Webhook Stripe (Saldo Aplicado) - PI: $piId",
|
|
||||||
'createdDate' => date('c'),
|
|
||||||
]);
|
|
||||||
$this->logger->info("Pago registrado en UCRM para el cliente $clientId");
|
|
||||||
} else {
|
|
||||||
$this->logger->warning("No se encontró clientId en metadata del PaymentIntent $piId");
|
|
||||||
}
|
|
||||||
} catch (\Exception $e) {
|
|
||||||
$this->logger->error("Error registrando pago: " . $e->getMessage());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Creates the Stripe Customer
|
* Creates the Stripe Customer
|
||||||
@ -201,30 +136,19 @@ abstract class AbstractStripeOperationsFacade
|
|||||||
$UCRMAPIToken = $config['apitoken'];
|
$UCRMAPIToken = $config['apitoken'];
|
||||||
$StripeToken = $config['tokenstripe'];
|
$StripeToken = $config['tokenstripe'];
|
||||||
$baseUri = 'https://' . $IPServer . '/crm/api/v1.0/'; //endpoint de la API REST del CRM
|
$baseUri = 'https://' . $IPServer . '/crm/api/v1.0/'; //endpoint de la API REST del CRM
|
||||||
$this->ucrmApi = UcrmApi::create();
|
|
||||||
|
|
||||||
$stripe = new \Stripe\StripeClient($StripeToken); //Token de clave privada en modo prueba para la API de Stripe
|
$stripe = new \Stripe\StripeClient($StripeToken); //Token de clave privada en modo prueba para la API de Stripe
|
||||||
//$stripe = new \Stripe\StripeClient('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'); //Token de clave privada en modo prodcucción para la API de Stripe
|
//$stripe = new \Stripe\StripeClient('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'); //Token de clave privada en modo prodcucción para la API de Stripe
|
||||||
|
|
||||||
//valor de $notificationData en json
|
|
||||||
$this->logger->info("Valor de notificationData: " . json_encode($notificationData) . PHP_EOL);
|
|
||||||
|
|
||||||
//ejemplo de notificationData: {"uuid":"0be6fee6-db1d-4ab5-a52c-2ee87b04315e","changeType":"edit","entity":"client","entityId":170,"message":null,"clientId":170,"eventName":"client.edit","clientData":{"id":170,"userIdent":null,"previousIsp":null,"isLead":false,"clientType":1,"companyName":null,"companyRegistrationNumber":null,"companyTaxId":null,"companyWebsite":null,"street1":"San Luis 34","street2":null,"city":"Dolores Hidalgo","countryId":173,"stateId":null,"zipCode":"37800","fullAddress":"San Luis 34, Dolores Hidalgo, 37800","invoiceStreet1":null,"invoiceStreet2":null,"invoiceCity":null,"invoiceStateId":null,"invoiceCountryId":null,"invoiceZipCode":null,"invoiceAddressSameAsContact":true,"note":null,"sendInvoiceByPost":null,"invoiceMaturityDays":null,"stopServiceDue":null,"stopServiceDueDays":null,"organizationId":1,"tax1Id":null,"tax2Id":null,"tax3Id":null,"registrationDate":"2025-03-24T00:00:00-0600","leadConvertedAt":"2025-03-24T15:01:22-0600","companyContactFirstName":null,"companyContactLastName":null,"isActive":false,"firstName":"Charicuas","lastName":"Quinero","username":null,"contacts":[{"id":176,"clientId":170,"email":null,"phone":null,"name":null,"isBilling":true,"isContact":true,"types":[{"id":1,"name":"Billing"},{"id":2,"name":"General"}]}],"attributes":[{"id":192,"clientId":170,"customAttributeId":10,"name":"Stripe Customer ID","key":"stripeCustomerId","value":"cus_S0T9BJ4dO0p0A3","clientZoneVisible":true},{"id":193,"clientId":170,"customAttributeId":11,"name":"Clabe Interbancaria","key":"clabeInterbancaria","value":"124180302040274015","clientZoneVisible":true}],"accountBalance":0,"accountCredit":0,"accountOutstanding":0,"currencyCode":"MXN","organizationName":"SIIP Pruebas","bankAccounts":[],"tags":[{"id":5,"name":"CREARCLABESTRIPE","colorBackground":"#e30000","colorText":"#fff"}],"invitationEmailSentDate":null,"avatarColor":"#ef5350","addressGpsLat":22.00854045,"addressGpsLon":-99.0272544,"isArchived":false,"generateProformaInvoices":null,"usesProforma":false,"hasOverdueInvoice":false,"hasOutage":false,"hasSuspendedService":false,"hasServiceWithoutDevices":true,"referral":null,"hasPaymentSubscription":false,"hasAutopayCreditCard":false},"serviceData":null,"invoiceData":null,"paymentData":null}
|
//$this->logger->info("Ya dentro del metodo Create Stripe Client " . PHP_EOL);
|
||||||
|
//$this->sendWhatsApp('Hola Dany');
|
||||||
|
|
||||||
//obtener el id del cliente
|
$this->ucrmApi = UcrmApi::create();
|
||||||
$clientId = $notificationData->clientData['id'];
|
if ($tagStripe) {
|
||||||
|
$tagsIds = $this->ucrmApi->get('client-tags', ['name' => 'STRIPE']);
|
||||||
//si en attributes del cliente encuentra el custom field de Stripe Customer ID entonces no se vuelve a crear el cliente en Stripe
|
$this->createCustomerStripe($notificationData, $stripe, $baseUri, $UCRMAPIToken);
|
||||||
$attributes = $notificationData->clientData['attributes'];
|
|
||||||
$this->logger->info("Valor de attributes: " . json_encode($attributes) . PHP_EOL);
|
|
||||||
$stripeCustomerId = null;
|
|
||||||
foreach ($attributes as $attribute) {
|
|
||||||
if ($attribute['key'] === 'stripeCustomerId') {
|
|
||||||
$stripeCustomerId = $attribute['value'];
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
$customAttributes = $this->ucrmApi->get('custom-attributes/', ['attributeType' => 'client']);//Obtener los atributos del sistema que estén vinculados a la entidad "cliente"
|
$customAttributes = $this->ucrmApi->get('custom-attributes/', ['attributeType' => 'client']);//Obtener los atributos del sistema que estén vinculados a la entidad "cliente"
|
||||||
//$this->logger->info("result del custom Attributes: " . json_encode($customAttributes) . PHP_EOL);
|
//$this->logger->info("result del custom Attributes: " . json_encode($customAttributes) . PHP_EOL);
|
||||||
|
|
||||||
@ -247,61 +171,6 @@ abstract class AbstractStripeOperationsFacade
|
|||||||
$this->logger->info("Error al obtener los atributos personalizados." . PHP_EOL);
|
$this->logger->info("Error al obtener los atributos personalizados." . PHP_EOL);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($stripeCustomerId) {
|
|
||||||
$this->logger->info("El cliente ya tiene un Stripe Customer ID: " . $stripeCustomerId . PHP_EOL);
|
|
||||||
if ($tagStripe) {
|
|
||||||
$tagsIds = $this->ucrmApi->get('client-tags', []);
|
|
||||||
//ejemplo de respuesta $tagsIds: [{"id":4,"name":"EQUIPO A CREDITO","colorBackground":"#fed74a","colorText":"#444"},{"id":5,"name":"CREARCLABESTRIPE","colorBackground":"#e30000","colorText":"#fff"}]
|
|
||||||
|
|
||||||
//obtener el ID de la etiqueta o tag llamada "CREAR CLABE STRIPE" y asiganarla a una variable $tagCrearClabeStripe basandose en el ejemplo de respuesta anterior
|
|
||||||
$tagCrearClabeStripe = null;
|
|
||||||
foreach ($tagsIds as $tag) {
|
|
||||||
if ($tag['name'] === 'CREAR CLABE STRIPE') {
|
|
||||||
$tagCrearClabeStripe = $tag['id'];
|
|
||||||
// $this->logger->info("ID de la etiqueta 'CREAR CLABE STRIPE': " . $tagCrearClabeStripe . PHP_EOL);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!$tagCrearClabeStripe) {
|
|
||||||
$this->logger->info("No se encontró la etiqueta 'CREAR CLABE STRIPE'." . PHP_EOL);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
$this->ucrmApi->patch("clients/$clientId/remove-tag/" . $tagCrearClabeStripe);
|
|
||||||
$this->logger->info("Se eliminó la etiqueta 'CREAR CLABE STRIPE' del cliente." . PHP_EOL);
|
|
||||||
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
//$this->logger->info("Ya dentro del metodo Create Stripe Client " . PHP_EOL);
|
|
||||||
//$this->sendWhatsApp('Hola Dany');
|
|
||||||
|
|
||||||
|
|
||||||
if ($tagStripe) {
|
|
||||||
$tagsIds = $this->ucrmApi->get('client-tags', []);
|
|
||||||
//ejemplo de respuesta $tagsIds: [{"id":4,"name":"EQUIPO A CREDITO","colorBackground":"#fed74a","colorText":"#444"},{"id":5,"name":"CREARCLABESTRIPE","colorBackground":"#e30000","colorText":"#fff"}]
|
|
||||||
|
|
||||||
//obtener el ID de la etiqueta o tag llamada "CREARCLABESTRIPE" y asiganarla a una variable $tagCrearClabeStripe basandose en el ejemplo de respuesta anterior
|
|
||||||
$tagCrearClabeStripe = null;
|
|
||||||
foreach ($tagsIds as $tag) { //revisamos los tags del cliente y si encuentra el tag de "CREARCLABESTRIPE" entonces lo asigna a la variable $tagCrearClabeStripe el valor de id
|
|
||||||
if ($tag['name'] === 'CREAR CLABE STRIPE') {
|
|
||||||
$tagCrearClabeStripe = $tag['id'];
|
|
||||||
// $this->logger->info("ID de la etiqueta 'CREAR CLABE STRIPE': " . $tagCrearClabeStripe . PHP_EOL);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!$tagCrearClabeStripe) {
|
|
||||||
$this->logger->info("No se encontró la etiqueta 'CREAR CLABE STRIPE'." . PHP_EOL);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
$this->createCustomerStripe($notificationData, $stripe, $baseUri, $UCRMAPIToken);
|
|
||||||
$this->ucrmApi->patch("clients/$clientId/remove-tag/" . $tagCrearClabeStripe);
|
|
||||||
$this->logger->info("Se eliminó la etiqueta 'CREAR CLABE STRIPE' del cliente." . PHP_EOL);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@ -320,8 +189,26 @@ abstract class AbstractStripeOperationsFacade
|
|||||||
}
|
}
|
||||||
|
|
||||||
$this->createCustomerStripe($notificationData, $stripe, $baseUri, $UCRMAPIToken);
|
$this->createCustomerStripe($notificationData, $stripe, $baseUri, $UCRMAPIToken);
|
||||||
|
// Acceder a "isLead" de forma segura
|
||||||
|
// $isLead = $dataObject->isLead ?? null;
|
||||||
|
|
||||||
|
// $this->logger->info("El valor de 'isLead' es: " . ($isLead ? "true" : "false") . PHP_EOL);
|
||||||
|
|
||||||
|
// if ($isLead === true) {
|
||||||
|
// $this->logger->info("El cliente es un lead, no se procesará" . PHP_EOL);
|
||||||
|
// return;
|
||||||
|
// } else {
|
||||||
|
// $this->logger->info("El cliente NO es un lead, se procesará" . PHP_EOL);
|
||||||
|
// $this->createCustomerStripe($notificationData, $stripe, $baseUri, $UCRMAPIToken);
|
||||||
|
// }
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// /**
|
// /**
|
||||||
// * implement in subclass with the specific messaging provider
|
// * implement in subclass with the specific messaging provider
|
||||||
// * @see TwilioNotifierFacade::sendWhatsApp()
|
// * @see TwilioNotifierFacade::sendWhatsApp()
|
||||||
@ -333,7 +220,6 @@ abstract class AbstractStripeOperationsFacade
|
|||||||
|
|
||||||
function createCustomerStripe($notificationData, $stripe, $baseUri, $token): bool
|
function createCustomerStripe($notificationData, $stripe, $baseUri, $token): bool
|
||||||
{
|
{
|
||||||
$this->ucrmApi = UcrmApi::create();
|
|
||||||
$this->logger->info("Creando el Customer Stripe" . PHP_EOL);
|
$this->logger->info("Creando el Customer Stripe" . PHP_EOL);
|
||||||
|
|
||||||
|
|
||||||
@ -402,7 +288,7 @@ abstract class AbstractStripeOperationsFacade
|
|||||||
//validar si se creo el cliente con la API de Stripe $stripe->customers->create
|
//validar si se creo el cliente con la API de Stripe $stripe->customers->create
|
||||||
if (!isset($result['id'])) { //si no existe el ID del cliente en la respuesta de Stripe entonces se manda un mensaje de error
|
if (!isset($result['id'])) { //si no existe el ID del cliente en la respuesta de Stripe entonces se manda un mensaje de error
|
||||||
$this->logger->info('Error al crear el cliente en Stripe: ' . json_encode($result) . PHP_EOL);
|
$this->logger->info('Error al crear el cliente en Stripe: ' . json_encode($result) . PHP_EOL);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -457,33 +343,22 @@ abstract class AbstractStripeOperationsFacade
|
|||||||
]
|
]
|
||||||
|
|
||||||
}'; //JSON para hacer patch de los custom fields del cliente en el UISCP CRM, Campo para el Stripe Customer ID y la Clabe interbancaria
|
}'; //JSON para hacer patch de los custom fields del cliente en el UISCP CRM, Campo para el Stripe Customer ID y la Clabe interbancaria
|
||||||
|
// $json_data_patch = '{
|
||||||
|
// "attributes": [
|
||||||
|
// {
|
||||||
|
// "value": "' . $stripe_customer_id . '",
|
||||||
|
// "customAttributeId": 29
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// "value": "' . $clabe . '",
|
||||||
|
// "customAttributeId": 30
|
||||||
|
// }
|
||||||
|
// ]
|
||||||
|
|
||||||
//valor de $json_data_patch en json
|
// }'; //JSON para hacer patch de los custom fields del cliente en el UISCP CRM, Campo para el Stripe Customer ID y la Clabe interbancaria
|
||||||
//$this->logger->info("Valor de json_data_patch: " . $json_data_patch . PHP_EOL);
|
|
||||||
// try{
|
|
||||||
// $responsepatchCRM= $this->ucrmApi->patch("clients/$ucrm_client_id", [
|
|
||||||
// "attributes" => [
|
|
||||||
// [
|
|
||||||
// "value" => $stripe_customer_id,
|
|
||||||
// "customAttributeId" => $stripeID
|
|
||||||
// ],
|
|
||||||
// [
|
|
||||||
// "value" => $clabeInterbancaria,
|
|
||||||
// "customAttributeId" => $clabeInterbancariaID
|
|
||||||
// ]
|
|
||||||
// ]
|
|
||||||
// ]); //aquí se contruye la petición para hacer patch hacia el cliente en sus custom fields con la API del UISP UCRM
|
|
||||||
// $this->logger->info("Se actualizó el cliente en UCRM con el Stripe Customer ID y la Clabe Interbancaria." . PHP_EOL);
|
|
||||||
// $this->logger->info(json_encode($responsepatchCRM) . PHP_EOL); //imprimir respuesta del patch de CRM con la clabe y Customer ID Stripe
|
|
||||||
// }catch (GuzzleException $e) {
|
|
||||||
// $this->logger->info("Error al hacer el patch al cliente en UCRM: " . $e->getMessage() . PHP_EOL);
|
|
||||||
// return false; // Return false if patch fails
|
|
||||||
// }
|
|
||||||
|
|
||||||
|
|
||||||
$clientguzz = new Client(); //instancia de cliente GuzzleHttp para consumir API UISP CRM
|
$clientguzz = new Client(); //instancia de cliente GuzzleHttp para consumir API UISP CRM
|
||||||
try {
|
try {
|
||||||
//aquí se contruye la petición para hacer patch hacia el cliente en sus custom fields con la API del UISP UCRM
|
|
||||||
$responseCRM = $clientguzz->patch($baseUri . 'clients/' . $ucrm_client_id, [
|
$responseCRM = $clientguzz->patch($baseUri . 'clients/' . $ucrm_client_id, [
|
||||||
'json' => json_decode($json_data_patch, true),
|
'json' => json_decode($json_data_patch, true),
|
||||||
'headers' => [
|
'headers' => [
|
||||||
@ -491,7 +366,7 @@ abstract class AbstractStripeOperationsFacade
|
|||||||
'Accept' => 'application/json', // Indica que esperamos una respuesta en formato JSON
|
'Accept' => 'application/json', // Indica que esperamos una respuesta en formato JSON
|
||||||
],
|
],
|
||||||
'verify' => false,
|
'verify' => false,
|
||||||
]);
|
]); //aquí se contruye la petición para hacer patch hacia el cliente en sus custom fields con la API del UISP UCRM
|
||||||
|
|
||||||
|
|
||||||
} catch (GuzzleException $error) {
|
} catch (GuzzleException $error) {
|
||||||
@ -537,6 +412,4 @@ abstract class AbstractStripeOperationsFacade
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,13 +1,17 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
namespace SmsNotifier\Facade;
|
namespace SmsNotifier\Facade;
|
||||||
|
|
||||||
|
use CURLFile;
|
||||||
use DateTime;
|
use DateTime;
|
||||||
use GuzzleHttp\Client;
|
use GuzzleHttp\Client;
|
||||||
|
use GuzzleHttp\Exception\GuzzleException;
|
||||||
use Imagick;
|
use Imagick;
|
||||||
use ImagickException;
|
|
||||||
use Ubnt\UcrmPluginSdk\Service\PluginConfigManager;
|
|
||||||
use Ubnt\UcrmPluginSdk\Service\PluginLogManager;
|
use Ubnt\UcrmPluginSdk\Service\PluginLogManager;
|
||||||
|
use ImagickException;
|
||||||
use Ubnt\UcrmPluginSdk\Service\UcrmApi;
|
use Ubnt\UcrmPluginSdk\Service\UcrmApi;
|
||||||
|
use Ubnt\UcrmPluginSdk\Service\PluginConfigManager;
|
||||||
|
use Ubnt\UcrmPluginSdk\Service\UcrmOptionsManager;
|
||||||
|
|
||||||
//use SmsNotifier\Service\Logger;
|
//use SmsNotifier\Service\Logger;
|
||||||
|
|
||||||
@ -15,15 +19,15 @@ class ClientCallBellAPI
|
|||||||
{
|
{
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @var
|
* @var
|
||||||
*/
|
*/
|
||||||
private $CallBellAPIToken;
|
private $CallBellAPIToken;
|
||||||
/**
|
/**
|
||||||
* @var
|
* @var
|
||||||
*/
|
*/
|
||||||
private $IPServer;
|
private $IPServer;
|
||||||
/**
|
/**
|
||||||
* @var
|
* @var
|
||||||
*/
|
*/
|
||||||
private $UCRMAPIToken;
|
private $UCRMAPIToken;
|
||||||
/**
|
/**
|
||||||
@ -52,6 +56,7 @@ class ClientCallBellAPI
|
|||||||
|
|
||||||
public $ucrmVersion;
|
public $ucrmVersion;
|
||||||
|
|
||||||
|
|
||||||
public function __construct(
|
public function __construct(
|
||||||
$UCRMAPIToken,
|
$UCRMAPIToken,
|
||||||
$IPServer,
|
$IPServer,
|
||||||
@ -100,6 +105,9 @@ class ClientCallBellAPI
|
|||||||
$campo2 = sprintf("📡 Su servicio está: %s 📍Su dirección es: *%s* ", $estado_service, $domicilio);
|
$campo2 = sprintf("📡 Su servicio está: %s 📍Su dirección es: *%s* ", $estado_service, $domicilio);
|
||||||
$log->appendLog("Valor del campo2 " . $campo2);
|
$log->appendLog("Valor del campo2 " . $campo2);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
$curl_string = "{\n \"to\": \"$clientWhatsAppNumber\",\n \"from\": \"whatsapp\",\n \"type\": \"text\",\n \"content\": {\n \"text\": \"S/M\"\n },\n \"template_values\": [\"$campo1\", \"$campo2\"],\n \"template_uuid\": \"55705f1fe4e24bab80104dc2643fe11c\",\n \"optin_contact\": true\n }";
|
$curl_string = "{\n \"to\": \"$clientWhatsAppNumber\",\n \"from\": \"whatsapp\",\n \"type\": \"text\",\n \"content\": {\n \"text\": \"S/M\"\n },\n \"template_values\": [\"$campo1\", \"$campo2\"],\n \"template_uuid\": \"55705f1fe4e24bab80104dc2643fe11c\",\n \"optin_contact\": true\n }";
|
||||||
$log->appendLog("La cadena CURL que se envia es: " . $curl_string);
|
$log->appendLog("La cadena CURL que se envia es: " . $curl_string);
|
||||||
curl_setopt($ch, CURLOPT_POSTFIELDS, $curl_string);
|
curl_setopt($ch, CURLOPT_POSTFIELDS, $curl_string);
|
||||||
@ -110,21 +118,15 @@ class ClientCallBellAPI
|
|||||||
curl_close($ch);
|
curl_close($ch);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function sendJobNotificationWhatsAppToClient($clientWhatsAppNumber, $jobNotificationData, $reprogramming, $changeInstaller): bool
|
public function sendJobNotificationWhatsAppToClient($clientWhatsAppNumber, $jobNotificationData, $reprogramming = false, $changeInstaller = false): bool
|
||||||
{
|
{
|
||||||
|
|
||||||
$log = PluginLogManager::create(); //Initialize Logger
|
$log = PluginLogManager::create(); //Initialize Logger
|
||||||
$log->appendLog("Enviando mensaje de trabajo para el cliente" . PHP_EOL);
|
$log->appendLog("Enviando mensaje de trabajo para el cliente" . PHP_EOL);
|
||||||
$jsonJobNotificationData = json_encode($jobNotificationData, true);
|
$jsonJobNotificationData = json_encode($jobNotificationData, true);
|
||||||
$log->appendLog("Datos de la notificación de trabajo: " . $jsonJobNotificationData . PHP_EOL);
|
$log->appendLog("Datos de la notificación de trabajo: " . $jsonJobNotificationData . PHP_EOL);
|
||||||
|
$log->appendLog("Debugging: reprogramming = " . var_export($reprogramming, true) . ", changeInstaller = " . var_export($changeInstaller, true) . PHP_EOL);
|
||||||
|
|
||||||
// --- ¡AÑADE ESTAS LÍNEAS PARA CONVERTIR A BOOLEANO REAL! ---
|
|
||||||
$reprogramming = filter_var($reprogramming, FILTER_VALIDATE_BOOLEAN, FILTER_NULL_ON_FAILURE);
|
|
||||||
$changeInstaller = filter_var($changeInstaller, FILTER_VALIDATE_BOOLEAN, FILTER_NULL_ON_FAILURE);
|
|
||||||
// -----------------------------------------------------------
|
|
||||||
|
|
||||||
// Puedes volver a loggear los valores para confirmar la conversión (opcional)
|
|
||||||
$log->appendLog("DEBUG: Valores después de conversión - Reprogramming: " . var_export($reprogramming, true) . ", ChangeInstaller: " . var_export($changeInstaller, true) . PHP_EOL);
|
|
||||||
|
|
||||||
$ch = curl_init();
|
$ch = curl_init();
|
||||||
curl_setopt($ch, CURLOPT_URL, 'https://api.callbell.eu/v1/messages/send');
|
curl_setopt($ch, CURLOPT_URL, 'https://api.callbell.eu/v1/messages/send');
|
||||||
@ -135,53 +137,24 @@ class ClientCallBellAPI
|
|||||||
'Content-Type: application/json',
|
'Content-Type: application/json',
|
||||||
]);
|
]);
|
||||||
|
|
||||||
$campo1 = '👤 ' . sprintf(' *%s*', $jobNotificationData['clientFullName']);
|
$campo1 = sprintf('*%s*', $jobNotificationData['clientFullName']);
|
||||||
if ($changeInstaller && !$reprogramming) {
|
$campo2 = sprintf('*#%s*', $jobNotificationData['jobId']);
|
||||||
$campo2 = sprintf('se ha hecho un cambio de técnico 👷🏻♂️🔄 para su visita con el folio *#️⃣%s*', $jobNotificationData['jobId']);
|
$campo3 = sprintf('*%s*', $jobNotificationData['date']);
|
||||||
} else {
|
$campo4 = sprintf('*%s*', $jobNotificationData['installerName']);
|
||||||
$campo2 = sprintf('*#️⃣%s*', $jobNotificationData['jobId']);
|
|
||||||
}
|
|
||||||
$campo3 = '🗓️ ' . sprintf('%s', $jobNotificationData['date']);
|
|
||||||
if ($changeInstaller && $reprogramming) {
|
|
||||||
$campo4 = 'Además se ha hecho un cambio de técnico por el siguiente 👷🏻♂️➡️ ' . sprintf('*%s*', $jobNotificationData['installerName']);
|
|
||||||
} else {
|
|
||||||
$campo4 = '👷🏻♂️➡️ ' . sprintf('*%s*', $jobNotificationData['installerName']);
|
|
||||||
}
|
|
||||||
|
|
||||||
$campo5 = "asegúrese de que alguien esté presente en el domicilio 🏠 para permitir el acceso y confirme su disponibilidad.";
|
if ($reprogramming && $changeInstaller === false) {
|
||||||
|
|
||||||
$log->appendLog("DEBUG: Valores antes de la estructura IF - Reprogramming: " . var_export($reprogramming, true) . ", ChangeInstaller: " . var_export($changeInstaller, true) . PHP_EOL);
|
|
||||||
|
|
||||||
if ($reprogramming && !$changeInstaller) {
|
|
||||||
//{{1}}, se ha reprogramado su visita técnica con el folio {{2}}
|
|
||||||
|
|
||||||
$campo3 = '🗓️➡️ ' . sprintf('%s', $jobNotificationData['date']);
|
|
||||||
$campo1_combinado = "Estimado cliente $campo1 se ha reprogramado su visita técnica con folio $campo2";
|
|
||||||
|
|
||||||
// Case: true, false
|
|
||||||
//Enviar notificación de reprogramación al cliente
|
//Enviar notificación de reprogramación al cliente
|
||||||
$log->appendLog("Enviando notificación de reprogramación al cliente, valor de reprogramming $reprogramming y valor de changeInstaller $changeInstaller " . PHP_EOL);
|
$log->appendLog("Enviando notificación de reprogramación al cliente, valor de reprogramming $reprogramming y valor de changeInstaller $changeInstaller " . PHP_EOL);
|
||||||
$curl_string = "{\n \"to\": \"$clientWhatsAppNumber\",\n \"from\": \"whatsapp\",\n \"type\": \"text\",\n \"content\": {\n \"text\": \"S/M\"\n },\n \"template_values\": [\"$campo1_combinado\", \"$campo3\", \"$campo4\", \"$campo5\"],\n \"template_uuid\": \"715eed9d6f2d4d90853f25e296202e00\",\n \"optin_contact\": true\n }";
|
$curl_string = "{\n \"to\": \"$clientWhatsAppNumber\",\n \"from\": \"whatsapp\",\n \"type\": \"text\",\n \"content\": {\n \"text\": \"S/M\"\n },\n \"template_values\": [\"$campo1\", \"$campo2\", \"$campo3\", \"$campo4\"],\n \"template_uuid\": \"70579353773f4de1836d4f9b6bf6074d\",\n \"optin_contact\": true\n }";
|
||||||
} else if (!$reprogramming && $changeInstaller) {
|
}
|
||||||
// Case: false, true
|
if ($changeInstaller) {
|
||||||
//Enviar notificación de cambio de instalador
|
//Enviar notificación de cambio de instalador
|
||||||
$log->appendLog("Enviando notificación de cambio de instalador al cliente, valor de reprogramming $reprogramming y valor de changeInstaller $changeInstaller " . PHP_EOL);
|
$log->appendLog("Enviando notificación de cambio de instalador al cliente, valor de reprogramming $reprogramming y valor de changeInstaller $changeInstaller " . PHP_EOL);
|
||||||
$curl_string = "{\n \"to\": \"$clientWhatsAppNumber\",\n \"from\": \"whatsapp\",\n \"type\": \"text\",\n \"content\": {\n \"text\": \"S/M\"\n },\n \"template_values\": [\"$campo1\", \"$campo2\", \"$campo3\", \"$campo4\", \"$campo5\"],\n \"template_uuid\": \"d684e6fa2ba24593a86c98be1815831d\",\n \"optin_contact\": true\n }";
|
$curl_string = "{\n \"to\": \"$clientWhatsAppNumber\",\n \"from\": \"whatsapp\",\n \"type\": \"text\",\n \"content\": {\n \"text\": \"S/M\"\n },\n \"template_values\": [\"$campo1\", \"$campo2\", \"$campo3\", \"$campo4\"],\n \"template_uuid\": \"0d57fd210595422caf2f5999642882a3\",\n \"optin_contact\": true\n }";
|
||||||
} else if (!$reprogramming && !$changeInstaller) { // <--- Ahora este else if está correctamente encadenado
|
} else {
|
||||||
// Case: false, false
|
|
||||||
//Enviar notificación normal de visita técnica al cliente
|
//Enviar notificación normal de visita técnica al cliente
|
||||||
$log->appendLog("Enviando notificación normal de visita técnica al cliente, valor de reprogramming $reprogramming y valor de changeInstaller $changeInstaller " . PHP_EOL);
|
$log->appendLog("Enviando notificación normal de visita técnica al cliente, valor de reprogramming $reprogramming y valor de changeInstaller $changeInstaller " . PHP_EOL);
|
||||||
$curl_string = "{\n \"to\": \"$clientWhatsAppNumber\",\n \"from\": \"whatsapp\",\n \"type\": \"text\",\n \"content\": {\n \"text\": \"S/M\"\n },\n \"template_values\": [\"$campo1\", \"$campo2\", \"$campo3\", \"$campo4\", \"$campo5\"],\n \"template_uuid\": \"07cfbc6e394044608485b530a27177d0\",\n \"optin_contact\": true\n }";
|
$curl_string = "{\n \"to\": \"$clientWhatsAppNumber\",\n \"from\": \"whatsapp\",\n \"type\": \"text\",\n \"content\": {\n \"text\": \"S/M\"\n },\n \"template_values\": [\"$campo1\", \"$campo2\", \"$campo3\", \"$campo4\"],\n \"template_uuid\": \"c0ef8228b50a4d9690a2e87bc11e9ab3\",\n \"optin_contact\": true\n }";
|
||||||
} else if ($reprogramming && $changeInstaller) { // <--- Ahora este else if está correctamente encadenado
|
|
||||||
// Case: true, true
|
|
||||||
//Enviar notificación de cambio de instalador y reprogramación al cliente
|
|
||||||
$log->appendLog("Enviando notificación de cambio de instalador y reprogramación al cliente, valor de reprogramming $reprogramming y valor de changeInstaller $changeInstaller " . PHP_EOL);
|
|
||||||
$curl_string = "{\n \"to\": \"$clientWhatsAppNumber\",\n \"from\": \"whatsapp\",\n \"type\": \"text\",\n \"content\": {\n \"text\": \"S/M\"\n },\n \"template_values\": [\"$campo1\", \"$campo2\", \"$campo3\", \"$campo4\", \"$campo5\"],\n \"template_uuid\": \"145885d15323414f978f1e3f249c2ae1\",\n \"optin_contact\": true\n }";
|
|
||||||
} else {
|
|
||||||
// Case: true, true (la única combinación restante con booleanos)
|
|
||||||
$log->appendLog("No se encontró una opción válida para enviar la notificación (reprogramming y changeInstaller son true)." . PHP_EOL);
|
|
||||||
// Decide qué hacer aquí, ¿Quizás devolver false? ¿O manejar esta combinación?
|
|
||||||
return false; // O el manejo adecuado para true/true
|
|
||||||
}
|
}
|
||||||
|
|
||||||
$log->appendLog("La cadena CURL que se envia es: " . $curl_string);
|
$log->appendLog("La cadena CURL que se envia es: " . $curl_string);
|
||||||
@ -217,8 +190,7 @@ class ClientCallBellAPI
|
|||||||
$log->appendLog("Ruta no prevista en la función." . PHP_EOL);
|
$log->appendLog("Ruta no prevista en la función." . PHP_EOL);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
public function sendJobNotificationWhatsAppToInstaller($installerWhatsAppNumber, $jobInstallerNotificationData, $reprogramming = false, $changeInstaller = false): bool
|
||||||
public function sendJobNotificationWhatsAppToInstaller($installerWhatsAppNumber, $jobInstallerNotificationData, $reprogramming, $changeInstaller): bool
|
|
||||||
{
|
{
|
||||||
|
|
||||||
$log = PluginLogManager::create(); //Initialize Logger
|
$log = PluginLogManager::create(); //Initialize Logger
|
||||||
@ -226,14 +198,6 @@ class ClientCallBellAPI
|
|||||||
$jsonJobNotificationData = json_encode($jobInstallerNotificationData, true);
|
$jsonJobNotificationData = json_encode($jobInstallerNotificationData, true);
|
||||||
$log->appendLog("Datos de la notificación de tarea: " . $jsonJobNotificationData . PHP_EOL);
|
$log->appendLog("Datos de la notificación de tarea: " . $jsonJobNotificationData . PHP_EOL);
|
||||||
|
|
||||||
// --- ¡AÑADE ESTAS LÍNEAS PARA CONVERTIR A BOOLEANO REAL! ---
|
|
||||||
$reprogramming = filter_var($reprogramming, FILTER_VALIDATE_BOOLEAN, FILTER_NULL_ON_FAILURE);
|
|
||||||
$changeInstaller = filter_var($changeInstaller, FILTER_VALIDATE_BOOLEAN, FILTER_NULL_ON_FAILURE);
|
|
||||||
// -----------------------------------------------------------
|
|
||||||
|
|
||||||
// Puedes volver a loggear los valores para confirmar la conversión (opcional)
|
|
||||||
$log->appendLog("DEBUG: Valores después de conversión - Reprogramming: " . var_export($reprogramming, true) . ", ChangeInstaller: " . var_export($changeInstaller, true) . PHP_EOL);
|
|
||||||
|
|
||||||
$ch = curl_init();
|
$ch = curl_init();
|
||||||
curl_setopt($ch, CURLOPT_URL, 'https://api.callbell.eu/v1/messages/send');
|
curl_setopt($ch, CURLOPT_URL, 'https://api.callbell.eu/v1/messages/send');
|
||||||
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
|
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
|
||||||
@ -243,62 +207,40 @@ class ClientCallBellAPI
|
|||||||
'Content-Type: application/json',
|
'Content-Type: application/json',
|
||||||
]);
|
]);
|
||||||
|
|
||||||
|
|
||||||
if (!$reprogramming && $changeInstaller) {
|
$campo1 = $jobInstallerNotificationData['installerName'];
|
||||||
$campo1 = $jobInstallerNotificationData['installerName'];
|
if ($changeInstaller) {
|
||||||
$campo2 = $jobInstallerNotificationData['subjectOfChange'];
|
$campo2 = $jobInstallerNotificationData['subjectOfChange'];
|
||||||
$campo3 = sprintf("#️⃣%s", $jobInstallerNotificationData['jobId']);
|
$campo3 = sprintf("#%s", $jobInstallerNotificationData['jobId']);
|
||||||
$campo4 = sprintf('*👤%s* ', $jobInstallerNotificationData['clientFullName']);
|
$campo4 = $jobInstallerNotificationData['clientFullName'];
|
||||||
$campo5 = $jobInstallerNotificationData['additionalChangeData'];
|
$campo5 = $jobInstallerNotificationData['additionalChangeData'];
|
||||||
} else {
|
} else {
|
||||||
$campo1 = '👷🏻♂️ ' . $jobInstallerNotificationData['installerName'];
|
$campo2 = sprintf("*#%s*", $jobInstallerNotificationData['jobId']);
|
||||||
$campo2 = sprintf("#️⃣%s", $jobInstallerNotificationData['jobId']);
|
$campo3 = $jobInstallerNotificationData['clientFullName'];
|
||||||
$campo3 = '👤 *' . $jobInstallerNotificationData['clientFullName'] . '*';
|
$campo4 = $jobInstallerNotificationData['clientAddress'];
|
||||||
// $campo4 = $jobInstallerNotificationData['clientAddress'];
|
$campo5 = $jobInstallerNotificationData['clientWhatsApp'];
|
||||||
$campo4 = '☎️ ' . $jobInstallerNotificationData['clientWhatsApp'];
|
$campo6 = $jobInstallerNotificationData['date'];
|
||||||
$campo5 = '🗓️ ' . $jobInstallerNotificationData['date'];
|
$campo7 = $jobInstallerNotificationData['jobDescription'];
|
||||||
// $campo6 = '🛠️ ' . $jobInstallerNotificationData['jobDescription'];
|
$campo8 = $jobInstallerNotificationData['gmapsLocation'];
|
||||||
// $campo7 = '📌 ' . $jobInstallerNotificationData['gmapsLocation'];
|
|
||||||
// $campo8 = '🔐 ' . $passwordAntenaCliente;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($reprogramming && !$changeInstaller) {
|
|
||||||
$jobId = sprintf("#️⃣ *%s*", $jobInstallerNotificationData['jobId']);
|
|
||||||
$clientFullName = sprintf("👤 *%s*", $jobInstallerNotificationData['clientFullName']);
|
|
||||||
$date = sprintf("🗓️➡️ %s", $jobInstallerNotificationData['date']);
|
|
||||||
$installerName = sprintf("👷🏻♂️ *%s*", $jobInstallerNotificationData['installerName']);
|
|
||||||
|
|
||||||
$campo1_combinado = "$installerName se reprogramó una tarea con el folio $jobId para el cliente $clientFullName, la nueva fecha será el $date";
|
if ($reprogramming && $changeInstaller === false) {
|
||||||
$campo2 = $jobInstallerNotificationData['clientWhatsApp'];
|
|
||||||
$campo3 = $jobInstallerNotificationData['gmapsLocation'];
|
|
||||||
$campo4 = $jobInstallerNotificationData['passwordAntenaCliente'];
|
|
||||||
|
|
||||||
//Enviar notificación de reprogramación
|
//Enviar notificación de reprogramación
|
||||||
$log->appendLog("Enviando notificación de reprogramación al instalador, valor de reprogramming $reprogramming y valor de changeInstaller $changeInstaller " . PHP_EOL);
|
$log->appendLog("Enviando notificación de reprogramación al instalador, valor de reprogramming $reprogramming y valor de changeInstaller $changeInstaller " . PHP_EOL);
|
||||||
$curl_string = "{\n \"to\": \"$installerWhatsAppNumber\",\n \"from\": \"whatsapp\",\n \"type\": \"text\",\n \"content\": {\n \"text\": \"S/M\"\n },\n \"template_values\": [\"$campo1_combinado\", \"$campo2\", \"$campo3\", \"$campo4\"],\n \"template_uuid\": \"88eeb6420a214fd8870dd28d741021c4\",\n \"optin_contact\": true\n }";
|
$curl_string = "{\n \"to\": \"$installerWhatsAppNumber\",\n \"from\": \"whatsapp\",\n \"type\": \"text\",\n \"content\": {\n \"text\": \"S/M\"\n },\n \"template_values\": [\"$campo1\", \"$campo2\", \"$campo3\", \"$campo4\", \"$campo5\", \"$campo6\", \"$campo7\", \"$campo8\"],\n \"template_uuid\": \"42152c07c67b468ba68e581c0283e22e\",\n \"optin_contact\": true\n }";
|
||||||
} else if (!$reprogramming && $changeInstaller) {
|
|
||||||
|
} else if ($changeInstaller) {
|
||||||
//Enviar notificación de cambio de instalador
|
//Enviar notificación de cambio de instalador
|
||||||
$log->appendLog("Enviando notificación de cambio de instalador al instalador anterior (desasignación), valor de reprogramming $reprogramming y valor de changeInstaller $changeInstaller " . PHP_EOL);
|
$log->appendLog("Enviando notificación de cambio de instalador al instalador, valor de reprogramming $reprogramming y valor de changeInstaller $changeInstaller " . PHP_EOL);
|
||||||
$curl_string = "{\n \"to\": \"$installerWhatsAppNumber\",\n \"from\": \"whatsapp\",\n \"type\": \"text\",\n \"content\": {\n \"text\": \"S/M\"\n },\n \"template_values\": [\"$campo1\", \"$campo2\", \"$campo3\", \"$campo4\", \"$campo5\"],\n \"template_uuid\": \"e1aa2b0fd3884595918f4ac2676acd29\",\n \"optin_contact\": true\n }";
|
$curl_string = "{\n \"to\": \"$installerWhatsAppNumber\",\n \"from\": \"whatsapp\",\n \"type\": \"text\",\n \"content\": {\n \"text\": \"S/M\"\n },\n \"template_values\": [\"$campo1\", \"$campo2\", \"$campo3\", \"$campo4\", \"$campo5\"],\n \"template_uuid\": \"e1aa2b0fd3884595918f4ac2676acd29\",\n \"optin_contact\": true\n }";
|
||||||
} else if ($reprogramming && $changeInstaller) {
|
|
||||||
//Enviar notificación de cambio de instalador
|
|
||||||
$log->appendLog("Enviando notificación de cambio de instalador al instalador y notificación de reprogramación al instalador, valor de reprogramming $reprogramming y valor de changeInstaller $changeInstaller " . PHP_EOL);
|
|
||||||
$curl_string = "{\n \"to\": \"$installerWhatsAppNumber\",\n \"from\": \"whatsapp\",\n \"type\": \"text\",\n \"content\": {\n \"text\": \"S/M\"\n },\n \"template_values\": [\"$campo1\", \"$campo2\", \"$campo3\", \"$campo4\", \"$campo5\"],\n \"template_uuid\": \"e1aa2b0fd3884595918f4ac2676acd29\",\n \"optin_contact\": true\n }";
|
|
||||||
} else if (!$reprogramming && !$changeInstaller) {
|
|
||||||
|
|
||||||
//combinar el campo3, campo4, campo5, campo6, campo7 y campo8 en un solo campo con saltos de línea
|
} else {
|
||||||
$jobId = sprintf("#️⃣ *%s*", $jobInstallerNotificationData['jobId']);
|
//Enviar notificación normal de asignación de tarea
|
||||||
$clientFullName = sprintf("👤 *%s*", $jobInstallerNotificationData['clientFullName']);
|
$log->appendLog("Enviando notificación normal de asignación de tarea al instalador, valor de reprogramming $reprogramming y valor de changeInstaller $changeInstaller " . PHP_EOL);
|
||||||
$date = sprintf("🗓️ %s", $jobInstallerNotificationData['date']);
|
$curl_string = "{\n \"to\": \"$installerWhatsAppNumber\",\n \"from\": \"whatsapp\",\n \"type\": \"text\",\n \"content\": {\n \"text\": \"S/M\"\n },\n \"template_values\": [\"$campo1\", \"$campo2\", \"$campo3\", \"$campo4\", \"$campo5\", \"$campo6\", \"$campo7\", \"$campo8\"],\n \"template_uuid\": \"b6663394265e4bcdb215369aa9ba0f21\",\n \"optin_contact\": true\n }";
|
||||||
$installerName = sprintf("👷🏻♂️ *%s*", $jobInstallerNotificationData['installerName']);
|
|
||||||
|
|
||||||
$campo1_combinado = "$installerName se te ha asignado una tarea con folio $jobId, del cliente $clientFullName, para el $date";
|
|
||||||
$campo2 = $jobInstallerNotificationData['clientWhatsApp'];
|
|
||||||
$campo3 = $jobInstallerNotificationData['gmapsLocation'];
|
|
||||||
$campo4 = $jobInstallerNotificationData['passwordAntenaCliente'];
|
|
||||||
|
|
||||||
$log->appendLog("Enviando notificación normal de tarea al instalador, valor de reprogramming $reprogramming y valor de changeInstaller $changeInstaller " . PHP_EOL);
|
|
||||||
$curl_string = "{\n \"to\": \"$installerWhatsAppNumber\",\n \"from\": \"whatsapp\",\n \"type\": \"text\",\n \"content\": {\n \"text\": \"S/M\"\n },\n \"template_values\": [\"$campo1_combinado\", \"$campo2\", \"$campo3\", \"$campo4\"],\n \"template_uuid\": \"88eeb6420a214fd8870dd28d741021c4\",\n \"optin_contact\": true\n }";
|
|
||||||
}
|
}
|
||||||
|
|
||||||
$log->appendLog("La cadena CURL que se envia es: " . $curl_string);
|
$log->appendLog("La cadena CURL que se envia es: " . $curl_string);
|
||||||
@ -309,9 +251,6 @@ class ClientCallBellAPI
|
|||||||
|
|
||||||
curl_close($ch);
|
curl_close($ch);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// Validar la respuesta de Callbell
|
// Validar la respuesta de Callbell
|
||||||
$jsonResponse = json_decode($response, true);
|
$jsonResponse = json_decode($response, true);
|
||||||
|
|
||||||
@ -336,6 +275,7 @@ class ClientCallBellAPI
|
|||||||
// Valor de retorno predeterminado en caso de que ninguna condición se cumpla
|
// Valor de retorno predeterminado en caso de que ninguna condición se cumpla
|
||||||
$log->appendLog("Ruta no prevista en la función." . PHP_EOL);
|
$log->appendLog("Ruta no prevista en la función." . PHP_EOL);
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function sendPaymentNotificationWhatsApp($clientWhatsAppNumber, $notificationData): bool
|
public function sendPaymentNotificationWhatsApp($clientWhatsAppNumber, $notificationData): bool
|
||||||
@ -352,17 +292,20 @@ class ClientCallBellAPI
|
|||||||
//Path base del comprobante de pago
|
//Path base del comprobante de pago
|
||||||
$pdf_payment_path = '';
|
$pdf_payment_path = '';
|
||||||
|
|
||||||
|
|
||||||
$this->ucrmApi = UcrmApi::create();
|
$this->ucrmApi = UcrmApi::create();
|
||||||
$payments = $this->ucrmApi->get(
|
$payments = $this->ucrmApi->get(
|
||||||
'payments/',
|
'payments/',
|
||||||
[
|
[
|
||||||
'clientId' => $notificationData->clientData['id'],
|
'clientId' => $notificationData->clientData['id'],
|
||||||
'limit' => 1,
|
'limit' => 1,
|
||||||
'direction' => 'DESC',
|
'direction' => 'DESC'
|
||||||
|
|
||||||
]
|
]
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
$payment_id = $payments[0]['id'];
|
$payment_id = $payments[0]['id'];
|
||||||
$payment_amount = '$' . $payments[0]['amount'];
|
$payment_amount = '$' . $payments[0]['amount'];
|
||||||
//$saldo = '$' . $notificationData->clientData['accountBalance'];
|
//$saldo = '$' . $notificationData->clientData['accountBalance'];
|
||||||
@ -386,12 +329,14 @@ class ClientCallBellAPI
|
|||||||
$clientGuzzleHttp = new Client([
|
$clientGuzzleHttp = new Client([
|
||||||
'base_uri' => $baseUri,
|
'base_uri' => $baseUri,
|
||||||
'headers' => [
|
'headers' => [
|
||||||
'X-Auth-App-Key' => $token, // Cambia el nombre de la cabecera de autorización
|
'X-Auth-App-Key' => $token, // Cambia el nombre de la cabecera de autorización
|
||||||
'Accept' => 'application/pdf', // Indica que esperamos una respuesta en formato JSON
|
'Accept' => 'application/pdf', // Indica que esperamos una respuesta en formato JSON
|
||||||
],
|
],
|
||||||
'verify' => false,
|
'verify' => false,
|
||||||
]);
|
]);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
// Hacer la solicitud GET para obtener el PDF
|
// Hacer la solicitud GET para obtener el PDF
|
||||||
$response = $clientGuzzleHttp->request('GET', "payments/$payment_id/pdf");
|
$response = $clientGuzzleHttp->request('GET', "payments/$payment_id/pdf");
|
||||||
@ -423,11 +368,20 @@ class ClientCallBellAPI
|
|||||||
|
|
||||||
$log->appendLog("El archivo PDF es válido y tiene contenido: $rutaArchivo" . PHP_EOL);
|
$log->appendLog("El archivo PDF es válido y tiene contenido: $rutaArchivo" . PHP_EOL);
|
||||||
$rutaImagen = __DIR__ . '/../../comprobantes/' . str_replace('.pdf', '.png', $fileNameComprobante);
|
$rutaImagen = __DIR__ . '/../../comprobantes/' . str_replace('.pdf', '.png', $fileNameComprobante);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
} catch (\Exception $e) {
|
} catch (\Exception $e) {
|
||||||
$log->appendLog("Error al manejar el comprobante de pago: " . $e->getMessage() . PHP_EOL);
|
$log->appendLog("Error al manejar el comprobante de pago: " . $e->getMessage() . PHP_EOL);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
$image = new Imagick();
|
$image = new Imagick();
|
||||||
$image->setResolution(300, 300);
|
$image->setResolution(300, 300);
|
||||||
@ -443,12 +397,16 @@ class ClientCallBellAPI
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
$fileNameComprobanteImage = str_replace('.pdf', '.png', $fileNameComprobante);
|
$fileNameComprobanteImage = str_replace('.pdf', '.png', $fileNameComprobante);
|
||||||
$url_file = $this->UploadReceiptToWordpressByImageFileName($fileNameComprobanteImage); //Carga del comprobante PDF a Wordpress para su posterior envío
|
$url_file = $this->UploadReceiptToWordpressByImageFileName($fileNameComprobanteImage);//Carga del comprobante PDF a Wordpress para su posterior envío
|
||||||
// $url_file = $this->UploadReceiptToWordpressByImageFileName($fileNameComprobante);//Carga del comprobante PDF a Wordpress para su posterior envío
|
// $url_file = $this->UploadReceiptToWordpressByImageFileName($fileNameComprobante);//Carga del comprobante PDF a Wordpress para su posterior envío
|
||||||
|
|
||||||
$log->appendLog("Se terminó de subir comprobante a wordpress " . PHP_EOL);
|
$log->appendLog("Se terminó de subir comprobante a wordpress " . PHP_EOL);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
//$log->appendLog("Entrando al metodo sendPaymentNotificationWhatsAp" . PHP_EOL);
|
//$log->appendLog("Entrando al metodo sendPaymentNotificationWhatsAp" . PHP_EOL);
|
||||||
$ch = curl_init();
|
$ch = curl_init();
|
||||||
curl_setopt($ch, CURLOPT_URL, 'https://api.callbell.eu/v1/messages/send');
|
curl_setopt($ch, CURLOPT_URL, 'https://api.callbell.eu/v1/messages/send');
|
||||||
@ -459,6 +417,8 @@ class ClientCallBellAPI
|
|||||||
'Content-Type: application/json',
|
'Content-Type: application/json',
|
||||||
]);
|
]);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
$curl_string = "{\n \"to\": \"$clientWhatsAppNumber\",\n \"from\": \"whatsapp\",\n \"type\": \"document\",\n \"content\": {\n \"text\": \"S/M\",\n \"url\": \"$url_file\"\n },\n \"template_values\": [\"$nombre_cliente\", \"$payment_amount\", \"$saldoTexto\"],\n \"template_uuid\": \"57ead79cebd14902921477922403093b\",\n \"optin_contact\": true\n }";
|
$curl_string = "{\n \"to\": \"$clientWhatsAppNumber\",\n \"from\": \"whatsapp\",\n \"type\": \"document\",\n \"content\": {\n \"text\": \"S/M\",\n \"url\": \"$url_file\"\n },\n \"template_values\": [\"$nombre_cliente\", \"$payment_amount\", \"$saldoTexto\"],\n \"template_uuid\": \"57ead79cebd14902921477922403093b\",\n \"optin_contact\": true\n }";
|
||||||
$log->appendLog("La cadena CURL que se envia es: " . $curl_string);
|
$log->appendLog("La cadena CURL que se envia es: " . $curl_string);
|
||||||
curl_setopt($ch, CURLOPT_POSTFIELDS, $curl_string);
|
curl_setopt($ch, CURLOPT_POSTFIELDS, $curl_string);
|
||||||
@ -505,10 +465,11 @@ class ClientCallBellAPI
|
|||||||
public function sendTextPaymentNotificationWhatsApp($clientWhatsAppNumber, $notificationData): bool
|
public function sendTextPaymentNotificationWhatsApp($clientWhatsAppNumber, $notificationData): bool
|
||||||
{
|
{
|
||||||
|
|
||||||
|
|
||||||
$nombre_cliente = sprintf("%s %s", $notificationData->clientData['firstName'], $notificationData->clientData['lastName']);
|
$nombre_cliente = sprintf("%s %s", $notificationData->clientData['firstName'], $notificationData->clientData['lastName']);
|
||||||
$folio = $notificationData->paymentData['id'];
|
$folio = $notificationData->paymentData['id'];
|
||||||
$client_id = $notificationData->clientData['id'];
|
$client_id = $notificationData->clientData['id'];
|
||||||
$fecha_pago = '';
|
$fecha_pago = null;
|
||||||
$cantidad_pagada = $notificationData->paymentData['amount'];
|
$cantidad_pagada = $notificationData->paymentData['amount'];
|
||||||
$metodo_pago = '';
|
$metodo_pago = '';
|
||||||
//$invoice_id= null;
|
//$invoice_id= null;
|
||||||
@ -519,6 +480,9 @@ class ClientCallBellAPI
|
|||||||
$texto_credito = null;
|
$texto_credito = null;
|
||||||
$creditoClienteBase = $notificationData->clientData['accountCredit'];
|
$creditoClienteBase = $notificationData->clientData['accountCredit'];
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
switch ($notificationData->paymentData['methodId']) {
|
switch ($notificationData->paymentData['methodId']) {
|
||||||
case '11721cdf-a498-48be-903e-daa67552e4f6':
|
case '11721cdf-a498-48be-903e-daa67552e4f6':
|
||||||
$metodo_pago = 'Cheque 📄';
|
$metodo_pago = 'Cheque 📄';
|
||||||
@ -553,8 +517,11 @@ class ClientCallBellAPI
|
|||||||
default:
|
default:
|
||||||
$metodo_pago = 'Desconocido, revisar metodos de pago no contemplados';
|
$metodo_pago = 'Desconocido, revisar metodos de pago no contemplados';
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
$log = PluginLogManager::create(); //Initialize Logger
|
$log = PluginLogManager::create(); //Initialize Logger
|
||||||
|
|
||||||
$log->appendLog("Eviando comprobante de pago al cliente: " . $notificationData->clientData['id'] . ' con número: ' . $clientWhatsAppNumber . PHP_EOL);
|
$log->appendLog("Eviando comprobante de pago al cliente: " . $notificationData->clientData['id'] . ' con número: ' . $clientWhatsAppNumber . PHP_EOL);
|
||||||
@ -566,13 +533,14 @@ class ClientCallBellAPI
|
|||||||
//Path base del comprobante de pago
|
//Path base del comprobante de pago
|
||||||
$pdf_payment_path = '';
|
$pdf_payment_path = '';
|
||||||
|
|
||||||
|
|
||||||
$this->ucrmApi = UcrmApi::create();
|
$this->ucrmApi = UcrmApi::create();
|
||||||
$payments = $this->ucrmApi->get(
|
$payments = $this->ucrmApi->get(
|
||||||
'payments/',
|
'payments/',
|
||||||
[
|
[
|
||||||
'clientId' => $notificationData->clientData['id'],
|
'clientId' => $notificationData->clientData['id'],
|
||||||
'limit' => 1,
|
'limit' => 1,
|
||||||
'direction' => 'DESC',
|
'direction' => 'DESC'
|
||||||
|
|
||||||
]
|
]
|
||||||
);
|
);
|
||||||
@ -581,6 +549,7 @@ class ClientCallBellAPI
|
|||||||
$datos_paymentJsonText = json_encode($payments, true);
|
$datos_paymentJsonText = json_encode($payments, true);
|
||||||
$log->appendLog("Datos traidos con payment api: " . $datos_paymentJsonText . PHP_EOL);
|
$log->appendLog("Datos traidos con payment api: " . $datos_paymentJsonText . PHP_EOL);
|
||||||
|
|
||||||
|
|
||||||
// $log->appendLog("Check 1" . PHP_EOL);
|
// $log->appendLog("Check 1" . PHP_EOL);
|
||||||
$paymentDate = new DateTime($fecha_pago);
|
$paymentDate = new DateTime($fecha_pago);
|
||||||
|
|
||||||
@ -590,6 +559,7 @@ class ClientCallBellAPI
|
|||||||
// Formatear la fecha como "d/m/Y g:ia" (día/mes/año hora:minutos am/pm)
|
// Formatear la fecha como "d/m/Y g:ia" (día/mes/año hora:minutos am/pm)
|
||||||
$fecha_pago = $paymentDate->format('d/m/Y g:ia');
|
$fecha_pago = $paymentDate->format('d/m/Y g:ia');
|
||||||
|
|
||||||
|
|
||||||
$accountBalance = $notificationData->clientData['accountBalance'];
|
$accountBalance = $notificationData->clientData['accountBalance'];
|
||||||
$saldoTexto = '';
|
$saldoTexto = '';
|
||||||
|
|
||||||
@ -611,15 +581,21 @@ class ClientCallBellAPI
|
|||||||
|
|
||||||
if ($creditoClienteBase > 0 && empty($notificationData->paymentData['paymentCovers'])) {
|
if ($creditoClienteBase > 0 && empty($notificationData->paymentData['paymentCovers'])) {
|
||||||
|
|
||||||
|
|
||||||
$texto_credito = "La cantidad que sobra de $creditoPorPagoFormateado se ha convertido a crédito";
|
$texto_credito = "La cantidad que sobra de $creditoPorPagoFormateado se ha convertido a crédito";
|
||||||
$log->appendLog("La cantidad que sobra de $creditoPorPagoFormateado se ha convertido a crédito" . PHP_EOL);
|
$log->appendLog("La cantidad que sobra de $creditoPorPagoFormateado se ha convertido a crédito" . PHP_EOL);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
$curl_string = "{\n \"to\": \"$clientWhatsAppNumber\",\n \"from\": \"whatsapp\",\n \"type\": \"text\",\n \"content\": {\n \"text\": \"John Doe\"\n },\n \"template_values\": [\"$nombre_cliente\", \"$folio\", \"$client_id\", \"$fecha_pago\", \"$cantidad_pagadaFormateada\", \"$metodo_pago\", \"$saldoTexto\", \"$texto_credito\"],\n \"template_uuid\": \"4ac9dc060cf746b6ad7f2e8acad355e0\",\n \"optin_contact\": true\n }";
|
$curl_string = "{\n \"to\": \"$clientWhatsAppNumber\",\n \"from\": \"whatsapp\",\n \"type\": \"text\",\n \"content\": {\n \"text\": \"John Doe\"\n },\n \"template_values\": [\"$nombre_cliente\", \"$folio\", \"$client_id\", \"$fecha_pago\", \"$cantidad_pagadaFormateada\", \"$metodo_pago\", \"$saldoTexto\", \"$texto_credito\"],\n \"template_uuid\": \"4ac9dc060cf746b6ad7f2e8acad355e0\",\n \"optin_contact\": true\n }";
|
||||||
|
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
if ($creditoPorPago > 0) {
|
if ($creditoPorPago > 0) {
|
||||||
$texto_credito = "La cantidad que sobra de $creditoPorPagoFormateado se ha convertido a crédito";
|
$texto_credito = "La cantidad que sobra de $creditoPorPagoFormateado se ha convertido a crédito";
|
||||||
$log->appendLog("La cantidad que sobra de $creditoPorPagoFormateado se ha convertido a crédito" . PHP_EOL);
|
$log->appendLog("La cantidad que sobra de $creditoPorPagoFormateado se ha convertido a crédito" . PHP_EOL);
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
$texto_credito = '_________________________';
|
$texto_credito = '_________________________';
|
||||||
}
|
}
|
||||||
@ -628,7 +604,7 @@ class ClientCallBellAPI
|
|||||||
$clientGuzzleHttp = new Client([
|
$clientGuzzleHttp = new Client([
|
||||||
'base_uri' => $baseUri,
|
'base_uri' => $baseUri,
|
||||||
'headers' => [
|
'headers' => [
|
||||||
'X-Auth-App-Key' => $token, // Cambia el nombre de la cabecera de autorización
|
'X-Auth-App-Key' => $token, // Cambia el nombre de la cabecera de autorización
|
||||||
'Accept' => 'application/pdf', // Indica que esperamos una respuesta en formato JSON
|
'Accept' => 'application/pdf', // Indica que esperamos una respuesta en formato JSON
|
||||||
],
|
],
|
||||||
'verify' => false,
|
'verify' => false,
|
||||||
@ -636,13 +612,15 @@ class ClientCallBellAPI
|
|||||||
|
|
||||||
$log->appendLog("Verificar paymentCovers " . PHP_EOL);
|
$log->appendLog("Verificar paymentCovers " . PHP_EOL);
|
||||||
|
|
||||||
|
|
||||||
$log->appendLog("payment covers" . json_encode($notificationData->paymentData['paymentCovers']) . PHP_EOL);
|
$log->appendLog("payment covers" . json_encode($notificationData->paymentData['paymentCovers']) . PHP_EOL);
|
||||||
|
|
||||||
|
|
||||||
if (!empty($notificationData->paymentData['paymentCovers'])) {
|
if (!empty($notificationData->paymentData['paymentCovers'])) {
|
||||||
$log->appendLog('Datos del payment covers:' . PHP_EOL);
|
$log->appendLog('Datos del payment covers:' . PHP_EOL);
|
||||||
|
|
||||||
$invoiceIds = ''; // Variable para almacenar los invoiceId
|
$invoiceIds = ''; // Variable para almacenar los invoiceId
|
||||||
$amounts = ''; // Variable para almacenar los amounts formateados
|
$amounts = ''; // Variable para almacenar los amounts formateados
|
||||||
|
|
||||||
foreach ($notificationData->paymentData['paymentCovers'] as $paymentCover) {
|
foreach ($notificationData->paymentData['paymentCovers'] as $paymentCover) {
|
||||||
$log->appendLog('Invoice ID pagado: ' . $paymentCover['invoiceId'] . ' de esta cantidad: ' . $paymentCover['amount'] . PHP_EOL);
|
$log->appendLog('Invoice ID pagado: ' . $paymentCover['invoiceId'] . ' de esta cantidad: ' . $paymentCover['amount'] . PHP_EOL);
|
||||||
@ -659,7 +637,7 @@ class ClientCallBellAPI
|
|||||||
|
|
||||||
// Eliminar la última coma y el espacio extra usando substr
|
// Eliminar la última coma y el espacio extra usando substr
|
||||||
$invoiceIds = substr($invoiceIds, 0, -2); // Elimina los últimos dos caracteres (coma y espacio)
|
$invoiceIds = substr($invoiceIds, 0, -2); // Elimina los últimos dos caracteres (coma y espacio)
|
||||||
$amounts = substr($amounts, 0, -2); // Elimina los últimos dos caracteres (coma y espacio)
|
$amounts = substr($amounts, 0, -2); // Elimina los últimos dos caracteres (coma y espacio)
|
||||||
|
|
||||||
// Mostrar las cadenas finales
|
// Mostrar las cadenas finales
|
||||||
$log->appendLog('Todos los Invoice IDs: ' . $invoiceIds . PHP_EOL);
|
$log->appendLog('Todos los Invoice IDs: ' . $invoiceIds . PHP_EOL);
|
||||||
@ -676,10 +654,14 @@ class ClientCallBellAPI
|
|||||||
$log->appendLog('Numero de factura: ' . $responseInvoicesJSON['number'] . PHP_EOL);
|
$log->appendLog('Numero de factura: ' . $responseInvoicesJSON['number'] . PHP_EOL);
|
||||||
$log->appendLog('TOTAL de factura: ' . $responseInvoicesJSON['total'] . PHP_EOL);
|
$log->appendLog('TOTAL de factura: ' . $responseInvoicesJSON['total'] . PHP_EOL);
|
||||||
$total_factura = $responseInvoicesJSON['total'];
|
$total_factura = $responseInvoicesJSON['total'];
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
} catch (\Exception $e) {
|
} catch (\Exception $e) {
|
||||||
$log->appendLog("Error con un problema al obtener alguna factura del cliente: " . $e->getMessage() . PHP_EOL);
|
$log->appendLog("Error con un problema al obtener alguna factura del cliente: " . $e->getMessage() . PHP_EOL);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
$log->appendLog("no hay datos en payment covers" . PHP_EOL);
|
$log->appendLog("no hay datos en payment covers" . PHP_EOL);
|
||||||
$invoiceIds = $notificationData->paymentData['id'];
|
$invoiceIds = $notificationData->paymentData['id'];
|
||||||
@ -692,8 +674,13 @@ class ClientCallBellAPI
|
|||||||
$pagoFacturaFormateado = '$' . $amounts . ' MXN';
|
$pagoFacturaFormateado = '$' . $amounts . ' MXN';
|
||||||
|
|
||||||
$curl_string = "{\n \"to\": \"$clientWhatsAppNumber\",\n \"from\": \"whatsapp\",\n \"type\": \"text\",\n \"content\": {\n \"text\": \"John Doe\"\n },\n \"template_values\": [\"$nombre_cliente\", \"$folio\", \"$client_id\", \"$fecha_pago\", \"$cantidad_pagadaFormateada\", \"$metodo_pago\", \"$invoiceIds\", \"$total_facturaFormateada\", \"$pagoFacturaFormateado\", \"$saldoTexto\", \"$texto_credito\"],\n \"template_uuid\": \"c1396a6ad3cb4192916d4ac2bfb782a5\",\n \"optin_contact\": true\n }";
|
$curl_string = "{\n \"to\": \"$clientWhatsAppNumber\",\n \"from\": \"whatsapp\",\n \"type\": \"text\",\n \"content\": {\n \"text\": \"John Doe\"\n },\n \"template_values\": [\"$nombre_cliente\", \"$folio\", \"$client_id\", \"$fecha_pago\", \"$cantidad_pagadaFormateada\", \"$metodo_pago\", \"$invoiceIds\", \"$total_facturaFormateada\", \"$pagoFacturaFormateado\", \"$saldoTexto\", \"$texto_credito\"],\n \"template_uuid\": \"c1396a6ad3cb4192916d4ac2bfb782a5\",\n \"optin_contact\": true\n }";
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
//$log->appendLog("Entrando al metodo sendPaymentNotificationWhatsAp" . PHP_EOL);
|
//$log->appendLog("Entrando al metodo sendPaymentNotificationWhatsAp" . PHP_EOL);
|
||||||
$ch = curl_init();
|
$ch = curl_init();
|
||||||
curl_setopt($ch, CURLOPT_URL, 'https://api.callbell.eu/v1/messages/send');
|
curl_setopt($ch, CURLOPT_URL, 'https://api.callbell.eu/v1/messages/send');
|
||||||
@ -704,6 +691,9 @@ class ClientCallBellAPI
|
|||||||
'Content-Type: application/json',
|
'Content-Type: application/json',
|
||||||
]);
|
]);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
//$curl_string = "{\n \"to\": \"$clientWhatsAppNumber\",\n \"from\": \"whatsapp\",\n \"type\": \"document\",\n \"content\": {\n \"text\": \"S/M\",\n \"url\": \"$url_file\"\n },\n \"template_values\": [\"$nombre_cliente\", \"$payment_amount\", \"$saldo\"],\n \"template_uuid\": \"6c0df98317b44f7b8666375a6cc8454c\",\n \"optin_contact\": true\n }";
|
//$curl_string = "{\n \"to\": \"$clientWhatsAppNumber\",\n \"from\": \"whatsapp\",\n \"type\": \"document\",\n \"content\": {\n \"text\": \"S/M\",\n \"url\": \"$url_file\"\n },\n \"template_values\": [\"$nombre_cliente\", \"$payment_amount\", \"$saldo\"],\n \"template_uuid\": \"6c0df98317b44f7b8666375a6cc8454c\",\n \"optin_contact\": true\n }";
|
||||||
|
|
||||||
// $curl_string = "{\n \"to\": \"$clientWhatsAppNumber\",\n \"from\": \"whatsapp\",\n \"type\": \"text\",\n \"content\": {\n \"text\": \"S/M\"\n },\n \"template_values\": [\"$campo1\", \"$campo2\"],\n \"template_uuid\": \"55705f1fe4e24bab80104dc2643fe11c\",\n \"optin_contact\": true\n }";
|
// $curl_string = "{\n \"to\": \"$clientWhatsAppNumber\",\n \"from\": \"whatsapp\",\n \"type\": \"text\",\n \"content\": {\n \"text\": \"S/M\"\n },\n \"template_values\": [\"$campo1\", \"$campo2\"],\n \"template_uuid\": \"55705f1fe4e24bab80104dc2643fe11c\",\n \"optin_contact\": true\n }";
|
||||||
@ -752,6 +742,7 @@ class ClientCallBellAPI
|
|||||||
public function sendOverdueNotificationWhatsApp($clientWhatsAppNumber, $notificationData): void
|
public function sendOverdueNotificationWhatsApp($clientWhatsAppNumber, $notificationData): void
|
||||||
{
|
{
|
||||||
|
|
||||||
|
|
||||||
$log = PluginLogManager::create(); //Initialize Logger
|
$log = PluginLogManager::create(); //Initialize Logger
|
||||||
|
|
||||||
// URL base de la API
|
// URL base de la API
|
||||||
@ -761,6 +752,7 @@ class ClientCallBellAPI
|
|||||||
//Path base del comprobante de pago
|
//Path base del comprobante de pago
|
||||||
//$pdf_payment_path = '';
|
//$pdf_payment_path = '';
|
||||||
|
|
||||||
|
|
||||||
// $this->ucrmApi = UcrmApi::create();
|
// $this->ucrmApi = UcrmApi::create();
|
||||||
// $invoices = $this->ucrmApi->get(
|
// $invoices = $this->ucrmApi->get(
|
||||||
// 'invoices/',
|
// 'invoices/',
|
||||||
@ -794,6 +786,8 @@ class ClientCallBellAPI
|
|||||||
// 'verify' => false,
|
// 'verify' => false,
|
||||||
// ]);
|
// ]);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// if (empty($notificationData->clientData['contacts'][0]['email'])) {
|
// if (empty($notificationData->clientData['contacts'][0]['email'])) {
|
||||||
// $log->appendLog("El cliente no tiene correo" . PHP_EOL);
|
// $log->appendLog("El cliente no tiene correo" . PHP_EOL);
|
||||||
// } else {
|
// } else {
|
||||||
@ -821,6 +815,9 @@ class ClientCallBellAPI
|
|||||||
// $log->appendLog("La ruta no es válida o no existe" . PHP_EOL);
|
// $log->appendLog("La ruta no es válida o no existe" . PHP_EOL);
|
||||||
// }
|
// }
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
$curl_string = "{\n \"to\": \"$clientWhatsAppNumber\",\n \"from\": \"SIIP INTERNET\",\n \"type\": \"text\",\n \"content\": {\n \"text\": \"S/M\",\n },\n \"template_values\": [\"$nombre_cliente\", \"$saldo\"],\n \"template_uuid\": \"9e7024c0a61a4c49b382150d26888dc2\",\n \"optin_contact\": true\n }";
|
$curl_string = "{\n \"to\": \"$clientWhatsAppNumber\",\n \"from\": \"SIIP INTERNET\",\n \"type\": \"text\",\n \"content\": {\n \"text\": \"S/M\",\n },\n \"template_values\": [\"$nombre_cliente\", \"$saldo\"],\n \"template_uuid\": \"9e7024c0a61a4c49b382150d26888dc2\",\n \"optin_contact\": true\n }";
|
||||||
//$curl_string = "{\n \"to\": \"$clientWhatsAppNumber\",\n \"from\": \"whatsapp\",\n \"type\": \"document\",\n \"content\": {\n \"text\": \"S/M\",\n \"url\": \"$url_file\"\n },\n \"template_values\": [\"$nombre_cliente\", \"$payment_amount\", \"$saldo\"],\n \"template_uuid\": \"57ead79cebd14902921477922403093b\",\n \"optin_contact\": true\n }";
|
//$curl_string = "{\n \"to\": \"$clientWhatsAppNumber\",\n \"from\": \"whatsapp\",\n \"type\": \"document\",\n \"content\": {\n \"text\": \"S/M\",\n \"url\": \"$url_file\"\n },\n \"template_values\": [\"$nombre_cliente\", \"$payment_amount\", \"$saldo\"],\n \"template_uuid\": \"57ead79cebd14902921477922403093b\",\n \"optin_contact\": true\n }";
|
||||||
//$curl_string = "{\n \"to\": \"$clientWhatsAppNumber\",\n \"from\": \"whatsapp\",\n \"type\": \"document\",\n \"content\": {\n \"text\": \"S/M\",\n \"url\": \"$url_file\"\n },\n \"template_values\": [\"$nombre_cliente\", \"$payment_amount\", \"$saldo\"],\n \"template_uuid\": \"6c0df98317b44f7b8666375a6cc8454c\",\n \"optin_contact\": true\n }";
|
//$curl_string = "{\n \"to\": \"$clientWhatsAppNumber\",\n \"from\": \"whatsapp\",\n \"type\": \"document\",\n \"content\": {\n \"text\": \"S/M\",\n \"url\": \"$url_file\"\n },\n \"template_values\": [\"$nombre_cliente\", \"$payment_amount\", \"$saldo\"],\n \"template_uuid\": \"6c0df98317b44f7b8666375a6cc8454c\",\n \"optin_contact\": true\n }";
|
||||||
@ -833,8 +830,10 @@ class ClientCallBellAPI
|
|||||||
$log->appendLog("Response del CallBell: " . $response);
|
$log->appendLog("Response del CallBell: " . $response);
|
||||||
|
|
||||||
curl_close($ch);
|
curl_close($ch);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public function getContactWhatsapp($cellphone_number): string
|
public function getContactWhatsapp($cellphone_number): string
|
||||||
{
|
{
|
||||||
// URL de la API REST
|
// URL de la API REST
|
||||||
@ -848,7 +847,7 @@ class ClientCallBellAPI
|
|||||||
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
|
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
|
||||||
curl_setopt($ch, CURLOPT_HTTPHEADER, [
|
curl_setopt($ch, CURLOPT_HTTPHEADER, [
|
||||||
'Authorization: Bearer ' . $this->CallBellAPIToken,
|
'Authorization: Bearer ' . $this->CallBellAPIToken,
|
||||||
'Content-Type: application/json',
|
'Content-Type: application/json'
|
||||||
]);
|
]);
|
||||||
|
|
||||||
// Ejecutar la solicitud y obtener la respuesta
|
// Ejecutar la solicitud y obtener la respuesta
|
||||||
@ -868,7 +867,7 @@ class ClientCallBellAPI
|
|||||||
{
|
{
|
||||||
|
|
||||||
$log = PluginLogManager::create(); //Initialize Logger
|
$log = PluginLogManager::create(); //Initialize Logger
|
||||||
//imprimir notificacionData
|
//imprimir notificacionData
|
||||||
$log->appendLog("Notificacion data: " . json_encode($notificationData) . PHP_EOL);
|
$log->appendLog("Notificacion data: " . json_encode($notificationData) . PHP_EOL);
|
||||||
//ejemplo de $notificationData: {"uuid":"cad4fa25-176e-4823-9f4c-1421d05d2a31","changeType":"edit","entity":"client","entityId":2,"message":null,"clientId":2,"eventName":"client.edit","clientData":{"id":2,"userIdent":null,"previousIsp":null,"isLead":false,"clientType":1,"companyName":null,"companyRegistrationNumber":null,"companyTaxId":null,"companyWebsite":null,"street1":"31 Chiapas","street2":null,"city":"Dolores Hidalgo Cuna de la Independencia Nacional","countryId":173,"stateId":null,"zipCode":"37800","fullAddress":"Chiapas 31, Centro, Dolores Hidalgo Cuna de la Independencia Nacional, Gto., M\u00e9xico","invoiceStreet1":null,"invoiceStreet2":null,"invoiceCity":null,"invoiceStateId":null,"invoiceCountryId":null,"invoiceZipCode":null,"invoiceAddressSameAsContact":true,"note":"Cliente espacial, el m\u00e1s chido","sendInvoiceByPost":null,"invoiceMaturityDays":null,"stopServiceDue":null,"stopServiceDueDays":null,"organizationId":1,"tax1Id":null,"tax2Id":null,"tax3Id":null,"registrationDate":"2024-01-25T00:00:00-0600","leadConvertedAt":null,"companyContactFirstName":null,"companyContactLastName":null,"isActive":true,"firstName":"Daniel Humberto","lastName":"Soto Villegas Pollerias2","username":"danydhsv","contacts":[{"id":2,"clientId":2,"email":"dhsv.141089@gmail.com","phone":"5214181878106","name":"Personal","isBilling":false,"isContact":false,"types":[{"id":1000,"name":"WhatsApp"}]},{"id":170,"clientId":2,"email":null,"phone":"5214181817609","name":"Bussiness","isBilling":false,"isContact":false,"types":[]}],"attributes":[{"id":112,"clientId":2,"customAttributeId":10,"name":"Stripe Customer ID","key":"stripeCustomerId","value":"cus_PetN1dhr4rx0kX","clientZoneVisible":true},{"id":113,"clientId":2,"customAttributeId":11,"name":"Clabe Interbancaria","key":"clabeInterbancaria","value":"0021804341999569810","clientZoneVisible":true},{"id":178,"clientId":2,"customAttributeId":15,"name":"Site","key":"site","value":"0LOCS","clientZoneVisible":false},{"id":179,"clientId":2,"customAttributeId":16,"name":"Antena\/Sectorial","key":"antenaSectorial","value":"Sectorial-4b 172.16.13.16\/24","clientZoneVisible":false}],"accountBalance":1553.33,"accountCredit":1553.33,"accountOutstanding":0,"currencyCode":"MXN","organizationName":"SIIP Pruebas","bankAccounts":[],"tags":[{"id":2,"name":"NS EXENTO","colorBackground":"#42a3df","colorText":"#fff"}],"invitationEmailSentDate":null,"avatarColor":"#f1df43","addressGpsLat":21.1564209,"addressGpsLon":-100.9384185,"isArchived":false,"generateProformaInvoices":null,"usesProforma":false,"hasOverdueInvoice":false,"hasOutage":true,"hasSuspendedService":false,"hasServiceWithoutDevices":false,"referral":null,"hasPaymentSubscription":false,"hasAutopayCreditCard":false},"serviceData":null,"invoiceData":null,"paymentData":null}
|
//ejemplo de $notificationData: {"uuid":"cad4fa25-176e-4823-9f4c-1421d05d2a31","changeType":"edit","entity":"client","entityId":2,"message":null,"clientId":2,"eventName":"client.edit","clientData":{"id":2,"userIdent":null,"previousIsp":null,"isLead":false,"clientType":1,"companyName":null,"companyRegistrationNumber":null,"companyTaxId":null,"companyWebsite":null,"street1":"31 Chiapas","street2":null,"city":"Dolores Hidalgo Cuna de la Independencia Nacional","countryId":173,"stateId":null,"zipCode":"37800","fullAddress":"Chiapas 31, Centro, Dolores Hidalgo Cuna de la Independencia Nacional, Gto., M\u00e9xico","invoiceStreet1":null,"invoiceStreet2":null,"invoiceCity":null,"invoiceStateId":null,"invoiceCountryId":null,"invoiceZipCode":null,"invoiceAddressSameAsContact":true,"note":"Cliente espacial, el m\u00e1s chido","sendInvoiceByPost":null,"invoiceMaturityDays":null,"stopServiceDue":null,"stopServiceDueDays":null,"organizationId":1,"tax1Id":null,"tax2Id":null,"tax3Id":null,"registrationDate":"2024-01-25T00:00:00-0600","leadConvertedAt":null,"companyContactFirstName":null,"companyContactLastName":null,"isActive":true,"firstName":"Daniel Humberto","lastName":"Soto Villegas Pollerias2","username":"danydhsv","contacts":[{"id":2,"clientId":2,"email":"dhsv.141089@gmail.com","phone":"5214181878106","name":"Personal","isBilling":false,"isContact":false,"types":[{"id":1000,"name":"WhatsApp"}]},{"id":170,"clientId":2,"email":null,"phone":"5214181817609","name":"Bussiness","isBilling":false,"isContact":false,"types":[]}],"attributes":[{"id":112,"clientId":2,"customAttributeId":10,"name":"Stripe Customer ID","key":"stripeCustomerId","value":"cus_PetN1dhr4rx0kX","clientZoneVisible":true},{"id":113,"clientId":2,"customAttributeId":11,"name":"Clabe Interbancaria","key":"clabeInterbancaria","value":"0021804341999569810","clientZoneVisible":true},{"id":178,"clientId":2,"customAttributeId":15,"name":"Site","key":"site","value":"0LOCS","clientZoneVisible":false},{"id":179,"clientId":2,"customAttributeId":16,"name":"Antena\/Sectorial","key":"antenaSectorial","value":"Sectorial-4b 172.16.13.16\/24","clientZoneVisible":false}],"accountBalance":1553.33,"accountCredit":1553.33,"accountOutstanding":0,"currencyCode":"MXN","organizationName":"SIIP Pruebas","bankAccounts":[],"tags":[{"id":2,"name":"NS EXENTO","colorBackground":"#42a3df","colorText":"#fff"}],"invitationEmailSentDate":null,"avatarColor":"#f1df43","addressGpsLat":21.1564209,"addressGpsLon":-100.9384185,"isArchived":false,"generateProformaInvoices":null,"usesProforma":false,"hasOverdueInvoice":false,"hasOutage":true,"hasSuspendedService":false,"hasServiceWithoutDevices":false,"referral":null,"hasPaymentSubscription":false,"hasAutopayCreditCard":false},"serviceData":null,"invoiceData":null,"paymentData":null}
|
||||||
|
|
||||||
@ -889,6 +888,8 @@ class ClientCallBellAPI
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
$log->appendLog("Dentro del proceso del patch: " . PHP_EOL);
|
$log->appendLog("Dentro del proceso del patch: " . PHP_EOL);
|
||||||
$this->ucrmApi = UcrmApi::create();
|
$this->ucrmApi = UcrmApi::create();
|
||||||
$payments = $this->ucrmApi->get(
|
$payments = $this->ucrmApi->get(
|
||||||
@ -896,7 +897,7 @@ class ClientCallBellAPI
|
|||||||
[
|
[
|
||||||
'clientId' => $notificationData->clientData['id'],
|
'clientId' => $notificationData->clientData['id'],
|
||||||
'limit' => 1,
|
'limit' => 1,
|
||||||
'direction' => 'DESC',
|
'direction' => 'DESC'
|
||||||
|
|
||||||
]
|
]
|
||||||
);
|
);
|
||||||
@ -908,6 +909,10 @@ class ClientCallBellAPI
|
|||||||
//$log->appendLog("Esto es lo que trae la fecha mas reciente de los pagos: " . $notificationData->paymentData[0]['createdDate']. PHP_EOL);
|
//$log->appendLog("Esto es lo que trae la fecha mas reciente de los pagos: " . $notificationData->paymentData[0]['createdDate']. PHP_EOL);
|
||||||
// $log->appendLog("Esto es lo que trae la fecha mas reciente de los pagos opcion 2: " . $payments[0]['createdDate'] . PHP_EOL);
|
// $log->appendLog("Esto es lo que trae la fecha mas reciente de los pagos opcion 2: " . $payments[0]['createdDate'] . PHP_EOL);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
$uuid = $response_getContactCallBell['contact']['uuid'];
|
$uuid = $response_getContactCallBell['contact']['uuid'];
|
||||||
$ch = curl_init();
|
$ch = curl_init();
|
||||||
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
|
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
|
||||||
@ -968,8 +973,11 @@ class ClientCallBellAPI
|
|||||||
default:
|
default:
|
||||||
$payment_method = 'Desconocido, revisar metodos de pago no contemplados';
|
$payment_method = 'Desconocido, revisar metodos de pago no contemplados';
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
$fecha_actual = new DateTime();
|
$fecha_actual = new DateTime();
|
||||||
$fecha_actual->modify('-6 hours');
|
$fecha_actual->modify('-6 hours');
|
||||||
$fecha_actual_ajustada = $fecha_actual->format("d/m/Y H:i");
|
$fecha_actual_ajustada = $fecha_actual->format("d/m/Y H:i");
|
||||||
@ -1012,7 +1020,7 @@ class ClientCallBellAPI
|
|||||||
'"Cliente": "' . $notificationData->clientData['id'] . '",' .
|
'"Cliente": "' . $notificationData->clientData['id'] . '",' .
|
||||||
'"Domicilio": "' .
|
'"Domicilio": "' .
|
||||||
//(($notificationData->clientData['fullAddress'] == null) ? 'Sin domicilio' : '' . $notificationData->clientData['fullAddress']) . '",' .
|
//(($notificationData->clientData['fullAddress'] == null) ? 'Sin domicilio' : '' . $notificationData->clientData['fullAddress']) . '",' .
|
||||||
'"Nombre": "' . sprintf("%s %s", $notificationData->clientData['firstName'], $notificationData->clientData['lastName']) . '",' .
|
'"Nombre": "' . sprintf("%s %s", $notificationData->clientData['firstName'], $notificationData->clientData['lastName']) . '",' .
|
||||||
'"URL": "https://sistema.siip.mx/crm/client/' . $notificationData->clientId . '",' .
|
'"URL": "https://sistema.siip.mx/crm/client/' . $notificationData->clientId . '",' .
|
||||||
'"Saldo Actual": "' . $saldoTexto . '",' .
|
'"Saldo Actual": "' . $saldoTexto . '",' .
|
||||||
'"Monto Ultimo Pago": "$ ' . $payments[0]['amount'] . '",' .
|
'"Monto Ultimo Pago": "$ ' . $payments[0]['amount'] . '",' .
|
||||||
@ -1025,11 +1033,15 @@ class ClientCallBellAPI
|
|||||||
'"Antena/Sectorial": "' . $antenaSectorial . '"' .
|
'"Antena/Sectorial": "' . $antenaSectorial . '"' .
|
||||||
'}';
|
'}';
|
||||||
|
|
||||||
$data_CRM = [
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
$data_CRM = array(
|
||||||
//"uuid" => $json_responseAPI->contact->uuid,
|
//"uuid" => $json_responseAPI->contact->uuid,
|
||||||
"name" => sprintf("%s %s", $notificationData->clientData['firstName'], $notificationData->clientData['lastName']),
|
"name" => sprintf("%s %s", $notificationData->clientData['firstName'], $notificationData->clientData['lastName']),
|
||||||
|
|
||||||
"custom_fields" => [
|
"custom_fields" => array(
|
||||||
"Cliente" => $notificationData->clientData['id'],
|
"Cliente" => $notificationData->clientData['id'],
|
||||||
"Domicilio" => ($notificationData->clientData['fullAddress'] == null) ? '📍❌ Sin domicilio' : '📍 ' . $notificationData->clientData['fullAddress'],
|
"Domicilio" => ($notificationData->clientData['fullAddress'] == null) ? '📍❌ Sin domicilio' : '📍 ' . $notificationData->clientData['fullAddress'],
|
||||||
"Nombre" => sprintf("👤 %s %s", $notificationData->clientData['firstName'], $notificationData->clientData['lastName']),
|
"Nombre" => sprintf("👤 %s %s", $notificationData->clientData['firstName'], $notificationData->clientData['lastName']),
|
||||||
@ -1042,20 +1054,21 @@ class ClientCallBellAPI
|
|||||||
"Fecha Ultima Actualizacion" => '📆🔄️ ' . $fecha_actual_ajustada,
|
"Fecha Ultima Actualizacion" => '📆🔄️ ' . $fecha_actual_ajustada,
|
||||||
"Clabe Interbancaria" => $clabeInterbancaria,
|
"Clabe Interbancaria" => $clabeInterbancaria,
|
||||||
"Site" => $site,
|
"Site" => $site,
|
||||||
"Antena/Sectorial" => $antenaSectorial,
|
"Antena/Sectorial" => $antenaSectorial
|
||||||
],
|
)
|
||||||
];
|
);
|
||||||
|
|
||||||
$log->appendLog("JSON con los datos a actualizar: " . json_encode($data_CRM) . PHP_EOL);
|
$log->appendLog("JSON con los datos a actualizar: " . json_encode($data_CRM) . PHP_EOL);
|
||||||
|
|
||||||
|
|
||||||
$data_CRM2 = [
|
$data_CRM2 = array(
|
||||||
"custom_fields" => [
|
"custom_fields" => array(
|
||||||
"Resumen" => $resumenClienteJSON,
|
"Resumen" => $resumenClienteJSON,
|
||||||
],
|
)
|
||||||
];
|
);
|
||||||
|
|
||||||
$log->appendLog("JSON con los datos a actualizar del resumen: " . $resumenClienteJSON . PHP_EOL);
|
$log->appendLog("JSON con los datos a actualizar del resumen: " . $resumenClienteJSON . PHP_EOL);
|
||||||
|
|
||||||
if (
|
if (
|
||||||
$response_getContactCallBell['custom_fields']['Cliente'] != $data_CRM['custom_fields']['Cliente']
|
$response_getContactCallBell['custom_fields']['Cliente'] != $data_CRM['custom_fields']['Cliente']
|
||||||
|| $response_getContactCallBell['custom_fields']['Domicilio'] != $data_CRM['custom_fields']['Domicilio']
|
|| $response_getContactCallBell['custom_fields']['Domicilio'] != $data_CRM['custom_fields']['Domicilio']
|
||||||
@ -1066,7 +1079,7 @@ class ClientCallBellAPI
|
|||||||
|| $response_getContactCallBell['custom_fields']['Fecha Ultimo Pago'] != $data_CRM['custom_fields']['Fecha Ultimo Pago']
|
|| $response_getContactCallBell['custom_fields']['Fecha Ultimo Pago'] != $data_CRM['custom_fields']['Fecha Ultimo Pago']
|
||||||
|| $response_getContactCallBell['custom_fields']['Monto Ultimo Pago'] != $data_CRM['custom_fields']['Monto Ultimo Pago']
|
|| $response_getContactCallBell['custom_fields']['Monto Ultimo Pago'] != $data_CRM['custom_fields']['Monto Ultimo Pago']
|
||||||
|| $response_getContactCallBell['name'] != $data_CRM['name']
|
|| $response_getContactCallBell['name'] != $data_CRM['name']
|
||||||
|
|
||||||
) {
|
) {
|
||||||
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($data_CRM));
|
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($data_CRM));
|
||||||
curl_setopt($ch2, CURLOPT_POSTFIELDS, json_encode($data_CRM2));
|
curl_setopt($ch2, CURLOPT_POSTFIELDS, json_encode($data_CRM2));
|
||||||
@ -1076,12 +1089,13 @@ class ClientCallBellAPI
|
|||||||
$log->appendLog("Response 2 Patch CallBell: " . $response2 . PHP_EOL);
|
$log->appendLog("Response 2 Patch CallBell: " . $response2 . PHP_EOL);
|
||||||
curl_close($ch);
|
curl_close($ch);
|
||||||
curl_close($ch2);
|
curl_close($ch2);
|
||||||
|
|
||||||
// if($fileNameComprobante != null){
|
// if($fileNameComprobante != null){
|
||||||
// sleep(3);
|
// sleep(3);
|
||||||
// $this->deleteFileWordPressAndLocal($fileNameComprobante);
|
// $this->deleteFileWordPressAndLocal($fileNameComprobante);
|
||||||
// }
|
// }
|
||||||
|
|
||||||
|
|
||||||
// $json_data_patch = '{
|
// $json_data_patch = '{
|
||||||
// "attributes": [
|
// "attributes": [
|
||||||
// {
|
// {
|
||||||
@ -1103,6 +1117,7 @@ class ClientCallBellAPI
|
|||||||
// 'verify' => false,
|
// 'verify' => false,
|
||||||
// ]); //aquí se contruye la petición para hacer patch hacia el cliente en sus custom fields con la API del UISP UCRM
|
// ]); //aquí se contruye la petición para hacer patch hacia el cliente en sus custom fields con la API del UISP UCRM
|
||||||
|
|
||||||
|
|
||||||
// } catch (GuzzleException $error) {
|
// } catch (GuzzleException $error) {
|
||||||
// echo "Error al hacer el patch al CRM: " . $error->getMessage() . PHP_EOL;
|
// echo "Error al hacer el patch al CRM: " . $error->getMessage() . PHP_EOL;
|
||||||
// //exit();
|
// //exit();
|
||||||
@ -1114,13 +1129,17 @@ class ClientCallBellAPI
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
public function patchServiceStatusWhatsApp($response_getContactCallBell, $notificationData)
|
public function patchServiceStatusWhatsApp($response_getContactCallBell, $notificationData)
|
||||||
{
|
{
|
||||||
|
|
||||||
$log = PluginLogManager::create(); //Initialize Logger
|
$log = PluginLogManager::create(); //Initialize Logger
|
||||||
|
|
||||||
|
|
||||||
$log->appendLog("Actualizando estado del servicio " . PHP_EOL);
|
$log->appendLog("Actualizando estado del servicio " . PHP_EOL);
|
||||||
|
|
||||||
|
|
||||||
$uuid = $response_getContactCallBell['contact']['uuid'];
|
$uuid = $response_getContactCallBell['contact']['uuid'];
|
||||||
$ch = curl_init();
|
$ch = curl_init();
|
||||||
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
|
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
|
||||||
@ -1135,13 +1154,18 @@ class ClientCallBellAPI
|
|||||||
$log->appendLog("Nombre del cliente al que se va a actualizar el estado del servicio: " . $nombre_cliente . PHP_EOL);
|
$log->appendLog("Nombre del cliente al que se va a actualizar el estado del servicio: " . $nombre_cliente . PHP_EOL);
|
||||||
$log->appendLog("UUID: " . $uuid . PHP_EOL);
|
$log->appendLog("UUID: " . $uuid . PHP_EOL);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
$fecha_actual = new DateTime();
|
$fecha_actual = new DateTime();
|
||||||
$fecha_actual->modify('-6 hours');
|
$fecha_actual->modify('-6 hours');
|
||||||
$fecha_actual_ajustada = $fecha_actual->format("d/m/Y H:i");
|
$fecha_actual_ajustada = $fecha_actual->format("d/m/Y H:i");
|
||||||
|
|
||||||
$data_CRM = [
|
|
||||||
|
|
||||||
|
$data_CRM = array(
|
||||||
"name" => $nombre_cliente,
|
"name" => $nombre_cliente,
|
||||||
"custom_fields" => [
|
"custom_fields" => array(
|
||||||
"Estado" => (
|
"Estado" => (
|
||||||
isset($notificationData->serviceData['status'])
|
isset($notificationData->serviceData['status'])
|
||||||
&& $notificationData->serviceData['status'] == 3
|
&& $notificationData->serviceData['status'] == 3
|
||||||
@ -1149,9 +1173,11 @@ class ClientCallBellAPI
|
|||||||
(isset($notificationData->serviceData['status'])
|
(isset($notificationData->serviceData['status'])
|
||||||
&& $notificationData->serviceData['status'] == 1)
|
&& $notificationData->serviceData['status'] == 1)
|
||||||
? '🟢 Activo' : '🚫 Finalizado'),
|
? '🟢 Activo' : '🚫 Finalizado'),
|
||||||
"Fecha Ultima Actualizacion" => '📆🔄️ ' . $fecha_actual_ajustada,
|
"Fecha Ultima Actualizacion" => '📆🔄️ ' . $fecha_actual_ajustada
|
||||||
],
|
)
|
||||||
];
|
);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
$log->appendLog("JSON con los datos a actualizar: " . json_encode($data_CRM) . PHP_EOL);
|
$log->appendLog("JSON con los datos a actualizar: " . json_encode($data_CRM) . PHP_EOL);
|
||||||
|
|
||||||
@ -1160,6 +1186,8 @@ class ClientCallBellAPI
|
|||||||
$response = curl_exec($ch);
|
$response = curl_exec($ch);
|
||||||
$log->appendLog("Response Patch CallBell: " . $response . PHP_EOL);
|
$log->appendLog("Response Patch CallBell: " . $response . PHP_EOL);
|
||||||
curl_close($ch);
|
curl_close($ch);
|
||||||
|
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
$log->appendLog("No hay cambios en el estado del servicio que actualizar " . PHP_EOL);
|
$log->appendLog("No hay cambios en el estado del servicio que actualizar " . PHP_EOL);
|
||||||
}
|
}
|
||||||
@ -1189,6 +1217,7 @@ class ClientCallBellAPI
|
|||||||
|
|
||||||
$log->appendLog("file_to_upload: " . $file_to_upload . PHP_EOL);
|
$log->appendLog("file_to_upload: " . $file_to_upload . PHP_EOL);
|
||||||
|
|
||||||
|
|
||||||
// Conexión FTP
|
// Conexión FTP
|
||||||
$ftp_conn = ftp_connect($ftp_server) or die("No se pudo conectar al servidor FTP");
|
$ftp_conn = ftp_connect($ftp_server) or die("No se pudo conectar al servidor FTP");
|
||||||
$login = ftp_login($ftp_conn, $ftp_username, $ftp_password);
|
$login = ftp_login($ftp_conn, $ftp_username, $ftp_password);
|
||||||
@ -1202,10 +1231,10 @@ class ClientCallBellAPI
|
|||||||
$log->appendLog("El archivo ha sido cargado exitosamente." . PHP_EOL);
|
$log->appendLog("El archivo ha sido cargado exitosamente." . PHP_EOL);
|
||||||
$log->appendLog("La URL es: " . $url . PHP_EOL);
|
$log->appendLog("La URL es: " . $url . PHP_EOL);
|
||||||
|
|
||||||
$this->deleteFilesWordpressExceptLastHundred($log, $ftp_conn, $remote_file);
|
$this->deleteFilesWordpressExceptLastHundred($log,$ftp_conn,$remote_file);
|
||||||
// Cerrar conexión FTP
|
// Cerrar conexión FTP
|
||||||
ftp_close($ftp_conn); //COMENTAR AQUÍ SI SE BORRAN LOS ARCHIVOS DE WORDPRESS DESCOMENTANDO EL CÓDIGO DE MÁS ABAJO
|
ftp_close($ftp_conn);//COMENTAR AQUÍ SI SE BORRAN LOS ARCHIVOS DE WORDPRESS DESCOMENTANDO EL CÓDIGO DE MÁS ABAJO
|
||||||
return $url; //COMENTAR AQUÍ SI SE BORRAN LOS ARCHIVOS DE WORDPRESS DESCOMENTANDO EL CÓDIGO DE MÁS ABAJO
|
return $url;//COMENTAR AQUÍ SI SE BORRAN LOS ARCHIVOS DE WORDPRESS DESCOMENTANDO EL CÓDIGO DE MÁS ABAJO
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
$log->appendLog("Error al cargar el archivo " . PHP_EOL);
|
$log->appendLog("Error al cargar el archivo " . PHP_EOL);
|
||||||
@ -1255,12 +1284,15 @@ class ClientCallBellAPI
|
|||||||
// return $url;
|
// return $url;
|
||||||
// }
|
// }
|
||||||
|
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
$log->appendLog("No se pudo conectar o iniciar sesión en el servidor FTP." . PHP_EOL);
|
$log->appendLog("No se pudo conectar o iniciar sesión en el servidor FTP." . PHP_EOL);
|
||||||
return '';
|
return '';
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
function deleteFilesWordpressExceptLastHundred($log, $ftp_conn, $remote_folder): bool
|
function deleteFilesWordpressExceptLastHundred($log, $ftp_conn, $remote_folder): bool
|
||||||
{
|
{
|
||||||
|
|
||||||
@ -1303,8 +1335,10 @@ class ClientCallBellAPI
|
|||||||
ftp_close($ftp_conn);
|
ftp_close($ftp_conn);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* /Elimina los archivos del directorio de comprobantes de pago a excepción de los últimos 100 para evitar errores de envío
|
* /Elimina los archivos del directorio de comprobantes de pago a excepción de los últimos 100 para evitar errores de envío
|
||||||
* @return void
|
* @return void
|
||||||
@ -1317,6 +1351,7 @@ class ClientCallBellAPI
|
|||||||
if (!is_dir($directory)) {
|
if (!is_dir($directory)) {
|
||||||
$log->appendLog('El directorio no existe.');
|
$log->appendLog('El directorio no existe.');
|
||||||
die("El directorio no existe.");
|
die("El directorio no existe.");
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Obtener la lista de archivos en el directorio
|
// Obtener la lista de archivos en el directorio
|
||||||
@ -1343,4 +1378,5 @@ class ClientCallBellAPI
|
|||||||
$log->appendLog("Hay menos de 100 archivos en el directorio. No se eliminarán archivos." . PHP_EOL);
|
$log->appendLog("Hay menos de 100 archivos en el directorio. No se eliminarán archivos." . PHP_EOL);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
}
|
||||||
341
src/Plugin.php
341
src/Plugin.php
@ -1,13 +1,14 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
declare (strict_types = 1);
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
|
||||||
namespace SmsNotifier;
|
namespace SmsNotifier;
|
||||||
|
|
||||||
use Psr\Log\LogLevel;
|
use Psr\Log\LogLevel;
|
||||||
|
use SmsNotifier\Facade\TwilioNotifierFacade;
|
||||||
use SmsNotifier\Facade\PluginNotifierFacade;
|
use SmsNotifier\Facade\PluginNotifierFacade;
|
||||||
use SmsNotifier\Facade\PluginOxxoNotifierFacade;
|
use SmsNotifier\Facade\PluginOxxoNotifierFacade;
|
||||||
use SmsNotifier\Facade\TwilioNotifierFacade;
|
|
||||||
use SmsNotifier\Factory\NotificationDataFactory;
|
use SmsNotifier\Factory\NotificationDataFactory;
|
||||||
use SmsNotifier\Service\Logger;
|
use SmsNotifier\Service\Logger;
|
||||||
use SmsNotifier\Service\OptionsManager;
|
use SmsNotifier\Service\OptionsManager;
|
||||||
@ -55,6 +56,7 @@ class Plugin
|
|||||||
*/
|
*/
|
||||||
protected $ucrmApi;
|
protected $ucrmApi;
|
||||||
|
|
||||||
|
|
||||||
public function __construct(
|
public function __construct(
|
||||||
Logger $logger,
|
Logger $logger,
|
||||||
OptionsManager $optionsManager,
|
OptionsManager $optionsManager,
|
||||||
@ -64,13 +66,13 @@ class Plugin
|
|||||||
PluginOxxoNotifierFacade $pluginOxxoNotifierFacade,
|
PluginOxxoNotifierFacade $pluginOxxoNotifierFacade,
|
||||||
NotificationDataFactory $notificationDataFactory
|
NotificationDataFactory $notificationDataFactory
|
||||||
) {
|
) {
|
||||||
$this->logger = $logger;
|
$this->logger = $logger;
|
||||||
$this->optionsManager = $optionsManager;
|
$this->optionsManager = $optionsManager;
|
||||||
$this->pluginDataValidator = $pluginDataValidator;
|
$this->pluginDataValidator = $pluginDataValidator;
|
||||||
$this->notifierFacade = $notifierFacade;
|
$this->notifierFacade = $notifierFacade;
|
||||||
$this->pluginNotifierFacade = $pluginNotifierFacade;
|
$this->pluginNotifierFacade = $pluginNotifierFacade;
|
||||||
$this->pluginOxxoNotifierFacade = $pluginOxxoNotifierFacade;
|
$this->pluginOxxoNotifierFacade = $pluginOxxoNotifierFacade;
|
||||||
$this->notificationDataFactory = $notificationDataFactory;
|
$this->notificationDataFactory = $notificationDataFactory;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function run(): void
|
public function run(): void
|
||||||
@ -78,13 +80,13 @@ class Plugin
|
|||||||
// $hola = PHP_SAPI;
|
// $hola = PHP_SAPI;
|
||||||
// $this->logger->info('valor de PHP_SAPI: ' . $hola);
|
// $this->logger->info('valor de PHP_SAPI: ' . $hola);
|
||||||
if (PHP_SAPI === 'fpm-fcgi') {
|
if (PHP_SAPI === 'fpm-fcgi') {
|
||||||
// $this->logger->debug('Whatsapp over HTTP started');
|
//$this->logger->debug('Whatsapp over HTTP started');
|
||||||
$this->processHttpRequest();
|
$this->processHttpRequest();
|
||||||
// $this->logger->debug('HTTP request processing ended.');
|
//$this->logger->debug('HTTP request processing ended.');
|
||||||
} elseif (PHP_SAPI === 'cli') {
|
} elseif (PHP_SAPI === 'cli') {
|
||||||
// $this->logger->debug('Whatsapp over CLI started');
|
//$this->logger->debug('Whatsapp over CLI started');
|
||||||
$this->processCli();
|
$this->processCli();
|
||||||
// $this->logger->debug('CLI process ended.');
|
//$this->logger->debug('CLI process ended.');
|
||||||
} else {
|
} else {
|
||||||
throw new \UnexpectedValueException('Unknown PHP_SAPI type: ' . PHP_SAPI);
|
throw new \UnexpectedValueException('Unknown PHP_SAPI type: ' . PHP_SAPI);
|
||||||
}
|
}
|
||||||
@ -106,11 +108,12 @@ class Plugin
|
|||||||
$this->logger->setLogLevelThreshold(LogLevel::DEBUG);
|
$this->logger->setLogLevelThreshold(LogLevel::DEBUG);
|
||||||
}
|
}
|
||||||
|
|
||||||
$userInput = file_get_contents('php://input'); //se recibe el json del webhook
|
|
||||||
//imprimir el json del webhook
|
|
||||||
$this->logger->debug('valor del webhook: ' . $userInput . PHP_EOL);
|
|
||||||
|
|
||||||
if (! $userInput) {
|
$userInput = file_get_contents('php://input');
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
if (!$userInput) {
|
||||||
$this->logger->warning('no input');
|
$this->logger->warning('no input');
|
||||||
|
|
||||||
return;
|
return;
|
||||||
@ -118,7 +121,7 @@ class Plugin
|
|||||||
|
|
||||||
$jsonData = @json_decode($userInput, true, 50);
|
$jsonData = @json_decode($userInput, true, 50);
|
||||||
|
|
||||||
if (! isset($jsonData['uuid'])) {
|
if (!isset($jsonData['uuid'])) {
|
||||||
$this->logger->info('No UUID found in the webhook data');
|
$this->logger->info('No UUID found in the webhook data');
|
||||||
//$this->logger->error('JSON error: ' . json_last_error_msg());
|
//$this->logger->error('JSON error: ' . json_last_error_msg());
|
||||||
|
|
||||||
@ -128,50 +131,25 @@ class Plugin
|
|||||||
if ($jsonData) {
|
if ($jsonData) {
|
||||||
switch ($jsonData['type']) {
|
switch ($jsonData['type']) {
|
||||||
case 'customer_cash_balance_transaction.created':
|
case 'customer_cash_balance_transaction.created':
|
||||||
if ($jsonData['data']['object']['type'] === 'funded') {
|
$this->logger->info('Evento de transfencia al cliente encontrado');
|
||||||
$this->logger->info('Evento de transferencia de un cliente recibido: ' . json_encode($jsonData) . PHP_EOL);
|
$this->logger->info('Valor del EventJSON: ' . json_encode($jsonData) . PHP_EOL);
|
||||||
$this->pluginNotifierFacade->createPaymentIntent($jsonData);
|
$this->pluginNotifierFacade->createPaymentIntent($jsonData);
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($jsonData['data']['object']['type'] === 'applied_to_payment') {
|
|
||||||
$this->logger->info('Se aplicó el saldo en Stripe de un pago: ' . json_encode($jsonData) . PHP_EOL);
|
|
||||||
$this->pluginNotifierFacade->registerPaymentFromWebhook($jsonData);
|
|
||||||
}elseif ($jsonData['data']['object']['type'] === 'unapplied_from_payment'){
|
|
||||||
//ejemplo de json para transferencia de dinero cancelada: {"id":"evt_1RlEGgEFY1WEUtgR6Bp2DzDP","object":"event","api_version":"2023-10-16","created":1752606717,"data":{"object":{"id":"ccsbtxn_1RlEGfEFY1WEUtgRv8jAUGmE","object":"customer_cash_balance_transaction","created":1752606717,"currency":"mxn","customer":"cus_PetN1dhr4rx0kX","ending_balance":18000,"livemode":false,"net_amount":18000,"type":"unapplied_from_payment","unapplied_from_payment":{"payment_intent":"pi_3RlDPdEFY1WEUtgR1JBgNhTQ"}}},"livemode":false,"pending_webhooks":2,"request":{"id":"req_954mskVBfAI0jn","idempotency_key":"749518f6-baa0-4ae9-99e4-8029a35719aa"},"type":"customer_cash_balance_transaction.created"}
|
|
||||||
$paymentIntentId = $jsonData['data']['object']['unapplied_from_payment']['payment_intent'];
|
|
||||||
//Se canceló una transferencia de dinero, imprimir que se canceló y además el monto neto
|
|
||||||
$this->logger->warning('Evento de transferencia cancelada para el pago: ' . $paymentIntentId . PHP_EOL);
|
|
||||||
$this->logger->warning('Monto neto de la transferencia cancelada: ' . $jsonData['data']['object']['net_amount'] . PHP_EOL);
|
|
||||||
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case 'payout.failed':
|
|
||||||
$this->logger->info('Evento de transferencia fallida encontrado: ' . json_encode($jsonData) . PHP_EOL);
|
|
||||||
//imprimir detalles del fallo
|
|
||||||
$this->logger->info('Detalles del fallo: ' . json_encode($jsonData));
|
|
||||||
break;
|
|
||||||
case 'payment_intent.partially_funded':
|
|
||||||
$this->logger->info('Evento de pago parcialmente financiado encontrado: ' . json_encode($jsonData) . PHP_EOL);
|
|
||||||
//imprimir detalles del evento o pago
|
|
||||||
$this->logger->info('Detalles del evento: ' . json_encode($jsonData));
|
|
||||||
break;
|
break;
|
||||||
case 'inbound_payment.payment_attempt':
|
case 'inbound_payment.payment_attempt':
|
||||||
//$this->logger->info('Evento de Pago de OXXO recibido: ' . json_encode($jsonData) . PHP_EOL);
|
$this->logger->info('Evento de Pago de OXXO recibido');
|
||||||
break;
|
$this->logger->info('Valor del EventJSON: ' . json_encode($jsonData) . PHP_EOL);
|
||||||
case 'cash_balance.funds_available':
|
|
||||||
$this->logger->info('Evento de Pago de fondos disponibles recibido: ' . json_encode($jsonData) . PHP_EOL);
|
|
||||||
break;
|
break;
|
||||||
case 'energy.alert':
|
case 'energy.alert':
|
||||||
$this->logger->info('Evento de Energía recibido: ' . $jsonData['message'] . PHP_EOL);
|
$this->logger->info('Evento de Energía recibido: ' . $jsonData['message'] . PHP_EOL);
|
||||||
break;
|
break;
|
||||||
case 'oxxo.request':
|
case 'oxxo.request':
|
||||||
$this->logger->info('Evento de solicitud de referencia de oxxo recibido' . PHP_EOL);
|
$this->logger->info('Evento de referencia de oxxo recibido' . PHP_EOL);
|
||||||
|
|
||||||
|
|
||||||
// Construir la URL basada en el "client_id"
|
// Construir la URL basada en el "client_id"
|
||||||
// $url = "https://siip.mx/wp/wp-content/uploads/img/voucher.png";
|
// $url = "https://siip.mx/wp/wp-content/uploads/img/voucher.png";
|
||||||
if (! empty($jsonData['amount'])) {
|
if (!empty($jsonData['amount'])) {
|
||||||
$this->logger->info('Referencia personalizada, Valor del monto: ' . $jsonData['amount'] . PHP_EOL);
|
$this->logger->info('Referencia persnoalizada, Valor del monto: ' . $jsonData['amount'] . PHP_EOL);
|
||||||
$intentos = 0;
|
$intentos = 0;
|
||||||
do {
|
do {
|
||||||
// if ($intentos > 1) {
|
// if ($intentos > 1) {
|
||||||
@ -200,14 +178,12 @@ class Plugin
|
|||||||
//this->logger->error('Error al crear la referencia de OXXO: ' . $responseOxxo);
|
//this->logger->error('Error al crear la referencia de OXXO: ' . $responseOxxo);
|
||||||
//crear un json con variable $response que contenga las claves y valores del array $responseOxxo los cuales son: oxxo_reference, error, failDescription, clientID, clientFullName amount
|
//crear un json con variable $response que contenga las claves y valores del array $responseOxxo los cuales son: oxxo_reference, error, failDescription, clientID, clientFullName amount
|
||||||
$response = '{' .
|
$response = '{' .
|
||||||
'"url": "' . $responseOxxo['url'] . '",' .
|
'"url":' . $responseOxxo['url'] . ',' .
|
||||||
'"oxxo_reference": "' . $responseOxxo['oxxo_reference'] . '",' .
|
|
||||||
'"voucher_image_url": "' . $responseOxxo['voucher_image_url'] . '",' .
|
|
||||||
'"error": "' . $responseOxxo['error'] . '",' .
|
'"error": "' . $responseOxxo['error'] . '",' .
|
||||||
'"failDescription": "' . $responseOxxo['failDescription'] . '",' .
|
'"failDescription": "' . $responseOxxo['failDescription'] . '",' .
|
||||||
'"clientID": "' . $responseOxxo['clientID'] . '",' .
|
'"clientID": "' . $responseOxxo['clientID'] . '",' .
|
||||||
'"clientFullName": "' . $responseOxxo['clientFullName'] . '",' .
|
'"clientFullName": "' . $responseOxxo['clientFullName'] . '",' .
|
||||||
'"amount": "' . $responseOxxo['amount'] . '"' .
|
'"amount": "' . $responseOxxo['amount'] . '",' .
|
||||||
'}';
|
'}';
|
||||||
|
|
||||||
header('Content-Type: application/json');
|
header('Content-Type: application/json');
|
||||||
@ -219,7 +195,6 @@ class Plugin
|
|||||||
$response = '{' .
|
$response = '{' .
|
||||||
'"url": "' . $responseOxxo['url'] . '",' .
|
'"url": "' . $responseOxxo['url'] . '",' .
|
||||||
'"oxxo_reference": "' . $responseOxxo['oxxo_reference'] . '",' .
|
'"oxxo_reference": "' . $responseOxxo['oxxo_reference'] . '",' .
|
||||||
'"voucher_image_url": "' . $responseOxxo['voucher_image_url'] . '",' .
|
|
||||||
'"error": "' . $responseOxxo['error'] . '",' .
|
'"error": "' . $responseOxxo['error'] . '",' .
|
||||||
'"failDescription": "' . $responseOxxo['failDescription'] . '",' .
|
'"failDescription": "' . $responseOxxo['failDescription'] . '",' .
|
||||||
'"clientID": "' . $responseOxxo['clientID'] . '",' .
|
'"clientID": "' . $responseOxxo['clientID'] . '",' .
|
||||||
@ -231,7 +206,7 @@ class Plugin
|
|||||||
// Enviar el encabezado de respuesta como JSON
|
// Enviar el encabezado de respuesta como JSON
|
||||||
header('Content-Type: application/json');
|
header('Content-Type: application/json');
|
||||||
|
|
||||||
// Enviar la respuesta en formato JSON
|
// Enviar la respuesta en formato JSON
|
||||||
//echo json_encode($response);
|
//echo json_encode($response);
|
||||||
echo $response;
|
echo $response;
|
||||||
|
|
||||||
@ -248,6 +223,11 @@ class Plugin
|
|||||||
// $webhook_string = json_encode($event_json);
|
// $webhook_string = json_encode($event_json);
|
||||||
// $this->logger->debug("El valor de webhook_string: " . $webhook_string . PHP_EOL);
|
// $this->logger->debug("El valor de webhook_string: " . $webhook_string . PHP_EOL);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
$notification = $this->notificationDataFactory->getObject($jsonData);
|
$notification = $this->notificationDataFactory->getObject($jsonData);
|
||||||
$this->logger->debug('valor el evento recibido por webhook: ' . $notification->eventName . PHP_EOL);
|
$this->logger->debug('valor el evento recibido por webhook: ' . $notification->eventName . PHP_EOL);
|
||||||
$this->logger->debug('Valor de JSON: ' . json_encode($jsonData) . PHP_EOL);
|
$this->logger->debug('Valor de JSON: ' . json_encode($jsonData) . PHP_EOL);
|
||||||
@ -255,14 +235,11 @@ class Plugin
|
|||||||
if ($notification->changeType === 'test') {
|
if ($notification->changeType === 'test') {
|
||||||
|
|
||||||
$configManager = \Ubnt\UcrmPluginSdk\Service\PluginConfigManager::create();
|
$configManager = \Ubnt\UcrmPluginSdk\Service\PluginConfigManager::create();
|
||||||
$config = $configManager->loadConfig();
|
$config = $configManager->loadConfig();
|
||||||
|
|
||||||
$this->logger->info('Webhook test successful.');
|
$this->logger->info('Webhook test successful.');
|
||||||
|
|
||||||
return;
|
return;
|
||||||
} else if ($notification->changeType === 'paperless.update') {
|
|
||||||
//imprimir el webhook json
|
|
||||||
$this->logger->info('Webhook de paperless update: ' . json_encode($jsonData) . PHP_EOL);
|
|
||||||
}
|
}
|
||||||
// if (!$notification->clientId) {
|
// if (!$notification->clientId) {
|
||||||
// $this->logger->warning('No client specified, cannot notify them.');
|
// $this->logger->warning('No client specified, cannot notify them.');
|
||||||
@ -271,7 +248,7 @@ class Plugin
|
|||||||
// }
|
// }
|
||||||
|
|
||||||
$configManager = \Ubnt\UcrmPluginSdk\Service\PluginConfigManager::create();
|
$configManager = \Ubnt\UcrmPluginSdk\Service\PluginConfigManager::create();
|
||||||
$config = $configManager->loadConfig();
|
$config = $configManager->loadConfig();
|
||||||
// the "exportFormat" key must be defined in plugin's manifest file, see the link above
|
// the "exportFormat" key must be defined in plugin's manifest file, see the link above
|
||||||
|
|
||||||
try {
|
try {
|
||||||
@ -286,8 +263,11 @@ class Plugin
|
|||||||
$payment_method_id = $notification->paymentData['methodId'];
|
$payment_method_id = $notification->paymentData['methodId'];
|
||||||
//$this->logger->debug('Metodo de pago: ' . $notification->paymentData['methodId'] . PHP_EOL);
|
//$this->logger->debug('Metodo de pago: ' . $notification->paymentData['methodId'] . PHP_EOL);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
$payment_method = '';
|
$payment_method = '';
|
||||||
|
|
||||||
|
|
||||||
switch ($payment_method_id) {
|
switch ($payment_method_id) {
|
||||||
|
|
||||||
case '11721cdf-a498-48be-903e-daa67552e4f6':
|
case '11721cdf-a498-48be-903e-daa67552e4f6':
|
||||||
@ -360,63 +340,15 @@ class Plugin
|
|||||||
$payment_method = 'Desconocido, revisar metodos de pago no contemplados';
|
$payment_method = 'Desconocido, revisar metodos de pago no contemplados';
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
} else if ($notification->eventName === 'client.edit') {
|
} else if ($notification->eventName === 'client.edit') {
|
||||||
$this->logger->debug('Se actualiza a un cliente');
|
$this->logger->debug('Se actualiza a un cliente');
|
||||||
$this->logger->debug('Valor de json_data: ' . json_encode($jsonData));
|
$this->logger->debug('Valor de json_data: ' . json_encode($jsonData));
|
||||||
//ejemplo de json_data: {"uuid":"aacaf5c5-2bf4-44ea-864f-a24121b453bb","changeType":"edit","entity":"client","entityId":"171","eventName":"client.edit","extraData":{"entity":{"id":171,"userIdent":null,"previousIsp":null,"isLead":false,"clientType":1,"companyName":null,"companyRegistrationNumber":null,"companyTaxId":null,"companyWebsite":null,"street1":"Campeche 56","street2":null,"city":"Dolores Hidalgo","countryId":173,"stateId":null,"zipCode":"37800","fullAddress":"Campeche 56, Dolores Hidalgo, 37800","invoiceStreet1":null,"invoiceStreet2":null,"invoiceCity":null,"invoiceStateId":null,"invoiceCountryId":null,"invoiceZipCode":null,"invoiceAddressSameAsContact":true,"note":null,"sendInvoiceByPost":null,"invoiceMaturityDays":null,"stopServiceDue":null,"stopServiceDueDays":null,"organizationId":1,"tax1Id":null,"tax2Id":null,"tax3Id":null,"registrationDate":"2025-05-21T00:00:00-0600","leadConvertedAt":null,"companyContactFirstName":null,"companyContactLastName":null,"isActive":false,"firstName":"Archi","lastName":"Isalas","username":"mainstreamm2@gmail.com","contacts":[{"id":177,"clientId":171,"email":"mainstreamm2@gmail.com","phone":"4181878106","name":null,"isBilling":false,"isContact":false,"types":[]}],"attributes":[{"id":198,"clientId":171,"customAttributeId":10,"name":"Stripe Customer ID","key":"stripeCustomerId","value":"cus_SM2zH6IsjTz6ol","clientZoneVisible":true},{"id":199,"clientId":171,"customAttributeId":11,"name":"Clabe Interbancaria","key":"clabeInterbancaria","value":"124180950530868794","clientZoneVisible":true}],"accountBalance":0,"accountCredit":0,"accountOutstanding":0,"currencyCode":"MXN","organizationName":"SIIP Pruebas","bankAccounts":[],"tags":[],"invitationEmailSentDate":null,"avatarColor":"#f1df43","addressGpsLat":21.1572461,"addressGpsLon":-100.9377137,"isArchived":false,"generateProformaInvoices":null,"usesProforma":false,"hasOverdueInvoice":false,"hasOutage":false,"hasSuspendedService":false,"hasServiceWithoutDevices":true,"referral":null,"hasPaymentSubscription":false,"hasAutopayCreditCard":false},"entityBeforeEdit":{"id":171,"userIdent":null,"previousIsp":null,"isLead":false,"clientType":1,"companyName":null,"companyRegistrationNumber":null,"companyTaxId":null,"companyWebsite":null,"street1":"Campeche 56","street2":null,"city":"Dolores Hidalgo","countryId":173,"stateId":null,"zipCode":"37800","fullAddress":"Campeche 56, Dolores Hidalgo, 37800","invoiceStreet1":null,"invoiceStreet2":null,"invoiceCity":null,"invoiceStateId":null,"invoiceCountryId":null,"invoiceZipCode":null,"invoiceAddressSameAsContact":true,"note":null,"sendInvoiceByPost":null,"invoiceMaturityDays":null,"stopServiceDue":null,"stopServiceDueDays":null,"organizationId":1,"tax1Id":null,"tax2Id":null,"tax3Id":null,"registrationDate":"2025-05-21T00:00:00-0600","leadConvertedAt":null,"companyContactFirstName":null,"companyContactLastName":null,"isActive":false,"firstName":"Archi","lastName":"Isalas","username":"mainstreamm2@gmail.com","contacts":[{"id":177,"clientId":171,"email":"mainstreamm2@gmail.com","phone":"4181878106","name":null,"isBilling":false,"isContact":false,"types":[{"id":1003,"name":"WhatsNotifica"}]}],"attributes":[{"id":198,"clientId":171,"customAttributeId":10,"name":"Stripe Customer ID","key":"stripeCustomerId","value":"cus_SM2zH6IsjTz6ol","clientZoneVisible":true},{"id":199,"clientId":171,"customAttributeId":11,"name":"Clabe Interbancaria","key":"clabeInterbancaria","value":"124180950530868794","clientZoneVisible":true}],"accountBalance":0,"accountCredit":0,"accountOutstanding":0,"currencyCode":"MXN","organizationName":"SIIP Pruebas","bankAccounts":[],"tags":[],"invitationEmailSentDate":null,"avatarColor":"#f1df43","addressGpsLat":21.1572461,"addressGpsLon":-100.9377137,"isArchived":false,"generateProformaInvoices":null,"usesProforma":false,"hasOverdueInvoice":false,"hasOutage":false,"hasSuspendedService":false,"hasServiceWithoutDevices":true,"referral":null,"hasPaymentSubscription":false,"hasAutopayCreditCard":false}}}
|
|
||||||
|
|
||||||
|
|
||||||
$clientID = $jsonData['entityId'];
|
|
||||||
$this->ucrmApi = UcrmApi::create();
|
|
||||||
$customAttributes = $this->ucrmApi->get('custom-attributes/', ['attributeType' => 'client']); //Obtener los atributos del sistema que estén vinculados a la entidad "cliente"
|
|
||||||
//$this->logger->info("result del custom Attributes: " . json_encode($customAttributes) . PHP_EOL);
|
|
||||||
|
|
||||||
$idPasswordAntenaCliente = null;
|
|
||||||
$passwordAntenaValue = null;
|
|
||||||
|
|
||||||
//ejemplo de $customAttributes: [{"id":1,"name":"ip","key":"ip","attributeType":"client","type":"string","clientZoneVisible":false},{"id":2,"name":"ubntpass","key":"ubntpass","attributeType":"client","type":"string","clientZoneVisible":false},{"id":3,"name":"adminpass","key":"adminpass","attributeType":"client","type":"string","clientZoneVisible":true},{"id":4,"name":"ssid","key":"ssid","attributeType":"client","type":"string","clientZoneVisible":true},{"id":5,"name":"clavessid","key":"clavessid","attributeType":"client","type":"string","clientZoneVisible":true},{"id":6,"name":"clave","key":"clave","attributeType":"client","type":"string","clientZoneVisible":true},{"id":11,"name":"latitud","key":"latitud","attributeType":"client","type":"string","clientZoneVisible":true},{"id":12,"name":"longitud","key":"longitud","attributeType":"client","type":"string","clientZoneVisible":true},{"id":16,"name":"instalador","key":"instalador","attributeType":"client","type":"string","clientZoneVisible":true},{"id":17,"name":"creado por","key":"creadoPor","attributeType":"client","type":"string","clientZoneVisible":true},{"id":21,"name":"Chat de CallBell","key":"chatDeCallbell","attributeType":"client","type":"string","clientZoneVisible":false},{"id":22,"name":"uuid","key":"uuid","attributeType":"client","type":"string","clientZoneVisible":false},{"id":23,"name":"zona","key":"zona","attributeType":"client","type":"enum","clientZoneVisible":true},{"id":29,"name":"Stripe Customer ID","key":"stripeCustomerId","attributeType":"client","type":"string","clientZoneVisible":true},{"id":30,"name":"Clabe Interbancaria","key":"clabeInterbancaria","attributeType":"client","type":"string","clientZoneVisible":true},{"id":31,"name":"RUTA DE COBRANZA","key":"rutaDeCobranza","attributeType":"client","type":"enum","clientZoneVisible":true},{"id":35,"name":"Site","key":"site","attributeType":"client","type":"string","clientZoneVisible":true},{"id":36,"name":"Antena/Sectorial","key":"antenaSectorial","attributeType":"client","type":"string","clientZoneVisible":true},{"id":37,"name":"Password Antena Cliente","key":"passwordAntenaCliente","attributeType":"client","type":"string","clientZoneVisible":false}]
|
|
||||||
|
|
||||||
// Verificar si se obtuvieron los atributos
|
|
||||||
if ($customAttributes && is_array($customAttributes)) {
|
|
||||||
foreach ($customAttributes as $attribute) {
|
|
||||||
// Verificar si 'name' contiene la palabra 'passwordAntenaCliente' sin distinguir mayúsculas y minúsculas
|
|
||||||
if (isset($attribute['key']) && stripos($attribute['key'], 'passwordAntenaCliente') !== false) {
|
|
||||||
$this->logger->info("ID correspondiente a 'passwordAntenaCliente': " . $attribute['id'] . PHP_EOL);
|
|
||||||
$idPasswordAntenaCliente = $attribute['id'];
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
$this->logger->info("Error al obtener los atributos personalizados." . PHP_EOL);
|
|
||||||
}
|
|
||||||
|
|
||||||
//buscar en los attributes ($jsonData) del cliente el id del atributo personalizado 'passwordAntenaCliente' si no está o si está pero está en blanco se manda llamar la función $this->notifierFacade->getVaultCredentials($clientID);
|
|
||||||
|
|
||||||
foreach ($jsonData['extraData']['entity']['attributes'] as $attribute) {
|
|
||||||
if ($attribute['customAttributeId'] === $idPasswordAntenaCliente) {
|
|
||||||
$this->logger->info("El valor de passwordAntenaValue es: " . $attribute['value'] . PHP_EOL);
|
|
||||||
$passwordAntenaValue = $attribute['value'];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//si el value de passwordAntenaValue es igual a null o cadena vacía se manda llamar la función $this->notifierFacade->getVaultCredentials($clientID);
|
|
||||||
if ($passwordAntenaValue === null || $passwordAntenaValue === '') {
|
|
||||||
$password = $this->notifierFacade->getVaultCredentials($clientID);
|
|
||||||
$this->logger->info("El valor de passwordAntenaValue es null o cadena vacía, se manda llamar la función getVaultCredentials" . PHP_EOL);
|
|
||||||
$this->logger->info("El valor de password es: " . $password . PHP_EOL);
|
|
||||||
|
|
||||||
if ($this->notifierFacade->patchClientCustomAttribute($clientID, $idPasswordAntenaCliente, $password)) {
|
|
||||||
$this->logger->info("Se actualizó el atributo personalizado passwordAntenaCliente con el valor: " . $password . PHP_EOL);
|
|
||||||
} else {
|
|
||||||
$this->logger->info("No se pudo actualizar el atributo personalizado passwordAntenaCliente" . PHP_EOL);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
$this->logger->info("Ya existe un valor de passwordAntenaValue: " . $passwordAntenaValue . PHP_EOL);
|
|
||||||
}
|
|
||||||
|
|
||||||
//ejemplo de json_data: {"uuid":"17e043a7-03b5-4312-ab81-a7818124a77e","changeType":"edit","entity":"client","entityId":"158","eventName":"client.edit","extraData":{"entity":{"id":158,"userIdent":null,"previousIsp":null,"isLead":false,"clientType":1,"companyName":null,"companyRegistrationNumber":null,"companyTaxId":null,"companyWebsite":null,"street1":"23 San Luis","street2":null,"city":"Dolores Hidalgo Cuna de la Independencia Nacional","countryId":173,"stateId":null,"zipCode":"37804","fullAddress":"San Luis 23, Guadalupe, Dolores Hidalgo Cuna de la Independencia Nacional, Gto., M\u00e9xico","invoiceStreet1":null,"invoiceStreet2":null,"invoiceCity":null,"invoiceStateId":null,"invoiceCountryId":null,"invoiceZipCode":null,"invoiceAddressSameAsContact":true,"note":null,"sendInvoiceByPost":null,"invoiceMaturityDays":null,"stopServiceDue":null,"stopServiceDueDays":null,"organizationId":1,"tax1Id":null,"tax2Id":null,"tax3Id":null,"registrationDate":"2025-01-06T00:00:00-0600","leadConvertedAt":"2025-02-09T03:15:49-0600","companyContactFirstName":null,"companyContactLastName":null,"isActive":false,"firstName":"Luis","lastName":"Guti\u00e9rrez","username":null,"contacts":[{"id":162,"clientId":158,"email":null,"phone":null,"name":null,"isBilling":true,"isContact":true,"types":[{"id":1,"name":"Billing"},{"id":2,"name":"General"}]}],"attributes":[],"accountBalance":0,"accountCredit":0,"accountOutstanding":0,"currencyCode":"MXN","organizationName":"SIIP Pruebas","bankAccounts":[],"tags":[],"invitationEmailSentDate":null,"avatarColor":"#2196f3","addressGpsLat":21.153272,"addressGpsLon":-100.9134508,"isArchived":false,"generateProformaInvoices":null,"usesProforma":false,"hasOverdueInvoice":false,"hasOutage":false,"hasSuspendedService":false,"hasServiceWithoutDevices":false,"referral":null,"hasPaymentSubscription":false,"hasAutopayCreditCard":false},"entityBeforeEdit":{"id":158,"userIdent":null,"previousIsp":null,"isLead":true,"clientType":1,"companyName":null,"companyRegistrationNumber":null,"companyTaxId":null,"companyWebsite":null,"street1":"23 San Luis","street2":null,"city":"Dolores Hidalgo Cuna de la Independencia Nacional","countryId":173,"stateId":null,"zipCode":"37804","fullAddress":"San Luis 23, Guadalupe, Dolores Hidalgo Cuna de la Independencia Nacional, Gto., M\u00e9xico","invoiceStreet1":null,"invoiceStreet2":null,"invoiceCity":null,"invoiceStateId":null,"invoiceCountryId":null,"invoiceZipCode":null,"invoiceAddressSameAsContact":true,"note":null,"sendInvoiceByPost":null,"invoiceMaturityDays":null,"stopServiceDue":null,"stopServiceDueDays":null,"organizationId":1,"tax1Id":null,"tax2Id":null,"tax3Id":null,"registrationDate":"2025-01-06T00:00:00-0600","leadConvertedAt":null,"companyContactFirstName":null,"companyContactLastName":null,"isActive":false,"firstName":"Luis","lastName":"Guti\u00e9rrez","username":null,"contacts":[{"id":162,"clientId":158,"email":null,"phone":null,"name":null,"isBilling":true,"isContact":true,"types":[{"id":1,"name":"Billing"},{"id":2,"name":"General"}]}],"attributes":[],"accountBalance":0,"accountCredit":0,"accountOutstanding":0,"currencyCode":"MXN","organizationName":"SIIP Pruebas","bankAccounts":[],"tags":[],"invitationEmailSentDate":null,"avatarColor":"#2196f3","addressGpsLat":21.153272,"addressGpsLon":-100.9134508,"isArchived":false,"generateProformaInvoices":null,"usesProforma":false,"hasOverdueInvoice":false,"hasOutage":false,"hasSuspendedService":false,"hasServiceWithoutDevices":false,"referral":null,"hasPaymentSubscription":false,"hasAutopayCreditCard":false}}}
|
//ejemplo de json_data: {"uuid":"17e043a7-03b5-4312-ab81-a7818124a77e","changeType":"edit","entity":"client","entityId":"158","eventName":"client.edit","extraData":{"entity":{"id":158,"userIdent":null,"previousIsp":null,"isLead":false,"clientType":1,"companyName":null,"companyRegistrationNumber":null,"companyTaxId":null,"companyWebsite":null,"street1":"23 San Luis","street2":null,"city":"Dolores Hidalgo Cuna de la Independencia Nacional","countryId":173,"stateId":null,"zipCode":"37804","fullAddress":"San Luis 23, Guadalupe, Dolores Hidalgo Cuna de la Independencia Nacional, Gto., M\u00e9xico","invoiceStreet1":null,"invoiceStreet2":null,"invoiceCity":null,"invoiceStateId":null,"invoiceCountryId":null,"invoiceZipCode":null,"invoiceAddressSameAsContact":true,"note":null,"sendInvoiceByPost":null,"invoiceMaturityDays":null,"stopServiceDue":null,"stopServiceDueDays":null,"organizationId":1,"tax1Id":null,"tax2Id":null,"tax3Id":null,"registrationDate":"2025-01-06T00:00:00-0600","leadConvertedAt":"2025-02-09T03:15:49-0600","companyContactFirstName":null,"companyContactLastName":null,"isActive":false,"firstName":"Luis","lastName":"Guti\u00e9rrez","username":null,"contacts":[{"id":162,"clientId":158,"email":null,"phone":null,"name":null,"isBilling":true,"isContact":true,"types":[{"id":1,"name":"Billing"},{"id":2,"name":"General"}]}],"attributes":[],"accountBalance":0,"accountCredit":0,"accountOutstanding":0,"currencyCode":"MXN","organizationName":"SIIP Pruebas","bankAccounts":[],"tags":[],"invitationEmailSentDate":null,"avatarColor":"#2196f3","addressGpsLat":21.153272,"addressGpsLon":-100.9134508,"isArchived":false,"generateProformaInvoices":null,"usesProforma":false,"hasOverdueInvoice":false,"hasOutage":false,"hasSuspendedService":false,"hasServiceWithoutDevices":false,"referral":null,"hasPaymentSubscription":false,"hasAutopayCreditCard":false},"entityBeforeEdit":{"id":158,"userIdent":null,"previousIsp":null,"isLead":true,"clientType":1,"companyName":null,"companyRegistrationNumber":null,"companyTaxId":null,"companyWebsite":null,"street1":"23 San Luis","street2":null,"city":"Dolores Hidalgo Cuna de la Independencia Nacional","countryId":173,"stateId":null,"zipCode":"37804","fullAddress":"San Luis 23, Guadalupe, Dolores Hidalgo Cuna de la Independencia Nacional, Gto., M\u00e9xico","invoiceStreet1":null,"invoiceStreet2":null,"invoiceCity":null,"invoiceStateId":null,"invoiceCountryId":null,"invoiceZipCode":null,"invoiceAddressSameAsContact":true,"note":null,"sendInvoiceByPost":null,"invoiceMaturityDays":null,"stopServiceDue":null,"stopServiceDueDays":null,"organizationId":1,"tax1Id":null,"tax2Id":null,"tax3Id":null,"registrationDate":"2025-01-06T00:00:00-0600","leadConvertedAt":null,"companyContactFirstName":null,"companyContactLastName":null,"isActive":false,"firstName":"Luis","lastName":"Guti\u00e9rrez","username":null,"contacts":[{"id":162,"clientId":158,"email":null,"phone":null,"name":null,"isBilling":true,"isContact":true,"types":[{"id":1,"name":"Billing"},{"id":2,"name":"General"}]}],"attributes":[],"accountBalance":0,"accountCredit":0,"accountOutstanding":0,"currencyCode":"MXN","organizationName":"SIIP Pruebas","bankAccounts":[],"tags":[],"invitationEmailSentDate":null,"avatarColor":"#2196f3","addressGpsLat":21.153272,"addressGpsLon":-100.9134508,"isArchived":false,"generateProformaInvoices":null,"usesProforma":false,"hasOverdueInvoice":false,"hasOutage":false,"hasSuspendedService":false,"hasServiceWithoutDevices":false,"referral":null,"hasPaymentSubscription":false,"hasAutopayCreditCard":false}}}
|
||||||
|
|
||||||
|
|
||||||
// Validar que 'extraData' existe y contiene las claves necesarias
|
// Validar que 'extraData' existe y contiene las claves necesarias
|
||||||
if (
|
if (
|
||||||
@ -424,30 +356,31 @@ class Plugin
|
|||||||
isset($jsonData['extraData']['entity'])
|
isset($jsonData['extraData']['entity'])
|
||||||
) {
|
) {
|
||||||
$entityBeforeEdit = $jsonData['extraData']['entityBeforeEdit'];
|
$entityBeforeEdit = $jsonData['extraData']['entityBeforeEdit'];
|
||||||
$entity = $jsonData['extraData']['entity'];
|
$entity = $jsonData['extraData']['entity'];
|
||||||
|
|
||||||
//$this->logger->debug('Validando claves dentro de entityBeforeEdit y entity');
|
$this->logger->debug('Validando claves dentro de entityBeforeEdit y entity');
|
||||||
|
|
||||||
// Validar si 'isLead' esta en true en entityBeforeEdit y en false en entity
|
// Validar si 'isLead' esta en true en entityBeforeEdit y en false en entity
|
||||||
if (array_key_exists('isLead', $entityBeforeEdit) && array_key_exists('isLead', $entity)) {
|
if (array_key_exists('isLead', $entityBeforeEdit) && array_key_exists('isLead', $entity)) {
|
||||||
//$this->logger->debug('Los datos entityBeforeEdit y entity contienen el campo isLead');
|
$this->logger->debug('Los datos entityBeforeEdit y entity contienen el campo isLead');
|
||||||
|
|
||||||
$isLeadBefore = $entityBeforeEdit['isLead'];
|
$isLeadBefore = $entityBeforeEdit['isLead'];
|
||||||
$isLeadAfter = $entity['isLead'];
|
$isLeadAfter = $entity['isLead'];
|
||||||
|
|
||||||
// Comprobar si 'isLead' cambió de true a false
|
// Comprobar si 'isLead' cambió de true a false
|
||||||
if ($isLeadBefore === true && $isLeadAfter === false) {
|
if ($isLeadBefore === true && $isLeadAfter === false) {
|
||||||
$this->logger->debug('El cliente cambió de potencial a cliente');
|
$this->logger->debug('El cliente cambió de potencial a cliente');
|
||||||
//$this->pluginNotifierFacade->createStripeClient($notification); //Se comenta esta línea para que no se cree el cliente en Stripe al convertir el lead a cliente, ya que se hará al agregar la etiqueta 'CREAR CLABE STRIPE'
|
$this->pluginNotifierFacade->createStripeClient($notification);
|
||||||
} else {
|
} else {
|
||||||
$this->logger->debug('El cliente no cambió de potencial a cliente');
|
$this->logger->debug('El cliente no cambió de potencial a cliente');
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
$this->logger->warning('El campo isLead no existe en entityBeforeEdit o entity');
|
$this->logger->warning('El campo isLead no existe en entityBeforeEdit o entity');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// buscar si existe la etiqueta 'STRIPE' en entity pero no en entityBeforeEdit
|
// buscar si existe la etiqueta 'STRIPE' en entity pero no en entityBeforeEdit
|
||||||
$tags = $jsonData['extraData']['entity']['tags'];
|
$tags = $jsonData['extraData']['entity']['tags'];
|
||||||
$tagsBefore = $jsonData['extraData']['entityBeforeEdit']['tags'];
|
$tagsBefore = $jsonData['extraData']['entityBeforeEdit']['tags'];
|
||||||
|
|
||||||
$this->logger->debug('Validando claves dentro de entity y entityBeforeEdit');
|
$this->logger->debug('Validando claves dentro de entity y entityBeforeEdit');
|
||||||
@ -456,42 +389,46 @@ class Plugin
|
|||||||
if (array_key_exists('tags', $jsonData['extraData']['entity']) && array_key_exists('tags', $jsonData['extraData']['entityBeforeEdit'])) {
|
if (array_key_exists('tags', $jsonData['extraData']['entity']) && array_key_exists('tags', $jsonData['extraData']['entityBeforeEdit'])) {
|
||||||
$this->logger->debug('Los datos entity y entityBeforeEdit contienen el campo tags');
|
$this->logger->debug('Los datos entity y entityBeforeEdit contienen el campo tags');
|
||||||
|
|
||||||
$tags = $jsonData['extraData']['entity']['tags'];
|
$tags = $jsonData['extraData']['entity']['tags'];
|
||||||
$tagsBefore = $jsonData['extraData']['entityBeforeEdit']['tags'];
|
$tagsBefore = $jsonData['extraData']['entityBeforeEdit']['tags'];
|
||||||
|
|
||||||
$this->logger->debug('Validando si la etiqueta STRIPE existe en entity pero no en entityBeforeEdit');
|
$this->logger->debug('Validando si la etiqueta STRIPE existe en entity pero no en entityBeforeEdit');
|
||||||
|
|
||||||
// Comprobar si la etiqueta 'CREAR CLABE STRIPE' existe en 'tags' pero no en 'tagsBefore'
|
// Comprobar si la etiqueta 'STRIPE' existe en 'tags' pero no en 'tagsBefore'
|
||||||
$stripeTagExists = false;
|
$stripeTagExists = false;
|
||||||
$stripeTagExistsBefore = false;
|
$stripeTagExistsBefore = false;
|
||||||
foreach ($tags as $tag) {
|
foreach ($tags as $tag) {
|
||||||
if ($tag['name'] === 'CREAR CLABE STRIPE') {
|
if ($tag['name'] === 'CREARCLABESTRIPE') {
|
||||||
$stripeTagExists = true;
|
$stripeTagExists = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
foreach ($tagsBefore as $tag) {
|
foreach ($tagsBefore as $tag) {
|
||||||
if ($tag['name'] === 'CREAR CLABE STRIPE') {
|
if ($tag['name'] === 'CREARCLABESTRIPE') {
|
||||||
$stripeTagExistsBefore = true;
|
$stripeTagExistsBefore = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Comprobar si la etiqueta 'STRIPE' existe en 'tags' pero no en 'tagsBefore'
|
// Comprobar si la etiqueta 'STRIPE' existe en 'tags' pero no en 'tagsBefore'
|
||||||
if ($stripeTagExists && ! $stripeTagExistsBefore) {
|
if ($stripeTagExists && !$stripeTagExistsBefore) {
|
||||||
$this->logger->debug('La etiqueta CREAR CLABE STRIPE se agregará al cliente');
|
$this->logger->debug('La etiqueta STRIPE se agregará al cliente');
|
||||||
$this->pluginNotifierFacade->createStripeClient($notification, true);
|
$this->pluginNotifierFacade->createStripeClient($notification, true);
|
||||||
|
} else {
|
||||||
|
$this->logger->debug('La etiqueta STRIPE no se agregó al cliente');
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
$this->logger->warning('El campo tags no existe en entity o entityBeforeEdit');
|
$this->logger->warning('El campo tags no existe en entity o entityBeforeEdit');
|
||||||
}
|
}
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
$this->logger->warning('Los datos entityBeforeEdit o entity no están presentes en extraData');
|
$this->logger->warning('Los datos entityBeforeEdit o entity no están presentes en extraData');
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->notifierFacade->verifyClientActionToDo($notification);
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
$this->notifierFacade->verifyClientActionToDo($notification);
|
||||||
} else if ($notification->eventName === 'client.add') {
|
} else if ($notification->eventName === 'client.add') {
|
||||||
$this->logger->debug('Se agregó un nuevo cliente' . PHP_EOL);
|
$this->logger->debug('Se agregó un nuevo cliente' . PHP_EOL);
|
||||||
$this->logger->debug('Valor de json_data: ' . json_encode($jsonData));
|
$this->logger->debug('Valor de json_data: ' . json_encode($jsonData));
|
||||||
@ -516,56 +453,6 @@ class Plugin
|
|||||||
} else if ($notification->eventName === 'service.edit') {
|
} else if ($notification->eventName === 'service.edit') {
|
||||||
$this->logger->debug('Se editó el servicio a un cliente' . PHP_EOL);
|
$this->logger->debug('Se editó el servicio a un cliente' . PHP_EOL);
|
||||||
$this->notifierFacade->verifyServiceActionToDo($notification);
|
$this->notifierFacade->verifyServiceActionToDo($notification);
|
||||||
//ejemplo de json_data: {"uuid":"06d281ca-d78e-4f0a-a282-3a6b77d25da0","changeType":"edit","entity":"service","entityId":"155","eventName":"service.edit","extraData":{"entity":{"id":155,"prepaid":false,"clientId":171,"status":1,"name":"Basico 300","fullAddress":"Campeche 56, Dolores Hidalgo, 37800","street1":"Campeche 56","street2":null,"city":"Dolores Hidalgo","countryId":173,"stateId":null,"zipCode":"37800","note":null,"addressGpsLat":21.1572461,"addressGpsLon":-100.9377137,"servicePlanId":6,"servicePlanPeriodId":26,"price":300,"hasIndividualPrice":false,"totalPrice":300,"currencyCode":"MXN","invoiceLabel":null,"contractId":null,"contractLengthType":1,"minimumContractLengthMonths":null,"activeFrom":"2025-05-21T00:00:00-0600","activeTo":null,"contractEndDate":null,"discountType":0,"discountValue":null,"discountInvoiceLabel":"Descuento","discountFrom":null,"discountTo":null,"tax1Id":null,"tax2Id":null,"tax3Id":null,"invoicingStart":"2025-05-21T00:00:00-0600","invoicingPeriodType":1,"invoicingPeriodStartDay":1,"nextInvoicingDayAdjustment":10,"invoicingProratedSeparately":true,"invoicingSeparately":false,"sendEmailsAutomatically":null,"useCreditAutomatically":true,"servicePlanName":"Basico 300","servicePlanPrice":300,"servicePlanPeriod":1,"servicePlanType":"Internet","downloadSpeed":8,"uploadSpeed":8,"hasOutage":false,"unmsClientSiteStatus":null,"fccBlockId":null,"lastInvoicedDate":null,"unmsClientSiteId":"359cb58d-e64f-453a-890e-23d5abb4f116","attributes":[],"addressData":null,"suspensionReasonId":null,"serviceChangeRequestId":null,"setupFeePrice":null,"earlyTerminationFeePrice":null,"downloadSpeedOverride":null,"uploadSpeedOverride":null,"trafficShapingOverrideEnd":null,"trafficShapingOverrideEnabled":false,"servicePlanGroupId":null,"suspensionPeriods":[],"surcharges":[]},"entityBeforeEdit":{"id":155,"prepaid":false,"clientId":171,"status":1,"name":"Basico 300","fullAddress":"Campeche 56, Dolores Hidalgo, 37800","street1":"Campeche 56","street2":null,"city":"Dolores Hidalgo","countryId":173,"stateId":null,"zipCode":"37800","note":null,"addressGpsLat":21.1572461,"addressGpsLon":-100.9377137,"servicePlanId":6,"servicePlanPeriodId":26,"price":300,"hasIndividualPrice":false,"totalPrice":300,"currencyCode":"MXN","invoiceLabel":null,"contractId":null,"contractLengthType":1,"minimumContractLengthMonths":null,"activeFrom":"2025-05-21T00:00:00-0600","activeTo":null,"contractEndDate":null,"discountType":0,"discountValue":null,"discountInvoiceLabel":"Descuento","discountFrom":null,"discountTo":null,"tax1Id":null,"tax2Id":null,"tax3Id":null,"invoicingStart":"2025-05-21T00:00:00-0600","invoicingPeriodType":1,"invoicingPeriodStartDay":1,"nextInvoicingDayAdjustment":10,"invoicingProratedSeparately":true,"invoicingSeparately":false,"sendEmailsAutomatically":null,"useCreditAutomatically":true,"servicePlanName":"Basico 300","servicePlanPrice":300,"servicePlanPeriod":1,"servicePlanType":"Internet","downloadSpeed":8,"uploadSpeed":8,"hasOutage":false,"unmsClientSiteStatus":null,"fccBlockId":null,"lastInvoicedDate":null,"unmsClientSiteId":"359cb58d-e64f-453a-890e-23d5abb4f116","attributes":[],"addressData":null,"suspensionReasonId":null,"serviceChangeRequestId":null,"setupFeePrice":null,"earlyTerminationFeePrice":null,"downloadSpeedOverride":null,"uploadSpeedOverride":null,"trafficShapingOverrideEnd":null,"trafficShapingOverrideEnabled":false,"servicePlanGroupId":null,"suspensionPeriods":[],"surcharges":[]}}}
|
|
||||||
//obtener el clientID y asginarlo a la variable $clientID
|
|
||||||
$clientID = $jsonData['extraData']['entity']['clientId'];
|
|
||||||
$this->ucrmApi = UcrmApi::create();
|
|
||||||
$customAttributes = $this->ucrmApi->get('custom-attributes/', ['attributeType' => 'client']); //Obtener los atributos del sistema que estén vinculados a la entidad "cliente"
|
|
||||||
//$this->logger->info("result del custom Attributes: " . json_encode($customAttributes) . PHP_EOL);
|
|
||||||
|
|
||||||
$idPasswordAntenaCliente = null;
|
|
||||||
$passwordAntenaValue = null;
|
|
||||||
|
|
||||||
//ejemplo de $customAttributes: [{"id":1,"name":"ip","key":"ip","attributeType":"client","type":"string","clientZoneVisible":false},{"id":2,"name":"ubntpass","key":"ubntpass","attributeType":"client","type":"string","clientZoneVisible":false},{"id":3,"name":"adminpass","key":"adminpass","attributeType":"client","type":"string","clientZoneVisible":true},{"id":4,"name":"ssid","key":"ssid","attributeType":"client","type":"string","clientZoneVisible":true},{"id":5,"name":"clavessid","key":"clavessid","attributeType":"client","type":"string","clientZoneVisible":true},{"id":6,"name":"clave","key":"clave","attributeType":"client","type":"string","clientZoneVisible":true},{"id":11,"name":"latitud","key":"latitud","attributeType":"client","type":"string","clientZoneVisible":true},{"id":12,"name":"longitud","key":"longitud","attributeType":"client","type":"string","clientZoneVisible":true},{"id":16,"name":"instalador","key":"instalador","attributeType":"client","type":"string","clientZoneVisible":true},{"id":17,"name":"creado por","key":"creadoPor","attributeType":"client","type":"string","clientZoneVisible":true},{"id":21,"name":"Chat de CallBell","key":"chatDeCallbell","attributeType":"client","type":"string","clientZoneVisible":false},{"id":22,"name":"uuid","key":"uuid","attributeType":"client","type":"string","clientZoneVisible":false},{"id":23,"name":"zona","key":"zona","attributeType":"client","type":"enum","clientZoneVisible":true},{"id":29,"name":"Stripe Customer ID","key":"stripeCustomerId","attributeType":"client","type":"string","clientZoneVisible":true},{"id":30,"name":"Clabe Interbancaria","key":"clabeInterbancaria","attributeType":"client","type":"string","clientZoneVisible":true},{"id":31,"name":"RUTA DE COBRANZA","key":"rutaDeCobranza","attributeType":"client","type":"enum","clientZoneVisible":true},{"id":35,"name":"Site","key":"site","attributeType":"client","type":"string","clientZoneVisible":true},{"id":36,"name":"Antena/Sectorial","key":"antenaSectorial","attributeType":"client","type":"string","clientZoneVisible":true},{"id":37,"name":"Password Antena Cliente","key":"passwordAntenaCliente","attributeType":"client","type":"string","clientZoneVisible":false}]
|
|
||||||
|
|
||||||
// Verificar si se obtuvieron los atributos
|
|
||||||
if ($customAttributes && is_array($customAttributes)) {
|
|
||||||
foreach ($customAttributes as $attribute) {
|
|
||||||
// Verificar si 'name' contiene la palabra 'passwordAntenaCliente' sin distinguir mayúsculas y minúsculas
|
|
||||||
if (isset($attribute['key']) && stripos($attribute['key'], 'passwordAntenaCliente') !== false) {
|
|
||||||
$this->logger->info("ID correspondiente a 'passwordAntenaCliente': " . $attribute['id'] . PHP_EOL);
|
|
||||||
$idPasswordAntenaCliente = $attribute['id'];
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
$this->logger->info("Error al obtener los atributos personalizados." . PHP_EOL);
|
|
||||||
}
|
|
||||||
|
|
||||||
//buscar en los attributes ($jsonData) del cliente el id del atributo personalizado 'passwordAntenaCliente' si no está o si está pero está en blanco se manda llamar la función $this->notifierFacade->getVaultCredentials($clientID);
|
|
||||||
|
|
||||||
foreach ($jsonData['extraData']['entity']['attributes'] as $attribute) {
|
|
||||||
if ($attribute['customAttributeId'] === $idPasswordAntenaCliente) {
|
|
||||||
$this->logger->info("El valor de passwordAntenaValue es: " . $attribute['value'] . PHP_EOL);
|
|
||||||
$passwordAntenaValue = $attribute['value'];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//si el value de passwordAntenaValue es igual a null o cadena vacía se manda llamar la función $this->notifierFacade->getVaultCredentials($clientID);
|
|
||||||
if ($passwordAntenaValue === null || $passwordAntenaValue === '') {
|
|
||||||
$password = $this->notifierFacade->getVaultCredentials($clientID);
|
|
||||||
$this->logger->info("El valor de passwordAntenaValue es null o cadena vacía, se manda llamar la función getVaultCredentials" . PHP_EOL);
|
|
||||||
$this->logger->info("El valor de password es: " . $password . PHP_EOL);
|
|
||||||
|
|
||||||
if ($this->notifierFacade->patchClientCustomAttribute($clientID, $idPasswordAntenaCliente, $password)) {
|
|
||||||
$this->logger->info("Se actualizó el atributo personalizado passwordAntenaCliente con el valor: " . $password . PHP_EOL);
|
|
||||||
} else {
|
|
||||||
$this->logger->info("No se pudo actualizar el atributo personalizado passwordAntenaCliente" . PHP_EOL);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
$this->logger->info("Ya existe un valor de passwordAntenaValue: " . $passwordAntenaValue . PHP_EOL);
|
|
||||||
}
|
|
||||||
|
|
||||||
} else if ($notification->eventName === 'service.suspend') {
|
} else if ($notification->eventName === 'service.suspend') {
|
||||||
$this->logger->debug('Se suspendió el servicio a un cliente' . PHP_EOL);
|
$this->logger->debug('Se suspendió el servicio a un cliente' . PHP_EOL);
|
||||||
$this->notifierFacade->verifyServiceActionToDo($notification);
|
$this->notifierFacade->verifyServiceActionToDo($notification);
|
||||||
@ -607,21 +494,28 @@ class Plugin
|
|||||||
$this->notifierFacade->verifyInvoiceActionToDo($notification);
|
$this->notifierFacade->verifyInvoiceActionToDo($notification);
|
||||||
} else if ($notification->eventName === 'job.add') {
|
} else if ($notification->eventName === 'job.add') {
|
||||||
$this->logger->debug('Se ha agregado un nuevo trabajo' . PHP_EOL);
|
$this->logger->debug('Se ha agregado un nuevo trabajo' . PHP_EOL);
|
||||||
$this->logger->debug('Valor de json_data: ' . json_encode($jsonData));
|
|
||||||
//Ejemplo de json_data: {"uuid":"434b3da0-984a-4358-a1b6-2a4418bacc49","changeType":"insert","entity":"job","entityId":"38","eventName":"job.add","extraData":{"entity":{"id":38,"title":"Servicio","description":"Revisar Router","assignedUserId":null,"clientId":2,"date":null,"duration":60,"status":0,"address":"31 Chiapas, Dolores Hidalgo Cuna de la Independencia Nacional, 37800, Mexico","gpsLat":null,"gpsLon":null,"attachments":[],"tasks":[]},"entityBeforeEdit":null}}
|
|
||||||
//Extraer el valor de title en una variable y concatenarle como prefijo la cadena "[SINENVIONOTIFICACION]" por ejemplo: "[NOTIFICACION-PENDIENTE]Servicio"
|
|
||||||
$title = $jsonData['extraData']['entity']['title'];
|
|
||||||
$title = '[NOTIFICACION-PENDIENTE]' . $title;
|
|
||||||
$this->ucrmApi = UcrmApi::create();
|
|
||||||
$responsePatch = $this->ucrmApi->patch('scheduling/jobs/' . $jsonData['entityId'], [
|
|
||||||
'title' => $title,
|
|
||||||
]);
|
|
||||||
|
|
||||||
$this->logger->debug('Respuesta de la API al agregar el trabajo: ' . json_encode($responsePatch) . PHP_EOL);
|
|
||||||
|
// Verificar que existen tanto 'assignedUserId' como 'entity'
|
||||||
|
if (isset($jsonData['extraData']['entity']['assignedUserId'])) {
|
||||||
|
$this->logger->debug('El campo assignedUserId existe en los datos del evento');
|
||||||
|
$assignedUserId = $jsonData['extraData']['entity']['assignedUserId'];
|
||||||
|
|
||||||
|
// Comprobar si 'isLead' es null
|
||||||
|
if ($assignedUserId === null) {
|
||||||
|
$this->logger->debug('El campo assignedUserId es null');
|
||||||
|
$this->pluginNotifierFacade->createStripeClient($notification);
|
||||||
|
} else {
|
||||||
|
$this->logger->debug('El campo assignedUserId no es null');
|
||||||
|
$this->notifierFacade->verifyJobActionToDo($notification);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
$this->logger->warning('El campo assignedUserId no existe en los datos del evento');
|
||||||
|
}
|
||||||
|
|
||||||
} else if ($notification->eventName === 'job.edit') {
|
} else if ($notification->eventName === 'job.edit') {
|
||||||
$this->logger->debug('Se actualiza un trabajo' . PHP_EOL);
|
$this->logger->debug('Se actualiza un trabajo' . PHP_EOL);
|
||||||
// $this->logger->debug('Valor de json_data: ' . json_encode($jsonData));
|
$this->logger->debug('Valor de json_data: ' . json_encode($jsonData));
|
||||||
|
|
||||||
// Validar que 'extraData' existe y contiene las claves necesarias
|
// Validar que 'extraData' existe y contiene las claves necesarias
|
||||||
if (
|
if (
|
||||||
@ -629,54 +523,39 @@ class Plugin
|
|||||||
isset($jsonData['extraData']['entity'])
|
isset($jsonData['extraData']['entity'])
|
||||||
) {
|
) {
|
||||||
$entityBeforeEdit = $jsonData['extraData']['entityBeforeEdit'];
|
$entityBeforeEdit = $jsonData['extraData']['entityBeforeEdit'];
|
||||||
$entity = $jsonData['extraData']['entity'];
|
$entity = $jsonData['extraData']['entity'];
|
||||||
|
|
||||||
$this->logger->debug('Validando claves dentro de entityBeforeEdit y entity');
|
$this->logger->debug('Validando claves dentro de entityBeforeEdit y entity');
|
||||||
|
|
||||||
// Validar que 'assignedUserId' existe en ambas entidades
|
// Validar que 'assignedUserId' existe en ambas entidades
|
||||||
if (array_key_exists('assignedUserId', $entityBeforeEdit) && array_key_exists('assignedUserId', $entity)) {
|
if (array_key_exists('assignedUserId', $entityBeforeEdit) && array_key_exists('assignedUserId', $entity)) {
|
||||||
// $this->logger->debug('Los datos entityBeforeEdit y entity contienen el campo assignedUserId');
|
$this->logger->debug('Los datos entityBeforeEdit y entity contienen el campo assignedUserId');
|
||||||
|
|
||||||
$assignedUserIdBefore = $entityBeforeEdit['assignedUserId'];
|
$assignedUserIdBefore = $entityBeforeEdit['assignedUserId'];
|
||||||
$assignedUserIdAfter = $entity['assignedUserId'];
|
$assignedUserIdAfter = $entity['assignedUserId'];
|
||||||
$dateBefore = $entityBeforeEdit['date'];
|
$dateBefore = $entityBeforeEdit['date'];
|
||||||
$dateAfter = $entity['date'];
|
$dateAfter = $entity['date'];
|
||||||
$statusBefore = $entityBeforeEdit['status'];
|
$statusBefore = $entityBeforeEdit['status'];
|
||||||
$statusAfter = $entity['status'];
|
$statusAfter = $entity['status'];
|
||||||
$title = $entityBeforeEdit['title'];
|
|
||||||
$pendingPrefix = '[NOTIFICACION-PENDIENTE]'; // Prefijo para trabajos pendientes de notificación
|
|
||||||
$currentTitle = $entity['title'] ?? ''; // Obtener el título actual
|
|
||||||
|
|
||||||
//Valores de status y su significado: 0 = abierto, 1= En curso, 2 = Cerrado
|
// Comprobar si 'assignedUserId' cambió
|
||||||
|
if ($assignedUserIdBefore === null && $assignedUserIdAfter != null) { //Si el campo "assignedUserId" cambió de null a un valor
|
||||||
if ($statusAfter == 1) {
|
$this->logger->debug('El instalador cambió de null a un valor');
|
||||||
// Comprobar si 'assignedUserId' cambió
|
$this->notifierFacade->verifyJobActionToDo($jsonData); // Se envía notificación de trabajo asignado
|
||||||
// if (($assignedUserIdBefore === null && $assignedUserIdAfter != null) || ($statusBefore == 0 && $statusAfter == 1)) { //Si el campo "assignedUserId" cambió de null a un valor
|
} else if (($assignedUserIdBefore != null && $assignedUserIdAfter != $assignedUserIdBefore) && ($dateBefore === $dateAfter)) {//Si el campo "assignedUserId" cambió de un valor a otro y la fecha no cambió
|
||||||
// $this->logger->debug('El instalador cambió de null a un valor');
|
$this->logger->debug('El instalador cambió y la fecha no cambió');
|
||||||
|
$this->notifierFacade->verifyJobActionToDo($jsonData, false, true); // Se envía notificación de trabajo reasignado
|
||||||
// $this->notifierFacade->verifyJobActionToDo($jsonData); // Se envía notificación de trabajo asignado
|
} else if (($assignedUserIdBefore != null && $assignedUserIdBefore === $assignedUserIdAfter) && ($dateBefore != $dateAfter)) {//Si el campo "assignedUserId" no cambió y la fecha cambió
|
||||||
// }
|
$this->logger->debug('El instalador no cambió y la fecha sí cambió');
|
||||||
|
$this->notifierFacade->verifyJobActionToDo($jsonData, true, false); // Se envía notificación de reprogramación de trabajo
|
||||||
//Si el campo status cambió de 0 a 1 y title comienza con el prefijo [NOTIFICACION-PENDIENTE]
|
} else if (($assignedUserIdBefore != null && $assignedUserIdAfter != $assignedUserIdBefore) && ($dateBefore != $dateAfter)) {
|
||||||
if (($statusBefore == 0 && $statusAfter == 1) && strpos($currentTitle, $pendingPrefix) !== false) { // Se envía notificación de trabajo asignado
|
$this->logger->debug('El instalador cambió y la fecha sí cambió');
|
||||||
$this->logger->debug('El instalador cambió de null a un valor');
|
$this->notifierFacade->verifyJobActionToDo($jsonData, true, true); // Se envía notificación de trabajo reasignado
|
||||||
$this->notifierFacade->verifyJobActionToDo($jsonData, false, false);
|
} else if ($assignedUserIdBefore != null && $assignedUserIdAfter === null) { //Si el campo "assignedUserId" cambió de un valor a null
|
||||||
} else if (($assignedUserIdBefore != null && $assignedUserIdAfter != $assignedUserIdBefore) && ($dateBefore === $dateAfter)) { //Si el campo "assignedUserId" cambió de un valor a otro y la fecha no cambió
|
$this->logger->debug('El instalador cambió de un valor a null');
|
||||||
$this->logger->debug('No hay reprogramación de trabajo pero si hay cambio de instalador');
|
$this->notifierFacade->verifyJobActionToDo($jsonData, null, true); // Se envía notificación de trabajo desasignado
|
||||||
$this->notifierFacade->verifyJobActionToDo($jsonData, false, true); // Se envía notificación de trabajo reasignado
|
} else {
|
||||||
} else if (($assignedUserIdBefore != null && $assignedUserIdBefore === $assignedUserIdAfter) && ($dateBefore != $dateAfter)) { //Si el campo "assignedUserId" no cambió y la fecha cambió
|
$this->logger->debug('No hubo cambio en el instalador ni en la fecha');
|
||||||
$this->logger->debug('Se reprogramó el trabajo pero no hubo cambio de instalador');
|
|
||||||
$this->notifierFacade->verifyJobActionToDo($jsonData, true, false); // Se envía notificación de reprogramación de trabajo
|
|
||||||
} else if (($assignedUserIdBefore != null && $assignedUserIdAfter != $assignedUserIdBefore) && ($dateBefore != $dateAfter)) {
|
|
||||||
$this->logger->debug('Se reprogramó el trabajo y hubo cambio de instalador');
|
|
||||||
$this->notifierFacade->verifyJobActionToDo($jsonData, true, true); // Se envía notificación de trabajo reasignado
|
|
||||||
} else if ($assignedUserIdBefore != null && $assignedUserIdAfter === null) { //Si el campo "assignedUserId" cambió de un valor a null
|
|
||||||
$this->logger->debug('El instalador cambió de un valor a null');
|
|
||||||
$this->notifierFacade->verifyJobActionToDo($jsonData, null, true); // Se envía notificación de trabajo desasignado
|
|
||||||
} else {
|
|
||||||
$this->logger->debug('No hubo cambio en el instalador ni en la fecha');
|
|
||||||
//$this->notifierFacade->verifyJobActionToDo($jsonData); // Se envía notificación de trabajo asignado
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
@ -688,6 +567,8 @@ class Plugin
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
//$this->notifierFacade->update($notification);
|
//$this->notifierFacade->update($notification);
|
||||||
} catch (TwilioException $exception) {
|
} catch (TwilioException $exception) {
|
||||||
$this->logger->error($exception->getMessage());
|
$this->logger->error($exception->getMessage());
|
||||||
@ -696,4 +577,4 @@ class Plugin
|
|||||||
$this->logger->info($ex->getTraceAsString());
|
$this->logger->info($ex->getTraceAsString());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1 +1 @@
|
|||||||
{"ucrmPublicUrl":"https://venus.siip.mx/crm/","ucrmLocalUrl":"http://localhost/crm/","unmsLocalUrl":"http://unms-api:8081/nms/","pluginPublicUrl":"https://venus.siip.mx/crm/_plugins/siip-whatsapp-notifications/public.php","pluginAppKey":"5dVI22XIa9NSK0tiDeiQ3SLDBa1UZVT7g5s/tJzi944Bygx89WIHH7I2/niVPiBK","pluginId":16}
|
{"ucrmPublicUrl":"https://venus.siip.mx/crm/","ucrmLocalUrl":"http://localhost/crm/","unmsLocalUrl":"http://unms:8081/nms/","pluginPublicUrl":"https://venus.siip.mx/crm/_plugins/siip-whatsapp-notifications/public.php","pluginAppKey":"5dVI22XIa9NSK0tiDeiQ3SLDBa1UZVT7g5s/tJzi944Bygx89WIHH7I2/niVPiBK","pluginId":16}
|
||||||
4
vendor/composer/installed.php
vendored
4
vendor/composer/installed.php
vendored
@ -5,7 +5,7 @@
|
|||||||
'type' => 'library',
|
'type' => 'library',
|
||||||
'install_path' => __DIR__ . '/../../',
|
'install_path' => __DIR__ . '/../../',
|
||||||
'aliases' => array(),
|
'aliases' => array(),
|
||||||
'reference' => '506615e9116829588e84ecacf5e6e28769e6dd87',
|
'reference' => '9db9febc39027c302495c041d5a28e198c035b21',
|
||||||
'name' => 'ucrm-plugins/sms-twilio',
|
'name' => 'ucrm-plugins/sms-twilio',
|
||||||
'dev' => false,
|
'dev' => false,
|
||||||
),
|
),
|
||||||
@ -307,7 +307,7 @@
|
|||||||
'type' => 'library',
|
'type' => 'library',
|
||||||
'install_path' => __DIR__ . '/../../',
|
'install_path' => __DIR__ . '/../../',
|
||||||
'aliases' => array(),
|
'aliases' => array(),
|
||||||
'reference' => '506615e9116829588e84ecacf5e6e28769e6dd87',
|
'reference' => '9db9febc39027c302495c041d5a28e198c035b21',
|
||||||
'dev_requirement' => false,
|
'dev_requirement' => false,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user