271 lines
8.7 KiB
PHP
271 lines
8.7 KiB
PHP
<?php
|
|
|
|
namespace App\Http\Controllers\Api\Transaction;
|
|
|
|
use App\Enums\TransactionStatus;
|
|
use App\Http\Controllers\Controller;
|
|
use App\Http\Requests\DepositRequest;
|
|
use App\Http\Services\VNPayService;
|
|
use App\Models\Customer;
|
|
use App\Models\Log;
|
|
use App\Models\Transaction;
|
|
use Illuminate\Http\Request;
|
|
use Illuminate\Support\Facades\DB;
|
|
use Illuminate\Support\Facades\Log as FacadesLog;
|
|
|
|
class TransactionController extends Controller
|
|
{
|
|
protected VNPayService $vnpayService;
|
|
|
|
public function __construct(VNPayService $vnpayService)
|
|
{
|
|
$this->vnpayService = $vnpayService;
|
|
}
|
|
|
|
public function handle(DepositRequest $request)
|
|
{
|
|
$user = $request->user();
|
|
$transRef = time();
|
|
|
|
$transaction = Transaction::create([
|
|
'trans' => 'DEP' . $transRef,
|
|
'amount' => $request->amount,
|
|
'customer_id' => $user->id,
|
|
'status' => TransactionStatus::PENDING->value,
|
|
]);
|
|
|
|
$paymentUrl = $this->vnpayService->createPaymentUrl([
|
|
'amount' => $request->amount,
|
|
'transaction_ref' => $transRef,
|
|
]);
|
|
|
|
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,
|
|
'payment_url' => $paymentUrl,
|
|
],
|
|
]);
|
|
}
|
|
|
|
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();
|
|
|
|
if (!$transaction) {
|
|
return response()->json([
|
|
'error' => true,
|
|
'message' => 'Giao dịch không tồn tại',
|
|
'debug' => [
|
|
'vnp_TxnRef' => $vnp_TxnRef,
|
|
'search_trans' => 'DEP' . $vnp_TxnRef,
|
|
]
|
|
], 404);
|
|
}
|
|
|
|
if ($transaction->status == TransactionStatus::COMPLETED->value) {
|
|
return response()->json([
|
|
'error' => false,
|
|
'message' => 'Giao dịch đã được xử lý trước đó',
|
|
'data' => $transaction,
|
|
]);
|
|
}
|
|
|
|
$user = $request->user();
|
|
|
|
if (!$user) {
|
|
return response()->json([
|
|
'error' => true,
|
|
'message' => 'Vui lòng đăng nhập',
|
|
'debug' => [
|
|
'transaction_found' => true,
|
|
'trans' => $transaction->trans,
|
|
'amount_db' => $transaction->amount,
|
|
'amount_vnp' => $vnp_Amount,
|
|
]
|
|
], 401);
|
|
}
|
|
|
|
if ($transaction->customer_id !== $user->id) {
|
|
return response()->json([
|
|
'error' => true,
|
|
'message' => 'Giao dịch không thuộc về bạn',
|
|
], 403);
|
|
}
|
|
|
|
$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 response()->json([
|
|
'error' => true,
|
|
'message' => 'Dữ liệu không hợp lệ',
|
|
], 400);
|
|
}
|
|
|
|
if (!$verify['isSuccess']) {
|
|
$transaction->update(['status' => TransactionStatus::FAILED->value]);
|
|
|
|
return response()->json([
|
|
'error' => true,
|
|
'message' => 'Thanh toán thất bại',
|
|
'data' => $verify['data'],
|
|
], 400);
|
|
}
|
|
|
|
$originalAmount = $transaction->amount * 100;
|
|
if ($vnp_Amount != $originalAmount) {
|
|
$transaction->update(['status' => TransactionStatus::FAILED->value]);
|
|
return response()->json([
|
|
'error' => true,
|
|
'message' => 'Số tiền không khớp',
|
|
'debug' => [
|
|
'amount_db' => $transaction->amount,
|
|
'amount_db_times_100' => $originalAmount,
|
|
'amount_vnp' => $vnp_Amount,
|
|
]
|
|
], 400);
|
|
}
|
|
|
|
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,
|
|
]);
|
|
|
|
DB::commit();
|
|
} catch (\Exception $e) {
|
|
DB::rollBack();
|
|
return response()->json([
|
|
'error' => true,
|
|
'message' => 'Lỗi xử lý giao dịch: ' . $e->getMessage(),
|
|
], 500);
|
|
}
|
|
|
|
return response()->json([
|
|
'error' => false,
|
|
'message' => 'Thanh toán thành công',
|
|
'data' => [
|
|
'transaction' => $transaction->fresh(),
|
|
'customer' => [
|
|
'total' => $customer->total,
|
|
'credit' => $customer->credit,
|
|
],
|
|
],
|
|
]);
|
|
}
|
|
|
|
public function getTransactions(Request $request)
|
|
{
|
|
$user = $request->user();
|
|
|
|
$transactions = Transaction::where('customer_id', $user->id)
|
|
->orderBy('created_at', 'desc')
|
|
->get();
|
|
|
|
return response()->json([
|
|
'error' => false,
|
|
'message' => 'Lấy danh sách giao dịch thành công',
|
|
'data' => $transactions,
|
|
]);
|
|
}
|
|
|
|
public function getDetailTransaction(Request $request, $slug)
|
|
{
|
|
$user = $request->user();
|
|
|
|
$transaction = Transaction::where('trans', $slug)
|
|
->where('customer_id', $user->id)
|
|
->first();
|
|
|
|
if (!$transaction) {
|
|
return response()->json([
|
|
'error' => true,
|
|
'message' => 'Giao dịch không tồn tại',
|
|
], 404);
|
|
}
|
|
|
|
return response()->json([
|
|
'error' => false,
|
|
'message' => 'Lấy chi tiết giao dịch thành công',
|
|
'data' => $transaction,
|
|
]);
|
|
}
|
|
|
|
public function verifyPayment(Request $request)
|
|
{
|
|
$transRef = $request->query('vnp_TxnRef');
|
|
|
|
if (!$transRef) {
|
|
return response()->json([
|
|
'error' => true,
|
|
'message' => 'Thiếu tham số vnp_TxnRef',
|
|
], 400);
|
|
}
|
|
|
|
$transaction = Transaction::where('trans', 'DEP' . $transRef)->first();
|
|
|
|
if (!$transaction) {
|
|
return response()->json([
|
|
'error' => true,
|
|
'message' => 'Giao dịch không tồn tại',
|
|
], 404);
|
|
}
|
|
|
|
return response()->json([
|
|
'error' => false,
|
|
'message' => 'Lấy thông tin giao dịch thành công',
|
|
'data' => [
|
|
'trans' => $transaction->trans,
|
|
'amount' => $transaction->amount,
|
|
'amount_vnp' => $transaction->amount * 100,
|
|
'status' => $transaction->status,
|
|
'status_label' => TransactionStatus::from($transaction->status)->label(),
|
|
'created_at' => $transaction->created_at,
|
|
'updated_at' => $transaction->updated_at,
|
|
],
|
|
]);
|
|
}
|
|
} |