270 lines
9.1 KiB
PHP
270 lines
9.1 KiB
PHP
<?php
|
|
|
|
declare(strict_types=1);
|
|
|
|
namespace App\Http\Controllers\Market;
|
|
|
|
use App\Http\Controllers\Helpers\ResponseHelper;
|
|
use App\Http\Controllers\Helpers\PaymentProcessor;
|
|
use App\Http\Controllers\Helpers\QrphDecoder;
|
|
use App\Models\SystemSetting;
|
|
use App\Models\Accounting\MemberLedger;
|
|
use App\Models\User;
|
|
use App\Models\GlobalTransaction;
|
|
use Hypervel\Http\Request;
|
|
use Hypervel\Support\Facades\Auth;
|
|
use Hypervel\Support\Facades\DB;
|
|
use Hypervel\Support\Str;
|
|
use App\Enums\Market\ProductTransactionType;
|
|
use App\Enums\Market\TransactionFlow;
|
|
|
|
class CreditController
|
|
{
|
|
public function getWalletData(Request $request)
|
|
{
|
|
$user = User::find(Auth::id());
|
|
if (!$user) return ResponseHelper::returnUnauthorized();
|
|
|
|
$history = MemberLedger::where('user_id', $user->id)
|
|
->where('is_active', true)
|
|
->orderBy('created_at', 'desc')
|
|
->limit(20)
|
|
->get();
|
|
|
|
return response()->json([
|
|
'success' => true,
|
|
'balance' => $user->total_balance,
|
|
'credit' => $user->total_credit,
|
|
'history' => $history
|
|
]);
|
|
}
|
|
|
|
public function topUp(Request $request)
|
|
{
|
|
// Check if Top Up is enabled globally
|
|
if (!(\App\Models\SystemSetting::getValue('top_up_enabled', true))) {
|
|
return ResponseHelper::returnError('Credit top-up is currently disabled by administrators.');
|
|
}
|
|
|
|
$amount = (float) $request->input('amount');
|
|
$method = $request->input('method', 'GCASH');
|
|
|
|
if ($amount <= 0) {
|
|
return ResponseHelper::returnError('Amount must be greater than zero');
|
|
}
|
|
|
|
$user = User::find(Auth::id());
|
|
if (!$user) return ResponseHelper::returnUnauthorized();
|
|
|
|
// Start Transaction
|
|
DB::beginTransaction();
|
|
try {
|
|
// 1. Simulate Payment Success (in real life this would be a webhook/callback)
|
|
$payment = PaymentProcessor::initiatePayment($amount, $method, $user->hashkey);
|
|
|
|
if (!$payment['success']) {
|
|
throw new \Exception('Payment initiation failed');
|
|
}
|
|
|
|
// 2. Update User Balance
|
|
$user->total_balance += $amount;
|
|
$user->save();
|
|
|
|
// 3. Record in MemberLedger
|
|
$ledger = new MemberLedger([
|
|
'hashkey' => Str::random(64),
|
|
'user_id' => $user->id,
|
|
'amount' => $amount,
|
|
'transaction_type' => 'TOP_UP',
|
|
'flow' => 'IN',
|
|
'balance_after' => $user->total_balance,
|
|
'description' => "Credit Top-up via {$method}",
|
|
'reference_id' => $payment['transaction_id'],
|
|
'created_by' => $user->id,
|
|
'is_active' => true,
|
|
]);
|
|
$ledger->save();
|
|
|
|
// 4. Record in GlobalTransaction (for compatibility with existing reports)
|
|
$globalTxn = new GlobalTransaction([
|
|
'hashkey' => Str::random(64),
|
|
'user_id' => $user->id,
|
|
'amount' => $amount,
|
|
'type' => ProductTransactionType::TOP_UP,
|
|
'status' => 'COMPLETED',
|
|
'description' => "Credit Top-up via {$method}",
|
|
'flow' => TransactionFlow::INCOME,
|
|
'created_by' => $user->id,
|
|
]);
|
|
$globalTxn->save();
|
|
|
|
DB::commit();
|
|
|
|
return response()->json([
|
|
'success' => true,
|
|
'message' => 'Top-up successful',
|
|
'balance' => $user->total_balance,
|
|
'transaction_id' => $payment['transaction_id']
|
|
]);
|
|
|
|
} catch (\Exception $e) {
|
|
DB::rollBack();
|
|
return ResponseHelper::returnError('Top-up failed: ' . $e->getMessage());
|
|
}
|
|
}
|
|
|
|
public function transferCredit(Request $request)
|
|
{
|
|
$recipientHash = $request->input('recipient_hash');
|
|
$amount = (float) $request->input('amount');
|
|
|
|
if ($amount <= 0) return ResponseHelper::returnError('Invalid amount');
|
|
|
|
$sender = User::find(Auth::id());
|
|
if (!$sender) return ResponseHelper::returnUnauthorized();
|
|
|
|
if ($sender->total_balance < $amount) {
|
|
return ResponseHelper::returnError('Insufficient balance');
|
|
}
|
|
|
|
$recipient = User::where('hashkey', $recipientHash)->first();
|
|
if (!$recipient) return ResponseHelper::returnError('Recipient not found');
|
|
|
|
if ($sender->id === $recipient->id) {
|
|
return ResponseHelper::returnError('Cannot transfer to yourself');
|
|
}
|
|
|
|
DB::beginTransaction();
|
|
try {
|
|
// Deduct from sender
|
|
$sender->total_balance -= $amount;
|
|
$sender->save();
|
|
|
|
// Add to recipient
|
|
$recipient->total_balance += $amount;
|
|
$recipient->save();
|
|
|
|
$txnRef = Str::random(12);
|
|
|
|
// Record Ledger for Sender
|
|
MemberLedger::create([
|
|
'hashkey' => Str::random(64),
|
|
'user_id' => $sender->id,
|
|
'amount' => $amount,
|
|
'transaction_type' => 'TRANSFER_OUT',
|
|
'flow' => 'OUT',
|
|
'balance_after' => $sender->total_balance,
|
|
'description' => "Credit Transfer to {$recipient->fullname}",
|
|
'reference_id' => $txnRef,
|
|
'created_by' => $sender->id,
|
|
]);
|
|
|
|
// Record Ledger for Recipient
|
|
MemberLedger::create([
|
|
'hashkey' => Str::random(64),
|
|
'user_id' => $recipient->id,
|
|
'amount' => $amount,
|
|
'transaction_type' => 'TRANSFER_IN',
|
|
'flow' => 'IN',
|
|
'balance_after' => $recipient->total_balance,
|
|
'description' => "Credit Transfer from {$sender->fullname}",
|
|
'reference_id' => $txnRef,
|
|
'created_by' => $sender->id,
|
|
]);
|
|
|
|
DB::commit();
|
|
return response()->json(['success' => true, 'message' => 'Transfer successful']);
|
|
|
|
} catch (\Exception $e) {
|
|
DB::rollBack();
|
|
return ResponseHelper::returnError('Transfer failed');
|
|
}
|
|
}
|
|
|
|
public function searchUsers(Request $request)
|
|
{
|
|
$query = $request->input('q');
|
|
if (empty($query)) return response()->json(['success' => true, 'data' => []]);
|
|
|
|
$users = User::where('fullname', 'like', "%{$query}%")
|
|
->orWhere('name', 'like', "%{$query}%")
|
|
->orWhere('mobile_number', 'like', "%{$query}%")
|
|
->where('id', '!=', Auth::id())
|
|
->limit(10)
|
|
->get(['hashkey', 'fullname', 'name', 'mobile_number']);
|
|
|
|
return response()->json(['success' => true, 'data' => $users]);
|
|
}
|
|
|
|
/**
|
|
* GET the current QRPH payment code (available to all authenticated users for top-up display).
|
|
*/
|
|
public function getQrphCode(Request $request)
|
|
{
|
|
$raw = SystemSetting::getValue('qrph_payment_code', null);
|
|
$imgHashkey = SystemSetting::getValue('qrph_payment_image_hashkey', null);
|
|
|
|
if (empty($raw)) {
|
|
return response()->json(['success' => true, 'qrph' => null, 'decoded' => null, 'image_url' => null]);
|
|
}
|
|
|
|
$decoded = QrphDecoder::decode($raw);
|
|
$imageUrl = $imgHashkey ? "/RequestData/File/{$imgHashkey}" : null;
|
|
|
|
return response()->json([
|
|
'success' => true,
|
|
'qrph' => $raw,
|
|
'decoded' => $decoded,
|
|
'image_url' => $imageUrl,
|
|
]);
|
|
}
|
|
|
|
/**
|
|
* SET the QRPH payment code — ULTIMATE only (enforced by route middleware).
|
|
* Accepts optional image_hashkey from a prior /File/Upload/QrphPayment call.
|
|
*/
|
|
public function setQrphCode(Request $request)
|
|
{
|
|
$raw = trim($request->input('qrph_code', ''));
|
|
$imgHashkey = trim($request->input('image_hashkey', ''));
|
|
|
|
if (empty($raw)) {
|
|
SystemSetting::setValue('qrph_payment_code', '');
|
|
SystemSetting::setValue('qrph_payment_image_hashkey', '');
|
|
return response()->json(['success' => true, 'message' => 'QRPH code cleared.']);
|
|
}
|
|
|
|
$decoded = QrphDecoder::decode($raw);
|
|
|
|
SystemSetting::setValue('qrph_payment_code', $raw);
|
|
if (!empty($imgHashkey)) {
|
|
SystemSetting::setValue('qrph_payment_image_hashkey', $imgHashkey);
|
|
}
|
|
|
|
$imageUrl = $imgHashkey ? "/RequestData/File/{$imgHashkey}" : null;
|
|
|
|
return response()->json([
|
|
'success' => true,
|
|
'message' => 'QRPH code saved.',
|
|
'decoded' => $decoded,
|
|
'image_url' => $imageUrl,
|
|
]);
|
|
}
|
|
|
|
/**
|
|
* Decode a QRPH string without saving — for preview before saving.
|
|
*/
|
|
public function decodeQrph(Request $request)
|
|
{
|
|
$raw = trim($request->input('qrph_code', ''));
|
|
if (empty($raw)) {
|
|
return ResponseHelper::returnError('No QR string provided.');
|
|
}
|
|
|
|
return response()->json([
|
|
'success' => true,
|
|
'decoded' => QrphDecoder::decode($raw),
|
|
]);
|
|
}
|
|
}
|