- Se agregó 'getPaymentMethodIdByName' para buscar automáticamente el ID de "Transferencia bancaria" por nombre, asegurando portabilidad entre servidores UISP. - Se implementó el manejo del webhook 'customer_cash_balance_transaction.created' para el registro automático de pagos fondeados. - Fix: Se corrigió error 422 en la API de UCRM forzando el cast de 'clientId' a integer y 'methodId' a string (GUID). - Se actualizó la documentación (README/CHANGELOG) con instrucciones de configuración de webhooks.
636 lines
34 KiB
PHP
Executable File
636 lines
34 KiB
PHP
Executable File
<?php
|
|
use GuzzleHttp\Client;
|
|
use Ubnt\UcrmPluginSdk\Service\UcrmApi;
|
|
use Ubnt\UcrmPluginSdk\Service\PluginLogManager;
|
|
// use Exception;
|
|
|
|
//version febereo 2025 funcional
|
|
require(__DIR__ . '/vendor/autoload.php');
|
|
|
|
// Establecer la zona horaria en Ciudad de México (UTC -6 o UTC -5 con horario de verano)
|
|
date_default_timezone_set('America/Mexico_City');
|
|
|
|
// Fechas en zona horaria de Ciudad de México
|
|
$startDateLocal = strtotime('2025-01-20 00:00:00'); // 20 de enero de 2025, 00:00 (hora local)
|
|
$endDateLocal = strtotime('2025-02-06 18:00:00'); // 6 de febrero de 2025, 18:00 (hora local)
|
|
// Convertir a UTC
|
|
$startDate = (new DateTime('@' . $startDateLocal))->setTimezone(new DateTimeZone('UTC'))->getTimestamp();
|
|
$endDate = (new DateTime('@' . $endDateLocal))->setTimezone(new DateTimeZone('UTC'))->getTimestamp();
|
|
|
|
$amount = 200; //Cantidad a cobrar
|
|
//$amount = intval($amount * 100); //Conversión de la cantidad a centavos, solo referencia, no usar
|
|
$customer_id_stripe = 'cus_PdXOlNaXGOxvlw'; //ID del cliente en Stripe
|
|
$clientId_CRM = 409; //ID del cliente en UISP CRM
|
|
//agregar constante de id de administrador 5472
|
|
$signedAdminId = 5472; //ID del administrador que realiza la operación
|
|
$produccion = true; //Variable para indicar si se está en modo producción o no
|
|
|
|
$clientGuzzleHttp = new Client([
|
|
'base_uri' => $baseUri,
|
|
'headers' => [
|
|
'X-Auth-App-Key' => $token,
|
|
'Accept' => 'application/json',
|
|
],
|
|
'verify' => false,
|
|
]);
|
|
|
|
if ($produccion) {
|
|
$stripe = new \Stripe\StripeClient('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'); //Token de clave privada en modo prodcucción para la API de Stripe
|
|
$baseUri = 'https://sistema.siip.mx/crm/api/v1.0/'; //endpoint de la API REST del CRM
|
|
// $token = '7adc9198-50b1-41d0-9bfa-d4946902ed89'; //Token para acceder a los recursos del CRM 2025
|
|
// $token = '079c28f5-888c-457d-bd7a-0a4202590f75'; //Token para acceder a los recursos del CRM
|
|
$token = '72VoFACForJQzveorR1sTLrXXwrnnK/oy6Bp9luwFTGC/dRdeQWNmFZqJeHuUzqK'; //Token para acceder a los recursos del CRM actualizado
|
|
} else {
|
|
$stripe = new \Stripe\StripeClient('sk_test_51OkG0REFY1WEUtgRH6UxBK5pu80Aq5Iy8EcdPnf0cOWzuVLQTpyLCd7CbPzqMsWMafZOHElCxhEHF7g8boURjWlJ00tBwE0W1M'); //Token de clave privada en modo prueba para la API de Stripe
|
|
$baseUri = 'https://venus.siip.mx/crm/api/v1.0/'; //endpoint de la API REST del CRM
|
|
// $token = '6abef18c-783d-4dd0-b530-be6e6a7bbd1d'; //Token para acceder a los recursos del CRM
|
|
$token = 'gvcnIJqXdUjneVSjhl6THLlQcYXJyIFCcwHKVba2bvIrNraanCTb5VeoWuJ0TFZ9'; //Token para acceder a los recursos del CRM actualizado
|
|
|
|
}
|
|
|
|
|
|
createPaymentIntent($stripe, $amount, $customer_id_stripe, $clientId_CRM, $signedAdminId); //Crea el PaymentIntent
|
|
|
|
|
|
//createOxxoPaymentIntent($stripe, $amount, $customer_id_stripe, $clientId_CRM); //Crea el PaymentIntent para OXXO
|
|
//cancelarPaymentIntent($stripe, $customer_id_stripe, $clientId_CRM); //Cancela el PaymentIntent
|
|
//cancelarOxxoPaymentIntent($stripe, $customer_id_stripe, $clientId_CRM); //Cancela el PaymentIntent para OXXO
|
|
|
|
|
|
//cliente GuzzleHttp para consumir API del UISP CRM
|
|
|
|
|
|
//descomentar para generar el archivo csv con los ID de los clientes a los que se les va a cancelar sus payment intents
|
|
// $archivoCsv = './PaymentIntentStripe.csv'; //ruta al archivo csv con los ID de los clientes a los que se les va a cancelar sus payment intents
|
|
|
|
// $columnaDeseada = 0; // Columna para leer del archivo csv
|
|
// $esPrimeraFila = false; // Variable de control para detectar la primera fila e ignorarla ya que son las columnas
|
|
// $ucrm_client_id;
|
|
|
|
// if (($gestor = fopen($archivoCsv, 'r')) !== false) { //Abre el archivo csv
|
|
// while (($datos = fgetcsv($gestor, 1000, ',')) !== false) { //Lee el archivo csv
|
|
// if ($esPrimeraFila) { //Ignora la primera fila
|
|
// $esPrimeraFila = false;
|
|
// continue;
|
|
// }
|
|
// $num = count($datos); //Cuenta el número de columnas
|
|
// for ($c = 0; $c < $num; $c++) { //Recorre las columnas
|
|
// sleep(2); //Espera 1 segundo
|
|
// $ucrm_client_id = $datos[$columnaDeseada]; //Obtiene el ID del cliente en UISP CRM
|
|
|
|
// //Hace la petición GET al CRM para obtener el ID del cliente en Stripe
|
|
// $response = $clientGuzzleHttp->request('GET', 'clients/' . $ucrm_client_id);
|
|
// $responseBody = json_decode($response->getBody(), true); //Decodifica el JSON de la respuesta
|
|
|
|
// //ejemplo de respuesta en formato JSON de la API del CRM: {"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","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":"chavoloco@homail.com","phone":"4181148783","name":"Tio","isBilling":false,"isContact":false,"types":[{"id":1003,"name":"WhatsNotifica"}]}],"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}],"accountBalance":700.99,"accountCredit":700.99,"accountOutstanding":0.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}
|
|
|
|
// //consutar los adeudos del cliente (accountOutstanding) y ponerlo en una variable
|
|
// $accountOutstanding = $responseBody['accountOutstanding'];
|
|
|
|
// //Consultar el nombre completo del cliente y ponerlo en una variable
|
|
// $nombreCompleto = $responseBody['firstName'] . ' ' . $responseBody['lastName'];
|
|
// print_r("Nombre del cliente: " . $nombreCompleto); //Imprime el nombre del cliente
|
|
// logMessage("Nombre del cliente: " . $nombreCompleto); //Imprime el nombre del cliente
|
|
|
|
// //Consultar los atributos del cliente en UISP CRM y obtener el ID del cliente en Stripe
|
|
// $attributes = $responseBody['attributes']; //Obtiene los atributos del cliente
|
|
// $stripeCustomerId = null; //Inicializa la variable para el ID del cliente en Stripe
|
|
// foreach ($attributes as $attribute) { //Recorre los atributos del cliente
|
|
// if ($attribute['key'] == 'stripeCustomerId') { //Busca el atributo con la clave 'stripeCustomerId'
|
|
// $stripeCustomerId = $attribute['value']; //Obtiene el valor del atributo 'stripeCustomerId'
|
|
// break; //Sale del ciclo
|
|
// }
|
|
// }
|
|
|
|
// if ($stripeCustomerId == null) { //Si no se encontró el ID del cliente en Stripe
|
|
// print_r("No se encontró el ID del cliente en Stripe" . PHP_EOL);
|
|
// logMessage("No se encontró el ID del cliente en Stripe" . PHP_EOL);
|
|
// continue; //Continúa con el siguiente cliente
|
|
// } else {
|
|
// print_r("ID del cliente en Stripe: " . $stripeCustomerId); //Imprime el ID del cliente en Stripe
|
|
// logMessage("ID del cliente en Stripe: " . $stripeCustomerId); //Imprime el ID del cliente en Stripe
|
|
// if (cancelRequiresActionPaymentIntents($stripe, $stripeCustomerId )) {
|
|
// echo "Se encontraron y cancelaron PaymentIntents en estado 'requires_action'.\n";
|
|
// logMessage("Se encontraron y cancelaron PaymentIntents en estado 'requires_action'.\n");
|
|
// } else {
|
|
// echo "No se encontraron PaymentIntents en estado 'requires_action' para este cliente.\n";
|
|
// logMessage("No se encontraron PaymentIntents en estado 'requires_action' para este cliente.\n");
|
|
// }
|
|
// $saldoFinal = getSaldoFinal($stripe, $stripeCustomerId, $startDate, $endDate); //Obtiene el saldo final del cliente
|
|
// print_r("El saldo final es: " . $saldoFinal); //Imprime el saldo final del cliente
|
|
// logMessage("El saldo final es: " . $saldoFinal); //Imprime el saldo final del cliente
|
|
// if ($saldoFinal > 0) { //Si el saldo final es mayor a 0 y el adeudo es mayor a 0 o si el saldo final es mayor a 0 y el adeudo es igual a 0
|
|
// print_r("El saldo de Stripe es $$saldoFinal y los adeudos están en $$accountOutstanding, se procede a realizar un payment Intent" . PHP_EOL); //Imprime el saldo final del cliente
|
|
// logMessage("El saldo de Stripe es $$saldoFinal y los adeudos están en $$accountOutstanding, se procede a realizar un payment Intent" .PHP_EOL); //Imprime el saldo final del cliente
|
|
// createPaymentIntent($stripe, $saldoFinal, $stripeCustomerId, $ucrm_client_id); //Crea el PaymentIntent
|
|
// } else {
|
|
// print_r("El saldo de Stripe es $$saldoFinal y los adeudos están en $$accountOutstanding, no se realizará el cobro" . PHP_EOL); //Imprime el saldo final del cliente
|
|
// logMessage("El saldo de Stripe es $$saldoFinal y los adeudos están en $$accountOutstanding, no se realizará el cobro".PHP_EOL); //Imprime el saldo final del cliente
|
|
// }
|
|
|
|
// }
|
|
|
|
|
|
// }
|
|
// }
|
|
// fclose($gestor);
|
|
// } else {
|
|
// print_r("Error al abrir el archivo CSV" . PHP_EOL);
|
|
// logMessage("Error al abrir el archivo CSV" . PHP_EOL, 'error');
|
|
// }
|
|
|
|
|
|
// function getSaldoFinal($stripe, $customerId, $startDate, $endDate)
|
|
// {
|
|
// $limit = 100; // Máximo de eventos por solicitud (Stripe permite un máximo de 100)
|
|
// $lastEventId = null; // Almacena el ID del último evento para la paginación
|
|
// $filteredEvents = []; // Arreglo para almacenar los eventos filtrados
|
|
// $saldoFinal = 0; // Inicializar el saldo final
|
|
|
|
// do {
|
|
// // Obtener los eventos de transacciones de saldo en efectivo, filtrando por fechas
|
|
// $params = [
|
|
// 'type' => 'customer_cash_balance_transaction.created',
|
|
// 'created' => [
|
|
// 'gte' => $startDate, // Mayor o igual a la fecha de inicio
|
|
// 'lte' => $endDate, // Menor o igual a la fecha de fin
|
|
// ],
|
|
// 'limit' => $limit, // Establecer el límite de eventos por solicitud
|
|
// ];
|
|
|
|
// // Si ya se ha procesado una página, agregar el parámetro de paginación
|
|
// if ($lastEventId) {
|
|
// $params['starting_after'] = $lastEventId;
|
|
// }
|
|
|
|
// // Obtener los eventos
|
|
// $events = $stripe->events->all($params);
|
|
|
|
// // Filtrar por customer ID y almacenar los eventos filtrados
|
|
// foreach ($events->data as $event) {
|
|
// $eventObject = $event->data->object;
|
|
|
|
// if (isset($eventObject->customer) && $eventObject->customer === $customerId) {
|
|
// $filteredEvents[] = $event; // Almacenar el evento filtrado
|
|
// }
|
|
// }
|
|
|
|
// // Guardar el ID del último evento para la paginación
|
|
// if (!empty($events->data)) {
|
|
// $lastEventId = end($events->data)->id;// Obtener el último ID de evento
|
|
// }
|
|
|
|
// } while (!empty($events->has_more)); // Repetir mientras haya más eventos
|
|
|
|
// // Ordenar los eventos filtrados por fecha de creación (más reciente primero)
|
|
// usort($filteredEvents, function ($a, $b) {
|
|
// return $b->created - $a->created; // Orden descendente
|
|
// });
|
|
|
|
// // Obtener el evento más reciente
|
|
// if (!empty($filteredEvents)) {
|
|
// $mostRecentEvent = $filteredEvents[0]; // El primer evento será el más reciente
|
|
// $eventObject = $mostRecentEvent->data->object;
|
|
|
|
// $netAmount = abs($eventObject->net_amount); // Valor absoluto de la cantidad en centavos
|
|
// $netAmountMXN = $netAmount / 100; // Convertir a pesos mexicanos
|
|
|
|
// // echo "Evento ID: " . $mostRecentEvent->id . "\n";
|
|
// // echo "Tipo de Evento: " . $mostRecentEvent->type . "\n";
|
|
// // echo "Fecha del Evento: " . date('Y-m-d H:i:s', $mostRecentEvent->created) . "\n";
|
|
// // echo "Cantidad en positivo: " . $netAmountMXN . " MXN\n"; // Mostrar la cantidad positiva convertida a MXN
|
|
// // echo "Saldo final: " . ($eventObject->ending_balance / 100) . " MXN\n"; // Mostrar el saldo convertido a MXN
|
|
// // echo "Detalles: " . json_encode($eventObject, JSON_PRETTY_PRINT) . "\n";
|
|
|
|
// $saldoFinal = ($eventObject->ending_balance / 100); // Asignar el saldo final
|
|
// } else {
|
|
// echo "No se encontraron eventos para el cliente especificado dentro del periodo dado.\n";
|
|
// logMessage("No se encontraron eventos para el cliente especificado dentro del periodo dado.", 'error');
|
|
// }
|
|
|
|
// return $saldoFinal;
|
|
// }
|
|
|
|
|
|
function createPaymentIntent($stripe, $amount, $customer_id_stripe, $clientId_CRM, $signedAdminId)
|
|
{
|
|
$amount = intval($amount * 100); //Conversión de la cantidad a centavos
|
|
try {
|
|
|
|
$paymentIntent = $stripe->paymentIntents->create([
|
|
'amount' => $amount, //Cantidad a cobrar
|
|
'currency' => 'mxn',
|
|
'customer' => $customer_id_stripe, //ID del cliente en Stripe
|
|
'payment_method_types' => ['customer_balance'],
|
|
'payment_method_data' => ['type' => 'customer_balance'],
|
|
'confirm' => true,
|
|
'payment_method_options' => [
|
|
'customer_balance' => [
|
|
'funding_type' => 'bank_transfer',
|
|
'bank_transfer' => ['type' => 'mx_bank_transfer']
|
|
],
|
|
],
|
|
'metadata' => [
|
|
'clientId' => $clientId_CRM, // ID del cliente en UISP CRM
|
|
'createdBy' => 'UCRM',
|
|
'paymentType' => 'card.one_time',
|
|
'signedInAdminId' => $signedAdminId, // ID del administrador que realiza la operación
|
|
'tipoPago' => 'Transferencia Bancaria'
|
|
],
|
|
]);
|
|
|
|
print_r("PaymentIntent creado: " . $paymentIntent->id . PHP_EOL); //Imprime el ID del PaymentIntent creado
|
|
logMessage("PaymentIntent creado: " . $paymentIntent->id); //Imprime el ID del PaymentIntent creado
|
|
print_r("Status: " . $paymentIntent->status . PHP_EOL); //Imprime el estatus del PaymentIntent creado
|
|
logMessage("Status: " . $paymentIntent->status); //Imprime el estatus del PaymentIntent creado
|
|
print_r("Amount: " . $paymentIntent->amount . PHP_EOL); //Imprime el monto del PaymentIntent creado
|
|
logMessage("Amount: " . $paymentIntent->amount); //Imprime el monto del PaymentIntent creado
|
|
print_r("Currency: " . $paymentIntent->currency . PHP_EOL); //Imprime la moneda del PaymentIntent creado
|
|
logMessage("Currency: " . $paymentIntent->currency); //Imprime la moneda del PaymentIntent creado
|
|
print_r("Customer: " . $paymentIntent->customer . PHP_EOL); //Imprime el ID del cliente del PaymentIntent creado
|
|
logMessage("Customer: " . $paymentIntent->customer); //Imprime el ID del cliente del PaymentIntent creado
|
|
print_r("Payment Method: " . $paymentIntent->payment_method . PHP_EOL); //Imprime el ID del método de pago del PaymentIntent creado
|
|
logMessage("Payment Method: " . $paymentIntent->payment_method); //Imprime el ID del método de pago del PaymentIntent creado
|
|
print_r("Payment Method Type: " . $paymentIntent->payment_method_types[0] . PHP_EOL); //Imprime el tipo de método de pago del PaymentIntent creado
|
|
logMessage("Payment Method Type: " . $paymentIntent->payment_method_types[0]); //Imprime el tipo de método de pago del PaymentIntent creado
|
|
|
|
|
|
|
|
} catch (\Stripe\Exception\ApiErrorException $e) {
|
|
print_r("Error creando PaymentIntent: " . $e->getMessage() . PHP_EOL);
|
|
logMessage("Error creando PaymentIntent: " . $e->getMessage() . PHP_EOL, 'error');
|
|
}
|
|
}
|
|
|
|
|
|
// function createOxxoPaymentIntent($event_json, $amount = null): array
|
|
// {
|
|
// //declarar un array asociativo de strings pero no asignarle nada aun
|
|
// $arrayOxxoPayment = array();
|
|
// $integerAmount = $amount;
|
|
|
|
// print_r("Creando referencia del cliente para OXXO: " . PHP_EOL);
|
|
// $configManager = PluginConfigManager::create();
|
|
// $config = $configManager->loadConfig();
|
|
// $StripeToken = $config['tokenstripe'];
|
|
// $IPServer = $config['ipserver'];
|
|
// $tokenCRM = $config['apitoken'];
|
|
|
|
// $baseUri = 'https://' . $IPServer . '/crm/api/v1.0/';
|
|
// $ucrmApi = UcrmApi::create();
|
|
// $currentUserAdmin = $ucrmApi->get('users/admins', []);
|
|
// $clientID = $event_json['client_id'];
|
|
|
|
// $stripeCustomerId = null;
|
|
// $clientEmail = '';
|
|
// $clientFullName = '';
|
|
|
|
// $clientGuzzleHttp = new Client([
|
|
// 'base_uri' => $baseUri,
|
|
// 'headers' => [
|
|
// 'X-Auth-App-Key' => $tokenCRM,
|
|
// 'Accept' => 'application/json',
|
|
// ],
|
|
// 'verify' => false,
|
|
// 'timeout' => 5, // Timeout de 5 segundos
|
|
// ]);
|
|
|
|
// try {
|
|
// $response = $clientGuzzleHttp->request('GET', "clients/" . $clientID);
|
|
// $arrayClientCRM = json_decode($response->getBody()->getContents(), true);
|
|
// //$this->logger->info("Valor de arrayClientCRM: " . print_r($arrayClientCRM, true) . PHP_EOL);
|
|
// $clientFullName = $arrayClientCRM['firstName'] . ' ' . $arrayClientCRM['lastName'];
|
|
// } catch (RequestException $e) {
|
|
// if ($e->getCode() === 404) {
|
|
// print_r("Cliente no encontrado en CRM: " . $clientID . PHP_EOL);
|
|
// //devolver un array con los campos del codigo error, descripción de la falla, clientID, clientFullName y amount
|
|
// $arrayOxxoPayment['oxxo_reference'] = '';
|
|
// $arrayOxxoPayment['url'] = '';
|
|
// $arrayOxxoPayment['error'] = 'errorGetClientNotFound';
|
|
// $arrayOxxoPayment['failDescription'] = 'Cliente no encontrado en CRM: ' . $clientID;
|
|
// $arrayOxxoPayment['clientID'] = $clientID;
|
|
// $arrayOxxoPayment['clientFullName'] = $clientFullName;
|
|
// $arrayOxxoPayment['amount'] = $integerAmount;
|
|
// $arrayOxxoPayment['voucher_image_url'] = '';
|
|
// return $arrayOxxoPayment;
|
|
|
|
|
|
// }
|
|
// //timeout
|
|
// if ($e->getCode() === 408) {
|
|
// print_r("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
|
|
// $arrayOxxoPayment['oxxo_reference'] = '';
|
|
// $arrayOxxoPayment['url'] = '';
|
|
// $arrayOxxoPayment['error'] = 'errorTimeoutGetClient';
|
|
// $arrayOxxoPayment['failDescription'] = 'Timeout al obtener el cliente en CRM: ' . $clientID;
|
|
// $arrayOxxoPayment['clientID'] = $clientID;
|
|
// $arrayOxxoPayment['clientFullName'] = $clientFullName;
|
|
// $arrayOxxoPayment['amount'] = $integerAmount;
|
|
// $arrayOxxoPayment['voucher_image_url'] = '';
|
|
// return $arrayOxxoPayment;
|
|
// }
|
|
// print_r("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
|
|
// $arrayOxxoPayment['oxxo_reference'] = '';
|
|
// $arrayOxxoPayment['url'] = '';
|
|
// $arrayOxxoPayment['error'] = 'errorGetClient';
|
|
// $arrayOxxoPayment['failDescription'] = 'Error al obtener el cliente en CRM: ' . $clientID;
|
|
// $arrayOxxoPayment['clientID'] = $clientID;
|
|
// $arrayOxxoPayment['clientFullName'] = $clientFullName;
|
|
// $arrayOxxoPayment['amount'] = $integerAmount;
|
|
// $arrayOxxoPayment['voucher_image_url'] = '';
|
|
// return $arrayOxxoPayment;
|
|
|
|
// }
|
|
|
|
// // Obtener email del cliente
|
|
// foreach ($arrayClientCRM['contacts'] as $contact) {
|
|
// if (!empty($contact['email'])) {
|
|
// $clientEmail = $contact['email'];
|
|
// break;
|
|
// } else {
|
|
// $clientEmail = 'siip8873@gmail.com'; // Default
|
|
// }
|
|
// }
|
|
|
|
// try {
|
|
// // Obtener stripeCustomerId
|
|
// foreach ($arrayClientCRM['attributes'] as $attribute) {
|
|
// if ($attribute['key'] === 'stripeCustomerId') {
|
|
// $stripeCustomerId = $attribute['value'];
|
|
// break;
|
|
// }
|
|
// }
|
|
|
|
// print_r("Stripe Customer ID obtenido: " . $stripeCustomerId . PHP_EOL);
|
|
// } catch (Exception $e) {
|
|
// print_r("Error al obtener el Customer ID de 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
|
|
// $arrayOxxoPayment['oxxo_reference'] = '';
|
|
// $arrayOxxoPayment['error'] = 'errorGetCustomerStripe';
|
|
// $arrayOxxoPayment['failDescription'] = 'Error al obtener el Customer ID de Stripe: ' . $clientID;
|
|
// $arrayOxxoPayment['clientID'] = $clientID;
|
|
// $arrayOxxoPayment['clientFullName'] = $clientFullName;
|
|
// $arrayOxxoPayment['amount'] = $integerAmount;
|
|
// $arrayOxxoPayment['voucher_image_url'] = '';
|
|
// return $arrayOxxoPayment;
|
|
// }
|
|
|
|
// if ($amount === null) {
|
|
// $amount = abs($arrayClientCRM['accountOutstanding']); //Monto adeudado del cliente
|
|
// } else {
|
|
// print_r("Monto proporcionado directamente: $amount " . PHP_EOL);
|
|
// }
|
|
|
|
// if ($amount > 10) {
|
|
// $amountInCents = intval($amount * 100); // Convertir a centavos
|
|
|
|
// try {
|
|
// print_r("Creando referencia en Stripe por $amount para el cliente $stripeCustomerId" . PHP_EOL);
|
|
// $guzzleClient = new Client([
|
|
// 'timeout' => 5, // Timeout de 5 segundos
|
|
// ]);
|
|
|
|
// $response = $guzzleClient->post('https://api.stripe.com/v1/payment_intents', [
|
|
// 'auth' => [$StripeToken, ''],
|
|
// 'form_params' => [
|
|
// 'amount' => $amountInCents,
|
|
// 'currency' => 'mxn',
|
|
// 'payment_method_types' => ['customer_balance', 'card', 'oxxo'],
|
|
// 'description' => 'Pago de servicio de SIIP Internet',
|
|
// 'customer' => $stripeCustomerId,
|
|
// 'metadata' => [
|
|
// 'clientId' => $clientID,
|
|
// 'createdBy' => 'UCRM',
|
|
// 'paymentType' => 'card.one_time',
|
|
// 'signedInAdminId' => $currentUserAdmin[1]['id'],
|
|
// 'tipoPago' => 'OXXO',
|
|
// ],
|
|
// 'payment_method_options' => [
|
|
// 'oxxo' => [
|
|
// 'expires_after_days' => 3,
|
|
// ],
|
|
// ],
|
|
// ]
|
|
// ]);
|
|
|
|
// $paymentIntent = json_decode($response->getBody()->getContents(), true);
|
|
|
|
// } catch (\Stripe\Exception\ApiConnectionException $e) {
|
|
// print_r("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
|
|
// $arrayOxxoPayment['oxxo_reference'] = '';
|
|
// $arrayOxxoPayment['url'] = '';
|
|
// $arrayOxxoPayment['error'] = 'errorConnectionStripe';
|
|
// $arrayOxxoPayment['failDescription'] = 'Error de conexión con Stripe: ' . $clientID;
|
|
// $arrayOxxoPayment['clientID'] = $clientID;
|
|
// $arrayOxxoPayment['clientFullName'] = $clientFullName;
|
|
// $arrayOxxoPayment['amount'] = $amount;
|
|
// $arrayOxxoPayment['voucher_image_url'] = '';
|
|
// return $arrayOxxoPayment;
|
|
|
|
// } catch (\Stripe\Exception\ApiErrorException $e) {
|
|
// print_r("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
|
|
// $arrayOxxoPayment['oxxo_reference'] = '';
|
|
// $arrayOxxoPayment['url'] = '';
|
|
// $arrayOxxoPayment['error'] = 'errorApiStripe';
|
|
// $arrayOxxoPayment['failDescription'] = 'Error de la API de Stripe: ' . $clientID;
|
|
// $arrayOxxoPayment['clientID'] = $clientID;
|
|
// $arrayOxxoPayment['clientFullName'] = $clientFullName;
|
|
// $arrayOxxoPayment['amount'] = $amount;
|
|
// $arrayOxxoPayment['voucher_image_url'] = '';
|
|
// return $arrayOxxoPayment;
|
|
|
|
// } catch (Exception $e) {
|
|
// print_r("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...)') {
|
|
// print_r("Este cliente no tiene cuenta de Stripe" . PHP_EOL);
|
|
// $arrayOxxoPayment['failDescription'] = 'Este cliente no tiene cuenta de Stripe: ' . $clientID;
|
|
// } else {
|
|
// print_r("Este cliente no tiene cuenta de Stripe" . PHP_EOL);
|
|
// print_r("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
|
|
// $arrayOxxoPayment['oxxo_reference'] = '';
|
|
// $arrayOxxoPayment['url'] = '';
|
|
// $arrayOxxoPayment['error'] = 'errorCreatePaymentIntent';
|
|
// $arrayOxxoPayment['clientID'] = $clientID;
|
|
// $arrayOxxoPayment['clientFullName'] = $clientFullName;
|
|
// $arrayOxxoPayment['amount'] = $amount;
|
|
// $arrayOxxoPayment['voucher_image_url'] = '';
|
|
// return $arrayOxxoPayment;
|
|
|
|
// }
|
|
|
|
// try {
|
|
// $firstName = isset($arrayClientCRM['firstName']) ? trim($arrayClientCRM['firstName']) : '';
|
|
// $lastName = isset($arrayClientCRM['lastName']) ? trim($arrayClientCRM['lastName']) : '';
|
|
|
|
// if (strlen($firstName) < 2 || strlen($lastName) < 2) {
|
|
// print_r("Este cliente no tiene cuenta de Stripe" . PHP_EOL);
|
|
// ("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
|
|
// $arrayOxxoPayment['oxxo_reference'] = '';
|
|
// $arrayOxxoPayment['url'] = '';
|
|
// $arrayOxxoPayment['error'] = 'errorNombreApellidoInvalido';
|
|
// $arrayOxxoPayment['failDescription'] = "Nombre/apellido inválido: ' . $firstName . ' ' . $lastName";
|
|
// $arrayOxxoPayment['clientID'] = $clientID;
|
|
// $arrayOxxoPayment['clientFullName'] = $clientFullName;
|
|
// $arrayOxxoPayment['amount'] = $amount;
|
|
// $arrayOxxoPayment['voucher_image_url'] = '';
|
|
// return $arrayOxxoPayment;
|
|
|
|
// }
|
|
|
|
// $responsePaymentMethod = $guzzleClient->post('https://api.stripe.com/v1/payment_methods', [
|
|
// 'auth' => [$StripeToken, ''],
|
|
// 'form_params' => [
|
|
// 'type' => 'oxxo',
|
|
// 'billing_details' => [
|
|
// 'name' => "$firstName $lastName",
|
|
// 'email' => $clientEmail,
|
|
// ],
|
|
// ]
|
|
// ]);
|
|
|
|
// $paymentMethod = json_decode($responsePaymentMethod->getBody()->getContents(), true);
|
|
|
|
// $responseConfirmPaymentIntent = $guzzleClient->post('https://api.stripe.com/v1/payment_intents/' . $paymentIntent['id'] . '/confirm', [
|
|
// 'auth' => [$StripeToken, ''],
|
|
// 'form_params' => [
|
|
// 'payment_method' => $paymentMethod['id'],
|
|
// ]
|
|
// ]);
|
|
|
|
// $paymentIntentConfirm = json_decode($responseConfirmPaymentIntent->getBody()->getContents(), true);
|
|
|
|
// } catch (Exception $e) {
|
|
// print_r("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
|
|
// $arrayOxxoPayment['oxxo_reference'] = '';
|
|
// $arrayOxxoPayment['url'] = '';
|
|
// $arrayOxxoPayment['error'] = 'errorConfirmPaymentIntent';
|
|
// $arrayOxxoPayment['failDescription'] = 'Error al confirmar PaymentIntent: ' . $e->getMessage();
|
|
// $arrayOxxoPayment['clientID'] = $clientID;
|
|
// $arrayOxxoPayment['clientFullName'] = $clientFullName;
|
|
// $arrayOxxoPayment['amount'] = $amount;
|
|
// $arrayOxxoPayment['voucher_image_url'] = '';
|
|
// return $arrayOxxoPayment;
|
|
// }
|
|
|
|
// if (!empty($paymentIntentConfirm['next_action']) && isset($paymentIntentConfirm['next_action']['oxxo_display_details'])) {
|
|
// $oxxoPayment = $paymentIntentConfirm['next_action']['oxxo_display_details'];
|
|
// $oxxo_reference = $oxxoPayment['number'];
|
|
// $oxxo_receipt_url = $oxxoPayment['hosted_voucher_url'];
|
|
|
|
// print_r("Referencia OXXO: " . $oxxo_reference . PHP_EOL);
|
|
// print_r("URL del recibo: " . $oxxo_receipt_url . PHP_EOL);
|
|
// //$this->captureScreenshot($oxxo_receipt_url);
|
|
// //devolver un array con los campos de url de oxxo, descripción de la falla, clientID y amount
|
|
// $arrayOxxoPayment['oxxo_reference'] = $oxxo_reference;
|
|
// $arrayOxxoPayment['url'] = $oxxo_receipt_url;
|
|
// $arrayOxxoPayment['error'] = '';
|
|
// $arrayOxxoPayment['failDescription'] = '';
|
|
// $arrayOxxoPayment['clientID'] = $clientID;
|
|
// $arrayOxxoPayment['clientFullName'] = $clientFullName;
|
|
// $arrayOxxoPayment['amount'] = $amount;
|
|
// print_r("Referencia OXXO creada correctamente." . PHP_EOL);
|
|
|
|
|
|
|
|
// return $arrayOxxoPayment;
|
|
// } else {
|
|
// print_r("El PaymentIntent no tiene detalles de OXXO disponibles. Estado: " . $paymentIntentConfirm['status'] . PHP_EOL);
|
|
// //devolver un array con los campos del codigo error, descripción de la falla, clientID y amount
|
|
// $arrayOxxoPayment['oxxo_reference'] = '';
|
|
// $arrayOxxoPayment['url'] = '';
|
|
// $arrayOxxoPayment['error'] = 'errorPaymentIntentWithoutOxxoDetails';
|
|
// $arrayOxxoPayment['failDescription'] = 'El PaymentIntent no tiene detalles de OXXO disponibles. Estado: ' . $paymentIntentConfirm['status'];
|
|
// $arrayOxxoPayment['clientID'] = $clientID;
|
|
// $arrayOxxoPayment['clientFullName'] = $clientFullName;
|
|
// $arrayOxxoPayment['amount'] = $amount;
|
|
// $arrayOxxoPayment['voucher_image_url'] = '';
|
|
// return $arrayOxxoPayment;
|
|
|
|
// }
|
|
|
|
// } else {
|
|
// print_r("Este cliente no tiene adeudos." . PHP_EOL);
|
|
// //devolver un array con los campos del codigo error, descripción de la falla, clientID y amount
|
|
// $arrayOxxoPayment['oxxo_reference'] = '';
|
|
// $arrayOxxoPayment['url'] = '';
|
|
// $arrayOxxoPayment['error'] = 'errorsinadeudo';
|
|
// $arrayOxxoPayment['failDescription'] = 'Este cliente no tiene adeudos.';
|
|
// $arrayOxxoPayment['clientID'] = $clientID;
|
|
// $arrayOxxoPayment['clientFullName'] = $clientFullName;
|
|
// $arrayOxxoPayment['amount'] = $amount;
|
|
// $arrayOxxoPayment['voucher_image_url'] = '';
|
|
// return $arrayOxxoPayment;
|
|
// }
|
|
// }
|
|
|
|
|
|
// /**
|
|
// * Cancela todos los PaymentIntents en estado 'requires_action' para un cliente específico.
|
|
// *
|
|
// * @param \Stripe\StripeClient $stripe Instancia de StripeClient
|
|
// * @param string $customerId ID del cliente en Stripe
|
|
// * @return bool True si se encontraron y cancelaron PaymentIntents, False si no hay ninguno en estado 'requires_action'
|
|
// */
|
|
// function cancelRequiresActionPaymentIntents($stripe, $customerId)
|
|
// {
|
|
// try {
|
|
// // Listar todos los PaymentIntents del cliente
|
|
// $paymentIntents = $stripe->paymentIntents->all([
|
|
// 'customer' => $customerId,
|
|
// 'limit' => 100, // Número máximo de resultados por página
|
|
// ]);
|
|
|
|
// $foundAndCanceled = false;
|
|
|
|
// foreach ($paymentIntents->data as $intent) {
|
|
// // Verificar si el estado es 'requires_action'
|
|
// if ($intent->status === 'requires_action') {
|
|
// // Cancelar el PaymentIntent
|
|
// $stripe->paymentIntents->cancel($intent->id);
|
|
// $foundAndCanceled = true;
|
|
// }
|
|
// }
|
|
|
|
// // Manejar paginación si hay más de 100 PaymentIntents
|
|
// while ($paymentIntents->has_more) {
|
|
// $lastIntentId = end($paymentIntents->data)->id;
|
|
// $paymentIntents = $stripe->paymentIntents->all([
|
|
// 'customer' => $customerId,
|
|
// 'limit' => 100,
|
|
// 'starting_after' => $lastIntentId,
|
|
// ]);
|
|
|
|
// foreach ($paymentIntents->data as $intent) {
|
|
// if ($intent->status === 'requires_action') {
|
|
// $stripe->paymentIntents->cancel($intent->id);
|
|
// $foundAndCanceled = true;
|
|
// }
|
|
// }
|
|
// }
|
|
|
|
// return $foundAndCanceled;
|
|
|
|
// } catch (\Stripe\Exception\ApiErrorException $e) {
|
|
// // Manejo de errores
|
|
// error_log('Error al procesar PaymentIntents: ' . $e->getMessage());
|
|
// return false;
|
|
// }
|
|
// }
|
|
function logMessage($message, $type = 'info')
|
|
{
|
|
$logFile = __DIR__ . '/payment_intents.log';
|
|
$dateTime = new DateTime('now', new DateTimeZone('America/Mexico_City'));
|
|
$formattedDateTime = $dateTime->format('Y-m-d H:i:s');
|
|
file_put_contents($logFile, "[$formattedDateTime] [$type] $message" . PHP_EOL, FILE_APPEND);
|
|
}
|