| Server IP : 77.37.53.71 / Your IP :
216.73.216.109 [
Web Server : LiteSpeed System : Linux nl-srv-web1124.main-hosting.eu 4.18.0-553.121.1.lve.el8.x86_64 #1 SMP Thu Apr 30 16:40:41 UTC 2026 x86_64 User : u964240598 ( 964240598) PHP Version : 8.4.19 Disable Function : system, exec, shell_exec, passthru, mysql_list_dbs, ini_alter, dl, symlink, link, chgrp, leak, popen, apache_child_terminate, virtual, mb_send_mail Domains : 2 Domains MySQL : OFF | cURL : ON | WGET : ON | Perl : OFF | Python : OFF | Sudo : OFF | Pkexec : OFF Directory : /home/u964240598/domains/hofam.org/public_html/churchapp/application/controllers/ |
Upload File : |
<?php
defined('BASEPATH') or exit('No direct script access allowed');
require APPPATH . '/libraries/BaseController.php';
class Donations extends BaseController
{
public function __construct()
{
parent::__construct();
$this->load->model('donations_model');
$this->load->library('Pesapal'); // Pesapal library already discussed
}
/* =========================================================
* ADMIN PAGES (UNCHANGED)
* ========================================================= */
public function index()
{
$this->isLoggedIn();
$this->load->template('donations', []);
}
public function list()
{
$this->load->model('branches_model');
$branches = $this->branches_model->branchesListing();
echo json_encode([
'status' => 'ok',
'data' => $branches
]);
}
function donationsummary()
{
$this->isLoggedIn();
$this->load->model('branches_model');
$data['branches'] = $this->branches_model->branchesListing();
$this->load->template('donationsummary', $data);
}
/* =========================================================
* SUMMARY DATA (IMPORTANT: COMPLETED ONLY)
* ========================================================= */
function loaddonationsummary()
{
$draw = intval($_POST['draw']);
$branch = $_POST['branch'];
$monthyear = explode("-", $_POST['monthyear']);
$year = $monthyear[0];
$month = ltrim($monthyear[1], '0');
// Donation categories
$tithes = $this->donations_model->getDonationByTypes($branch,$year,$month,"tithe");
$mainservice = $this->donations_model->getDonationByTypes($branch,$year,$month,"mainservice");
$sundayschool = $this->donations_model->getDonationByTypes($branch,$year,$month,"sundayschool");
$loveoffering = $this->donations_model->getDonationByTypes($branch,$year,$month,"loveoffering");
$jumblesales = $this->donations_model->getDonationByTypes($branch,$year,$month,"jumblesales");
$donationsrecieved = $this->donations_model->getDonationByTypes($branch,$year,$month,"donationsrecieved");
$otherincome = $this->donations_model->getDonationByTypes($branch,$year,$month,"otherincome");
$totalincome = [];
for ($i = 0; $i < 5; $i++) {
$totalincome[$i] =
$tithes[$i] +
$mainservice[$i] +
$sundayschool[$i] +
$loveoffering[$i] +
$jumblesales[$i] +
$donationsrecieved[$i] +
$otherincome[$i];
}
$dat = [];
$dat[] = ["Details","KES","KES","KES","KES","KES"];
$dat[] = ["Tithes",$tithes[0],$tithes[1],$tithes[2],$tithes[3],$tithes[4]];
$dat[] = ["Offerings (Main Service)",$mainservice[0],$mainservice[1],$mainservice[2],$mainservice[3],$mainservice[4]];
$dat[] = ["Offerings (Sunday School)",$sundayschool[0],$sundayschool[1],$sundayschool[2],$sundayschool[3],$sundayschool[4]];
$dat[] = ["Love Offerings",$loveoffering[0],$loveoffering[1],$loveoffering[2],$loveoffering[3],$loveoffering[4]];
$dat[] = ["Jumbo Sales",$jumblesales[0],$jumblesales[1],$jumblesales[2],$jumblesales[3],$jumblesales[4]];
$dat[] = ["Donations (Received)",$donationsrecieved[0],$donationsrecieved[1],$donationsrecieved[2],$donationsrecieved[3],$donationsrecieved[4]];
$dat[] = ["Other Income",$otherincome[0],$otherincome[1],$otherincome[2],$otherincome[3],$otherincome[4]];
$dat[] = ["Total Income (100%)",$totalincome[0],$totalincome[1],$totalincome[2],$totalincome[3],$totalincome[4]];
$dat[] = ["General Fund (75%)",
floor(0.75 * $totalincome[0]),
floor(0.75 * $totalincome[1]),
floor(0.75 * $totalincome[2]),
floor(0.75 * $totalincome[3]),
floor(0.75 * $totalincome[4]),
];
$dat[] = ["Church Fund (25%)",
floor(0.25 * $totalincome[0]),
floor(0.25 * $totalincome[1]),
floor(0.25 * $totalincome[2]),
floor(0.25 * $totalincome[3]),
floor(0.25 * $totalincome[4]),
];
echo json_encode([
"draw" => $draw,
"recordsTotal" => count($dat),
"recordsFiltered" => count($dat),
"data" => $dat
]);
}
/* =========================================================
* DONATIONS LISTING (ADMIN)
* ========================================================= */
function donationslisting()
{
$draw = intval($_POST['draw']);
$start = intval($_POST['start']);
$length = intval($_POST['length']);
$searchValue = $_POST['search']['value'] ?? "";
$users = $this->donations_model
->donationsListing("", "ASC", $searchValue, $start, $length);
$total_users = $this->donations_model
->get_total_donations($searchValue);
$dat = [];
$count = $start + 1;
foreach ($users as $r) {
$dat[] = [
$count++,
$r->branchname,
$r->reason,
$r->email,
$r->name,
$r->reference,
$r->amount,
$r->method,
$r->status, // NEW
$r->date
];
}
echo json_encode([
"draw" => $draw,
"recordsTotal" => $total_users,
"recordsFiltered" => $total_users,
"data" => $dat
]);
}
/* =========================================================
* PUBLIC DONATION PAGE
* ========================================================= */
public function donate()
{
$this->load->model('branches_model');
$data['branches'] = $this->branches_model->branchesListing();
$data['settings'] = $this->donations_model->getSettings();
$this->load->view('donate', $data);
}
public function thank_you()
{
$this->load->view('thank_you');
}
/* =========================================================
* SETTINGS
* ========================================================= */
public function update_donations_api()
{
$this->isLoggedIn();
$data['settings'] = $this->donations_model->getSettings();
$this->load->template('donation_settings', $data);
}
function updatedonationSettings()
{
$this->load->library(['session','form_validation']);
$data = [
'paystack_key' => $this->input->post('paystack_key'),
'flutterwaves_key' => $this->input->post('flutterwaves_key'),
'flutterwaves_currency_code' => $this->input->post('flutterwaves_currency_code'),
'paypal_link' => $this->input->post('paypal_link')
];
$this->donations_model->updateSettings($data);
$this->session->set_flashdata(
$this->donations_model->status == 'ok' ? 'success' : 'error',
$this->donations_model->message
);
redirect('update_donations_api');
}
/* =========================================================
* START DONATION (API FOR FLUTTER)
* ========================================================= */
public function start()
{
$this->output->set_content_type('application/json');
// --------------------------------------------------
// READ FORM DATA (CI3 SAFE)
// --------------------------------------------------
$branch = $this->input->post('branch');
$email = $this->input->post('email');
$name = $this->input->post('name');
$amount = $this->input->post('amount');
$reason = $this->input->post('reason');
$reference = $this->input->post('reference');
// --------------------------------------------------
// VALIDATION
// --------------------------------------------------
if (
empty($branch) ||
empty($email) ||
empty($name) ||
empty($amount) ||
empty($reason)
) {
return $this->output->set_output(json_encode([
'status' => 'error',
'message' => 'Missing required fields'
]));
}
if (!$reference) {
$reference = uniqid('DON_', true);
}
// --------------------------------------------------
// PREPARE DONATION RECORD
// --------------------------------------------------
/*$donation = [
'branch' => (int) $branch,
'email' => trim($email),
'name' => trim($name),
'amount' => (int) $amount,
'reason' => trim($reason),
'reference' => $reference,
'method' => 'pesapal',
'status' => 'PENDING',
'date' => date('Y-m-d H:i:s'),
'year' => date('Y'),
'month' => date('n'),
'week' => ceil(date('j') / 7),
];*/
// --------------------------------------------------
// SAVE DONATION (PENDING)
// --------------------------------------------------
//$created = $this->donations_model->createPendingDonation($donation);
$tmpDonation = [
'branch' => (int)$branch,
'email' => trim($email),
'name' => trim($name),
'amount' => (int)$amount,
'currency' => 'UGX',
'reason' => trim($reason),
'reference' => $reference,
'method' => 'PESAPAL',
'status' => 'PENDING'
];
$created = $this->donations_model->createTempDonation($tmpDonation);
if (!$created) {
return $this->output->set_output(json_encode([
'status' => 'error',
'message' => 'Unable to initiate donation'
]));
}
// --------------------------------------------------
// CREATE PESAPAL ORDER
// --------------------------------------------------
$orderPayload = [
'id' => $reference,
'currency' => 'UGX',
'amount' => (int) $amount,
'description' => ucfirst($reason) . ' donation',
// 👇 THIS IS WHERE YOUR IPN ID IS USED
'notification_id' => $this->config->item('pesapal_ipn'),
'callback_url' => site_url('donations/callback'),
'billing_address' => [
'email_address' => $email,
'country_code' => 'UG'
]
];
$order = $this->pesapal->createOrder($orderPayload);
if (!isset($order['redirect_url'])) {
return $this->output->set_output(json_encode([
'status' => 'error',
'message' => 'Unable to initiate payment',
'debug' => $order
]));
}
// --------------------------------------------------
// RETURN PAYMENT URL
// --------------------------------------------------
return $this->output->set_output(json_encode([
'status' => 'success',
'payment_url' => $order['redirect_url'],
'reference' => $reference
]));
}
/* =========================================================
* PESAPAL CALLBACK (USER REDIRECT)
* ========================================================= */
public function callback()
{
$trackingId = $this->input->get('OrderTrackingId');
$reference = $this->input->get('OrderMerchantReference');
// Optional: you can log these if you want
// Do NOT rely on callback for final status
// Redirect user to thank-you page
redirect('donations/thank_you');
}
public function pesapal_ipn()
{
$trackingId = $this->input->get('OrderTrackingId');
$reference = $this->input->get('OrderMerchantReference');
if (!$trackingId || !$reference) {
http_response_code(400);
return;
}
$result = $this->pesapal->verify($trackingId);
$status = strtoupper(
$result['payment_status_description'] ?? 'FAILED'
);
if ($status === 'COMPLETED') {
$this->donations_model->finalizeDonation(
$reference,
$trackingId
);
} else {
// mark temp record as failed
$this->db->where('reference', $reference)
->update('tbl_donations_tmp', [
'status' => 'FAILED',
'order_tracking_id' => $trackingId
]);
}
echo json_encode(['status' => 'ok']);
}
/* =========================================================
* PESAPAL IPN HANDLER (MANDATORY)
* ========================================================= */
public function pesapal_ipnOLD()
{
header('Content-Type: application/json');
$trackingId = $this->input->get('OrderTrackingId');
$reference = $this->input->get('OrderMerchantReference');
if (!$trackingId || !$reference) {
http_response_code(400);
echo json_encode(['status' => 'error']);
return;
}
$result = $this->pesapal->verify($trackingId);
$status = strtoupper(
$result['payment_status_description'] ?? 'FAILED'
);
$this->donations_model->markDonationCompleted(
$reference,
$trackingId,
$status
);
echo json_encode(['status' => 'ok']);
}
public function registerIpn($url)
{
$token = $this->authenticate();
return $this->curl(
$this->baseUrl . '/URLSetup/RegisterIPN',
[
'url' => $url,
'ipn_notification_type' => 'GET'
],
["Authorization: Bearer {$token}"]
);
}
public function register_ipn()
{
$this->load->library('Pesapal');
$token = $this->pesapal->authenticate();
if (!$token) {
echo "Auth failed";
return;
}
$baseUrl =
$this->config->item('pesapal_env') === 'live'
? 'https://pay.pesapal.com/v3/api'
: 'https://cybqa.pesapal.com/pesapalv3/api';
$payload = [
'url' => site_url('pesapal/ipn'),
'ipn_notification_type' => 'GET'
];
$ch = curl_init($baseUrl . '/URLSetup/RegisterIPN');
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_POST => true,
CURLOPT_POSTFIELDS => json_encode($payload),
CURLOPT_HTTPHEADER => [
'Accept: application/json',
'Content-Type: application/json',
"Authorization: Bearer {$token}"
]
]);
$response = curl_exec($ch);
curl_close($ch);
header('Content-Type: application/json');
echo $response;
}
}
Anon7 - 2022
AnonSec Team
