Compare commits

..

No commits in common. "3b3cd70eced76670e2aad8fbe97b422f516ab7eb" and "9e78efdf2f231a3ca70be5cac52428f77f1700cf" have entirely different histories.

8 changed files with 1024 additions and 1040 deletions

Binary file not shown.

Before

Width:  |  Height:  |  Size: 427 KiB

After

Width:  |  Height:  |  Size: 383 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 429 KiB

After

Width:  |  Height:  |  Size: 411 KiB

View File

@ -1 +1 @@
{"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,"dataInstallersWhatsApp":"{ \"instaladores\": [{\"ID\": 1015, \"nombre\": \"Daniel Peña, \"whatsapp\": 4181878106}, {\"ID\": 1020, \"nombre\": \"Angel Arvizu\", \"whatsapp\": 4123456789}, {\"ID\": 1035,\"nombre\": \"Juan Rostro, \"whatsapp\": 4198765432}] }","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,"debugMode":true,"logging_level":true,"dataInstallersWhatsApp":"{ \"instaladores\": [{\"ID\": 1015, \"nombre\": \"Daniel Peña, \"whatsapp\": 4181878106}, {\"ID\": 1020, \"nombre\": \"Angel Arvizu\", \"whatsapp\": 4123456789}, {\"ID\": 1035,\"nombre\": \"Juan Rostro, \"whatsapp\": 4198765432}] }"}

File diff suppressed because it is too large Load Diff

View File

@ -5,7 +5,7 @@
"displayName": "SIIP - Procesador de Pagos en línea con Stripe, Sincronizador de CallBell y Envío de Notificaciones y comprobantes vía WhatsApp", "displayName": "SIIP - Procesador de Pagos en línea con Stripe, Sincronizador de CallBell y Envío de Notificaciones y comprobantes vía WhatsApp",
"description": "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 vía Whatsapp a los clientes", "description": "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 vía Whatsapp a los clientes",
"url": "https://siip.mx/", "url": "https://siip.mx/",
"version": "2.5.1", "version": "2.4.9",
"unmsVersionCompliancy": { "unmsVersionCompliancy": {
"min": "2.1.0", "min": "2.1.0",
"max": null "max": null

View File

@ -54,159 +54,160 @@ abstract class AbstractOxxoOperationsFacade
/* /*
* Creates a PaymentIntent for OXXO in Stripe for a Customer * Creates a PaymentIntent for OXXO in Stripe for a Customer
*/ */
public function createOxxoPaymentIntent($event_json, $amount = null): string public function createOxxoPaymentIntent($event_json):string
{ {
$this->logger->info("Creando referencia del cliente para OXXO: " . PHP_EOL); $this->logger->info("Creando referencia del cliente para oxxo: ".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'];
$IPServer = $config['ipserver']; $IPServer = $config['ipserver'];
$tokenCRM = $config['apitoken']; $tokenCRM = $config['apitoken'];
// $this->logger->info("Datos de configuración: ".PHP_EOL);
// $this->logger->info("Stripe token: ".$StripeToken.PHP_EOL);
// $this->logger->info("IP server: ".$IPServer.PHP_EOL);
// $this->logger->info("Token CRM: ".$tokenCRM.PHP_EOL);
$baseUri = 'https://'.$IPServer.'/crm/api/v1.0/'; //endpoint de la API REST del CRM
$stripe = new \Stripe\StripeClient($StripeToken); //Token de clave privada para la API de Stripe
//$stripe = new \Stripe\StripeClient('sk_test_51OkG0REFY1WEUtgRH6UxBK5pu80Aq5Iy8EcdPnf0cOWzuVLQTpyLCd7CbPzqMsWMafZOHElCxhEHF7g8boURjWlJ00tBwE0W1M'); //Token de clave privada para la API de Stripe modo pruebas
$baseUri = 'https://' . $IPServer . '/crm/api/v1.0/';
$stripe = new \Stripe\StripeClient($StripeToken);
$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;
$clientEmail = '';
try {
$clientGuzzleHttp = new Client([ $clientGuzzleHttp = new Client([
'base_uri' => $baseUri, 'base_uri' => $baseUri,
'headers' => [ 'headers' => [
'X-Auth-App-Key' => $tokenCRM, 'X-Auth-App-Key' => $tokenCRM, // Cambia el nombre de la cabecera de autorización para el UISP CRM
'Accept' => 'application/json', 'Accept' => 'application/json', // Indica que esperamos una respuesta en formato JSON
], ],
'verify' => false, 'verify' => false,
]); ]);
$response = $clientGuzzleHttp->request('GET', "clients/" . $clientID); // Hacer la solicitud GET para obtener los datos del cliente
$response = $clientGuzzleHttp->request('GET', "clients/".$clientID);
// Obtener el cuerpo de la respuesta como JSON
$arrayClientCRM = json_decode($response->getBody()->getContents(), true); $arrayClientCRM = json_decode($response->getBody()->getContents(), true);
// Obtener stripeCustomerId // Inicializamos una variable para guardar el valor del 'stripeCustomerId'
$stripeCustomerId = null;
$clientEmail = '';
// Recorrer los atributos para encontrar el 'stripeCustomerId'
foreach ($arrayClientCRM['attributes'] as $attribute) { foreach ($arrayClientCRM['attributes'] as $attribute) {
if ($attribute['key'] === 'stripeCustomerId') { if ($attribute['key'] === 'stripeCustomerId') {
$stripeCustomerId = $attribute['value']; $stripeCustomerId = $attribute['value'];
break; break;
} }
} }
$this->logger->info("Se obtuvo el Stripe Customer ID: " . $stripeCustomerId . PHP_EOL);
// Obtener email del cliente // Recorrer los contactos
foreach ($arrayClientCRM['contacts'] as $contact) { foreach ($arrayClientCRM['contacts'] as $contact) {
if (!empty($contact['email'])) { if ($contact['email'] != '') {
$clientEmail = $contact['email']; $clientEmail = $contact['email'];
break; break;
} else { }else{
$clientEmail = 'siip8873@gmail.com '; $clientEmail = 'siip8873@gmail.com';
break;
} }
} }
// Validar y procesar el monto proporcionado $this->logger->info("Se obtuvieron los datos del cliente y Stripe Customer ID: ".$stripeCustomerId.PHP_EOL);
if ($amount !== null) {
// Extraer solo dígitos numéricos del monto
$numericAmount = preg_replace('/\D/', '', $amount);
if (empty($numericAmount)) {
$this->logger->error("Cantidad no válida proporcionada: " . $amount . PHP_EOL);
return 'cantidadnovalida'; // Retornar error si no se obtiene un valor válido
}
// Convertir el valor limpio a entero
$amount = (int) $numericAmount;
$this->logger->info("Monto proporcionado directamente (procesado): $amount " . PHP_EOL);
} else {
try {
// Obtener el monto pendiente del cliente en centavos
$amount = abs($arrayClientCRM['accountOutstanding']);
$this->logger->info("Monto pendiente del cliente (procesado): $amount " . PHP_EOL);
} catch (RequestException $e) { } catch (RequestException $e) {
$this->logger->error('Error al obtener el monto pendiente del cliente: ' . $e->getMessage() . PHP_EOL); // Manejo de errores en la petición
return 'errorobtenermontopendiente'; // Error al obtener el monto pendiente $this->logger->error("Error al obtener atributos personalizados del cliente: " . $e->getMessage().PHP_EOL);
}
} }
// Validar que el monto sea mayor a 0 antes de proceder $amount = abs($arrayClientCRM['accountOutstanding']) * 100;
if ($amount > 10) {
$amount = intval($amount * 100); //$this->logger->info("User Admin ID: " . json_encode($currentUserAdmin) . PHP_EOL);
if($amount>0){
try { try {
// Crear el PaymentIntent vinculado al cliente
$paymentIntent = $stripe->paymentIntents->create([ $paymentIntent = $stripe->paymentIntents->create([
'amount' => $amount, 'amount' => $amount, // Monto en centavos (300 MXN)
'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',
'customer' => $stripeCustomerId, 'customer' => $stripeCustomerId, // Vincular al cliente existente
'metadata' => [ 'metadata' => [
'clientId' => $clientID, 'clientId' => $clientID, // ID del cliente en UISP
'createdBy' => 'UCRM', 'createdBy' => 'UCRM',
'paymentType' => 'card.one_time', 'paymentType' => 'card.one_time',
'signedInAdminId' => $currentUserAdmin[0]['id'] 'signedInAdminId' => $currentUserAdmin[0]['id']
], ],
'payment_method_options' => [ 'payment_method_options' => [
'oxxo' => [ 'oxxo' => [
'expires_after_days' => 3, 'expires_after_days' => 3, // El voucher expira en 3 días
], ],
], ],
]); ]);
} catch (Exception $e) {
$this->logger->error('Error al crear el payment intent: ' . $e->getMessage() . PHP_EOL); // Crear un método de pago OXXO con detalles de facturación
return 'errorCreatePaymentIntent'; // Error al crear el payment intent
}
try {
$this->logger->info("Creando payment methods del voucher" . PHP_EOL);
$paymentMethod = $stripe->paymentMethods->create([ $paymentMethod = $stripe->paymentMethods->create([
'type' => 'oxxo', 'type' => 'oxxo',
'billing_details' => [ 'billing_details' => [
'name' => $arrayClientCRM['firstName'] . ' ' . $arrayClientCRM['lastName'], 'name' => $arrayClientCRM['firstName'].' '.$arrayClientCRM['lastName'], // Proporciona el nombre del cliente
'email' => $clientEmail, 'email' => $clientEmail, // Proporciona el correo del cliente
], ],
]); ]);
} catch (Exception $e) {
$this->logger->error('Error al crear el payment method: ' . $e->getMessage() . PHP_EOL);
return 'errorCreatePaymentMethod'; // Error al crear el payment method
}
try {
// Confirmar el PaymentIntent con el método de pago OXXO
$paymentIntent = $stripe->paymentIntents->confirm( $paymentIntent = $stripe->paymentIntents->confirm(
$paymentIntent->id, $paymentIntent->id,
['payment_method' => $paymentMethod->id] ['payment_method' => $paymentMethod->id]
); );
} catch (Exception $e) {
$this->logger->error('Error al confirmar el payment intent: ' . $e->getMessage() . PHP_EOL);
return 'errorConfirmPaymentIntent'; // Error al confirmar el payment intent
}
// Verificar si hay acciones pendientes (next_action)
if (!empty($paymentIntent->next_action) && isset($paymentIntent->next_action->oxxo_display_details)) { if (!empty($paymentIntent->next_action) && isset($paymentIntent->next_action->oxxo_display_details)) {
$oxxoPayment = $paymentIntent->next_action->oxxo_display_details; $oxxoPayment = $paymentIntent->next_action->oxxo_display_details;
//print_r($oxxoPayment);
// Obtener la referencia OXXO y la URL del recibo
$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); // Mostrar la referencia y la URL del recibo al cliente
$this->logger->info("URL del recibo: " . $oxxo_receipt_url . PHP_EOL); $this->logger->info("Referencia OXXO: " . $oxxo_reference.PHP_EOL);
$this->logger->info("URL del recibo: " . $oxxo_receipt_url.PHP_EOL);
return $oxxo_receipt_url; return $oxxo_receipt_url;
// echo "Referencia OXXO: " . $oxxo_reference . "\n";
// echo "URL del recibo: " . $oxxo_receipt_url . "\n";
} else { } else {
$this->logger->info("El PaymentIntent no tiene detalles de OXXO disponibles aún. " . PHP_EOL); // Manejo de error si no hay detalles de OXXO
$this->logger->info("Estado actual del PaymentIntent: " . $paymentIntent->status . PHP_EOL); // echo "El PaymentIntent no tiene detalles de OXXO disponibles aún.\n";
return 'errorPyamentIntentWithoutOxxoDetails'; // echo "Estado actual del PaymentIntent: " . $paymentIntent->status . "\n";
$this->logger->info("El PaymentIntent no tiene detalles de OXXO disponibles aún. " .PHP_EOL);
$this->logger->info("Estado actual del PaymentIntent: " . $paymentIntent->status.PHP_EOL);
return 'error';
} }
} else { } catch (Exception $e) {
$this->logger->info("Este cliente no tiene adeudos por lo tanto no se puede generar su referencia de OXXO. " . PHP_EOL); // Manejar cualquier error
//echo 'Error: ' . $e->getMessage();
$this->logger->error('Error al crear el payment intent: ' . $e->getMessage().PHP_EOL);
return 'error';
}
}else{
$this->logger->info("Este cliente no tiene adeudos por lo tanto no se puede genear su referencia de oxxo. " .PHP_EOL);
return 'errorsinadeudo'; return 'errorsinadeudo';
} }
} }
// /** // /**
// * implement in subclass with the specific messaging provider // * implement in subclass with the specific messaging provider
// * @see TwilioNotifierFacade::sendWhatsApp() // * @see TwilioNotifierFacade::sendWhatsApp()
@ -220,7 +221,7 @@ abstract class AbstractOxxoOperationsFacade
function validarEmail($email) function validarEmail($email)
{ {
$this->logger->info('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

View File

@ -132,30 +132,13 @@ class Plugin
case 'oxxo.request': case 'oxxo.request':
$this->logger->info('Evento 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($event_json->amount )) {
$this->logger->info('Valor del monto: ' . $event_json->amount . PHP_EOL);
$intentos = 0; $intentos = 0;
do { do {
if($intentos>1){
sleep(2);
}
$url = $this->pluginOxxoNotifierFacade->createOxxoPaymentIntent($event_json, $event_json->amount );
$intentos++;
} while (strpos($url, 'https') !== 0 && $intentos < 5);
} else {
$intentos = 0;
do {
if($intentos>1){
sleep(2);
}
$url = $this->pluginOxxoNotifierFacade->createOxxoPaymentIntent($event_json); $url = $this->pluginOxxoNotifierFacade->createOxxoPaymentIntent($event_json);
$intentos++; $attempts++;
} while (strpos($url, 'https') !== 0 && $intentos < 5); } while (strpos($url, 'https') !== 0 && $intentos < 5);
}
// Crear una respuesta en formato JSON // Crear una respuesta en formato JSON
// $response = [ // $response = [
// 'event' => 'response.siip', // 'event' => 'response.siip',
@ -322,7 +305,7 @@ class Plugin
} else if ($notification->eventName === 'service.postpone') { } else if ($notification->eventName === 'service.postpone') {
$this->logger->debug('Se pospuso la suspención del servicio a un cliente' . PHP_EOL); $this->logger->debug('Se pospuso la suspención del servicio a un cliente' . PHP_EOL);
$this->notifierFacade->verifyServiceActionToDo($notification); $this->notifierFacade->verifyServiceActionToDo($notification);
} else if ($notification->eventName === 'invoice.near_due') { }else if ($notification->eventName === 'invoice.near_due') {
$this->logger->debug('Factura casi por vencer' . PHP_EOL); $this->logger->debug('Factura casi por vencer' . PHP_EOL);
$this->notifierFacade->notifyOverDue($notification); $this->notifierFacade->notifyOverDue($notification);
} else if ($notification->eventName === 'invoice.overdue') { } else if ($notification->eventName === 'invoice.overdue') {
@ -340,7 +323,7 @@ class Plugin
$this->logger->debug("Account Balance: " . $accountBalance . PHP_EOL); $this->logger->debug("Account Balance: " . $accountBalance . PHP_EOL);
$this->logger->debug("Pago hecho con la factura: " . $invoiceAmountPaid . PHP_EOL); $this->logger->debug("Pago hecho con la factura: " . $invoiceAmountPaid . PHP_EOL);
$this->notifierFacade->verifyInvoiceActionToDo($notification); $this->notifierFacade->verifyInvoiceActionToDo($notification);
} else if ($notification->eventName === 'invoice.edit') { }else if($notification->eventName === 'invoice.edit'){
$this->logger->debug('Edición de Factura' . PHP_EOL); $this->logger->debug('Edición de Factura' . PHP_EOL);
$this->notifierFacade->verifyInvoiceActionToDo($notification); $this->notifierFacade->verifyInvoiceActionToDo($notification);
} }

View File

@ -5,7 +5,7 @@
'type' => 'library', 'type' => 'library',
'install_path' => __DIR__ . '/../../', 'install_path' => __DIR__ . '/../../',
'aliases' => array(), 'aliases' => array(),
'reference' => '9e78efdf2f231a3ca70be5cac52428f77f1700cf', 'reference' => '4b490c0cde49d24087b56b4ce89ec91badbc2263',
'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' => '9e78efdf2f231a3ca70be5cac52428f77f1700cf', 'reference' => '4b490c0cde49d24087b56b4ce89ec91badbc2263',
'dev_requirement' => false, 'dev_requirement' => false,
), ),
), ),