topups = new TopupModel(); $this->fiuu = new Fiuu(); $this->customer = new Customer(); $this->wallets = new CustomerWallet(); $this->db = db_connect(); } public function index() { $data = $this->topups ->orderBy('created_at', 'DESC') ->findAll(); return $this->respond([ 'status' => 200, 'data' => $data, ]); } private function createPendingWalletRow(array $topupRow, array $customer): void { $current = (float)($customer['customer_wallet'] ?? 0); $incoming = (float)($topupRow['credit'] ?? 0); if ($incoming <= 0) { $incoming = (float)($topupRow['other_amount'] ?? 0); } $walletData = [ 'customer_id' => $topupRow['customer_id'], 'related_type' => 'topup', 'related_id' => $topupRow['id'], 'action' => 'in', 'current' => $current, 'in' => $incoming, 'out' => 0, 'balance' => $current, 'remark' => 'Topup '.$topupRow['topup_number'].' (pending)', 'status' => 'Pending', 'created_at' => date('Y-m-d H:i:s'), ]; try { $this->wallets->insert($walletData, true); } catch (\Throwable $e) { } } public function createTopupPayment() { $data = $this->request->getJSON(true); $rules = [ 'customer_id' => 'required|integer', 'payment_method' => 'required|string|max_length[50]', 'topup_setting_id' => 'permit_empty|integer', 'amount' => 'permit_empty|decimal', 'credit' => 'permit_empty|decimal', 'other_amount' => 'permit_empty|decimal' ]; if (!$this->validate($rules)) { return $this->failValidationErrors($this->validator->getErrors()); } $topupSettingId = !empty($data['topup_setting_id']) ? (int)$data['topup_setting_id'] : null; if ($topupSettingId) { // MODE 1: package top-up $pkg = model('App\Models\TopupSettingModel') ->where('id', $topupSettingId) ->where('deleted_at', null) ->first(); if (!$pkg || ($pkg['status'] ?? '') !== 'active') { return $this->failValidationErrors(['topup_setting_id' => 'Selected package is invalid or inactive']); } $amount = (float)$pkg['topup_amount']; $credit = (float)$pkg['credit_amount']; if ($amount <= 0 || $credit <= 0) { return $this->failValidationErrors(['topup_setting' => 'Package amounts must be > 0']); } $otherAmount = null; } else { $otherAmount = isset($data['other_amount']) && $data['other_amount'] !== '' ? (float)$data['other_amount'] : 0.0; if ($otherAmount <= 0) { return $this->failValidationErrors(['other_amount' => 'Provide a positive amount for custom top-up']); } $amount = 0.0; $credit = 0.0; } $topupNumber = 'T' . strtoupper(bin2hex(random_bytes(6))); $insertData = [ 'topup_setting_id' => $topupSettingId, 'customer_id' => (int)$data['customer_id'], 'topup_number' => $topupNumber, 'amount' => $amount, // package cash (0 for custom) 'credit' => $credit, // package credit (0 for custom) 'payment_method' => $data['payment_method'], 'other_amount' => $otherAmount, // used for custom 'status' => 'Pending', ]; $id = $this->topups->insert($insertData, true); if (!$id) return $this->fail('Topup failed', 400); $topup = $this->topups->find($id); $customer = $this->customer->find((int)$data['customer_id']) ?? []; // Write PENDING wallet ledger (no balance change yet) $this->createPendingWalletRow($topup, $customer); // Payment link uses the payable amount: // - package mode → $amount // - custom mode → $otherAmount $payable = $topupSettingId ? $amount : $otherAmount; $payment_details = [ 'bill_name' => $customer['name'] ?? '', 'bill_email' => $customer['email'] ?? '', 'bill_mobile' => $customer['phone'] ?? '', 'bill_desc' => 'US Pizza - Wallet Topup - ' . $topupNumber, ]; $result = $this->fiuu->createTopup($topupNumber, $payable, $payment_details); return $this->respond([ 'status' => 201, 'message' => 'Topup created successfully', 'data' => $this->topups->find($id), 'redirect_url' => $result['redirect_url'] ?? null ]); } public function fiuuTopupNotification() { $payload = $this->request->getPost(); // $payload = $this->request->getJSON(true); // print_r($payload);exit; $result = $this->fiuu->topupNotification($payload); log_message('error', 'Fiuu Payload: '.json_encode($payload)); log_message('error', 'Fiuu Result: '.json_encode($result)); $topupNumber = $payload['orderid'] ?? null; if (!$topupNumber) { return $this->respond(['status' => 400, 'message' => 'Missing orderid'], 400); } $topup = $this->topups->where('topup_number', $topupNumber)->first(); if (!$topup) { return $this->respond(['status' => 404, 'message' => 'Topup not found'], 404); } if (in_array($topup['status'], ['completed','failed'], true)) { return $this->respond(['status' => 200, 'message' => 'Already processed', 'result' => $result]); } $payStat = strtolower((string)($payload['status'] ?? '')); $resStat = is_array($result) ? strtolower((string)($result['status'] ?? '')) : strtolower((string)$result); $isSuccess = in_array($payStat, ['00','success','approved'], true) || (is_string($resStat) && strpos($resStat, 'success') !== false); $this->db->transStart(); if ($isSuccess) { $table = $this->customer->builder()->getTable(); $customer = $this->db->query( 'SELECT * FROM `'.$table.'` WHERE `id` = ? FOR UPDATE', [$topup['customer_id']] )->getRowArray(); if (!$customer) { $this->db->transRollback(); return $this->respond(['status' => 404, 'message' => 'Customer not found'], 404); } $current = (float)($customer['customer_wallet'] ?? 0); $delta = $topup['amount'] + $topup['credit']; // print_r($delta);exit; if ($delta <= 0) $delta = (float)$topup['other_amount']; if ($delta <= 0) { $this->topups->update($topup['id'], ['status' => 'failed']); $this->db->transComplete(); return $this->respond(['status' => 400, 'message' => 'Invalid topup amount'], 400); } $newBal = $current + $delta; $walletRow = $this->wallets ->where('related_type', 'topup') ->where('related_id', $topup['id']) ->orderBy('id', 'desc') ->first(); if ($walletRow) { $this->wallets->update($walletRow['id'], [ 'status' => 'completed', 'current' => $current, 'balance' => $newBal, 'remark' => 'Topup '.$topupNumber.' (completed)', 'in' => $delta, ]); } else { $this->wallets->insert([ 'customer_id' => $topup['customer_id'], 'related_type' => 'topup', 'related_id' => $topup['id'], 'action' => 'in', 'current' => $current, 'in' => $delta, 'out' => 0, 'balance' => $newBal, 'remark' => 'Topup '.$topupNumber.' (completed)', 'status' => 'completed', 'created_at' => date('Y-m-d H:i:s'), ], true); } $this->customer->update($customer['id'], ['customer_wallet' => $newBal]); $this->topups->update($topup['id'], ['status' => 'Success']); } else { $this->topups->update($topup['id'], ['status' => 'Failed']); $this->wallets ->where('related_type', 'topup') ->where('related_id', $topup['id']) ->set([ 'status' => 'failed', 'remark' => 'Topup '.$topupNumber.' (failed)' ])->update(); } $this->db->transComplete(); if ($this->db->transStatus() === false) { return $this->respond(['status' => 500, 'message' => 'Transaction error'], 500); } return $this->respond(['status' => 200, 'message' => 'Notification processed', 'result' => $result]); } public function fiuuTopupReturn() { $data = $this->request->getPost(); $this->fiuu->topupNotification($data); } public function checkTopupPayment($topup_id = null) { // echo(123123);exit; $topup = $this->topups->find($topup_id); if (!$topup) { return $this->fail('Topup not found', 400); } // print_r($topup);exit; $status = strtolower($topup['status'] ?? ''); // print_r($status);exit; if ($status === 'success') { return $this->respond(['status' => 200, 'result' => 'Success', 'topup_id' => $topup_id]); } elseif ($status === 'pending') { return $this->respond(['status' => 200, 'result' => 'Pending', 'topup_id' => $topup_id]); } return $this->respond(['status' => 400, 'result' => 'Failed', 'topup_id' => $topup_id]); } public function show($id = null) { $id = (int) $id; $row = $this->topups ->select('topup.*, topup_setting.id AS setting_id, topup_setting.topup_amount, topup_setting.credit_amount, topup_setting.status AS setting_status') ->join('topup_setting', 'topup_setting.id = topup.topup_setting_id', 'left') ->where('topup.id', $id) ->first(); if (!$row) { return $this->failNotFound('Topup record not found'); } $data = [ 'id' => $row['id'], 'topup_setting_id' => $row['topup_setting_id'], 'customer_id' => $row['customer_id'], 'topup_number' => $row['topup_number'], 'amount' => $row['amount'], 'credit' => $row['credit'], 'payment_method' => $row['payment_method'], 'other_amount' => $row['other_amount'], 'status' => $row['status'], 'created_at' => $row['created_at'], 'updated_at' => $row['updated_at'], 'topup_setting' => [ 'id' => $row['setting_id'], 'topup_amount' => $row['topup_amount'], 'credit_amount' => $row['credit_amount'], 'status' => $row['setting_status'] ] ]; return $this->respond([ 'status' => 200, 'data' => $data ]); } }