Initial commit
This commit is contained in:
commit
8eea1e9163
60
GoogleDriveUpload.php
Executable file
60
GoogleDriveUpload.php
Executable file
@ -0,0 +1,60 @@
|
|||||||
|
<?php
|
||||||
|
require 'vendor/autoload.php';
|
||||||
|
|
||||||
|
use Google\Client;
|
||||||
|
use Google\Service\Drive;
|
||||||
|
|
||||||
|
// Configuración de Google Drive
|
||||||
|
function getClient() {
|
||||||
|
$client = new Client();
|
||||||
|
$client->setApplicationName('Google Drive API PHP Quickstart');
|
||||||
|
$client->setScopes(Drive::DRIVE_FILE);
|
||||||
|
$client->setAuthConfig(__DIR__.'/credentials.json');
|
||||||
|
$client->setAccessType('offline');
|
||||||
|
$client->setPrompt('select_account consent');
|
||||||
|
|
||||||
|
$tokenPath = 'token.json';
|
||||||
|
if (file_exists($tokenPath)) {
|
||||||
|
$accessToken = json_decode(file_get_contents($tokenPath), true);
|
||||||
|
$client->setAccessToken($accessToken);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($client->isAccessTokenExpired()) {
|
||||||
|
if ($client->getRefreshToken()) {
|
||||||
|
$client->fetchAccessTokenWithRefreshToken($client->getRefreshToken());
|
||||||
|
} else {
|
||||||
|
$authUrl = $client->createAuthUrl();
|
||||||
|
printf("Open the following link in your browser:\n%s\n", $authUrl);
|
||||||
|
print 'Enter verification code: ';
|
||||||
|
$authCode = trim(fgets(STDIN));
|
||||||
|
|
||||||
|
$accessToken = $client->fetchAccessTokenWithAuthCode($authCode);
|
||||||
|
$client->setAccessToken($accessToken);
|
||||||
|
|
||||||
|
if (!file_exists(dirname($tokenPath))) {
|
||||||
|
mkdir(dirname($tokenPath), 0700, true);
|
||||||
|
}
|
||||||
|
file_put_contents($tokenPath, json_encode($client->getAccessToken()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return $client;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Función para subir archivo a Google Drive
|
||||||
|
function uploadFileToDrive($client, $filePath) {
|
||||||
|
$driveService = new Drive($client);
|
||||||
|
$fileMetadata = new Drive\DriveFile(array(
|
||||||
|
'name' => basename($filePath)
|
||||||
|
));
|
||||||
|
$content = file_get_contents($filePath);
|
||||||
|
$file = $driveService->files->create($fileMetadata, array(
|
||||||
|
'data' => $content,
|
||||||
|
'mimeType' => mime_content_type($filePath),
|
||||||
|
'uploadType' => 'multipart',
|
||||||
|
'fields' => 'id'
|
||||||
|
));
|
||||||
|
printf("File ID: %s\n", $file->id);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
107
PHP_PermisosArchivos.php
Executable file
107
PHP_PermisosArchivos.php
Executable file
@ -0,0 +1,107 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
require 'vendor/autoload.php';
|
||||||
|
|
||||||
|
use GuzzleHttp\Client;
|
||||||
|
use GuzzleHttp\Exception\GuzzleException;
|
||||||
|
|
||||||
|
|
||||||
|
// URL base de la API
|
||||||
|
$baseUri = 'https://172.16.5.134/crm/api/v1.0/';
|
||||||
|
// Token de autenticación
|
||||||
|
$token = '6abef18c-783d-4dd0-b530-be6e6a7bbd1d';
|
||||||
|
|
||||||
|
// Configuración del cliente GuzzleHttp
|
||||||
|
$clientGuzzleHttp = new Client([
|
||||||
|
'base_uri' => $baseUri,
|
||||||
|
'headers' => [
|
||||||
|
'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
|
||||||
|
],
|
||||||
|
'verify' => false,
|
||||||
|
]);
|
||||||
|
|
||||||
|
// Hacer la solicitud GET
|
||||||
|
$response = $clientGuzzleHttp->request('GET', "payments/89/pdf");
|
||||||
|
|
||||||
|
// Obtener el cuerpo de la respuesta (contenido binario)
|
||||||
|
$binaryData = $response->getBody()->getContents();
|
||||||
|
|
||||||
|
// Abrir un recurso de flujo de datos en memoria
|
||||||
|
$fileHandle = fopen('php://temp', 'r+');
|
||||||
|
|
||||||
|
// Escribir los datos binarios en el recurso de flujo de datos en memoria
|
||||||
|
fwrite($fileHandle, $binaryData);
|
||||||
|
|
||||||
|
// Rebobinar el puntero del flujo de datos para leer desde el principio
|
||||||
|
rewind($fileHandle);
|
||||||
|
|
||||||
|
if (!isset($fileHandle)) {
|
||||||
|
print_r("viene vacia la variable filehandle" . PHP_EOL);
|
||||||
|
}
|
||||||
|
// Subir el archivo al servidor FTP usando ftp_fput
|
||||||
|
$remoteFilename = 'archivo.pdf';
|
||||||
|
|
||||||
|
$pdf_payment_path = '/home/unms/data/ucrm/ucrm/data/payment_receipts/hola.txt';
|
||||||
|
$permisos = 0777; // Permisos 777 (lectura, escritura y ejecución para todos)
|
||||||
|
|
||||||
|
// Verificar si el archivo existe antes de cambiar los permisos
|
||||||
|
if (file_exists($pdf_payment_path)) {
|
||||||
|
// Cambiar los permisos del archivo
|
||||||
|
if (chmod($pdf_payment_path, $permisos)) {
|
||||||
|
print_r("Los permisos del archivo se han cambiado correctamente." . PHP_EOL);
|
||||||
|
} else {
|
||||||
|
print_r("No se pudieron cambiar los permisos del archivo." . PHP_EOL);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
print_r("El archivo no existe en la ruta especificada." . PHP_EOL);
|
||||||
|
}
|
||||||
|
|
||||||
|
UploadFileWordpress($fileHandle);
|
||||||
|
|
||||||
|
function UploadFileWordpress($fileHandle): string
|
||||||
|
{
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// Configuración de conexión FTP
|
||||||
|
$ftp_server = "siip.mx";
|
||||||
|
$ftp_username = "siip0001";
|
||||||
|
$ftp_password = '$spGiT,[wa)n';
|
||||||
|
//$fileName = $fileNameComprobantePDF;
|
||||||
|
$remote_file = "/public_html/wp/wp-content/uploads/pdf/Comprobante_de_pago.pdf";
|
||||||
|
//$file_to_upload = '/home/unms/data/ucrm/ucrm/data/payment_receipts/' . $fileName;
|
||||||
|
$url = 'http://siip.mx/wp/wp-content/uploads/pdf/Comprobante_de_pago.pdf';
|
||||||
|
|
||||||
|
|
||||||
|
// 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);
|
||||||
|
|
||||||
|
|
||||||
|
// Verificar conexión y login
|
||||||
|
if ($ftp_conn && $login) {
|
||||||
|
print_r("Conexión FTP exitosa" . PHP_EOL);
|
||||||
|
|
||||||
|
var_dump($ftp_conn);
|
||||||
|
// Cargar archivo
|
||||||
|
if (ftp_fput($ftp_conn, $remote_file, $fileHandle, FTP_BINARY)) {
|
||||||
|
print_r("El archivo ha sido cargado exitosamente." . PHP_EOL);
|
||||||
|
print_r("La URL es: " . $url . PHP_EOL);
|
||||||
|
// Cerrar conexión FTP
|
||||||
|
ftp_close($ftp_conn);
|
||||||
|
return $url;
|
||||||
|
|
||||||
|
} else {
|
||||||
|
print_r("Error al cargar el archivo " . PHP_EOL);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Cerrar conexión FTP
|
||||||
|
ftp_close($ftp_conn);
|
||||||
|
return '';
|
||||||
|
} else {
|
||||||
|
print_r("No se pudo conectar o iniciar sesión en el servidor FTP." . PHP_EOL);
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
212
README.md
Executable file
212
README.md
Executable file
@ -0,0 +1,212 @@
|
|||||||
|
# SMS notifier - Twilio
|
||||||
|
|
||||||
|
* This plugin sends SMS notifications to clients.
|
||||||
|
* SMS is triggered by an event which happened in UCRM, e.g. new invoice has been issued, or client's sevice became suspended.
|
||||||
|
* It only sends SMS to clients having a phone number set in their contacts details.
|
||||||
|
* [Twilio](https://www.twilio.com/) account is required to access its API.
|
||||||
|
|
||||||
|
## Configuration
|
||||||
|
|
||||||
|
* 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
|
||||||
|
|
||||||
|
## Usage
|
||||||
|
* In UCRM admin, go to System / Webhooks / Endpoints
|
||||||
|
* Click Test Endpoint
|
||||||
|
* Go to System / Plugins / SMS notifications via Twilio
|
||||||
|
* In the log output, you'll see `Webhook test successful.`
|
||||||
|
|
||||||
|
## Variables replaced
|
||||||
|
|
||||||
|
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.
|
||||||
|
|
||||||
|
### Client variables
|
||||||
|
|
||||||
|
* `%%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.'
|
||||||
|
|
||||||
|
### 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
|
||||||
|
|
||||||
|
### 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
|
||||||
|
|
||||||
|
### Service variables
|
||||||
|
* `%%service.id%%` => 23
|
||||||
|
* `%%service.clientId%%` => 20
|
||||||
|
* `%%service.status%%` => 1
|
||||||
|
* `%%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'
|
||||||
|
|
||||||
|
|
||||||
|
## 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
|
||||||
|
* Preferably also change the SmsNotifier namespace to some other (not strictly necessary).
|
||||||
|
|
||||||
|
Read more about creating your own plugin in the [Developer documentation](https://github.com/Ubiquiti-App/UCRM-plugins/blob/master/docs/index.md).
|
||||||
|
|
||||||
73
StripeWebhook.php
Executable file
73
StripeWebhook.php
Executable file
@ -0,0 +1,73 @@
|
|||||||
|
<?php
|
||||||
|
use GuzzleHttp\Client;
|
||||||
|
|
||||||
|
require 'vendor/autoload.php';
|
||||||
|
|
||||||
|
// $baseUri = 'https://172.16.5.120/crm/api/v1.0/'; //endpoint de la API REST del CRM
|
||||||
|
// $token = '3d5fa4c9-e134-4e8b-b8d7-aae394d48d4d'; //Token para acceder a los recursos del CRM
|
||||||
|
$baseUri = 'https://172.16.5.134/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
|
||||||
|
|
||||||
|
$stripe = new \Stripe\StripeClient('sk_test_51OkG0REFY1WEUtgRH6UxBK5pu80Aq5Iy8EcdPnf0cOWzuVLQTpyLCd7CbPzqMsWMafZOHElCxhEHF7g8boURjWlJ00tBwE0W1M'); //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
|
||||||
|
|
||||||
|
//cliente GuzzleHttp para consumir API del UISP CRM
|
||||||
|
$clientGuzzleHttp = new Client([
|
||||||
|
'base_uri' => $baseUri,
|
||||||
|
'headers' => [
|
||||||
|
'X-Auth-App-Key' => $token,
|
||||||
|
'Accept' => 'application/json',
|
||||||
|
],
|
||||||
|
'verify' => false,
|
||||||
|
]);
|
||||||
|
|
||||||
|
// Obtén el contenido del cuerpo de la solicitud
|
||||||
|
$input = @file_get_contents('php://input');
|
||||||
|
$event_json = json_decode($input);
|
||||||
|
$cadena = json_encode($event_json);
|
||||||
|
file_put_contents(__DIR__ . '/logsiip.log', "[" . date('Y-m-d H:i:s') . "] " . "Valor json: ".$cadena.PHP_EOL);
|
||||||
|
// Maneja el evento del webhook
|
||||||
|
if ($event_json) {
|
||||||
|
switch ($event_json->type) {
|
||||||
|
case 'cash_balance.funds_available':
|
||||||
|
$customer = $event_json->data->object;
|
||||||
|
$customerId = $customer->id;
|
||||||
|
$newBalance = $customer->balance; // El nuevo saldo del cliente
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
try {// Aquí puedes crear un nuevo PaymentIntent o un Cargo (Charge) usando el nuevo saldo
|
||||||
|
$paymentIntent = \Stripe\PaymentIntent::create([
|
||||||
|
'amount' => 30000,
|
||||||
|
'currency' => 'mxn',
|
||||||
|
'customer' => $customerId,
|
||||||
|
'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' => $customerId, // ID del cliente en Ubiquiti
|
||||||
|
'createdBy' => 'UCRM', // ID de la factura en Ubiquiti
|
||||||
|
'paymentType' => 'card.one_time',
|
||||||
|
'signedInAdminId' => 1015,
|
||||||
|
],
|
||||||
|
]);
|
||||||
|
file_put_contents(__DIR__ . '/logsiip.log', "[" . date('Y-m-d H:i:s') . "] " . "PaymentIntent creado: " . $paymentIntent->id . PHP_EOL, FILE_APPEND);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
} catch (\Stripe\Exception\ApiErrorException $e) {
|
||||||
|
file_put_contents(__DIR__ . '/logsiip.log', "[" . date('Y-m-d H:i:s') . "] " ."Error creando PaymentIntent: " . $e->getMessage() . PHP_EOL, FILE_APPEND);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
// Otros eventos relevantes
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
http_response_code(200); // Responde con un 200 OK a Stripe
|
||||||
1748
composer-setup.php
Executable file
1748
composer-setup.php
Executable file
File diff suppressed because it is too large
Load Diff
21
composer.json
Executable file
21
composer.json
Executable file
@ -0,0 +1,21 @@
|
|||||||
|
{
|
||||||
|
"name": "ucrm-plugins/sms-twilio",
|
||||||
|
"description": "UCRM plugin for SMS notifications, powered by Twilio",
|
||||||
|
"license": "MIT",
|
||||||
|
"autoload": {
|
||||||
|
"psr-4": {
|
||||||
|
"SmsNotifier\\": [
|
||||||
|
"src/"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"require": {
|
||||||
|
"ubnt/ucrm-plugin-sdk": "^0.10.0",
|
||||||
|
"twilio/sdk": "^7.9",
|
||||||
|
"php-di/php-di": "^7.0",
|
||||||
|
"katzgrau/klogger": "^1.2",
|
||||||
|
"stripe/stripe-php": "^13.11",
|
||||||
|
"ext-imagick": "*",
|
||||||
|
"google/apiclient": "^2.0"
|
||||||
|
}
|
||||||
|
}
|
||||||
1969
composer.lock
generated
Executable file
1969
composer.lock
generated
Executable file
File diff suppressed because it is too large
Load Diff
BIN
composer.phar
Executable file
BIN
composer.phar
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: 232 KiB |
BIN
comprobantes/Comprobante_Daniel_Humberto_Soto_Villegas_Polleria.png
Executable file
BIN
comprobantes/Comprobante_Daniel_Humberto_Soto_Villegas_Polleria.png
Executable file
Binary file not shown.
BIN
comprobantes/Comprobante_Daniel_Humberto_Soto_Villegas_Polleria_2_prueba.png
Executable file
BIN
comprobantes/Comprobante_Daniel_Humberto_Soto_Villegas_Polleria_2_prueba.png
Executable file
Binary file not shown.
|
After Width: | Height: | Size: 215 KiB |
BIN
comprobantes/Comprobante_Daniel_Humberto_Soto_Villegas_resss.png
Executable file
BIN
comprobantes/Comprobante_Daniel_Humberto_Soto_Villegas_resss.png
Executable file
Binary file not shown.
|
After Width: | Height: | Size: 212 KiB |
BIN
comprobantes/Comprobante_Don_Miguel_Ángel_Guerrero_González.png
Executable file
BIN
comprobantes/Comprobante_Don_Miguel_Ángel_Guerrero_González.png
Executable file
Binary file not shown.
|
After Width: | Height: | Size: 206 KiB |
BIN
comprobantes/Comprobante_Lupita_Morales.png
Executable file
BIN
comprobantes/Comprobante_Lupita_Morales.png
Executable file
Binary file not shown.
|
After Width: | Height: | Size: 280 KiB |
1
credentials.json
Executable file
1
credentials.json
Executable file
@ -0,0 +1 @@
|
|||||||
|
{"web":{"client_id":"643910347881-h8cas0s9i56ub3l3e822gc9iv7mcs1ip.apps.googleusercontent.com","project_id":"drive-comprobantes-siip","auth_uri":"https://accounts.google.com/o/oauth2/auth","token_uri":"https://oauth2.googleapis.com/token","auth_provider_x509_cert_url":"https://www.googleapis.com/oauth2/v1/certs","client_secret":"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"}}
|
||||||
1
data/config.json
Executable file
1
data/config.json
Executable file
@ -0,0 +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,"debugMode":true,"logging_level":true}
|
||||||
1
data/plugin.json
Executable file
1
data/plugin.json
Executable file
@ -0,0 +1 @@
|
|||||||
|
{"twilioAccountSid":null,"twilioAuthToken":null,"twilioSmsNumber":null,"displayedErrors":"Not valid configuration: Twilio Account SID must be configured\nNot valid configuration: Twilio Auth Token must be configured","event_client_add":null,"event_client_archive":null,"event_client_delete":null,"event_client_edit":null,"event_invoice_add":null,"event_invoice_add_draft":null,"event_invoice_draft_approved":null,"event_invoice_delete":null,"event_invoice_edit":null,"event_payment_add":null,"event_payment_delete":null,"event_payment_edit":null,"event_payment_unmatch":null,"event_service_activate":null,"event_service_add":null,"event_service_archive":null,"event_service_end":null,"event_service_postpone":null,"event_service_suspend_cancel":null,"event_service_suspend":null,"event_invoice_near_due":null,"event_invoice_overdue":null,"event_client_message":null}
|
||||||
1023
data/plugin.log
Normal file
1023
data/plugin.log
Normal file
File diff suppressed because it is too large
Load Diff
42
hook_install.php
Executable file
42
hook_install.php
Executable file
@ -0,0 +1,42 @@
|
|||||||
|
<?php
|
||||||
|
use Ubnt\UcrmPluginSdk\Service\PluginLogManager;
|
||||||
|
|
||||||
|
$log = PluginLogManager::create(); //Initialize Logger
|
||||||
|
|
||||||
|
// Configuración de conexión FTP
|
||||||
|
$ftp_server = "siip.mx";
|
||||||
|
$ftp_username = "siip0001";
|
||||||
|
$ftp_password = '$spGiT,[wa)n';
|
||||||
|
|
||||||
|
// Establecer la conexión FTP
|
||||||
|
$ftp_conexion = ftp_connect("siip.mx");
|
||||||
|
$usuario_ftp = "siip0001";
|
||||||
|
$contrasena_ftp = '$spGiT,[wa)n';
|
||||||
|
|
||||||
|
if ($ftp_conexion) {
|
||||||
|
// Iniciar sesión con el nombre de usuario y contraseña
|
||||||
|
$login_resultado = ftp_login($ftp_conexion, $usuario_ftp, $contrasena_ftp);
|
||||||
|
|
||||||
|
// Verificar si la sesión se ha iniciado correctamente
|
||||||
|
if ($login_resultado) {
|
||||||
|
// Ruta de la carpeta que deseas vaciar
|
||||||
|
$carpeta_ftp = '/public_html/wp/wp-content/uploads/pdf/';
|
||||||
|
|
||||||
|
// Obtener lista de archivos en la carpeta
|
||||||
|
$archivos = ftp_nlist($ftp_conexion, $carpeta_ftp);
|
||||||
|
|
||||||
|
// Iterar sobre cada archivo y eliminarlo
|
||||||
|
foreach ($archivos as $archivo) {
|
||||||
|
// Eliminar el archivo
|
||||||
|
ftp_delete($ftp_conexion, $archivo);
|
||||||
|
|
||||||
|
}
|
||||||
|
$log->appendLog("ArchivoS eliminados".PHP_EOL);
|
||||||
|
// Cerrar la conexión FTP
|
||||||
|
ftp_close($ftp_conexion);
|
||||||
|
} else {
|
||||||
|
$log->appendLog("Error al iniciar sesión en el servidor FTP".PHP_EOL);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
$log->appendLog("Error al conectar al servidor FTP".PHP_EOL);
|
||||||
|
}
|
||||||
64
html_public.php
Executable file
64
html_public.php
Executable file
@ -0,0 +1,64 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
class htmlPublic{
|
||||||
|
public $html;
|
||||||
|
|
||||||
|
public static function imprimirBody(){
|
||||||
|
|
||||||
|
$html = '
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="es">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
|
<style>
|
||||||
|
body {
|
||||||
|
font-family: Arial, sans-serif;
|
||||||
|
background-color: #f0f0f0;
|
||||||
|
margin: 0;
|
||||||
|
padding: 20px;
|
||||||
|
}
|
||||||
|
h1 {
|
||||||
|
text-align: center;
|
||||||
|
color: #333;
|
||||||
|
}
|
||||||
|
table {
|
||||||
|
width: 100%;
|
||||||
|
border-collapse: collapse;
|
||||||
|
border: 2px solid #333;
|
||||||
|
margin-bottom: 20px;
|
||||||
|
}
|
||||||
|
th, td {
|
||||||
|
padding: 10px;
|
||||||
|
border: 1px solid #999;
|
||||||
|
}
|
||||||
|
th {
|
||||||
|
background-color: #f2f2f2;
|
||||||
|
}
|
||||||
|
tr:nth-child(even) {
|
||||||
|
background-color: #f9f9f9;
|
||||||
|
}
|
||||||
|
|
||||||
|
.container {
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<h1>Limpieza de archivos PDF de comprobantes de pago subidos a Wordpress para su envío</h1>
|
||||||
|
<div class="container">
|
||||||
|
<form method="post">
|
||||||
|
<button type="submit" name="pintar">Ejecutar borrado de archivos</button>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
';
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
23
main.php
Executable file
23
main.php
Executable file
@ -0,0 +1,23 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
chdir(__DIR__);
|
||||||
|
|
||||||
|
require 'vendor/autoload.php';
|
||||||
|
|
||||||
|
(static function () {
|
||||||
|
$builder = new \DI\ContainerBuilder();
|
||||||
|
$container = $builder->build();
|
||||||
|
$plugin = $container->get(\SmsNotifier\Plugin::class);
|
||||||
|
|
||||||
|
try {
|
||||||
|
$plugin->run();
|
||||||
|
|
||||||
|
// cleanup plugin log
|
||||||
|
$container->get(\SmsNotifier\Service\LogCleaner::class)->clean();
|
||||||
|
} catch (Exception $e) {
|
||||||
|
$logger = new \SmsNotifier\Service\Logger();
|
||||||
|
$logger->error($e->getMessage());
|
||||||
|
$logger->debug($e->getTraceAsString());
|
||||||
|
}
|
||||||
|
})();
|
||||||
|
http_response_code(200); //Response OK when it's called by a webhook.
|
||||||
198
manifest.json
Executable file
198
manifest.json
Executable file
@ -0,0 +1,198 @@
|
|||||||
|
{
|
||||||
|
"version": "1",
|
||||||
|
"information": {
|
||||||
|
"name": "siip-whatsapp-notifications",
|
||||||
|
"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",
|
||||||
|
"url": "https://siip.mx/",
|
||||||
|
"version": "2.4.7",
|
||||||
|
"unmsVersionCompliancy": {
|
||||||
|
"min": "2.1.0",
|
||||||
|
"max": null
|
||||||
|
},
|
||||||
|
"author": "SIIP INTERNET"
|
||||||
|
},
|
||||||
|
"configuration": [
|
||||||
|
{
|
||||||
|
"key": "ipserver",
|
||||||
|
"label": "Dirección IP o dominio del servidor",
|
||||||
|
"description": "La dirección IP del servidor o dominio donde se ejecuta el sistema UISP CRM. Ejemplo: 192.168.1.120 o sistema.empresa.com",
|
||||||
|
"required": 1,
|
||||||
|
"type": "text"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"key": "apitoken",
|
||||||
|
"label": "Token de la API UCRM",
|
||||||
|
"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,
|
||||||
|
"type": "text"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"key": "tokencallbell",
|
||||||
|
"label": "Token de la API de CallBell",
|
||||||
|
"description": "Token de autenticación para el uso de la API de CallBell que maneja las funciones realacionadas con WhatsApp. El token es de tipo 'Bearer' y contiene 97 caracteres, ejemplo: g9thcZkXGd3xBj2g2TtYNYFMH1fuesbJ.b6a947ea7d78cf6c8e42f067a21c8daf91e9fa2a9e310bfd0c7c7c4d7fa36f68",
|
||||||
|
"required": 1,
|
||||||
|
"type": "text"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"key": "tokenstripe",
|
||||||
|
"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. ",
|
||||||
|
"required": 1,
|
||||||
|
"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",
|
||||||
|
"label": "IP o dominio del servidor FTP",
|
||||||
|
"description": "Dirección IP o dominio del sitio del servidor FTP para la carga de comprobantes de pago del sistema y su posterior envío",
|
||||||
|
"required": 1,
|
||||||
|
"type": "text"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"key": "usernameServerFTP",
|
||||||
|
"label": "Usuario FTP",
|
||||||
|
"description": "Nombre de usuario para inicio de sesión el servidor FTP",
|
||||||
|
"required": 1,
|
||||||
|
"type": "text"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"key": "passServerFTP",
|
||||||
|
"label": "Password FTP",
|
||||||
|
"description": "Contraseña para inicio de sesión en el servidor FTP",
|
||||||
|
"required": 1,
|
||||||
|
"type": "text"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"key": "cashPaymentMethodId",
|
||||||
|
"label": "Envío de Comprobante por pago en efectivo",
|
||||||
|
"description": "Habilita el envío de comprobantes en formato de imagen por WhatsApp cuando el método de pago es en efectivo",
|
||||||
|
"required": 0,
|
||||||
|
"type": "checkbox"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"key": "courtesyPaymentMethodId",
|
||||||
|
"label": "Envío de Comprobante por pago de cortesía",
|
||||||
|
"description": "Habilita el envío de comprobantes en formato de imagen por WhatsApp cuando el método de pago es por crédito de cortesía",
|
||||||
|
"required": 0,
|
||||||
|
"type": "checkbox"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"key": "bankTransferPaymentMethodId",
|
||||||
|
"label": "Envío de Comprobante por pago con Transferencia Bancaria",
|
||||||
|
"description": "Habilita el envío de comprobantes en formato de imagen por WhatsApp cuando el método de pago es por Transferencia Bancaria",
|
||||||
|
"required": 0,
|
||||||
|
"type": "checkbox"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"key": "paypalPaymentMethodId",
|
||||||
|
"label": "Envío de Comprobante por pago con PayPal",
|
||||||
|
"description": "Habilita el envío de comprobantes en formato de imagen por WhatsApp cuando el método de pago es por PayPal",
|
||||||
|
"required": 0,
|
||||||
|
"type": "checkbox"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"key": "creditCardPaypalPaymentMethodId",
|
||||||
|
"label": "Envío de Comprobante por pago de Tarjeta de Crédito o Débito con PayPal",
|
||||||
|
"description": "Habilita el envío de comprobantes en formato de imagen por WhatsApp cuando el método de pago es con Tarjeta de Credito o Débito con PayPal",
|
||||||
|
"required": 0,
|
||||||
|
"type": "checkbox"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"key": "creditCardStripePaymentMethodId",
|
||||||
|
"label": "Envío de Comprobante por pago de Tarjeta de Crédito o Débito por medio de Stripe",
|
||||||
|
"description": "Habilita el envío de comprobantes en formato de imagen por WhatsApp cuando el método de pago es con Tarjeta de Crédito o Débito por medio de Stripe",
|
||||||
|
"required": 0,
|
||||||
|
"type": "checkbox"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"key": "stripeSubscriptionCreditCardPaymentMethodId",
|
||||||
|
"label": "Envío de Comprobante por pago con una Suscripción de Stripe (tarjeta de crédito)",
|
||||||
|
"description": "Habilita el envío de comprobantes en formato de imagen por WhatsApp cuando el método de pago es por una Suscripción de Stripe (tarjeta de crédito)",
|
||||||
|
"required": 0,
|
||||||
|
"type": "checkbox"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"key": "paypalSubscriptionPaymentMethodId",
|
||||||
|
"label": "Envío de Comprobante por pago con Suscripción de PayPal",
|
||||||
|
"description": "Habilita el envío de comprobantes en formato de imagen por WhatsApp cuando el método de pago es por Suscripción de PayPal",
|
||||||
|
"required": 0,
|
||||||
|
"type": "checkbox"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"key": "mercadopagoPaymentMethodId",
|
||||||
|
"label": "Envío de Comprobante por pago de MercadoPago",
|
||||||
|
"description": "Habilita el envío de comprobantes en formato de imagen por WhatsApp cuando el método de pago es por MercadoPago",
|
||||||
|
"required": 0,
|
||||||
|
"type": "checkbox"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"key": "checkPaymentMethodId",
|
||||||
|
"label": "Envío de Comprobante por pago de Cheque",
|
||||||
|
"description": "Habilita el envío de comprobantes en formato de imagen por WhatsApp cuando el método de pago es por Cheque",
|
||||||
|
"required": 0,
|
||||||
|
"type": "checkbox"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"key": "customPaymentMethodId",
|
||||||
|
"label": "Envío de Comprobante por pago Personalizado",
|
||||||
|
"description": "Habilita el envío de comprobantes en formato de imagen por WhatsApp cuando el método de pago es Personalizado",
|
||||||
|
"required": 0,
|
||||||
|
"type": "checkbox"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"key": "notificationTypeText",
|
||||||
|
"label": "Envío de Comprobante por medio de plantilla de texto",
|
||||||
|
"description": "Habilita el envío de comprobantes en formato TEXTO por WhatsApp, si está deshabilitado se utiliza el formato de imagen.",
|
||||||
|
"required": 0,
|
||||||
|
"type": "checkbox"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"key": "dataInstallersWhatsApp",
|
||||||
|
"label": "Datos de los instaladores en formato JSON",
|
||||||
|
"required": 1,
|
||||||
|
"type": "text"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"key": "debugMode",
|
||||||
|
"label": "Debug Mode?",
|
||||||
|
"description": "More detailed log info - Informacion de log mas detallada",
|
||||||
|
"required": 0,
|
||||||
|
"type": "checkbox"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"key": "logging_level",
|
||||||
|
"label": "enable debug logs",
|
||||||
|
"description": "Make the plugin more verbose.",
|
||||||
|
"type": "checkbox",
|
||||||
|
"required": 0
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"menu": [
|
||||||
|
{
|
||||||
|
"key": "Reports",
|
||||||
|
"label": "Borrar comprobantes Wordpress",
|
||||||
|
"type": "admin",
|
||||||
|
"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
|
||||||
|
}
|
||||||
147
public.php
Executable file
147
public.php
Executable file
@ -0,0 +1,147 @@
|
|||||||
|
<?php
|
||||||
|
use Ubnt\UcrmPluginSdk\Service\PluginLogManager;
|
||||||
|
use Ubnt\UcrmPluginSdk\Service\PluginConfigManager;
|
||||||
|
|
||||||
|
require_once 'main.php';
|
||||||
|
|
||||||
|
// Función para imprimir una tabla
|
||||||
|
// function imprimirTabla()
|
||||||
|
// {
|
||||||
|
// echo '
|
||||||
|
// <table border="1">
|
||||||
|
// <tr>
|
||||||
|
// <th>Archivos PDF</th>
|
||||||
|
// <th>Resultado</th>
|
||||||
|
// </tr>
|
||||||
|
// ';
|
||||||
|
|
||||||
|
// borrarArchivosPDFWordpress();
|
||||||
|
// echo '</table>
|
||||||
|
// ';
|
||||||
|
// }
|
||||||
|
|
||||||
|
// function borrarArchivosPDFWordpress()
|
||||||
|
// {
|
||||||
|
// $log = PluginLogManager::create(); //Initialize Logger
|
||||||
|
// $configManager = PluginConfigManager::create();
|
||||||
|
// $config = $configManager->loadConfig();
|
||||||
|
|
||||||
|
// // Configuración de conexión FTP
|
||||||
|
// $ftp_server = $config['hostServerFTP'];
|
||||||
|
// $ftp_username = $config['usernameServerFTP'];
|
||||||
|
// $ftp_password = $config['passServerFTP'];
|
||||||
|
// $remote_folder = "/public_html/wp/wp-content/uploads/img/";
|
||||||
|
|
||||||
|
// // 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);
|
||||||
|
|
||||||
|
// // 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 5 más recientes)
|
||||||
|
// $filesToDelete = array_slice(array_keys($filesWithTime), 5);
|
||||||
|
|
||||||
|
// // Eliminar archivos antiguos
|
||||||
|
// foreach ($filesToDelete as $file) {
|
||||||
|
// if (ftp_delete($ftp_conn, $remote_folder . $file)) {
|
||||||
|
// echo '<tr><td>' . $file . '</td><td>Archivo borrado</td></tr>';
|
||||||
|
// } else {
|
||||||
|
// echo '<tr><td>' . $file . '</td><td>Error al borrar archivo</td></tr>';
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// $log->appendLog("Archivos eliminados" . PHP_EOL);
|
||||||
|
// } else {
|
||||||
|
// $log->appendLog("No se pudo obtener la lista de archivos de la carpeta FTP" . PHP_EOL);
|
||||||
|
// }
|
||||||
|
// // Cerrar conexión FTP
|
||||||
|
// ftp_close($ftp_conn);
|
||||||
|
// } else {
|
||||||
|
// $log->appendLog("No se pudo conectar o iniciar sesión en el servidor FTP." . PHP_EOL);
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
// // Verificar si se ha enviado una solicitud POST
|
||||||
|
// if ($_SERVER["REQUEST_METHOD"] == "POST" && isset($_POST["pintar"])) {
|
||||||
|
// // Llamar a la función para imprimir la tabla
|
||||||
|
// imprimirTabla();
|
||||||
|
|
||||||
|
// }
|
||||||
|
|
||||||
|
// // Contenido HTML para el formulario con el botón
|
||||||
|
// $html = '
|
||||||
|
// <!DOCTYPE html>
|
||||||
|
// <html lang="es">
|
||||||
|
// <head>
|
||||||
|
// <meta charset="UTF-8">
|
||||||
|
// <meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
|
// <style>
|
||||||
|
// body {
|
||||||
|
// font-family: Arial, sans-serif;
|
||||||
|
// background-color: #f0f0f0;
|
||||||
|
// margin: 0;
|
||||||
|
// padding: 20px;
|
||||||
|
// }
|
||||||
|
// h1 {
|
||||||
|
// text-align: center;
|
||||||
|
// color: #333;
|
||||||
|
// }
|
||||||
|
// table {
|
||||||
|
// width: 100%;
|
||||||
|
// border-collapse: collapse;
|
||||||
|
// border: 2px solid #333;
|
||||||
|
// margin-bottom: 20px;
|
||||||
|
// }
|
||||||
|
// th, td {
|
||||||
|
// padding: 10px;
|
||||||
|
// border: 1px solid #999;
|
||||||
|
// }
|
||||||
|
// th {
|
||||||
|
// background-color: #f2f2f2;
|
||||||
|
// }
|
||||||
|
// tr:nth-child(even) {
|
||||||
|
// background-color: #f9f9f9;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// .container {
|
||||||
|
// display: flex;
|
||||||
|
// justify-content: center;
|
||||||
|
// align-items: center;
|
||||||
|
|
||||||
|
// }
|
||||||
|
// </style>
|
||||||
|
// </head>
|
||||||
|
// <body>
|
||||||
|
// <h1>Limpieza de archivos PDF de comprobantes de pago subidos a Wordpress para su envío</h1>
|
||||||
|
// <div class="container">
|
||||||
|
// <form method="post">
|
||||||
|
// <button type="submit" name="pintar">Ejecutar borrado de archivos</button>
|
||||||
|
// </form>
|
||||||
|
// </div>
|
||||||
|
|
||||||
|
// </body>
|
||||||
|
// </html>
|
||||||
|
// ';
|
||||||
|
// echo $html;
|
||||||
BIN
siip-whatsapp-notifications.zip
Normal file
BIN
siip-whatsapp-notifications.zip
Normal file
Binary file not shown.
72
src/Data/NotificationData.php
Executable file
72
src/Data/NotificationData.php
Executable file
@ -0,0 +1,72 @@
|
|||||||
|
<?php
|
||||||
|
/*
|
||||||
|
* @copyright Copyright (c) 2018 Ubiquiti Networks, Inc.
|
||||||
|
* @see https://www.ubnt.com/
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
|
||||||
|
namespace SmsNotifier\Data;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* data received in webhook, plus details loaded from UCRM API
|
||||||
|
*/
|
||||||
|
class NotificationData
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
public $uuid;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
public $changeType;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
public $entity;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var int|null
|
||||||
|
*/
|
||||||
|
public $entityId;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var string|null
|
||||||
|
*/
|
||||||
|
public $message;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var int|null
|
||||||
|
*/
|
||||||
|
public $clientId;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
public $eventName;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var array|null
|
||||||
|
*/
|
||||||
|
public $clientData;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var array|null
|
||||||
|
*/
|
||||||
|
public $serviceData;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var array|null
|
||||||
|
*/
|
||||||
|
public $invoiceData;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var array|null
|
||||||
|
*/
|
||||||
|
public $paymentData;
|
||||||
|
}
|
||||||
152
src/Data/PluginData.php
Executable file
152
src/Data/PluginData.php
Executable file
@ -0,0 +1,152 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
|
||||||
|
namespace SmsNotifier\Data;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* data entered in plugin's config
|
||||||
|
*/
|
||||||
|
class PluginData extends UcrmData
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
public $twilioAccountSid;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
public $twilioAuthToken;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
public $twilioSmsNumber;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
public $displayedErrors;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
public $event_client_add;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
public $event_client_archive;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
public $event_client_delete;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
public $event_client_edit;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
public $event_invoice_add;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
public $event_invoice_add_draft;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
public $event_invoice_draft_approved;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
public $event_invoice_delete;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
public $event_invoice_edit;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
public $event_payment_add;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
public $event_payment_delete;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
public $event_payment_edit;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
public $event_payment_unmatch;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
public $event_service_activate;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
public $event_service_add;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
public $event_service_archive;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
public $event_service_end;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
public $event_service_postpone;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
public $event_service_suspend_cancel;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
public $event_service_suspend;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
public $event_invoice_near_due;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
public $event_invoice_overdue;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
public $event_client_message;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
public $logging_level;
|
||||||
|
}
|
||||||
32
src/Data/UcrmData.php
Executable file
32
src/Data/UcrmData.php
Executable file
@ -0,0 +1,32 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
|
||||||
|
namespace SmsNotifier\Data;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* automatically filled data for UCRM API
|
||||||
|
*/
|
||||||
|
class UcrmData
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
public $pluginAppKey;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
public $ucrmPublicUrl;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var string|null
|
||||||
|
*/
|
||||||
|
public $ucrmLocalUrl;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
public $pluginPublicUrl;
|
||||||
|
}
|
||||||
9
src/Exception/CurlException.php
Executable file
9
src/Exception/CurlException.php
Executable file
@ -0,0 +1,9 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace SmsNotifier\Exception;
|
||||||
|
|
||||||
|
class CurlException extends \Exception
|
||||||
|
{
|
||||||
|
}
|
||||||
586
src/Facade/AbstractMessageNotifierFacade.php
Executable file
586
src/Facade/AbstractMessageNotifierFacade.php
Executable file
@ -0,0 +1,586 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace SmsNotifier\Facade;
|
||||||
|
|
||||||
|
use SmsNotifier\Data\NotificationData;
|
||||||
|
use SmsNotifier\Factory\MessageTextFactory;
|
||||||
|
use SmsNotifier\Service\Logger;
|
||||||
|
use SmsNotifier\Service\SmsNumberProvider;
|
||||||
|
use Twilio\Exceptions\HttpException;
|
||||||
|
use SmsNotifier\Facade\ClientCallBellAPI;
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* send message to client's number
|
||||||
|
*/
|
||||||
|
|
||||||
|
abstract class AbstractMessageNotifierFacade
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @var Logger
|
||||||
|
*/
|
||||||
|
protected $logger;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var MessageTextFactory
|
||||||
|
*/
|
||||||
|
protected $messageTextFactory;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var SmsNumberProvider
|
||||||
|
*/
|
||||||
|
protected $clientPhoneNumber;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
public function __construct(
|
||||||
|
Logger $logger,
|
||||||
|
MessageTextFactory $messageTextFactory,
|
||||||
|
SmsNumberProvider $clientPhoneNumber
|
||||||
|
) {
|
||||||
|
$this->logger = $logger;
|
||||||
|
$this->messageTextFactory = $messageTextFactory;
|
||||||
|
$this->clientPhoneNumber = $clientPhoneNumber;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Verify contact type numbers to do notification, update or both
|
||||||
|
*/
|
||||||
|
public function verifyPaymentActionToDo(NotificationData $notificationData): void
|
||||||
|
{
|
||||||
|
|
||||||
|
//$this->logger->debug(print_r(json_encode($notificationData),true).PHP_EOL);
|
||||||
|
|
||||||
|
$arrayPhones = $this->clientPhoneNumber->getUcrmClientNumbers($notificationData);
|
||||||
|
// Procesar el array de teléfonos y ejecutar la función correspondiente
|
||||||
|
|
||||||
|
foreach ($arrayPhones as $type => $phone) {
|
||||||
|
|
||||||
|
switch ($type) {
|
||||||
|
case 'WhatsApp':
|
||||||
|
$this->notifyAndUpdate($notificationData, $phone); // Ejecuta función de Notificar y Actualizar
|
||||||
|
break;
|
||||||
|
case 'WhatsNotifica':
|
||||||
|
$this->notify($notificationData, $phone); // Ejecuta función de Notificar
|
||||||
|
break;
|
||||||
|
case 'WhatsActualiza':
|
||||||
|
$this->onlyUpdate($notificationData, $phone); // Ejecuta función de Actualizar
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
$this->logger->info("Tipo de contacto no reconocido: $type" . PHP_EOL);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Verify contact type numbers to do client's data update at CallBell
|
||||||
|
*/
|
||||||
|
public function verifyClientActionToDo(NotificationData $notificationData): void
|
||||||
|
{
|
||||||
|
|
||||||
|
//$this->logger->debug(print_r(json_encode($notificationData),true).PHP_EOL);
|
||||||
|
|
||||||
|
$arrayPhones = $this->clientPhoneNumber->getUcrmClientNumbers($notificationData);
|
||||||
|
// Procesar el array de teléfonos y ejecutar la función correspondiente
|
||||||
|
|
||||||
|
foreach ($arrayPhones as $type => $phone) {
|
||||||
|
|
||||||
|
switch ($type) {
|
||||||
|
case 'WhatsApp':
|
||||||
|
$this->onlyUpdate($notificationData, $phone); // Ejecuta función de Notificar y Actualizar
|
||||||
|
break;
|
||||||
|
case 'WhatsActualiza':
|
||||||
|
$this->onlyUpdate($notificationData, $phone); // Ejecuta función de Actualizar
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
$this->logger->info("Tipo de contacto no reconocido: $type" . PHP_EOL);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
* Verify contact type numbers to do client's data service status at CallBell
|
||||||
|
*/
|
||||||
|
public function verifyServiceActionToDo(NotificationData $notificationData): void
|
||||||
|
{
|
||||||
|
|
||||||
|
//$this->logger->debug(print_r(json_encode($notificationData),true).PHP_EOL);
|
||||||
|
|
||||||
|
$arrayPhones = $this->clientPhoneNumber->getUcrmClientNumbers($notificationData);
|
||||||
|
// Procesar el array de teléfonos y ejecutar la función correspondiente
|
||||||
|
|
||||||
|
foreach ($arrayPhones as $type => $phone) {
|
||||||
|
|
||||||
|
switch ($type) {
|
||||||
|
case 'WhatsApp':
|
||||||
|
$this->onlyUpdateService($notificationData, $phone); // Ejecuta función de Notificar y Actualizar
|
||||||
|
break;
|
||||||
|
case 'WhatsActualiza':
|
||||||
|
$this->onlyUpdateService($notificationData, $phone); // Ejecuta función de Actualizar
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
$this->logger->info("Tipo de contacto no reconocido: $type" . PHP_EOL);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Verify contact type numbers to do client's data update at CallBell by invoice add or edit
|
||||||
|
*/
|
||||||
|
public function verifyInvoiceActionToDo(NotificationData $notificationData): void
|
||||||
|
{
|
||||||
|
|
||||||
|
$this->logger->debug(print_r(json_encode($notificationData), true) . PHP_EOL);
|
||||||
|
|
||||||
|
$arrayPhones = $this->clientPhoneNumber->getUcrmClientNumbers($notificationData);
|
||||||
|
// Procesar el array de teléfonos y ejecutar la función correspondiente
|
||||||
|
|
||||||
|
foreach ($arrayPhones as $type => $phone) {
|
||||||
|
|
||||||
|
switch ($type) {
|
||||||
|
case 'WhatsApp':
|
||||||
|
$this->onlyUpdate($notificationData, $phone); // Ejecuta función de Notificar y Actualizar
|
||||||
|
break;
|
||||||
|
case 'WhatsActualiza':
|
||||||
|
$this->onlyUpdate($notificationData, $phone); // Ejecuta función de Actualizar
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
$this->logger->info("Tipo de contacto no reconocido: $type" . PHP_EOL);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Notify to client with the payment receipt via WhatsApp
|
||||||
|
*/
|
||||||
|
public function notify(NotificationData $notificationData, $phoneToNotify = null): void
|
||||||
|
{
|
||||||
|
|
||||||
|
// $notification_client_data = $notificationData->clientData; //array con los datos del cliente
|
||||||
|
|
||||||
|
// $notification_client_data_export = json_encode($notification_client_data);
|
||||||
|
// $this->logger->info("Valor de notification client data export: " . $notification_client_data_export . PHP_EOL);
|
||||||
|
$configManager = \Ubnt\UcrmPluginSdk\Service\PluginConfigManager::create();
|
||||||
|
$config = $configManager->loadConfig();
|
||||||
|
// the "exportFormat" key must be defined in plugin's manifest file, see the link above
|
||||||
|
$IPServer = $config['ipserver'];
|
||||||
|
$UCRMAPIToken = $config['apitoken'];
|
||||||
|
$CallBellAPIToken = $config['tokencallbell'];
|
||||||
|
$notificationTypeText = $config['notificationTypeText'];
|
||||||
|
|
||||||
|
|
||||||
|
$client_callbell_api = new ClientCallBellAPI($UCRMAPIToken, $IPServer, $CallBellAPIToken);
|
||||||
|
|
||||||
|
//$clientPhoneNumber = $this->clientPhoneNumber->getUcrmClientNumber($notificationData);
|
||||||
|
$clientPhoneNumber = $this->validarNumeroTelefono($phoneToNotify); //Obtiene el número de celular del cliente que sea del tipo de contacto "WhatsApp"
|
||||||
|
|
||||||
|
//$this->logger->debug("Numero de cel obtenido " . $clientPhoneNumber . PHP_EOL);
|
||||||
|
|
||||||
|
|
||||||
|
if (empty($clientPhoneNumber)) {
|
||||||
|
$this->logger->warning('No se encontró un teléfono celular válido para el cliente: ' . $notificationData->clientId);
|
||||||
|
return;
|
||||||
|
} else {
|
||||||
|
|
||||||
|
|
||||||
|
if ($notificationTypeText) {
|
||||||
|
try {
|
||||||
|
//$this->logger->debug(sprintf('llego al llamado de sendPaymentNotificationWhatsApp con client_id: %s y número de celular: %s', $notificationData->clientId, $clientPhoneNumber));
|
||||||
|
//$this->sendMessage($notificationData, $clientSmsNumber, $messageBody);
|
||||||
|
//$this->sendWhatsApp($notificationData, $clientSmsNumber);
|
||||||
|
if (!$client_callbell_api->sendTextPaymentNotificationWhatsApp($clientPhoneNumber, $notificationData)) {
|
||||||
|
$this->logger->warning("No se pudo enviar el comprobante para este cliente" . PHP_EOL);
|
||||||
|
}
|
||||||
|
|
||||||
|
} catch (HttpException $httpException) {
|
||||||
|
//$this->logger->debug('Ocurrio un error en el try catch');
|
||||||
|
$this->logger->error($httpException->getCode() . ' ' . $httpException->getMessage());
|
||||||
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
try {
|
||||||
|
//$this->logger->debug(sprintf('llego al llamado de sendPaymentNotificationWhatsApp con client_id: %s y número de celular: %s', $notificationData->clientId, $clientPhoneNumber));
|
||||||
|
//$this->sendMessage($notificationData, $clientSmsNumber, $messageBody);
|
||||||
|
//$this->sendWhatsApp($notificationData, $clientSmsNumber);
|
||||||
|
if (!$client_callbell_api->sendPaymentNotificationWhatsApp($clientPhoneNumber, $notificationData)) {
|
||||||
|
$this->logger->warning("No se pudo enviar el comprobante para este cliente" . PHP_EOL);
|
||||||
|
}
|
||||||
|
|
||||||
|
} catch (HttpException $httpException) {
|
||||||
|
//$this->logger->debug('Ocurrio un error en el try catch');
|
||||||
|
$this->logger->error($httpException->getCode() . ' ' . $httpException->getMessage());
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// $messageBody = $this->messageTextFactory->createBody($notificationData);
|
||||||
|
// if (! $messageBody) {
|
||||||
|
// $this->logger->info('No text configured for event: ' . $notificationData->eventName);
|
||||||
|
// return;
|
||||||
|
// }
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Notify to client with the payment receipt via WhatsApp and Update the client's data at CallBell
|
||||||
|
*/
|
||||||
|
public function notifyAndUpdate(NotificationData $notificationData, $phoneToNotifyAndUpdate = null): void
|
||||||
|
{
|
||||||
|
$this->logger->debug("***Se notifica y actualiza al cliente sobre su pago***" . PHP_EOL);
|
||||||
|
|
||||||
|
// $notification_client_data = $notificationData->clientData; //array con los datos del cliente
|
||||||
|
|
||||||
|
// $notification_client_data_export = json_encode($notification_client_data);
|
||||||
|
// $this->logger->info("Valor de notification client data export: " . $notification_client_data_export . PHP_EOL);
|
||||||
|
//$this->logger->debug("Creando instancia callbell ".PHP_EOL);
|
||||||
|
$configManager = \Ubnt\UcrmPluginSdk\Service\PluginConfigManager::create();
|
||||||
|
$config = $configManager->loadConfig();
|
||||||
|
// the "exportFormat" key must be defined in plugin's manifest file, see the link above
|
||||||
|
$IPServer = $config['ipserver'];
|
||||||
|
$UCRMAPIToken = $config['apitoken'];
|
||||||
|
$CallBellAPIToken = $config['tokencallbell'];
|
||||||
|
$notificationTypeText = $config['notificationTypeText'];
|
||||||
|
|
||||||
|
|
||||||
|
$client_callbell_api = new ClientCallBellAPI($UCRMAPIToken, $IPServer, $CallBellAPIToken);
|
||||||
|
//$this->logger->debug(" instancia callbell creada".PHP_EOL);
|
||||||
|
//$clientPhoneNumber = $this->validarNumeroTelefono($this->clientPhoneNumber->getUcrmClientNumber($notificationData));
|
||||||
|
|
||||||
|
//$clientPhoneNumber = $this->clientPhoneNumber->getUcrmClientNumber($notificationData);
|
||||||
|
//$clientPhoneNumber = $this->validarNumeroTelefono($this->clientPhoneNumber->getUcrmClientNumber($notificationData)); //Obtiene el número de celular del cliente que sea del tipo de contacto "WhatsApp"
|
||||||
|
|
||||||
|
$clientPhoneNumber = $this->validarNumeroTelefono($phoneToNotifyAndUpdate);
|
||||||
|
|
||||||
|
|
||||||
|
if (empty($clientPhoneNumber)) {
|
||||||
|
$this->logger->warning('No se encontró un teléfono celular válido para el cliente: ' . $notificationData->clientId);
|
||||||
|
return;
|
||||||
|
} else {
|
||||||
|
|
||||||
|
|
||||||
|
//$this->logger->debug(sprintf('llego al llamado de sendPaymentNotificationWhatsApp con client_id: %s y número de celular: %s', $notificationData->clientId, $clientPhoneNumber));
|
||||||
|
|
||||||
|
if ($notificationTypeText) {
|
||||||
|
$this->logger->debug("Activado el check de mensajes de texto: ".$notificationTypeText.PHP_EOL);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($notificationTypeText) {
|
||||||
|
try {
|
||||||
|
|
||||||
|
if ($client_callbell_api->sendTextPaymentNotificationWhatsApp($clientPhoneNumber, $notificationData)) {
|
||||||
|
$response_getContactCallBell = json_decode($client_callbell_api->getContactWhatsapp($clientPhoneNumber), true);
|
||||||
|
$client_callbell_api->patchWhatsapp($response_getContactCallBell, $notificationData);
|
||||||
|
} else {
|
||||||
|
$this->logger->warning("No se pudo enviar el comprobante para este cliente" . PHP_EOL);
|
||||||
|
}
|
||||||
|
} catch (\Exception $Exception) {
|
||||||
|
$this->logger->error($Exception->getCode() . ' ' . $Exception->getMessage());
|
||||||
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
|
||||||
|
try {
|
||||||
|
if ($client_callbell_api->sendPaymentNotificationWhatsApp($clientPhoneNumber, $notificationData)) {
|
||||||
|
$response_getContactCallBell = json_decode($client_callbell_api->getContactWhatsapp($clientPhoneNumber), true);
|
||||||
|
$client_callbell_api->patchWhatsapp($response_getContactCallBell, $notificationData);
|
||||||
|
} else {
|
||||||
|
$this->logger->warning("No se pudo enviar el comprobante para este cliente" . PHP_EOL);
|
||||||
|
}
|
||||||
|
|
||||||
|
} catch (\Exception $Exception) {
|
||||||
|
$this->logger->error($Exception->getCode() . ' ' . $Exception->getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// $messageBody = $this->messageTextFactory->createBody($notificationData);
|
||||||
|
// if (! $messageBody) {
|
||||||
|
// $this->logger->info('No text configured for event: ' . $notificationData->eventName);
|
||||||
|
// return;
|
||||||
|
// }
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Notify to client about Invoice Overdue
|
||||||
|
*/
|
||||||
|
public function notifyOverDue(NotificationData $notificationData): void
|
||||||
|
{
|
||||||
|
$this->logger->debug("***Se notifica al cliente que la factura de su servicio está vencida***" . PHP_EOL);
|
||||||
|
|
||||||
|
// $notification_client_data = $notificationData->clientData; //array con los datos del cliente
|
||||||
|
|
||||||
|
// $notification_client_data_export = json_encode($notification_client_data);
|
||||||
|
// $this->logger->info("Valor de notification client data export: " . $notification_client_data_export . PHP_EOL);
|
||||||
|
//$this->logger->debug("Creando instancia callbell ".PHP_EOL);
|
||||||
|
$configManager = \Ubnt\UcrmPluginSdk\Service\PluginConfigManager::create();
|
||||||
|
$config = $configManager->loadConfig();
|
||||||
|
// the "exportFormat" key must be defined in plugin's manifest file, see the link above
|
||||||
|
$IPServer = $config['ipserver'];
|
||||||
|
$UCRMAPIToken = $config['apitoken'];
|
||||||
|
$CallBellAPIToken = $config['tokencallbell'];
|
||||||
|
|
||||||
|
|
||||||
|
$client_callbell_api = new ClientCallBellAPI($UCRMAPIToken, $IPServer, $CallBellAPIToken);
|
||||||
|
//$this->logger->debug(" instancia callbell creada".PHP_EOL);
|
||||||
|
//$clientPhoneNumber = $this->validarNumeroTelefono($this->clientPhoneNumber->getUcrmClientNumber($notificationData));
|
||||||
|
$clientPhoneNumber = $this->clientPhoneNumber->getUcrmClientNumber($notificationData);
|
||||||
|
$this->logger->debug("Numero de cel obtenido " . $clientPhoneNumber . PHP_EOL);
|
||||||
|
|
||||||
|
|
||||||
|
if (empty($clientPhoneNumber)) {
|
||||||
|
$this->logger->warning('No se encontró un teléfono celular válido para el cliente: ' . $notificationData->clientId);
|
||||||
|
return;
|
||||||
|
} else {
|
||||||
|
|
||||||
|
try {
|
||||||
|
//$this->logger->debug(sprintf('llego al llamado de sendPaymentNotificationWhatsApp con client_id: %s y número de celular: %s', $notificationData->clientId, $clientPhoneNumber));
|
||||||
|
//$this->sendMessage($notificationData, $clientSmsNumber, $messageBody);
|
||||||
|
//$this->sendWhatsApp($notificationData, $clientSmsNumber);
|
||||||
|
|
||||||
|
$client_callbell_api->sendOverdueNotificationWhatsApp($clientPhoneNumber, $notificationData);
|
||||||
|
|
||||||
|
} catch (HttpException $httpException) {
|
||||||
|
//$this->logger->debug('Ocurrio un error en el try catch');
|
||||||
|
$this->logger->error($httpException->getCode() . ' ' . $httpException->getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// $messageBody = $this->messageTextFactory->createBody($notificationData);
|
||||||
|
// if (! $messageBody) {
|
||||||
|
// $this->logger->info('No text configured for event: ' . $notificationData->eventName);
|
||||||
|
// return;
|
||||||
|
// }
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Update the client's data at CallBell
|
||||||
|
*/
|
||||||
|
public function onlyUpdate(NotificationData $notificationData, $phoneToUpdate = null): void
|
||||||
|
{
|
||||||
|
//$this->logger->info("Se enviará una actualización a Callbell " . PHP_EOL);
|
||||||
|
|
||||||
|
$notification_client_data = $notificationData->clientData; //array con los datos del cliente
|
||||||
|
|
||||||
|
// $notification_client_data_export = json_encode($notification_client_data);
|
||||||
|
// $this->logger->info("Valor de notification client data export: " . $notification_client_data_export . PHP_EOL);
|
||||||
|
|
||||||
|
$configManager = \Ubnt\UcrmPluginSdk\Service\PluginConfigManager::create();
|
||||||
|
$config = $configManager->loadConfig();
|
||||||
|
// the "exportFormat" key must be defined in plugin's manifest file, see the link above
|
||||||
|
$IPServer = $config['ipserver'];
|
||||||
|
$UCRMAPIToken = $config['apitoken'];
|
||||||
|
$CallBellAPIToken = $config['tokencallbell'];
|
||||||
|
$StripeToken = $config['tokenstripe'];
|
||||||
|
|
||||||
|
$attributes = $notificationData->clientData['attributes']; //Obtener los atributos del cliente
|
||||||
|
// Variable para almacenar los valores de los atributos que comienzan con "clabe"
|
||||||
|
|
||||||
|
|
||||||
|
// Iterar sobre los atributoss
|
||||||
|
foreach ($attributes as $attribute) {
|
||||||
|
// Verificar si la "key" comienza con "stripe"
|
||||||
|
if (strpos($attribute['key'], 'stripe') === 0) {
|
||||||
|
// Agregar el valor al array $clabeValues
|
||||||
|
$customerStripeID = $attribute['value'];
|
||||||
|
} else if (strpos($attribute['key'], 'clabe') === 0) {// Verificar si la "key" comienza con "clabe"
|
||||||
|
// Agregar el valor al array $clabeValues
|
||||||
|
$clabeInterbancaria = $attribute['value'];
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
$contacts = $notificationData->clientData['contacts'] ?? []; //Obtener los contactos que tiene el cliente
|
||||||
|
|
||||||
|
foreach ($contacts as $contact) {
|
||||||
|
|
||||||
|
$types = $contact['types'] ?? []; //Obtener los tipos de contactos del cliente
|
||||||
|
foreach ($types as $type) {
|
||||||
|
|
||||||
|
if ($type['name'] == 'WhatsApp') { //Si el tipo de contacto es Whatsapp
|
||||||
|
|
||||||
|
$client_email = $contact['email']; //Asignar el correo del cliente a la variable
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
$this->logger->info("Se proceso los contactos " . PHP_EOL);
|
||||||
|
|
||||||
|
$stripe = new \Stripe\StripeClient($StripeToken); //Instancia de la clase manejadora de clientes para la API de Stripe
|
||||||
|
if (!empty($client_email)) {
|
||||||
|
$stripe->customers->update($customerStripeID, ['email' => $client_email]); //Actualiza el correo electrónico del cliente en la plataforma de Stripe en su correspondiente "customer Stripe ID"
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
$clientPhoneNumber = $this->validarNumeroTelefono($phoneToUpdate); //Obtiene el número de celular del cliente que sea del tipo de contacto "WhatsApp"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
if (empty($clientPhoneNumber)) {
|
||||||
|
$this->logger->warning('No se encontró un teléfono celular válido para el cliente: ' . $notificationData->clientId);
|
||||||
|
return;
|
||||||
|
} else {
|
||||||
|
|
||||||
|
try {
|
||||||
|
//$this->logger->debug(sprintf('llego al llamado de sendwhatsapp con client_id: %s y número de celular: %s', $notificationData->clientId, $clientPhoneNumber));
|
||||||
|
//$this->sendMessage($notificationData, $clientSmsNumber, $messageBody);
|
||||||
|
//$this->sendWhatsApp($notificationData, $clientSmsNumber);
|
||||||
|
|
||||||
|
//$client_callbell_api->sendMessageWhatsApp($clientPhoneNumber, $notificationData);
|
||||||
|
$client_callbell_api = new ClientCallBellAPI($UCRMAPIToken, $IPServer, $CallBellAPIToken);
|
||||||
|
$response_getContactCallBell = json_decode($client_callbell_api->getContactWhatsapp($clientPhoneNumber), true);
|
||||||
|
//$this->logger->debug('Se hizo la petición al callbell para obtener el uuid' . PHP_EOL);
|
||||||
|
$client_callbell_api->patchWhatsapp($response_getContactCallBell, $notificationData, $clabeInterbancaria);
|
||||||
|
|
||||||
|
} catch (HttpException $httpException) {
|
||||||
|
//$this->logger->debug('Ocurrio un error en el try catch');
|
||||||
|
$this->logger->error($httpException->getCode() . ' ' . $httpException->getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// $notificationData_export = var_export($notificationData, true);
|
||||||
|
// $this->logger->debug('valor de notificationdata: ' . $notificationData_export);
|
||||||
|
|
||||||
|
// $messageBody = $this->messageTextFactory->createBody($notificationData);
|
||||||
|
// if (! $messageBody) {
|
||||||
|
// $this->logger->info('No text configured for event: ' . $notificationData->eventName);
|
||||||
|
// return;
|
||||||
|
// }
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Update de status of service at CallBell
|
||||||
|
*/
|
||||||
|
public function onlyUpdateService(NotificationData $notificationData, $phoneToUpdate): void
|
||||||
|
{
|
||||||
|
//$this->logger->info("Se enviará una actualización del estado del servicio a Callbell, estado del servicio: ".$notificationData->serviceData['status'] . PHP_EOL);
|
||||||
|
$this->logger->info(json_encode($notificationData) . PHP_EOL);
|
||||||
|
|
||||||
|
//$clientID = $notificationData->extraData['entity']['clientId'];
|
||||||
|
|
||||||
|
//$this->logger->info("client id " .$clientID. PHP_EOL);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
$configManager = \Ubnt\UcrmPluginSdk\Service\PluginConfigManager::create();
|
||||||
|
$config = $configManager->loadConfig();
|
||||||
|
// the "exportFormat" key must be defined in plugin's manifest file, see the link above
|
||||||
|
$IPServer = $config['ipserver'];
|
||||||
|
$UCRMAPIToken = $config['apitoken'];
|
||||||
|
$CallBellAPIToken = $config['tokencallbell'];
|
||||||
|
|
||||||
|
|
||||||
|
$clientPhoneNumber = $this->validarNumeroTelefono($phoneToUpdate); //Obtiene el número de celular del cliente que sea del tipo de contacto "WhatsApp"
|
||||||
|
//$this->logger->info("Número de telefono obtenido para actualizar:" .$clientPhoneNumber. PHP_EOL);
|
||||||
|
|
||||||
|
if (empty($clientPhoneNumber)) {
|
||||||
|
$this->logger->warning('No se encontró un teléfono celular válido para el cliente: ' . $notificationData->clientId);
|
||||||
|
return;
|
||||||
|
} else {
|
||||||
|
|
||||||
|
try {
|
||||||
|
//$this->logger->debug(sprintf('llego al llamado de sendwhatsapp con client_id: %s y número de celular: %s', $notificationData->clientId, $clientPhoneNumber));
|
||||||
|
//$this->sendMessage($notificationData, $clientSmsNumber, $messageBody);
|
||||||
|
//$this->sendWhatsApp($notificationData, $clientSmsNumber);
|
||||||
|
|
||||||
|
$client_callbell_api = new ClientCallBellAPI($UCRMAPIToken, $IPServer, $CallBellAPIToken);
|
||||||
|
$response_getContactCallBell = json_decode($client_callbell_api->getContactWhatsapp($clientPhoneNumber), true);
|
||||||
|
$client_callbell_api->patchServiceStatusWhatsApp($response_getContactCallBell, $notificationData);
|
||||||
|
|
||||||
|
} catch (HttpException $httpException) {
|
||||||
|
//$this->logger->debug('Ocurrio un error en el try catch');
|
||||||
|
$this->logger->error($httpException->getCode() . ' ' . $httpException->getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* implement in subclass with the specific messaging provider
|
||||||
|
* @see TwilioNotifierFacade::sendMessage()
|
||||||
|
*/
|
||||||
|
abstract protected function sendMessage(
|
||||||
|
NotificationData $notificationData,
|
||||||
|
string $clientSmsNumber,
|
||||||
|
string $messageBody
|
||||||
|
): void;
|
||||||
|
|
||||||
|
// /**
|
||||||
|
// * implement in subclass with the specific messaging provider
|
||||||
|
// * @see TwilioNotifierFacade::sendWhatsApp()
|
||||||
|
// */
|
||||||
|
// abstract protected function sendWhatsApp(
|
||||||
|
// NotificationData $notificationData,
|
||||||
|
// string $clientSmsNumber
|
||||||
|
// ): void;
|
||||||
|
|
||||||
|
|
||||||
|
function validarNumeroTelefono($telefono)
|
||||||
|
{
|
||||||
|
// Eliminar espacios y guiones
|
||||||
|
$telefono = preg_replace('/\s+|-/', '', $telefono);
|
||||||
|
|
||||||
|
// Eliminar caracteres no numéricos, excepto el '+' si está al principio
|
||||||
|
$telefono = preg_replace('/(?!^\+)[^0-9]/', '', $telefono);
|
||||||
|
|
||||||
|
// Verificar si el número comienza con "+1" o "1" y tiene 11 dígitos en total
|
||||||
|
if (
|
||||||
|
(substr($telefono, 0, 2) === "+1" && strlen($telefono) === 12) ||
|
||||||
|
(substr($telefono, 0, 1) === "1" && strlen($telefono) === 11)
|
||||||
|
) {
|
||||||
|
return $telefono;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Si el número tiene exactamente 10 dígitos, agregar el prefijo "521"
|
||||||
|
if (strlen($telefono) === 10) {
|
||||||
|
return "521" . $telefono;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Si el número tiene más de 10 dígitos, verificar que comience con "521"
|
||||||
|
if (strlen($telefono) > 10) {
|
||||||
|
if (substr($telefono, 0, 2) === "521" && strlen($telefono) === 12) {
|
||||||
|
return $telefono;
|
||||||
|
} else {
|
||||||
|
// Si no comienza con "52", tomar los últimos 10 dígitos y agregar el prefijo "52"
|
||||||
|
return "521" . substr($telefono, -10);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Si no cumple con ninguna de las condiciones anteriores, retornar cadena vacía
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
342
src/Facade/AbstractOxxoOperationsFacade.php
Executable file
342
src/Facade/AbstractOxxoOperationsFacade.php
Executable file
@ -0,0 +1,342 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace SmsNotifier\Facade;
|
||||||
|
|
||||||
|
use Exception;
|
||||||
|
use SmsNotifier\Factory\MessageTextFactory;
|
||||||
|
use SmsNotifier\Service\Logger;
|
||||||
|
use SmsNotifier\Service\SmsNumberProvider;
|
||||||
|
use GuzzleHttp\Client;
|
||||||
|
use GuzzleHttp\Exception\RequestException;
|
||||||
|
use Ubnt\UcrmPluginSdk\Service\UcrmApi;
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* send message to client's number
|
||||||
|
*/
|
||||||
|
|
||||||
|
abstract class AbstractOxxoOperationsFacade
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @var Logger
|
||||||
|
*/
|
||||||
|
protected $logger;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var MessageTextFactory
|
||||||
|
*/
|
||||||
|
protected $messageTextFactory;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var SmsNumberProvider
|
||||||
|
*/
|
||||||
|
protected $clientPhoneNumber;
|
||||||
|
/**
|
||||||
|
* @var UcrmApi
|
||||||
|
*/
|
||||||
|
protected $ucrmApi;
|
||||||
|
|
||||||
|
protected $stripeCustomAttributeID;
|
||||||
|
protected $clabeInterbancariaBanamexID;
|
||||||
|
|
||||||
|
public function __construct(
|
||||||
|
Logger $logger,
|
||||||
|
MessageTextFactory $messageTextFactory,
|
||||||
|
SmsNumberProvider $clientPhoneNumber
|
||||||
|
) {
|
||||||
|
$this->logger = $logger;
|
||||||
|
$this->messageTextFactory = $messageTextFactory;
|
||||||
|
$this->clientPhoneNumber = $clientPhoneNumber;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Creates a PaymentIntent for OXXO in Stripe for a Customer
|
||||||
|
*/
|
||||||
|
public function createOxxoPaymentIntent($event_json):string
|
||||||
|
{
|
||||||
|
$this->logger->info("Creando referencia del cliente para oxxo: ".PHP_EOL);
|
||||||
|
$configManager = \Ubnt\UcrmPluginSdk\Service\PluginConfigManager::create();
|
||||||
|
$config = $configManager->loadConfig();
|
||||||
|
$StripeToken = $config['tokenstripe'];
|
||||||
|
$IPServer = $config['ipserver'];
|
||||||
|
$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
|
||||||
|
|
||||||
|
$this->ucrmApi = UcrmApi::create();
|
||||||
|
$currentUserAdmin = $this->ucrmApi->get('users/admins',[]);
|
||||||
|
$clientID = $event_json->client_id;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
try {
|
||||||
|
|
||||||
|
|
||||||
|
$clientGuzzleHttp = new Client([
|
||||||
|
'base_uri' => $baseUri,
|
||||||
|
'headers' => [
|
||||||
|
'X-Auth-App-Key' => $tokenCRM, // Cambia el nombre de la cabecera de autorización para el UISP CRM
|
||||||
|
'Accept' => 'application/json', // Indica que esperamos una respuesta en formato JSON
|
||||||
|
],
|
||||||
|
'verify' => false,
|
||||||
|
]);
|
||||||
|
|
||||||
|
// 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);
|
||||||
|
|
||||||
|
// Inicializamos una variable para guardar el valor del 'stripeCustomerId'
|
||||||
|
$stripeCustomerId = null;
|
||||||
|
$clientEmail = '';
|
||||||
|
|
||||||
|
// Recorrer los atributos para encontrar el 'stripeCustomerId'
|
||||||
|
foreach ($arrayClientCRM['attributes'] as $attribute) {
|
||||||
|
if ($attribute['key'] === 'stripeCustomerId') {
|
||||||
|
$stripeCustomerId = $attribute['value'];
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Recorrer los contactos
|
||||||
|
foreach ($arrayClientCRM['contacts'] as $contact) {
|
||||||
|
if ($contact['email'] != '') {
|
||||||
|
$clientEmail = $contact['email'];
|
||||||
|
break;
|
||||||
|
}else{
|
||||||
|
$clientEmail = 'siip8873@gmail.com';
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->logger->info("Se obtuvieron los datos del cliente y Stripe Customer ID: ".$stripeCustomerId.PHP_EOL);
|
||||||
|
|
||||||
|
} catch (RequestException $e) {
|
||||||
|
// Manejo de errores en la petición
|
||||||
|
$this->logger->error("Error al obtener atributos personalizados del cliente: " . $e->getMessage().PHP_EOL);
|
||||||
|
}
|
||||||
|
|
||||||
|
$amount = abs($arrayClientCRM['accountOutstanding']) * 100;
|
||||||
|
|
||||||
|
//$this->logger->info("User Admin ID: " . json_encode($currentUserAdmin) . PHP_EOL);
|
||||||
|
if($amount>0){
|
||||||
|
|
||||||
|
try {
|
||||||
|
// Crear el PaymentIntent vinculado al cliente
|
||||||
|
$paymentIntent = $stripe->paymentIntents->create([
|
||||||
|
'amount' => $amount, // Monto en centavos (300 MXN)
|
||||||
|
'currency' => 'mxn',
|
||||||
|
'payment_method_types' => ['customer_balance', 'card' ,'oxxo'],
|
||||||
|
'description' => 'Pago de servicio de SIIP Internet',
|
||||||
|
'customer' => $stripeCustomerId, // Vincular al cliente existente
|
||||||
|
'metadata' => [
|
||||||
|
'clientId' => $clientID, // ID del cliente en UISP
|
||||||
|
'createdBy' => 'UCRM',
|
||||||
|
'paymentType' => 'card.one_time',
|
||||||
|
'signedInAdminId' => $currentUserAdmin[0]['id']
|
||||||
|
],
|
||||||
|
'payment_method_options' => [
|
||||||
|
'oxxo' => [
|
||||||
|
'expires_after_days' => 3, // El voucher expira en 3 días
|
||||||
|
],
|
||||||
|
],
|
||||||
|
]);
|
||||||
|
|
||||||
|
// Crear un método de pago OXXO con detalles de facturación
|
||||||
|
$paymentMethod = $stripe->paymentMethods->create([
|
||||||
|
'type' => 'oxxo',
|
||||||
|
'billing_details' => [
|
||||||
|
'name' => $arrayClientCRM['firstName'].' '.$arrayClientCRM['lastName'], // Proporciona el nombre del cliente
|
||||||
|
'email' => $clientEmail, // Proporciona el correo del cliente
|
||||||
|
],
|
||||||
|
]);
|
||||||
|
|
||||||
|
// Confirmar el PaymentIntent con el método de pago OXXO
|
||||||
|
$paymentIntent = $stripe->paymentIntents->confirm(
|
||||||
|
$paymentIntent->id,
|
||||||
|
['payment_method' => $paymentMethod->id]
|
||||||
|
);
|
||||||
|
|
||||||
|
// Verificar si hay acciones pendientes (next_action)
|
||||||
|
if (!empty($paymentIntent->next_action) && isset($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_receipt_url = $oxxoPayment->hosted_voucher_url;
|
||||||
|
|
||||||
|
// Mostrar la referencia y la URL del recibo al cliente
|
||||||
|
$this->logger->info("Referencia OXXO: " . $oxxo_reference.PHP_EOL);
|
||||||
|
$this->logger->info("URL del recibo: " . $oxxo_receipt_url.PHP_EOL);
|
||||||
|
return $oxxo_receipt_url;
|
||||||
|
// echo "Referencia OXXO: " . $oxxo_reference . "\n";
|
||||||
|
// echo "URL del recibo: " . $oxxo_receipt_url . "\n";
|
||||||
|
} else {
|
||||||
|
// Manejo de error si no hay detalles de OXXO
|
||||||
|
// echo "El PaymentIntent no tiene detalles de OXXO disponibles aún.\n";
|
||||||
|
// 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';
|
||||||
|
}
|
||||||
|
|
||||||
|
} catch (Exception $e) {
|
||||||
|
// 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';
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// /**
|
||||||
|
// * implement in subclass with the specific messaging provider
|
||||||
|
// * @see TwilioNotifierFacade::sendWhatsApp()
|
||||||
|
// */
|
||||||
|
abstract protected function sendWhatsApp(
|
||||||
|
string $message
|
||||||
|
): void;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
function validarEmail($email)
|
||||||
|
{
|
||||||
|
$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
|
||||||
|
if (filter_var($email, FILTER_VALIDATE_EMAIL)) {
|
||||||
|
// Si el email es válido, devolver el email
|
||||||
|
return $email;
|
||||||
|
} else {
|
||||||
|
// Si el email no es válido, devolver una cadena vacía
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
function UploadReceiptToWordpressByImageFileName($imageFileName): string
|
||||||
|
{
|
||||||
|
|
||||||
|
// $log = PluginLogManager::create(); //Initialize Logger
|
||||||
|
// $configManager = PluginConfigManager::create();
|
||||||
|
// $config = $configManager->loadConfig();
|
||||||
|
|
||||||
|
// // Configuración de conexión FTP
|
||||||
|
// $ftp_server = $config['hostServerFTP'];
|
||||||
|
// $ftp_username = $config['usernameServerFTP'];
|
||||||
|
// $ftp_password = $config['passServerFTP'];
|
||||||
|
|
||||||
|
$remote_folder = "/public_html/wp/wp-content/uploads/img/";
|
||||||
|
|
||||||
|
|
||||||
|
// Configuración de conexión FTP
|
||||||
|
$ftp_server = "siip.mx";
|
||||||
|
$ftp_username = "siip0001";
|
||||||
|
$ftp_password = '$spGiT,[wa)n';
|
||||||
|
$remote_file = "/public_html/wp/wp-content/uploads/img/" . $imageFileName;
|
||||||
|
$file_to_upload = __DIR__ . '/' . $imageFileName;
|
||||||
|
$url = 'https://siip.mx/wp/wp-content/uploads/img/' . $imageFileName;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// 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) {
|
||||||
|
print_r("Conexión FTP exitosa" . PHP_EOL);
|
||||||
|
// $log->appendLog("Conexión FTP exitosa" . PHP_EOL);
|
||||||
|
|
||||||
|
// Cargar archivo
|
||||||
|
if (ftp_put($ftp_conn, $remote_file, $file_to_upload, FTP_BINARY)) {
|
||||||
|
print_r("El archivo ha sido cargado exitosamente." . PHP_EOL);
|
||||||
|
print_r("La URL es: " . $url . PHP_EOL);
|
||||||
|
// $log->appendLog("El archivo ha sido cargado exitosamente." . PHP_EOL);
|
||||||
|
// $log->appendLog("La URL es: " . $url . PHP_EOL);
|
||||||
|
// Cerrar conexión FTP
|
||||||
|
//ftp_close($ftp_conn);
|
||||||
|
//return $url;
|
||||||
|
|
||||||
|
} else {
|
||||||
|
//$log->appendLog("Error al cargar el archivo " . PHP_EOL);
|
||||||
|
print_r("Error al cargar el archivo " . PHP_EOL);
|
||||||
|
ftp_close($ftp_conn);
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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 5 más recientes)
|
||||||
|
$filesToDelete = array_slice(array_keys($filesWithTime), 5);
|
||||||
|
|
||||||
|
// Eliminar archivos antiguos
|
||||||
|
foreach ($filesToDelete as $file) {
|
||||||
|
if (ftp_delete($ftp_conn, $remote_folder . $file)) {
|
||||||
|
print_r("Comprobante eliminado de Wordpress: " . $file . PHP_EOL);
|
||||||
|
// $log->appendLog("Comprobante eliminado de Wordpress: " . $file . PHP_EOL);
|
||||||
|
} else {
|
||||||
|
print_r('Error al borrar comprobante' . $file . PHP_EOL);
|
||||||
|
// $log->appendLog('Error al borrar comprobante' . $file . PHP_EOL);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
print_r("Archivos eliminados" . PHP_EOL);
|
||||||
|
// $log->appendLog("Archivos eliminados" . PHP_EOL);
|
||||||
|
ftp_close($ftp_conn);
|
||||||
|
return $url;
|
||||||
|
} else {
|
||||||
|
print_r("No se pudo obtener la lista de archivos de la carpeta FTP" . PHP_EOL);
|
||||||
|
// $log->appendLog("No se pudo obtener la lista de archivos de la carpeta FTP" . PHP_EOL);
|
||||||
|
ftp_close($ftp_conn);
|
||||||
|
return $url;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Cerrar conexión FTP
|
||||||
|
//ftp_close($ftp_conn);
|
||||||
|
//return '';
|
||||||
|
} else {
|
||||||
|
print_r("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 '';
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
350
src/Facade/AbstractStripeOperationsFacade.php
Executable file
350
src/Facade/AbstractStripeOperationsFacade.php
Executable file
@ -0,0 +1,350 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace SmsNotifier\Facade;
|
||||||
|
|
||||||
|
use Exception;
|
||||||
|
use GuzzleHttp\Exception\GuzzleException;
|
||||||
|
use SmsNotifier\Data\NotificationData;
|
||||||
|
use SmsNotifier\Factory\MessageTextFactory;
|
||||||
|
use SmsNotifier\Service\Logger;
|
||||||
|
use SmsNotifier\Service\SmsNumberProvider;
|
||||||
|
use GuzzleHttp\Client;
|
||||||
|
use Ubnt\UcrmPluginSdk\Service\UcrmApi;
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* send message to client's number
|
||||||
|
*/
|
||||||
|
|
||||||
|
abstract class AbstractStripeOperationsFacade
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @var Logger
|
||||||
|
*/
|
||||||
|
protected $logger;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var MessageTextFactory
|
||||||
|
*/
|
||||||
|
protected $messageTextFactory;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var SmsNumberProvider
|
||||||
|
*/
|
||||||
|
protected $clientPhoneNumber;
|
||||||
|
/**
|
||||||
|
* @var UcrmApi
|
||||||
|
*/
|
||||||
|
protected $ucrmApi;
|
||||||
|
|
||||||
|
protected $stripeCustomAttributeID;
|
||||||
|
protected $clabeInterbancariaBanamexID;
|
||||||
|
|
||||||
|
public function __construct(
|
||||||
|
Logger $logger,
|
||||||
|
MessageTextFactory $messageTextFactory,
|
||||||
|
SmsNumberProvider $clientPhoneNumber
|
||||||
|
) {
|
||||||
|
$this->logger = $logger;
|
||||||
|
$this->messageTextFactory = $messageTextFactory;
|
||||||
|
$this->clientPhoneNumber = $clientPhoneNumber;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Creates a PaymentIntent in Stripe for a Customer
|
||||||
|
*/
|
||||||
|
public function createPaymentIntent($event_json)
|
||||||
|
{
|
||||||
|
$configManager = \Ubnt\UcrmPluginSdk\Service\PluginConfigManager::create();
|
||||||
|
$config = $configManager->loadConfig();
|
||||||
|
$StripeToken = $config['tokenstripe'];
|
||||||
|
$stripe = new \Stripe\StripeClient($StripeToken); //Token de clave privada para la API de Stripe
|
||||||
|
|
||||||
|
$customerId = $event_json->data->object->customer;
|
||||||
|
$amount = $event_json->data->object->net_amount;
|
||||||
|
$stripeQuery = $stripe->customers->retrieve($customerId, []);
|
||||||
|
$UCRM_clientID = $stripeQuery['metadata']['ucrm_client_id'];
|
||||||
|
|
||||||
|
$this->ucrmApi = UcrmApi::create();
|
||||||
|
$currentUserAdmin = $this->ucrmApi->get('users/admins', []);
|
||||||
|
//$this->logger->info("User Admin ID: " . json_encode($currentUserAdmin) . PHP_EOL);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
try {
|
||||||
|
$paymentIntent = $stripe->paymentIntents->create([
|
||||||
|
'amount' => $amount,
|
||||||
|
'currency' => 'mxn',
|
||||||
|
'customer' => $customerId,
|
||||||
|
'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' => $UCRM_clientID, // ID del cliente en Ubiquiti
|
||||||
|
'createdBy' => 'UCRM',
|
||||||
|
'paymentType' => 'card.one_time',
|
||||||
|
'signedInAdminId' => $currentUserAdmin[0]['id'],
|
||||||
|
],
|
||||||
|
]);
|
||||||
|
|
||||||
|
$this->logger->info("PaymentIntent creado: " . $paymentIntent->id . PHP_EOL);
|
||||||
|
|
||||||
|
|
||||||
|
} catch (\Stripe\Exception\ApiErrorException $e) {
|
||||||
|
$this->logger->info("Error creando PaymentIntent: " . $e->getMessage() . PHP_EOL);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
* Creates the Stripe Customer
|
||||||
|
*/
|
||||||
|
public function createStripeClient(NotificationData $notificationData): void
|
||||||
|
{
|
||||||
|
$configManager = \Ubnt\UcrmPluginSdk\Service\PluginConfigManager::create();
|
||||||
|
$config = $configManager->loadConfig();
|
||||||
|
// the "exportFormat" key must be defined in plugin's manifest file, see the link above
|
||||||
|
$IPServer = $config['ipserver'];
|
||||||
|
$UCRMAPIToken = $config['apitoken'];
|
||||||
|
$StripeToken = $config['tokenstripe'];
|
||||||
|
|
||||||
|
//$this->logger->info("Ya dentro del metodo Create Stripe Client " . PHP_EOL);
|
||||||
|
//$this->sendWhatsApp('Hola Dany');
|
||||||
|
|
||||||
|
$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);
|
||||||
|
|
||||||
|
|
||||||
|
// Verificar si se obtuvieron los atributos
|
||||||
|
if ($customAttributes && is_array($customAttributes)) {
|
||||||
|
foreach ($customAttributes as $attribute) {
|
||||||
|
// Verificar si 'name' contiene la palabra 'Stripe' sin distinguir mayúsculas y minúsculas
|
||||||
|
if (isset($attribute['name']) && stripos($attribute['name'], 'Stripe') !== false) {
|
||||||
|
$this->logger->info("ID correspondiente a 'Customer Stripe ID': " . $attribute['id'] . PHP_EOL);
|
||||||
|
$this->stripeCustomAttributeID = $attribute['id'];
|
||||||
|
} else if (isset($attribute['name']) && stripos($attribute['name'], 'Clabe') !== false) {
|
||||||
|
//$this->logger->info("ID correspondiente a 'Clabe Interbancaria Banamex': " . $attribute['id'] .PHP_EOL);
|
||||||
|
$this->clabeInterbancariaBanamexID = $attribute['id'];
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
$this->logger->info("Error al obtener los atributos personalizados." . 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 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
|
||||||
|
|
||||||
|
|
||||||
|
// Verificar si la solicitud fue exitosa (código de estado 200)
|
||||||
|
//https://172.16.5.120/crm/api/v1.0/payments?limit=1&clientId=1992&order=createdDate&direction=DESC
|
||||||
|
|
||||||
|
$notification_client_data = $notificationData->clientData; //array con los datos del cliente
|
||||||
|
|
||||||
|
$notification_client_data_export = json_encode($notification_client_data);
|
||||||
|
$this->logger->info("Valor de notification client data export: " . $notification_client_data_export . PHP_EOL);
|
||||||
|
$this->createCustomerStripe($notificationData, $stripe, $baseUri, $UCRMAPIToken);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// /**
|
||||||
|
// * implement in subclass with the specific messaging provider
|
||||||
|
// * @see TwilioNotifierFacade::sendWhatsApp()
|
||||||
|
// */
|
||||||
|
abstract protected function sendWhatsApp(
|
||||||
|
string $message
|
||||||
|
): void;
|
||||||
|
|
||||||
|
|
||||||
|
function createCustomerStripe($notificationData, $stripe, $baseUri, $token)
|
||||||
|
{
|
||||||
|
$this->logger->info("Creando el Customer Stripe" . PHP_EOL);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
$ucrm_client_id = $notificationData->clientData['id'];
|
||||||
|
$clientCRMContacts = $notificationData->clientData['contacts'];
|
||||||
|
|
||||||
|
$firstName = $notificationData->clientData['firstName']; //obtenemos nombre del cliente y lo almacenamos en una variable
|
||||||
|
$lastName = $notificationData->clientData['lastName']; //obtenemos apellidos del cliente y lo almacenamos en una variable
|
||||||
|
$this->logger->info('El cliente a procesar es : ' . $firstName . ' ' . $lastName . PHP_EOL); //impresión de control para ver el nombre del cliente a procesar en consola
|
||||||
|
|
||||||
|
$cadenaNotificationData = json_encode($notificationData);
|
||||||
|
$this->logger->info("Datos notificationData: " . $cadenaNotificationData . PHP_EOL);
|
||||||
|
foreach ($clientCRMContacts as $contact) { //aquí revisamos los datos de contacto del cliente, como pueden ser uno o varios se hace uso del foreach
|
||||||
|
$this->logger->info('Ya dentro del FOREACH!!! ' . PHP_EOL);
|
||||||
|
|
||||||
|
$phone = ''; //variable para almacenar el número de teléfono del cliente que se mandará a su cuenta de Stripe
|
||||||
|
|
||||||
|
foreach ($contact['types'] as $type) { //revisamos el tipo de contacto
|
||||||
|
|
||||||
|
$this->logger->info('REVISANDO EL PRIMER CONTACTO!!! ' . PHP_EOL);
|
||||||
|
if ($type['name'] === "WhatsApp") { //si es de tipo whatsapp..
|
||||||
|
//print_r("Encontré un tipo de Contacto para WhatsAapp" . PHP_EOL);
|
||||||
|
$phone = $contact['phone']; //se asigna como número de teléfono
|
||||||
|
break;
|
||||||
|
} else {
|
||||||
|
$phone = $contact['phone']; //Si no encuentra un tipo de contacto como Whatsapp entonces el último número de celular obtenido es el que se envía
|
||||||
|
}
|
||||||
|
}
|
||||||
|
$email = $this->validarEmail($contact['email']); //validamos el email del cliente mediante la función validarEmail para que en caso de que no esté bien formado lo ponga en blanco
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->logger->info('ahora se procede a validar el teléfono!!! ' . PHP_EOL);
|
||||||
|
|
||||||
|
$phone = $this->validarNumeroTelefono($phone); //validamos y procesamos el número de celular del cliente para que se vaya a 10 dígitos ya que Stripe por si mismo les agrega el +52
|
||||||
|
//******************************************** */
|
||||||
|
|
||||||
|
$this->logger->info('AHORA SE MANDA A CREAR EL CLIENTE A STRIPE!!! ' . PHP_EOL);
|
||||||
|
$result = $stripe->customers->create([
|
||||||
|
"description" => "Cliente SIIP CRM con client_id: " . $ucrm_client_id,
|
||||||
|
"name" => $firstName . ' ' . $lastName,
|
||||||
|
"phone" => $phone,
|
||||||
|
"email" => $email,
|
||||||
|
'preferred_locales' => ['es-419']
|
||||||
|
]); //aquí se contruye la petición de creación de un customer en Stripe y se consume la API
|
||||||
|
|
||||||
|
$this->logger->info(json_encode($result) . PHP_EOL); //imprimir respuesta de creación del cliente
|
||||||
|
|
||||||
|
$stripe_customer_id = $result['id']; //obtenemos el customer id de Stripe recibido por medio del consumo del API y lo asignamos a una variable $stripe_customer_id
|
||||||
|
sleep(2);
|
||||||
|
$result2 = $stripe->customers->update(
|
||||||
|
$stripe_customer_id,
|
||||||
|
['metadata' => ['ucrm_client_id' => '' . $ucrm_client_id]]
|
||||||
|
);//aquí se contruye la petición de actualización de un customer en Stripe para agregarle los metadatos y se consume la API, requiere el ID del Customer, por eso antes lo almacenamos en la variable $stripe_customer_id
|
||||||
|
|
||||||
|
$this->logger->info(json_encode($result2) . PHP_EOL); // imprimir respuesta de actualización del metadata del cliente
|
||||||
|
sleep(2);
|
||||||
|
$result3 = $stripe->customers->createFundingInstructions(
|
||||||
|
$stripe_customer_id,
|
||||||
|
[
|
||||||
|
'currency' => 'mxn',
|
||||||
|
'funding_type' => 'bank_transfer',
|
||||||
|
'bank_transfer' => ['type' => 'mx_bank_transfer'],
|
||||||
|
]
|
||||||
|
); //aquí se contruye la petición de creación de Instrucciones de Fondeo de un customer en Stripe (O su metodo de pago como cuenta bancaria para transferencias) y se consume la API
|
||||||
|
|
||||||
|
$this->logger->info(json_encode($result3) . PHP_EOL); //imprimir respuesta de asignación de cuenta bancaria de transferencia
|
||||||
|
|
||||||
|
// Acceder al valor de "clabe" para BANORTE
|
||||||
|
$clabeInterbancaria = $result3['bank_transfer']['financial_addresses'][0]['spei']['clabe']; //Asignamos la clabe obtenida con la API de Stripe con la solicitud anterior a la variable $clabe
|
||||||
|
$stripeID = $this->stripeCustomAttributeID;
|
||||||
|
$clabeInterbancariaID = $this->clabeInterbancariaBanamexID;
|
||||||
|
|
||||||
|
$customer = $stripe->customers->update(
|
||||||
|
$stripe_customer_id,
|
||||||
|
[
|
||||||
|
'metadata' => [
|
||||||
|
'clabe' => $clabeInterbancaria, // Nueva clabe
|
||||||
|
],
|
||||||
|
]
|
||||||
|
);
|
||||||
|
|
||||||
|
$this->logger->info("CLABE guardada en metadata: " . $customer->metadata->clabe . PHP_EOL);
|
||||||
|
|
||||||
|
|
||||||
|
$json_data_patch = '{
|
||||||
|
"attributes": [
|
||||||
|
{
|
||||||
|
"value": "' . $stripe_customer_id . '",
|
||||||
|
"customAttributeId":' . $stripeID . '
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"value": "' . $clabeInterbancaria . '",
|
||||||
|
"customAttributeId":' . $clabeInterbancariaID . '
|
||||||
|
}
|
||||||
|
]
|
||||||
|
|
||||||
|
}'; //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
|
||||||
|
// }
|
||||||
|
// ]
|
||||||
|
|
||||||
|
// }'; //JSON para hacer patch de los custom fields del cliente en el UISCP CRM, Campo para el Stripe Customer ID y la Clabe interbancaria
|
||||||
|
|
||||||
|
$clientguzz = new Client(); //instancia de cliente GuzzleHttp para consumir API UISP CRM
|
||||||
|
try {
|
||||||
|
$responseCRM = $clientguzz->patch($baseUri . 'clients/' . $ucrm_client_id, [
|
||||||
|
'json' => json_decode($json_data_patch, true),
|
||||||
|
'headers' => [
|
||||||
|
'X-Auth-App-Key' => $token, // Cambia el nombre de la cabecera de autorización
|
||||||
|
'Accept' => 'application/json', // Indica que esperamos una respuesta en formato JSON
|
||||||
|
],
|
||||||
|
'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) {
|
||||||
|
$this->logger->info("Error al hacer el patch al CRM: " . $error->getMessage() . PHP_EOL);
|
||||||
|
//exit();
|
||||||
|
}
|
||||||
|
$this->logger->info(json_encode($responseCRM) . PHP_EOL); //imprimir respuesta del patch de CRM con la clabe y Customer ID Stripe
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
function validarNumeroTelefono($telefono)
|
||||||
|
{
|
||||||
|
// Eliminar espacios y guiones
|
||||||
|
$telefono = preg_replace('/\s+|-/', '', $telefono);
|
||||||
|
|
||||||
|
// Eliminar caracteres no numéricos
|
||||||
|
$telefono = preg_replace('/\D/', '', $telefono);
|
||||||
|
|
||||||
|
// Verificar si quedan exactamente 10 dígitos
|
||||||
|
if (strlen($telefono) === 10) {
|
||||||
|
// Retornar el número de teléfono correctamente formateado
|
||||||
|
return $telefono;
|
||||||
|
} elseif (strlen($telefono) > 10) {
|
||||||
|
// Si el número tiene más de 10 dígitos, quitar los primeros
|
||||||
|
return substr($telefono, -10);
|
||||||
|
} else {
|
||||||
|
// Si el número tiene menos de 10 dígitos, retornar cadena vacía
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function validarEmail($email)
|
||||||
|
{
|
||||||
|
$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
|
||||||
|
if (filter_var($email, FILTER_VALIDATE_EMAIL)) {
|
||||||
|
// Si el email es válido, devolver el email
|
||||||
|
return $email;
|
||||||
|
} else {
|
||||||
|
// Si el email no es válido, devolver una cadena vacía
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
98
src/Facade/AbstractUpdateClientFacade.php
Executable file
98
src/Facade/AbstractUpdateClientFacade.php
Executable file
@ -0,0 +1,98 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace SmsNotifier\Facade;
|
||||||
|
|
||||||
|
use SmsNotifier\Data\NotificationData;
|
||||||
|
use SmsNotifier\Factory\MessageTextFactory;
|
||||||
|
use SmsNotifier\Service\Logger;
|
||||||
|
use SmsNotifier\Service\SmsNumberProvider;
|
||||||
|
use Twilio\Exceptions\HttpException;
|
||||||
|
use SmsNotifier\Facade\ClientCallBellAPI;
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* send message to client's number
|
||||||
|
*/
|
||||||
|
|
||||||
|
abstract class AbstractUpdateClientFacade
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @var Logger
|
||||||
|
*/
|
||||||
|
protected $logger;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var MessageTextFactory
|
||||||
|
*/
|
||||||
|
protected $messageTextFactory;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var SmsNumberProvider
|
||||||
|
*/
|
||||||
|
protected $smsNumberProvider;
|
||||||
|
|
||||||
|
public function __construct(
|
||||||
|
Logger $logger,
|
||||||
|
MessageTextFactory $messageTextFactory,
|
||||||
|
SmsNumberProvider $smsNumberProvider
|
||||||
|
) {
|
||||||
|
$this->logger = $logger;
|
||||||
|
$this->messageTextFactory = $messageTextFactory;
|
||||||
|
$this->smsNumberProvider = $smsNumberProvider;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* sets up the body and uses the implementation's sendMessage() to send
|
||||||
|
*/
|
||||||
|
public function notify(NotificationData $notificationData): void
|
||||||
|
{
|
||||||
|
$clientSmsNumber = $this->smsNumberProvider->getUcrmClientNumber($notificationData); //renombrar variables
|
||||||
|
|
||||||
|
if (empty($clientSmsNumber)) {
|
||||||
|
$this->logger->warning('No SMS number found for client: ' . $notificationData->clientId);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// $messageBody = $this->messageTextFactory->createBody($notificationData);
|
||||||
|
// if (! $messageBody) {
|
||||||
|
// $this->logger->info('No text configured for event: ' . $notificationData->eventName);
|
||||||
|
// return;
|
||||||
|
// }
|
||||||
|
|
||||||
|
|
||||||
|
try {
|
||||||
|
$this->logger->debug(sprintf('llego al llamado de sendwhatsapp con client_id: %s y número de celular: %s', $notificationData->clientId, $clientSmsNumber));
|
||||||
|
//$this->sendMessage($notificationData, $clientSmsNumber, $messageBody);
|
||||||
|
//$this->sendWhatsApp($notificationData, $clientSmsNumber);
|
||||||
|
|
||||||
|
$client_callbell_api = new ClientCallBellAPI();
|
||||||
|
$client_callbell_api->sendMessageWhatsApp($clientSmsNumber, $notificationData);
|
||||||
|
$response_getContactCallBell=json_decode($client_callbell_api->getContactWhatsapp($clientSmsNumber));
|
||||||
|
$client_callbell_api->patchWhatsapp($response_getContactCallBell->contact->uuid,$notificationData);
|
||||||
|
|
||||||
|
} catch (HttpException $httpException) {
|
||||||
|
//$this->logger->debug('Ocurrio un error en el try catch');
|
||||||
|
$this->logger->error($httpException->getCode() . ' ' . $httpException->getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* implement in subclass with the specific messaging provider
|
||||||
|
* @see TwilioNotifierFacade::sendMessage()
|
||||||
|
*/
|
||||||
|
abstract protected function sendMessage(
|
||||||
|
NotificationData $notificationData,
|
||||||
|
string $clientSmsNumber,
|
||||||
|
string $messageBody
|
||||||
|
): void;
|
||||||
|
|
||||||
|
// /**
|
||||||
|
// * implement in subclass with the specific messaging provider
|
||||||
|
// * @see TwilioNotifierFacade::sendWhatsApp()
|
||||||
|
// */
|
||||||
|
// abstract protected function sendWhatsApp(
|
||||||
|
// NotificationData $notificationData,
|
||||||
|
// string $clientSmsNumber
|
||||||
|
// ): void;
|
||||||
|
}
|
||||||
1281
src/Facade/ClientCallBellAPI.php
Executable file
1281
src/Facade/ClientCallBellAPI.php
Executable file
File diff suppressed because it is too large
Load Diff
58
src/Facade/PluginNotifierFacade.php
Executable file
58
src/Facade/PluginNotifierFacade.php
Executable file
@ -0,0 +1,58 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace SmsNotifier\Facade;
|
||||||
|
|
||||||
|
use SmsNotifier\Data\NotificationData;
|
||||||
|
use SmsNotifier\Data\PluginData;
|
||||||
|
use SmsNotifier\Factory\MessageTextFactory;
|
||||||
|
use SmsNotifier\Service\Logger;
|
||||||
|
use SmsNotifier\Service\OptionsManager;
|
||||||
|
use SmsNotifier\Service\SmsNumberProvider;
|
||||||
|
use Twilio\Rest\Client;
|
||||||
|
|
||||||
|
|
||||||
|
class PluginNotifierFacade extends AbstractStripeOperationsFacade
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @var Client
|
||||||
|
*/
|
||||||
|
private $twilioClient;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var PluginData
|
||||||
|
*/
|
||||||
|
private $pluginData;
|
||||||
|
|
||||||
|
public function __construct(
|
||||||
|
Logger $logger,
|
||||||
|
MessageTextFactory $messageTextFactory,
|
||||||
|
SmsNumberProvider $smsNumberProvider,
|
||||||
|
OptionsManager $optionsManager
|
||||||
|
) {
|
||||||
|
parent::__construct($logger, $messageTextFactory, $smsNumberProvider);
|
||||||
|
// load config data
|
||||||
|
$this->pluginData = $optionsManager->load();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Send WhatsApp through the CallBell API
|
||||||
|
*/
|
||||||
|
protected function sendWhatsApp(
|
||||||
|
string $message,
|
||||||
|
): void {
|
||||||
|
$this->logger->debug('Enviando mensaje desde twilio notifier facade: '.$message);
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Phone number of sender - required by Twilio. In this plugin, we only load it from config.
|
||||||
|
*/
|
||||||
|
private function getSenderNumber(): string
|
||||||
|
{
|
||||||
|
return $this->pluginData->twilioSmsNumber;
|
||||||
|
}
|
||||||
|
}
|
||||||
58
src/Facade/PluginOxxoNotifierFacade.php
Executable file
58
src/Facade/PluginOxxoNotifierFacade.php
Executable file
@ -0,0 +1,58 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace SmsNotifier\Facade;
|
||||||
|
|
||||||
|
use SmsNotifier\Data\NotificationData;
|
||||||
|
use SmsNotifier\Data\PluginData;
|
||||||
|
use SmsNotifier\Factory\MessageTextFactory;
|
||||||
|
use SmsNotifier\Service\Logger;
|
||||||
|
use SmsNotifier\Service\OptionsManager;
|
||||||
|
use SmsNotifier\Service\SmsNumberProvider;
|
||||||
|
use Twilio\Rest\Client;
|
||||||
|
|
||||||
|
|
||||||
|
class PluginOxxoNotifierFacade extends AbstractOxxoOperationsFacade
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @var Client
|
||||||
|
*/
|
||||||
|
private $twilioClient;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var PluginData
|
||||||
|
*/
|
||||||
|
private $pluginData;
|
||||||
|
|
||||||
|
public function __construct(
|
||||||
|
Logger $logger,
|
||||||
|
MessageTextFactory $messageTextFactory,
|
||||||
|
SmsNumberProvider $smsNumberProvider,
|
||||||
|
OptionsManager $optionsManager
|
||||||
|
) {
|
||||||
|
parent::__construct($logger, $messageTextFactory, $smsNumberProvider);
|
||||||
|
// load config data
|
||||||
|
$this->pluginData = $optionsManager->load();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Send WhatsApp through the CallBell API
|
||||||
|
*/
|
||||||
|
protected function sendWhatsApp(
|
||||||
|
string $message,
|
||||||
|
): void {
|
||||||
|
$this->logger->debug('Enviando mensaje desde twilio notifier facade: '.$message);
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Phone number of sender - required by Twilio. In this plugin, we only load it from config.
|
||||||
|
*/
|
||||||
|
private function getSenderNumber(): string
|
||||||
|
{
|
||||||
|
return $this->pluginData->twilioSmsNumber;
|
||||||
|
}
|
||||||
|
}
|
||||||
93
src/Facade/TwilioNotifierFacade.php
Executable file
93
src/Facade/TwilioNotifierFacade.php
Executable file
@ -0,0 +1,93 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace SmsNotifier\Facade;
|
||||||
|
|
||||||
|
use SmsNotifier\Data\NotificationData;
|
||||||
|
use SmsNotifier\Data\PluginData;
|
||||||
|
use SmsNotifier\Factory\MessageTextFactory;
|
||||||
|
use SmsNotifier\Service\Logger;
|
||||||
|
use SmsNotifier\Service\OptionsManager;
|
||||||
|
use SmsNotifier\Service\SmsNumberProvider;
|
||||||
|
use Twilio\Rest\Client;
|
||||||
|
use SmsNotifier\Facade\ClientCallBellAPI;
|
||||||
|
|
||||||
|
class TwilioNotifierFacade extends AbstractMessageNotifierFacade
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @var Client
|
||||||
|
*/
|
||||||
|
private $twilioClient;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var PluginData
|
||||||
|
*/
|
||||||
|
private $pluginData;
|
||||||
|
|
||||||
|
public function __construct(
|
||||||
|
Logger $logger,
|
||||||
|
MessageTextFactory $messageTextFactory,
|
||||||
|
SmsNumberProvider $smsNumberProvider,
|
||||||
|
OptionsManager $optionsManager
|
||||||
|
) {
|
||||||
|
parent::__construct($logger, $messageTextFactory, $smsNumberProvider);
|
||||||
|
// load config data
|
||||||
|
$this->pluginData = $optionsManager->load();
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Get Twilio SMS API object (unless it's already initialized)
|
||||||
|
*/
|
||||||
|
public function getTwilioClient(): Client
|
||||||
|
{
|
||||||
|
if (!$this->twilioClient) {
|
||||||
|
$this->twilioClient = new Client(
|
||||||
|
$this->pluginData->token_callbell
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return $this->twilioClient;
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
* Send WhatsApp through the CallBell API
|
||||||
|
*/
|
||||||
|
protected function sendWhatsApp(
|
||||||
|
string $message,
|
||||||
|
): void {
|
||||||
|
$this->logger->debug('Enviando mensaje desde twilio notifier facade: '.$message);
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
* Send message through the Twilio client
|
||||||
|
*/
|
||||||
|
protected function sendMessage(
|
||||||
|
NotificationData $notificationData,
|
||||||
|
string $clientSmsNumber,
|
||||||
|
string $messageBody
|
||||||
|
): void {
|
||||||
|
$this->logger->debug(sprintf('Sending: %s', $messageBody));
|
||||||
|
|
||||||
|
$messageInstance = $this->getTwilioClient()->messages->create(
|
||||||
|
$clientSmsNumber,
|
||||||
|
[
|
||||||
|
'from' => $this->getSenderNumber(),
|
||||||
|
'body' => $messageBody,
|
||||||
|
]
|
||||||
|
);
|
||||||
|
|
||||||
|
$this->logger->debug((string) $messageInstance);
|
||||||
|
$this->logger->info(sprintf('Twilio status: %s, message id: %s', $messageInstance->status, $messageInstance->sid));
|
||||||
|
if ($messageInstance->errorCode) {
|
||||||
|
$this->logger->warning(sprintf('Twilio error: %s %s', $messageInstance->errorCode, $messageInstance->errorMessage));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Phone number of sender - required by Twilio. In this plugin, we only load it from config.
|
||||||
|
*/
|
||||||
|
private function getSenderNumber(): string
|
||||||
|
{
|
||||||
|
return $this->pluginData->twilioSmsNumber;
|
||||||
|
}
|
||||||
|
}
|
||||||
5
src/Facade/pruebas_ucrm_api.php
Executable file
5
src/Facade/pruebas_ucrm_api.php
Executable file
@ -0,0 +1,5 @@
|
|||||||
|
<?php
|
||||||
|
use Ubnt\UcrmPluginSdk\Service\UcrmApi;
|
||||||
|
|
||||||
|
|
||||||
|
$$ucrmApi = UcrmApi::create();
|
||||||
116
src/Factory/MessageTextFactory.php
Executable file
116
src/Factory/MessageTextFactory.php
Executable file
@ -0,0 +1,116 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace SmsNotifier\Factory;
|
||||||
|
|
||||||
|
use SmsNotifier\Data\NotificationData;
|
||||||
|
use SmsNotifier\Data\PluginData;
|
||||||
|
use SmsNotifier\Service\Logger;
|
||||||
|
use SmsNotifier\Service\OptionsManager;
|
||||||
|
|
||||||
|
class MessageTextFactory
|
||||||
|
{
|
||||||
|
private const DELIMITER = '%%';
|
||||||
|
|
||||||
|
private const DATA_TYPES = [
|
||||||
|
'client' => 'clientData',
|
||||||
|
'invoice' => 'invoiceData',
|
||||||
|
'payment' => 'paymentData',
|
||||||
|
'service' => 'serviceData',
|
||||||
|
];
|
||||||
|
|
||||||
|
private const DATETIME_FORMAT = 'Y-m-d H:i';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var Logger
|
||||||
|
*/
|
||||||
|
private $logger;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var PluginData
|
||||||
|
*/
|
||||||
|
private $pluginData;
|
||||||
|
|
||||||
|
public function __construct(
|
||||||
|
Logger $logger,
|
||||||
|
OptionsManager $optionsManager
|
||||||
|
) {
|
||||||
|
$this->logger = $logger;
|
||||||
|
$this->pluginData = $optionsManager->load();
|
||||||
|
}
|
||||||
|
|
||||||
|
public function createBody(NotificationData $notificationData): string
|
||||||
|
{
|
||||||
|
// configuration keys do not allow dots, replace with underscore
|
||||||
|
$eventName = 'event_' . str_replace('.', '_', $notificationData->eventName);
|
||||||
|
|
||||||
|
if (! property_exists($this->pluginData, $eventName)) {
|
||||||
|
throw new \InvalidArgumentException('Unconfigured event name: ' . $notificationData->eventName);
|
||||||
|
}
|
||||||
|
|
||||||
|
$eventText = trim((string) $this->pluginData->{$eventName});
|
||||||
|
$this->logger->debug($eventText);
|
||||||
|
if (! $eventText) {
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
|
||||||
|
$tokens = $this->createReplacementTokenArray($notificationData);
|
||||||
|
$this->logger->debug($tokens);
|
||||||
|
$eventText = str_replace(array_keys($tokens), array_values($tokens), $eventText);
|
||||||
|
$this->logger->debug($eventText);
|
||||||
|
|
||||||
|
return $eventText;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function createBodyWhatsApp(NotificationData $notificationData): string
|
||||||
|
{
|
||||||
|
// configuration keys do not allow dots, replace with underscore
|
||||||
|
$eventName = 'event_' . str_replace('.', '_', $notificationData->eventName);
|
||||||
|
|
||||||
|
if (! property_exists($this->pluginData, $eventName)) {
|
||||||
|
throw new \InvalidArgumentException('Unconfigured event name: ' . $notificationData->eventName);
|
||||||
|
}
|
||||||
|
|
||||||
|
$eventText = trim((string) $this->pluginData->{$eventName});
|
||||||
|
$this->logger->debug($eventText);
|
||||||
|
if (! $eventText) {
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
|
||||||
|
$tokens = $this->createReplacementTokenArray($notificationData);
|
||||||
|
$this->logger->debug($tokens);
|
||||||
|
$eventText = str_replace(array_keys($tokens), array_values($tokens), $eventText);
|
||||||
|
$this->logger->debug($eventText);
|
||||||
|
|
||||||
|
return $eventText;
|
||||||
|
}
|
||||||
|
|
||||||
|
private function createReplacementTokenArray(NotificationData $notificationData): array
|
||||||
|
{
|
||||||
|
$tokens = [];
|
||||||
|
foreach (self::DATA_TYPES as $typeName => $typeVariable) {
|
||||||
|
if (empty($notificationData->{$typeVariable})) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
foreach ($notificationData->{$typeVariable} as $dataKey => $dataValue) {
|
||||||
|
if (! is_array($dataValue)) {
|
||||||
|
if ($dataValue && strpos($dataKey, 'Date') > 0) {
|
||||||
|
$dateTimeValue = \DateTime::createFromFormat('Y-m-d\TH:i:sO', $dataValue);
|
||||||
|
if ($dateTimeValue) {
|
||||||
|
$dataValue = $this->formatDate($dateTimeValue);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
$tokens[self::DELIMITER . $typeName . '.' . $dataKey . self::DELIMITER] = $dataValue ?? '';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $tokens;
|
||||||
|
}
|
||||||
|
|
||||||
|
private function formatDate(\DateTimeInterface $dateTime): string
|
||||||
|
{
|
||||||
|
return $dateTime->format(self::DATETIME_FORMAT);
|
||||||
|
}
|
||||||
|
}
|
||||||
111
src/Factory/NotificationDataFactory.php
Executable file
111
src/Factory/NotificationDataFactory.php
Executable file
@ -0,0 +1,111 @@
|
|||||||
|
<?php
|
||||||
|
/*
|
||||||
|
* @copyright Copyright (c) 2018 Ubiquiti Networks, Inc.
|
||||||
|
* @see https://www.ubnt.com/
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
|
||||||
|
namespace SmsNotifier\Factory;
|
||||||
|
|
||||||
|
use SmsNotifier\Data\NotificationData;
|
||||||
|
use SmsNotifier\Service\Logger;
|
||||||
|
use SmsNotifier\Service\UcrmApi;
|
||||||
|
|
||||||
|
class NotificationDataFactory
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @var UcrmApi
|
||||||
|
*/
|
||||||
|
private $ucrmApi;
|
||||||
|
|
||||||
|
public function __construct(
|
||||||
|
UcrmApi $ucrmApi
|
||||||
|
) {
|
||||||
|
$this->ucrmApi = $ucrmApi;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getObject($jsonData): NotificationData
|
||||||
|
{
|
||||||
|
$notificationData = new NotificationData();
|
||||||
|
$notificationData->uuid = $jsonData['uuid'];
|
||||||
|
$notificationData->changeType = $jsonData['changeType'];
|
||||||
|
$notificationData->entity = $jsonData['entity'];
|
||||||
|
$notificationData->entityId = $jsonData['entityId'] ? (int) $jsonData['entityId'] : null;
|
||||||
|
$notificationData->eventName = $jsonData['eventName'];
|
||||||
|
$notificationData->message = $jsonData['extraData']['message'] ?? null;
|
||||||
|
|
||||||
|
// Check if the given webhook exists.
|
||||||
|
$this->ucrmApi->query('webhook-events/' . $notificationData->uuid);
|
||||||
|
|
||||||
|
$this->resolveUcrmData($notificationData);
|
||||||
|
|
||||||
|
return $notificationData;
|
||||||
|
}
|
||||||
|
|
||||||
|
private function resolveUcrmData(NotificationData $notificationData): void
|
||||||
|
{
|
||||||
|
switch ($notificationData->entity) {
|
||||||
|
case 'client':
|
||||||
|
$notificationData->clientId = $notificationData->entityId;
|
||||||
|
break;
|
||||||
|
case 'invoice':
|
||||||
|
$notificationData->clientId = $this->getInvoiceData($notificationData)['clientId'] ?? null;
|
||||||
|
break;
|
||||||
|
case 'payment':
|
||||||
|
$notificationData->clientId = $this->getPaymentData($notificationData)['clientId'] ?? null;
|
||||||
|
break;
|
||||||
|
case 'service':
|
||||||
|
$notificationData->clientId = $this->getServiceData($notificationData)['clientId'] ?? null;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if ($notificationData->clientId) {
|
||||||
|
$this->getClientData($notificationData);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private function getClientData(NotificationData $notificationData)
|
||||||
|
{
|
||||||
|
if (empty($notificationData->clientData) && $notificationData->clientId) {
|
||||||
|
$notificationData->clientData = $this->ucrmApi->query('clients/' . $notificationData->clientId);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($notificationData->message) {
|
||||||
|
$notificationData->clientData['message'] = $notificationData->message;
|
||||||
|
}
|
||||||
|
return $notificationData->clientData;
|
||||||
|
}
|
||||||
|
|
||||||
|
private function getPaymentData(NotificationData $notificationData)
|
||||||
|
{
|
||||||
|
if (empty($notificationData->paymentData) && $notificationData->entityId) {
|
||||||
|
$notificationData->paymentData = $this->ucrmApi->query('payments/' . $notificationData->entityId);
|
||||||
|
}
|
||||||
|
return $notificationData->paymentData;
|
||||||
|
}
|
||||||
|
|
||||||
|
private function getInvoiceData(NotificationData $notificationData)
|
||||||
|
{
|
||||||
|
if (empty($notificationData->invoiceData) && $notificationData->entityId) {
|
||||||
|
$notificationData->invoiceData = $this->ucrmApi->query('invoices/' . $notificationData->entityId);
|
||||||
|
}
|
||||||
|
return $notificationData->invoiceData;
|
||||||
|
}
|
||||||
|
|
||||||
|
private function getServiceData(NotificationData $notificationData)
|
||||||
|
{
|
||||||
|
if (empty($notificationData->serviceData) && $notificationData->entityId) {
|
||||||
|
$notificationData->serviceData = $this->ucrmApi->query('clients/services/' . $notificationData->entityId);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (($notificationData->serviceData['suspensionReasonId'] ?? null) !== null) {
|
||||||
|
$notificationData->serviceData['stopReason'] = $this->ucrmApi->query(
|
||||||
|
'service-suspension-reasons/' . $notificationData->serviceData['suspensionReasonId']
|
||||||
|
)['name'] ?? null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $notificationData->serviceData;
|
||||||
|
}
|
||||||
|
}
|
||||||
337
src/Plugin.php
Executable file
337
src/Plugin.php
Executable file
@ -0,0 +1,337 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
|
||||||
|
namespace SmsNotifier;
|
||||||
|
|
||||||
|
use Psr\Log\LogLevel;
|
||||||
|
use SmsNotifier\Facade\TwilioNotifierFacade;
|
||||||
|
use SmsNotifier\Facade\PluginNotifierFacade;
|
||||||
|
use SmsNotifier\Facade\PluginOxxoNotifierFacade;
|
||||||
|
use SmsNotifier\Factory\NotificationDataFactory;
|
||||||
|
use SmsNotifier\Service\Logger;
|
||||||
|
use SmsNotifier\Service\OptionsManager;
|
||||||
|
use SmsNotifier\Service\PluginDataValidator;
|
||||||
|
use Twilio\Exceptions\TwilioException;
|
||||||
|
|
||||||
|
class Plugin
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @var Logger
|
||||||
|
*/
|
||||||
|
private $logger;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var OptionsManager
|
||||||
|
*/
|
||||||
|
private $optionsManager;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var PluginDataValidator
|
||||||
|
*/
|
||||||
|
private $pluginDataValidator;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var PluginNotifierFacade
|
||||||
|
*/
|
||||||
|
private $pluginNotifierFacade;
|
||||||
|
/**
|
||||||
|
* @var PluginOxxoNotifierFacade
|
||||||
|
*/
|
||||||
|
private $pluginOxxoNotifierFacade;
|
||||||
|
/**
|
||||||
|
* @var TwilioNotifierFacade
|
||||||
|
*/
|
||||||
|
private $notifierFacade;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var NotificationDataFactory
|
||||||
|
*/
|
||||||
|
private $notificationDataFactory;
|
||||||
|
|
||||||
|
public function __construct(
|
||||||
|
Logger $logger,
|
||||||
|
OptionsManager $optionsManager,
|
||||||
|
PluginDataValidator $pluginDataValidator,
|
||||||
|
TwilioNotifierFacade $notifierFacade,
|
||||||
|
PluginNotifierFacade $pluginNotifierFacade,
|
||||||
|
PluginOxxoNotifierFacade $pluginOxxoNotifierFacade,
|
||||||
|
NotificationDataFactory $notificationDataFactory
|
||||||
|
) {
|
||||||
|
$this->logger = $logger;
|
||||||
|
$this->optionsManager = $optionsManager;
|
||||||
|
$this->pluginDataValidator = $pluginDataValidator;
|
||||||
|
$this->notifierFacade = $notifierFacade;
|
||||||
|
$this->pluginNotifierFacade = $pluginNotifierFacade;
|
||||||
|
$this->pluginOxxoNotifierFacade = $pluginOxxoNotifierFacade;
|
||||||
|
$this->notificationDataFactory = $notificationDataFactory;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function run(): void
|
||||||
|
{
|
||||||
|
// $hola = PHP_SAPI;
|
||||||
|
// $this->logger->info('valor de PHP_SAPI: ' . $hola);
|
||||||
|
if (PHP_SAPI === 'fpm-fcgi') {
|
||||||
|
$this->logger->debug('Whatsapp over HTTP started');
|
||||||
|
$this->processHttpRequest();
|
||||||
|
$this->logger->debug('HTTP request processing ended.');
|
||||||
|
} elseif (PHP_SAPI === 'cli') {
|
||||||
|
$this->logger->debug('Whatsapp over CLI started');
|
||||||
|
$this->processCli();
|
||||||
|
$this->logger->debug('CLI process ended.');
|
||||||
|
} else {
|
||||||
|
throw new \UnexpectedValueException('Unknown PHP_SAPI type: ' . PHP_SAPI);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private function processCli(): void
|
||||||
|
{
|
||||||
|
if ($this->pluginDataValidator->validate()) {
|
||||||
|
$this->logger->info('Validating config');
|
||||||
|
$this->optionsManager->load();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private function processHttpRequest(): void
|
||||||
|
{
|
||||||
|
$pluginData = $this->optionsManager->load();
|
||||||
|
if ($pluginData->logging_level) {
|
||||||
|
$this->logger->setLogLevelThreshold(LogLevel::DEBUG);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
$userInput = file_get_contents('php://input');
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
if (!$userInput) {
|
||||||
|
$this->logger->warning('no input');
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
$event_json = json_decode($userInput);
|
||||||
|
$webhook_string = json_encode($event_json);
|
||||||
|
$this->logger->debug("El valor del evento recibio en json: " . $webhook_string . PHP_EOL);
|
||||||
|
// Maneja el evento del webhook
|
||||||
|
if ($event_json) {
|
||||||
|
switch ($event_json->type) {
|
||||||
|
case 'customer_cash_balance_transaction.created':
|
||||||
|
$this->logger->info('Evento de transfencia al cliente encontrado');
|
||||||
|
$this->logger->info('Valor del EventJSON: ' . json_encode($event_json) . PHP_EOL);
|
||||||
|
$this->pluginNotifierFacade->createPaymentIntent($event_json);
|
||||||
|
break;
|
||||||
|
case 'inbound_payment.payment_attempt':
|
||||||
|
$this->logger->info('Evento de Pagode OXXO recibido');
|
||||||
|
$this->logger->info('Valor del EventJSON: ' . json_encode($event_json) . PHP_EOL);
|
||||||
|
break;
|
||||||
|
case 'energy.alert':
|
||||||
|
$this->logger->info('Evento de Energía recibido: ' . $event_json->message . PHP_EOL);
|
||||||
|
break;
|
||||||
|
case 'oxxo.request':
|
||||||
|
$this->logger->info('Evento de referencia de oxxo recibido: ' . PHP_EOL);
|
||||||
|
|
||||||
|
// Construir la URL basada en el "client_id"
|
||||||
|
// $url = "https://siip.mx/wp/wp-content/uploads/img/voucher.png";
|
||||||
|
$url = $this->pluginOxxoNotifierFacade->createOxxoPaymentIntent($event_json);
|
||||||
|
// Crear una respuesta en formato JSON
|
||||||
|
// $response = [
|
||||||
|
// 'event' => 'response.siip',
|
||||||
|
// 'status' => 'success',
|
||||||
|
// 'url' => $url
|
||||||
|
// ];
|
||||||
|
|
||||||
|
$response = '{' .
|
||||||
|
'"url": "' . $url . '"' .
|
||||||
|
'}';
|
||||||
|
|
||||||
|
$this->logger->debug('Este ese el reponse que se envía a CallBell: ' . $response);
|
||||||
|
// $json_codificado = json_encode($response);
|
||||||
|
// if (json_last_error() !== JSON_ERROR_NONE) {
|
||||||
|
// $this->logger->error('Error en la codificación JSON: ' . json_last_error_msg() . PHP_EOL);
|
||||||
|
|
||||||
|
// }
|
||||||
|
|
||||||
|
//$this->logger->info('Se está enviando esta respuesta: ' . json_encode($json_codificado) . PHP_EOL);
|
||||||
|
|
||||||
|
// Enviar el encabezado de respuesta como JSON
|
||||||
|
header('Content-Type: application/json');
|
||||||
|
|
||||||
|
// Enviar la respuesta en formato JSON
|
||||||
|
//echo json_encode($response);
|
||||||
|
echo $response;
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
|
// Otros eventos relevantes
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$jsonData = @json_decode($userInput, true, 10);
|
||||||
|
if (!isset($jsonData['uuid'])) {
|
||||||
|
$this->logger->error('JSON error: ' . json_last_error_msg());
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
$notification = $this->notificationDataFactory->getObject($jsonData);
|
||||||
|
$this->logger->debug('valor el evento recibido por webhook: ' . $notification->eventName . PHP_EOL);
|
||||||
|
|
||||||
|
if ($notification->changeType === 'test') {
|
||||||
|
$this->logger->info('Webhook test successful.');
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!$notification->clientId) {
|
||||||
|
$this->logger->warning('No client specified, cannot notify them.');
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
$configManager = \Ubnt\UcrmPluginSdk\Service\PluginConfigManager::create();
|
||||||
|
$config = $configManager->loadConfig();
|
||||||
|
// the "exportFormat" key must be defined in plugin's manifest file, see the link above
|
||||||
|
|
||||||
|
try {
|
||||||
|
|
||||||
|
if ($notification->eventName === 'payment.add') {
|
||||||
|
|
||||||
|
$result = json_encode($notification);
|
||||||
|
$this->logger->debug('datos del notification para el invoice add:' . $result . PHP_EOL);
|
||||||
|
|
||||||
|
$datos_payment = $notification->paymentData;
|
||||||
|
$this->logger->debug('valor del payment data: ' . json_encode($datos_payment) . PHP_EOL);
|
||||||
|
$payment_method_id = $notification->paymentData['methodId'];
|
||||||
|
//$this->logger->debug('Metodo de pago: ' . $notification->paymentData['methodId'] . PHP_EOL);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
$payment_method = '';
|
||||||
|
|
||||||
|
|
||||||
|
switch ($payment_method_id) {
|
||||||
|
|
||||||
|
case '11721cdf-a498-48be-903e-daa67552e4f6':
|
||||||
|
$payment_method = 'Cheque';
|
||||||
|
if ($config['checkPaymentMethodId']) {
|
||||||
|
$this->notifierFacade->verifyPaymentActionToDo($notification);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case '6efe0fa8-36b2-4dd1-b049-427bffc7d369':
|
||||||
|
$payment_method = 'Efectivo';
|
||||||
|
if ($config['cashPaymentMethodId']) {
|
||||||
|
$this->notifierFacade->verifyPaymentActionToDo($notification);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case '4145b5f5-3bbc-45e3-8fc5-9cda970c62fb':
|
||||||
|
$payment_method = 'Transferencia bancaria';
|
||||||
|
if ($config['bankTransferPaymentMethodId']) {
|
||||||
|
$this->notifierFacade->verifyPaymentActionToDo($notification);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case '78e84000-9b5b-44a4-8367-da43df86ce34':
|
||||||
|
$payment_method = 'PayPal';
|
||||||
|
if ($config['paypalPaymentMethodId']) {
|
||||||
|
$this->notifierFacade->verifyPaymentActionToDo($notification);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case '6da98bb9-6df7-4c41-8608-5cdd7fde7d5d':
|
||||||
|
$payment_method = 'Tarjeta de crédito PayPal';
|
||||||
|
if ($config['creditCardPaypalPaymentMethodId']) {
|
||||||
|
$this->notifierFacade->verifyPaymentActionToDo($notification);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case '1dd098fa-5d63-4c8d-88b7-3c27ffbbb6ae':
|
||||||
|
$payment_method = 'Tarjeta de crédito Stripe';
|
||||||
|
if ($config['creditCardStripePaymentMethodId']) {
|
||||||
|
$this->notifierFacade->verifyPaymentActionToDo($notification);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 'b9e1e9d1-5c7b-41d2-b6b2-3e568d700290':
|
||||||
|
$payment_method = 'Suscripción de Stripe (tarjeta de crédito)';
|
||||||
|
if ($config['stripeSubscriptionCreditCardPaymentMethodId']) {
|
||||||
|
$this->notifierFacade->verifyPaymentActionToDo($notification);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case '939f7701-00b7-4676-9b1e-17afb268c8ba':
|
||||||
|
$payment_method = 'Suscripción de PayPal';
|
||||||
|
if ($config['paypalSubscriptionPaymentMethodId']) {
|
||||||
|
$this->notifierFacade->verifyPaymentActionToDo($notification);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case '1c963e35-df24-444d-95d2-12592d5107e8':
|
||||||
|
$payment_method = 'MercadoPago';
|
||||||
|
if ($config['mercadopagoPaymentMethodId']) {
|
||||||
|
$this->notifierFacade->verifyPaymentActionToDo($notification);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 'd8c1eae9-d41d-479f-aeaf-38497975d7b3':
|
||||||
|
$payment_method = 'Personalizado';
|
||||||
|
if ($config['customPaymentMethodId']) {
|
||||||
|
$this->notifierFacade->verifyPaymentActionToDo($notification);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case '72271b72-5c0a-45e2-94d1-cdf4d7cf10e2':
|
||||||
|
$payment_method = 'Cortesía';
|
||||||
|
if ($config['courtesyPaymentMethodId']) {
|
||||||
|
$this->notifierFacade->verifyPaymentActionToDo($notification);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
$payment_method = 'Desconocido, revisar metodos de pago no contemplados';
|
||||||
|
break;
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
} else if ($notification->eventName === 'client.edit') {
|
||||||
|
$this->logger->debug('Se actualiza a un cliente' . PHP_EOL);
|
||||||
|
$this->notifierFacade->verifyClientActionToDo($notification);
|
||||||
|
} else if ($notification->eventName === 'client.add') {
|
||||||
|
$this->logger->debug('Se agregó un nuevo cliente' . PHP_EOL);
|
||||||
|
$this->pluginNotifierFacade->createStripeClient($notification);
|
||||||
|
} else if ($notification->eventName === 'service.suspend') {
|
||||||
|
$this->logger->debug('Se suspendió el servicio a un cliente' . PHP_EOL);
|
||||||
|
$this->notifierFacade->verifyServiceActionToDo($notification);
|
||||||
|
} else if ($notification->eventName === 'service.suspend_cancel') {
|
||||||
|
$this->logger->debug('Se reactivó el servicio a un cliente' . PHP_EOL);
|
||||||
|
$this->notifierFacade->verifyServiceActionToDo($notification);
|
||||||
|
} else if ($notification->eventName === 'service.postpone') {
|
||||||
|
$this->logger->debug('Se pospuso la suspención del servicio a un cliente' . PHP_EOL);
|
||||||
|
$this->notifierFacade->verifyServiceActionToDo($notification);
|
||||||
|
}else if ($notification->eventName === 'invoice.near_due') {
|
||||||
|
$this->logger->debug('Factura casi por vencer' . PHP_EOL);
|
||||||
|
$this->notifierFacade->notifyOverDue($notification);
|
||||||
|
} else if ($notification->eventName === 'invoice.overdue') {
|
||||||
|
$this->logger->debug('Factura vencida' . PHP_EOL);
|
||||||
|
$result = json_encode($notification);
|
||||||
|
$this->logger->debug('datos del notification para el invoice overdue:' . $result . PHP_EOL);
|
||||||
|
$this->notifierFacade->notifyOverDue($notification);
|
||||||
|
} else if ($notification->eventName === 'invoice.add') {
|
||||||
|
$this->logger->debug('Adición de Factura' . PHP_EOL);
|
||||||
|
$result = json_encode($notification);
|
||||||
|
$this->logger->debug('datos del notification para el invoice add:' . $result . PHP_EOL);
|
||||||
|
|
||||||
|
$accountBalance = $notification->clientData['accountBalance'];
|
||||||
|
$invoiceAmountPaid = $notification->invoiceData['amountPaid'];
|
||||||
|
$this->logger->debug("Account Balance: " . $accountBalance . PHP_EOL);
|
||||||
|
$this->logger->debug("Pago hecho con la factura: " . $invoiceAmountPaid . PHP_EOL);
|
||||||
|
$this->notifierFacade->verifyInvoiceActionToDo($notification);
|
||||||
|
}else if($notification->eventName === 'invoice.edit'){
|
||||||
|
$this->logger->debug('Edición de Factura' . PHP_EOL);
|
||||||
|
$this->notifierFacade->verifyInvoiceActionToDo($notification);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//$this->notifierFacade->update($notification);
|
||||||
|
} catch (TwilioException $exception) {
|
||||||
|
$this->logger->error($exception->getMessage());
|
||||||
|
} catch (\Exception $ex) {
|
||||||
|
$this->logger->error($ex->getMessage());
|
||||||
|
$this->logger->info($ex->getTraceAsString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
99
src/Service/CurlExecutor.php
Executable file
99
src/Service/CurlExecutor.php
Executable file
@ -0,0 +1,99 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
|
||||||
|
namespace SmsNotifier\Service;
|
||||||
|
|
||||||
|
use SmsNotifier\Exception\CurlException;
|
||||||
|
|
||||||
|
class CurlExecutor
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @throws CurlException
|
||||||
|
*/
|
||||||
|
public function curlCommand($url, $method, array $headers = [], $data = null, bool $verifySsl = true): void
|
||||||
|
{
|
||||||
|
$c = curl_init();
|
||||||
|
curl_setopt($c, CURLOPT_URL, $url);
|
||||||
|
curl_setopt($c, CURLOPT_HTTPHEADER, $headers);
|
||||||
|
curl_setopt($c, CURLOPT_CUSTOMREQUEST, $method);
|
||||||
|
|
||||||
|
if ($data) {
|
||||||
|
curl_setopt($c, CURLOPT_POST, true);
|
||||||
|
curl_setopt($c, CURLOPT_POSTFIELDS, $data);
|
||||||
|
}
|
||||||
|
|
||||||
|
curl_setopt($c, CURLOPT_RETURNTRANSFER, true);
|
||||||
|
if ($verifySsl) {
|
||||||
|
curl_setopt($c, CURLOPT_SSL_VERIFYPEER, true);
|
||||||
|
curl_setopt($c, CURLOPT_SSL_VERIFYHOST, 2);
|
||||||
|
} else {
|
||||||
|
// we are disabling verification by request
|
||||||
|
curl_setopt($c, CURLOPT_SSL_VERIFYPEER, false);
|
||||||
|
curl_setopt($c, CURLOPT_SSL_VERIFYHOST, 0);
|
||||||
|
}
|
||||||
|
$result = curl_exec($c);
|
||||||
|
|
||||||
|
$error = curl_error($c);
|
||||||
|
$errno = curl_errno($c);
|
||||||
|
|
||||||
|
if ($errno || $error) {
|
||||||
|
throw new CurlException("Error for request ${url}. Curl error ${errno}: ${error}");
|
||||||
|
}
|
||||||
|
|
||||||
|
$httpCode = curl_getinfo($c, CURLINFO_HTTP_CODE);
|
||||||
|
|
||||||
|
if ($httpCode < 200 || $httpCode >= 300) {
|
||||||
|
throw new CurlException("Error for request ${url}. HTTP error (${httpCode}): ${result}", $httpCode);
|
||||||
|
}
|
||||||
|
|
||||||
|
curl_close($c);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @throws CurlException
|
||||||
|
*/
|
||||||
|
public function curlQuery($url, array $headers = [], array $parameters = [], bool $verifySsl = true): array
|
||||||
|
{
|
||||||
|
if ($parameters) {
|
||||||
|
$url .= '?' . http_build_query($parameters);
|
||||||
|
}
|
||||||
|
|
||||||
|
$c = curl_init();
|
||||||
|
curl_setopt($c, CURLOPT_URL, $url);
|
||||||
|
curl_setopt($c, CURLOPT_HTTPHEADER, $headers);
|
||||||
|
|
||||||
|
curl_setopt($c, CURLOPT_RETURNTRANSFER, true);
|
||||||
|
if ($verifySsl) {
|
||||||
|
curl_setopt($c, CURLOPT_SSL_VERIFYPEER, true);
|
||||||
|
curl_setopt($c, CURLOPT_SSL_VERIFYHOST, 2);
|
||||||
|
} else {
|
||||||
|
// we are disabling verification by request
|
||||||
|
curl_setopt($c, CURLOPT_SSL_VERIFYPEER, false);
|
||||||
|
curl_setopt($c, CURLOPT_SSL_VERIFYHOST, 0);
|
||||||
|
}
|
||||||
|
$result = curl_exec($c);
|
||||||
|
|
||||||
|
$error = curl_error($c);
|
||||||
|
$errno = curl_errno($c);
|
||||||
|
|
||||||
|
if ($errno || $error) {
|
||||||
|
throw new CurlException("Error for request ${url}. Curl error ${errno}: ${error}");
|
||||||
|
}
|
||||||
|
|
||||||
|
$httpCode = curl_getinfo($c, CURLINFO_HTTP_CODE);
|
||||||
|
|
||||||
|
if ($httpCode < 200 || $httpCode >= 300) {
|
||||||
|
throw new CurlException("Error for request ${url}. HTTP error (${httpCode}): ${result}", $httpCode);
|
||||||
|
}
|
||||||
|
|
||||||
|
curl_close($c);
|
||||||
|
|
||||||
|
if (! $result) {
|
||||||
|
throw new CurlException("Error for request ${url}. Empty result.");
|
||||||
|
}
|
||||||
|
|
||||||
|
return json_decode($result, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
36
src/Service/LogCleaner.php
Executable file
36
src/Service/LogCleaner.php
Executable file
@ -0,0 +1,36 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace SmsNotifier\Service;
|
||||||
|
|
||||||
|
use Ubnt\UcrmPluginSdk\Service\PluginLogManager;
|
||||||
|
|
||||||
|
final class LogCleaner
|
||||||
|
{
|
||||||
|
private const MAX_LINES = 1024;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var PluginLogManager
|
||||||
|
*/
|
||||||
|
private $pluginLogManager;
|
||||||
|
|
||||||
|
public function __construct(PluginLogManager $pluginLogManager)
|
||||||
|
{
|
||||||
|
$this->pluginLogManager = $pluginLogManager;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function clean(): void
|
||||||
|
{
|
||||||
|
$log = $this->pluginLogManager->getLog();
|
||||||
|
$log = explode(PHP_EOL, $log);
|
||||||
|
|
||||||
|
if (count($log) <= self::MAX_LINES) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
$log = array_slice($log, -self::MAX_LINES);
|
||||||
|
$this->pluginLogManager->clearLog();
|
||||||
|
$this->pluginLogManager->appendLog(rtrim(implode(PHP_EOL, $log), PHP_EOL));
|
||||||
|
}
|
||||||
|
}
|
||||||
66
src/Service/Logger.php
Executable file
66
src/Service/Logger.php
Executable file
@ -0,0 +1,66 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
|
||||||
|
namespace SmsNotifier\Service;
|
||||||
|
|
||||||
|
use Psr\Log\LogLevel;
|
||||||
|
|
||||||
|
class Logger extends \Katzgrau\KLogger\Logger
|
||||||
|
{
|
||||||
|
private const DEFAULT_LEVEL = LogLevel::INFO; // now configurable in manifest
|
||||||
|
|
||||||
|
private const AVAILABLE_LEVELS = [
|
||||||
|
LogLevel::EMERGENCY,
|
||||||
|
LogLevel::ALERT,
|
||||||
|
LogLevel::CRITICAL,
|
||||||
|
LogLevel::ERROR,
|
||||||
|
LogLevel::WARNING,
|
||||||
|
LogLevel::NOTICE,
|
||||||
|
LogLevel::INFO,
|
||||||
|
LogLevel::DEBUG,
|
||||||
|
];
|
||||||
|
|
||||||
|
public function __construct($level = null)
|
||||||
|
{
|
||||||
|
parent::__construct(
|
||||||
|
'data',
|
||||||
|
self::DEFAULT_LEVEL,
|
||||||
|
[
|
||||||
|
'extension' => 'log',
|
||||||
|
'filename' => 'plugin',
|
||||||
|
]
|
||||||
|
);
|
||||||
|
if ($level) {
|
||||||
|
$this->setLogLevelThreshold($level);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param mixed $level
|
||||||
|
* @param mixed $message
|
||||||
|
*/
|
||||||
|
public function log($level, $message, array $context = [])
|
||||||
|
{
|
||||||
|
if (! is_string($message)) {
|
||||||
|
$message = var_export($message, true);
|
||||||
|
}
|
||||||
|
return parent::log($level, $message, $context);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setLogLevelThreshold($logLevelThreshold): void
|
||||||
|
{
|
||||||
|
$logLevelThreshold = $this->validateLevel($logLevelThreshold, self::DEFAULT_LEVEL);
|
||||||
|
parent::setLogLevelThreshold($logLevelThreshold);
|
||||||
|
$this->notice('Logging level set to:' . $logLevelThreshold);
|
||||||
|
}
|
||||||
|
|
||||||
|
private function validateLevel($level, $defaultLevel): string
|
||||||
|
{
|
||||||
|
if (in_array($level, self::AVAILABLE_LEVELS, true)) {
|
||||||
|
return $level;
|
||||||
|
}
|
||||||
|
return $defaultLevel;
|
||||||
|
}
|
||||||
|
}
|
||||||
71
src/Service/OptionsManager.php
Executable file
71
src/Service/OptionsManager.php
Executable file
@ -0,0 +1,71 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
|
||||||
|
namespace SmsNotifier\Service;
|
||||||
|
|
||||||
|
use SmsNotifier\Data\PluginData;
|
||||||
|
|
||||||
|
class OptionsManager
|
||||||
|
{
|
||||||
|
private const UCRM_JSON = 'ucrm.json';
|
||||||
|
|
||||||
|
private const CONFIG_JSON = 'data/config.json';
|
||||||
|
|
||||||
|
private const PLUGIN_JSON = 'data/plugin.json';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var PluginData
|
||||||
|
*/
|
||||||
|
private $optionsData;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @throws \ReflectionException
|
||||||
|
*/
|
||||||
|
public function load(): PluginData
|
||||||
|
{
|
||||||
|
if ($this->optionsData) {
|
||||||
|
return $this->optionsData;
|
||||||
|
}
|
||||||
|
|
||||||
|
$options = array_merge(
|
||||||
|
$this->getDataFromJson(self::UCRM_JSON),
|
||||||
|
$this->getDataFromJson(self::CONFIG_JSON),
|
||||||
|
$this->getDataFromJson(self::PLUGIN_JSON)
|
||||||
|
);
|
||||||
|
|
||||||
|
$this->optionsData = new PluginData();
|
||||||
|
$reflectionClass = new \ReflectionClass($this->optionsData);
|
||||||
|
|
||||||
|
foreach ($reflectionClass->getProperties() as $reflectionProperty) {
|
||||||
|
if (array_key_exists($reflectionProperty->getName(), $options)) {
|
||||||
|
$reflectionProperty->setValue($this->optionsData, $options[$reflectionProperty->getName()]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this->optionsData;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function update(): void
|
||||||
|
{
|
||||||
|
$newData = (array) $this->optionsData;
|
||||||
|
|
||||||
|
$oldConfigData = $this->getDataFromJson(self::CONFIG_JSON);
|
||||||
|
$newConfigData = array_intersect_key($newData, $oldConfigData);
|
||||||
|
file_put_contents(self::CONFIG_JSON, json_encode($newConfigData));
|
||||||
|
|
||||||
|
$ucrmData = $this->getDataFromJson(self::UCRM_JSON);
|
||||||
|
|
||||||
|
file_put_contents(self::PLUGIN_JSON, json_encode(array_diff_key($newData, $ucrmData, $newConfigData)));
|
||||||
|
}
|
||||||
|
|
||||||
|
private function getDataFromJson(string $filename): array
|
||||||
|
{
|
||||||
|
if (! file_exists($filename)) {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
|
||||||
|
return json_decode(file_get_contents($filename), true);
|
||||||
|
}
|
||||||
|
}
|
||||||
63
src/Service/PluginDataValidator.php
Executable file
63
src/Service/PluginDataValidator.php
Executable file
@ -0,0 +1,63 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace SmsNotifier\Service;
|
||||||
|
|
||||||
|
class PluginDataValidator
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @var Logger
|
||||||
|
*/
|
||||||
|
private $logger;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var OptionsManager
|
||||||
|
*/
|
||||||
|
private $optionsManager;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var array
|
||||||
|
*/
|
||||||
|
private $errors = [];
|
||||||
|
|
||||||
|
public function __construct(Logger $logger, OptionsManager $optionsManager)
|
||||||
|
{
|
||||||
|
$this->logger = $logger;
|
||||||
|
$this->optionsManager = $optionsManager;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function validate(): bool
|
||||||
|
{
|
||||||
|
$pluginData = $this->optionsManager->load();
|
||||||
|
$valid = true;
|
||||||
|
if (empty($pluginData->twilioAccountSid)) {
|
||||||
|
$this->errors[] = 'Not valid configuration: Twilio Account SID must be configured';
|
||||||
|
$valid = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (empty($pluginData->twilioAuthToken)) {
|
||||||
|
$this->errors[] = 'Not valid configuration: Twilio Auth Token must be configured';
|
||||||
|
$valid = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->logErrors();
|
||||||
|
return $valid;
|
||||||
|
}
|
||||||
|
|
||||||
|
private function logErrors(): void
|
||||||
|
{
|
||||||
|
$pluginData = $this->optionsManager->load();
|
||||||
|
if ($this->errors) {
|
||||||
|
$errorString = implode(PHP_EOL, $this->errors);
|
||||||
|
if ($this->errors && $errorString !== $pluginData->displayedErrors) {
|
||||||
|
$this->logger->error($errorString);
|
||||||
|
$pluginData->displayedErrors = $errorString;
|
||||||
|
$this->optionsManager->update();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
$pluginData->displayedErrors = null;
|
||||||
|
$this->optionsManager->update();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
113
src/Service/SmsNumberProvider.php
Executable file
113
src/Service/SmsNumberProvider.php
Executable file
@ -0,0 +1,113 @@
|
|||||||
|
<?php
|
||||||
|
/*
|
||||||
|
* @copyright Copyright (c) 2018 Ubiquiti Networks, Inc.
|
||||||
|
* @see https://www.ubnt.com/
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
|
||||||
|
namespace SmsNotifier\Service;
|
||||||
|
|
||||||
|
use SmsNotifier\Data\NotificationData;
|
||||||
|
use Ubnt\UcrmPluginSdk\Service\PluginLogManager;
|
||||||
|
|
||||||
|
class SmsNumberProvider
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* go through client's contacts and find an applicable one, if any
|
||||||
|
*/
|
||||||
|
public function getUcrmClientNumber(NotificationData $notificationData): ?string
|
||||||
|
{
|
||||||
|
$contacts = $notificationData->clientData['contacts'] ?? [];
|
||||||
|
foreach ($contacts as $contact) {
|
||||||
|
if ($this->isContactApplicable($notificationData->entity, $contact)) {
|
||||||
|
|
||||||
|
return $contact['phone'];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* go through client's contacts and find an applicable one, if any
|
||||||
|
*/
|
||||||
|
public function getUcrmClientNumbers(NotificationData $notificationData)
|
||||||
|
{
|
||||||
|
// Array asociativo donde almacenarás los números de teléfono con sus tipos correspondientes
|
||||||
|
$arrayPhones = [];
|
||||||
|
|
||||||
|
// Recorrer los contactos del cliente para encontrar los teléfonos con sus tipos
|
||||||
|
foreach ($notificationData->clientData['contacts'] as $contact) {
|
||||||
|
if (!empty($contact['phone'])) { // Verificar que el teléfono no esté vacío
|
||||||
|
if (isset($contact['types']) && is_array($contact['types'])) { // Verificar que 'types' exista y sea un array
|
||||||
|
foreach ($contact['types'] as $type) {
|
||||||
|
if (in_array($type['name'], ['WhatsApp', 'WhatsNotifica', 'WhatsActualiza'])) {
|
||||||
|
// Si el tipo de contacto es uno de los deseados, agregamos al array asociativo
|
||||||
|
$arrayPhones[$type['name']] = $contact['phone'];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return $arrayPhones; // Devolver el arreglo de teléfonos por tipo
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* not every contact has a phone; also check if the type of notification is applicable to contact
|
||||||
|
*/
|
||||||
|
protected function isContactApplicable(string $entity, array $contact = null): bool
|
||||||
|
{
|
||||||
|
$log = PluginLogManager::create(); //Initialize Logger
|
||||||
|
//$log->appendLog("Ejecutando metodo isContactApplicable: " . json_encode($contact) . PHP_EOL);
|
||||||
|
//$entity_export = var_export($entity, true);
|
||||||
|
//$log->appendLog("Valor de Entity: " . $entity_export . PHP_EOL);
|
||||||
|
if (!$contact || empty($contact['phone'])) {
|
||||||
|
$log->appendLog("contac vacio");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
//$log->appendLog("Entrando al switch del método isContactApplicable : " . json_encode($entity));
|
||||||
|
switch ($entity) {
|
||||||
|
case 'invoice':
|
||||||
|
return false;
|
||||||
|
case 'payment': {
|
||||||
|
|
||||||
|
$types = $contact['types'] ?? [];
|
||||||
|
foreach ($types as $type) {
|
||||||
|
//$log->appendLog("Entrando al case client del switch: " . json_encode($type));
|
||||||
|
if ($type['name'] == 'WhatsApp') {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
//return $contact['isBilling'] ?? false;
|
||||||
|
case 'client': {
|
||||||
|
|
||||||
|
$types = $contact['types'] ?? [];
|
||||||
|
foreach ($types as $type) {
|
||||||
|
//$log->appendLog("Entrando al case client del switch: " . json_encode($type));
|
||||||
|
if ($type['name'] == 'WhatsApp') {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
case 'service':
|
||||||
|
{
|
||||||
|
|
||||||
|
$types = $contact['types'] ?? [];
|
||||||
|
foreach ($types as $type) {
|
||||||
|
//$log->appendLog("Entrando al case client del switch: " . json_encode($type));
|
||||||
|
if ($type['name'] == 'WhatsApp') {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
return $contact['isContact'] ?? false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
86
src/Service/UcrmApi.php
Executable file
86
src/Service/UcrmApi.php
Executable file
@ -0,0 +1,86 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
|
||||||
|
namespace SmsNotifier\Service;
|
||||||
|
|
||||||
|
use SmsNotifier\Data\PluginData;
|
||||||
|
use SmsNotifier\Exception\CurlException;
|
||||||
|
|
||||||
|
class UcrmApi
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @var CurlExecutor
|
||||||
|
*/
|
||||||
|
private $curlExecutor;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var OptionsManager
|
||||||
|
*/
|
||||||
|
private $optionsManager;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var bool
|
||||||
|
*/
|
||||||
|
private $verifyUcrmApiConnection;
|
||||||
|
|
||||||
|
public function __construct(CurlExecutor $curlExecutor, OptionsManager $optionsManager)
|
||||||
|
{
|
||||||
|
$this->curlExecutor = $curlExecutor;
|
||||||
|
$this->optionsManager = $optionsManager;
|
||||||
|
|
||||||
|
$urlData = parse_url(
|
||||||
|
$this->getApiUrl($this->optionsManager->load())
|
||||||
|
);
|
||||||
|
$this->verifyUcrmApiConnection = ! (
|
||||||
|
$urlData
|
||||||
|
&& strtolower($urlData['host']) === 'localhost'
|
||||||
|
&& strtolower($urlData['scheme']) === 'https'
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @throws CurlException
|
||||||
|
* @throws \ReflectionException
|
||||||
|
*/
|
||||||
|
public function command(string $endpoint, string $method, array $data): void
|
||||||
|
{
|
||||||
|
$optionsData = $this->optionsManager->load();
|
||||||
|
|
||||||
|
$this->curlExecutor->curlCommand(
|
||||||
|
sprintf('%sapi/v1.0/%s', $this->getApiUrl($optionsData), $endpoint),
|
||||||
|
$method,
|
||||||
|
[
|
||||||
|
'Content-Type: application/json',
|
||||||
|
'X-Auth-App-Key: ' . $optionsData->pluginAppKey,
|
||||||
|
],
|
||||||
|
json_encode((object) $data),
|
||||||
|
$this->verifyUcrmApiConnection
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @throws CurlException
|
||||||
|
* @throws \ReflectionException
|
||||||
|
*/
|
||||||
|
public function query(string $endpoint, array $parameters = []): array
|
||||||
|
{
|
||||||
|
$optionsData = $this->optionsManager->load();
|
||||||
|
|
||||||
|
return $this->curlExecutor->curlQuery(
|
||||||
|
sprintf('%sapi/v1.0/%s', $this->getApiUrl($optionsData), $endpoint),
|
||||||
|
[
|
||||||
|
'Content-Type: application/json',
|
||||||
|
'X-Auth-App-Key: ' . $optionsData->pluginAppKey,
|
||||||
|
],
|
||||||
|
$parameters,
|
||||||
|
$this->verifyUcrmApiConnection
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
private function getApiUrl(PluginData $optionsData): string
|
||||||
|
{
|
||||||
|
return ($optionsData->ucrmLocalUrl ?? false) ?: $optionsData->ucrmPublicUrl;
|
||||||
|
}
|
||||||
|
}
|
||||||
1
ucrm.json
Executable file
1
ucrm.json
Executable file
@ -0,0 +1 @@
|
|||||||
|
{"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}
|
||||||
7
vendor/autoload.php
vendored
Executable file
7
vendor/autoload.php
vendored
Executable file
@ -0,0 +1,7 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
// autoload.php @generated by Composer
|
||||||
|
|
||||||
|
require_once __DIR__ . '/composer/autoload_real.php';
|
||||||
|
|
||||||
|
return ComposerAutoloaderInitd6442a7ec79f2f43fc97d16bdcdd18ee::getLoader();
|
||||||
120
vendor/bin/pack-plugin
vendored
Executable file
120
vendor/bin/pack-plugin
vendored
Executable file
@ -0,0 +1,120 @@
|
|||||||
|
#!/usr/bin/env php
|
||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Proxy PHP file generated by Composer
|
||||||
|
*
|
||||||
|
* This file includes the referenced bin path (../ubnt/ucrm-plugin-sdk/bin/pack-plugin)
|
||||||
|
* using a stream wrapper to prevent the shebang from being output on PHP<8
|
||||||
|
*
|
||||||
|
* @generated
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Composer;
|
||||||
|
|
||||||
|
$GLOBALS['_composer_bin_dir'] = __DIR__;
|
||||||
|
$GLOBALS['_composer_autoload_path'] = __DIR__ . '/..'.'/autoload.php';
|
||||||
|
|
||||||
|
if (PHP_VERSION_ID < 80000) {
|
||||||
|
if (!class_exists('Composer\BinProxyWrapper')) {
|
||||||
|
/**
|
||||||
|
* @internal
|
||||||
|
*/
|
||||||
|
final class BinProxyWrapper
|
||||||
|
{
|
||||||
|
private $handle;
|
||||||
|
private $position;
|
||||||
|
private $realpath;
|
||||||
|
|
||||||
|
public function stream_open($path, $mode, $options, &$opened_path)
|
||||||
|
{
|
||||||
|
// get rid of phpvfscomposer:// prefix for __FILE__ & __DIR__ resolution
|
||||||
|
$opened_path = substr($path, 17);
|
||||||
|
$this->realpath = realpath($opened_path) ?: $opened_path;
|
||||||
|
$opened_path = $this->realpath;
|
||||||
|
$this->handle = fopen($this->realpath, $mode);
|
||||||
|
$this->position = 0;
|
||||||
|
|
||||||
|
return (bool) $this->handle;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function stream_read($count)
|
||||||
|
{
|
||||||
|
$data = fread($this->handle, $count);
|
||||||
|
|
||||||
|
if ($this->position === 0) {
|
||||||
|
$data = preg_replace('{^#!.*\r?\n}', '', $data);
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->position += strlen($data);
|
||||||
|
|
||||||
|
return $data;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function stream_cast($castAs)
|
||||||
|
{
|
||||||
|
return $this->handle;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function stream_close()
|
||||||
|
{
|
||||||
|
fclose($this->handle);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function stream_lock($operation)
|
||||||
|
{
|
||||||
|
return $operation ? flock($this->handle, $operation) : true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function stream_seek($offset, $whence)
|
||||||
|
{
|
||||||
|
if (0 === fseek($this->handle, $offset, $whence)) {
|
||||||
|
$this->position = ftell($this->handle);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function stream_tell()
|
||||||
|
{
|
||||||
|
return $this->position;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function stream_eof()
|
||||||
|
{
|
||||||
|
return feof($this->handle);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function stream_stat()
|
||||||
|
{
|
||||||
|
return array();
|
||||||
|
}
|
||||||
|
|
||||||
|
public function stream_set_option($option, $arg1, $arg2)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function url_stat($path, $flags)
|
||||||
|
{
|
||||||
|
$path = substr($path, 17);
|
||||||
|
if (file_exists($path)) {
|
||||||
|
return stat($path);
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (
|
||||||
|
(function_exists('stream_get_wrappers') && in_array('phpvfscomposer', stream_get_wrappers(), true))
|
||||||
|
|| (function_exists('stream_wrapper_register') && stream_wrapper_register('phpvfscomposer', 'Composer\BinProxyWrapper'))
|
||||||
|
) {
|
||||||
|
include("phpvfscomposer://" . __DIR__ . '/..'.'/ubnt/ucrm-plugin-sdk/bin/pack-plugin');
|
||||||
|
exit(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
include __DIR__ . '/..'.'/ubnt/ucrm-plugin-sdk/bin/pack-plugin';
|
||||||
4
vendor/bin/pack-plugin.bat
vendored
Executable file
4
vendor/bin/pack-plugin.bat
vendored
Executable file
@ -0,0 +1,4 @@
|
|||||||
|
@ECHO OFF
|
||||||
|
setlocal DISABLEDELAYEDEXPANSION
|
||||||
|
SET BIN_TARGET=%~dp0/../ubnt/ucrm-plugin-sdk/bin/pack-plugin
|
||||||
|
php "%BIN_TARGET%" %*
|
||||||
572
vendor/composer/ClassLoader.php
vendored
Executable file
572
vendor/composer/ClassLoader.php
vendored
Executable file
@ -0,0 +1,572 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file is part of Composer.
|
||||||
|
*
|
||||||
|
* (c) Nils Adermann <naderman@naderman.de>
|
||||||
|
* Jordi Boggiano <j.boggiano@seld.be>
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please view the LICENSE
|
||||||
|
* file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Composer\Autoload;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ClassLoader implements a PSR-0, PSR-4 and classmap class loader.
|
||||||
|
*
|
||||||
|
* $loader = new \Composer\Autoload\ClassLoader();
|
||||||
|
*
|
||||||
|
* // register classes with namespaces
|
||||||
|
* $loader->add('Symfony\Component', __DIR__.'/component');
|
||||||
|
* $loader->add('Symfony', __DIR__.'/framework');
|
||||||
|
*
|
||||||
|
* // activate the autoloader
|
||||||
|
* $loader->register();
|
||||||
|
*
|
||||||
|
* // to enable searching the include path (eg. for PEAR packages)
|
||||||
|
* $loader->setUseIncludePath(true);
|
||||||
|
*
|
||||||
|
* In this example, if you try to use a class in the Symfony\Component
|
||||||
|
* namespace or one of its children (Symfony\Component\Console for instance),
|
||||||
|
* the autoloader will first look for the class under the component/
|
||||||
|
* directory, and it will then fallback to the framework/ directory if not
|
||||||
|
* found before giving up.
|
||||||
|
*
|
||||||
|
* This class is loosely based on the Symfony UniversalClassLoader.
|
||||||
|
*
|
||||||
|
* @author Fabien Potencier <fabien@symfony.com>
|
||||||
|
* @author Jordi Boggiano <j.boggiano@seld.be>
|
||||||
|
* @see https://www.php-fig.org/psr/psr-0/
|
||||||
|
* @see https://www.php-fig.org/psr/psr-4/
|
||||||
|
*/
|
||||||
|
class ClassLoader
|
||||||
|
{
|
||||||
|
/** @var ?string */
|
||||||
|
private $vendorDir;
|
||||||
|
|
||||||
|
// PSR-4
|
||||||
|
/**
|
||||||
|
* @var array[]
|
||||||
|
* @psalm-var array<string, array<string, int>>
|
||||||
|
*/
|
||||||
|
private $prefixLengthsPsr4 = array();
|
||||||
|
/**
|
||||||
|
* @var array[]
|
||||||
|
* @psalm-var array<string, array<int, string>>
|
||||||
|
*/
|
||||||
|
private $prefixDirsPsr4 = array();
|
||||||
|
/**
|
||||||
|
* @var array[]
|
||||||
|
* @psalm-var array<string, string>
|
||||||
|
*/
|
||||||
|
private $fallbackDirsPsr4 = array();
|
||||||
|
|
||||||
|
// PSR-0
|
||||||
|
/**
|
||||||
|
* @var array[]
|
||||||
|
* @psalm-var array<string, array<string, string[]>>
|
||||||
|
*/
|
||||||
|
private $prefixesPsr0 = array();
|
||||||
|
/**
|
||||||
|
* @var array[]
|
||||||
|
* @psalm-var array<string, string>
|
||||||
|
*/
|
||||||
|
private $fallbackDirsPsr0 = array();
|
||||||
|
|
||||||
|
/** @var bool */
|
||||||
|
private $useIncludePath = false;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var string[]
|
||||||
|
* @psalm-var array<string, string>
|
||||||
|
*/
|
||||||
|
private $classMap = array();
|
||||||
|
|
||||||
|
/** @var bool */
|
||||||
|
private $classMapAuthoritative = false;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var bool[]
|
||||||
|
* @psalm-var array<string, bool>
|
||||||
|
*/
|
||||||
|
private $missingClasses = array();
|
||||||
|
|
||||||
|
/** @var ?string */
|
||||||
|
private $apcuPrefix;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var self[]
|
||||||
|
*/
|
||||||
|
private static $registeredLoaders = array();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param ?string $vendorDir
|
||||||
|
*/
|
||||||
|
public function __construct($vendorDir = null)
|
||||||
|
{
|
||||||
|
$this->vendorDir = $vendorDir;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return string[]
|
||||||
|
*/
|
||||||
|
public function getPrefixes()
|
||||||
|
{
|
||||||
|
if (!empty($this->prefixesPsr0)) {
|
||||||
|
return call_user_func_array('array_merge', array_values($this->prefixesPsr0));
|
||||||
|
}
|
||||||
|
|
||||||
|
return array();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return array[]
|
||||||
|
* @psalm-return array<string, array<int, string>>
|
||||||
|
*/
|
||||||
|
public function getPrefixesPsr4()
|
||||||
|
{
|
||||||
|
return $this->prefixDirsPsr4;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return array[]
|
||||||
|
* @psalm-return array<string, string>
|
||||||
|
*/
|
||||||
|
public function getFallbackDirs()
|
||||||
|
{
|
||||||
|
return $this->fallbackDirsPsr0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return array[]
|
||||||
|
* @psalm-return array<string, string>
|
||||||
|
*/
|
||||||
|
public function getFallbackDirsPsr4()
|
||||||
|
{
|
||||||
|
return $this->fallbackDirsPsr4;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return string[] Array of classname => path
|
||||||
|
* @psalm-return array<string, string>
|
||||||
|
*/
|
||||||
|
public function getClassMap()
|
||||||
|
{
|
||||||
|
return $this->classMap;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string[] $classMap Class to filename map
|
||||||
|
* @psalm-param array<string, string> $classMap
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function addClassMap(array $classMap)
|
||||||
|
{
|
||||||
|
if ($this->classMap) {
|
||||||
|
$this->classMap = array_merge($this->classMap, $classMap);
|
||||||
|
} else {
|
||||||
|
$this->classMap = $classMap;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Registers a set of PSR-0 directories for a given prefix, either
|
||||||
|
* appending or prepending to the ones previously set for this prefix.
|
||||||
|
*
|
||||||
|
* @param string $prefix The prefix
|
||||||
|
* @param string[]|string $paths The PSR-0 root directories
|
||||||
|
* @param bool $prepend Whether to prepend the directories
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function add($prefix, $paths, $prepend = false)
|
||||||
|
{
|
||||||
|
if (!$prefix) {
|
||||||
|
if ($prepend) {
|
||||||
|
$this->fallbackDirsPsr0 = array_merge(
|
||||||
|
(array) $paths,
|
||||||
|
$this->fallbackDirsPsr0
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
$this->fallbackDirsPsr0 = array_merge(
|
||||||
|
$this->fallbackDirsPsr0,
|
||||||
|
(array) $paths
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
$first = $prefix[0];
|
||||||
|
if (!isset($this->prefixesPsr0[$first][$prefix])) {
|
||||||
|
$this->prefixesPsr0[$first][$prefix] = (array) $paths;
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if ($prepend) {
|
||||||
|
$this->prefixesPsr0[$first][$prefix] = array_merge(
|
||||||
|
(array) $paths,
|
||||||
|
$this->prefixesPsr0[$first][$prefix]
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
$this->prefixesPsr0[$first][$prefix] = array_merge(
|
||||||
|
$this->prefixesPsr0[$first][$prefix],
|
||||||
|
(array) $paths
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Registers a set of PSR-4 directories for a given namespace, either
|
||||||
|
* appending or prepending to the ones previously set for this namespace.
|
||||||
|
*
|
||||||
|
* @param string $prefix The prefix/namespace, with trailing '\\'
|
||||||
|
* @param string[]|string $paths The PSR-4 base directories
|
||||||
|
* @param bool $prepend Whether to prepend the directories
|
||||||
|
*
|
||||||
|
* @throws \InvalidArgumentException
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function addPsr4($prefix, $paths, $prepend = false)
|
||||||
|
{
|
||||||
|
if (!$prefix) {
|
||||||
|
// Register directories for the root namespace.
|
||||||
|
if ($prepend) {
|
||||||
|
$this->fallbackDirsPsr4 = array_merge(
|
||||||
|
(array) $paths,
|
||||||
|
$this->fallbackDirsPsr4
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
$this->fallbackDirsPsr4 = array_merge(
|
||||||
|
$this->fallbackDirsPsr4,
|
||||||
|
(array) $paths
|
||||||
|
);
|
||||||
|
}
|
||||||
|
} elseif (!isset($this->prefixDirsPsr4[$prefix])) {
|
||||||
|
// Register directories for a new namespace.
|
||||||
|
$length = strlen($prefix);
|
||||||
|
if ('\\' !== $prefix[$length - 1]) {
|
||||||
|
throw new \InvalidArgumentException("A non-empty PSR-4 prefix must end with a namespace separator.");
|
||||||
|
}
|
||||||
|
$this->prefixLengthsPsr4[$prefix[0]][$prefix] = $length;
|
||||||
|
$this->prefixDirsPsr4[$prefix] = (array) $paths;
|
||||||
|
} elseif ($prepend) {
|
||||||
|
// Prepend directories for an already registered namespace.
|
||||||
|
$this->prefixDirsPsr4[$prefix] = array_merge(
|
||||||
|
(array) $paths,
|
||||||
|
$this->prefixDirsPsr4[$prefix]
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
// Append directories for an already registered namespace.
|
||||||
|
$this->prefixDirsPsr4[$prefix] = array_merge(
|
||||||
|
$this->prefixDirsPsr4[$prefix],
|
||||||
|
(array) $paths
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Registers a set of PSR-0 directories for a given prefix,
|
||||||
|
* replacing any others previously set for this prefix.
|
||||||
|
*
|
||||||
|
* @param string $prefix The prefix
|
||||||
|
* @param string[]|string $paths The PSR-0 base directories
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function set($prefix, $paths)
|
||||||
|
{
|
||||||
|
if (!$prefix) {
|
||||||
|
$this->fallbackDirsPsr0 = (array) $paths;
|
||||||
|
} else {
|
||||||
|
$this->prefixesPsr0[$prefix[0]][$prefix] = (array) $paths;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Registers a set of PSR-4 directories for a given namespace,
|
||||||
|
* replacing any others previously set for this namespace.
|
||||||
|
*
|
||||||
|
* @param string $prefix The prefix/namespace, with trailing '\\'
|
||||||
|
* @param string[]|string $paths The PSR-4 base directories
|
||||||
|
*
|
||||||
|
* @throws \InvalidArgumentException
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function setPsr4($prefix, $paths)
|
||||||
|
{
|
||||||
|
if (!$prefix) {
|
||||||
|
$this->fallbackDirsPsr4 = (array) $paths;
|
||||||
|
} else {
|
||||||
|
$length = strlen($prefix);
|
||||||
|
if ('\\' !== $prefix[$length - 1]) {
|
||||||
|
throw new \InvalidArgumentException("A non-empty PSR-4 prefix must end with a namespace separator.");
|
||||||
|
}
|
||||||
|
$this->prefixLengthsPsr4[$prefix[0]][$prefix] = $length;
|
||||||
|
$this->prefixDirsPsr4[$prefix] = (array) $paths;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Turns on searching the include path for class files.
|
||||||
|
*
|
||||||
|
* @param bool $useIncludePath
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function setUseIncludePath($useIncludePath)
|
||||||
|
{
|
||||||
|
$this->useIncludePath = $useIncludePath;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Can be used to check if the autoloader uses the include path to check
|
||||||
|
* for classes.
|
||||||
|
*
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
public function getUseIncludePath()
|
||||||
|
{
|
||||||
|
return $this->useIncludePath;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Turns off searching the prefix and fallback directories for classes
|
||||||
|
* that have not been registered with the class map.
|
||||||
|
*
|
||||||
|
* @param bool $classMapAuthoritative
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function setClassMapAuthoritative($classMapAuthoritative)
|
||||||
|
{
|
||||||
|
$this->classMapAuthoritative = $classMapAuthoritative;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Should class lookup fail if not found in the current class map?
|
||||||
|
*
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
public function isClassMapAuthoritative()
|
||||||
|
{
|
||||||
|
return $this->classMapAuthoritative;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* APCu prefix to use to cache found/not-found classes, if the extension is enabled.
|
||||||
|
*
|
||||||
|
* @param string|null $apcuPrefix
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function setApcuPrefix($apcuPrefix)
|
||||||
|
{
|
||||||
|
$this->apcuPrefix = function_exists('apcu_fetch') && filter_var(ini_get('apc.enabled'), FILTER_VALIDATE_BOOLEAN) ? $apcuPrefix : null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The APCu prefix in use, or null if APCu caching is not enabled.
|
||||||
|
*
|
||||||
|
* @return string|null
|
||||||
|
*/
|
||||||
|
public function getApcuPrefix()
|
||||||
|
{
|
||||||
|
return $this->apcuPrefix;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Registers this instance as an autoloader.
|
||||||
|
*
|
||||||
|
* @param bool $prepend Whether to prepend the autoloader or not
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function register($prepend = false)
|
||||||
|
{
|
||||||
|
spl_autoload_register(array($this, 'loadClass'), true, $prepend);
|
||||||
|
|
||||||
|
if (null === $this->vendorDir) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($prepend) {
|
||||||
|
self::$registeredLoaders = array($this->vendorDir => $this) + self::$registeredLoaders;
|
||||||
|
} else {
|
||||||
|
unset(self::$registeredLoaders[$this->vendorDir]);
|
||||||
|
self::$registeredLoaders[$this->vendorDir] = $this;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Unregisters this instance as an autoloader.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function unregister()
|
||||||
|
{
|
||||||
|
spl_autoload_unregister(array($this, 'loadClass'));
|
||||||
|
|
||||||
|
if (null !== $this->vendorDir) {
|
||||||
|
unset(self::$registeredLoaders[$this->vendorDir]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Loads the given class or interface.
|
||||||
|
*
|
||||||
|
* @param string $class The name of the class
|
||||||
|
* @return true|null True if loaded, null otherwise
|
||||||
|
*/
|
||||||
|
public function loadClass($class)
|
||||||
|
{
|
||||||
|
if ($file = $this->findFile($class)) {
|
||||||
|
includeFile($file);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Finds the path to the file where the class is defined.
|
||||||
|
*
|
||||||
|
* @param string $class The name of the class
|
||||||
|
*
|
||||||
|
* @return string|false The path if found, false otherwise
|
||||||
|
*/
|
||||||
|
public function findFile($class)
|
||||||
|
{
|
||||||
|
// class map lookup
|
||||||
|
if (isset($this->classMap[$class])) {
|
||||||
|
return $this->classMap[$class];
|
||||||
|
}
|
||||||
|
if ($this->classMapAuthoritative || isset($this->missingClasses[$class])) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (null !== $this->apcuPrefix) {
|
||||||
|
$file = apcu_fetch($this->apcuPrefix.$class, $hit);
|
||||||
|
if ($hit) {
|
||||||
|
return $file;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$file = $this->findFileWithExtension($class, '.php');
|
||||||
|
|
||||||
|
// Search for Hack files if we are running on HHVM
|
||||||
|
if (false === $file && defined('HHVM_VERSION')) {
|
||||||
|
$file = $this->findFileWithExtension($class, '.hh');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (null !== $this->apcuPrefix) {
|
||||||
|
apcu_add($this->apcuPrefix.$class, $file);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (false === $file) {
|
||||||
|
// Remember that this class does not exist.
|
||||||
|
$this->missingClasses[$class] = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $file;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the currently registered loaders indexed by their corresponding vendor directories.
|
||||||
|
*
|
||||||
|
* @return self[]
|
||||||
|
*/
|
||||||
|
public static function getRegisteredLoaders()
|
||||||
|
{
|
||||||
|
return self::$registeredLoaders;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $class
|
||||||
|
* @param string $ext
|
||||||
|
* @return string|false
|
||||||
|
*/
|
||||||
|
private function findFileWithExtension($class, $ext)
|
||||||
|
{
|
||||||
|
// PSR-4 lookup
|
||||||
|
$logicalPathPsr4 = strtr($class, '\\', DIRECTORY_SEPARATOR) . $ext;
|
||||||
|
|
||||||
|
$first = $class[0];
|
||||||
|
if (isset($this->prefixLengthsPsr4[$first])) {
|
||||||
|
$subPath = $class;
|
||||||
|
while (false !== $lastPos = strrpos($subPath, '\\')) {
|
||||||
|
$subPath = substr($subPath, 0, $lastPos);
|
||||||
|
$search = $subPath . '\\';
|
||||||
|
if (isset($this->prefixDirsPsr4[$search])) {
|
||||||
|
$pathEnd = DIRECTORY_SEPARATOR . substr($logicalPathPsr4, $lastPos + 1);
|
||||||
|
foreach ($this->prefixDirsPsr4[$search] as $dir) {
|
||||||
|
if (file_exists($file = $dir . $pathEnd)) {
|
||||||
|
return $file;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// PSR-4 fallback dirs
|
||||||
|
foreach ($this->fallbackDirsPsr4 as $dir) {
|
||||||
|
if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr4)) {
|
||||||
|
return $file;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// PSR-0 lookup
|
||||||
|
if (false !== $pos = strrpos($class, '\\')) {
|
||||||
|
// namespaced class name
|
||||||
|
$logicalPathPsr0 = substr($logicalPathPsr4, 0, $pos + 1)
|
||||||
|
. strtr(substr($logicalPathPsr4, $pos + 1), '_', DIRECTORY_SEPARATOR);
|
||||||
|
} else {
|
||||||
|
// PEAR-like class name
|
||||||
|
$logicalPathPsr0 = strtr($class, '_', DIRECTORY_SEPARATOR) . $ext;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isset($this->prefixesPsr0[$first])) {
|
||||||
|
foreach ($this->prefixesPsr0[$first] as $prefix => $dirs) {
|
||||||
|
if (0 === strpos($class, $prefix)) {
|
||||||
|
foreach ($dirs as $dir) {
|
||||||
|
if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr0)) {
|
||||||
|
return $file;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// PSR-0 fallback dirs
|
||||||
|
foreach ($this->fallbackDirsPsr0 as $dir) {
|
||||||
|
if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr0)) {
|
||||||
|
return $file;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// PSR-0 include paths.
|
||||||
|
if ($this->useIncludePath && $file = stream_resolve_include_path($logicalPathPsr0)) {
|
||||||
|
return $file;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Scope isolated include.
|
||||||
|
*
|
||||||
|
* Prevents access to $this/self from included files.
|
||||||
|
*
|
||||||
|
* @param string $file
|
||||||
|
* @return void
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
function includeFile($file)
|
||||||
|
{
|
||||||
|
include $file;
|
||||||
|
}
|
||||||
350
vendor/composer/InstalledVersions.php
vendored
Executable file
350
vendor/composer/InstalledVersions.php
vendored
Executable file
@ -0,0 +1,350 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file is part of Composer.
|
||||||
|
*
|
||||||
|
* (c) Nils Adermann <naderman@naderman.de>
|
||||||
|
* Jordi Boggiano <j.boggiano@seld.be>
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please view the LICENSE
|
||||||
|
* file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Composer;
|
||||||
|
|
||||||
|
use Composer\Autoload\ClassLoader;
|
||||||
|
use Composer\Semver\VersionParser;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This class is copied in every Composer installed project and available to all
|
||||||
|
*
|
||||||
|
* See also https://getcomposer.org/doc/07-runtime.md#installed-versions
|
||||||
|
*
|
||||||
|
* To require its presence, you can require `composer-runtime-api ^2.0`
|
||||||
|
*/
|
||||||
|
class InstalledVersions
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @var mixed[]|null
|
||||||
|
* @psalm-var array{root: array{name: string, version: string, reference: string, pretty_version: string, aliases: string[], dev: bool, install_path: string, type: string}, versions: array<string, array{dev_requirement: bool, pretty_version?: string, version?: string, aliases?: string[], reference?: string, replaced?: string[], provided?: string[], install_path?: string, type?: string}>}|array{}|null
|
||||||
|
*/
|
||||||
|
private static $installed;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var bool|null
|
||||||
|
*/
|
||||||
|
private static $canGetVendors;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var array[]
|
||||||
|
* @psalm-var array<string, array{root: array{name: string, version: string, reference: string, pretty_version: string, aliases: string[], dev: bool, install_path: string, type: string}, versions: array<string, array{dev_requirement: bool, pretty_version?: string, version?: string, aliases?: string[], reference?: string, replaced?: string[], provided?: string[], install_path?: string, type?: string}>}>
|
||||||
|
*/
|
||||||
|
private static $installedByVendor = array();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a list of all package names which are present, either by being installed, replaced or provided
|
||||||
|
*
|
||||||
|
* @return string[]
|
||||||
|
* @psalm-return list<string>
|
||||||
|
*/
|
||||||
|
public static function getInstalledPackages()
|
||||||
|
{
|
||||||
|
$packages = array();
|
||||||
|
foreach (self::getInstalled() as $installed) {
|
||||||
|
$packages[] = array_keys($installed['versions']);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (1 === \count($packages)) {
|
||||||
|
return $packages[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
return array_keys(array_flip(\call_user_func_array('array_merge', $packages)));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a list of all package names with a specific type e.g. 'library'
|
||||||
|
*
|
||||||
|
* @param string $type
|
||||||
|
* @return string[]
|
||||||
|
* @psalm-return list<string>
|
||||||
|
*/
|
||||||
|
public static function getInstalledPackagesByType($type)
|
||||||
|
{
|
||||||
|
$packagesByType = array();
|
||||||
|
|
||||||
|
foreach (self::getInstalled() as $installed) {
|
||||||
|
foreach ($installed['versions'] as $name => $package) {
|
||||||
|
if (isset($package['type']) && $package['type'] === $type) {
|
||||||
|
$packagesByType[] = $name;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $packagesByType;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks whether the given package is installed
|
||||||
|
*
|
||||||
|
* This also returns true if the package name is provided or replaced by another package
|
||||||
|
*
|
||||||
|
* @param string $packageName
|
||||||
|
* @param bool $includeDevRequirements
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
public static function isInstalled($packageName, $includeDevRequirements = true)
|
||||||
|
{
|
||||||
|
foreach (self::getInstalled() as $installed) {
|
||||||
|
if (isset($installed['versions'][$packageName])) {
|
||||||
|
return $includeDevRequirements || empty($installed['versions'][$packageName]['dev_requirement']);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks whether the given package satisfies a version constraint
|
||||||
|
*
|
||||||
|
* e.g. If you want to know whether version 2.3+ of package foo/bar is installed, you would call:
|
||||||
|
*
|
||||||
|
* Composer\InstalledVersions::satisfies(new VersionParser, 'foo/bar', '^2.3')
|
||||||
|
*
|
||||||
|
* @param VersionParser $parser Install composer/semver to have access to this class and functionality
|
||||||
|
* @param string $packageName
|
||||||
|
* @param string|null $constraint A version constraint to check for, if you pass one you have to make sure composer/semver is required by your package
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
public static function satisfies(VersionParser $parser, $packageName, $constraint)
|
||||||
|
{
|
||||||
|
$constraint = $parser->parseConstraints($constraint);
|
||||||
|
$provided = $parser->parseConstraints(self::getVersionRanges($packageName));
|
||||||
|
|
||||||
|
return $provided->matches($constraint);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a version constraint representing all the range(s) which are installed for a given package
|
||||||
|
*
|
||||||
|
* It is easier to use this via isInstalled() with the $constraint argument if you need to check
|
||||||
|
* whether a given version of a package is installed, and not just whether it exists
|
||||||
|
*
|
||||||
|
* @param string $packageName
|
||||||
|
* @return string Version constraint usable with composer/semver
|
||||||
|
*/
|
||||||
|
public static function getVersionRanges($packageName)
|
||||||
|
{
|
||||||
|
foreach (self::getInstalled() as $installed) {
|
||||||
|
if (!isset($installed['versions'][$packageName])) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
$ranges = array();
|
||||||
|
if (isset($installed['versions'][$packageName]['pretty_version'])) {
|
||||||
|
$ranges[] = $installed['versions'][$packageName]['pretty_version'];
|
||||||
|
}
|
||||||
|
if (array_key_exists('aliases', $installed['versions'][$packageName])) {
|
||||||
|
$ranges = array_merge($ranges, $installed['versions'][$packageName]['aliases']);
|
||||||
|
}
|
||||||
|
if (array_key_exists('replaced', $installed['versions'][$packageName])) {
|
||||||
|
$ranges = array_merge($ranges, $installed['versions'][$packageName]['replaced']);
|
||||||
|
}
|
||||||
|
if (array_key_exists('provided', $installed['versions'][$packageName])) {
|
||||||
|
$ranges = array_merge($ranges, $installed['versions'][$packageName]['provided']);
|
||||||
|
}
|
||||||
|
|
||||||
|
return implode(' || ', $ranges);
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $packageName
|
||||||
|
* @return string|null If the package is being replaced or provided but is not really installed, null will be returned as version, use satisfies or getVersionRanges if you need to know if a given version is present
|
||||||
|
*/
|
||||||
|
public static function getVersion($packageName)
|
||||||
|
{
|
||||||
|
foreach (self::getInstalled() as $installed) {
|
||||||
|
if (!isset($installed['versions'][$packageName])) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!isset($installed['versions'][$packageName]['version'])) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $installed['versions'][$packageName]['version'];
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $packageName
|
||||||
|
* @return string|null If the package is being replaced or provided but is not really installed, null will be returned as version, use satisfies or getVersionRanges if you need to know if a given version is present
|
||||||
|
*/
|
||||||
|
public static function getPrettyVersion($packageName)
|
||||||
|
{
|
||||||
|
foreach (self::getInstalled() as $installed) {
|
||||||
|
if (!isset($installed['versions'][$packageName])) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!isset($installed['versions'][$packageName]['pretty_version'])) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $installed['versions'][$packageName]['pretty_version'];
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $packageName
|
||||||
|
* @return string|null If the package is being replaced or provided but is not really installed, null will be returned as reference
|
||||||
|
*/
|
||||||
|
public static function getReference($packageName)
|
||||||
|
{
|
||||||
|
foreach (self::getInstalled() as $installed) {
|
||||||
|
if (!isset($installed['versions'][$packageName])) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!isset($installed['versions'][$packageName]['reference'])) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $installed['versions'][$packageName]['reference'];
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $packageName
|
||||||
|
* @return string|null If the package is being replaced or provided but is not really installed, null will be returned as install path. Packages of type metapackages also have a null install path.
|
||||||
|
*/
|
||||||
|
public static function getInstallPath($packageName)
|
||||||
|
{
|
||||||
|
foreach (self::getInstalled() as $installed) {
|
||||||
|
if (!isset($installed['versions'][$packageName])) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
return isset($installed['versions'][$packageName]['install_path']) ? $installed['versions'][$packageName]['install_path'] : null;
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return array
|
||||||
|
* @psalm-return array{name: string, version: string, reference: string, pretty_version: string, aliases: string[], dev: bool, install_path: string, type: string}
|
||||||
|
*/
|
||||||
|
public static function getRootPackage()
|
||||||
|
{
|
||||||
|
$installed = self::getInstalled();
|
||||||
|
|
||||||
|
return $installed[0]['root'];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the raw installed.php data for custom implementations
|
||||||
|
*
|
||||||
|
* @deprecated Use getAllRawData() instead which returns all datasets for all autoloaders present in the process. getRawData only returns the first dataset loaded, which may not be what you expect.
|
||||||
|
* @return array[]
|
||||||
|
* @psalm-return array{root: array{name: string, version: string, reference: string, pretty_version: string, aliases: string[], dev: bool, install_path: string, type: string}, versions: array<string, array{dev_requirement: bool, pretty_version?: string, version?: string, aliases?: string[], reference?: string, replaced?: string[], provided?: string[], install_path?: string, type?: string}>}
|
||||||
|
*/
|
||||||
|
public static function getRawData()
|
||||||
|
{
|
||||||
|
@trigger_error('getRawData only returns the first dataset loaded, which may not be what you expect. Use getAllRawData() instead which returns all datasets for all autoloaders present in the process.', E_USER_DEPRECATED);
|
||||||
|
|
||||||
|
if (null === self::$installed) {
|
||||||
|
// only require the installed.php file if this file is loaded from its dumped location,
|
||||||
|
// and not from its source location in the composer/composer package, see https://github.com/composer/composer/issues/9937
|
||||||
|
if (substr(__DIR__, -8, 1) !== 'C') {
|
||||||
|
self::$installed = include __DIR__ . '/installed.php';
|
||||||
|
} else {
|
||||||
|
self::$installed = array();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return self::$installed;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the raw data of all installed.php which are currently loaded for custom implementations
|
||||||
|
*
|
||||||
|
* @return array[]
|
||||||
|
* @psalm-return list<array{root: array{name: string, version: string, reference: string, pretty_version: string, aliases: string[], dev: bool, install_path: string, type: string}, versions: array<string, array{dev_requirement: bool, pretty_version?: string, version?: string, aliases?: string[], reference?: string, replaced?: string[], provided?: string[], install_path?: string, type?: string}>}>
|
||||||
|
*/
|
||||||
|
public static function getAllRawData()
|
||||||
|
{
|
||||||
|
return self::getInstalled();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Lets you reload the static array from another file
|
||||||
|
*
|
||||||
|
* This is only useful for complex integrations in which a project needs to use
|
||||||
|
* this class but then also needs to execute another project's autoloader in process,
|
||||||
|
* and wants to ensure both projects have access to their version of installed.php.
|
||||||
|
*
|
||||||
|
* A typical case would be PHPUnit, where it would need to make sure it reads all
|
||||||
|
* the data it needs from this class, then call reload() with
|
||||||
|
* `require $CWD/vendor/composer/installed.php` (or similar) as input to make sure
|
||||||
|
* the project in which it runs can then also use this class safely, without
|
||||||
|
* interference between PHPUnit's dependencies and the project's dependencies.
|
||||||
|
*
|
||||||
|
* @param array[] $data A vendor/composer/installed.php data set
|
||||||
|
* @return void
|
||||||
|
*
|
||||||
|
* @psalm-param array{root: array{name: string, version: string, reference: string, pretty_version: string, aliases: string[], dev: bool, install_path: string, type: string}, versions: array<string, array{dev_requirement: bool, pretty_version?: string, version?: string, aliases?: string[], reference?: string, replaced?: string[], provided?: string[], install_path?: string, type?: string}>} $data
|
||||||
|
*/
|
||||||
|
public static function reload($data)
|
||||||
|
{
|
||||||
|
self::$installed = $data;
|
||||||
|
self::$installedByVendor = array();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return array[]
|
||||||
|
* @psalm-return list<array{root: array{name: string, version: string, reference: string, pretty_version: string, aliases: string[], dev: bool, install_path: string, type: string}, versions: array<string, array{dev_requirement: bool, pretty_version?: string, version?: string, aliases?: string[], reference?: string, replaced?: string[], provided?: string[], install_path?: string, type?: string}>}>
|
||||||
|
*/
|
||||||
|
private static function getInstalled()
|
||||||
|
{
|
||||||
|
if (null === self::$canGetVendors) {
|
||||||
|
self::$canGetVendors = method_exists('Composer\Autoload\ClassLoader', 'getRegisteredLoaders');
|
||||||
|
}
|
||||||
|
|
||||||
|
$installed = array();
|
||||||
|
|
||||||
|
if (self::$canGetVendors) {
|
||||||
|
foreach (ClassLoader::getRegisteredLoaders() as $vendorDir => $loader) {
|
||||||
|
if (isset(self::$installedByVendor[$vendorDir])) {
|
||||||
|
$installed[] = self::$installedByVendor[$vendorDir];
|
||||||
|
} elseif (is_file($vendorDir.'/composer/installed.php')) {
|
||||||
|
$installed[] = self::$installedByVendor[$vendorDir] = require $vendorDir.'/composer/installed.php';
|
||||||
|
if (null === self::$installed && strtr($vendorDir.'/composer', '\\', '/') === strtr(__DIR__, '\\', '/')) {
|
||||||
|
self::$installed = $installed[count($installed) - 1];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (null === self::$installed) {
|
||||||
|
// only require the installed.php file if this file is loaded from its dumped location,
|
||||||
|
// and not from its source location in the composer/composer package, see https://github.com/composer/composer/issues/9937
|
||||||
|
if (substr(__DIR__, -8, 1) !== 'C') {
|
||||||
|
self::$installed = require __DIR__ . '/installed.php';
|
||||||
|
} else {
|
||||||
|
self::$installed = array();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
$installed[] = self::$installed;
|
||||||
|
|
||||||
|
return $installed;
|
||||||
|
}
|
||||||
|
}
|
||||||
19
vendor/composer/LICENSE
vendored
Executable file
19
vendor/composer/LICENSE
vendored
Executable file
@ -0,0 +1,19 @@
|
|||||||
|
Copyright (c) Nils Adermann, Jordi Boggiano
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is furnished
|
||||||
|
to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in all
|
||||||
|
copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
THE SOFTWARE.
|
||||||
29146
vendor/composer/autoload_classmap.php
vendored
Executable file
29146
vendor/composer/autoload_classmap.php
vendored
Executable file
File diff suppressed because it is too large
Load Diff
18
vendor/composer/autoload_files.php
vendored
Executable file
18
vendor/composer/autoload_files.php
vendored
Executable file
@ -0,0 +1,18 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
// autoload_files.php @generated by Composer
|
||||||
|
|
||||||
|
$vendorDir = dirname(dirname(__FILE__));
|
||||||
|
$baseDir = dirname($vendorDir);
|
||||||
|
|
||||||
|
return array(
|
||||||
|
'7b11c4dc42b3b3023073cb14e519683c' => $vendorDir . '/ralouphie/getallheaders/src/getallheaders.php',
|
||||||
|
'6e3fae29631ef280660b3cdad06f25a8' => $vendorDir . '/symfony/deprecation-contracts/function.php',
|
||||||
|
'37a3dc5111fe8f707ab4c132ef1dbc62' => $vendorDir . '/guzzlehttp/guzzle/src/functions_include.php',
|
||||||
|
'decc78cc4436b1292c6c0d151b19445c' => $vendorDir . '/phpseclib/phpseclib/phpseclib/bootstrap.php',
|
||||||
|
'320cde22f66dd4f5d3fd621d3e88b98f' => $vendorDir . '/symfony/polyfill-ctype/bootstrap.php',
|
||||||
|
'0e6d7bf4a5811bfa5cf40c5ccd6fae6a' => $vendorDir . '/symfony/polyfill-mbstring/bootstrap.php',
|
||||||
|
'1f87db08236948d07391152dccb70f04' => $vendorDir . '/google/apiclient-services/autoload.php',
|
||||||
|
'a8d3953fd9959404dd22d3dfcd0a79f0' => $vendorDir . '/google/apiclient/src/aliases.php',
|
||||||
|
'b33e3d135e5d9e47d845c576147bda89' => $vendorDir . '/php-di/php-di/src/functions.php',
|
||||||
|
);
|
||||||
9
vendor/composer/autoload_namespaces.php
vendored
Executable file
9
vendor/composer/autoload_namespaces.php
vendored
Executable file
@ -0,0 +1,9 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
// autoload_namespaces.php @generated by Composer
|
||||||
|
|
||||||
|
$vendorDir = dirname(dirname(__FILE__));
|
||||||
|
$baseDir = dirname($vendorDir);
|
||||||
|
|
||||||
|
return array(
|
||||||
|
);
|
||||||
35
vendor/composer/autoload_psr4.php
vendored
Executable file
35
vendor/composer/autoload_psr4.php
vendored
Executable file
@ -0,0 +1,35 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
// autoload_psr4.php @generated by Composer
|
||||||
|
|
||||||
|
$vendorDir = dirname(dirname(__FILE__));
|
||||||
|
$baseDir = dirname($vendorDir);
|
||||||
|
|
||||||
|
return array(
|
||||||
|
'phpseclib3\\' => array($vendorDir . '/phpseclib/phpseclib/phpseclib'),
|
||||||
|
'Ubnt\\' => array($vendorDir . '/ubnt/ucrm-plugin-sdk/src'),
|
||||||
|
'Twilio\\' => array($vendorDir . '/twilio/sdk/src/Twilio'),
|
||||||
|
'Symfony\\Polyfill\\Mbstring\\' => array($vendorDir . '/symfony/polyfill-mbstring'),
|
||||||
|
'Symfony\\Polyfill\\Ctype\\' => array($vendorDir . '/symfony/polyfill-ctype'),
|
||||||
|
'Symfony\\Component\\Filesystem\\' => array($vendorDir . '/symfony/filesystem'),
|
||||||
|
'Stripe\\' => array($vendorDir . '/stripe/stripe-php/lib'),
|
||||||
|
'SmsNotifier\\' => array($baseDir . '/src'),
|
||||||
|
'Psr\\Log\\' => array($vendorDir . '/psr/log/Psr/Log'),
|
||||||
|
'Psr\\Http\\Message\\' => array($vendorDir . '/psr/http-factory/src', $vendorDir . '/psr/http-message/src'),
|
||||||
|
'Psr\\Http\\Client\\' => array($vendorDir . '/psr/http-client/src'),
|
||||||
|
'Psr\\Container\\' => array($vendorDir . '/psr/container/src'),
|
||||||
|
'Psr\\Cache\\' => array($vendorDir . '/psr/cache/src'),
|
||||||
|
'ParagonIE\\ConstantTime\\' => array($vendorDir . '/paragonie/constant_time_encoding/src'),
|
||||||
|
'Monolog\\' => array($vendorDir . '/monolog/monolog/src/Monolog'),
|
||||||
|
'Laravel\\SerializableClosure\\' => array($vendorDir . '/laravel/serializable-closure/src'),
|
||||||
|
'Katzgrau\\KLogger\\' => array($vendorDir . '/katzgrau/klogger/src'),
|
||||||
|
'Invoker\\' => array($vendorDir . '/php-di/invoker/src'),
|
||||||
|
'GuzzleHttp\\Psr7\\' => array($vendorDir . '/guzzlehttp/psr7/src'),
|
||||||
|
'GuzzleHttp\\Promise\\' => array($vendorDir . '/guzzlehttp/promises/src'),
|
||||||
|
'GuzzleHttp\\' => array($vendorDir . '/guzzlehttp/guzzle/src'),
|
||||||
|
'Google\\Service\\' => array($vendorDir . '/google/apiclient-services/src'),
|
||||||
|
'Google\\Auth\\' => array($vendorDir . '/google/auth/src'),
|
||||||
|
'Google\\' => array($vendorDir . '/google/apiclient/src'),
|
||||||
|
'Firebase\\JWT\\' => array($vendorDir . '/firebase/php-jwt/src'),
|
||||||
|
'DI\\' => array($vendorDir . '/php-di/php-di/src'),
|
||||||
|
);
|
||||||
71
vendor/composer/autoload_real.php
vendored
Executable file
71
vendor/composer/autoload_real.php
vendored
Executable file
@ -0,0 +1,71 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
// autoload_real.php @generated by Composer
|
||||||
|
|
||||||
|
class ComposerAutoloaderInitd6442a7ec79f2f43fc97d16bdcdd18ee
|
||||||
|
{
|
||||||
|
private static $loader;
|
||||||
|
|
||||||
|
public static function loadClassLoader($class)
|
||||||
|
{
|
||||||
|
if ('Composer\Autoload\ClassLoader' === $class) {
|
||||||
|
require __DIR__ . '/ClassLoader.php';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return \Composer\Autoload\ClassLoader
|
||||||
|
*/
|
||||||
|
public static function getLoader()
|
||||||
|
{
|
||||||
|
if (null !== self::$loader) {
|
||||||
|
return self::$loader;
|
||||||
|
}
|
||||||
|
|
||||||
|
require __DIR__ . '/platform_check.php';
|
||||||
|
|
||||||
|
spl_autoload_register(array('ComposerAutoloaderInitd6442a7ec79f2f43fc97d16bdcdd18ee', 'loadClassLoader'), true, true);
|
||||||
|
self::$loader = $loader = new \Composer\Autoload\ClassLoader(\dirname(\dirname(__FILE__)));
|
||||||
|
spl_autoload_unregister(array('ComposerAutoloaderInitd6442a7ec79f2f43fc97d16bdcdd18ee', 'loadClassLoader'));
|
||||||
|
|
||||||
|
$useStaticLoader = PHP_VERSION_ID >= 50600 && !defined('HHVM_VERSION') && (!function_exists('zend_loader_file_encoded') || !zend_loader_file_encoded());
|
||||||
|
if ($useStaticLoader) {
|
||||||
|
require __DIR__ . '/autoload_static.php';
|
||||||
|
|
||||||
|
call_user_func(\Composer\Autoload\ComposerStaticInitd6442a7ec79f2f43fc97d16bdcdd18ee::getInitializer($loader));
|
||||||
|
} else {
|
||||||
|
$classMap = require __DIR__ . '/autoload_classmap.php';
|
||||||
|
if ($classMap) {
|
||||||
|
$loader->addClassMap($classMap);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$loader->setClassMapAuthoritative(true);
|
||||||
|
$loader->register(true);
|
||||||
|
|
||||||
|
if ($useStaticLoader) {
|
||||||
|
$includeFiles = Composer\Autoload\ComposerStaticInitd6442a7ec79f2f43fc97d16bdcdd18ee::$files;
|
||||||
|
} else {
|
||||||
|
$includeFiles = require __DIR__ . '/autoload_files.php';
|
||||||
|
}
|
||||||
|
foreach ($includeFiles as $fileIdentifier => $file) {
|
||||||
|
composerRequired6442a7ec79f2f43fc97d16bdcdd18ee($fileIdentifier, $file);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $loader;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $fileIdentifier
|
||||||
|
* @param string $file
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
function composerRequired6442a7ec79f2f43fc97d16bdcdd18ee($fileIdentifier, $file)
|
||||||
|
{
|
||||||
|
if (empty($GLOBALS['__composer_autoload_files'][$fileIdentifier])) {
|
||||||
|
$GLOBALS['__composer_autoload_files'][$fileIdentifier] = true;
|
||||||
|
|
||||||
|
require $file;
|
||||||
|
}
|
||||||
|
}
|
||||||
29343
vendor/composer/autoload_static.php
vendored
Executable file
29343
vendor/composer/autoload_static.php
vendored
Executable file
File diff suppressed because it is too large
Load Diff
2041
vendor/composer/installed.json
vendored
Executable file
2041
vendor/composer/installed.json
vendored
Executable file
File diff suppressed because it is too large
Load Diff
314
vendor/composer/installed.php
vendored
Executable file
314
vendor/composer/installed.php
vendored
Executable file
@ -0,0 +1,314 @@
|
|||||||
|
<?php return array(
|
||||||
|
'root' => array(
|
||||||
|
'pretty_version' => '1.0.0+no-version-set',
|
||||||
|
'version' => '1.0.0.0',
|
||||||
|
'type' => 'library',
|
||||||
|
'install_path' => __DIR__ . '/../../',
|
||||||
|
'aliases' => array(),
|
||||||
|
'reference' => NULL,
|
||||||
|
'name' => 'ucrm-plugins/sms-twilio',
|
||||||
|
'dev' => false,
|
||||||
|
),
|
||||||
|
'versions' => array(
|
||||||
|
'firebase/php-jwt' => array(
|
||||||
|
'pretty_version' => 'v6.10.1',
|
||||||
|
'version' => '6.10.1.0',
|
||||||
|
'type' => 'library',
|
||||||
|
'install_path' => __DIR__ . '/../firebase/php-jwt',
|
||||||
|
'aliases' => array(),
|
||||||
|
'reference' => '500501c2ce893c824c801da135d02661199f60c5',
|
||||||
|
'dev_requirement' => false,
|
||||||
|
),
|
||||||
|
'google/apiclient' => array(
|
||||||
|
'pretty_version' => 'v2.16.0',
|
||||||
|
'version' => '2.16.0.0',
|
||||||
|
'type' => 'library',
|
||||||
|
'install_path' => __DIR__ . '/../google/apiclient',
|
||||||
|
'aliases' => array(),
|
||||||
|
'reference' => '017400f609c1fb71ab5ad824c50eabd4c3eaf779',
|
||||||
|
'dev_requirement' => false,
|
||||||
|
),
|
||||||
|
'google/apiclient-services' => array(
|
||||||
|
'pretty_version' => 'v0.359.0',
|
||||||
|
'version' => '0.359.0.0',
|
||||||
|
'type' => 'library',
|
||||||
|
'install_path' => __DIR__ . '/../google/apiclient-services',
|
||||||
|
'aliases' => array(),
|
||||||
|
'reference' => 'e975e6d0efa47f7e49280c4ea7fd6a93b6d7e338',
|
||||||
|
'dev_requirement' => false,
|
||||||
|
),
|
||||||
|
'google/auth' => array(
|
||||||
|
'pretty_version' => 'v1.40.0',
|
||||||
|
'version' => '1.40.0.0',
|
||||||
|
'type' => 'library',
|
||||||
|
'install_path' => __DIR__ . '/../google/auth',
|
||||||
|
'aliases' => array(),
|
||||||
|
'reference' => 'bff9f2d01677e71a98394b5ac981b99523df5178',
|
||||||
|
'dev_requirement' => false,
|
||||||
|
),
|
||||||
|
'guzzlehttp/guzzle' => array(
|
||||||
|
'pretty_version' => '7.8.1',
|
||||||
|
'version' => '7.8.1.0',
|
||||||
|
'type' => 'library',
|
||||||
|
'install_path' => __DIR__ . '/../guzzlehttp/guzzle',
|
||||||
|
'aliases' => array(),
|
||||||
|
'reference' => '41042bc7ab002487b876a0683fc8dce04ddce104',
|
||||||
|
'dev_requirement' => false,
|
||||||
|
),
|
||||||
|
'guzzlehttp/promises' => array(
|
||||||
|
'pretty_version' => '2.0.2',
|
||||||
|
'version' => '2.0.2.0',
|
||||||
|
'type' => 'library',
|
||||||
|
'install_path' => __DIR__ . '/../guzzlehttp/promises',
|
||||||
|
'aliases' => array(),
|
||||||
|
'reference' => 'bbff78d96034045e58e13dedd6ad91b5d1253223',
|
||||||
|
'dev_requirement' => false,
|
||||||
|
),
|
||||||
|
'guzzlehttp/psr7' => array(
|
||||||
|
'pretty_version' => '2.6.2',
|
||||||
|
'version' => '2.6.2.0',
|
||||||
|
'type' => 'library',
|
||||||
|
'install_path' => __DIR__ . '/../guzzlehttp/psr7',
|
||||||
|
'aliases' => array(),
|
||||||
|
'reference' => '45b30f99ac27b5ca93cb4831afe16285f57b8221',
|
||||||
|
'dev_requirement' => false,
|
||||||
|
),
|
||||||
|
'katzgrau/klogger' => array(
|
||||||
|
'pretty_version' => '1.2.2',
|
||||||
|
'version' => '1.2.2.0',
|
||||||
|
'type' => 'library',
|
||||||
|
'install_path' => __DIR__ . '/../katzgrau/klogger',
|
||||||
|
'aliases' => array(),
|
||||||
|
'reference' => '36481c69db9305169a2ceadead25c2acaabd567c',
|
||||||
|
'dev_requirement' => false,
|
||||||
|
),
|
||||||
|
'laravel/serializable-closure' => array(
|
||||||
|
'pretty_version' => 'v1.3.3',
|
||||||
|
'version' => '1.3.3.0',
|
||||||
|
'type' => 'library',
|
||||||
|
'install_path' => __DIR__ . '/../laravel/serializable-closure',
|
||||||
|
'aliases' => array(),
|
||||||
|
'reference' => '3dbf8a8e914634c48d389c1234552666b3d43754',
|
||||||
|
'dev_requirement' => false,
|
||||||
|
),
|
||||||
|
'monolog/monolog' => array(
|
||||||
|
'pretty_version' => '2.9.3',
|
||||||
|
'version' => '2.9.3.0',
|
||||||
|
'type' => 'library',
|
||||||
|
'install_path' => __DIR__ . '/../monolog/monolog',
|
||||||
|
'aliases' => array(),
|
||||||
|
'reference' => 'a30bfe2e142720dfa990d0a7e573997f5d884215',
|
||||||
|
'dev_requirement' => false,
|
||||||
|
),
|
||||||
|
'paragonie/constant_time_encoding' => array(
|
||||||
|
'pretty_version' => 'v2.7.0',
|
||||||
|
'version' => '2.7.0.0',
|
||||||
|
'type' => 'library',
|
||||||
|
'install_path' => __DIR__ . '/../paragonie/constant_time_encoding',
|
||||||
|
'aliases' => array(),
|
||||||
|
'reference' => '52a0d99e69f56b9ec27ace92ba56897fe6993105',
|
||||||
|
'dev_requirement' => false,
|
||||||
|
),
|
||||||
|
'paragonie/random_compat' => array(
|
||||||
|
'pretty_version' => 'v9.99.100',
|
||||||
|
'version' => '9.99.100.0',
|
||||||
|
'type' => 'library',
|
||||||
|
'install_path' => __DIR__ . '/../paragonie/random_compat',
|
||||||
|
'aliases' => array(),
|
||||||
|
'reference' => '996434e5492cb4c3edcb9168db6fbb1359ef965a',
|
||||||
|
'dev_requirement' => false,
|
||||||
|
),
|
||||||
|
'php-di/invoker' => array(
|
||||||
|
'pretty_version' => '2.3.4',
|
||||||
|
'version' => '2.3.4.0',
|
||||||
|
'type' => 'library',
|
||||||
|
'install_path' => __DIR__ . '/../php-di/invoker',
|
||||||
|
'aliases' => array(),
|
||||||
|
'reference' => '33234b32dafa8eb69202f950a1fc92055ed76a86',
|
||||||
|
'dev_requirement' => false,
|
||||||
|
),
|
||||||
|
'php-di/php-di' => array(
|
||||||
|
'pretty_version' => '7.0.6',
|
||||||
|
'version' => '7.0.6.0',
|
||||||
|
'type' => 'library',
|
||||||
|
'install_path' => __DIR__ . '/../php-di/php-di',
|
||||||
|
'aliases' => array(),
|
||||||
|
'reference' => '8097948a89f6ec782839b3e958432f427cac37fd',
|
||||||
|
'dev_requirement' => false,
|
||||||
|
),
|
||||||
|
'phpseclib/phpseclib' => array(
|
||||||
|
'pretty_version' => '3.0.37',
|
||||||
|
'version' => '3.0.37.0',
|
||||||
|
'type' => 'library',
|
||||||
|
'install_path' => __DIR__ . '/../phpseclib/phpseclib',
|
||||||
|
'aliases' => array(),
|
||||||
|
'reference' => 'cfa2013d0f68c062055180dd4328cc8b9d1f30b8',
|
||||||
|
'dev_requirement' => false,
|
||||||
|
),
|
||||||
|
'psr/cache' => array(
|
||||||
|
'pretty_version' => '3.0.0',
|
||||||
|
'version' => '3.0.0.0',
|
||||||
|
'type' => 'library',
|
||||||
|
'install_path' => __DIR__ . '/../psr/cache',
|
||||||
|
'aliases' => array(),
|
||||||
|
'reference' => 'aa5030cfa5405eccfdcb1083ce040c2cb8d253bf',
|
||||||
|
'dev_requirement' => false,
|
||||||
|
),
|
||||||
|
'psr/container' => array(
|
||||||
|
'pretty_version' => '2.0.2',
|
||||||
|
'version' => '2.0.2.0',
|
||||||
|
'type' => 'library',
|
||||||
|
'install_path' => __DIR__ . '/../psr/container',
|
||||||
|
'aliases' => array(),
|
||||||
|
'reference' => 'c71ecc56dfe541dbd90c5360474fbc405f8d5963',
|
||||||
|
'dev_requirement' => false,
|
||||||
|
),
|
||||||
|
'psr/container-implementation' => array(
|
||||||
|
'dev_requirement' => false,
|
||||||
|
'provided' => array(
|
||||||
|
0 => '^1.0',
|
||||||
|
),
|
||||||
|
),
|
||||||
|
'psr/http-client' => array(
|
||||||
|
'pretty_version' => '1.0.3',
|
||||||
|
'version' => '1.0.3.0',
|
||||||
|
'type' => 'library',
|
||||||
|
'install_path' => __DIR__ . '/../psr/http-client',
|
||||||
|
'aliases' => array(),
|
||||||
|
'reference' => 'bb5906edc1c324c9a05aa0873d40117941e5fa90',
|
||||||
|
'dev_requirement' => false,
|
||||||
|
),
|
||||||
|
'psr/http-client-implementation' => array(
|
||||||
|
'dev_requirement' => false,
|
||||||
|
'provided' => array(
|
||||||
|
0 => '1.0',
|
||||||
|
),
|
||||||
|
),
|
||||||
|
'psr/http-factory' => array(
|
||||||
|
'pretty_version' => '1.0.2',
|
||||||
|
'version' => '1.0.2.0',
|
||||||
|
'type' => 'library',
|
||||||
|
'install_path' => __DIR__ . '/../psr/http-factory',
|
||||||
|
'aliases' => array(),
|
||||||
|
'reference' => 'e616d01114759c4c489f93b099585439f795fe35',
|
||||||
|
'dev_requirement' => false,
|
||||||
|
),
|
||||||
|
'psr/http-factory-implementation' => array(
|
||||||
|
'dev_requirement' => false,
|
||||||
|
'provided' => array(
|
||||||
|
0 => '1.0',
|
||||||
|
),
|
||||||
|
),
|
||||||
|
'psr/http-message' => array(
|
||||||
|
'pretty_version' => '2.0',
|
||||||
|
'version' => '2.0.0.0',
|
||||||
|
'type' => 'library',
|
||||||
|
'install_path' => __DIR__ . '/../psr/http-message',
|
||||||
|
'aliases' => array(),
|
||||||
|
'reference' => '402d35bcb92c70c026d1a6a9883f06b2ead23d71',
|
||||||
|
'dev_requirement' => false,
|
||||||
|
),
|
||||||
|
'psr/http-message-implementation' => array(
|
||||||
|
'dev_requirement' => false,
|
||||||
|
'provided' => array(
|
||||||
|
0 => '1.0',
|
||||||
|
),
|
||||||
|
),
|
||||||
|
'psr/log' => array(
|
||||||
|
'pretty_version' => '1.1.4',
|
||||||
|
'version' => '1.1.4.0',
|
||||||
|
'type' => 'library',
|
||||||
|
'install_path' => __DIR__ . '/../psr/log',
|
||||||
|
'aliases' => array(),
|
||||||
|
'reference' => 'd49695b909c3b7628b6289db5479a1c204601f11',
|
||||||
|
'dev_requirement' => false,
|
||||||
|
),
|
||||||
|
'psr/log-implementation' => array(
|
||||||
|
'dev_requirement' => false,
|
||||||
|
'provided' => array(
|
||||||
|
0 => '1.0.0 || 2.0.0 || 3.0.0',
|
||||||
|
),
|
||||||
|
),
|
||||||
|
'ralouphie/getallheaders' => array(
|
||||||
|
'pretty_version' => '3.0.3',
|
||||||
|
'version' => '3.0.3.0',
|
||||||
|
'type' => 'library',
|
||||||
|
'install_path' => __DIR__ . '/../ralouphie/getallheaders',
|
||||||
|
'aliases' => array(),
|
||||||
|
'reference' => '120b605dfeb996808c31b6477290a714d356e822',
|
||||||
|
'dev_requirement' => false,
|
||||||
|
),
|
||||||
|
'stripe/stripe-php' => array(
|
||||||
|
'pretty_version' => 'v13.18.0',
|
||||||
|
'version' => '13.18.0.0',
|
||||||
|
'type' => 'library',
|
||||||
|
'install_path' => __DIR__ . '/../stripe/stripe-php',
|
||||||
|
'aliases' => array(),
|
||||||
|
'reference' => '02abb043b103766f4ed920642ae56ffdc58c7467',
|
||||||
|
'dev_requirement' => false,
|
||||||
|
),
|
||||||
|
'symfony/deprecation-contracts' => array(
|
||||||
|
'pretty_version' => 'v3.4.0',
|
||||||
|
'version' => '3.4.0.0',
|
||||||
|
'type' => 'library',
|
||||||
|
'install_path' => __DIR__ . '/../symfony/deprecation-contracts',
|
||||||
|
'aliases' => array(),
|
||||||
|
'reference' => '7c3aff79d10325257a001fcf92d991f24fc967cf',
|
||||||
|
'dev_requirement' => false,
|
||||||
|
),
|
||||||
|
'symfony/filesystem' => array(
|
||||||
|
'pretty_version' => 'v6.4.6',
|
||||||
|
'version' => '6.4.6.0',
|
||||||
|
'type' => 'library',
|
||||||
|
'install_path' => __DIR__ . '/../symfony/filesystem',
|
||||||
|
'aliases' => array(),
|
||||||
|
'reference' => '9919b5509ada52cc7f66f9a35c86a4a29955c9d3',
|
||||||
|
'dev_requirement' => false,
|
||||||
|
),
|
||||||
|
'symfony/polyfill-ctype' => array(
|
||||||
|
'pretty_version' => 'v1.29.0',
|
||||||
|
'version' => '1.29.0.0',
|
||||||
|
'type' => 'library',
|
||||||
|
'install_path' => __DIR__ . '/../symfony/polyfill-ctype',
|
||||||
|
'aliases' => array(),
|
||||||
|
'reference' => 'ef4d7e442ca910c4764bce785146269b30cb5fc4',
|
||||||
|
'dev_requirement' => false,
|
||||||
|
),
|
||||||
|
'symfony/polyfill-mbstring' => array(
|
||||||
|
'pretty_version' => 'v1.29.0',
|
||||||
|
'version' => '1.29.0.0',
|
||||||
|
'type' => 'library',
|
||||||
|
'install_path' => __DIR__ . '/../symfony/polyfill-mbstring',
|
||||||
|
'aliases' => array(),
|
||||||
|
'reference' => '9773676c8a1bb1f8d4340a62efe641cf76eda7ec',
|
||||||
|
'dev_requirement' => false,
|
||||||
|
),
|
||||||
|
'twilio/sdk' => array(
|
||||||
|
'pretty_version' => '7.16.2',
|
||||||
|
'version' => '7.16.2.0',
|
||||||
|
'type' => 'library',
|
||||||
|
'install_path' => __DIR__ . '/../twilio/sdk',
|
||||||
|
'aliases' => array(),
|
||||||
|
'reference' => '02ad214b0cc9fc513bd67df251d54aed8901284f',
|
||||||
|
'dev_requirement' => false,
|
||||||
|
),
|
||||||
|
'ubnt/ucrm-plugin-sdk' => array(
|
||||||
|
'pretty_version' => 'v0.10.0',
|
||||||
|
'version' => '0.10.0.0',
|
||||||
|
'type' => 'library',
|
||||||
|
'install_path' => __DIR__ . '/../ubnt/ucrm-plugin-sdk',
|
||||||
|
'aliases' => array(),
|
||||||
|
'reference' => '072f01637913b37f598e7c457e431f3370c5dbbf',
|
||||||
|
'dev_requirement' => false,
|
||||||
|
),
|
||||||
|
'ucrm-plugins/sms-twilio' => array(
|
||||||
|
'pretty_version' => '1.0.0+no-version-set',
|
||||||
|
'version' => '1.0.0.0',
|
||||||
|
'type' => 'library',
|
||||||
|
'install_path' => __DIR__ . '/../../',
|
||||||
|
'aliases' => array(),
|
||||||
|
'reference' => NULL,
|
||||||
|
'dev_requirement' => false,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
26
vendor/composer/platform_check.php
vendored
Executable file
26
vendor/composer/platform_check.php
vendored
Executable file
@ -0,0 +1,26 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
// platform_check.php @generated by Composer
|
||||||
|
|
||||||
|
$issues = array();
|
||||||
|
|
||||||
|
if (!(PHP_VERSION_ID >= 80100)) {
|
||||||
|
$issues[] = 'Your Composer dependencies require a PHP version ">= 8.1.0". You are running ' . PHP_VERSION . '.';
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($issues) {
|
||||||
|
if (!headers_sent()) {
|
||||||
|
header('HTTP/1.1 500 Internal Server Error');
|
||||||
|
}
|
||||||
|
if (!ini_get('display_errors')) {
|
||||||
|
if (PHP_SAPI === 'cli' || PHP_SAPI === 'phpdbg') {
|
||||||
|
fwrite(STDERR, 'Composer detected issues in your platform:' . PHP_EOL.PHP_EOL . implode(PHP_EOL, $issues) . PHP_EOL.PHP_EOL);
|
||||||
|
} elseif (!headers_sent()) {
|
||||||
|
echo 'Composer detected issues in your platform:' . PHP_EOL.PHP_EOL . str_replace('You are running '.PHP_VERSION.'.', '', implode(PHP_EOL, $issues)) . PHP_EOL.PHP_EOL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
trigger_error(
|
||||||
|
'Composer detected issues in your platform: ' . implode(' ', $issues),
|
||||||
|
E_USER_ERROR
|
||||||
|
);
|
||||||
|
}
|
||||||
178
vendor/firebase/php-jwt/CHANGELOG.md
vendored
Executable file
178
vendor/firebase/php-jwt/CHANGELOG.md
vendored
Executable file
@ -0,0 +1,178 @@
|
|||||||
|
# Changelog
|
||||||
|
|
||||||
|
## [6.10.1](https://github.com/firebase/php-jwt/compare/v6.10.0...v6.10.1) (2024-05-18)
|
||||||
|
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* ensure ratelimit expiry is set every time ([#556](https://github.com/firebase/php-jwt/issues/556)) ([09cb208](https://github.com/firebase/php-jwt/commit/09cb2081c2c3bc0f61e2f2a5fbea5741f7498648))
|
||||||
|
* ratelimit cache expiration ([#550](https://github.com/firebase/php-jwt/issues/550)) ([dda7250](https://github.com/firebase/php-jwt/commit/dda725033585ece30ff8cae8937320d7e9f18bae))
|
||||||
|
|
||||||
|
## [6.10.0](https://github.com/firebase/php-jwt/compare/v6.9.0...v6.10.0) (2023-11-28)
|
||||||
|
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
* allow typ header override ([#546](https://github.com/firebase/php-jwt/issues/546)) ([79cb30b](https://github.com/firebase/php-jwt/commit/79cb30b729a22931b2fbd6b53f20629a83031ba9))
|
||||||
|
|
||||||
|
## [6.9.0](https://github.com/firebase/php-jwt/compare/v6.8.1...v6.9.0) (2023-10-04)
|
||||||
|
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
* add payload to jwt exception ([#521](https://github.com/firebase/php-jwt/issues/521)) ([175edf9](https://github.com/firebase/php-jwt/commit/175edf958bb61922ec135b2333acf5622f2238a2))
|
||||||
|
|
||||||
|
## [6.8.1](https://github.com/firebase/php-jwt/compare/v6.8.0...v6.8.1) (2023-07-14)
|
||||||
|
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* accept float claims but round down to ignore them ([#492](https://github.com/firebase/php-jwt/issues/492)) ([3936842](https://github.com/firebase/php-jwt/commit/39368423beeaacb3002afa7dcb75baebf204fe7e))
|
||||||
|
* different BeforeValidException messages for nbf and iat ([#526](https://github.com/firebase/php-jwt/issues/526)) ([0a53cf2](https://github.com/firebase/php-jwt/commit/0a53cf2986e45c2bcbf1a269f313ebf56a154ee4))
|
||||||
|
|
||||||
|
## [6.8.0](https://github.com/firebase/php-jwt/compare/v6.7.0...v6.8.0) (2023-06-14)
|
||||||
|
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
* add support for P-384 curve ([#515](https://github.com/firebase/php-jwt/issues/515)) ([5de4323](https://github.com/firebase/php-jwt/commit/5de4323f4baf4d70bca8663bd87682a69c656c3d))
|
||||||
|
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* handle invalid http responses ([#508](https://github.com/firebase/php-jwt/issues/508)) ([91c39c7](https://github.com/firebase/php-jwt/commit/91c39c72b22fc3e1191e574089552c1f2041c718))
|
||||||
|
|
||||||
|
## [6.7.0](https://github.com/firebase/php-jwt/compare/v6.6.0...v6.7.0) (2023-06-14)
|
||||||
|
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
* add ed25519 support to JWK (public keys) ([#452](https://github.com/firebase/php-jwt/issues/452)) ([e53979a](https://github.com/firebase/php-jwt/commit/e53979abae927de916a75b9d239cfda8ce32be2a))
|
||||||
|
|
||||||
|
## [6.6.0](https://github.com/firebase/php-jwt/compare/v6.5.0...v6.6.0) (2023-06-13)
|
||||||
|
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
* allow get headers when decoding token ([#442](https://github.com/firebase/php-jwt/issues/442)) ([fb85f47](https://github.com/firebase/php-jwt/commit/fb85f47cfaeffdd94faf8defdf07164abcdad6c3))
|
||||||
|
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* only check iat if nbf is not used ([#493](https://github.com/firebase/php-jwt/issues/493)) ([398ccd2](https://github.com/firebase/php-jwt/commit/398ccd25ea12fa84b9e4f1085d5ff448c21ec797))
|
||||||
|
|
||||||
|
## [6.5.0](https://github.com/firebase/php-jwt/compare/v6.4.0...v6.5.0) (2023-05-12)
|
||||||
|
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* allow KID of '0' ([#505](https://github.com/firebase/php-jwt/issues/505)) ([9dc46a9](https://github.com/firebase/php-jwt/commit/9dc46a9c3e5801294249cfd2554c5363c9f9326a))
|
||||||
|
|
||||||
|
|
||||||
|
### Miscellaneous Chores
|
||||||
|
|
||||||
|
* drop support for PHP 7.3 ([#495](https://github.com/firebase/php-jwt/issues/495))
|
||||||
|
|
||||||
|
## [6.4.0](https://github.com/firebase/php-jwt/compare/v6.3.2...v6.4.0) (2023-02-08)
|
||||||
|
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
* add support for W3C ES256K ([#462](https://github.com/firebase/php-jwt/issues/462)) ([213924f](https://github.com/firebase/php-jwt/commit/213924f51936291fbbca99158b11bd4ae56c2c95))
|
||||||
|
* improve caching by only decoding jwks when necessary ([#486](https://github.com/firebase/php-jwt/issues/486)) ([78d3ed1](https://github.com/firebase/php-jwt/commit/78d3ed1073553f7d0bbffa6c2010009a0d483d5c))
|
||||||
|
|
||||||
|
## [6.3.2](https://github.com/firebase/php-jwt/compare/v6.3.1...v6.3.2) (2022-11-01)
|
||||||
|
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* check kid before using as array index ([bad1b04](https://github.com/firebase/php-jwt/commit/bad1b040d0c736bbf86814c6b5ae614f517cf7bd))
|
||||||
|
|
||||||
|
## [6.3.1](https://github.com/firebase/php-jwt/compare/v6.3.0...v6.3.1) (2022-11-01)
|
||||||
|
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* casing of GET for PSR compat ([#451](https://github.com/firebase/php-jwt/issues/451)) ([60b52b7](https://github.com/firebase/php-jwt/commit/60b52b71978790eafcf3b95cfbd83db0439e8d22))
|
||||||
|
* string interpolation format for php 8.2 ([#446](https://github.com/firebase/php-jwt/issues/446)) ([2e07d8a](https://github.com/firebase/php-jwt/commit/2e07d8a1524d12b69b110ad649f17461d068b8f2))
|
||||||
|
|
||||||
|
## 6.3.0 / 2022-07-15
|
||||||
|
|
||||||
|
- Added ES256 support to JWK parsing ([#399](https://github.com/firebase/php-jwt/pull/399))
|
||||||
|
- Fixed potential caching error in `CachedKeySet` by caching jwks as strings ([#435](https://github.com/firebase/php-jwt/pull/435))
|
||||||
|
|
||||||
|
## 6.2.0 / 2022-05-14
|
||||||
|
|
||||||
|
- Added `CachedKeySet` ([#397](https://github.com/firebase/php-jwt/pull/397))
|
||||||
|
- Added `$defaultAlg` parameter to `JWT::parseKey` and `JWT::parseKeySet` ([#426](https://github.com/firebase/php-jwt/pull/426)).
|
||||||
|
|
||||||
|
## 6.1.0 / 2022-03-23
|
||||||
|
|
||||||
|
- Drop support for PHP 5.3, 5.4, 5.5, 5.6, and 7.0
|
||||||
|
- Add parameter typing and return types where possible
|
||||||
|
|
||||||
|
## 6.0.0 / 2022-01-24
|
||||||
|
|
||||||
|
- **Backwards-Compatibility Breaking Changes**: See the [Release Notes](https://github.com/firebase/php-jwt/releases/tag/v6.0.0) for more information.
|
||||||
|
- New Key object to prevent key/algorithm type confusion (#365)
|
||||||
|
- Add JWK support (#273)
|
||||||
|
- Add ES256 support (#256)
|
||||||
|
- Add ES384 support (#324)
|
||||||
|
- Add Ed25519 support (#343)
|
||||||
|
|
||||||
|
## 5.0.0 / 2017-06-26
|
||||||
|
- Support RS384 and RS512.
|
||||||
|
See [#117](https://github.com/firebase/php-jwt/pull/117). Thanks [@joostfaassen](https://github.com/joostfaassen)!
|
||||||
|
- Add an example for RS256 openssl.
|
||||||
|
See [#125](https://github.com/firebase/php-jwt/pull/125). Thanks [@akeeman](https://github.com/akeeman)!
|
||||||
|
- Detect invalid Base64 encoding in signature.
|
||||||
|
See [#162](https://github.com/firebase/php-jwt/pull/162). Thanks [@psignoret](https://github.com/psignoret)!
|
||||||
|
- Update `JWT::verify` to handle OpenSSL errors.
|
||||||
|
See [#159](https://github.com/firebase/php-jwt/pull/159). Thanks [@bshaffer](https://github.com/bshaffer)!
|
||||||
|
- Add `array` type hinting to `decode` method
|
||||||
|
See [#101](https://github.com/firebase/php-jwt/pull/101). Thanks [@hywak](https://github.com/hywak)!
|
||||||
|
- Add all JSON error types.
|
||||||
|
See [#110](https://github.com/firebase/php-jwt/pull/110). Thanks [@gbalduzzi](https://github.com/gbalduzzi)!
|
||||||
|
- Bugfix 'kid' not in given key list.
|
||||||
|
See [#129](https://github.com/firebase/php-jwt/pull/129). Thanks [@stampycode](https://github.com/stampycode)!
|
||||||
|
- Miscellaneous cleanup, documentation and test fixes.
|
||||||
|
See [#107](https://github.com/firebase/php-jwt/pull/107), [#115](https://github.com/firebase/php-jwt/pull/115),
|
||||||
|
[#160](https://github.com/firebase/php-jwt/pull/160), [#161](https://github.com/firebase/php-jwt/pull/161), and
|
||||||
|
[#165](https://github.com/firebase/php-jwt/pull/165). Thanks [@akeeman](https://github.com/akeeman),
|
||||||
|
[@chinedufn](https://github.com/chinedufn), and [@bshaffer](https://github.com/bshaffer)!
|
||||||
|
|
||||||
|
## 4.0.0 / 2016-07-17
|
||||||
|
- Add support for late static binding. See [#88](https://github.com/firebase/php-jwt/pull/88) for details. Thanks to [@chappy84](https://github.com/chappy84)!
|
||||||
|
- Use static `$timestamp` instead of `time()` to improve unit testing. See [#93](https://github.com/firebase/php-jwt/pull/93) for details. Thanks to [@josephmcdermott](https://github.com/josephmcdermott)!
|
||||||
|
- Fixes to exceptions classes. See [#81](https://github.com/firebase/php-jwt/pull/81) for details. Thanks to [@Maks3w](https://github.com/Maks3w)!
|
||||||
|
- Fixes to PHPDoc. See [#76](https://github.com/firebase/php-jwt/pull/76) for details. Thanks to [@akeeman](https://github.com/akeeman)!
|
||||||
|
|
||||||
|
## 3.0.0 / 2015-07-22
|
||||||
|
- Minimum PHP version updated from `5.2.0` to `5.3.0`.
|
||||||
|
- Add `\Firebase\JWT` namespace. See
|
||||||
|
[#59](https://github.com/firebase/php-jwt/pull/59) for details. Thanks to
|
||||||
|
[@Dashron](https://github.com/Dashron)!
|
||||||
|
- Require a non-empty key to decode and verify a JWT. See
|
||||||
|
[#60](https://github.com/firebase/php-jwt/pull/60) for details. Thanks to
|
||||||
|
[@sjones608](https://github.com/sjones608)!
|
||||||
|
- Cleaner documentation blocks in the code. See
|
||||||
|
[#62](https://github.com/firebase/php-jwt/pull/62) for details. Thanks to
|
||||||
|
[@johanderuijter](https://github.com/johanderuijter)!
|
||||||
|
|
||||||
|
## 2.2.0 / 2015-06-22
|
||||||
|
- Add support for adding custom, optional JWT headers to `JWT::encode()`. See
|
||||||
|
[#53](https://github.com/firebase/php-jwt/pull/53/files) for details. Thanks to
|
||||||
|
[@mcocaro](https://github.com/mcocaro)!
|
||||||
|
|
||||||
|
## 2.1.0 / 2015-05-20
|
||||||
|
- Add support for adding a leeway to `JWT:decode()` that accounts for clock skew
|
||||||
|
between signing and verifying entities. Thanks to [@lcabral](https://github.com/lcabral)!
|
||||||
|
- Add support for passing an object implementing the `ArrayAccess` interface for
|
||||||
|
`$keys` argument in `JWT::decode()`. Thanks to [@aztech-dev](https://github.com/aztech-dev)!
|
||||||
|
|
||||||
|
## 2.0.0 / 2015-04-01
|
||||||
|
- **Note**: It is strongly recommended that you update to > v2.0.0 to address
|
||||||
|
known security vulnerabilities in prior versions when both symmetric and
|
||||||
|
asymmetric keys are used together.
|
||||||
|
- Update signature for `JWT::decode(...)` to require an array of supported
|
||||||
|
algorithms to use when verifying token signatures.
|
||||||
30
vendor/firebase/php-jwt/LICENSE
vendored
Executable file
30
vendor/firebase/php-jwt/LICENSE
vendored
Executable file
@ -0,0 +1,30 @@
|
|||||||
|
Copyright (c) 2011, Neuman Vong
|
||||||
|
|
||||||
|
All rights reserved.
|
||||||
|
|
||||||
|
Redistribution and use in source and binary forms, with or without
|
||||||
|
modification, are permitted provided that the following conditions are met:
|
||||||
|
|
||||||
|
* Redistributions of source code must retain the above copyright
|
||||||
|
notice, this list of conditions and the following disclaimer.
|
||||||
|
|
||||||
|
* Redistributions in binary form must reproduce the above
|
||||||
|
copyright notice, this list of conditions and the following
|
||||||
|
disclaimer in the documentation and/or other materials provided
|
||||||
|
with the distribution.
|
||||||
|
|
||||||
|
* Neither the name of the copyright holder nor the names of other
|
||||||
|
contributors may be used to endorse or promote products derived
|
||||||
|
from this software without specific prior written permission.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||||
|
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||||
|
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||||
|
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||||
|
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
|
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
424
vendor/firebase/php-jwt/README.md
vendored
Executable file
424
vendor/firebase/php-jwt/README.md
vendored
Executable file
@ -0,0 +1,424 @@
|
|||||||
|

|
||||||
|
[](https://packagist.org/packages/firebase/php-jwt)
|
||||||
|
[](https://packagist.org/packages/firebase/php-jwt)
|
||||||
|
[](https://packagist.org/packages/firebase/php-jwt)
|
||||||
|
|
||||||
|
PHP-JWT
|
||||||
|
=======
|
||||||
|
A simple library to encode and decode JSON Web Tokens (JWT) in PHP, conforming to [RFC 7519](https://tools.ietf.org/html/rfc7519).
|
||||||
|
|
||||||
|
Installation
|
||||||
|
------------
|
||||||
|
|
||||||
|
Use composer to manage your dependencies and download PHP-JWT:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
composer require firebase/php-jwt
|
||||||
|
```
|
||||||
|
|
||||||
|
Optionally, install the `paragonie/sodium_compat` package from composer if your
|
||||||
|
php env does not have libsodium installed:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
composer require paragonie/sodium_compat
|
||||||
|
```
|
||||||
|
|
||||||
|
Example
|
||||||
|
-------
|
||||||
|
```php
|
||||||
|
use Firebase\JWT\JWT;
|
||||||
|
use Firebase\JWT\Key;
|
||||||
|
|
||||||
|
$key = 'example_key';
|
||||||
|
$payload = [
|
||||||
|
'iss' => 'http://example.org',
|
||||||
|
'aud' => 'http://example.com',
|
||||||
|
'iat' => 1356999524,
|
||||||
|
'nbf' => 1357000000
|
||||||
|
];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* IMPORTANT:
|
||||||
|
* You must specify supported algorithms for your application. See
|
||||||
|
* https://tools.ietf.org/html/draft-ietf-jose-json-web-algorithms-40
|
||||||
|
* for a list of spec-compliant algorithms.
|
||||||
|
*/
|
||||||
|
$jwt = JWT::encode($payload, $key, 'HS256');
|
||||||
|
$decoded = JWT::decode($jwt, new Key($key, 'HS256'));
|
||||||
|
print_r($decoded);
|
||||||
|
|
||||||
|
// Pass a stdClass in as the third parameter to get the decoded header values
|
||||||
|
$decoded = JWT::decode($jwt, new Key($key, 'HS256'), $headers = new stdClass());
|
||||||
|
print_r($headers);
|
||||||
|
|
||||||
|
/*
|
||||||
|
NOTE: This will now be an object instead of an associative array. To get
|
||||||
|
an associative array, you will need to cast it as such:
|
||||||
|
*/
|
||||||
|
|
||||||
|
$decoded_array = (array) $decoded;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* You can add a leeway to account for when there is a clock skew times between
|
||||||
|
* the signing and verifying servers. It is recommended that this leeway should
|
||||||
|
* not be bigger than a few minutes.
|
||||||
|
*
|
||||||
|
* Source: http://self-issued.info/docs/draft-ietf-oauth-json-web-token.html#nbfDef
|
||||||
|
*/
|
||||||
|
JWT::$leeway = 60; // $leeway in seconds
|
||||||
|
$decoded = JWT::decode($jwt, new Key($key, 'HS256'));
|
||||||
|
```
|
||||||
|
Example encode/decode headers
|
||||||
|
-------
|
||||||
|
Decoding the JWT headers without verifying the JWT first is NOT recommended, and is not supported by
|
||||||
|
this library. This is because without verifying the JWT, the header values could have been tampered with.
|
||||||
|
Any value pulled from an unverified header should be treated as if it could be any string sent in from an
|
||||||
|
attacker. If this is something you still want to do in your application for whatever reason, it's possible to
|
||||||
|
decode the header values manually simply by calling `json_decode` and `base64_decode` on the JWT
|
||||||
|
header part:
|
||||||
|
```php
|
||||||
|
use Firebase\JWT\JWT;
|
||||||
|
|
||||||
|
$key = 'example_key';
|
||||||
|
$payload = [
|
||||||
|
'iss' => 'http://example.org',
|
||||||
|
'aud' => 'http://example.com',
|
||||||
|
'iat' => 1356999524,
|
||||||
|
'nbf' => 1357000000
|
||||||
|
];
|
||||||
|
|
||||||
|
$headers = [
|
||||||
|
'x-forwarded-for' => 'www.google.com'
|
||||||
|
];
|
||||||
|
|
||||||
|
// Encode headers in the JWT string
|
||||||
|
$jwt = JWT::encode($payload, $key, 'HS256', null, $headers);
|
||||||
|
|
||||||
|
// Decode headers from the JWT string WITHOUT validation
|
||||||
|
// **IMPORTANT**: This operation is vulnerable to attacks, as the JWT has not yet been verified.
|
||||||
|
// These headers could be any value sent by an attacker.
|
||||||
|
list($headersB64, $payloadB64, $sig) = explode('.', $jwt);
|
||||||
|
$decoded = json_decode(base64_decode($headersB64), true);
|
||||||
|
|
||||||
|
print_r($decoded);
|
||||||
|
```
|
||||||
|
Example with RS256 (openssl)
|
||||||
|
----------------------------
|
||||||
|
```php
|
||||||
|
use Firebase\JWT\JWT;
|
||||||
|
use Firebase\JWT\Key;
|
||||||
|
|
||||||
|
$privateKey = <<<EOD
|
||||||
|
-----BEGIN RSA PRIVATE KEY-----
|
||||||
|
MIIEowIBAAKCAQEAuzWHNM5f+amCjQztc5QTfJfzCC5J4nuW+L/aOxZ4f8J3Frew
|
||||||
|
M2c/dufrnmedsApb0By7WhaHlcqCh/ScAPyJhzkPYLae7bTVro3hok0zDITR8F6S
|
||||||
|
JGL42JAEUk+ILkPI+DONM0+3vzk6Kvfe548tu4czCuqU8BGVOlnp6IqBHhAswNMM
|
||||||
|
78pos/2z0CjPM4tbeXqSTTbNkXRboxjU29vSopcT51koWOgiTf3C7nJUoMWZHZI5
|
||||||
|
HqnIhPAG9yv8HAgNk6CMk2CadVHDo4IxjxTzTTqo1SCSH2pooJl9O8at6kkRYsrZ
|
||||||
|
WwsKlOFE2LUce7ObnXsYihStBUDoeBQlGG/BwQIDAQABAoIBAFtGaOqNKGwggn9k
|
||||||
|
6yzr6GhZ6Wt2rh1Xpq8XUz514UBhPxD7dFRLpbzCrLVpzY80LbmVGJ9+1pJozyWc
|
||||||
|
VKeCeUdNwbqkr240Oe7GTFmGjDoxU+5/HX/SJYPpC8JZ9oqgEA87iz+WQX9hVoP2
|
||||||
|
oF6EB4ckDvXmk8FMwVZW2l2/kd5mrEVbDaXKxhvUDf52iVD+sGIlTif7mBgR99/b
|
||||||
|
c3qiCnxCMmfYUnT2eh7Vv2LhCR/G9S6C3R4lA71rEyiU3KgsGfg0d82/XWXbegJW
|
||||||
|
h3QbWNtQLxTuIvLq5aAryV3PfaHlPgdgK0ft6ocU2de2FagFka3nfVEyC7IUsNTK
|
||||||
|
bq6nhAECgYEA7d/0DPOIaItl/8BWKyCuAHMss47j0wlGbBSHdJIiS55akMvnAG0M
|
||||||
|
39y22Qqfzh1at9kBFeYeFIIU82ZLF3xOcE3z6pJZ4Dyvx4BYdXH77odo9uVK9s1l
|
||||||
|
3T3BlMcqd1hvZLMS7dviyH79jZo4CXSHiKzc7pQ2YfK5eKxKqONeXuECgYEAyXlG
|
||||||
|
vonaus/YTb1IBei9HwaccnQ/1HRn6MvfDjb7JJDIBhNClGPt6xRlzBbSZ73c2QEC
|
||||||
|
6Fu9h36K/HZ2qcLd2bXiNyhIV7b6tVKk+0Psoj0dL9EbhsD1OsmE1nTPyAc9XZbb
|
||||||
|
OPYxy+dpBCUA8/1U9+uiFoCa7mIbWcSQ+39gHuECgYAz82pQfct30aH4JiBrkNqP
|
||||||
|
nJfRq05UY70uk5k1u0ikLTRoVS/hJu/d4E1Kv4hBMqYCavFSwAwnvHUo51lVCr/y
|
||||||
|
xQOVYlsgnwBg2MX4+GjmIkqpSVCC8D7j/73MaWb746OIYZervQ8dbKahi2HbpsiG
|
||||||
|
8AHcVSA/agxZr38qvWV54QKBgCD5TlDE8x18AuTGQ9FjxAAd7uD0kbXNz2vUYg9L
|
||||||
|
hFL5tyL3aAAtUrUUw4xhd9IuysRhW/53dU+FsG2dXdJu6CxHjlyEpUJl2iZu/j15
|
||||||
|
YnMzGWHIEX8+eWRDsw/+Ujtko/B7TinGcWPz3cYl4EAOiCeDUyXnqnO1btCEUU44
|
||||||
|
DJ1BAoGBAJuPD27ErTSVtId90+M4zFPNibFP50KprVdc8CR37BE7r8vuGgNYXmnI
|
||||||
|
RLnGP9p3pVgFCktORuYS2J/6t84I3+A17nEoB4xvhTLeAinAW/uTQOUmNicOP4Ek
|
||||||
|
2MsLL2kHgL8bLTmvXV4FX+PXphrDKg1XxzOYn0otuoqdAQrkK4og
|
||||||
|
-----END RSA PRIVATE KEY-----
|
||||||
|
EOD;
|
||||||
|
|
||||||
|
$publicKey = <<<EOD
|
||||||
|
-----BEGIN PUBLIC KEY-----
|
||||||
|
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAuzWHNM5f+amCjQztc5QT
|
||||||
|
fJfzCC5J4nuW+L/aOxZ4f8J3FrewM2c/dufrnmedsApb0By7WhaHlcqCh/ScAPyJ
|
||||||
|
hzkPYLae7bTVro3hok0zDITR8F6SJGL42JAEUk+ILkPI+DONM0+3vzk6Kvfe548t
|
||||||
|
u4czCuqU8BGVOlnp6IqBHhAswNMM78pos/2z0CjPM4tbeXqSTTbNkXRboxjU29vS
|
||||||
|
opcT51koWOgiTf3C7nJUoMWZHZI5HqnIhPAG9yv8HAgNk6CMk2CadVHDo4IxjxTz
|
||||||
|
TTqo1SCSH2pooJl9O8at6kkRYsrZWwsKlOFE2LUce7ObnXsYihStBUDoeBQlGG/B
|
||||||
|
wQIDAQAB
|
||||||
|
-----END PUBLIC KEY-----
|
||||||
|
EOD;
|
||||||
|
|
||||||
|
$payload = [
|
||||||
|
'iss' => 'example.org',
|
||||||
|
'aud' => 'example.com',
|
||||||
|
'iat' => 1356999524,
|
||||||
|
'nbf' => 1357000000
|
||||||
|
];
|
||||||
|
|
||||||
|
$jwt = JWT::encode($payload, $privateKey, 'RS256');
|
||||||
|
echo "Encode:\n" . print_r($jwt, true) . "\n";
|
||||||
|
|
||||||
|
$decoded = JWT::decode($jwt, new Key($publicKey, 'RS256'));
|
||||||
|
|
||||||
|
/*
|
||||||
|
NOTE: This will now be an object instead of an associative array. To get
|
||||||
|
an associative array, you will need to cast it as such:
|
||||||
|
*/
|
||||||
|
|
||||||
|
$decoded_array = (array) $decoded;
|
||||||
|
echo "Decode:\n" . print_r($decoded_array, true) . "\n";
|
||||||
|
```
|
||||||
|
|
||||||
|
Example with a passphrase
|
||||||
|
-------------------------
|
||||||
|
|
||||||
|
```php
|
||||||
|
use Firebase\JWT\JWT;
|
||||||
|
use Firebase\JWT\Key;
|
||||||
|
|
||||||
|
// Your passphrase
|
||||||
|
$passphrase = '[YOUR_PASSPHRASE]';
|
||||||
|
|
||||||
|
// Your private key file with passphrase
|
||||||
|
// Can be generated with "ssh-keygen -t rsa -m pem"
|
||||||
|
$privateKeyFile = '/path/to/key-with-passphrase.pem';
|
||||||
|
|
||||||
|
// Create a private key of type "resource"
|
||||||
|
$privateKey = openssl_pkey_get_private(
|
||||||
|
file_get_contents($privateKeyFile),
|
||||||
|
$passphrase
|
||||||
|
);
|
||||||
|
|
||||||
|
$payload = [
|
||||||
|
'iss' => 'example.org',
|
||||||
|
'aud' => 'example.com',
|
||||||
|
'iat' => 1356999524,
|
||||||
|
'nbf' => 1357000000
|
||||||
|
];
|
||||||
|
|
||||||
|
$jwt = JWT::encode($payload, $privateKey, 'RS256');
|
||||||
|
echo "Encode:\n" . print_r($jwt, true) . "\n";
|
||||||
|
|
||||||
|
// Get public key from the private key, or pull from from a file.
|
||||||
|
$publicKey = openssl_pkey_get_details($privateKey)['key'];
|
||||||
|
|
||||||
|
$decoded = JWT::decode($jwt, new Key($publicKey, 'RS256'));
|
||||||
|
echo "Decode:\n" . print_r((array) $decoded, true) . "\n";
|
||||||
|
```
|
||||||
|
|
||||||
|
Example with EdDSA (libsodium and Ed25519 signature)
|
||||||
|
----------------------------
|
||||||
|
```php
|
||||||
|
use Firebase\JWT\JWT;
|
||||||
|
use Firebase\JWT\Key;
|
||||||
|
|
||||||
|
// Public and private keys are expected to be Base64 encoded. The last
|
||||||
|
// non-empty line is used so that keys can be generated with
|
||||||
|
// sodium_crypto_sign_keypair(). The secret keys generated by other tools may
|
||||||
|
// need to be adjusted to match the input expected by libsodium.
|
||||||
|
|
||||||
|
$keyPair = sodium_crypto_sign_keypair();
|
||||||
|
|
||||||
|
$privateKey = base64_encode(sodium_crypto_sign_secretkey($keyPair));
|
||||||
|
|
||||||
|
$publicKey = base64_encode(sodium_crypto_sign_publickey($keyPair));
|
||||||
|
|
||||||
|
$payload = [
|
||||||
|
'iss' => 'example.org',
|
||||||
|
'aud' => 'example.com',
|
||||||
|
'iat' => 1356999524,
|
||||||
|
'nbf' => 1357000000
|
||||||
|
];
|
||||||
|
|
||||||
|
$jwt = JWT::encode($payload, $privateKey, 'EdDSA');
|
||||||
|
echo "Encode:\n" . print_r($jwt, true) . "\n";
|
||||||
|
|
||||||
|
$decoded = JWT::decode($jwt, new Key($publicKey, 'EdDSA'));
|
||||||
|
echo "Decode:\n" . print_r((array) $decoded, true) . "\n";
|
||||||
|
````
|
||||||
|
|
||||||
|
Example with multiple keys
|
||||||
|
--------------------------
|
||||||
|
```php
|
||||||
|
use Firebase\JWT\JWT;
|
||||||
|
use Firebase\JWT\Key;
|
||||||
|
|
||||||
|
// Example RSA keys from previous example
|
||||||
|
// $privateKey1 = '...';
|
||||||
|
// $publicKey1 = '...';
|
||||||
|
|
||||||
|
// Example EdDSA keys from previous example
|
||||||
|
// $privateKey2 = '...';
|
||||||
|
// $publicKey2 = '...';
|
||||||
|
|
||||||
|
$payload = [
|
||||||
|
'iss' => 'example.org',
|
||||||
|
'aud' => 'example.com',
|
||||||
|
'iat' => 1356999524,
|
||||||
|
'nbf' => 1357000000
|
||||||
|
];
|
||||||
|
|
||||||
|
$jwt1 = JWT::encode($payload, $privateKey1, 'RS256', 'kid1');
|
||||||
|
$jwt2 = JWT::encode($payload, $privateKey2, 'EdDSA', 'kid2');
|
||||||
|
echo "Encode 1:\n" . print_r($jwt1, true) . "\n";
|
||||||
|
echo "Encode 2:\n" . print_r($jwt2, true) . "\n";
|
||||||
|
|
||||||
|
$keys = [
|
||||||
|
'kid1' => new Key($publicKey1, 'RS256'),
|
||||||
|
'kid2' => new Key($publicKey2, 'EdDSA'),
|
||||||
|
];
|
||||||
|
|
||||||
|
$decoded1 = JWT::decode($jwt1, $keys);
|
||||||
|
$decoded2 = JWT::decode($jwt2, $keys);
|
||||||
|
|
||||||
|
echo "Decode 1:\n" . print_r((array) $decoded1, true) . "\n";
|
||||||
|
echo "Decode 2:\n" . print_r((array) $decoded2, true) . "\n";
|
||||||
|
```
|
||||||
|
|
||||||
|
Using JWKs
|
||||||
|
----------
|
||||||
|
|
||||||
|
```php
|
||||||
|
use Firebase\JWT\JWK;
|
||||||
|
use Firebase\JWT\JWT;
|
||||||
|
|
||||||
|
// Set of keys. The "keys" key is required. For example, the JSON response to
|
||||||
|
// this endpoint: https://www.gstatic.com/iap/verify/public_key-jwk
|
||||||
|
$jwks = ['keys' => []];
|
||||||
|
|
||||||
|
// JWK::parseKeySet($jwks) returns an associative array of **kid** to Firebase\JWT\Key
|
||||||
|
// objects. Pass this as the second parameter to JWT::decode.
|
||||||
|
JWT::decode($payload, JWK::parseKeySet($jwks));
|
||||||
|
```
|
||||||
|
|
||||||
|
Using Cached Key Sets
|
||||||
|
---------------------
|
||||||
|
|
||||||
|
The `CachedKeySet` class can be used to fetch and cache JWKS (JSON Web Key Sets) from a public URI.
|
||||||
|
This has the following advantages:
|
||||||
|
|
||||||
|
1. The results are cached for performance.
|
||||||
|
2. If an unrecognized key is requested, the cache is refreshed, to accomodate for key rotation.
|
||||||
|
3. If rate limiting is enabled, the JWKS URI will not make more than 10 requests a second.
|
||||||
|
|
||||||
|
```php
|
||||||
|
use Firebase\JWT\CachedKeySet;
|
||||||
|
use Firebase\JWT\JWT;
|
||||||
|
|
||||||
|
// The URI for the JWKS you wish to cache the results from
|
||||||
|
$jwksUri = 'https://www.gstatic.com/iap/verify/public_key-jwk';
|
||||||
|
|
||||||
|
// Create an HTTP client (can be any PSR-7 compatible HTTP client)
|
||||||
|
$httpClient = new GuzzleHttp\Client();
|
||||||
|
|
||||||
|
// Create an HTTP request factory (can be any PSR-17 compatible HTTP request factory)
|
||||||
|
$httpFactory = new GuzzleHttp\Psr\HttpFactory();
|
||||||
|
|
||||||
|
// Create a cache item pool (can be any PSR-6 compatible cache item pool)
|
||||||
|
$cacheItemPool = Phpfastcache\CacheManager::getInstance('files');
|
||||||
|
|
||||||
|
$keySet = new CachedKeySet(
|
||||||
|
$jwksUri,
|
||||||
|
$httpClient,
|
||||||
|
$httpFactory,
|
||||||
|
$cacheItemPool,
|
||||||
|
null, // $expiresAfter int seconds to set the JWKS to expire
|
||||||
|
true // $rateLimit true to enable rate limit of 10 RPS on lookup of invalid keys
|
||||||
|
);
|
||||||
|
|
||||||
|
$jwt = 'eyJhbGci...'; // Some JWT signed by a key from the $jwkUri above
|
||||||
|
$decoded = JWT::decode($jwt, $keySet);
|
||||||
|
```
|
||||||
|
|
||||||
|
Miscellaneous
|
||||||
|
-------------
|
||||||
|
|
||||||
|
#### Exception Handling
|
||||||
|
|
||||||
|
When a call to `JWT::decode` is invalid, it will throw one of the following exceptions:
|
||||||
|
|
||||||
|
```php
|
||||||
|
use Firebase\JWT\JWT;
|
||||||
|
use Firebase\JWT\SignatureInvalidException;
|
||||||
|
use Firebase\JWT\BeforeValidException;
|
||||||
|
use Firebase\JWT\ExpiredException;
|
||||||
|
use DomainException;
|
||||||
|
use InvalidArgumentException;
|
||||||
|
use UnexpectedValueException;
|
||||||
|
|
||||||
|
try {
|
||||||
|
$decoded = JWT::decode($payload, $keys);
|
||||||
|
} catch (InvalidArgumentException $e) {
|
||||||
|
// provided key/key-array is empty or malformed.
|
||||||
|
} catch (DomainException $e) {
|
||||||
|
// provided algorithm is unsupported OR
|
||||||
|
// provided key is invalid OR
|
||||||
|
// unknown error thrown in openSSL or libsodium OR
|
||||||
|
// libsodium is required but not available.
|
||||||
|
} catch (SignatureInvalidException $e) {
|
||||||
|
// provided JWT signature verification failed.
|
||||||
|
} catch (BeforeValidException $e) {
|
||||||
|
// provided JWT is trying to be used before "nbf" claim OR
|
||||||
|
// provided JWT is trying to be used before "iat" claim.
|
||||||
|
} catch (ExpiredException $e) {
|
||||||
|
// provided JWT is trying to be used after "exp" claim.
|
||||||
|
} catch (UnexpectedValueException $e) {
|
||||||
|
// provided JWT is malformed OR
|
||||||
|
// provided JWT is missing an algorithm / using an unsupported algorithm OR
|
||||||
|
// provided JWT algorithm does not match provided key OR
|
||||||
|
// provided key ID in key/key-array is empty or invalid.
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
All exceptions in the `Firebase\JWT` namespace extend `UnexpectedValueException`, and can be simplified
|
||||||
|
like this:
|
||||||
|
|
||||||
|
```php
|
||||||
|
use Firebase\JWT\JWT;
|
||||||
|
use UnexpectedValueException;
|
||||||
|
try {
|
||||||
|
$decoded = JWT::decode($payload, $keys);
|
||||||
|
} catch (LogicException $e) {
|
||||||
|
// errors having to do with environmental setup or malformed JWT Keys
|
||||||
|
} catch (UnexpectedValueException $e) {
|
||||||
|
// errors having to do with JWT signature and claims
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Casting to array
|
||||||
|
|
||||||
|
The return value of `JWT::decode` is the generic PHP object `stdClass`. If you'd like to handle with arrays
|
||||||
|
instead, you can do the following:
|
||||||
|
|
||||||
|
```php
|
||||||
|
// return type is stdClass
|
||||||
|
$decoded = JWT::decode($payload, $keys);
|
||||||
|
|
||||||
|
// cast to array
|
||||||
|
$decoded = json_decode(json_encode($decoded), true);
|
||||||
|
```
|
||||||
|
|
||||||
|
Tests
|
||||||
|
-----
|
||||||
|
Run the tests using phpunit:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
$ pear install PHPUnit
|
||||||
|
$ phpunit --configuration phpunit.xml.dist
|
||||||
|
PHPUnit 3.7.10 by Sebastian Bergmann.
|
||||||
|
.....
|
||||||
|
Time: 0 seconds, Memory: 2.50Mb
|
||||||
|
OK (5 tests, 5 assertions)
|
||||||
|
```
|
||||||
|
|
||||||
|
New Lines in private keys
|
||||||
|
-----
|
||||||
|
|
||||||
|
If your private key contains `\n` characters, be sure to wrap it in double quotes `""`
|
||||||
|
and not single quotes `''` in order to properly interpret the escaped characters.
|
||||||
|
|
||||||
|
License
|
||||||
|
-------
|
||||||
|
[3-Clause BSD](http://opensource.org/licenses/BSD-3-Clause).
|
||||||
42
vendor/firebase/php-jwt/composer.json
vendored
Executable file
42
vendor/firebase/php-jwt/composer.json
vendored
Executable file
@ -0,0 +1,42 @@
|
|||||||
|
{
|
||||||
|
"name": "firebase/php-jwt",
|
||||||
|
"description": "A simple library to encode and decode JSON Web Tokens (JWT) in PHP. Should conform to the current spec.",
|
||||||
|
"homepage": "https://github.com/firebase/php-jwt",
|
||||||
|
"keywords": [
|
||||||
|
"php",
|
||||||
|
"jwt"
|
||||||
|
],
|
||||||
|
"authors": [
|
||||||
|
{
|
||||||
|
"name": "Neuman Vong",
|
||||||
|
"email": "neuman+pear@twilio.com",
|
||||||
|
"role": "Developer"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Anant Narayanan",
|
||||||
|
"email": "anant@php.net",
|
||||||
|
"role": "Developer"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"license": "BSD-3-Clause",
|
||||||
|
"require": {
|
||||||
|
"php": "^8.0"
|
||||||
|
},
|
||||||
|
"suggest": {
|
||||||
|
"paragonie/sodium_compat": "Support EdDSA (Ed25519) signatures when libsodium is not present",
|
||||||
|
"ext-sodium": "Support EdDSA (Ed25519) signatures"
|
||||||
|
},
|
||||||
|
"autoload": {
|
||||||
|
"psr-4": {
|
||||||
|
"Firebase\\JWT\\": "src"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"require-dev": {
|
||||||
|
"guzzlehttp/guzzle": "^7.4",
|
||||||
|
"phpspec/prophecy-phpunit": "^2.0",
|
||||||
|
"phpunit/phpunit": "^9.5",
|
||||||
|
"psr/cache": "^2.0||^3.0",
|
||||||
|
"psr/http-client": "^1.0",
|
||||||
|
"psr/http-factory": "^1.0"
|
||||||
|
}
|
||||||
|
}
|
||||||
18
vendor/firebase/php-jwt/src/BeforeValidException.php
vendored
Executable file
18
vendor/firebase/php-jwt/src/BeforeValidException.php
vendored
Executable file
@ -0,0 +1,18 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Firebase\JWT;
|
||||||
|
|
||||||
|
class BeforeValidException extends \UnexpectedValueException implements JWTExceptionWithPayloadInterface
|
||||||
|
{
|
||||||
|
private object $payload;
|
||||||
|
|
||||||
|
public function setPayload(object $payload): void
|
||||||
|
{
|
||||||
|
$this->payload = $payload;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getPayload(): object
|
||||||
|
{
|
||||||
|
return $this->payload;
|
||||||
|
}
|
||||||
|
}
|
||||||
274
vendor/firebase/php-jwt/src/CachedKeySet.php
vendored
Executable file
274
vendor/firebase/php-jwt/src/CachedKeySet.php
vendored
Executable file
@ -0,0 +1,274 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Firebase\JWT;
|
||||||
|
|
||||||
|
use ArrayAccess;
|
||||||
|
use InvalidArgumentException;
|
||||||
|
use LogicException;
|
||||||
|
use OutOfBoundsException;
|
||||||
|
use Psr\Cache\CacheItemInterface;
|
||||||
|
use Psr\Cache\CacheItemPoolInterface;
|
||||||
|
use Psr\Http\Client\ClientInterface;
|
||||||
|
use Psr\Http\Message\RequestFactoryInterface;
|
||||||
|
use RuntimeException;
|
||||||
|
use UnexpectedValueException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @implements ArrayAccess<string, Key>
|
||||||
|
*/
|
||||||
|
class CachedKeySet implements ArrayAccess
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
private $jwksUri;
|
||||||
|
/**
|
||||||
|
* @var ClientInterface
|
||||||
|
*/
|
||||||
|
private $httpClient;
|
||||||
|
/**
|
||||||
|
* @var RequestFactoryInterface
|
||||||
|
*/
|
||||||
|
private $httpFactory;
|
||||||
|
/**
|
||||||
|
* @var CacheItemPoolInterface
|
||||||
|
*/
|
||||||
|
private $cache;
|
||||||
|
/**
|
||||||
|
* @var ?int
|
||||||
|
*/
|
||||||
|
private $expiresAfter;
|
||||||
|
/**
|
||||||
|
* @var ?CacheItemInterface
|
||||||
|
*/
|
||||||
|
private $cacheItem;
|
||||||
|
/**
|
||||||
|
* @var array<string, array<mixed>>
|
||||||
|
*/
|
||||||
|
private $keySet;
|
||||||
|
/**
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
private $cacheKey;
|
||||||
|
/**
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
private $cacheKeyPrefix = 'jwks';
|
||||||
|
/**
|
||||||
|
* @var int
|
||||||
|
*/
|
||||||
|
private $maxKeyLength = 64;
|
||||||
|
/**
|
||||||
|
* @var bool
|
||||||
|
*/
|
||||||
|
private $rateLimit;
|
||||||
|
/**
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
private $rateLimitCacheKey;
|
||||||
|
/**
|
||||||
|
* @var int
|
||||||
|
*/
|
||||||
|
private $maxCallsPerMinute = 10;
|
||||||
|
/**
|
||||||
|
* @var string|null
|
||||||
|
*/
|
||||||
|
private $defaultAlg;
|
||||||
|
|
||||||
|
public function __construct(
|
||||||
|
string $jwksUri,
|
||||||
|
ClientInterface $httpClient,
|
||||||
|
RequestFactoryInterface $httpFactory,
|
||||||
|
CacheItemPoolInterface $cache,
|
||||||
|
int $expiresAfter = null,
|
||||||
|
bool $rateLimit = false,
|
||||||
|
string $defaultAlg = null
|
||||||
|
) {
|
||||||
|
$this->jwksUri = $jwksUri;
|
||||||
|
$this->httpClient = $httpClient;
|
||||||
|
$this->httpFactory = $httpFactory;
|
||||||
|
$this->cache = $cache;
|
||||||
|
$this->expiresAfter = $expiresAfter;
|
||||||
|
$this->rateLimit = $rateLimit;
|
||||||
|
$this->defaultAlg = $defaultAlg;
|
||||||
|
$this->setCacheKeys();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $keyId
|
||||||
|
* @return Key
|
||||||
|
*/
|
||||||
|
public function offsetGet($keyId): Key
|
||||||
|
{
|
||||||
|
if (!$this->keyIdExists($keyId)) {
|
||||||
|
throw new OutOfBoundsException('Key ID not found');
|
||||||
|
}
|
||||||
|
return JWK::parseKey($this->keySet[$keyId], $this->defaultAlg);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $keyId
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
public function offsetExists($keyId): bool
|
||||||
|
{
|
||||||
|
return $this->keyIdExists($keyId);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $offset
|
||||||
|
* @param Key $value
|
||||||
|
*/
|
||||||
|
public function offsetSet($offset, $value): void
|
||||||
|
{
|
||||||
|
throw new LogicException('Method not implemented');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $offset
|
||||||
|
*/
|
||||||
|
public function offsetUnset($offset): void
|
||||||
|
{
|
||||||
|
throw new LogicException('Method not implemented');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return array<mixed>
|
||||||
|
*/
|
||||||
|
private function formatJwksForCache(string $jwks): array
|
||||||
|
{
|
||||||
|
$jwks = json_decode($jwks, true);
|
||||||
|
|
||||||
|
if (!isset($jwks['keys'])) {
|
||||||
|
throw new UnexpectedValueException('"keys" member must exist in the JWK Set');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (empty($jwks['keys'])) {
|
||||||
|
throw new InvalidArgumentException('JWK Set did not contain any keys');
|
||||||
|
}
|
||||||
|
|
||||||
|
$keys = [];
|
||||||
|
foreach ($jwks['keys'] as $k => $v) {
|
||||||
|
$kid = isset($v['kid']) ? $v['kid'] : $k;
|
||||||
|
$keys[(string) $kid] = $v;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $keys;
|
||||||
|
}
|
||||||
|
|
||||||
|
private function keyIdExists(string $keyId): bool
|
||||||
|
{
|
||||||
|
if (null === $this->keySet) {
|
||||||
|
$item = $this->getCacheItem();
|
||||||
|
// Try to load keys from cache
|
||||||
|
if ($item->isHit()) {
|
||||||
|
// item found! retrieve it
|
||||||
|
$this->keySet = $item->get();
|
||||||
|
// If the cached item is a string, the JWKS response was cached (previous behavior).
|
||||||
|
// Parse this into expected format array<kid, jwk> instead.
|
||||||
|
if (\is_string($this->keySet)) {
|
||||||
|
$this->keySet = $this->formatJwksForCache($this->keySet);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!isset($this->keySet[$keyId])) {
|
||||||
|
if ($this->rateLimitExceeded()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
$request = $this->httpFactory->createRequest('GET', $this->jwksUri);
|
||||||
|
$jwksResponse = $this->httpClient->sendRequest($request);
|
||||||
|
if ($jwksResponse->getStatusCode() !== 200) {
|
||||||
|
throw new UnexpectedValueException(
|
||||||
|
sprintf('HTTP Error: %d %s for URI "%s"',
|
||||||
|
$jwksResponse->getStatusCode(),
|
||||||
|
$jwksResponse->getReasonPhrase(),
|
||||||
|
$this->jwksUri,
|
||||||
|
),
|
||||||
|
$jwksResponse->getStatusCode()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
$this->keySet = $this->formatJwksForCache((string) $jwksResponse->getBody());
|
||||||
|
|
||||||
|
if (!isset($this->keySet[$keyId])) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
$item = $this->getCacheItem();
|
||||||
|
$item->set($this->keySet);
|
||||||
|
if ($this->expiresAfter) {
|
||||||
|
$item->expiresAfter($this->expiresAfter);
|
||||||
|
}
|
||||||
|
$this->cache->save($item);
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private function rateLimitExceeded(): bool
|
||||||
|
{
|
||||||
|
if (!$this->rateLimit) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
$cacheItem = $this->cache->getItem($this->rateLimitCacheKey);
|
||||||
|
|
||||||
|
$cacheItemData = [];
|
||||||
|
if ($cacheItem->isHit() && \is_array($data = $cacheItem->get())) {
|
||||||
|
$cacheItemData = $data;
|
||||||
|
}
|
||||||
|
|
||||||
|
$callsPerMinute = $cacheItemData['callsPerMinute'] ?? 0;
|
||||||
|
$expiry = $cacheItemData['expiry'] ?? new \DateTime('+60 seconds', new \DateTimeZone('UTC'));
|
||||||
|
|
||||||
|
if (++$callsPerMinute > $this->maxCallsPerMinute) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
$cacheItem->set(['expiry' => $expiry, 'callsPerMinute' => $callsPerMinute]);
|
||||||
|
$cacheItem->expiresAt($expiry);
|
||||||
|
$this->cache->save($cacheItem);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
private function getCacheItem(): CacheItemInterface
|
||||||
|
{
|
||||||
|
if (\is_null($this->cacheItem)) {
|
||||||
|
$this->cacheItem = $this->cache->getItem($this->cacheKey);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this->cacheItem;
|
||||||
|
}
|
||||||
|
|
||||||
|
private function setCacheKeys(): void
|
||||||
|
{
|
||||||
|
if (empty($this->jwksUri)) {
|
||||||
|
throw new RuntimeException('JWKS URI is empty');
|
||||||
|
}
|
||||||
|
|
||||||
|
// ensure we do not have illegal characters
|
||||||
|
$key = preg_replace('|[^a-zA-Z0-9_\.!]|', '', $this->jwksUri);
|
||||||
|
|
||||||
|
// add prefix
|
||||||
|
$key = $this->cacheKeyPrefix . $key;
|
||||||
|
|
||||||
|
// Hash keys if they exceed $maxKeyLength of 64
|
||||||
|
if (\strlen($key) > $this->maxKeyLength) {
|
||||||
|
$key = substr(hash('sha256', $key), 0, $this->maxKeyLength);
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->cacheKey = $key;
|
||||||
|
|
||||||
|
if ($this->rateLimit) {
|
||||||
|
// add prefix
|
||||||
|
$rateLimitKey = $this->cacheKeyPrefix . 'ratelimit' . $key;
|
||||||
|
|
||||||
|
// Hash keys if they exceed $maxKeyLength of 64
|
||||||
|
if (\strlen($rateLimitKey) > $this->maxKeyLength) {
|
||||||
|
$rateLimitKey = substr(hash('sha256', $rateLimitKey), 0, $this->maxKeyLength);
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->rateLimitCacheKey = $rateLimitKey;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
18
vendor/firebase/php-jwt/src/ExpiredException.php
vendored
Executable file
18
vendor/firebase/php-jwt/src/ExpiredException.php
vendored
Executable file
@ -0,0 +1,18 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Firebase\JWT;
|
||||||
|
|
||||||
|
class ExpiredException extends \UnexpectedValueException implements JWTExceptionWithPayloadInterface
|
||||||
|
{
|
||||||
|
private object $payload;
|
||||||
|
|
||||||
|
public function setPayload(object $payload): void
|
||||||
|
{
|
||||||
|
$this->payload = $payload;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getPayload(): object
|
||||||
|
{
|
||||||
|
return $this->payload;
|
||||||
|
}
|
||||||
|
}
|
||||||
349
vendor/firebase/php-jwt/src/JWK.php
vendored
Executable file
349
vendor/firebase/php-jwt/src/JWK.php
vendored
Executable file
@ -0,0 +1,349 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Firebase\JWT;
|
||||||
|
|
||||||
|
use DomainException;
|
||||||
|
use InvalidArgumentException;
|
||||||
|
use UnexpectedValueException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* JSON Web Key implementation, based on this spec:
|
||||||
|
* https://tools.ietf.org/html/draft-ietf-jose-json-web-key-41
|
||||||
|
*
|
||||||
|
* PHP version 5
|
||||||
|
*
|
||||||
|
* @category Authentication
|
||||||
|
* @package Authentication_JWT
|
||||||
|
* @author Bui Sy Nguyen <nguyenbs@gmail.com>
|
||||||
|
* @license http://opensource.org/licenses/BSD-3-Clause 3-clause BSD
|
||||||
|
* @link https://github.com/firebase/php-jwt
|
||||||
|
*/
|
||||||
|
class JWK
|
||||||
|
{
|
||||||
|
private const OID = '1.2.840.10045.2.1';
|
||||||
|
private const ASN1_OBJECT_IDENTIFIER = 0x06;
|
||||||
|
private const ASN1_SEQUENCE = 0x10; // also defined in JWT
|
||||||
|
private const ASN1_BIT_STRING = 0x03;
|
||||||
|
private const EC_CURVES = [
|
||||||
|
'P-256' => '1.2.840.10045.3.1.7', // Len: 64
|
||||||
|
'secp256k1' => '1.3.132.0.10', // Len: 64
|
||||||
|
'P-384' => '1.3.132.0.34', // Len: 96
|
||||||
|
// 'P-521' => '1.3.132.0.35', // Len: 132 (not supported)
|
||||||
|
];
|
||||||
|
|
||||||
|
// For keys with "kty" equal to "OKP" (Octet Key Pair), the "crv" parameter must contain the key subtype.
|
||||||
|
// This library supports the following subtypes:
|
||||||
|
private const OKP_SUBTYPES = [
|
||||||
|
'Ed25519' => true, // RFC 8037
|
||||||
|
];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parse a set of JWK keys
|
||||||
|
*
|
||||||
|
* @param array<mixed> $jwks The JSON Web Key Set as an associative array
|
||||||
|
* @param string $defaultAlg The algorithm for the Key object if "alg" is not set in the
|
||||||
|
* JSON Web Key Set
|
||||||
|
*
|
||||||
|
* @return array<string, Key> An associative array of key IDs (kid) to Key objects
|
||||||
|
*
|
||||||
|
* @throws InvalidArgumentException Provided JWK Set is empty
|
||||||
|
* @throws UnexpectedValueException Provided JWK Set was invalid
|
||||||
|
* @throws DomainException OpenSSL failure
|
||||||
|
*
|
||||||
|
* @uses parseKey
|
||||||
|
*/
|
||||||
|
public static function parseKeySet(array $jwks, string $defaultAlg = null): array
|
||||||
|
{
|
||||||
|
$keys = [];
|
||||||
|
|
||||||
|
if (!isset($jwks['keys'])) {
|
||||||
|
throw new UnexpectedValueException('"keys" member must exist in the JWK Set');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (empty($jwks['keys'])) {
|
||||||
|
throw new InvalidArgumentException('JWK Set did not contain any keys');
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach ($jwks['keys'] as $k => $v) {
|
||||||
|
$kid = isset($v['kid']) ? $v['kid'] : $k;
|
||||||
|
if ($key = self::parseKey($v, $defaultAlg)) {
|
||||||
|
$keys[(string) $kid] = $key;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (0 === \count($keys)) {
|
||||||
|
throw new UnexpectedValueException('No supported algorithms found in JWK Set');
|
||||||
|
}
|
||||||
|
|
||||||
|
return $keys;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parse a JWK key
|
||||||
|
*
|
||||||
|
* @param array<mixed> $jwk An individual JWK
|
||||||
|
* @param string $defaultAlg The algorithm for the Key object if "alg" is not set in the
|
||||||
|
* JSON Web Key Set
|
||||||
|
*
|
||||||
|
* @return Key The key object for the JWK
|
||||||
|
*
|
||||||
|
* @throws InvalidArgumentException Provided JWK is empty
|
||||||
|
* @throws UnexpectedValueException Provided JWK was invalid
|
||||||
|
* @throws DomainException OpenSSL failure
|
||||||
|
*
|
||||||
|
* @uses createPemFromModulusAndExponent
|
||||||
|
*/
|
||||||
|
public static function parseKey(array $jwk, string $defaultAlg = null): ?Key
|
||||||
|
{
|
||||||
|
if (empty($jwk)) {
|
||||||
|
throw new InvalidArgumentException('JWK must not be empty');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!isset($jwk['kty'])) {
|
||||||
|
throw new UnexpectedValueException('JWK must contain a "kty" parameter');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!isset($jwk['alg'])) {
|
||||||
|
if (\is_null($defaultAlg)) {
|
||||||
|
// The "alg" parameter is optional in a KTY, but an algorithm is required
|
||||||
|
// for parsing in this library. Use the $defaultAlg parameter when parsing the
|
||||||
|
// key set in order to prevent this error.
|
||||||
|
// @see https://datatracker.ietf.org/doc/html/rfc7517#section-4.4
|
||||||
|
throw new UnexpectedValueException('JWK must contain an "alg" parameter');
|
||||||
|
}
|
||||||
|
$jwk['alg'] = $defaultAlg;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch ($jwk['kty']) {
|
||||||
|
case 'RSA':
|
||||||
|
if (!empty($jwk['d'])) {
|
||||||
|
throw new UnexpectedValueException('RSA private keys are not supported');
|
||||||
|
}
|
||||||
|
if (!isset($jwk['n']) || !isset($jwk['e'])) {
|
||||||
|
throw new UnexpectedValueException('RSA keys must contain values for both "n" and "e"');
|
||||||
|
}
|
||||||
|
|
||||||
|
$pem = self::createPemFromModulusAndExponent($jwk['n'], $jwk['e']);
|
||||||
|
$publicKey = \openssl_pkey_get_public($pem);
|
||||||
|
if (false === $publicKey) {
|
||||||
|
throw new DomainException(
|
||||||
|
'OpenSSL error: ' . \openssl_error_string()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return new Key($publicKey, $jwk['alg']);
|
||||||
|
case 'EC':
|
||||||
|
if (isset($jwk['d'])) {
|
||||||
|
// The key is actually a private key
|
||||||
|
throw new UnexpectedValueException('Key data must be for a public key');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (empty($jwk['crv'])) {
|
||||||
|
throw new UnexpectedValueException('crv not set');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!isset(self::EC_CURVES[$jwk['crv']])) {
|
||||||
|
throw new DomainException('Unrecognised or unsupported EC curve');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (empty($jwk['x']) || empty($jwk['y'])) {
|
||||||
|
throw new UnexpectedValueException('x and y not set');
|
||||||
|
}
|
||||||
|
|
||||||
|
$publicKey = self::createPemFromCrvAndXYCoordinates($jwk['crv'], $jwk['x'], $jwk['y']);
|
||||||
|
return new Key($publicKey, $jwk['alg']);
|
||||||
|
case 'OKP':
|
||||||
|
if (isset($jwk['d'])) {
|
||||||
|
// The key is actually a private key
|
||||||
|
throw new UnexpectedValueException('Key data must be for a public key');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!isset($jwk['crv'])) {
|
||||||
|
throw new UnexpectedValueException('crv not set');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (empty(self::OKP_SUBTYPES[$jwk['crv']])) {
|
||||||
|
throw new DomainException('Unrecognised or unsupported OKP key subtype');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (empty($jwk['x'])) {
|
||||||
|
throw new UnexpectedValueException('x not set');
|
||||||
|
}
|
||||||
|
|
||||||
|
// This library works internally with EdDSA keys (Ed25519) encoded in standard base64.
|
||||||
|
$publicKey = JWT::convertBase64urlToBase64($jwk['x']);
|
||||||
|
return new Key($publicKey, $jwk['alg']);
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Converts the EC JWK values to pem format.
|
||||||
|
*
|
||||||
|
* @param string $crv The EC curve (only P-256 & P-384 is supported)
|
||||||
|
* @param string $x The EC x-coordinate
|
||||||
|
* @param string $y The EC y-coordinate
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
private static function createPemFromCrvAndXYCoordinates(string $crv, string $x, string $y): string
|
||||||
|
{
|
||||||
|
$pem =
|
||||||
|
self::encodeDER(
|
||||||
|
self::ASN1_SEQUENCE,
|
||||||
|
self::encodeDER(
|
||||||
|
self::ASN1_SEQUENCE,
|
||||||
|
self::encodeDER(
|
||||||
|
self::ASN1_OBJECT_IDENTIFIER,
|
||||||
|
self::encodeOID(self::OID)
|
||||||
|
)
|
||||||
|
. self::encodeDER(
|
||||||
|
self::ASN1_OBJECT_IDENTIFIER,
|
||||||
|
self::encodeOID(self::EC_CURVES[$crv])
|
||||||
|
)
|
||||||
|
) .
|
||||||
|
self::encodeDER(
|
||||||
|
self::ASN1_BIT_STRING,
|
||||||
|
\chr(0x00) . \chr(0x04)
|
||||||
|
. JWT::urlsafeB64Decode($x)
|
||||||
|
. JWT::urlsafeB64Decode($y)
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
return sprintf(
|
||||||
|
"-----BEGIN PUBLIC KEY-----\n%s\n-----END PUBLIC KEY-----\n",
|
||||||
|
wordwrap(base64_encode($pem), 64, "\n", true)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a public key represented in PEM format from RSA modulus and exponent information
|
||||||
|
*
|
||||||
|
* @param string $n The RSA modulus encoded in Base64
|
||||||
|
* @param string $e The RSA exponent encoded in Base64
|
||||||
|
*
|
||||||
|
* @return string The RSA public key represented in PEM format
|
||||||
|
*
|
||||||
|
* @uses encodeLength
|
||||||
|
*/
|
||||||
|
private static function createPemFromModulusAndExponent(
|
||||||
|
string $n,
|
||||||
|
string $e
|
||||||
|
): string {
|
||||||
|
$mod = JWT::urlsafeB64Decode($n);
|
||||||
|
$exp = JWT::urlsafeB64Decode($e);
|
||||||
|
|
||||||
|
$modulus = \pack('Ca*a*', 2, self::encodeLength(\strlen($mod)), $mod);
|
||||||
|
$publicExponent = \pack('Ca*a*', 2, self::encodeLength(\strlen($exp)), $exp);
|
||||||
|
|
||||||
|
$rsaPublicKey = \pack(
|
||||||
|
'Ca*a*a*',
|
||||||
|
48,
|
||||||
|
self::encodeLength(\strlen($modulus) + \strlen($publicExponent)),
|
||||||
|
$modulus,
|
||||||
|
$publicExponent
|
||||||
|
);
|
||||||
|
|
||||||
|
// sequence(oid(1.2.840.113549.1.1.1), null)) = rsaEncryption.
|
||||||
|
$rsaOID = \pack('H*', '300d06092a864886f70d0101010500'); // hex version of MA0GCSqGSIb3DQEBAQUA
|
||||||
|
$rsaPublicKey = \chr(0) . $rsaPublicKey;
|
||||||
|
$rsaPublicKey = \chr(3) . self::encodeLength(\strlen($rsaPublicKey)) . $rsaPublicKey;
|
||||||
|
|
||||||
|
$rsaPublicKey = \pack(
|
||||||
|
'Ca*a*',
|
||||||
|
48,
|
||||||
|
self::encodeLength(\strlen($rsaOID . $rsaPublicKey)),
|
||||||
|
$rsaOID . $rsaPublicKey
|
||||||
|
);
|
||||||
|
|
||||||
|
return "-----BEGIN PUBLIC KEY-----\r\n" .
|
||||||
|
\chunk_split(\base64_encode($rsaPublicKey), 64) .
|
||||||
|
'-----END PUBLIC KEY-----';
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* DER-encode the length
|
||||||
|
*
|
||||||
|
* DER supports lengths up to (2**8)**127, however, we'll only support lengths up to (2**8)**4. See
|
||||||
|
* {@link http://itu.int/ITU-T/studygroups/com17/languages/X.690-0207.pdf#p=13 X.690 paragraph 8.1.3} for more information.
|
||||||
|
*
|
||||||
|
* @param int $length
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
private static function encodeLength(int $length): string
|
||||||
|
{
|
||||||
|
if ($length <= 0x7F) {
|
||||||
|
return \chr($length);
|
||||||
|
}
|
||||||
|
|
||||||
|
$temp = \ltrim(\pack('N', $length), \chr(0));
|
||||||
|
|
||||||
|
return \pack('Ca*', 0x80 | \strlen($temp), $temp);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Encodes a value into a DER object.
|
||||||
|
* Also defined in Firebase\JWT\JWT
|
||||||
|
*
|
||||||
|
* @param int $type DER tag
|
||||||
|
* @param string $value the value to encode
|
||||||
|
* @return string the encoded object
|
||||||
|
*/
|
||||||
|
private static function encodeDER(int $type, string $value): string
|
||||||
|
{
|
||||||
|
$tag_header = 0;
|
||||||
|
if ($type === self::ASN1_SEQUENCE) {
|
||||||
|
$tag_header |= 0x20;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Type
|
||||||
|
$der = \chr($tag_header | $type);
|
||||||
|
|
||||||
|
// Length
|
||||||
|
$der .= \chr(\strlen($value));
|
||||||
|
|
||||||
|
return $der . $value;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Encodes a string into a DER-encoded OID.
|
||||||
|
*
|
||||||
|
* @param string $oid the OID string
|
||||||
|
* @return string the binary DER-encoded OID
|
||||||
|
*/
|
||||||
|
private static function encodeOID(string $oid): string
|
||||||
|
{
|
||||||
|
$octets = explode('.', $oid);
|
||||||
|
|
||||||
|
// Get the first octet
|
||||||
|
$first = (int) array_shift($octets);
|
||||||
|
$second = (int) array_shift($octets);
|
||||||
|
$oid = \chr($first * 40 + $second);
|
||||||
|
|
||||||
|
// Iterate over subsequent octets
|
||||||
|
foreach ($octets as $octet) {
|
||||||
|
if ($octet == 0) {
|
||||||
|
$oid .= \chr(0x00);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
$bin = '';
|
||||||
|
|
||||||
|
while ($octet) {
|
||||||
|
$bin .= \chr(0x80 | ($octet & 0x7f));
|
||||||
|
$octet >>= 7;
|
||||||
|
}
|
||||||
|
$bin[0] = $bin[0] & \chr(0x7f);
|
||||||
|
|
||||||
|
// Convert to big endian if necessary
|
||||||
|
if (pack('V', 65534) == pack('L', 65534)) {
|
||||||
|
$oid .= strrev($bin);
|
||||||
|
} else {
|
||||||
|
$oid .= $bin;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $oid;
|
||||||
|
}
|
||||||
|
}
|
||||||
672
vendor/firebase/php-jwt/src/JWT.php
vendored
Executable file
672
vendor/firebase/php-jwt/src/JWT.php
vendored
Executable file
@ -0,0 +1,672 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Firebase\JWT;
|
||||||
|
|
||||||
|
use ArrayAccess;
|
||||||
|
use DateTime;
|
||||||
|
use DomainException;
|
||||||
|
use Exception;
|
||||||
|
use InvalidArgumentException;
|
||||||
|
use OpenSSLAsymmetricKey;
|
||||||
|
use OpenSSLCertificate;
|
||||||
|
use stdClass;
|
||||||
|
use UnexpectedValueException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* JSON Web Token implementation, based on this spec:
|
||||||
|
* https://tools.ietf.org/html/rfc7519
|
||||||
|
*
|
||||||
|
* PHP version 5
|
||||||
|
*
|
||||||
|
* @category Authentication
|
||||||
|
* @package Authentication_JWT
|
||||||
|
* @author Neuman Vong <neuman@twilio.com>
|
||||||
|
* @author Anant Narayanan <anant@php.net>
|
||||||
|
* @license http://opensource.org/licenses/BSD-3-Clause 3-clause BSD
|
||||||
|
* @link https://github.com/firebase/php-jwt
|
||||||
|
*/
|
||||||
|
class JWT
|
||||||
|
{
|
||||||
|
private const ASN1_INTEGER = 0x02;
|
||||||
|
private const ASN1_SEQUENCE = 0x10;
|
||||||
|
private const ASN1_BIT_STRING = 0x03;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* When checking nbf, iat or expiration times,
|
||||||
|
* we want to provide some extra leeway time to
|
||||||
|
* account for clock skew.
|
||||||
|
*
|
||||||
|
* @var int
|
||||||
|
*/
|
||||||
|
public static $leeway = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Allow the current timestamp to be specified.
|
||||||
|
* Useful for fixing a value within unit testing.
|
||||||
|
* Will default to PHP time() value if null.
|
||||||
|
*
|
||||||
|
* @var ?int
|
||||||
|
*/
|
||||||
|
public static $timestamp = null;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var array<string, string[]>
|
||||||
|
*/
|
||||||
|
public static $supported_algs = [
|
||||||
|
'ES384' => ['openssl', 'SHA384'],
|
||||||
|
'ES256' => ['openssl', 'SHA256'],
|
||||||
|
'ES256K' => ['openssl', 'SHA256'],
|
||||||
|
'HS256' => ['hash_hmac', 'SHA256'],
|
||||||
|
'HS384' => ['hash_hmac', 'SHA384'],
|
||||||
|
'HS512' => ['hash_hmac', 'SHA512'],
|
||||||
|
'RS256' => ['openssl', 'SHA256'],
|
||||||
|
'RS384' => ['openssl', 'SHA384'],
|
||||||
|
'RS512' => ['openssl', 'SHA512'],
|
||||||
|
'EdDSA' => ['sodium_crypto', 'EdDSA'],
|
||||||
|
];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Decodes a JWT string into a PHP object.
|
||||||
|
*
|
||||||
|
* @param string $jwt The JWT
|
||||||
|
* @param Key|ArrayAccess<string,Key>|array<string,Key> $keyOrKeyArray The Key or associative array of key IDs
|
||||||
|
* (kid) to Key objects.
|
||||||
|
* If the algorithm used is asymmetric, this is
|
||||||
|
* the public key.
|
||||||
|
* Each Key object contains an algorithm and
|
||||||
|
* matching key.
|
||||||
|
* Supported algorithms are 'ES384','ES256',
|
||||||
|
* 'HS256', 'HS384', 'HS512', 'RS256', 'RS384'
|
||||||
|
* and 'RS512'.
|
||||||
|
* @param stdClass $headers Optional. Populates stdClass with headers.
|
||||||
|
*
|
||||||
|
* @return stdClass The JWT's payload as a PHP object
|
||||||
|
*
|
||||||
|
* @throws InvalidArgumentException Provided key/key-array was empty or malformed
|
||||||
|
* @throws DomainException Provided JWT is malformed
|
||||||
|
* @throws UnexpectedValueException Provided JWT was invalid
|
||||||
|
* @throws SignatureInvalidException Provided JWT was invalid because the signature verification failed
|
||||||
|
* @throws BeforeValidException Provided JWT is trying to be used before it's eligible as defined by 'nbf'
|
||||||
|
* @throws BeforeValidException Provided JWT is trying to be used before it's been created as defined by 'iat'
|
||||||
|
* @throws ExpiredException Provided JWT has since expired, as defined by the 'exp' claim
|
||||||
|
*
|
||||||
|
* @uses jsonDecode
|
||||||
|
* @uses urlsafeB64Decode
|
||||||
|
*/
|
||||||
|
public static function decode(
|
||||||
|
string $jwt,
|
||||||
|
$keyOrKeyArray,
|
||||||
|
stdClass &$headers = null
|
||||||
|
): stdClass {
|
||||||
|
// Validate JWT
|
||||||
|
$timestamp = \is_null(static::$timestamp) ? \time() : static::$timestamp;
|
||||||
|
|
||||||
|
if (empty($keyOrKeyArray)) {
|
||||||
|
throw new InvalidArgumentException('Key may not be empty');
|
||||||
|
}
|
||||||
|
$tks = \explode('.', $jwt);
|
||||||
|
if (\count($tks) !== 3) {
|
||||||
|
throw new UnexpectedValueException('Wrong number of segments');
|
||||||
|
}
|
||||||
|
list($headb64, $bodyb64, $cryptob64) = $tks;
|
||||||
|
$headerRaw = static::urlsafeB64Decode($headb64);
|
||||||
|
if (null === ($header = static::jsonDecode($headerRaw))) {
|
||||||
|
throw new UnexpectedValueException('Invalid header encoding');
|
||||||
|
}
|
||||||
|
if ($headers !== null) {
|
||||||
|
$headers = $header;
|
||||||
|
}
|
||||||
|
$payloadRaw = static::urlsafeB64Decode($bodyb64);
|
||||||
|
if (null === ($payload = static::jsonDecode($payloadRaw))) {
|
||||||
|
throw new UnexpectedValueException('Invalid claims encoding');
|
||||||
|
}
|
||||||
|
if (\is_array($payload)) {
|
||||||
|
// prevent PHP Fatal Error in edge-cases when payload is empty array
|
||||||
|
$payload = (object) $payload;
|
||||||
|
}
|
||||||
|
if (!$payload instanceof stdClass) {
|
||||||
|
throw new UnexpectedValueException('Payload must be a JSON object');
|
||||||
|
}
|
||||||
|
$sig = static::urlsafeB64Decode($cryptob64);
|
||||||
|
if (empty($header->alg)) {
|
||||||
|
throw new UnexpectedValueException('Empty algorithm');
|
||||||
|
}
|
||||||
|
if (empty(static::$supported_algs[$header->alg])) {
|
||||||
|
throw new UnexpectedValueException('Algorithm not supported');
|
||||||
|
}
|
||||||
|
|
||||||
|
$key = self::getKey($keyOrKeyArray, property_exists($header, 'kid') ? $header->kid : null);
|
||||||
|
|
||||||
|
// Check the algorithm
|
||||||
|
if (!self::constantTimeEquals($key->getAlgorithm(), $header->alg)) {
|
||||||
|
// See issue #351
|
||||||
|
throw new UnexpectedValueException('Incorrect key for this algorithm');
|
||||||
|
}
|
||||||
|
if (\in_array($header->alg, ['ES256', 'ES256K', 'ES384'], true)) {
|
||||||
|
// OpenSSL expects an ASN.1 DER sequence for ES256/ES256K/ES384 signatures
|
||||||
|
$sig = self::signatureToDER($sig);
|
||||||
|
}
|
||||||
|
if (!self::verify("{$headb64}.{$bodyb64}", $sig, $key->getKeyMaterial(), $header->alg)) {
|
||||||
|
throw new SignatureInvalidException('Signature verification failed');
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check the nbf if it is defined. This is the time that the
|
||||||
|
// token can actually be used. If it's not yet that time, abort.
|
||||||
|
if (isset($payload->nbf) && floor($payload->nbf) > ($timestamp + static::$leeway)) {
|
||||||
|
$ex = new BeforeValidException(
|
||||||
|
'Cannot handle token with nbf prior to ' . \date(DateTime::ISO8601, (int) $payload->nbf)
|
||||||
|
);
|
||||||
|
$ex->setPayload($payload);
|
||||||
|
throw $ex;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check that this token has been created before 'now'. This prevents
|
||||||
|
// using tokens that have been created for later use (and haven't
|
||||||
|
// correctly used the nbf claim).
|
||||||
|
if (!isset($payload->nbf) && isset($payload->iat) && floor($payload->iat) > ($timestamp + static::$leeway)) {
|
||||||
|
$ex = new BeforeValidException(
|
||||||
|
'Cannot handle token with iat prior to ' . \date(DateTime::ISO8601, (int) $payload->iat)
|
||||||
|
);
|
||||||
|
$ex->setPayload($payload);
|
||||||
|
throw $ex;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if this token has expired.
|
||||||
|
if (isset($payload->exp) && ($timestamp - static::$leeway) >= $payload->exp) {
|
||||||
|
$ex = new ExpiredException('Expired token');
|
||||||
|
$ex->setPayload($payload);
|
||||||
|
throw $ex;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $payload;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Converts and signs a PHP array into a JWT string.
|
||||||
|
*
|
||||||
|
* @param array<mixed> $payload PHP array
|
||||||
|
* @param string|resource|OpenSSLAsymmetricKey|OpenSSLCertificate $key The secret key.
|
||||||
|
* @param string $alg Supported algorithms are 'ES384','ES256', 'ES256K', 'HS256',
|
||||||
|
* 'HS384', 'HS512', 'RS256', 'RS384', and 'RS512'
|
||||||
|
* @param string $keyId
|
||||||
|
* @param array<string, string> $head An array with header elements to attach
|
||||||
|
*
|
||||||
|
* @return string A signed JWT
|
||||||
|
*
|
||||||
|
* @uses jsonEncode
|
||||||
|
* @uses urlsafeB64Encode
|
||||||
|
*/
|
||||||
|
public static function encode(
|
||||||
|
array $payload,
|
||||||
|
$key,
|
||||||
|
string $alg,
|
||||||
|
string $keyId = null,
|
||||||
|
array $head = null
|
||||||
|
): string {
|
||||||
|
$header = ['typ' => 'JWT'];
|
||||||
|
if (isset($head) && \is_array($head)) {
|
||||||
|
$header = \array_merge($header, $head);
|
||||||
|
}
|
||||||
|
$header['alg'] = $alg;
|
||||||
|
if ($keyId !== null) {
|
||||||
|
$header['kid'] = $keyId;
|
||||||
|
}
|
||||||
|
$segments = [];
|
||||||
|
$segments[] = static::urlsafeB64Encode((string) static::jsonEncode($header));
|
||||||
|
$segments[] = static::urlsafeB64Encode((string) static::jsonEncode($payload));
|
||||||
|
$signing_input = \implode('.', $segments);
|
||||||
|
|
||||||
|
$signature = static::sign($signing_input, $key, $alg);
|
||||||
|
$segments[] = static::urlsafeB64Encode($signature);
|
||||||
|
|
||||||
|
return \implode('.', $segments);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sign a string with a given key and algorithm.
|
||||||
|
*
|
||||||
|
* @param string $msg The message to sign
|
||||||
|
* @param string|resource|OpenSSLAsymmetricKey|OpenSSLCertificate $key The secret key.
|
||||||
|
* @param string $alg Supported algorithms are 'EdDSA', 'ES384', 'ES256', 'ES256K', 'HS256',
|
||||||
|
* 'HS384', 'HS512', 'RS256', 'RS384', and 'RS512'
|
||||||
|
*
|
||||||
|
* @return string An encrypted message
|
||||||
|
*
|
||||||
|
* @throws DomainException Unsupported algorithm or bad key was specified
|
||||||
|
*/
|
||||||
|
public static function sign(
|
||||||
|
string $msg,
|
||||||
|
$key,
|
||||||
|
string $alg
|
||||||
|
): string {
|
||||||
|
if (empty(static::$supported_algs[$alg])) {
|
||||||
|
throw new DomainException('Algorithm not supported');
|
||||||
|
}
|
||||||
|
list($function, $algorithm) = static::$supported_algs[$alg];
|
||||||
|
switch ($function) {
|
||||||
|
case 'hash_hmac':
|
||||||
|
if (!\is_string($key)) {
|
||||||
|
throw new InvalidArgumentException('key must be a string when using hmac');
|
||||||
|
}
|
||||||
|
return \hash_hmac($algorithm, $msg, $key, true);
|
||||||
|
case 'openssl':
|
||||||
|
$signature = '';
|
||||||
|
if (!\is_resource($key) && !openssl_pkey_get_private($key)) {
|
||||||
|
throw new DomainException('OpenSSL unable to validate key');
|
||||||
|
}
|
||||||
|
$success = \openssl_sign($msg, $signature, $key, $algorithm); // @phpstan-ignore-line
|
||||||
|
if (!$success) {
|
||||||
|
throw new DomainException('OpenSSL unable to sign data');
|
||||||
|
}
|
||||||
|
if ($alg === 'ES256' || $alg === 'ES256K') {
|
||||||
|
$signature = self::signatureFromDER($signature, 256);
|
||||||
|
} elseif ($alg === 'ES384') {
|
||||||
|
$signature = self::signatureFromDER($signature, 384);
|
||||||
|
}
|
||||||
|
return $signature;
|
||||||
|
case 'sodium_crypto':
|
||||||
|
if (!\function_exists('sodium_crypto_sign_detached')) {
|
||||||
|
throw new DomainException('libsodium is not available');
|
||||||
|
}
|
||||||
|
if (!\is_string($key)) {
|
||||||
|
throw new InvalidArgumentException('key must be a string when using EdDSA');
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
// The last non-empty line is used as the key.
|
||||||
|
$lines = array_filter(explode("\n", $key));
|
||||||
|
$key = base64_decode((string) end($lines));
|
||||||
|
if (\strlen($key) === 0) {
|
||||||
|
throw new DomainException('Key cannot be empty string');
|
||||||
|
}
|
||||||
|
return sodium_crypto_sign_detached($msg, $key);
|
||||||
|
} catch (Exception $e) {
|
||||||
|
throw new DomainException($e->getMessage(), 0, $e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new DomainException('Algorithm not supported');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Verify a signature with the message, key and method. Not all methods
|
||||||
|
* are symmetric, so we must have a separate verify and sign method.
|
||||||
|
*
|
||||||
|
* @param string $msg The original message (header and body)
|
||||||
|
* @param string $signature The original signature
|
||||||
|
* @param string|resource|OpenSSLAsymmetricKey|OpenSSLCertificate $keyMaterial For Ed*, ES*, HS*, a string key works. for RS*, must be an instance of OpenSSLAsymmetricKey
|
||||||
|
* @param string $alg The algorithm
|
||||||
|
*
|
||||||
|
* @return bool
|
||||||
|
*
|
||||||
|
* @throws DomainException Invalid Algorithm, bad key, or OpenSSL failure
|
||||||
|
*/
|
||||||
|
private static function verify(
|
||||||
|
string $msg,
|
||||||
|
string $signature,
|
||||||
|
$keyMaterial,
|
||||||
|
string $alg
|
||||||
|
): bool {
|
||||||
|
if (empty(static::$supported_algs[$alg])) {
|
||||||
|
throw new DomainException('Algorithm not supported');
|
||||||
|
}
|
||||||
|
|
||||||
|
list($function, $algorithm) = static::$supported_algs[$alg];
|
||||||
|
switch ($function) {
|
||||||
|
case 'openssl':
|
||||||
|
$success = \openssl_verify($msg, $signature, $keyMaterial, $algorithm); // @phpstan-ignore-line
|
||||||
|
if ($success === 1) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if ($success === 0) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
// returns 1 on success, 0 on failure, -1 on error.
|
||||||
|
throw new DomainException(
|
||||||
|
'OpenSSL error: ' . \openssl_error_string()
|
||||||
|
);
|
||||||
|
case 'sodium_crypto':
|
||||||
|
if (!\function_exists('sodium_crypto_sign_verify_detached')) {
|
||||||
|
throw new DomainException('libsodium is not available');
|
||||||
|
}
|
||||||
|
if (!\is_string($keyMaterial)) {
|
||||||
|
throw new InvalidArgumentException('key must be a string when using EdDSA');
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
// The last non-empty line is used as the key.
|
||||||
|
$lines = array_filter(explode("\n", $keyMaterial));
|
||||||
|
$key = base64_decode((string) end($lines));
|
||||||
|
if (\strlen($key) === 0) {
|
||||||
|
throw new DomainException('Key cannot be empty string');
|
||||||
|
}
|
||||||
|
if (\strlen($signature) === 0) {
|
||||||
|
throw new DomainException('Signature cannot be empty string');
|
||||||
|
}
|
||||||
|
return sodium_crypto_sign_verify_detached($signature, $msg, $key);
|
||||||
|
} catch (Exception $e) {
|
||||||
|
throw new DomainException($e->getMessage(), 0, $e);
|
||||||
|
}
|
||||||
|
case 'hash_hmac':
|
||||||
|
default:
|
||||||
|
if (!\is_string($keyMaterial)) {
|
||||||
|
throw new InvalidArgumentException('key must be a string when using hmac');
|
||||||
|
}
|
||||||
|
$hash = \hash_hmac($algorithm, $msg, $keyMaterial, true);
|
||||||
|
return self::constantTimeEquals($hash, $signature);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Decode a JSON string into a PHP object.
|
||||||
|
*
|
||||||
|
* @param string $input JSON string
|
||||||
|
*
|
||||||
|
* @return mixed The decoded JSON string
|
||||||
|
*
|
||||||
|
* @throws DomainException Provided string was invalid JSON
|
||||||
|
*/
|
||||||
|
public static function jsonDecode(string $input)
|
||||||
|
{
|
||||||
|
$obj = \json_decode($input, false, 512, JSON_BIGINT_AS_STRING);
|
||||||
|
|
||||||
|
if ($errno = \json_last_error()) {
|
||||||
|
self::handleJsonError($errno);
|
||||||
|
} elseif ($obj === null && $input !== 'null') {
|
||||||
|
throw new DomainException('Null result with non-null input');
|
||||||
|
}
|
||||||
|
return $obj;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Encode a PHP array into a JSON string.
|
||||||
|
*
|
||||||
|
* @param array<mixed> $input A PHP array
|
||||||
|
*
|
||||||
|
* @return string JSON representation of the PHP array
|
||||||
|
*
|
||||||
|
* @throws DomainException Provided object could not be encoded to valid JSON
|
||||||
|
*/
|
||||||
|
public static function jsonEncode(array $input): string
|
||||||
|
{
|
||||||
|
if (PHP_VERSION_ID >= 50400) {
|
||||||
|
$json = \json_encode($input, \JSON_UNESCAPED_SLASHES);
|
||||||
|
} else {
|
||||||
|
// PHP 5.3 only
|
||||||
|
$json = \json_encode($input);
|
||||||
|
}
|
||||||
|
if ($errno = \json_last_error()) {
|
||||||
|
self::handleJsonError($errno);
|
||||||
|
} elseif ($json === 'null') {
|
||||||
|
throw new DomainException('Null result with non-null input');
|
||||||
|
}
|
||||||
|
if ($json === false) {
|
||||||
|
throw new DomainException('Provided object could not be encoded to valid JSON');
|
||||||
|
}
|
||||||
|
return $json;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Decode a string with URL-safe Base64.
|
||||||
|
*
|
||||||
|
* @param string $input A Base64 encoded string
|
||||||
|
*
|
||||||
|
* @return string A decoded string
|
||||||
|
*
|
||||||
|
* @throws InvalidArgumentException invalid base64 characters
|
||||||
|
*/
|
||||||
|
public static function urlsafeB64Decode(string $input): string
|
||||||
|
{
|
||||||
|
return \base64_decode(self::convertBase64UrlToBase64($input));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Convert a string in the base64url (URL-safe Base64) encoding to standard base64.
|
||||||
|
*
|
||||||
|
* @param string $input A Base64 encoded string with URL-safe characters (-_ and no padding)
|
||||||
|
*
|
||||||
|
* @return string A Base64 encoded string with standard characters (+/) and padding (=), when
|
||||||
|
* needed.
|
||||||
|
*
|
||||||
|
* @see https://www.rfc-editor.org/rfc/rfc4648
|
||||||
|
*/
|
||||||
|
public static function convertBase64UrlToBase64(string $input): string
|
||||||
|
{
|
||||||
|
$remainder = \strlen($input) % 4;
|
||||||
|
if ($remainder) {
|
||||||
|
$padlen = 4 - $remainder;
|
||||||
|
$input .= \str_repeat('=', $padlen);
|
||||||
|
}
|
||||||
|
return \strtr($input, '-_', '+/');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Encode a string with URL-safe Base64.
|
||||||
|
*
|
||||||
|
* @param string $input The string you want encoded
|
||||||
|
*
|
||||||
|
* @return string The base64 encode of what you passed in
|
||||||
|
*/
|
||||||
|
public static function urlsafeB64Encode(string $input): string
|
||||||
|
{
|
||||||
|
return \str_replace('=', '', \strtr(\base64_encode($input), '+/', '-_'));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determine if an algorithm has been provided for each Key
|
||||||
|
*
|
||||||
|
* @param Key|ArrayAccess<string,Key>|array<string,Key> $keyOrKeyArray
|
||||||
|
* @param string|null $kid
|
||||||
|
*
|
||||||
|
* @throws UnexpectedValueException
|
||||||
|
*
|
||||||
|
* @return Key
|
||||||
|
*/
|
||||||
|
private static function getKey(
|
||||||
|
$keyOrKeyArray,
|
||||||
|
?string $kid
|
||||||
|
): Key {
|
||||||
|
if ($keyOrKeyArray instanceof Key) {
|
||||||
|
return $keyOrKeyArray;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (empty($kid) && $kid !== '0') {
|
||||||
|
throw new UnexpectedValueException('"kid" empty, unable to lookup correct key');
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($keyOrKeyArray instanceof CachedKeySet) {
|
||||||
|
// Skip "isset" check, as this will automatically refresh if not set
|
||||||
|
return $keyOrKeyArray[$kid];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!isset($keyOrKeyArray[$kid])) {
|
||||||
|
throw new UnexpectedValueException('"kid" invalid, unable to lookup correct key');
|
||||||
|
}
|
||||||
|
|
||||||
|
return $keyOrKeyArray[$kid];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $left The string of known length to compare against
|
||||||
|
* @param string $right The user-supplied string
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
public static function constantTimeEquals(string $left, string $right): bool
|
||||||
|
{
|
||||||
|
if (\function_exists('hash_equals')) {
|
||||||
|
return \hash_equals($left, $right);
|
||||||
|
}
|
||||||
|
$len = \min(self::safeStrlen($left), self::safeStrlen($right));
|
||||||
|
|
||||||
|
$status = 0;
|
||||||
|
for ($i = 0; $i < $len; $i++) {
|
||||||
|
$status |= (\ord($left[$i]) ^ \ord($right[$i]));
|
||||||
|
}
|
||||||
|
$status |= (self::safeStrlen($left) ^ self::safeStrlen($right));
|
||||||
|
|
||||||
|
return ($status === 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Helper method to create a JSON error.
|
||||||
|
*
|
||||||
|
* @param int $errno An error number from json_last_error()
|
||||||
|
*
|
||||||
|
* @throws DomainException
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
private static function handleJsonError(int $errno): void
|
||||||
|
{
|
||||||
|
$messages = [
|
||||||
|
JSON_ERROR_DEPTH => 'Maximum stack depth exceeded',
|
||||||
|
JSON_ERROR_STATE_MISMATCH => 'Invalid or malformed JSON',
|
||||||
|
JSON_ERROR_CTRL_CHAR => 'Unexpected control character found',
|
||||||
|
JSON_ERROR_SYNTAX => 'Syntax error, malformed JSON',
|
||||||
|
JSON_ERROR_UTF8 => 'Malformed UTF-8 characters' //PHP >= 5.3.3
|
||||||
|
];
|
||||||
|
throw new DomainException(
|
||||||
|
isset($messages[$errno])
|
||||||
|
? $messages[$errno]
|
||||||
|
: 'Unknown JSON error: ' . $errno
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the number of bytes in cryptographic strings.
|
||||||
|
*
|
||||||
|
* @param string $str
|
||||||
|
*
|
||||||
|
* @return int
|
||||||
|
*/
|
||||||
|
private static function safeStrlen(string $str): int
|
||||||
|
{
|
||||||
|
if (\function_exists('mb_strlen')) {
|
||||||
|
return \mb_strlen($str, '8bit');
|
||||||
|
}
|
||||||
|
return \strlen($str);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Convert an ECDSA signature to an ASN.1 DER sequence
|
||||||
|
*
|
||||||
|
* @param string $sig The ECDSA signature to convert
|
||||||
|
* @return string The encoded DER object
|
||||||
|
*/
|
||||||
|
private static function signatureToDER(string $sig): string
|
||||||
|
{
|
||||||
|
// Separate the signature into r-value and s-value
|
||||||
|
$length = max(1, (int) (\strlen($sig) / 2));
|
||||||
|
list($r, $s) = \str_split($sig, $length);
|
||||||
|
|
||||||
|
// Trim leading zeros
|
||||||
|
$r = \ltrim($r, "\x00");
|
||||||
|
$s = \ltrim($s, "\x00");
|
||||||
|
|
||||||
|
// Convert r-value and s-value from unsigned big-endian integers to
|
||||||
|
// signed two's complement
|
||||||
|
if (\ord($r[0]) > 0x7f) {
|
||||||
|
$r = "\x00" . $r;
|
||||||
|
}
|
||||||
|
if (\ord($s[0]) > 0x7f) {
|
||||||
|
$s = "\x00" . $s;
|
||||||
|
}
|
||||||
|
|
||||||
|
return self::encodeDER(
|
||||||
|
self::ASN1_SEQUENCE,
|
||||||
|
self::encodeDER(self::ASN1_INTEGER, $r) .
|
||||||
|
self::encodeDER(self::ASN1_INTEGER, $s)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Encodes a value into a DER object.
|
||||||
|
*
|
||||||
|
* @param int $type DER tag
|
||||||
|
* @param string $value the value to encode
|
||||||
|
*
|
||||||
|
* @return string the encoded object
|
||||||
|
*/
|
||||||
|
private static function encodeDER(int $type, string $value): string
|
||||||
|
{
|
||||||
|
$tag_header = 0;
|
||||||
|
if ($type === self::ASN1_SEQUENCE) {
|
||||||
|
$tag_header |= 0x20;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Type
|
||||||
|
$der = \chr($tag_header | $type);
|
||||||
|
|
||||||
|
// Length
|
||||||
|
$der .= \chr(\strlen($value));
|
||||||
|
|
||||||
|
return $der . $value;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Encodes signature from a DER object.
|
||||||
|
*
|
||||||
|
* @param string $der binary signature in DER format
|
||||||
|
* @param int $keySize the number of bits in the key
|
||||||
|
*
|
||||||
|
* @return string the signature
|
||||||
|
*/
|
||||||
|
private static function signatureFromDER(string $der, int $keySize): string
|
||||||
|
{
|
||||||
|
// OpenSSL returns the ECDSA signatures as a binary ASN.1 DER SEQUENCE
|
||||||
|
list($offset, $_) = self::readDER($der);
|
||||||
|
list($offset, $r) = self::readDER($der, $offset);
|
||||||
|
list($offset, $s) = self::readDER($der, $offset);
|
||||||
|
|
||||||
|
// Convert r-value and s-value from signed two's compliment to unsigned
|
||||||
|
// big-endian integers
|
||||||
|
$r = \ltrim($r, "\x00");
|
||||||
|
$s = \ltrim($s, "\x00");
|
||||||
|
|
||||||
|
// Pad out r and s so that they are $keySize bits long
|
||||||
|
$r = \str_pad($r, $keySize / 8, "\x00", STR_PAD_LEFT);
|
||||||
|
$s = \str_pad($s, $keySize / 8, "\x00", STR_PAD_LEFT);
|
||||||
|
|
||||||
|
return $r . $s;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reads binary DER-encoded data and decodes into a single object
|
||||||
|
*
|
||||||
|
* @param string $der the binary data in DER format
|
||||||
|
* @param int $offset the offset of the data stream containing the object
|
||||||
|
* to decode
|
||||||
|
*
|
||||||
|
* @return array{int, string|null} the new offset and the decoded object
|
||||||
|
*/
|
||||||
|
private static function readDER(string $der, int $offset = 0): array
|
||||||
|
{
|
||||||
|
$pos = $offset;
|
||||||
|
$size = \strlen($der);
|
||||||
|
$constructed = (\ord($der[$pos]) >> 5) & 0x01;
|
||||||
|
$type = \ord($der[$pos++]) & 0x1f;
|
||||||
|
|
||||||
|
// Length
|
||||||
|
$len = \ord($der[$pos++]);
|
||||||
|
if ($len & 0x80) {
|
||||||
|
$n = $len & 0x1f;
|
||||||
|
$len = 0;
|
||||||
|
while ($n-- && $pos < $size) {
|
||||||
|
$len = ($len << 8) | \ord($der[$pos++]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Value
|
||||||
|
if ($type === self::ASN1_BIT_STRING) {
|
||||||
|
$pos++; // Skip the first contents octet (padding indicator)
|
||||||
|
$data = \substr($der, $pos, $len - 1);
|
||||||
|
$pos += $len - 1;
|
||||||
|
} elseif (!$constructed) {
|
||||||
|
$data = \substr($der, $pos, $len);
|
||||||
|
$pos += $len;
|
||||||
|
} else {
|
||||||
|
$data = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return [$pos, $data];
|
||||||
|
}
|
||||||
|
}
|
||||||
20
vendor/firebase/php-jwt/src/JWTExceptionWithPayloadInterface.php
vendored
Executable file
20
vendor/firebase/php-jwt/src/JWTExceptionWithPayloadInterface.php
vendored
Executable file
@ -0,0 +1,20 @@
|
|||||||
|
<?php
|
||||||
|
namespace Firebase\JWT;
|
||||||
|
|
||||||
|
interface JWTExceptionWithPayloadInterface
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Get the payload that caused this exception.
|
||||||
|
*
|
||||||
|
* @return object
|
||||||
|
*/
|
||||||
|
public function getPayload(): object;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the payload that caused this exception.
|
||||||
|
*
|
||||||
|
* @param object $payload
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function setPayload(object $payload): void;
|
||||||
|
}
|
||||||
64
vendor/firebase/php-jwt/src/Key.php
vendored
Executable file
64
vendor/firebase/php-jwt/src/Key.php
vendored
Executable file
@ -0,0 +1,64 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Firebase\JWT;
|
||||||
|
|
||||||
|
use InvalidArgumentException;
|
||||||
|
use OpenSSLAsymmetricKey;
|
||||||
|
use OpenSSLCertificate;
|
||||||
|
use TypeError;
|
||||||
|
|
||||||
|
class Key
|
||||||
|
{
|
||||||
|
/** @var string|resource|OpenSSLAsymmetricKey|OpenSSLCertificate */
|
||||||
|
private $keyMaterial;
|
||||||
|
/** @var string */
|
||||||
|
private $algorithm;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string|resource|OpenSSLAsymmetricKey|OpenSSLCertificate $keyMaterial
|
||||||
|
* @param string $algorithm
|
||||||
|
*/
|
||||||
|
public function __construct(
|
||||||
|
$keyMaterial,
|
||||||
|
string $algorithm
|
||||||
|
) {
|
||||||
|
if (
|
||||||
|
!\is_string($keyMaterial)
|
||||||
|
&& !$keyMaterial instanceof OpenSSLAsymmetricKey
|
||||||
|
&& !$keyMaterial instanceof OpenSSLCertificate
|
||||||
|
&& !\is_resource($keyMaterial)
|
||||||
|
) {
|
||||||
|
throw new TypeError('Key material must be a string, resource, or OpenSSLAsymmetricKey');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (empty($keyMaterial)) {
|
||||||
|
throw new InvalidArgumentException('Key material must not be empty');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (empty($algorithm)) {
|
||||||
|
throw new InvalidArgumentException('Algorithm must not be empty');
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: Remove in PHP 8.0 in favor of class constructor property promotion
|
||||||
|
$this->keyMaterial = $keyMaterial;
|
||||||
|
$this->algorithm = $algorithm;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the algorithm valid for this key
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function getAlgorithm(): string
|
||||||
|
{
|
||||||
|
return $this->algorithm;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return string|resource|OpenSSLAsymmetricKey|OpenSSLCertificate
|
||||||
|
*/
|
||||||
|
public function getKeyMaterial()
|
||||||
|
{
|
||||||
|
return $this->keyMaterial;
|
||||||
|
}
|
||||||
|
}
|
||||||
7
vendor/firebase/php-jwt/src/SignatureInvalidException.php
vendored
Executable file
7
vendor/firebase/php-jwt/src/SignatureInvalidException.php
vendored
Executable file
@ -0,0 +1,7 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Firebase\JWT;
|
||||||
|
|
||||||
|
class SignatureInvalidException extends \UnexpectedValueException
|
||||||
|
{
|
||||||
|
}
|
||||||
203
vendor/google/apiclient-services/LICENSE
vendored
Executable file
203
vendor/google/apiclient-services/LICENSE
vendored
Executable file
@ -0,0 +1,203 @@
|
|||||||
|
Apache License
|
||||||
|
Version 2.0, January 2004
|
||||||
|
http://www.apache.org/licenses/
|
||||||
|
|
||||||
|
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||||
|
|
||||||
|
1. Definitions.
|
||||||
|
|
||||||
|
"License" shall mean the terms and conditions for use, reproduction,
|
||||||
|
and distribution as defined by Sections 1 through 9 of this document.
|
||||||
|
|
||||||
|
"Licensor" shall mean the copyright owner or entity authorized by
|
||||||
|
the copyright owner that is granting the License.
|
||||||
|
|
||||||
|
"Legal Entity" shall mean the union of the acting entity and all
|
||||||
|
other entities that control, are controlled by, or are under common
|
||||||
|
control with that entity. For the purposes of this definition,
|
||||||
|
"control" means (i) the power, direct or indirect, to cause the
|
||||||
|
direction or management of such entity, whether by contract or
|
||||||
|
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||||
|
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||||
|
|
||||||
|
"You" (or "Your") shall mean an individual or Legal Entity
|
||||||
|
exercising permissions granted by this License.
|
||||||
|
|
||||||
|
"Source" form shall mean the preferred form for making modifications,
|
||||||
|
including but not limited to software source code, documentation
|
||||||
|
source, and configuration files.
|
||||||
|
|
||||||
|
"Object" form shall mean any form resulting from mechanical
|
||||||
|
transformation or translation of a Source form, including but
|
||||||
|
not limited to compiled object code, generated documentation,
|
||||||
|
and conversions to other media types.
|
||||||
|
|
||||||
|
"Work" shall mean the work of authorship, whether in Source or
|
||||||
|
Object form, made available under the License, as indicated by a
|
||||||
|
copyright notice that is included in or attached to the work
|
||||||
|
(an example is provided in the Appendix below).
|
||||||
|
|
||||||
|
"Derivative Works" shall mean any work, whether in Source or Object
|
||||||
|
form, that is based on (or derived from) the Work and for which the
|
||||||
|
editorial revisions, annotations, elaborations, or other modifications
|
||||||
|
represent, as a whole, an original work of authorship. For the purposes
|
||||||
|
of this License, Derivative Works shall not include works that remain
|
||||||
|
separable from, or merely link (or bind by name) to the interfaces of,
|
||||||
|
the Work and Derivative Works thereof.
|
||||||
|
|
||||||
|
"Contribution" shall mean any work of authorship, including
|
||||||
|
the original version of the Work and any modifications or additions
|
||||||
|
to that Work or Derivative Works thereof, that is intentionally
|
||||||
|
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||||
|
or by an individual or Legal Entity authorized to submit on behalf of
|
||||||
|
the copyright owner. For the purposes of this definition, "submitted"
|
||||||
|
means any form of electronic, verbal, or written communication sent
|
||||||
|
to the Licensor or its representatives, including but not limited to
|
||||||
|
communication on electronic mailing lists, source code control systems,
|
||||||
|
and issue tracking systems that are managed by, or on behalf of, the
|
||||||
|
Licensor for the purpose of discussing and improving the Work, but
|
||||||
|
excluding communication that is conspicuously marked or otherwise
|
||||||
|
designated in writing by the copyright owner as "Not a Contribution."
|
||||||
|
|
||||||
|
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||||
|
on behalf of whom a Contribution has been received by Licensor and
|
||||||
|
subsequently incorporated within the Work.
|
||||||
|
|
||||||
|
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||||
|
this License, each Contributor hereby grants to You a perpetual,
|
||||||
|
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||||
|
copyright license to reproduce, prepare Derivative Works of,
|
||||||
|
publicly display, publicly perform, sublicense, and distribute the
|
||||||
|
Work and such Derivative Works in Source or Object form.
|
||||||
|
|
||||||
|
3. Grant of Patent License. Subject to the terms and conditions of
|
||||||
|
this License, each Contributor hereby grants to You a perpetual,
|
||||||
|
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||||
|
(except as stated in this section) patent license to make, have made,
|
||||||
|
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||||
|
where such license applies only to those patent claims licensable
|
||||||
|
by such Contributor that are necessarily infringed by their
|
||||||
|
Contribution(s) alone or by combination of their Contribution(s)
|
||||||
|
with the Work to which such Contribution(s) was submitted. If You
|
||||||
|
institute patent litigation against any entity (including a
|
||||||
|
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||||
|
or a Contribution incorporated within the Work constitutes direct
|
||||||
|
or contributory patent infringement, then any patent licenses
|
||||||
|
granted to You under this License for that Work shall terminate
|
||||||
|
as of the date such litigation is filed.
|
||||||
|
|
||||||
|
4. Redistribution. You may reproduce and distribute copies of the
|
||||||
|
Work or Derivative Works thereof in any medium, with or without
|
||||||
|
modifications, and in Source or Object form, provided that You
|
||||||
|
meet the following conditions:
|
||||||
|
|
||||||
|
(a) You must give any other recipients of the Work or
|
||||||
|
Derivative Works a copy of this License; and
|
||||||
|
|
||||||
|
(b) You must cause any modified files to carry prominent notices
|
||||||
|
stating that You changed the files; and
|
||||||
|
|
||||||
|
(c) You must retain, in the Source form of any Derivative Works
|
||||||
|
that You distribute, all copyright, patent, trademark, and
|
||||||
|
attribution notices from the Source form of the Work,
|
||||||
|
excluding those notices that do not pertain to any part of
|
||||||
|
the Derivative Works; and
|
||||||
|
|
||||||
|
(d) If the Work includes a "NOTICE" text file as part of its
|
||||||
|
distribution, then any Derivative Works that You distribute must
|
||||||
|
include a readable copy of the attribution notices contained
|
||||||
|
within such NOTICE file, excluding those notices that do not
|
||||||
|
pertain to any part of the Derivative Works, in at least one
|
||||||
|
of the following places: within a NOTICE text file distributed
|
||||||
|
as part of the Derivative Works; within the Source form or
|
||||||
|
documentation, if provided along with the Derivative Works; or,
|
||||||
|
within a display generated by the Derivative Works, if and
|
||||||
|
wherever such third-party notices normally appear. The contents
|
||||||
|
of the NOTICE file are for informational purposes only and
|
||||||
|
do not modify the License. You may add Your own attribution
|
||||||
|
notices within Derivative Works that You distribute, alongside
|
||||||
|
or as an addendum to the NOTICE text from the Work, provided
|
||||||
|
that such additional attribution notices cannot be construed
|
||||||
|
as modifying the License.
|
||||||
|
|
||||||
|
You may add Your own copyright statement to Your modifications and
|
||||||
|
may provide additional or different license terms and conditions
|
||||||
|
for use, reproduction, or distribution of Your modifications, or
|
||||||
|
for any such Derivative Works as a whole, provided Your use,
|
||||||
|
reproduction, and distribution of the Work otherwise complies with
|
||||||
|
the conditions stated in this License.
|
||||||
|
|
||||||
|
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||||
|
any Contribution intentionally submitted for inclusion in the Work
|
||||||
|
by You to the Licensor shall be under the terms and conditions of
|
||||||
|
this License, without any additional terms or conditions.
|
||||||
|
Notwithstanding the above, nothing herein shall supersede or modify
|
||||||
|
the terms of any separate license agreement you may have executed
|
||||||
|
with Licensor regarding such Contributions.
|
||||||
|
|
||||||
|
6. Trademarks. This License does not grant permission to use the trade
|
||||||
|
names, trademarks, service marks, or product names of the Licensor,
|
||||||
|
except as required for reasonable and customary use in describing the
|
||||||
|
origin of the Work and reproducing the content of the NOTICE file.
|
||||||
|
|
||||||
|
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||||
|
agreed to in writing, Licensor provides the Work (and each
|
||||||
|
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||||
|
implied, including, without limitation, any warranties or conditions
|
||||||
|
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||||
|
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||||
|
appropriateness of using or redistributing the Work and assume any
|
||||||
|
risks associated with Your exercise of permissions under this License.
|
||||||
|
|
||||||
|
8. Limitation of Liability. In no event and under no legal theory,
|
||||||
|
whether in tort (including negligence), contract, or otherwise,
|
||||||
|
unless required by applicable law (such as deliberate and grossly
|
||||||
|
negligent acts) or agreed to in writing, shall any Contributor be
|
||||||
|
liable to You for damages, including any direct, indirect, special,
|
||||||
|
incidental, or consequential damages of any character arising as a
|
||||||
|
result of this License or out of the use or inability to use the
|
||||||
|
Work (including but not limited to damages for loss of goodwill,
|
||||||
|
work stoppage, computer failure or malfunction, or any and all
|
||||||
|
other commercial damages or losses), even if such Contributor
|
||||||
|
has been advised of the possibility of such damages.
|
||||||
|
|
||||||
|
9. Accepting Warranty or Additional Liability. While redistributing
|
||||||
|
the Work or Derivative Works thereof, You may choose to offer,
|
||||||
|
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||||
|
or other liability obligations and/or rights consistent with this
|
||||||
|
License. However, in accepting such obligations, You may act only
|
||||||
|
on Your own behalf and on Your sole responsibility, not on behalf
|
||||||
|
of any other Contributor, and only if You agree to indemnify,
|
||||||
|
defend, and hold each Contributor harmless for any liability
|
||||||
|
incurred by, or claims asserted against, such Contributor by reason
|
||||||
|
of your accepting any such warranty or additional liability.
|
||||||
|
|
||||||
|
END OF TERMS AND CONDITIONS
|
||||||
|
|
||||||
|
APPENDIX: How to apply the Apache License to your work.
|
||||||
|
|
||||||
|
To apply the Apache License to your work, attach the following
|
||||||
|
boilerplate notice, with the fields enclosed by brackets "[]"
|
||||||
|
replaced with your own identifying information. (Don't include
|
||||||
|
the brackets!) The text should be enclosed in the appropriate
|
||||||
|
comment syntax for the file format. We also recommend that a
|
||||||
|
file or class name and description of purpose be included on the
|
||||||
|
same "printed page" as the copyright notice for easier
|
||||||
|
identification within third-party archives.
|
||||||
|
|
||||||
|
Copyright [yyyy] [name of copyright owner]
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
|
||||||
|
|
||||||
17
vendor/google/apiclient-services/README.md
vendored
Executable file
17
vendor/google/apiclient-services/README.md
vendored
Executable file
@ -0,0 +1,17 @@
|
|||||||
|
Google PHP API Client Services
|
||||||
|
==============================
|
||||||
|
|
||||||
|
**NOTE**: please check to see if the package you'd like to install is available in our
|
||||||
|
list of [Google cloud packages](https://cloud.google.com/php/docs/reference) first, as
|
||||||
|
these are the recommended libraries.
|
||||||
|
|
||||||
|
## Requirements
|
||||||
|
|
||||||
|
[Google API PHP Client](https://github.com/googleapis/google-api-php-client/releases)
|
||||||
|
|
||||||
|
## Usage
|
||||||
|
|
||||||
|
This library is automatically updated daily with new API changes, and tagged weekly.
|
||||||
|
It is installed as part of the
|
||||||
|
[Google API PHP Client](https://github.com/googleapis/google-api-php-client/releases)
|
||||||
|
library via Composer, which will pull down the most recent tag.
|
||||||
7
vendor/google/apiclient-services/SECURITY.md
vendored
Executable file
7
vendor/google/apiclient-services/SECURITY.md
vendored
Executable file
@ -0,0 +1,7 @@
|
|||||||
|
# Security Policy
|
||||||
|
|
||||||
|
To report a security issue, please use [g.co/vulnz](https://g.co/vulnz).
|
||||||
|
|
||||||
|
The Google Security Team will respond within 5 working days of your report on g.co/vulnz.
|
||||||
|
|
||||||
|
We use g.co/vulnz for our intake, and do coordination and disclosure here using GitHub Security Advisory to privately discuss and fix the issue.
|
||||||
36
vendor/google/apiclient-services/autoload.php
vendored
Executable file
36
vendor/google/apiclient-services/autoload.php
vendored
Executable file
@ -0,0 +1,36 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
// For older (pre-2.7.2) verions of google/apiclient
|
||||||
|
if (
|
||||||
|
file_exists(__DIR__ . '/../apiclient/src/Google/Client.php')
|
||||||
|
&& !class_exists('Google_Client', false)
|
||||||
|
) {
|
||||||
|
require_once(__DIR__ . '/../apiclient/src/Google/Client.php');
|
||||||
|
if (
|
||||||
|
defined('Google_Client::LIBVER')
|
||||||
|
&& version_compare(Google_Client::LIBVER, '2.7.2', '<=')
|
||||||
|
) {
|
||||||
|
$servicesClassMap = [
|
||||||
|
'Google\\Client' => 'Google_Client',
|
||||||
|
'Google\\Service' => 'Google_Service',
|
||||||
|
'Google\\Service\\Resource' => 'Google_Service_Resource',
|
||||||
|
'Google\\Model' => 'Google_Model',
|
||||||
|
'Google\\Collection' => 'Google_Collection',
|
||||||
|
];
|
||||||
|
foreach ($servicesClassMap as $alias => $class) {
|
||||||
|
class_alias($class, $alias);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
spl_autoload_register(function ($class) {
|
||||||
|
if (0 === strpos($class, 'Google_Service_')) {
|
||||||
|
// Autoload the new class, which will also create an alias for the
|
||||||
|
// old class by changing underscores to namespaces:
|
||||||
|
// Google_Service_Speech_Resource_Operations
|
||||||
|
// => Google\Service\Speech\Resource\Operations
|
||||||
|
$classExists = class_exists($newClass = str_replace('_', '\\', $class));
|
||||||
|
if ($classExists) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}, true, true);
|
||||||
27
vendor/google/apiclient-services/composer.json
vendored
Executable file
27
vendor/google/apiclient-services/composer.json
vendored
Executable file
@ -0,0 +1,27 @@
|
|||||||
|
{
|
||||||
|
"name": "google/apiclient-services",
|
||||||
|
"type": "library",
|
||||||
|
"description": "Client library for Google APIs",
|
||||||
|
"keywords": ["google"],
|
||||||
|
"homepage": "http://developers.google.com/api-client-library/php",
|
||||||
|
"license": "Apache-2.0",
|
||||||
|
"require": {
|
||||||
|
"php": "^8.0"
|
||||||
|
},
|
||||||
|
"require-dev": {
|
||||||
|
"phpunit/phpunit": "^9.6"
|
||||||
|
},
|
||||||
|
"autoload": {
|
||||||
|
"psr-4": {
|
||||||
|
"Google\\Service\\": "src"
|
||||||
|
},
|
||||||
|
"files": [
|
||||||
|
"autoload.php"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"autoload-dev": {
|
||||||
|
"psr-4": {
|
||||||
|
"Google\\": "tests/mocks"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
94
vendor/google/apiclient-services/src/ACMEDNS.php
vendored
Executable file
94
vendor/google/apiclient-services/src/ACMEDNS.php
vendored
Executable file
@ -0,0 +1,94 @@
|
|||||||
|
<?php
|
||||||
|
/*
|
||||||
|
* Copyright 2014 Google Inc.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
|
||||||
|
* use this file except in compliance with the License. You may obtain a copy of
|
||||||
|
* the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||||
|
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||||
|
* License for the specific language governing permissions and limitations under
|
||||||
|
* the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Google\Service;
|
||||||
|
|
||||||
|
use Google\Client;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Service definition for ACMEDNS (v1).
|
||||||
|
*
|
||||||
|
* <p>
|
||||||
|
* Google Domains ACME DNS API that allows users to complete ACME DNS-01
|
||||||
|
* challenges for a domain.</p>
|
||||||
|
*
|
||||||
|
* <p>
|
||||||
|
* For more information about this service, see the API
|
||||||
|
* <a href="https://developers.google.com/domains/acme-dns/" target="_blank">Documentation</a>
|
||||||
|
* </p>
|
||||||
|
*
|
||||||
|
* @author Google, Inc.
|
||||||
|
*/
|
||||||
|
class ACMEDNS extends \Google\Service
|
||||||
|
{
|
||||||
|
|
||||||
|
|
||||||
|
public $acmeChallengeSets;
|
||||||
|
public $rootUrlTemplate;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructs the internal representation of the ACMEDNS service.
|
||||||
|
*
|
||||||
|
* @param Client|array $clientOrConfig The client used to deliver requests, or a
|
||||||
|
* config array to pass to a new Client instance.
|
||||||
|
* @param string $rootUrl The root URL used for requests to the service.
|
||||||
|
*/
|
||||||
|
public function __construct($clientOrConfig = [], $rootUrl = null)
|
||||||
|
{
|
||||||
|
parent::__construct($clientOrConfig);
|
||||||
|
$this->rootUrl = $rootUrl ?: 'https://acmedns.googleapis.com/';
|
||||||
|
$this->rootUrlTemplate = $rootUrl ?: 'https://acmedns.UNIVERSE_DOMAIN/';
|
||||||
|
$this->servicePath = '';
|
||||||
|
$this->batchPath = 'batch';
|
||||||
|
$this->version = 'v1';
|
||||||
|
$this->serviceName = 'acmedns';
|
||||||
|
|
||||||
|
$this->acmeChallengeSets = new ACMEDNS\Resource\AcmeChallengeSets(
|
||||||
|
$this,
|
||||||
|
$this->serviceName,
|
||||||
|
'acmeChallengeSets',
|
||||||
|
[
|
||||||
|
'methods' => [
|
||||||
|
'get' => [
|
||||||
|
'path' => 'v1/acmeChallengeSets/{rootDomain}',
|
||||||
|
'httpMethod' => 'GET',
|
||||||
|
'parameters' => [
|
||||||
|
'rootDomain' => [
|
||||||
|
'location' => 'path',
|
||||||
|
'type' => 'string',
|
||||||
|
'required' => true,
|
||||||
|
],
|
||||||
|
],
|
||||||
|
],'rotateChallenges' => [
|
||||||
|
'path' => 'v1/acmeChallengeSets/{rootDomain}:rotateChallenges',
|
||||||
|
'httpMethod' => 'POST',
|
||||||
|
'parameters' => [
|
||||||
|
'rootDomain' => [
|
||||||
|
'location' => 'path',
|
||||||
|
'type' => 'string',
|
||||||
|
'required' => true,
|
||||||
|
],
|
||||||
|
],
|
||||||
|
],
|
||||||
|
]
|
||||||
|
]
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Adding a class alias for backwards compatibility with the previous class name.
|
||||||
|
class_alias(ACMEDNS::class, 'Google_Service_ACMEDNS');
|
||||||
43
vendor/google/apiclient-services/src/ACMEDNS/AcmeChallengeSet.php
vendored
Executable file
43
vendor/google/apiclient-services/src/ACMEDNS/AcmeChallengeSet.php
vendored
Executable file
@ -0,0 +1,43 @@
|
|||||||
|
<?php
|
||||||
|
/*
|
||||||
|
* Copyright 2014 Google Inc.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
|
||||||
|
* use this file except in compliance with the License. You may obtain a copy of
|
||||||
|
* the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||||
|
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||||
|
* License for the specific language governing permissions and limitations under
|
||||||
|
* the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Google\Service\ACMEDNS;
|
||||||
|
|
||||||
|
class AcmeChallengeSet extends \Google\Collection
|
||||||
|
{
|
||||||
|
protected $collection_key = 'record';
|
||||||
|
protected $recordType = AcmeTxtRecord::class;
|
||||||
|
protected $recordDataType = 'array';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param AcmeTxtRecord[]
|
||||||
|
*/
|
||||||
|
public function setRecord($record)
|
||||||
|
{
|
||||||
|
$this->record = $record;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* @return AcmeTxtRecord[]
|
||||||
|
*/
|
||||||
|
public function getRecord()
|
||||||
|
{
|
||||||
|
return $this->record;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Adding a class alias for backwards compatibility with the previous class name.
|
||||||
|
class_alias(AcmeChallengeSet::class, 'Google_Service_ACMEDNS_AcmeChallengeSet');
|
||||||
80
vendor/google/apiclient-services/src/ACMEDNS/AcmeTxtRecord.php
vendored
Executable file
80
vendor/google/apiclient-services/src/ACMEDNS/AcmeTxtRecord.php
vendored
Executable file
@ -0,0 +1,80 @@
|
|||||||
|
<?php
|
||||||
|
/*
|
||||||
|
* Copyright 2014 Google Inc.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
|
||||||
|
* use this file except in compliance with the License. You may obtain a copy of
|
||||||
|
* the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||||
|
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||||
|
* License for the specific language governing permissions and limitations under
|
||||||
|
* the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Google\Service\ACMEDNS;
|
||||||
|
|
||||||
|
class AcmeTxtRecord extends \Google\Model
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
public $digest;
|
||||||
|
/**
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
public $fqdn;
|
||||||
|
/**
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
public $updateTime;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string
|
||||||
|
*/
|
||||||
|
public function setDigest($digest)
|
||||||
|
{
|
||||||
|
$this->digest = $digest;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function getDigest()
|
||||||
|
{
|
||||||
|
return $this->digest;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* @param string
|
||||||
|
*/
|
||||||
|
public function setFqdn($fqdn)
|
||||||
|
{
|
||||||
|
$this->fqdn = $fqdn;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function getFqdn()
|
||||||
|
{
|
||||||
|
return $this->fqdn;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* @param string
|
||||||
|
*/
|
||||||
|
public function setUpdateTime($updateTime)
|
||||||
|
{
|
||||||
|
$this->updateTime = $updateTime;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function getUpdateTime()
|
||||||
|
{
|
||||||
|
return $this->updateTime;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Adding a class alias for backwards compatibility with the previous class name.
|
||||||
|
class_alias(AcmeTxtRecord::class, 'Google_Service_ACMEDNS_AcmeTxtRecord');
|
||||||
74
vendor/google/apiclient-services/src/ACMEDNS/Resource/AcmeChallengeSets.php
vendored
Executable file
74
vendor/google/apiclient-services/src/ACMEDNS/Resource/AcmeChallengeSets.php
vendored
Executable file
@ -0,0 +1,74 @@
|
|||||||
|
<?php
|
||||||
|
/*
|
||||||
|
* Copyright 2014 Google Inc.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
|
||||||
|
* use this file except in compliance with the License. You may obtain a copy of
|
||||||
|
* the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||||
|
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||||
|
* License for the specific language governing permissions and limitations under
|
||||||
|
* the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Google\Service\ACMEDNS\Resource;
|
||||||
|
|
||||||
|
use Google\Service\ACMEDNS\AcmeChallengeSet;
|
||||||
|
use Google\Service\ACMEDNS\RotateChallengesRequest;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The "acmeChallengeSets" collection of methods.
|
||||||
|
* Typical usage is:
|
||||||
|
* <code>
|
||||||
|
* $acmednsService = new Google\Service\ACMEDNS(...);
|
||||||
|
* $acmeChallengeSets = $acmednsService->acmeChallengeSets;
|
||||||
|
* </code>
|
||||||
|
*/
|
||||||
|
class AcmeChallengeSets extends \Google\Service\Resource
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Gets the ACME challenge set for a given domain name. Domain names must be
|
||||||
|
* provided in Punycode. (acmeChallengeSets.get)
|
||||||
|
*
|
||||||
|
* @param string $rootDomain Required. SLD + TLD domain name to list challenges.
|
||||||
|
* For example, this would be "google.com" for any FQDN under "google.com". That
|
||||||
|
* includes challenges for "subdomain.google.com". This MAY be Unicode or
|
||||||
|
* Punycode.
|
||||||
|
* @param array $optParams Optional parameters.
|
||||||
|
* @return AcmeChallengeSet
|
||||||
|
* @throws \Google\Service\Exception
|
||||||
|
*/
|
||||||
|
public function get($rootDomain, $optParams = [])
|
||||||
|
{
|
||||||
|
$params = ['rootDomain' => $rootDomain];
|
||||||
|
$params = array_merge($params, $optParams);
|
||||||
|
return $this->call('get', [$params], AcmeChallengeSet::class);
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Rotate the ACME challenges for a given domain name. By default, removes any
|
||||||
|
* challenges that are older than 30 days. Domain names must be provided in
|
||||||
|
* Punycode. (acmeChallengeSets.rotateChallenges)
|
||||||
|
*
|
||||||
|
* @param string $rootDomain Required. SLD + TLD domain name to update records
|
||||||
|
* for. For example, this would be "google.com" for any FQDN under "google.com".
|
||||||
|
* That includes challenges for "subdomain.google.com". This MAY be Unicode or
|
||||||
|
* Punycode.
|
||||||
|
* @param RotateChallengesRequest $postBody
|
||||||
|
* @param array $optParams Optional parameters.
|
||||||
|
* @return AcmeChallengeSet
|
||||||
|
* @throws \Google\Service\Exception
|
||||||
|
*/
|
||||||
|
public function rotateChallenges($rootDomain, RotateChallengesRequest $postBody, $optParams = [])
|
||||||
|
{
|
||||||
|
$params = ['rootDomain' => $rootDomain, 'postBody' => $postBody];
|
||||||
|
$params = array_merge($params, $optParams);
|
||||||
|
return $this->call('rotateChallenges', [$params], AcmeChallengeSet::class);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Adding a class alias for backwards compatibility with the previous class name.
|
||||||
|
class_alias(AcmeChallengeSets::class, 'Google_Service_ACMEDNS_Resource_AcmeChallengeSets');
|
||||||
95
vendor/google/apiclient-services/src/ACMEDNS/RotateChallengesRequest.php
vendored
Executable file
95
vendor/google/apiclient-services/src/ACMEDNS/RotateChallengesRequest.php
vendored
Executable file
@ -0,0 +1,95 @@
|
|||||||
|
<?php
|
||||||
|
/*
|
||||||
|
* Copyright 2014 Google Inc.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
|
||||||
|
* use this file except in compliance with the License. You may obtain a copy of
|
||||||
|
* the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||||
|
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||||
|
* License for the specific language governing permissions and limitations under
|
||||||
|
* the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Google\Service\ACMEDNS;
|
||||||
|
|
||||||
|
class RotateChallengesRequest extends \Google\Collection
|
||||||
|
{
|
||||||
|
protected $collection_key = 'recordsToRemove';
|
||||||
|
/**
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
public $accessToken;
|
||||||
|
/**
|
||||||
|
* @var bool
|
||||||
|
*/
|
||||||
|
public $keepExpiredRecords;
|
||||||
|
protected $recordsToAddType = AcmeTxtRecord::class;
|
||||||
|
protected $recordsToAddDataType = 'array';
|
||||||
|
protected $recordsToRemoveType = AcmeTxtRecord::class;
|
||||||
|
protected $recordsToRemoveDataType = 'array';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string
|
||||||
|
*/
|
||||||
|
public function setAccessToken($accessToken)
|
||||||
|
{
|
||||||
|
$this->accessToken = $accessToken;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function getAccessToken()
|
||||||
|
{
|
||||||
|
return $this->accessToken;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* @param bool
|
||||||
|
*/
|
||||||
|
public function setKeepExpiredRecords($keepExpiredRecords)
|
||||||
|
{
|
||||||
|
$this->keepExpiredRecords = $keepExpiredRecords;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
public function getKeepExpiredRecords()
|
||||||
|
{
|
||||||
|
return $this->keepExpiredRecords;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* @param AcmeTxtRecord[]
|
||||||
|
*/
|
||||||
|
public function setRecordsToAdd($recordsToAdd)
|
||||||
|
{
|
||||||
|
$this->recordsToAdd = $recordsToAdd;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* @return AcmeTxtRecord[]
|
||||||
|
*/
|
||||||
|
public function getRecordsToAdd()
|
||||||
|
{
|
||||||
|
return $this->recordsToAdd;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* @param AcmeTxtRecord[]
|
||||||
|
*/
|
||||||
|
public function setRecordsToRemove($recordsToRemove)
|
||||||
|
{
|
||||||
|
$this->recordsToRemove = $recordsToRemove;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* @return AcmeTxtRecord[]
|
||||||
|
*/
|
||||||
|
public function getRecordsToRemove()
|
||||||
|
{
|
||||||
|
return $this->recordsToRemove;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Adding a class alias for backwards compatibility with the previous class name.
|
||||||
|
class_alias(RotateChallengesRequest::class, 'Google_Service_ACMEDNS_RotateChallengesRequest');
|
||||||
411
vendor/google/apiclient-services/src/AIPlatformNotebooks.php
vendored
Executable file
411
vendor/google/apiclient-services/src/AIPlatformNotebooks.php
vendored
Executable file
@ -0,0 +1,411 @@
|
|||||||
|
<?php
|
||||||
|
/*
|
||||||
|
* Copyright 2014 Google Inc.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
|
||||||
|
* use this file except in compliance with the License. You may obtain a copy of
|
||||||
|
* the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||||
|
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||||
|
* License for the specific language governing permissions and limitations under
|
||||||
|
* the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Google\Service;
|
||||||
|
|
||||||
|
use Google\Client;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Service definition for AIPlatformNotebooks (v2).
|
||||||
|
*
|
||||||
|
* <p>
|
||||||
|
* Notebooks API is used to manage notebook resources in Google Cloud.</p>
|
||||||
|
*
|
||||||
|
* <p>
|
||||||
|
* For more information about this service, see the API
|
||||||
|
* <a href="https://cloud.google.com/notebooks/docs/" target="_blank">Documentation</a>
|
||||||
|
* </p>
|
||||||
|
*
|
||||||
|
* @author Google, Inc.
|
||||||
|
*/
|
||||||
|
class AIPlatformNotebooks extends \Google\Service
|
||||||
|
{
|
||||||
|
/** See, edit, configure, and delete your Google Cloud data and see the email address for your Google Account.. */
|
||||||
|
const CLOUD_PLATFORM =
|
||||||
|
"https://www.googleapis.com/auth/cloud-platform";
|
||||||
|
|
||||||
|
public $projects_locations;
|
||||||
|
public $projects_locations_instances;
|
||||||
|
public $projects_locations_operations;
|
||||||
|
public $rootUrlTemplate;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructs the internal representation of the AIPlatformNotebooks service.
|
||||||
|
*
|
||||||
|
* @param Client|array $clientOrConfig The client used to deliver requests, or a
|
||||||
|
* config array to pass to a new Client instance.
|
||||||
|
* @param string $rootUrl The root URL used for requests to the service.
|
||||||
|
*/
|
||||||
|
public function __construct($clientOrConfig = [], $rootUrl = null)
|
||||||
|
{
|
||||||
|
parent::__construct($clientOrConfig);
|
||||||
|
$this->rootUrl = $rootUrl ?: 'https://notebooks.googleapis.com/';
|
||||||
|
$this->rootUrlTemplate = $rootUrl ?: 'https://notebooks.UNIVERSE_DOMAIN/';
|
||||||
|
$this->servicePath = '';
|
||||||
|
$this->batchPath = 'batch';
|
||||||
|
$this->version = 'v2';
|
||||||
|
$this->serviceName = 'notebooks';
|
||||||
|
|
||||||
|
$this->projects_locations = new AIPlatformNotebooks\Resource\ProjectsLocations(
|
||||||
|
$this,
|
||||||
|
$this->serviceName,
|
||||||
|
'locations',
|
||||||
|
[
|
||||||
|
'methods' => [
|
||||||
|
'get' => [
|
||||||
|
'path' => 'v2/{+name}',
|
||||||
|
'httpMethod' => 'GET',
|
||||||
|
'parameters' => [
|
||||||
|
'name' => [
|
||||||
|
'location' => 'path',
|
||||||
|
'type' => 'string',
|
||||||
|
'required' => true,
|
||||||
|
],
|
||||||
|
],
|
||||||
|
],'list' => [
|
||||||
|
'path' => 'v2/{+name}/locations',
|
||||||
|
'httpMethod' => 'GET',
|
||||||
|
'parameters' => [
|
||||||
|
'name' => [
|
||||||
|
'location' => 'path',
|
||||||
|
'type' => 'string',
|
||||||
|
'required' => true,
|
||||||
|
],
|
||||||
|
'filter' => [
|
||||||
|
'location' => 'query',
|
||||||
|
'type' => 'string',
|
||||||
|
],
|
||||||
|
'pageSize' => [
|
||||||
|
'location' => 'query',
|
||||||
|
'type' => 'integer',
|
||||||
|
],
|
||||||
|
'pageToken' => [
|
||||||
|
'location' => 'query',
|
||||||
|
'type' => 'string',
|
||||||
|
],
|
||||||
|
],
|
||||||
|
],
|
||||||
|
]
|
||||||
|
]
|
||||||
|
);
|
||||||
|
$this->projects_locations_instances = new AIPlatformNotebooks\Resource\ProjectsLocationsInstances(
|
||||||
|
$this,
|
||||||
|
$this->serviceName,
|
||||||
|
'instances',
|
||||||
|
[
|
||||||
|
'methods' => [
|
||||||
|
'checkUpgradability' => [
|
||||||
|
'path' => 'v2/{+notebookInstance}:checkUpgradability',
|
||||||
|
'httpMethod' => 'GET',
|
||||||
|
'parameters' => [
|
||||||
|
'notebookInstance' => [
|
||||||
|
'location' => 'path',
|
||||||
|
'type' => 'string',
|
||||||
|
'required' => true,
|
||||||
|
],
|
||||||
|
],
|
||||||
|
],'create' => [
|
||||||
|
'path' => 'v2/{+parent}/instances',
|
||||||
|
'httpMethod' => 'POST',
|
||||||
|
'parameters' => [
|
||||||
|
'parent' => [
|
||||||
|
'location' => 'path',
|
||||||
|
'type' => 'string',
|
||||||
|
'required' => true,
|
||||||
|
],
|
||||||
|
'instanceId' => [
|
||||||
|
'location' => 'query',
|
||||||
|
'type' => 'string',
|
||||||
|
],
|
||||||
|
'requestId' => [
|
||||||
|
'location' => 'query',
|
||||||
|
'type' => 'string',
|
||||||
|
],
|
||||||
|
],
|
||||||
|
],'delete' => [
|
||||||
|
'path' => 'v2/{+name}',
|
||||||
|
'httpMethod' => 'DELETE',
|
||||||
|
'parameters' => [
|
||||||
|
'name' => [
|
||||||
|
'location' => 'path',
|
||||||
|
'type' => 'string',
|
||||||
|
'required' => true,
|
||||||
|
],
|
||||||
|
'requestId' => [
|
||||||
|
'location' => 'query',
|
||||||
|
'type' => 'string',
|
||||||
|
],
|
||||||
|
],
|
||||||
|
],'diagnose' => [
|
||||||
|
'path' => 'v2/{+name}:diagnose',
|
||||||
|
'httpMethod' => 'POST',
|
||||||
|
'parameters' => [
|
||||||
|
'name' => [
|
||||||
|
'location' => 'path',
|
||||||
|
'type' => 'string',
|
||||||
|
'required' => true,
|
||||||
|
],
|
||||||
|
],
|
||||||
|
],'get' => [
|
||||||
|
'path' => 'v2/{+name}',
|
||||||
|
'httpMethod' => 'GET',
|
||||||
|
'parameters' => [
|
||||||
|
'name' => [
|
||||||
|
'location' => 'path',
|
||||||
|
'type' => 'string',
|
||||||
|
'required' => true,
|
||||||
|
],
|
||||||
|
],
|
||||||
|
],'getConfig' => [
|
||||||
|
'path' => 'v2/{+name}/instances:getConfig',
|
||||||
|
'httpMethod' => 'GET',
|
||||||
|
'parameters' => [
|
||||||
|
'name' => [
|
||||||
|
'location' => 'path',
|
||||||
|
'type' => 'string',
|
||||||
|
'required' => true,
|
||||||
|
],
|
||||||
|
],
|
||||||
|
],'getIamPolicy' => [
|
||||||
|
'path' => 'v2/{+resource}:getIamPolicy',
|
||||||
|
'httpMethod' => 'GET',
|
||||||
|
'parameters' => [
|
||||||
|
'resource' => [
|
||||||
|
'location' => 'path',
|
||||||
|
'type' => 'string',
|
||||||
|
'required' => true,
|
||||||
|
],
|
||||||
|
'options.requestedPolicyVersion' => [
|
||||||
|
'location' => 'query',
|
||||||
|
'type' => 'integer',
|
||||||
|
],
|
||||||
|
],
|
||||||
|
],'list' => [
|
||||||
|
'path' => 'v2/{+parent}/instances',
|
||||||
|
'httpMethod' => 'GET',
|
||||||
|
'parameters' => [
|
||||||
|
'parent' => [
|
||||||
|
'location' => 'path',
|
||||||
|
'type' => 'string',
|
||||||
|
'required' => true,
|
||||||
|
],
|
||||||
|
'filter' => [
|
||||||
|
'location' => 'query',
|
||||||
|
'type' => 'string',
|
||||||
|
],
|
||||||
|
'orderBy' => [
|
||||||
|
'location' => 'query',
|
||||||
|
'type' => 'string',
|
||||||
|
],
|
||||||
|
'pageSize' => [
|
||||||
|
'location' => 'query',
|
||||||
|
'type' => 'integer',
|
||||||
|
],
|
||||||
|
'pageToken' => [
|
||||||
|
'location' => 'query',
|
||||||
|
'type' => 'string',
|
||||||
|
],
|
||||||
|
],
|
||||||
|
],'patch' => [
|
||||||
|
'path' => 'v2/{+name}',
|
||||||
|
'httpMethod' => 'PATCH',
|
||||||
|
'parameters' => [
|
||||||
|
'name' => [
|
||||||
|
'location' => 'path',
|
||||||
|
'type' => 'string',
|
||||||
|
'required' => true,
|
||||||
|
],
|
||||||
|
'requestId' => [
|
||||||
|
'location' => 'query',
|
||||||
|
'type' => 'string',
|
||||||
|
],
|
||||||
|
'updateMask' => [
|
||||||
|
'location' => 'query',
|
||||||
|
'type' => 'string',
|
||||||
|
],
|
||||||
|
],
|
||||||
|
],'reportInfoSystem' => [
|
||||||
|
'path' => 'v2/{+name}:reportInfoSystem',
|
||||||
|
'httpMethod' => 'POST',
|
||||||
|
'parameters' => [
|
||||||
|
'name' => [
|
||||||
|
'location' => 'path',
|
||||||
|
'type' => 'string',
|
||||||
|
'required' => true,
|
||||||
|
],
|
||||||
|
],
|
||||||
|
],'reset' => [
|
||||||
|
'path' => 'v2/{+name}:reset',
|
||||||
|
'httpMethod' => 'POST',
|
||||||
|
'parameters' => [
|
||||||
|
'name' => [
|
||||||
|
'location' => 'path',
|
||||||
|
'type' => 'string',
|
||||||
|
'required' => true,
|
||||||
|
],
|
||||||
|
],
|
||||||
|
],'resizeDisk' => [
|
||||||
|
'path' => 'v2/{+notebookInstance}:resizeDisk',
|
||||||
|
'httpMethod' => 'POST',
|
||||||
|
'parameters' => [
|
||||||
|
'notebookInstance' => [
|
||||||
|
'location' => 'path',
|
||||||
|
'type' => 'string',
|
||||||
|
'required' => true,
|
||||||
|
],
|
||||||
|
],
|
||||||
|
],'rollback' => [
|
||||||
|
'path' => 'v2/{+name}:rollback',
|
||||||
|
'httpMethod' => 'POST',
|
||||||
|
'parameters' => [
|
||||||
|
'name' => [
|
||||||
|
'location' => 'path',
|
||||||
|
'type' => 'string',
|
||||||
|
'required' => true,
|
||||||
|
],
|
||||||
|
],
|
||||||
|
],'setIamPolicy' => [
|
||||||
|
'path' => 'v2/{+resource}:setIamPolicy',
|
||||||
|
'httpMethod' => 'POST',
|
||||||
|
'parameters' => [
|
||||||
|
'resource' => [
|
||||||
|
'location' => 'path',
|
||||||
|
'type' => 'string',
|
||||||
|
'required' => true,
|
||||||
|
],
|
||||||
|
],
|
||||||
|
],'start' => [
|
||||||
|
'path' => 'v2/{+name}:start',
|
||||||
|
'httpMethod' => 'POST',
|
||||||
|
'parameters' => [
|
||||||
|
'name' => [
|
||||||
|
'location' => 'path',
|
||||||
|
'type' => 'string',
|
||||||
|
'required' => true,
|
||||||
|
],
|
||||||
|
],
|
||||||
|
],'stop' => [
|
||||||
|
'path' => 'v2/{+name}:stop',
|
||||||
|
'httpMethod' => 'POST',
|
||||||
|
'parameters' => [
|
||||||
|
'name' => [
|
||||||
|
'location' => 'path',
|
||||||
|
'type' => 'string',
|
||||||
|
'required' => true,
|
||||||
|
],
|
||||||
|
],
|
||||||
|
],'testIamPermissions' => [
|
||||||
|
'path' => 'v2/{+resource}:testIamPermissions',
|
||||||
|
'httpMethod' => 'POST',
|
||||||
|
'parameters' => [
|
||||||
|
'resource' => [
|
||||||
|
'location' => 'path',
|
||||||
|
'type' => 'string',
|
||||||
|
'required' => true,
|
||||||
|
],
|
||||||
|
],
|
||||||
|
],'upgrade' => [
|
||||||
|
'path' => 'v2/{+name}:upgrade',
|
||||||
|
'httpMethod' => 'POST',
|
||||||
|
'parameters' => [
|
||||||
|
'name' => [
|
||||||
|
'location' => 'path',
|
||||||
|
'type' => 'string',
|
||||||
|
'required' => true,
|
||||||
|
],
|
||||||
|
],
|
||||||
|
],'upgradeSystem' => [
|
||||||
|
'path' => 'v2/{+name}:upgradeSystem',
|
||||||
|
'httpMethod' => 'POST',
|
||||||
|
'parameters' => [
|
||||||
|
'name' => [
|
||||||
|
'location' => 'path',
|
||||||
|
'type' => 'string',
|
||||||
|
'required' => true,
|
||||||
|
],
|
||||||
|
],
|
||||||
|
],
|
||||||
|
]
|
||||||
|
]
|
||||||
|
);
|
||||||
|
$this->projects_locations_operations = new AIPlatformNotebooks\Resource\ProjectsLocationsOperations(
|
||||||
|
$this,
|
||||||
|
$this->serviceName,
|
||||||
|
'operations',
|
||||||
|
[
|
||||||
|
'methods' => [
|
||||||
|
'cancel' => [
|
||||||
|
'path' => 'v2/{+name}:cancel',
|
||||||
|
'httpMethod' => 'POST',
|
||||||
|
'parameters' => [
|
||||||
|
'name' => [
|
||||||
|
'location' => 'path',
|
||||||
|
'type' => 'string',
|
||||||
|
'required' => true,
|
||||||
|
],
|
||||||
|
],
|
||||||
|
],'delete' => [
|
||||||
|
'path' => 'v2/{+name}',
|
||||||
|
'httpMethod' => 'DELETE',
|
||||||
|
'parameters' => [
|
||||||
|
'name' => [
|
||||||
|
'location' => 'path',
|
||||||
|
'type' => 'string',
|
||||||
|
'required' => true,
|
||||||
|
],
|
||||||
|
],
|
||||||
|
],'get' => [
|
||||||
|
'path' => 'v2/{+name}',
|
||||||
|
'httpMethod' => 'GET',
|
||||||
|
'parameters' => [
|
||||||
|
'name' => [
|
||||||
|
'location' => 'path',
|
||||||
|
'type' => 'string',
|
||||||
|
'required' => true,
|
||||||
|
],
|
||||||
|
],
|
||||||
|
],'list' => [
|
||||||
|
'path' => 'v2/{+name}/operations',
|
||||||
|
'httpMethod' => 'GET',
|
||||||
|
'parameters' => [
|
||||||
|
'name' => [
|
||||||
|
'location' => 'path',
|
||||||
|
'type' => 'string',
|
||||||
|
'required' => true,
|
||||||
|
],
|
||||||
|
'filter' => [
|
||||||
|
'location' => 'query',
|
||||||
|
'type' => 'string',
|
||||||
|
],
|
||||||
|
'pageSize' => [
|
||||||
|
'location' => 'query',
|
||||||
|
'type' => 'integer',
|
||||||
|
],
|
||||||
|
'pageToken' => [
|
||||||
|
'location' => 'query',
|
||||||
|
'type' => 'string',
|
||||||
|
],
|
||||||
|
],
|
||||||
|
],
|
||||||
|
]
|
||||||
|
]
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Adding a class alias for backwards compatibility with the previous class name.
|
||||||
|
class_alias(AIPlatformNotebooks::class, 'Google_Service_AIPlatformNotebooks');
|
||||||
62
vendor/google/apiclient-services/src/AIPlatformNotebooks/AcceleratorConfig.php
vendored
Executable file
62
vendor/google/apiclient-services/src/AIPlatformNotebooks/AcceleratorConfig.php
vendored
Executable file
@ -0,0 +1,62 @@
|
|||||||
|
<?php
|
||||||
|
/*
|
||||||
|
* Copyright 2014 Google Inc.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
|
||||||
|
* use this file except in compliance with the License. You may obtain a copy of
|
||||||
|
* the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||||
|
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||||
|
* License for the specific language governing permissions and limitations under
|
||||||
|
* the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Google\Service\AIPlatformNotebooks;
|
||||||
|
|
||||||
|
class AcceleratorConfig extends \Google\Model
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
public $coreCount;
|
||||||
|
/**
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
public $type;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string
|
||||||
|
*/
|
||||||
|
public function setCoreCount($coreCount)
|
||||||
|
{
|
||||||
|
$this->coreCount = $coreCount;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function getCoreCount()
|
||||||
|
{
|
||||||
|
return $this->coreCount;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* @param string
|
||||||
|
*/
|
||||||
|
public function setType($type)
|
||||||
|
{
|
||||||
|
$this->type = $type;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function getType()
|
||||||
|
{
|
||||||
|
return $this->type;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Adding a class alias for backwards compatibility with the previous class name.
|
||||||
|
class_alias(AcceleratorConfig::class, 'Google_Service_AIPlatformNotebooks_AcceleratorConfig');
|
||||||
44
vendor/google/apiclient-services/src/AIPlatformNotebooks/AccessConfig.php
vendored
Executable file
44
vendor/google/apiclient-services/src/AIPlatformNotebooks/AccessConfig.php
vendored
Executable file
@ -0,0 +1,44 @@
|
|||||||
|
<?php
|
||||||
|
/*
|
||||||
|
* Copyright 2014 Google Inc.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
|
||||||
|
* use this file except in compliance with the License. You may obtain a copy of
|
||||||
|
* the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||||
|
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||||
|
* License for the specific language governing permissions and limitations under
|
||||||
|
* the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Google\Service\AIPlatformNotebooks;
|
||||||
|
|
||||||
|
class AccessConfig extends \Google\Model
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
public $externalIp;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string
|
||||||
|
*/
|
||||||
|
public function setExternalIp($externalIp)
|
||||||
|
{
|
||||||
|
$this->externalIp = $externalIp;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function getExternalIp()
|
||||||
|
{
|
||||||
|
return $this->externalIp;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Adding a class alias for backwards compatibility with the previous class name.
|
||||||
|
class_alias(AccessConfig::class, 'Google_Service_AIPlatformNotebooks_AccessConfig');
|
||||||
79
vendor/google/apiclient-services/src/AIPlatformNotebooks/Binding.php
vendored
Executable file
79
vendor/google/apiclient-services/src/AIPlatformNotebooks/Binding.php
vendored
Executable file
@ -0,0 +1,79 @@
|
|||||||
|
<?php
|
||||||
|
/*
|
||||||
|
* Copyright 2014 Google Inc.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
|
||||||
|
* use this file except in compliance with the License. You may obtain a copy of
|
||||||
|
* the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||||
|
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||||
|
* License for the specific language governing permissions and limitations under
|
||||||
|
* the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Google\Service\AIPlatformNotebooks;
|
||||||
|
|
||||||
|
class Binding extends \Google\Collection
|
||||||
|
{
|
||||||
|
protected $collection_key = 'members';
|
||||||
|
protected $conditionType = Expr::class;
|
||||||
|
protected $conditionDataType = '';
|
||||||
|
/**
|
||||||
|
* @var string[]
|
||||||
|
*/
|
||||||
|
public $members;
|
||||||
|
/**
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
public $role;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param Expr
|
||||||
|
*/
|
||||||
|
public function setCondition(Expr $condition)
|
||||||
|
{
|
||||||
|
$this->condition = $condition;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* @return Expr
|
||||||
|
*/
|
||||||
|
public function getCondition()
|
||||||
|
{
|
||||||
|
return $this->condition;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* @param string[]
|
||||||
|
*/
|
||||||
|
public function setMembers($members)
|
||||||
|
{
|
||||||
|
$this->members = $members;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* @return string[]
|
||||||
|
*/
|
||||||
|
public function getMembers()
|
||||||
|
{
|
||||||
|
return $this->members;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* @param string
|
||||||
|
*/
|
||||||
|
public function setRole($role)
|
||||||
|
{
|
||||||
|
$this->role = $role;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function getRole()
|
||||||
|
{
|
||||||
|
return $this->role;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Adding a class alias for backwards compatibility with the previous class name.
|
||||||
|
class_alias(Binding::class, 'Google_Service_AIPlatformNotebooks_Binding');
|
||||||
98
vendor/google/apiclient-services/src/AIPlatformNotebooks/BootDisk.php
vendored
Executable file
98
vendor/google/apiclient-services/src/AIPlatformNotebooks/BootDisk.php
vendored
Executable file
@ -0,0 +1,98 @@
|
|||||||
|
<?php
|
||||||
|
/*
|
||||||
|
* Copyright 2014 Google Inc.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
|
||||||
|
* use this file except in compliance with the License. You may obtain a copy of
|
||||||
|
* the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||||
|
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||||
|
* License for the specific language governing permissions and limitations under
|
||||||
|
* the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Google\Service\AIPlatformNotebooks;
|
||||||
|
|
||||||
|
class BootDisk extends \Google\Model
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
public $diskEncryption;
|
||||||
|
/**
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
public $diskSizeGb;
|
||||||
|
/**
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
public $diskType;
|
||||||
|
/**
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
public $kmsKey;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string
|
||||||
|
*/
|
||||||
|
public function setDiskEncryption($diskEncryption)
|
||||||
|
{
|
||||||
|
$this->diskEncryption = $diskEncryption;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function getDiskEncryption()
|
||||||
|
{
|
||||||
|
return $this->diskEncryption;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* @param string
|
||||||
|
*/
|
||||||
|
public function setDiskSizeGb($diskSizeGb)
|
||||||
|
{
|
||||||
|
$this->diskSizeGb = $diskSizeGb;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function getDiskSizeGb()
|
||||||
|
{
|
||||||
|
return $this->diskSizeGb;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* @param string
|
||||||
|
*/
|
||||||
|
public function setDiskType($diskType)
|
||||||
|
{
|
||||||
|
$this->diskType = $diskType;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function getDiskType()
|
||||||
|
{
|
||||||
|
return $this->diskType;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* @param string
|
||||||
|
*/
|
||||||
|
public function setKmsKey($kmsKey)
|
||||||
|
{
|
||||||
|
$this->kmsKey = $kmsKey;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function getKmsKey()
|
||||||
|
{
|
||||||
|
return $this->kmsKey;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Adding a class alias for backwards compatibility with the previous class name.
|
||||||
|
class_alias(BootDisk::class, 'Google_Service_AIPlatformNotebooks_BootDisk');
|
||||||
25
vendor/google/apiclient-services/src/AIPlatformNotebooks/BootImage.php
vendored
Executable file
25
vendor/google/apiclient-services/src/AIPlatformNotebooks/BootImage.php
vendored
Executable file
@ -0,0 +1,25 @@
|
|||||||
|
<?php
|
||||||
|
/*
|
||||||
|
* Copyright 2014 Google Inc.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
|
||||||
|
* use this file except in compliance with the License. You may obtain a copy of
|
||||||
|
* the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||||
|
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||||
|
* License for the specific language governing permissions and limitations under
|
||||||
|
* the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Google\Service\AIPlatformNotebooks;
|
||||||
|
|
||||||
|
class BootImage extends \Google\Model
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
// Adding a class alias for backwards compatibility with the previous class name.
|
||||||
|
class_alias(BootImage::class, 'Google_Service_AIPlatformNotebooks_BootImage');
|
||||||
25
vendor/google/apiclient-services/src/AIPlatformNotebooks/CancelOperationRequest.php
vendored
Executable file
25
vendor/google/apiclient-services/src/AIPlatformNotebooks/CancelOperationRequest.php
vendored
Executable file
@ -0,0 +1,25 @@
|
|||||||
|
<?php
|
||||||
|
/*
|
||||||
|
* Copyright 2014 Google Inc.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
|
||||||
|
* use this file except in compliance with the License. You may obtain a copy of
|
||||||
|
* the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||||
|
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||||
|
* License for the specific language governing permissions and limitations under
|
||||||
|
* the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Google\Service\AIPlatformNotebooks;
|
||||||
|
|
||||||
|
class CancelOperationRequest extends \Google\Model
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
// Adding a class alias for backwards compatibility with the previous class name.
|
||||||
|
class_alias(CancelOperationRequest::class, 'Google_Service_AIPlatformNotebooks_CancelOperationRequest');
|
||||||
98
vendor/google/apiclient-services/src/AIPlatformNotebooks/CheckInstanceUpgradabilityResponse.php
vendored
Executable file
98
vendor/google/apiclient-services/src/AIPlatformNotebooks/CheckInstanceUpgradabilityResponse.php
vendored
Executable file
@ -0,0 +1,98 @@
|
|||||||
|
<?php
|
||||||
|
/*
|
||||||
|
* Copyright 2014 Google Inc.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
|
||||||
|
* use this file except in compliance with the License. You may obtain a copy of
|
||||||
|
* the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||||
|
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||||
|
* License for the specific language governing permissions and limitations under
|
||||||
|
* the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Google\Service\AIPlatformNotebooks;
|
||||||
|
|
||||||
|
class CheckInstanceUpgradabilityResponse extends \Google\Model
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
public $upgradeImage;
|
||||||
|
/**
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
public $upgradeInfo;
|
||||||
|
/**
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
public $upgradeVersion;
|
||||||
|
/**
|
||||||
|
* @var bool
|
||||||
|
*/
|
||||||
|
public $upgradeable;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string
|
||||||
|
*/
|
||||||
|
public function setUpgradeImage($upgradeImage)
|
||||||
|
{
|
||||||
|
$this->upgradeImage = $upgradeImage;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function getUpgradeImage()
|
||||||
|
{
|
||||||
|
return $this->upgradeImage;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* @param string
|
||||||
|
*/
|
||||||
|
public function setUpgradeInfo($upgradeInfo)
|
||||||
|
{
|
||||||
|
$this->upgradeInfo = $upgradeInfo;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function getUpgradeInfo()
|
||||||
|
{
|
||||||
|
return $this->upgradeInfo;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* @param string
|
||||||
|
*/
|
||||||
|
public function setUpgradeVersion($upgradeVersion)
|
||||||
|
{
|
||||||
|
$this->upgradeVersion = $upgradeVersion;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function getUpgradeVersion()
|
||||||
|
{
|
||||||
|
return $this->upgradeVersion;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* @param bool
|
||||||
|
*/
|
||||||
|
public function setUpgradeable($upgradeable)
|
||||||
|
{
|
||||||
|
$this->upgradeable = $upgradeable;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
public function getUpgradeable()
|
||||||
|
{
|
||||||
|
return $this->upgradeable;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Adding a class alias for backwards compatibility with the previous class name.
|
||||||
|
class_alias(CheckInstanceUpgradabilityResponse::class, 'Google_Service_AIPlatformNotebooks_CheckInstanceUpgradabilityResponse');
|
||||||
75
vendor/google/apiclient-services/src/AIPlatformNotebooks/Config.php
vendored
Executable file
75
vendor/google/apiclient-services/src/AIPlatformNotebooks/Config.php
vendored
Executable file
@ -0,0 +1,75 @@
|
|||||||
|
<?php
|
||||||
|
/*
|
||||||
|
* Copyright 2014 Google Inc.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
|
||||||
|
* use this file except in compliance with the License. You may obtain a copy of
|
||||||
|
* the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||||
|
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||||
|
* License for the specific language governing permissions and limitations under
|
||||||
|
* the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Google\Service\AIPlatformNotebooks;
|
||||||
|
|
||||||
|
class Config extends \Google\Collection
|
||||||
|
{
|
||||||
|
protected $collection_key = 'availableImages';
|
||||||
|
protected $availableImagesType = ImageRelease::class;
|
||||||
|
protected $availableImagesDataType = 'array';
|
||||||
|
protected $defaultValuesType = DefaultValues::class;
|
||||||
|
protected $defaultValuesDataType = '';
|
||||||
|
protected $supportedValuesType = SupportedValues::class;
|
||||||
|
protected $supportedValuesDataType = '';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param ImageRelease[]
|
||||||
|
*/
|
||||||
|
public function setAvailableImages($availableImages)
|
||||||
|
{
|
||||||
|
$this->availableImages = $availableImages;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* @return ImageRelease[]
|
||||||
|
*/
|
||||||
|
public function getAvailableImages()
|
||||||
|
{
|
||||||
|
return $this->availableImages;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* @param DefaultValues
|
||||||
|
*/
|
||||||
|
public function setDefaultValues(DefaultValues $defaultValues)
|
||||||
|
{
|
||||||
|
$this->defaultValues = $defaultValues;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* @return DefaultValues
|
||||||
|
*/
|
||||||
|
public function getDefaultValues()
|
||||||
|
{
|
||||||
|
return $this->defaultValues;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* @param SupportedValues
|
||||||
|
*/
|
||||||
|
public function setSupportedValues(SupportedValues $supportedValues)
|
||||||
|
{
|
||||||
|
$this->supportedValues = $supportedValues;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* @return SupportedValues
|
||||||
|
*/
|
||||||
|
public function getSupportedValues()
|
||||||
|
{
|
||||||
|
return $this->supportedValues;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Adding a class alias for backwards compatibility with the previous class name.
|
||||||
|
class_alias(Config::class, 'Google_Service_AIPlatformNotebooks_Config');
|
||||||
62
vendor/google/apiclient-services/src/AIPlatformNotebooks/ContainerImage.php
vendored
Executable file
62
vendor/google/apiclient-services/src/AIPlatformNotebooks/ContainerImage.php
vendored
Executable file
@ -0,0 +1,62 @@
|
|||||||
|
<?php
|
||||||
|
/*
|
||||||
|
* Copyright 2014 Google Inc.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
|
||||||
|
* use this file except in compliance with the License. You may obtain a copy of
|
||||||
|
* the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||||
|
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||||
|
* License for the specific language governing permissions and limitations under
|
||||||
|
* the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Google\Service\AIPlatformNotebooks;
|
||||||
|
|
||||||
|
class ContainerImage extends \Google\Model
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
public $repository;
|
||||||
|
/**
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
public $tag;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string
|
||||||
|
*/
|
||||||
|
public function setRepository($repository)
|
||||||
|
{
|
||||||
|
$this->repository = $repository;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function getRepository()
|
||||||
|
{
|
||||||
|
return $this->repository;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* @param string
|
||||||
|
*/
|
||||||
|
public function setTag($tag)
|
||||||
|
{
|
||||||
|
$this->tag = $tag;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function getTag()
|
||||||
|
{
|
||||||
|
return $this->tag;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Adding a class alias for backwards compatibility with the previous class name.
|
||||||
|
class_alias(ContainerImage::class, 'Google_Service_AIPlatformNotebooks_ContainerImage');
|
||||||
98
vendor/google/apiclient-services/src/AIPlatformNotebooks/DataDisk.php
vendored
Executable file
98
vendor/google/apiclient-services/src/AIPlatformNotebooks/DataDisk.php
vendored
Executable file
@ -0,0 +1,98 @@
|
|||||||
|
<?php
|
||||||
|
/*
|
||||||
|
* Copyright 2014 Google Inc.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
|
||||||
|
* use this file except in compliance with the License. You may obtain a copy of
|
||||||
|
* the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||||
|
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||||
|
* License for the specific language governing permissions and limitations under
|
||||||
|
* the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Google\Service\AIPlatformNotebooks;
|
||||||
|
|
||||||
|
class DataDisk extends \Google\Model
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
public $diskEncryption;
|
||||||
|
/**
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
public $diskSizeGb;
|
||||||
|
/**
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
public $diskType;
|
||||||
|
/**
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
public $kmsKey;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string
|
||||||
|
*/
|
||||||
|
public function setDiskEncryption($diskEncryption)
|
||||||
|
{
|
||||||
|
$this->diskEncryption = $diskEncryption;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function getDiskEncryption()
|
||||||
|
{
|
||||||
|
return $this->diskEncryption;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* @param string
|
||||||
|
*/
|
||||||
|
public function setDiskSizeGb($diskSizeGb)
|
||||||
|
{
|
||||||
|
$this->diskSizeGb = $diskSizeGb;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function getDiskSizeGb()
|
||||||
|
{
|
||||||
|
return $this->diskSizeGb;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* @param string
|
||||||
|
*/
|
||||||
|
public function setDiskType($diskType)
|
||||||
|
{
|
||||||
|
$this->diskType = $diskType;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function getDiskType()
|
||||||
|
{
|
||||||
|
return $this->diskType;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* @param string
|
||||||
|
*/
|
||||||
|
public function setKmsKey($kmsKey)
|
||||||
|
{
|
||||||
|
$this->kmsKey = $kmsKey;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function getKmsKey()
|
||||||
|
{
|
||||||
|
return $this->kmsKey;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Adding a class alias for backwards compatibility with the previous class name.
|
||||||
|
class_alias(DataDisk::class, 'Google_Service_AIPlatformNotebooks_DataDisk');
|
||||||
44
vendor/google/apiclient-services/src/AIPlatformNotebooks/DataprocParameters.php
vendored
Executable file
44
vendor/google/apiclient-services/src/AIPlatformNotebooks/DataprocParameters.php
vendored
Executable file
@ -0,0 +1,44 @@
|
|||||||
|
<?php
|
||||||
|
/*
|
||||||
|
* Copyright 2014 Google Inc.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
|
||||||
|
* use this file except in compliance with the License. You may obtain a copy of
|
||||||
|
* the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||||
|
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||||
|
* License for the specific language governing permissions and limitations under
|
||||||
|
* the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Google\Service\AIPlatformNotebooks;
|
||||||
|
|
||||||
|
class DataprocParameters extends \Google\Model
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
public $cluster;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string
|
||||||
|
*/
|
||||||
|
public function setCluster($cluster)
|
||||||
|
{
|
||||||
|
$this->cluster = $cluster;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function getCluster()
|
||||||
|
{
|
||||||
|
return $this->cluster;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Adding a class alias for backwards compatibility with the previous class name.
|
||||||
|
class_alias(DataprocParameters::class, 'Google_Service_AIPlatformNotebooks_DataprocParameters');
|
||||||
44
vendor/google/apiclient-services/src/AIPlatformNotebooks/DefaultValues.php
vendored
Executable file
44
vendor/google/apiclient-services/src/AIPlatformNotebooks/DefaultValues.php
vendored
Executable file
@ -0,0 +1,44 @@
|
|||||||
|
<?php
|
||||||
|
/*
|
||||||
|
* Copyright 2014 Google Inc.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
|
||||||
|
* use this file except in compliance with the License. You may obtain a copy of
|
||||||
|
* the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||||
|
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||||
|
* License for the specific language governing permissions and limitations under
|
||||||
|
* the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Google\Service\AIPlatformNotebooks;
|
||||||
|
|
||||||
|
class DefaultValues extends \Google\Model
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
public $machineType;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string
|
||||||
|
*/
|
||||||
|
public function setMachineType($machineType)
|
||||||
|
{
|
||||||
|
$this->machineType = $machineType;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function getMachineType()
|
||||||
|
{
|
||||||
|
return $this->machineType;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Adding a class alias for backwards compatibility with the previous class name.
|
||||||
|
class_alias(DefaultValues::class, 'Google_Service_AIPlatformNotebooks_DefaultValues');
|
||||||
60
vendor/google/apiclient-services/src/AIPlatformNotebooks/DiagnoseInstanceRequest.php
vendored
Executable file
60
vendor/google/apiclient-services/src/AIPlatformNotebooks/DiagnoseInstanceRequest.php
vendored
Executable file
@ -0,0 +1,60 @@
|
|||||||
|
<?php
|
||||||
|
/*
|
||||||
|
* Copyright 2014 Google Inc.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
|
||||||
|
* use this file except in compliance with the License. You may obtain a copy of
|
||||||
|
* the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||||
|
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||||
|
* License for the specific language governing permissions and limitations under
|
||||||
|
* the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Google\Service\AIPlatformNotebooks;
|
||||||
|
|
||||||
|
class DiagnoseInstanceRequest extends \Google\Model
|
||||||
|
{
|
||||||
|
protected $diagnosticConfigType = DiagnosticConfig::class;
|
||||||
|
protected $diagnosticConfigDataType = '';
|
||||||
|
/**
|
||||||
|
* @var int
|
||||||
|
*/
|
||||||
|
public $timeoutMinutes;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param DiagnosticConfig
|
||||||
|
*/
|
||||||
|
public function setDiagnosticConfig(DiagnosticConfig $diagnosticConfig)
|
||||||
|
{
|
||||||
|
$this->diagnosticConfig = $diagnosticConfig;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* @return DiagnosticConfig
|
||||||
|
*/
|
||||||
|
public function getDiagnosticConfig()
|
||||||
|
{
|
||||||
|
return $this->diagnosticConfig;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* @param int
|
||||||
|
*/
|
||||||
|
public function setTimeoutMinutes($timeoutMinutes)
|
||||||
|
{
|
||||||
|
$this->timeoutMinutes = $timeoutMinutes;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* @return int
|
||||||
|
*/
|
||||||
|
public function getTimeoutMinutes()
|
||||||
|
{
|
||||||
|
return $this->timeoutMinutes;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Adding a class alias for backwards compatibility with the previous class name.
|
||||||
|
class_alias(DiagnoseInstanceRequest::class, 'Google_Service_AIPlatformNotebooks_DiagnoseInstanceRequest');
|
||||||
43
vendor/google/apiclient-services/src/AIPlatformNotebooks/DiagnoseRuntimeRequest.php
vendored
Executable file
43
vendor/google/apiclient-services/src/AIPlatformNotebooks/DiagnoseRuntimeRequest.php
vendored
Executable file
@ -0,0 +1,43 @@
|
|||||||
|
<?php
|
||||||
|
/*
|
||||||
|
* Copyright 2014 Google Inc.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
|
||||||
|
* use this file except in compliance with the License. You may obtain a copy of
|
||||||
|
* the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||||
|
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||||
|
* License for the specific language governing permissions and limitations under
|
||||||
|
* the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Google\Service\AIPlatformNotebooks;
|
||||||
|
|
||||||
|
class DiagnoseRuntimeRequest extends \Google\Model
|
||||||
|
{
|
||||||
|
protected $diagnosticConfigType = DiagnosticConfig::class;
|
||||||
|
protected $diagnosticConfigDataType = '';
|
||||||
|
public $diagnosticConfig;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param DiagnosticConfig
|
||||||
|
*/
|
||||||
|
public function setDiagnosticConfig(DiagnosticConfig $diagnosticConfig)
|
||||||
|
{
|
||||||
|
$this->diagnosticConfig = $diagnosticConfig;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* @return DiagnosticConfig
|
||||||
|
*/
|
||||||
|
public function getDiagnosticConfig()
|
||||||
|
{
|
||||||
|
return $this->diagnosticConfig;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Adding a class alias for backwards compatibility with the previous class name.
|
||||||
|
class_alias(DiagnoseRuntimeRequest::class, 'Google_Service_AIPlatformNotebooks_DiagnoseRuntimeRequest');
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user