File: /var/www/vhost/disk-apps/teamdemo.sports-crowd.com/app/Core/Order/Application/OrderService.php
<?php
declare(strict_types=1);
namespace App\Core\Order\Application;
use App\AcademyUser;
use App\Core\Order\OrderStatusEnum;
use App\Core\Payment\Entities\Amount;
use App\Core\Payment\Entities\Payment;
use App\Core\Payment\Entities\PaymentRetrieveResponse;
use App\Core\Payment\Entities\Student;
use App\Core\Payment\PaymentMethodContext;
use App\Core\Payment\PaymentStatusEnum;
use App\Core\User\Application\UserService;
use App\Events\Order\OrderProcessesEvent;
use App\Events\Payment\PaymentConfirmed;
use App\Http\Controllers\Api\LealPayController;
use App\Http\Controllers\CollectionInvoiceController;
use App\Http\Controllers\OrderController;
use App\Order;
use App\OrderProduct;
use App\ProductTagAssign;
use App\UserTag;
use Carbon\Carbon;
class OrderService
{
private $userService;
public function __construct()
{
$this->userService = new UserService();
}
public function find(int $id)
{
return Order::findOrFail($id);
}
public function getByReference(string $reference)
{
return Order::where('gw_code_transaction', $reference)->first();
}
public function getByPin(string $pin)
{
return Order::where("code", $pin)->first();
}
public function getByPaymentGatewayTxId(string $txId)
{
return Order::where('payment_transaction_id', $txId)->first();
}
public function setOrderAsConfirmed($order)
{
$order->gw_state = OrderStatusEnum::CONFIRMED;
$order->update();
}
public function setOrderAsPending($order)
{
$order->gw_code_transaction = strtoupper(hash("md5", (string) $order->id)) . '_' . $order->code;
$order->gw_state = OrderStatusEnum::PENDING;
$order->update();
}
public function setPaymentGatewayTxId($order, $paymentGatewayTxId)
{
$order->payment_transaction_id = $paymentGatewayTxId;
$order->update();
}
public function setPaymentGatewayId($order, int $paymentGatewayId)
{
$order->gateway_payments_id = $paymentGatewayId;
$order->update();
}
public function buildPayment($order): Payment
{
$customer = $this->userService->buildCustomerFromUserId($order->client_id);
$payment = new Payment(
$order->id,
$order->code,
$order->gw_code_transaction,
"Pago de producto de tienda",
new Amount($order->total_price),
$customer
);
$payment->setPaymentGatewayId($order->gateway_payments_id);
$payment->setPaymentGatewayTxId($order->payment_transaction_id);
$payment->setPaymentGatewayStatus($order->gw_state);
if ($order->extra_params) {
$extraParams = json_decode($order->extra_params);
if ($extraParams->academyUserId) {
$academyUser = AcademyUser::find($extraParams->academyUserId);
if ($academyUser) {
$payment->setStudent(new Student(
$academyUser->user_id,
$academyUser->identification,
$academyUser->student_academy_code,
$academyUser->academy_category->academy_location->name
));
}
}
}
return $payment;
}
public function validatePayment($order): PaymentRetrieveResponse
{
$this->increasePaymentAttemps($order);
$payment = $this->buildPayment($order);
if ($payment->paymentGatewayStatus() == PaymentStatusEnum::CONFIRMED) {
$retrieveResponse = new PaymentRetrieveResponse(
(string) $payment->id(),
$payment->paymentGatewayStatus(),
$order->payment_comment
);
$retrieveResponse->setRawData(json_decode($order->gateway_response ?? ''));
return $retrieveResponse;
}
$paymentContext = PaymentMethodContext::init($order->gateway_payments_id);
$paymentMethodResponse = $paymentContext->retrieveOrderPayment($order);
if ($paymentMethodResponse->status() == PaymentStatusEnum::CONFIRMED) {
$this->confirmPayment($order, $paymentMethodResponse);
event(new PaymentConfirmed($payment));
} else {
$this->voidPayment($order, $paymentMethodResponse);
}
$order->gateway_response = json_encode($paymentMethodResponse->rawData());
$order->save();
return $paymentMethodResponse;
}
public function isPaymentConfirmed($order)
{
return $order->gw_state == OrderStatusEnum::CONFIRMED;
}
public function dispatchOrderProcesses($order)
{
OrderProcessesEvent::dispatch($order);
}
public function executeOrderProcesses($order)
{
$this->validateUserPointsAccumulation($order);
$this->validateCreditCollectionInvoice($order);
$this->validateProductSegmentationOrder($order);
}
private function validateCreditCollectionInvoice($order)
{
$invoice = new CollectionInvoiceController();
$invoice->validateCreditCollectionInvoice($order->gateway_payments_id, $order->gw_code_transaction, $order->payment_transaction_id, 'order', $order->total_price);
}
private function validateUserPointsAccumulation($order)
{
$pay = new LealPayController();
$pay->validateUserPointsAccumulation($order);
}
private function validateProductSegmentationOrder($order)
{
$products = OrderProduct::where('order_id', $order->id)->get();
foreach ($products as $product) {
$tags = ProductTagAssign::where('product_id', $product->product_id)->pluck('tag_id');
if (count($tags) > 0) {
$this->assignProductTags($order, $tags);
}
}
}
private function assignProductTags($order, $tags)
{
$academyUserId = $this->validateExtraParamsOrder($order);
foreach ($tags as $tag) {
UserTag::updateOrCreate(
['tag_id' => $tag, 'user_id' => $order->client_id, 'academy_user_id' => $academyUserId],
['tag_id' => $tag, 'user_id' => $order->client_id, 'academy_user_id' => $academyUserId]
);
}
}
private function validateExtraParamsOrder($order)
{
$academyUserId = null;
if ($order->extra_params) {
$extraParams = json_decode($order->extra_params, true);
if (isset($extraParams['academyUserId'])) {
$academyUserId = $extraParams['academyUserId'];
}
}
return $academyUserId;
}
private function confirmPayment($order, PaymentRetrieveResponse $paymentMethodResponse)
{
$this->updatePayment(
$order->gw_code_transaction,
$paymentMethodResponse->status(),
2,
$paymentMethodResponse->message(),
$paymentMethodResponse->id()
);
}
private function voidPayment($order, PaymentRetrieveResponse $paymentMethodResponse)
{
$this->updatePayment(
$order->gw_code_transaction,
$paymentMethodResponse->status(),
7,
$paymentMethodResponse->message(),
$paymentMethodResponse->id()
);
}
// TODO: check for refactor
private function updatePayment(
$paymentReference,
$paymentState,
$orderStateId,
$paymentComment,
$paymentTransactionId
) {
$orderController = new OrderController();
$orderController->updateOrderByPaymentReference(
$paymentReference,
$paymentState,
$orderStateId,
$paymentComment,
$paymentTransactionId
);
}
private function increasePaymentAttemps($order)
{
$order->payment_attempts = $order->payment_attempts + 1;
$order->update();
}
public function isProcessingPayment($order)
{
return $order->gw_state == OrderStatusEnum::PENDING && $order->gw_code_transaction != PaymentStatusEnum::PENDING && Carbon::now()->lessThan(Carbon::parse($order->updated_at)->addMinutes(30));
}
}