feat: Enhance service management and transaction handling
- Implemented client access token verification middleware to secure API endpoints. - Updated ServiceController to fetch active hosting services for authenticated users. - Refactored OrderController to ensure order retrieval is customer-specific. - Improved error logging in VmController for unexpected vCenter responses. - Disabled VNPay auto-deposit in TransactionController, switching to manual deposit flow. - Enhanced ServiceClientDetailResource to include Plesk credentials for hosting accounts. - Adjusted VpsServiceResource to dynamically set page type based on product type. - Added logging for PowerShellService to capture errors in RDP port changes. - Provisioning job now resolves service plans and logs relevant information for hosting accounts. - Updated database migrations to add necessary fields for service plans and DNS servers. - Refactored Service and ServicePlan models to establish relationships with hosting accounts and DNS servers.
This commit is contained in:
@@ -29,46 +29,52 @@ class TransactionController extends Controller
|
||||
$this->activityLogger = $activityLogger;
|
||||
}
|
||||
|
||||
// ponytail: VNPay auto-deposit disabled — nạp tiền hiện dùng luồng thủ công (ManualDepositController).
|
||||
public function handle(DepositRequest $request)
|
||||
{
|
||||
$user = $request->user();
|
||||
$transRef = time();
|
||||
$uuid = Str::uuid();
|
||||
$publicCode = 'DEP-' . now()->format('Ymd') . '-' . strtoupper(Str::random(6));
|
||||
|
||||
$transaction = Transaction::create([
|
||||
'uuid' => $uuid,
|
||||
'public_code' => $publicCode,
|
||||
'trans' => 'DEP' . $transRef,
|
||||
'amount' => $request->amount,
|
||||
'customer_id' => $user->id,
|
||||
'status' => TransactionStatus::PENDING->value,
|
||||
]);
|
||||
|
||||
$paymentUrl = $this->vnpayService->createPaymentUrl([
|
||||
'amount' => $request->amount,
|
||||
'transaction_ref' => $transRef,
|
||||
'transaction_uuid' => $uuid,
|
||||
]);
|
||||
|
||||
$this->activityLogger->log(
|
||||
event: 'deposit_vnpay',
|
||||
logName: 'Transaction',
|
||||
description: "Customer {$user->email} tạo yêu cầu nạp tiền VNPay: " . number_format($request->amount) . ' VNĐ - Mã: ' . $publicCode,
|
||||
subject: $transaction,
|
||||
newValues: ['public_code' => $publicCode, 'amount' => $request->amount, 'type' => 'vnpay'],
|
||||
);
|
||||
|
||||
return response()->json([
|
||||
'error' => false,
|
||||
'message' => 'Tạo yêu cầu nạp tiền thành công',
|
||||
'data' => [
|
||||
'transaction_id' => $transaction->trans,
|
||||
'transaction_uuid' => $uuid,
|
||||
'transaction_code' => $publicCode,
|
||||
'payment_url' => $paymentUrl,
|
||||
],
|
||||
]);
|
||||
'error' => true,
|
||||
'message' => 'Nạp tiền qua VNPay hiện không khả dụng. Vui lòng sử dụng nạp tiền thủ công.',
|
||||
], 410);
|
||||
|
||||
// $user = $request->user();
|
||||
// $transRef = time();
|
||||
// $uuid = Str::uuid();
|
||||
// $publicCode = 'DEP-' . now()->format('Ymd') . '-' . strtoupper(Str::random(6));
|
||||
//
|
||||
// $transaction = Transaction::create([
|
||||
// 'uuid' => $uuid,
|
||||
// 'public_code' => $publicCode,
|
||||
// 'trans' => 'DEP' . $transRef,
|
||||
// 'amount' => $request->amount,
|
||||
// 'customer_id' => $user->id,
|
||||
// 'status' => TransactionStatus::PENDING->value,
|
||||
// ]);
|
||||
//
|
||||
// $paymentUrl = $this->vnpayService->createPaymentUrl([
|
||||
// 'amount' => $request->amount,
|
||||
// 'transaction_ref' => $transRef,
|
||||
// 'transaction_uuid' => $uuid,
|
||||
// ]);
|
||||
//
|
||||
// $this->activityLogger->log(
|
||||
// event: 'deposit_vnpay',
|
||||
// logName: 'Transaction',
|
||||
// description: "Customer {$user->email} tạo yêu cầu nạp tiền VNPay: " . number_format($request->amount) . ' VNĐ - Mã: ' . $publicCode,
|
||||
// subject: $transaction,
|
||||
// newValues: ['public_code' => $publicCode, 'amount' => $request->amount, 'type' => 'vnpay'],
|
||||
// );
|
||||
//
|
||||
// return response()->json([
|
||||
// 'error' => false,
|
||||
// 'message' => 'Tạo yêu cầu nạp tiền thành công',
|
||||
// 'data' => [
|
||||
// 'transaction_id' => $transaction->trans,
|
||||
// 'transaction_uuid' => $uuid,
|
||||
// 'transaction_code' => $publicCode,
|
||||
// 'payment_url' => $paymentUrl,
|
||||
// ],
|
||||
// ]);
|
||||
}
|
||||
|
||||
protected function redirectToFrontend(string $status = 'failed', ?string $transactionCode = null): \Illuminate\Http\RedirectResponse
|
||||
@@ -85,110 +91,113 @@ class TransactionController extends Controller
|
||||
return redirect()->away($url . '?' . http_build_query($params));
|
||||
}
|
||||
|
||||
// ponytail: VNPay auto-deposit disabled — nạp tiền hiện dùng luồng thủ công (ManualDepositController).
|
||||
public function returnCallback(Request $request)
|
||||
{
|
||||
$data = $request->all();
|
||||
|
||||
$vnp_TxnRef = $data['vnp_TxnRef'] ?? null;
|
||||
$vnp_Amount = $data['vnp_Amount'] ?? 0;
|
||||
|
||||
FacadesLog::info('VNPay callback received', [
|
||||
'vnp_TxnRef' => $vnp_TxnRef,
|
||||
'vnp_Amount' => $vnp_Amount,
|
||||
'user' => $request->user() ? $request->user()->id : 'not authenticated',
|
||||
]);
|
||||
|
||||
$transaction = Transaction::where('trans', 'DEP' . $vnp_TxnRef)->first();
|
||||
return $this->redirectToFrontend('failed');
|
||||
|
||||
if (!$transaction) {
|
||||
return $this->redirectToFrontend('failed');
|
||||
}
|
||||
|
||||
if ($transaction->status == TransactionStatus::COMPLETED->value) {
|
||||
return $this->redirectToFrontend('success', $transaction->public_code);
|
||||
}
|
||||
|
||||
$verify = $this->vnpayService->verifyPayment($data);
|
||||
|
||||
FacadesLog::info('VNPay callback debug', [
|
||||
'isValid' => $verify['isValid'],
|
||||
'isSuccess' => $verify['isSuccess'] ?? false,
|
||||
'responseCode' => $data['vnp_ResponseCode'] ?? 'N/A',
|
||||
]);
|
||||
|
||||
if (!$verify['isValid']) {
|
||||
return $this->redirectToFrontend('failed', $transaction->public_code);
|
||||
}
|
||||
|
||||
if (!$verify['isSuccess']) {
|
||||
$transaction->update(['status' => TransactionStatus::FAILED->value]);
|
||||
return $this->redirectToFrontend('failed', $transaction->public_code);
|
||||
}
|
||||
|
||||
$originalAmount = $transaction->amount * 100;
|
||||
if ($vnp_Amount != $originalAmount) {
|
||||
$transaction->update(['status' => TransactionStatus::FAILED->value]);
|
||||
return $this->redirectToFrontend('failed', $transaction->public_code);
|
||||
}
|
||||
|
||||
try {
|
||||
DB::beginTransaction();
|
||||
|
||||
$transaction->update(['status' => TransactionStatus::COMPLETED->value]);
|
||||
|
||||
$customer = Customer::find($transaction->customer_id);
|
||||
|
||||
FacadesLog::info('Customer update debug', [
|
||||
'customer_id' => $transaction->customer_id,
|
||||
'customer_found' => $customer ? true : false,
|
||||
'transaction_amount' => $transaction->amount,
|
||||
'current_total' => $customer->total ?? 'N/A',
|
||||
'current_credit' => $customer->credit ?? 'N/A',
|
||||
]);
|
||||
|
||||
$customer->total += $transaction->amount;
|
||||
$customer->credit += $transaction->amount / 100;
|
||||
$customer->save();
|
||||
|
||||
FacadesLog::info('Customer after update', [
|
||||
'new_total' => $customer->total,
|
||||
'new_credit' => $customer->credit,
|
||||
]);
|
||||
|
||||
Log::create([
|
||||
'agent' => 'api',
|
||||
'client_ip' => $request->ip(),
|
||||
'description' => 'Nạp tiền vào tài khoản: ' . number_format($transaction->amount) . ' VNĐ (+' . number_format($transaction->amount / 100) . ' credit)',
|
||||
'customer_id' => $transaction->customer_id,
|
||||
]);
|
||||
|
||||
$this->activityLogger->log(
|
||||
event: 'deposit_success',
|
||||
logName: 'Transaction',
|
||||
description: "Customer {$customer->email} nạp tiền VNPay thành công: " . number_format($transaction->amount) . ' VNĐ - Mã: ' . $transaction->public_code,
|
||||
subject: $transaction,
|
||||
newValues: ['amount' => $transaction->amount, 'new_total' => $customer->total, 'public_code' => $transaction->public_code],
|
||||
);
|
||||
|
||||
DepositSuccessJob::dispatch([
|
||||
'customer_email' => $customer->email,
|
||||
'customer_name' => $customer->fullname,
|
||||
'transaction_code' => $transaction->public_code,
|
||||
'amount' => $transaction->amount,
|
||||
'credit' => $transaction->amount / 100,
|
||||
'current_total' => $customer->total,
|
||||
'current_credit' => $customer->credit,
|
||||
'deposit_date' => now()->format('d/m/Y H:i:s'),
|
||||
]);
|
||||
|
||||
DB::commit();
|
||||
} catch (\Exception $e) {
|
||||
DB::rollBack();
|
||||
FacadesLog::error('Payment processing error: ' . $e->getMessage());
|
||||
return $this->redirectToFrontend('failed', $transaction->public_code);
|
||||
}
|
||||
|
||||
return $this->redirectToFrontend('success', $transaction->public_code);
|
||||
// $data = $request->all();
|
||||
//
|
||||
// $vnp_TxnRef = $data['vnp_TxnRef'] ?? null;
|
||||
// $vnp_Amount = $data['vnp_Amount'] ?? 0;
|
||||
//
|
||||
// FacadesLog::info('VNPay callback received', [
|
||||
// 'vnp_TxnRef' => $vnp_TxnRef,
|
||||
// 'vnp_Amount' => $vnp_Amount,
|
||||
// 'user' => $request->user() ? $request->user()->id : 'not authenticated',
|
||||
// ]);
|
||||
//
|
||||
// $transaction = Transaction::where('trans', 'DEP' . $vnp_TxnRef)->first();
|
||||
//
|
||||
// if (!$transaction) {
|
||||
// return $this->redirectToFrontend('failed');
|
||||
// }
|
||||
//
|
||||
// if ($transaction->status == TransactionStatus::COMPLETED->value) {
|
||||
// return $this->redirectToFrontend('success', $transaction->public_code);
|
||||
// }
|
||||
//
|
||||
// $verify = $this->vnpayService->verifyPayment($data);
|
||||
//
|
||||
// FacadesLog::info('VNPay callback debug', [
|
||||
// 'isValid' => $verify['isValid'],
|
||||
// 'isSuccess' => $verify['isSuccess'] ?? false,
|
||||
// 'responseCode' => $data['vnp_ResponseCode'] ?? 'N/A',
|
||||
// ]);
|
||||
//
|
||||
// if (!$verify['isValid']) {
|
||||
// return $this->redirectToFrontend('failed', $transaction->public_code);
|
||||
// }
|
||||
//
|
||||
// if (!$verify['isSuccess']) {
|
||||
// $transaction->update(['status' => TransactionStatus::FAILED->value]);
|
||||
// return $this->redirectToFrontend('failed', $transaction->public_code);
|
||||
// }
|
||||
//
|
||||
// $originalAmount = $transaction->amount * 100;
|
||||
// if ($vnp_Amount != $originalAmount) {
|
||||
// $transaction->update(['status' => TransactionStatus::FAILED->value]);
|
||||
// return $this->redirectToFrontend('failed', $transaction->public_code);
|
||||
// }
|
||||
//
|
||||
// try {
|
||||
// DB::beginTransaction();
|
||||
//
|
||||
// $transaction->update(['status' => TransactionStatus::COMPLETED->value]);
|
||||
//
|
||||
// $customer = Customer::find($transaction->customer_id);
|
||||
//
|
||||
// FacadesLog::info('Customer update debug', [
|
||||
// 'customer_id' => $transaction->customer_id,
|
||||
// 'customer_found' => $customer ? true : false,
|
||||
// 'transaction_amount' => $transaction->amount,
|
||||
// 'current_total' => $customer->total ?? 'N/A',
|
||||
// 'current_credit' => $customer->credit ?? 'N/A',
|
||||
// ]);
|
||||
//
|
||||
// $customer->total += $transaction->amount;
|
||||
// $customer->credit += $transaction->amount / 100;
|
||||
// $customer->save();
|
||||
//
|
||||
// FacadesLog::info('Customer after update', [
|
||||
// 'new_total' => $customer->total,
|
||||
// 'new_credit' => $customer->credit,
|
||||
// ]);
|
||||
//
|
||||
// Log::create([
|
||||
// 'agent' => 'api',
|
||||
// 'client_ip' => $request->ip(),
|
||||
// 'description' => 'Nạp tiền vào tài khoản: ' . number_format($transaction->amount) . ' VNĐ (+' . number_format($transaction->amount / 100) . ' credit)',
|
||||
// 'customer_id' => $transaction->customer_id,
|
||||
// ]);
|
||||
//
|
||||
// $this->activityLogger->log(
|
||||
// event: 'deposit_success',
|
||||
// logName: 'Transaction',
|
||||
// description: "Customer {$customer->email} nạp tiền VNPay thành công: " . number_format($transaction->amount) . ' VNĐ - Mã: ' . $transaction->public_code,
|
||||
// subject: $transaction,
|
||||
// newValues: ['amount' => $transaction->amount, 'new_total' => $customer->total, 'public_code' => $transaction->public_code],
|
||||
// );
|
||||
//
|
||||
// DepositSuccessJob::dispatch([
|
||||
// 'customer_email' => $customer->email,
|
||||
// 'customer_name' => $customer->fullname,
|
||||
// 'transaction_code' => $transaction->public_code,
|
||||
// 'amount' => $transaction->amount,
|
||||
// 'credit' => $transaction->amount / 100,
|
||||
// 'current_total' => $customer->total,
|
||||
// 'current_credit' => $customer->credit,
|
||||
// 'deposit_date' => now()->format('d/m/Y H:i:s'),
|
||||
// ]);
|
||||
//
|
||||
// DB::commit();
|
||||
// } catch (\Exception $e) {
|
||||
// DB::rollBack();
|
||||
// FacadesLog::error('Payment processing error: ' . $e->getMessage());
|
||||
// return $this->redirectToFrontend('failed', $transaction->public_code);
|
||||
// }
|
||||
//
|
||||
// return $this->redirectToFrontend('success', $transaction->public_code);
|
||||
}
|
||||
|
||||
public function getTransactions(Request $request)
|
||||
@@ -231,7 +240,7 @@ class TransactionController extends Controller
|
||||
public function verifyPayment(Request $request)
|
||||
{
|
||||
$transRef = $request->query('vnp_TxnRef');
|
||||
|
||||
|
||||
if (!$transRef) {
|
||||
return response()->json([
|
||||
'error' => true,
|
||||
@@ -239,7 +248,9 @@ class TransactionController extends Controller
|
||||
], 400);
|
||||
}
|
||||
|
||||
$transaction = Transaction::where('trans', 'DEP' . $transRef)->first();
|
||||
$transaction = Transaction::where('trans', 'DEP' . $transRef)
|
||||
->where('customer_id', $request->user()->id)
|
||||
->first();
|
||||
|
||||
if (!$transaction) {
|
||||
return response()->json([
|
||||
@@ -325,7 +336,9 @@ class TransactionController extends Controller
|
||||
], 400);
|
||||
}
|
||||
|
||||
$transaction = Transaction::where('public_code', $code)->first();
|
||||
$transaction = Transaction::where('public_code', $code)
|
||||
->where('customer_id', $request->user()->id)
|
||||
->first();
|
||||
|
||||
if (!$transaction) {
|
||||
return response()->json([
|
||||
@@ -338,27 +351,13 @@ class TransactionController extends Controller
|
||||
'error' => false,
|
||||
'message' => 'Lấy thông tin giao dịch thành công',
|
||||
'data' => [
|
||||
'transaction' => [
|
||||
'public_code' => $transaction->public_code,
|
||||
'amount' => $transaction->amount,
|
||||
'amount_formatted' => number_format($transaction->amount) . ' VNĐ',
|
||||
'status' => $transaction->status,
|
||||
'status_label' => TransactionStatus::from($transaction->status)->label(),
|
||||
'created_at' => $transaction->created_at->format('Y-m-d H:i:s'),
|
||||
'paid_at' => $transaction->updated_at->format('Y-m-d H:i:s'),
|
||||
],
|
||||
'customer' => [
|
||||
'fullname' => $transaction->customer->fullname,
|
||||
'email' => $transaction->customer->email,
|
||||
'phone' => $transaction->customer->phone,
|
||||
'address' => $transaction->customer->address,
|
||||
],
|
||||
'balance' => [
|
||||
'total' => $transaction->customer->total,
|
||||
'credit' => $transaction->customer->credit,
|
||||
'total_formatted' => number_format($transaction->customer->total) . ' VNĐ',
|
||||
'credit_formatted' => number_format($transaction->customer->credit) . ' điểm',
|
||||
],
|
||||
'public_code' => $transaction->public_code,
|
||||
'amount' => $transaction->amount,
|
||||
'amount_formatted' => number_format($transaction->amount) . ' VNĐ',
|
||||
'status' => $transaction->status,
|
||||
'status_label' => TransactionStatus::from($transaction->status)->label(),
|
||||
'created_at' => $transaction->created_at->format('Y-m-d H:i:s'),
|
||||
'paid_at' => $transaction->updated_at->format('Y-m-d H:i:s'),
|
||||
],
|
||||
]);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user