345 lines
12 KiB
PHP
345 lines
12 KiB
PHP
<?php
|
|
|
|
namespace App\Controllers\Frontend;
|
|
|
|
use App\Controllers\BaseController;
|
|
use App\Models\TopupModel;
|
|
use App\Libraries\Fiuu;
|
|
use CodeIgniter\API\ResponseTrait;
|
|
use App\Models\Customer;
|
|
use App\Models\CustomerWallet;
|
|
|
|
class TopupController extends BaseController
|
|
{
|
|
use ResponseTrait;
|
|
|
|
private $topups;
|
|
private $fiuu;
|
|
|
|
private $customer;
|
|
private $wallets;
|
|
private $db;
|
|
|
|
public function __construct()
|
|
{
|
|
$this->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
|
|
]);
|
|
}
|
|
|
|
} |