Files
oficial/app/src/Service/Venta/MediosPago/Toku.php

267 lines
9.3 KiB
PHP
Raw Normal View History

2025-05-08 17:17:49 -04:00
<?php
2025-05-10 12:38:14 -04:00
namespace Incoviba\Service\Venta\MediosPago;
2025-05-08 17:17:49 -04:00
use Incoviba\Common\Ideal;
use Incoviba\Common\Implement\Exception\EmptyResponse;
2025-05-09 18:03:33 -04:00
use Incoviba\Exception\InvalidResult;
2025-05-10 12:38:14 -04:00
use Incoviba\Model;
2025-05-09 18:03:33 -04:00
use Incoviba\Model\Persona;
use Incoviba\Model\Venta\Propietario;
2025-05-10 12:38:14 -04:00
use InvalidArgumentException;
use Psr\Log\LoggerInterface;
2025-05-08 17:17:49 -04:00
class Toku extends Ideal\Service
{
const string CUSTOMER = 'customer';
const string SUBSCRIPTION = 'subscription';
const string INVOICE = 'invoice';
protected EndPoint $customer;
protected EndPoint $subscription;
protected EndPoint $invoice;
public function register(string $type, EndPoint $endPoint): self
{
if (!in_array(strtolower($type), ['customer', 'subscription', 'invoice'])) {
throw new InvalidArgumentException("{$type} is not a valid type of EndPoint for " . __CLASS__);
}
$this->{strtolower($type)} = $endPoint;
return $this;
}
/**
2025-05-09 18:03:33 -04:00
* @param Persona|Propietario $persona
2025-05-08 17:17:49 -04:00
* @return array
2025-05-09 18:03:33 -04:00
* @throws InvalidResult
2025-05-08 17:17:49 -04:00
*/
public function sendPersona(Model\Persona|Model\Venta\Propietario $persona): array
{
$rut = implode('', [$persona->rut, strtoupper($persona->dv)]);
try {
return $this->customer->getById($rut);
2025-05-09 18:03:33 -04:00
} catch (InvalidResult $exception) {
2025-05-08 17:17:49 -04:00
$datos = $persona->datos;
$customerData = [
'rut' => $rut,
'nombreCompleto' => $persona->nombreCompleto(),
'email' => $datos?->email ?? '',
'telefono' => $datos?->telefono ?? ''
];
2025-05-09 18:03:33 -04:00
try {
if (!$this->customer->add($customerData)) {
throw new InvalidResult("Could not save Customer for Persona {$rut}", 409, $exception);
}
} catch (EmptyResponse $exception) {
throw new InvalidResult("Could not save Customer for Persona {$rut}", 409, $exception);
2025-05-08 17:17:49 -04:00
}
return $this->customer->getById($rut);
}
}
/**
* @param Model\Venta $venta
2025-05-09 18:03:33 -04:00
* @return array
* @throws InvalidResult
2025-05-08 17:17:49 -04:00
*/
public function sendVenta(Model\Venta $venta): array
{
$customer = $this->sendPersona($venta->propietario());
try {
return $this->subscription->getById($venta->id);
2025-05-09 18:03:33 -04:00
} catch (InvalidResult $exception) {
2025-05-08 17:17:49 -04:00
$subscriptionData = [
'customer' => $customer['toku_id'],
'product_id' => $venta->id,
'venta' => $venta
];
2025-05-09 18:03:33 -04:00
try {
if (!$this->subscription->add($subscriptionData)) {
throw new InvalidResult("Could not save Subscription for Venta {$venta->id}", 409, $exception);
}
} catch (EmptyResponse $exception) {
throw new InvalidResult("Could not save Subscription for Venta {$venta->id}", 409, $exception);
2025-05-08 17:17:49 -04:00
}
return $this->subscription->getById($venta->id);
}
}
/**
* @param Model\Venta $venta
2025-05-09 18:03:33 -04:00
* @param array $cuotas_ids
2025-05-08 17:17:49 -04:00
* @return array
2025-05-09 18:03:33 -04:00
* @throws InvalidResult
2025-05-08 17:17:49 -04:00
*/
2025-05-09 18:03:33 -04:00
public function sendCuotas(Model\Venta $venta, array $cuotas_ids = []): array
2025-05-08 17:17:49 -04:00
{
$customer = $this->sendPersona($venta->propietario());
$subscription = $this->sendVenta($venta);
$invoices = [];
$errors = [];
foreach ($venta->formaPago()->pie->cuotas() as $cuota) {
2025-05-09 18:03:33 -04:00
if (count($cuotas_ids) > 0 and !in_array($cuota->id, $cuotas_ids)) {
continue;
}
2025-05-08 17:17:49 -04:00
try {
$invoices []= $this->invoice->getById($cuota->id);
2025-05-09 18:03:33 -04:00
} catch (InvalidResult $exception) {
2025-05-08 17:17:49 -04:00
try {
$invoiceData = [
'customer' => $customer['toku_id'],
'product_id' => $venta->id,
'subscription' => $subscription['toku_id'],
'cuota' => $cuota
];
if (!$this->invoice->add($invoiceData)) {
throw new EmptyResponse("Could not add Invoice for Cuota {$cuota->id}", $exception);
}
$invoices []= $this->invoice->getById($cuota->id);
} catch (EmptyResponse $exception) {
$this->logger->warning($exception);
$errors []= $exception;
}
}
}
if (count($errors) > 0) {
$this->logger->warning("Revisar el envío de cuotas de la Venta {$venta->id}");
}
return $invoices;
}
2025-05-09 18:03:33 -04:00
2025-05-12 19:46:09 -04:00
/**
* @param array $input
* @return bool
* @throws InvalidResult
*/
public function successEvent(array $input): bool
{
$validEvents = ['payment_intent.succeeded', 'payment.succeeded', 'transaction.success',
'transaction.bulk_success', 'payment_intent.succeeded_batch'];
if (!in_array($input['event_type'], $validEvents)) {
throw new InvalidResult("{$input['event_type']} is not a valid event", 422);
}
switch ($input['event_type']) {
case 'payment_intent.succeeded_batch':
case 'transaction.bulk_success':
return $this->successBulk($input);
case 'transaction.success':
return $this->successTransaction($input);
default:
$paymentData = $this->mapEventData($input);
return $this->updatePago($paymentData);
}
}
2025-05-09 18:03:33 -04:00
/**
* @param array $request
* @return bool
* @throws InvalidResult
*/
2025-05-12 19:46:09 -04:00
protected function updatePago(array $request): bool
2025-05-09 18:03:33 -04:00
{
# If $customer is not found, it will throw an exception and stop
$customer = $this->customer->getByExternalId($request['customer']);
$invoice = $this->invoice->getByExternalId($request['invoice']);
return $this->invoice->update($invoice['id'], $request);
}
2025-05-12 19:46:09 -04:00
protected function successTransaction(array $input): bool
{
$intents = $this->mapMultiplePaymentIntentsData($input);
$errors = [];
foreach ($intents as $intent) {
if (!$this->updatePago($intent)) {
$errors []= $intent;
}
}
if (array_key_exists('wallet_movements', $input)) {
foreach ($input['wallet_movements'] as $walletMovement) {
if (array_key_exists('type', $walletMovement) and $walletMovement['type'] === 'SURPLUS') {
$this->logger->alert('Revisar el envío de cuotas de la Venta ' . $walletMovement['product_id']);
}
}
}
return count($errors) === 0;
}
/**
* @param array $input
* @return bool
* @throws InvalidResult
*/
protected function successBulk(array $input): bool
{
return match($input['event_type']) {
'payment_intent.succeeded_batch' => $this->successBulkPaymentIntent($input),
'transaction.bulk_success' => $this->successBulkTransaction($input),
default => false
};
}
/**
* @param array $input
* @return bool
* @throws InvalidResult
*/
protected function successBulkTransaction(array $input): bool
{
$errors = [];
foreach($input['events'] as $event) {
$event['event_type'] = 'transaction.success';
if (!$this->successEvent($event)) {
$errors []= $event;
}
}
return count($errors) === 0;
}
/**
* @param array $input
* @return bool
* @throws InvalidResult
*/
protected function successBulkPaymentIntent(array $input): bool
{
$errors = [];
foreach($input['payment_intent'] as $intent) {
$intent['event_type'] = 'payment_intent.succeeded';
$intent['payment_intent'] = $input['payment_intents'];
unset($intent['payment_intents']);
if (!$this->successEvent($intent)) {
$errors []= $intent;
}
}
return count($errors) === 0;
}
protected function mapEventData(array $input): array
{
return match ($input['event_type']) {
'payment_intent.succeeded' => $this->mapPaymentIntentData($input),
'payment.succeeded' => $this->mapPaymentEventData($input),
default => [],
};
}
protected function mapMultiplePaymentIntentsData(array $input): array
{
$output = [];
foreach ($input['payment_intents'] as $intent) {
$intent['transaction_date'] = $input['transaction']['transaction_date'];
$intent['customer'] = $input['customer']['id'];
$intent['invoice'] = $intent['id_invoice'];
$intent['subscription'] = $intent['id_subscription'];
$intent['cuota_id'] = $intent['invoice_external_id'];
$o = $this->mapPaymentIntentData($intent);
$output []= $o;
}
return $output;
}
protected function mapPaymentEventData(array $input): array
{
$data = $input['payment'];
$data['status'] = 'AUTHORIZED';
$data['date'] = $data['payment_date'];
return $data;
}
protected function mapPaymentIntentData(array $input): array
{
$data = $input['payment_intent'];
$data['date'] = $data['transaction_date'];
return $data;
}
2025-05-08 17:17:49 -04:00
}