fix: Corregir autenticación API, bypass de pago y relaciones de modelos
- Corregir middleware Authenticate para retornar JSON 401 en rutas API - Agregar método unauthenticated() en Handler para respuestas JSON - Implementar bypass de pago en ContractController - Corregir relaciones belongsToMany en Postulations y Suppliers - Corregir concatenación de strings en NoHomeController Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -4,6 +4,7 @@ namespace App\Exceptions;
|
|||||||
|
|
||||||
use Throwable;
|
use Throwable;
|
||||||
use Illuminate\Foundation\Exceptions\Handler as ExceptionHandler;
|
use Illuminate\Foundation\Exceptions\Handler as ExceptionHandler;
|
||||||
|
use Illuminate\Auth\AuthenticationException;
|
||||||
|
|
||||||
class Handler extends ExceptionHandler
|
class Handler extends ExceptionHandler
|
||||||
{
|
{
|
||||||
@@ -48,4 +49,21 @@ class Handler extends ExceptionHandler
|
|||||||
{
|
{
|
||||||
return parent::render($request, $exception);
|
return parent::render($request, $exception);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Convert an authentication exception into a response.
|
||||||
|
*
|
||||||
|
* @param \Illuminate\Http\Request $request
|
||||||
|
* @param \Illuminate\Auth\AuthenticationException $exception
|
||||||
|
* @return \Illuminate\Http\Response
|
||||||
|
*/
|
||||||
|
protected function unauthenticated($request, AuthenticationException $exception)
|
||||||
|
{
|
||||||
|
// Para rutas API, siempre retornar JSON
|
||||||
|
if ($request->is('api/*') || $request->expectsJson()) {
|
||||||
|
return response()->json(['message' => 'Unauthenticated.'], 401);
|
||||||
|
}
|
||||||
|
|
||||||
|
return redirect()->guest(route('login'));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -159,28 +159,50 @@ class ContractController extends Controller
|
|||||||
|
|
||||||
public function create(Request $request) {
|
public function create(Request $request) {
|
||||||
|
|
||||||
$rules = [
|
// Si el bypass está activo, usar reglas relajadas
|
||||||
'postulation_id' => 'required|numeric',
|
$paymentBypass = env('PAYMENT_BYPASS', false);
|
||||||
'supplier_id' => 'required|numeric',
|
|
||||||
'card_id' => 'required|numeric',
|
if ($paymentBypass) {
|
||||||
'code' => 'required|numeric',
|
$rules = [
|
||||||
'device_id' => 'required|string|regex:/(^[A-Za-z0-9 ]+$)+/',
|
'postulation_id' => 'required|numeric',
|
||||||
'coupon' => 'nullable|string|regex:/(^[A-Za-z0-9 ]+$)+/',
|
'supplier_id' => 'required|numeric',
|
||||||
];
|
'card_id' => 'required|string',
|
||||||
|
'code' => 'required|string',
|
||||||
|
'device_id' => 'required|string',
|
||||||
|
'coupon' => 'nullable|string',
|
||||||
|
];
|
||||||
|
} else {
|
||||||
|
$rules = [
|
||||||
|
'postulation_id' => 'required|numeric',
|
||||||
|
'supplier_id' => 'required|numeric',
|
||||||
|
'card_id' => 'required|numeric',
|
||||||
|
'code' => 'required|numeric',
|
||||||
|
'device_id' => 'required|string|regex:/(^[A-Za-z0-9 ]+$)+/',
|
||||||
|
'coupon' => 'nullable|string|regex:/(^[A-Za-z0-9 ]+$)+/',
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
$validator = Validator::make($request->all(), $rules);
|
$validator = Validator::make($request->all(), $rules);
|
||||||
if ($validator->fails()) {
|
if ($validator->fails()) {
|
||||||
|
// Para rutas API, retornar JSON en lugar de redirect
|
||||||
|
if ($request->is('api/*') || $request->expectsJson()) {
|
||||||
|
return response()->json(['type' => 'error', 'message' => $validator->errors()->first()], 422);
|
||||||
|
}
|
||||||
return redirect()->back()->withInput($request->all())->withErrors($validator);
|
return redirect()->back()->withInput($request->all())->withErrors($validator);
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
$user = Auth::user();
|
$user = Auth::user();
|
||||||
$postulation = Postulations::where('id', $request->postulation_id)->first();
|
$postulation = Postulations::where('id', $request->postulation_id)->first();
|
||||||
$coupon = Coupon::where('name', $request->coupon)->first();
|
$coupon = Coupon::where('name', $request->coupon)->first();
|
||||||
Openpay::setProductionMode(true);
|
|
||||||
|
if (!$paymentBypass) {
|
||||||
|
Openpay::setProductionMode(true);
|
||||||
|
}
|
||||||
|
|
||||||
if ($user->id == $postulation->user_id) {
|
if ($user->id == $postulation->user_id) {
|
||||||
|
|
||||||
if ($request->card_id) {
|
$card = null;
|
||||||
|
if (!$paymentBypass && $request->card_id) {
|
||||||
$card = Cards::where('id', $request->card_id)->first();
|
$card = Cards::where('id', $request->card_id)->first();
|
||||||
}
|
}
|
||||||
$supplier = Suppliers::where('id', $request->supplier_id)->first();
|
$supplier = Suppliers::where('id', $request->supplier_id)->first();
|
||||||
@@ -191,7 +213,8 @@ class ContractController extends Controller
|
|||||||
$ichambafee = iChambaParameter::where('parameter', 'ichamba_fee')->first();
|
$ichambafee = iChambaParameter::where('parameter', 'ichamba_fee')->first();
|
||||||
$category = Categories::where('id', $postulation->category_id)->first();
|
$category = Categories::where('id', $postulation->category_id)->first();
|
||||||
|
|
||||||
if ($card->user_id == $user->id) {
|
// En modo bypass, saltar la validación de tarjeta
|
||||||
|
if ($paymentBypass || ($card && $card->user_id == $user->id)) {
|
||||||
|
|
||||||
$contract = new CurrentContracts();
|
$contract = new CurrentContracts();
|
||||||
$contract->user_id = $postulation->user_id;
|
$contract->user_id = $postulation->user_id;
|
||||||
@@ -232,14 +255,17 @@ class ContractController extends Controller
|
|||||||
$discount = (($fee*(($coupon->percentage = null ? 0 : $coupon->percentage)/100))+($coupon->amount = null ? 0 : $coupon->amount));
|
$discount = (($fee*(($coupon->percentage = null ? 0 : $coupon->percentage)/100))+($coupon->amount = null ? 0 : $coupon->amount));
|
||||||
|
|
||||||
$contract->coupon_id = $coupon->id;
|
$contract->coupon_id = $coupon->id;
|
||||||
$chargeData = array(
|
// Solo crear chargeData si no estamos en bypass mode
|
||||||
'source_id' => $card->token,
|
if (!$paymentBypass && $card) {
|
||||||
'method' => 'card',
|
$chargeData = array(
|
||||||
'amount' => ((($supplier->minimun_fee < 150 ? 150 : $supplier->minimun_fee)*(1 - (($coupon->percentage = null ? 0 : $coupon->percentage)/100)))-($coupon->amount = null ? 0 : $coupon->amount)),
|
'source_id' => $card->token,
|
||||||
'description' => ('Contrato del usuario: ' . $user->name . ' del servicio ' . $category->name . ' realizado por el proveedor: ' . $supplier->company_name),
|
'method' => 'card',
|
||||||
'device_session_id' => $request->device_id,
|
'amount' => ((($supplier->minimun_fee < 150 ? 150 : $supplier->minimun_fee)*(1 - (($coupon->percentage = null ? 0 : $coupon->percentage)/100)))-($coupon->amount = null ? 0 : $coupon->amount)),
|
||||||
'cvv2' => $request->code
|
'description' => ('Contrato del usuario: ' . $user->name . ' del servicio ' . $category->name . ' realizado por el proveedor: ' . $supplier->company_name),
|
||||||
);
|
'device_session_id' => $request->device_id,
|
||||||
|
'cvv2' => $request->code
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@@ -248,61 +274,69 @@ class ContractController extends Controller
|
|||||||
$discount = 0;
|
$discount = 0;
|
||||||
|
|
||||||
$contract->coupon_id = null;
|
$contract->coupon_id = null;
|
||||||
$chargeData = array(
|
// Solo crear chargeData si no estamos en bypass mode
|
||||||
'source_id' => $card->token,
|
if (!$paymentBypass && $card) {
|
||||||
'method' => 'card',
|
$chargeData = array(
|
||||||
'amount' => ($supplier->minimun_fee < 150 ? 150 : $supplier->minimun_fee),
|
'source_id' => $card->token,
|
||||||
'description' => ('Contrato del usuario: ' . $user->name . ' del servicio ' . $category->name . ' realizado por el proveedor: ' . $supplier->company_name),
|
'method' => 'card',
|
||||||
'device_session_id' => $request->device_id,
|
'amount' => ($supplier->minimun_fee < 150 ? 150 : $supplier->minimun_fee),
|
||||||
'cvv2' => $request->code
|
'description' => ('Contrato del usuario: ' . $user->name . ' del servicio ' . $category->name . ' realizado por el proveedor: ' . $supplier->company_name),
|
||||||
);
|
'device_session_id' => $request->device_id,
|
||||||
|
'cvv2' => $request->code
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
if (!empty($request->card_id) && !empty($request->device_id) && !empty($request->code) && $fee > $discount) {
|
if (!empty($request->card_id) && !empty($request->device_id) && !empty($request->code) && $fee > $discount) {
|
||||||
try {
|
// Bypass de pago para pruebas
|
||||||
$openpay = Openpay::getInstance(config('app.openpay_id'), config('app.openpay_apikey'));
|
if (env('PAYMENT_BYPASS', false)) {
|
||||||
|
$contract->transaction_id = 'BYPASS_' . uniqid();
|
||||||
|
} else {
|
||||||
|
try {
|
||||||
|
$openpay = Openpay::getInstance(config('app.openpay_id'), config('app.openpay_apikey'));
|
||||||
|
|
||||||
$customer = $openpay->customers->get($user->openpay_id);
|
$customer = $openpay->customers->get($user->openpay_id);
|
||||||
$charge = $customer->charges->create($chargeData);
|
$charge = $customer->charges->create($chargeData);
|
||||||
|
|
||||||
|
|
||||||
} catch (OpenpayApiTransactionError $e) {
|
} catch (OpenpayApiTransactionError $e) {
|
||||||
return response()->json([
|
return response()->json([
|
||||||
'type' => 'error',
|
'type' => 'error',
|
||||||
'message' => 'No se pudo procesar la transacción'
|
'message' => 'No se pudo procesar la transacción'
|
||||||
]);
|
]);
|
||||||
} catch (OpenpayApiRequestError $e) {
|
} catch (OpenpayApiRequestError $e) {
|
||||||
return response()->json([
|
return response()->json([
|
||||||
'type' => 'error',
|
'type' => 'error',
|
||||||
'message' => 'No se pudo procesar la operación'
|
'message' => 'No se pudo procesar la operación'
|
||||||
]);
|
]);
|
||||||
} catch (OpenpayApiConnectionError $e) {
|
} catch (OpenpayApiConnectionError $e) {
|
||||||
return response()->json([
|
return response()->json([
|
||||||
'type' => 'error',
|
'type' => 'error',
|
||||||
'message' => 'Error al conectarse a Openpay:' . $e->getMessage()
|
'message' => 'Error al conectarse a Openpay:' . $e->getMessage()
|
||||||
]);
|
]);
|
||||||
|
|
||||||
} catch (OpenpayApiAuthError $e) {
|
} catch (OpenpayApiAuthError $e) {
|
||||||
return response()->json([
|
return response()->json([
|
||||||
'type' => 'error',
|
'type' => 'error',
|
||||||
'message' => 'Error al conectarse a Openpay' . $e->getMessage()
|
'message' => 'Error al conectarse a Openpay' . $e->getMessage()
|
||||||
]);
|
]);
|
||||||
|
|
||||||
} catch (OpenpayApiError $e) {
|
} catch (OpenpayApiError $e) {
|
||||||
return response()->json([
|
return response()->json([
|
||||||
'type' => 'error',
|
'type' => 'error',
|
||||||
'message' => 'Error al conectarse a Openpay' . $e->getMessage()
|
'message' => 'Error al conectarse a Openpay' . $e->getMessage()
|
||||||
]);
|
]);
|
||||||
} catch (Exception $e) {
|
} catch (Exception $e) {
|
||||||
return response()->json([
|
return response()->json([
|
||||||
'type' => 'error',
|
'type' => 'error',
|
||||||
'message' => 'Error: ' . $e->getMessage()
|
'message' => 'Error: ' . $e->getMessage()
|
||||||
]);
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
$contract->transaction_id = $charge->id;
|
||||||
}
|
}
|
||||||
|
|
||||||
$contract->transaction_id = $charge->id;
|
|
||||||
|
|
||||||
} else if ($coupon) {
|
} else if ($coupon) {
|
||||||
if ($coupon->limit > 0 && $discount >= $fee) {
|
if ($coupon->limit > 0 && $discount >= $fee) {
|
||||||
if(!isset($checkccontracts) && !isset($checkccontracts)) {
|
if(!isset($checkccontracts) && !isset($checkccontracts)) {
|
||||||
|
|||||||
@@ -146,7 +146,7 @@ class NoHomeController extends Controller
|
|||||||
$data = null,
|
$data = null,
|
||||||
$buttons = null,
|
$buttons = null,
|
||||||
$schedule = null,
|
$schedule = null,
|
||||||
$headings = $client->name + ", tu proveedor del servicio ha llegado"
|
$headings = $client->name . ", tu proveedor del servicio ha llegado"
|
||||||
);
|
);
|
||||||
return response()->json([
|
return response()->json([
|
||||||
//'message' => 'Por favor espere a los 10 minutos de tolerancia de la hora acordada'
|
//'message' => 'Por favor espere a los 10 minutos de tolerancia de la hora acordada'
|
||||||
|
|||||||
@@ -14,6 +14,10 @@ class Authenticate extends Middleware
|
|||||||
*/
|
*/
|
||||||
protected function redirectTo($request)
|
protected function redirectTo($request)
|
||||||
{
|
{
|
||||||
|
// Para rutas API, nunca redirigir - dejar que lance excepción 401
|
||||||
|
if ($request->is('api/*')) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
if (! $request->expectsJson()) {
|
if (! $request->expectsJson()) {
|
||||||
return route('login');
|
return route('login');
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -44,7 +44,7 @@ class Postulations extends Model
|
|||||||
|
|
||||||
public function suppliers()
|
public function suppliers()
|
||||||
{
|
{
|
||||||
return $this->hasMany(Suppliers::class);
|
return $this->belongsToMany(Suppliers::class, 'postulations_suppliers', 'postulations_id', 'suppliers_id')->withTimestamps();
|
||||||
}
|
}
|
||||||
|
|
||||||
public function status()
|
public function status()
|
||||||
|
|||||||
@@ -55,7 +55,7 @@ class Suppliers extends Model
|
|||||||
|
|
||||||
public function postulations()
|
public function postulations()
|
||||||
{
|
{
|
||||||
return $this->belongsToMany(Postulations::class)->withTimestamps();
|
return $this->belongsToMany(Postulations::class, 'postulations_suppliers', 'suppliers_id', 'postulations_id')->withTimestamps();
|
||||||
}
|
}
|
||||||
|
|
||||||
public function payments()
|
public function payments()
|
||||||
|
|||||||
Reference in New Issue
Block a user