siip-stripe-payment_intents/PaymentIntentStripe.php
DANYDHSV 7e4a535038 feat(stripe-sync): implementar resolución dinámica de métodos de pago y corregir validación API
- 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.
2025-12-23 14:50:01 -06:00

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);
}