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:
2026-01-27 23:48:27 +00:00
parent f571caa204
commit 689e456fe5
6 changed files with 122 additions and 66 deletions

View File

@@ -159,28 +159,50 @@ class ContractController extends Controller
public function create(Request $request) {
$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 ]+$)+/',
];
// Si el bypass está activo, usar reglas relajadas
$paymentBypass = env('PAYMENT_BYPASS', false);
if ($paymentBypass) {
$rules = [
'postulation_id' => 'required|numeric',
'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);
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);
} else {
$user = Auth::user();
$postulation = Postulations::where('id', $request->postulation_id)->first();
$coupon = Coupon::where('name', $request->coupon)->first();
Openpay::setProductionMode(true);
if (!$paymentBypass) {
Openpay::setProductionMode(true);
}
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();
}
$supplier = Suppliers::where('id', $request->supplier_id)->first();
@@ -191,7 +213,8 @@ class ContractController extends Controller
$ichambafee = iChambaParameter::where('parameter', 'ichamba_fee')->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->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));
$contract->coupon_id = $coupon->id;
$chargeData = array(
'source_id' => $card->token,
'method' => 'card',
'amount' => ((($supplier->minimun_fee < 150 ? 150 : $supplier->minimun_fee)*(1 - (($coupon->percentage = null ? 0 : $coupon->percentage)/100)))-($coupon->amount = null ? 0 : $coupon->amount)),
'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
);
// Solo crear chargeData si no estamos en bypass mode
if (!$paymentBypass && $card) {
$chargeData = array(
'source_id' => $card->token,
'method' => 'card',
'amount' => ((($supplier->minimun_fee < 150 ? 150 : $supplier->minimun_fee)*(1 - (($coupon->percentage = null ? 0 : $coupon->percentage)/100)))-($coupon->amount = null ? 0 : $coupon->amount)),
'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 {
@@ -248,61 +274,69 @@ class ContractController extends Controller
$discount = 0;
$contract->coupon_id = null;
$chargeData = array(
'source_id' => $card->token,
'method' => 'card',
'amount' => ($supplier->minimun_fee < 150 ? 150 : $supplier->minimun_fee),
'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
);
// Solo crear chargeData si no estamos en bypass mode
if (!$paymentBypass && $card) {
$chargeData = array(
'source_id' => $card->token,
'method' => 'card',
'amount' => ($supplier->minimun_fee < 150 ? 150 : $supplier->minimun_fee),
'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) {
try {
$openpay = Openpay::getInstance(config('app.openpay_id'), config('app.openpay_apikey'));
// Bypass de pago para pruebas
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);
$charge = $customer->charges->create($chargeData);
$customer = $openpay->customers->get($user->openpay_id);
$charge = $customer->charges->create($chargeData);
} catch (OpenpayApiTransactionError $e) {
return response()->json([
'type' => 'error',
'message' => 'No se pudo procesar la transacción'
]);
} catch (OpenpayApiRequestError $e) {
return response()->json([
'type' => 'error',
'message' => 'No se pudo procesar la operación'
]);
} catch (OpenpayApiConnectionError $e) {
return response()->json([
'type' => 'error',
'message' => 'Error al conectarse a Openpay:' . $e->getMessage()
]);
} catch (OpenpayApiTransactionError $e) {
return response()->json([
'type' => 'error',
'message' => 'No se pudo procesar la transacción'
]);
} catch (OpenpayApiRequestError $e) {
return response()->json([
'type' => 'error',
'message' => 'No se pudo procesar la operación'
]);
} catch (OpenpayApiConnectionError $e) {
return response()->json([
'type' => 'error',
'message' => 'Error al conectarse a Openpay:' . $e->getMessage()
]);
} catch (OpenpayApiAuthError $e) {
return response()->json([
'type' => 'error',
'message' => 'Error al conectarse a Openpay' . $e->getMessage()
]);
} catch (OpenpayApiAuthError $e) {
return response()->json([
'type' => 'error',
'message' => 'Error al conectarse a Openpay' . $e->getMessage()
]);
} catch (OpenpayApiError $e) {
return response()->json([
'type' => 'error',
'message' => 'Error al conectarse a Openpay' . $e->getMessage()
]);
} catch (Exception $e) {
return response()->json([
'type' => 'error',
'message' => 'Error: ' . $e->getMessage()
]);
} catch (OpenpayApiError $e) {
return response()->json([
'type' => 'error',
'message' => 'Error al conectarse a Openpay' . $e->getMessage()
]);
} catch (Exception $e) {
return response()->json([
'type' => 'error',
'message' => 'Error: ' . $e->getMessage()
]);
}
$contract->transaction_id = $charge->id;
}
$contract->transaction_id = $charge->id;
} else if ($coupon) {
if ($coupon->limit > 0 && $discount >= $fee) {
if(!isset($checkccontracts) && !isset($checkccontracts)) {

View File

@@ -146,7 +146,7 @@ class NoHomeController extends Controller
$data = null,
$buttons = null,
$schedule = null,
$headings = $client->name + ", tu proveedor del servicio ha llegado"
$headings = $client->name . ", tu proveedor del servicio ha llegado"
);
return response()->json([
//'message' => 'Por favor espere a los 10 minutos de tolerancia de la hora acordada'