{strtolower($type)} = $endPoint; return $this; } /** * @param Persona|Propietario $persona * @return array * @throws InvalidResult */ public function sendPersona(Model\Persona|Model\Venta\Propietario $persona): array { $rut = implode('', [$persona->rut, strtoupper($persona->dv)]); try { return $this->customer->getById($rut); } catch (InvalidResult $exception) { $datos = $persona->datos; $customerData = [ 'rut' => $rut, 'nombreCompleto' => $persona->nombreCompleto(), 'email' => $datos?->email ?? '', 'telefono' => $datos?->telefono ?? '' ]; 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); } return $this->customer->getById($rut); } } /** * @param Model\Venta $venta * @return array * @throws InvalidResult */ public function sendVenta(Model\Venta $venta): array { $customer = $this->sendPersona($venta->propietario()); try { return $this->subscription->getById($venta->id); } catch (InvalidResult $exception) { $subscriptionData = [ 'customer' => $customer['toku_id'], 'product_id' => $venta->id, 'venta' => $venta ]; 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); } return $this->subscription->getById($venta->id); } } /** * @param Model\Venta $venta * @param array $cuotas_ids * @return array * @throws InvalidResult */ public function sendCuotas(Model\Venta $venta, array $cuotas_ids = []): array { $customer = $this->sendPersona($venta->propietario()); $subscription = $this->sendVenta($venta); $invoices = []; $errors = []; foreach ($venta->formaPago()->pie->cuotas() as $cuota) { if (count($cuotas_ids) > 0 and !in_array($cuota->id, $cuotas_ids)) { continue; } try { $invoices []= $this->invoice->getById($cuota->id); } catch (InvalidResult $exception) { 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; } /** * @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); } } /** * @param array $request * @return bool * @throws InvalidResult */ protected function updatePago(array $request): bool { # 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['toku_id'], $request); } 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']; if (!array_key_exists('amount', $data) and array_key_exists('payment_amount', $data)) { $data['amount'] = $data['payment_amount']; } $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; } }