diff --git a/sql/prodnew_db.sql b/sql/prodnew_db.sql new file mode 100644 index 0000000..b4d2bdc --- /dev/null +++ b/sql/prodnew_db.sql @@ -0,0 +1,652 @@ +-- phpMyAdmin SQL Dump +-- version 5.2.1deb3 +-- https://www.phpmyadmin.net/ +-- +-- Host: localhost:3306 +-- Generation Time: Jun 06, 2025 at 11:27 AM +-- Server version: 8.0.42-0ubuntu0.24.04.1 +-- PHP Version: 8.3.6 + +SET SQL_MODE = "NO_AUTO_VALUE_ON_ZERO"; +START TRANSACTION; +SET time_zone = "+00:00"; + + +/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */; +/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */; +/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */; +/*!40101 SET NAMES utf8mb4 */; + +-- +-- Database: `prodnew_db` +-- + +-- -------------------------------------------------------- + +-- +-- Table structure for table `sms_topups` +-- + +CREATE TABLE `sms_topups` ( + `id` int NOT NULL, + `phone_number` varchar(20) NOT NULL, + `sms_units` int NOT NULL, + `reference` varchar(255) NOT NULL, + `status` enum('completed','pending','failed') NOT NULL DEFAULT 'pending', + `created_at` timestamp NULL DEFAULT CURRENT_TIMESTAMP +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci; + +-- -------------------------------------------------------- + +-- +-- Table structure for table `tbl_appconfig` +-- + +CREATE TABLE `tbl_appconfig` ( + `id` int NOT NULL, + `setting` mediumtext CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL, + `value` mediumtext CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci; + +-- -------------------------------------------------------- + +-- +-- Table structure for table `tbl_bandwidth` +-- + +CREATE TABLE `tbl_bandwidth` ( + `id` int UNSIGNED NOT NULL, + `name_bw` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL, + `rate_down` int UNSIGNED NOT NULL, + `rate_down_unit` enum('Kbps','Mbps') CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL, + `rate_up` int UNSIGNED NOT NULL, + `rate_up_unit` enum('Kbps','Mbps') CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL, + `burst` varchar(128) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci; + +-- -------------------------------------------------------- + +-- +-- Table structure for table `tbl_banks` +-- + +CREATE TABLE `tbl_banks` ( + `id` int NOT NULL, + `name` varchar(50) NOT NULL, + `paybill` int NOT NULL +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci; + +-- +-- Dumping data for table `tbl_banks` +-- + +INSERT INTO `tbl_banks` (`id`, `name`, `paybill`) VALUES +(1, 'Equity', 247247), +(2, 'KCB', 522522), +(3, 'Coop', 400200), +(4, 'DTB', 516600), +(5, 'NCBA', 880100), +(6, 'Absa', 303030), +(1, '', 247247), +(2, 'KCB', 522522), +(3, 'Coop', 400200), +(4, 'DTB', 516600), +(5, 'NCBA', 880100), +(6, 'Absa', 303030); + +-- -------------------------------------------------------- + +-- +-- Table structure for table `tbl_customers` +-- + +CREATE TABLE `tbl_customers` ( + `id` int NOT NULL, + `username` varchar(45) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL, + `password` varchar(45) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL, + `pppoe_password` varchar(45) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT 'For PPPOE Login', + `fullname` varchar(45) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL, + `address` mediumtext CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci, + `city` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL, + `district` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL, + `state` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL, + `zip` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL, + `phonenumber` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT '0', + `email` varchar(128) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '1', + `coordinates` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT 'Latitude and Longitude coordinates', + `balance` decimal(15,2) NOT NULL DEFAULT '0.00' COMMENT 'For Money Deposit', + `router_id` int DEFAULT '1', + `service_type` enum('Hotspot','PPPoE','Others') CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT 'Others' COMMENT 'For selecting user type', + `account_type` enum('Business','Personal') CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT 'Personal' COMMENT 'For selecting account type', + `auto_renewal` tinyint(1) NOT NULL DEFAULT '1' COMMENT 'Auto renewall using balance', + `status` enum('Active','Banned','Disabled','Inactive','Limited','Suspended') CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT 'Active', + `created_by` int NOT NULL DEFAULT '0', + `created_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, + `last_login` datetime DEFAULT NULL, + `account` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci; + +-- -------------------------------------------------------- + +-- +-- Table structure for table `tbl_customers_fields` +-- + +CREATE TABLE `tbl_customers_fields` ( + `id` int NOT NULL, + `customer_id` int NOT NULL, + `field_name` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL, + `field_value` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci; + +-- -------------------------------------------------------- + +-- +-- Table structure for table `tbl_logs` +-- + +CREATE TABLE `tbl_logs` ( + `id` int NOT NULL, + `date` datetime DEFAULT NULL, + `type` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL, + `description` mediumtext CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL, + `userid` int NOT NULL, + `ip` mediumtext CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci; + +-- -------------------------------------------------------- + +-- +-- Table structure for table `tbl_message` +-- + +CREATE TABLE `tbl_message` ( + `id` int NOT NULL, + `from_user` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL, + `to_user` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL, + `title` varchar(60) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL, + `message` mediumtext CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL, + `status` enum('0','1') CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '0', + `date` datetime NOT NULL +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci; + +-- -------------------------------------------------------- + +-- +-- Table structure for table `tbl_mpesa_transactions` +-- + +CREATE TABLE `tbl_mpesa_transactions` ( + `id` int NOT NULL, + `TransID` varchar(255) NOT NULL, + `TransactionType` varchar(255) NOT NULL, + `TransTime` varchar(255) NOT NULL, + `TransAmount` decimal(10,2) NOT NULL, + `BusinessShortCode` varchar(255) NOT NULL, + `BillRefNumber` varchar(255) NOT NULL, + `OrgAccountBalance` decimal(10,2) NOT NULL, + `MSISDN` varchar(255) NOT NULL, + `FirstName` varchar(255) NOT NULL, + `CustomerID` varchar(255) NOT NULL, + `PackageName` varchar(255) NOT NULL, + `PackagePrice` varchar(255) NOT NULL, + `TransactionStatus` varchar(255) NOT NULL, + `CreatedAt` timestamp NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci; + +-- -------------------------------------------------------- + +-- +-- Table structure for table `tbl_payment_gateway` +-- + +CREATE TABLE `tbl_payment_gateway` ( + `id` int NOT NULL, + `username` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL, + `gateway` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT 'xendit | midtrans', + `checkout` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL, + `gateway_trx_id` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '', + `plan_id` int NOT NULL, + `plan_name` varchar(40) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL, + `routers_id` int NOT NULL, + `routers` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL, + `price` varchar(40) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL, + `pg_url_payment` varchar(256) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '', + `payment_method` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '', + `payment_channel` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '', + `pg_request` text CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci, + `pg_paid_response` text CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci, + `expired_date` datetime DEFAULT NULL, + `created_date` datetime NOT NULL, + `paid_date` datetime DEFAULT NULL, + `trx_invoice` varchar(25) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT 'from tbl_transactions', + `status` tinyint(1) NOT NULL DEFAULT '1' COMMENT '1 unpaid 2 paid 3 failed 4 canceled' +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci; + +-- -------------------------------------------------------- + +-- +-- Table structure for table `tbl_plans` +-- + +CREATE TABLE `tbl_plans` ( + `id` int NOT NULL, + `name_plan` varchar(40) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL, + `id_bw` int NOT NULL, + `price` varchar(40) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL, + `type` enum('Hotspot','PPPOE','Balance') CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL, + `typebp` enum('Unlimited','Limited') CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL, + `limit_type` enum('Time_Limit','Data_Limit','Both_Limit') CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL, + `time_limit` int UNSIGNED DEFAULT NULL, + `time_unit` enum('Mins','Hrs') CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL, + `data_limit` int UNSIGNED DEFAULT NULL, + `data_unit` enum('MB','GB') CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL, + `validity` int NOT NULL, + `validity_unit` enum('Mins','Hrs','Days','Months','Period') CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL, + `shared_users` int DEFAULT NULL, + `routers` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL, + `is_radius` tinyint(1) NOT NULL DEFAULT '0' COMMENT '1 is radius', + `pool` varchar(40) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL, + `pool_expired` varchar(40) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '', + `list_expired` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT 'address list', + `enabled` tinyint(1) NOT NULL DEFAULT '1' COMMENT '0 disabled', + `allow_purchase` enum('yes','no') CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT 'yes' COMMENT 'allow to show package in buy package page', + `prepaid` enum('yes','no') CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT 'yes' COMMENT 'is prepaid', + `plan_type` enum('Business','Personal') CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT 'Personal' COMMENT 'For switching plan according to user type' +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci; + +-- -------------------------------------------------------- + +-- +-- Table structure for table `tbl_pool` +-- + +CREATE TABLE `tbl_pool` ( + `id` int NOT NULL, + `pool_name` varchar(40) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL, + `range_ip` varchar(40) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL, + `routers` varchar(40) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci; + +-- -------------------------------------------------------- + +-- +-- Table structure for table `tbl_routers` +-- + +CREATE TABLE `tbl_routers` ( + `id` int NOT NULL, + `name` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL, + `ip_address` varchar(128) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL, + `username` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL, + `password` varchar(60) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL, + `description` varchar(256) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL, + `enabled` tinyint(1) NOT NULL DEFAULT '1' COMMENT '0 disabled', + `status` enum('Online','Offline') CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT 'Offline', + `last_check` datetime DEFAULT NULL, + `offline_since` datetime DEFAULT NULL +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci; + +-- -------------------------------------------------------- + +-- +-- Table structure for table `tbl_transactions` +-- + +CREATE TABLE `tbl_transactions` ( + `id` int NOT NULL, + `invoice` varchar(25) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL, + `username` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL, + `plan_name` varchar(40) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL, + `price` varchar(40) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL, + `recharged_on` date NOT NULL, + `recharged_time` time NOT NULL DEFAULT '00:00:00', + `expiration` date NOT NULL, + `time` time NOT NULL, + `method` varchar(128) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL, + `routers` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL, + `type` enum('Hotspot','PPPOE','Balance') CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL, + `note` varchar(256) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT 'for note', + `admin_id` int NOT NULL DEFAULT '1' +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci; + +-- -------------------------------------------------------- + +-- +-- Table structure for table `tbl_users` +-- + +CREATE TABLE `tbl_users` ( + `id` int UNSIGNED NOT NULL, + `root` int NOT NULL DEFAULT '0' COMMENT 'for sub account', + `username` varchar(45) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '', + `fullname` varchar(45) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '', + `password` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL, + `phone` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '', + `email` varchar(128) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '', + `city` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT 'kota', + `subdistrict` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT 'kecamatan', + `ward` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT 'kelurahan', + `user_type` enum('SuperAdmin','Admin','Report','Agent','Sales') CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL, + `status` enum('Active','Inactive') CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT 'Active', + `last_login` datetime DEFAULT NULL, + `creationdate` datetime NOT NULL +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci; + +-- +-- Dumping data for table `tbl_users` +-- + +INSERT INTO `tbl_users` (`id`, `root`, `username`, `fullname`, `password`, `phone`, `email`, `city`, `subdistrict`, `ward`, `user_type`, `status`, `last_login`, `creationdate`) VALUES +(4, 0, 'demo', 'demo', '6ea7ccdcf642953a24672d10b0d32cef576e0329', '1234567890', 'demo@example.com', '', '', '', 'Admin', 'Active', '2025-06-04 12:06:36', '2025-05-26 09:24:13'); + +-- -------------------------------------------------------- + +-- +-- Table structure for table `tbl_user_data_usage` +-- + +CREATE TABLE `tbl_user_data_usage` ( + `id` int NOT NULL, + `username` varchar(255) NOT NULL, + `bytes_in` bigint NOT NULL, + `bytes_out` bigint NOT NULL, + `connection_type` enum('hotspot','pppoe') NOT NULL, + `timestamp` datetime NOT NULL, + `last_updated` datetime NOT NULL +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci; + +-- -------------------------------------------------------- + +-- +-- Table structure for table `tbl_user_recharges` +-- + +CREATE TABLE `tbl_user_recharges` ( + `id` int NOT NULL, + `customer_id` int NOT NULL, + `username` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL, + `plan_id` int NOT NULL, + `namebp` varchar(40) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL, + `recharged_on` date NOT NULL, + `recharged_time` time NOT NULL DEFAULT '00:00:00', + `expiration` date NOT NULL, + `time` time NOT NULL, + `status` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL, + `method` varchar(128) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '', + `routers` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL, + `type` varchar(15) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL, + `admin_id` int NOT NULL DEFAULT '1' +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci; + +-- -------------------------------------------------------- + +-- +-- Table structure for table `tbl_voucher` +-- + +CREATE TABLE `tbl_voucher` ( + `id` int NOT NULL, + `type` enum('Hotspot','PPPOE') CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL, + `routers` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL, + `id_plan` int NOT NULL, + `code` varchar(55) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL, + `user` varchar(45) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL, + `status` varchar(25) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL, + `generated_by` int NOT NULL DEFAULT '0' COMMENT 'id admin' +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci; + +-- -------------------------------------------------------- + +-- +-- Table structure for table `tb_languages` +-- + +CREATE TABLE `tb_languages` ( + `id` int NOT NULL +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci; + +-- -------------------------------------------------------- + +-- +-- Table structure for table `user_sms_balance` +-- + +CREATE TABLE `user_sms_balance` ( + `id` int NOT NULL, + `phone_number` varchar(20) NOT NULL, + `sms_balance` int NOT NULL DEFAULT '0', + `updated_at` timestamp NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci; + +-- +-- Indexes for dumped tables +-- + +-- +-- Indexes for table `sms_topups` +-- +ALTER TABLE `sms_topups` + ADD PRIMARY KEY (`id`); + +-- +-- Indexes for table `tbl_appconfig` +-- +ALTER TABLE `tbl_appconfig` + ADD PRIMARY KEY (`id`); + +-- +-- Indexes for table `tbl_bandwidth` +-- +ALTER TABLE `tbl_bandwidth` + ADD PRIMARY KEY (`id`); + +-- +-- Indexes for table `tbl_customers` +-- +ALTER TABLE `tbl_customers` + ADD PRIMARY KEY (`id`); + +-- +-- Indexes for table `tbl_customers_fields` +-- +ALTER TABLE `tbl_customers_fields` + ADD PRIMARY KEY (`id`), + ADD KEY `customer_id` (`customer_id`); + +-- +-- Indexes for table `tbl_logs` +-- +ALTER TABLE `tbl_logs` + ADD PRIMARY KEY (`id`); + +-- +-- Indexes for table `tbl_message` +-- +ALTER TABLE `tbl_message` + ADD PRIMARY KEY (`id`); + +-- +-- Indexes for table `tbl_mpesa_transactions` +-- +ALTER TABLE `tbl_mpesa_transactions` + ADD PRIMARY KEY (`id`); + +-- +-- Indexes for table `tbl_payment_gateway` +-- +ALTER TABLE `tbl_payment_gateway` + ADD PRIMARY KEY (`id`); + +-- +-- Indexes for table `tbl_plans` +-- +ALTER TABLE `tbl_plans` + ADD PRIMARY KEY (`id`); + +-- +-- Indexes for table `tbl_pool` +-- +ALTER TABLE `tbl_pool` + ADD PRIMARY KEY (`id`); + +-- +-- Indexes for table `tbl_routers` +-- +ALTER TABLE `tbl_routers` + ADD PRIMARY KEY (`id`); + +-- +-- Indexes for table `tbl_transactions` +-- +ALTER TABLE `tbl_transactions` + ADD PRIMARY KEY (`id`); + +-- +-- Indexes for table `tbl_users` +-- +ALTER TABLE `tbl_users` + ADD PRIMARY KEY (`id`); + +-- +-- Indexes for table `tbl_user_data_usage` +-- +ALTER TABLE `tbl_user_data_usage` + ADD PRIMARY KEY (`id`), + ADD KEY `username` (`username`,`connection_type`,`timestamp`); + +-- +-- Indexes for table `tbl_user_recharges` +-- +ALTER TABLE `tbl_user_recharges` + ADD PRIMARY KEY (`id`); + +-- +-- Indexes for table `tbl_voucher` +-- +ALTER TABLE `tbl_voucher` + ADD PRIMARY KEY (`id`); + +-- +-- Indexes for table `user_sms_balance` +-- +ALTER TABLE `user_sms_balance` + ADD PRIMARY KEY (`id`), + ADD UNIQUE KEY `phone_number` (`phone_number`); + +-- +-- AUTO_INCREMENT for dumped tables +-- + +-- +-- AUTO_INCREMENT for table `sms_topups` +-- +ALTER TABLE `sms_topups` + MODIFY `id` int NOT NULL AUTO_INCREMENT; + +-- +-- AUTO_INCREMENT for table `tbl_appconfig` +-- +ALTER TABLE `tbl_appconfig` + MODIFY `id` int NOT NULL AUTO_INCREMENT; + +-- +-- AUTO_INCREMENT for table `tbl_bandwidth` +-- +ALTER TABLE `tbl_bandwidth` + MODIFY `id` int UNSIGNED NOT NULL AUTO_INCREMENT; + +-- +-- AUTO_INCREMENT for table `tbl_customers` +-- +ALTER TABLE `tbl_customers` + MODIFY `id` int NOT NULL AUTO_INCREMENT; + +-- +-- AUTO_INCREMENT for table `tbl_customers_fields` +-- +ALTER TABLE `tbl_customers_fields` + MODIFY `id` int NOT NULL AUTO_INCREMENT; + +-- +-- AUTO_INCREMENT for table `tbl_logs` +-- +ALTER TABLE `tbl_logs` + MODIFY `id` int NOT NULL AUTO_INCREMENT; + +-- +-- AUTO_INCREMENT for table `tbl_message` +-- +ALTER TABLE `tbl_message` + MODIFY `id` int NOT NULL AUTO_INCREMENT; + +-- +-- AUTO_INCREMENT for table `tbl_mpesa_transactions` +-- +ALTER TABLE `tbl_mpesa_transactions` + MODIFY `id` int NOT NULL AUTO_INCREMENT; + +-- +-- AUTO_INCREMENT for table `tbl_payment_gateway` +-- +ALTER TABLE `tbl_payment_gateway` + MODIFY `id` int NOT NULL AUTO_INCREMENT; + +-- +-- AUTO_INCREMENT for table `tbl_plans` +-- +ALTER TABLE `tbl_plans` + MODIFY `id` int NOT NULL AUTO_INCREMENT; + +-- +-- AUTO_INCREMENT for table `tbl_pool` +-- +ALTER TABLE `tbl_pool` + MODIFY `id` int NOT NULL AUTO_INCREMENT; + +-- +-- AUTO_INCREMENT for table `tbl_routers` +-- +ALTER TABLE `tbl_routers` + MODIFY `id` int NOT NULL AUTO_INCREMENT; + +-- +-- AUTO_INCREMENT for table `tbl_transactions` +-- +ALTER TABLE `tbl_transactions` + MODIFY `id` int NOT NULL AUTO_INCREMENT; + +-- +-- AUTO_INCREMENT for table `tbl_users` +-- +ALTER TABLE `tbl_users` + MODIFY `id` int UNSIGNED NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=5; + +-- +-- AUTO_INCREMENT for table `tbl_user_data_usage` +-- +ALTER TABLE `tbl_user_data_usage` + MODIFY `id` int NOT NULL AUTO_INCREMENT; + +-- +-- AUTO_INCREMENT for table `tbl_user_recharges` +-- +ALTER TABLE `tbl_user_recharges` + MODIFY `id` int NOT NULL AUTO_INCREMENT; + +-- +-- AUTO_INCREMENT for table `tbl_voucher` +-- +ALTER TABLE `tbl_voucher` + MODIFY `id` int NOT NULL AUTO_INCREMENT; + +-- +-- AUTO_INCREMENT for table `user_sms_balance` +-- +ALTER TABLE `user_sms_balance` + MODIFY `id` int NOT NULL AUTO_INCREMENT; +COMMIT; + +/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */; +/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */; +/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */; diff --git a/system/lan/country.json b/system/lan/country.json new file mode 100644 index 0000000..f9f798b --- /dev/null +++ b/system/lan/country.json @@ -0,0 +1,59 @@ +{ + "english": "en", + "indonesia": "id", + "spanish": "es", + "turkish": "tr", + "amharic": "am", + "arabic": "ar", + "basque": "eu", + "bengali": "bn", + "english-uk": "en-gb", + "portuguese-brazil": "pt-br", + "bulgarian": "bg", + "catalan": "ca", + "cherokee": "chr", + "croatian": "hr", + "czech": "cs", + "danish": "da", + "dutch": "nl", + "estonian": "et", + "filipino": "fil", + "finnish": "fi", + "french": "fr", + "german": "de", + "greek": "el", + "gujarati": "gu", + "hebrew": "iw", + "hindi": "hi", + "hungarian": "hu", + "iran": "ir", + "icelandic": "is", + "italian": "it", + "japanese": "ja", + "kannada": "kn", + "korean": "ko", + "latvian": "lv", + "lithuanian": "lt", + "malay": "ms", + "malayalam": "ml", + "marathi": "mr", + "norwegian": "no", + "polish": "pl", + "portuguese (portugal)": "pt-pt", + "romanian": "ro", + "russian": "ru", + "serbian": "sr", + "chinese (prc)": "zh-cn", + "slovak": "sk", + "slovenian": "sl", + "swahili": "sw", + "swedish": "sv", + "tamil": "ta", + "telugu": "te", + "thai": "th", + "chinese-taiwan": "zh-tw", + "urdu": "ur", + "ukrainian": "uk", + "vietnamese": "vi", + "welsh": "cy" +} diff --git a/system/lan/english.json b/system/lan/english.json new file mode 100644 index 0000000..89ac03b --- /dev/null +++ b/system/lan/english.json @@ -0,0 +1,803 @@ +{ + "Log_in": "Login", + "Register": "Register", + "Announcement": "Announcement", + "Registration_Info": "Registration Info", + "Voucher_not_found__please_buy_voucher_befor_register": "Voucher not found, please buy voucher befor register", + "Register_Success__You_can_login_now": "Register Success! You can login now", + "Log_in_to_Member_Panel": "Log in to Member Panel", + "Register_as_Member": "Register as Member", + "Enter_Admin_Area": "Enter Admin Area", + "PHPNuxBill": "PHPNuxBill", + "Username": "Username", + "Password": "Password", + "Passwords_does_not_match": "Passwords does not match", + "Account_already_axist": "Account already axist", + "Manage": "Manage", + "Submit": "Submit", + "Save_Changes": "Save Changes", + "Cancel": "Cancel", + "Edit": "Edit", + "Delete": "Delete", + "Welcome": "Welcome", + "Data_Created_Successfully": "Data Created Successfully", + "Data_Updated_Successfully": "Data Updated Successfully", + "Data_Deleted_Successfully": "Data Deleted Successfully", + "Static_Pages": "Static Pages", + "Failed_to_save_page__make_sure_i_can_write_to_folder_pages___i_chmod_664_pages___html_i_": "Failed to save page, make sure i can write to folder pages, chmod 664 pages\/*.html", + "Saving_page_success": "Saving page success", + "Sometimes_you_need_to_refresh_3_times_until_content_change": "Sometimes you need to refresh 3 times until content change", + "Dashboard": "Dashboard", + "Search_Customers___": "Search Customers...", + "My_Account": "My Account", + "My_Profile": "My Profile", + "Settings": "Settings", + "Edit_Profile": "Edit Profile", + "Change_Password": "Change Password", + "Logout": "Logout", + "Services": "Services", + "Bandwidth_Plans": "Bandwidth Plans", + "Bandwidth_Name": "Bandwidth Name", + "New_Bandwidth": "New Bandwidth", + "Edit_Bandwidth": "Edit Bandwidth", + "Add_New_Bandwidth": "Add New Bandwidth", + "Rate_Download": "Rate Download", + "Rate_Upload": "Rate Upload", + "Name_Bandwidth_Already_Exist": "Name Bandwidth Already Exist", + "Hotspot_Plans": "Hotspot Plans", + "PPPOE_Plans": "PPPOE Plans", + "Plan_Name": "Plan Name", + "New_Service_Plan": "New Service Plan", + "Add_Service_Plan": "Add Service Plan", + "Edit_Service_Plan": "Edit Service Plan", + "Name_Plan_Already_Exist": "Name Plan Already Exist", + "Plan_Type": "Plan Type", + "Plan_Price": "Plan Price", + "Limit_Type": "Limit Type", + "Unlimited": "Unlimited", + "Limited": "Limited", + "Time_Limit": "Time Limit", + "Data_Limit": "Data Limit", + "Both_Limit": "Both Limit", + "Plan_Validity": "Plan Validity", + "Select_Bandwidth": "Select Bandwidth", + "Shared_Users": "Shared Users", + "Choose_User_Type_Sales_to_disable_access_to_Settings": "Choose User Type Sales to disable access to Settings", + "Current_Password": "Current Password", + "New_Password": "New Password", + "Administrator": "Administrator", + "Sales": "Sales", + "Member": "Member", + "Confirm_New_Password": "Confirm New Password", + "Confirm_Password": "Confirm Password", + "Full_Name": "Full Name", + "User_Type": "User Type", + "Address": "Address", + "Created_On": "Created On", + "Expires_On": "Expires On", + "Phone_Number": "Phone Number", + "User_deleted_Successfully": "User deleted Successfully", + "Full_Administrator": "Full Administrator", + "Keep_Blank_to_do_not_change_Password": "Keep Blank to do not change Password", + "Keep_it_blank_if_you_do_not_want_to_show_currency_code": "Keep it blank if you do not want to show currency code", + "Theme_Style": "Theme Style", + "Theme_Color": "Theme Color", + "Default_Language": "Default Language", + "Network": "Network", + "Routers": "Routers", + "IP_Pool": "IP Pool", + "New_Router": "New Router", + "Add_Router": "Add Router", + "Edit_Router": "Edit Router", + "Router_Name": "Router Name", + "IP_Address": "IP Address", + "Router_Secret": "Router Secret", + "Description": "Description", + "IP_Router_Already_Exist": "IP Router Already Exist", + "Name_Pool": "Name Pool", + "Range_IP": "Range IP", + "New_Pool": "New Pool", + "Add_Pool": "Add Pool", + "Edit_Pool": "Edit Pool", + "Pool_Name_Already_Exist": "Pool Name Already Exist", + "Refill_Account": "Refill Account", + "Recharge_Account": "Recharge Account", + "Select_Account": "Select Account", + "Service_Plan": "Service Plan", + "Recharge": "Recharge", + "Method": "Method", + "Account_Created_Successfully": "Account Created Successfully", + "Database_Status": "Database Status", + "Total_Database_Size": "Total Database Size", + "Download_Database_Backup": "Download Database Backup", + "Table_Name": "Table Name", + "Rows": "Rows", + "Size": "Size", + "Customer": "Customer", + "Add_New_Contact": "Add New Contact", + "Edit_Contact": "Edit Contact", + "List_Contact": "List Contact", + "Manage_Contact": "Manage Contact", + "Reports": "Reports", + "Daily_Reports": "Daily Reports", + "Period_Reports": "Period Reports", + "All_Transactions": "All Transactions", + "Total_Income": "Total Income", + "All_Transactions_at_Date": "All Transactions at Date", + "Export_for_Print": "Export for Print", + "Print": "Print", + "Export_to_PDF": "Export to PDF", + "Click_Here_to_Print": "Click Here to Print", + "You_can_use_html_tag": "You can use html tag", + "Date_Format": "Date Format", + "Income_Today": "Income Today", + "Income_This_Month": "Income This Month", + "Users_Active": "Users Active", + "Total_Users": "Total Users", + "Users": "Users", + "Edit_User": "Edit User", + "Last_Login": "Last Login", + "Administrator_Users": "Administrator Users", + "Manage_Administrator": "Manage Administrator", + "Add_New_Administrator": "Add New Administrator", + "Localisation": "Localisation", + "Backup_Restore": "Backup\/Restore", + "General_Settings": "General Settings", + "Date": "Date", + "Login_Successful": "Login Successful", + "Failed_Login": "Failed Login", + "Settings_Saved_Successfully": "Settings Saved Successfully", + "User_Updated_Successfully": "User Updated Successfully", + "User_Expired__Today": "User Expired, Today", + "Activity_Log": "Activity Log", + "View_Reports": "View Reports", + "View_All": "View All", + "Number_of_Vouchers": "Number of Vouchers", + "Length_Code": "Length Code", + "Code_Voucher": "Code Voucher", + "Voucher": "Voucher", + "Hotspot_Voucher": "Hotspot Voucher", + "Status_Voucher": "Status Voucher", + "Add_Vouchers": "Add Vouchers", + "Create_Vouchers_Successfully": "Create Vouchers Successfully", + "Generate": "Generate", + "Print_side_by_side__it_will_easy_to_cut": "Print side by side, it will easy to cut", + "From_Date": "From Date", + "To_Date": "To Date", + "New_Service": "New Service", + "Type": "Type", + "Finish": "Finish", + "Application_Name__Company_Name": "Application Name\/ Company Name", + "This_Name_will_be_shown_on_the_Title": "This Name will be shown on the Title", + "Next": "Next", + "Last": "Last", + "Timezone": "Timezone", + "Decimal_Point": "Decimal Point", + "Thousands_Separator": "Thousands Separator", + "Currency_Code": "Currency Code", + "Order_Voucher": "Order Voucher", + "Voucher_Activation": "Voucher Activation", + "List_Activated_Voucher": "List Activated Voucher", + "Enter_voucher_code_here": "Enter voucher code here", + "Private_Message": "Private Message", + "Inbox": "Inbox", + "Outbox": "Outbox", + "Compose": "Compose", + "Send_to": "Send to", + "Title": "Title", + "Message": "Message", + "Your_Account_Information": "Your Account Information", + "Welcome_to_the_Panel_Members_page__on_this_page_you_can_": "Welcome to the Panel Members page, on this page you can:", + "Invalid_Username_or_Password": "Invalid Username or Password", + "You_do_not_have_permission_to_access_this_page": "You do not have permission to access this page", + "Incorrect_Current_Password": "Incorrect Current Password", + "Password_changed_successfully__Please_login_again": "Password changed successfully, Please login again", + "All_field_is_required": "All field is required", + "Voucher_Not_Valid": "Voucher Not Valid", + "Activation_Vouchers_Successfully": "Activation Vouchers Successfully", + "Data_Not_Found": "Data Not Found", + "Search_by_Username": "Search by Username", + "Search_by_Name": "Search by Name", + "Search_by_Code_Voucher": "Search by Code Voucher", + "Search": "Search", + "Select_a_customer": "Select a customer", + "Select_Routers": "Select Routers", + "Select_Plans": "Select Plans", + "Select_Pool": "Select Pool", + "Hrs": "Hrs", + "Mins": "Mins", + "Days": "Days", + "Months": "Months", + "Add_Language": "Add Language", + "Language_Name": "Language Name", + "Folder_Name": "Folder Name", + "Translator": "Translator", + "Language_Name_Already_Exist": "Language Name Already Exist", + "Payment_Gateway": "Payment Gateway", + "Community": "Community", + "1_user_can_be_used_for_many_devices_": "1 user can be used for many devices?", + "Cannot_be_change_after_saved": "Cannot be change after saved", + "Explain_Coverage_of_router": "Explain Coverage of router", + "Name_of_Area_that_router_operated": "Name of Area that router operated", + "Payment_Notification_URL__Recurring_Notification_URL__Pay_Account_Notification_URL": "Payment Notification URL, Recurring Notification URL, Pay Account Notification URL", + "Finish_Redirect_URL__Unfinish_Redirect_URL__Error_Redirect_URL": "Finish Redirect URL, Unfinish Redirect URL, Error Redirect URL", + "Status": "Status", + "Plan_Not_found": "Plan Not found", + "Failed_to_create_transaction_": "Failed to create transaction.", + "Seller_has_not_yet_setup_Xendit_payment_gateway": "Seller has not yet setup Xendit payment gateway", + "Admin_has_not_yet_setup_Xendit_payment_gateway__please_tell_admin": "Admin has not yet setup Xendit payment gateway, please tell admin", + "You_already_have_unpaid_transaction__cancel_it_or_pay_it_": "You already have unpaid transaction, cancel it or pay it.", + "Transaction_Not_found": "Transaction Not found", + "Cancel_it_": "Cancel it?", + "expired": "expired", + "Check_for_Payment": "Check for Payment", + "Transaction_still_unpaid_": "Transaction still unpaid.", + "Paid_Date": "Paid Date", + "Transaction_has_been_paid_": "Transaction has been paid.", + "PAID": "PAID", + "CANCELED": "CANCELED", + "UNPAID": "UNPAID", + "PAY_NOW": "PAY NOW", + "Buy_Hotspot_Plan": "Buy Hotspot Plan", + "Buy_PPOE_Plan": "Buy PPOE Plan", + "Package": "Package", + "Order_Internet_Package": "Order Internet Package", + "Unknown_Command_": "Unknown Command.", + "Checking_payment": "Checking payment", + "Create_Transaction_Success": "Create Transaction Success", + "You_have_unpaid_transaction": "You have unpaid transaction", + "TripayPayment_Channel": "TripayPayment Channel", + "Payment_Channel": "Payment Channel", + "Payment_check_failed_": "Payment check failed.", + "Order_Package": "Order Package", + "Transactions": "Transactions", + "Payments": "Payments", + "History": "History", + "Order_History": "Order History", + "Gateway": "Gateway", + "Date_Done": "Date Done", + "Unpaid_Order": "Unpaid Order", + "Payment_Gateway_Not_Found": "Payment Gateway Not Found", + "Payment_Gateway_saved_successfully": "Payment Gateway saved successfully", + "ORDER": "ORDER", + "Package_History": "Package History", + "Buy_History": "Buy History", + "Activation_History": "Activation History", + "Buy_Package": "Buy Package", + "Email": "Email", + "Company_Footer": "Company Footer", + "Will_show_below_user_pages": "Will show below user pages", + "Request_OTP": "Request OTP", + "Verification_Code": "Verification Code", + "SMS_Verification_Code": "SMS Verification Code", + "Please_enter_your_email_address": "Please enter your email address", + "Failed_to_create_Paypal_transaction_": "Failed to create Paypal transaction.", + "Plugin": "Plugin", + "Plugin_Manager": "Plugin Manager", + "User_Notification": "User Notification", + "Expired_Notification": "Expired Notification", + "User_will_get_notification_when_package_expired": "User will get notification when package expired", + "Expired_Notification_Message": "Expired Notification Message", + "Payment_Notification": "Payment Notification", + "User_will_get_invoice_notification_when_buy_package_or_package_refilled": "User will get invoice notification when buy package or package refilled", + "Current_IP": "Current IP", + "Current_MAC": "Current MAC", + "Login_Status": "Login Status", + "Login_Request_successfully": "Login Request successfully", + "Logout_Request_successfully": "Logout Request successfully", + "Disconnect_Internet_": "Disconnect Internet?", + "Not_Online__Login_now_": "Not Online, Login now?", + "You_are_Online__Logout_": "You are Online, Logout?", + "Connect_to_Internet_": "Connect to Internet?", + "Your_account_not_connected_to_internet": "Your account not connected to internet", + "Failed_to_create_transaction__": "Failed to create transaction. ", + "Failed_to_check_status_transaction__": "Failed to check status transaction. ", + "Disable_Voucher": "Disable Voucher", + "Balance": "Balance", + "Balance_System": "Balance System", + "Enable_System": "Enable System", + "Allow_Transfer": "Allow Transfer", + "Telegram_Notification": "Telegram Notification", + "SMS_OTP_Registration": "SMS OTP Registration", + "Whatsapp_Notification": "Whatsapp Notification", + "Tawk_to_Chat_Widget": "Tawk.to Chat Widget", + "Invoice": "Invoice", + "Country_Code_Phone": "Country Code Phone", + "Voucher_activation_menu_will_be_hidden": "Voucher activation menu will be hidden", + "Customer_can_deposit_money_to_buy_voucher": "Customer can deposit money to buy voucher", + "Allow_balance_transfer_between_customers": "Allow balance transfer between customers", + "Reminder_Notification": "Reminder Notification", + "Reminder_Notification_Message": "Reminder Notification Message", + "Reminder_7_days": "Reminder 7 days", + "Reminder_3_days": "Reminder 3 days", + "Reminder_1_day": "Reminder 1 day", + "PPPOE_Password": "PPPOE Password", + "User_Cannot_change_this__only_admin__if_it_Empty_it_will_use_user_password": "User Cannot change this, only admin. if it Empty it will use user password", + "Invoice_Balance_Message": "Invoice Balance Message", + "Invoice_Notification_Payment": "Invoice Notification Payment", + "Balance_Notification_Payment": "Balance Notification Payment", + "Balance_Plans": "Balance Plans", + "Buy_Balance": "Buy Balance", + "Price": "Price", + "Validity": "Validity", + "Disable_auto_renewal_": "Disable auto renewal?", + "Auto_Renewal_On": "Auto Renewal On", + "Enable_auto_renewal_": "Enable auto renewal?", + "Auto_Renewal_Off": "Auto Renewal Off", + "Refill_Balance": "Refill Balance", + "Invoice_Footer": "Invoice Footer", + "Pay_With_Balance": "Pay With Balance", + "Pay_this_with_Balance__your_active_package_will_be_overwrite": "Pay this with Balance? your active package will be overwrite", + "Success_to_buy_package": "Success to buy package", + "Auto_Renewal": "Auto Renewal", + "View": "View", + "Back": "Back", + "Active": "Active", + "Transfer_Balance": "Transfer Balance", + "Send_your_balance_": "Send your balance?", + "Send": "Send", + "Cannot_send_to_yourself": "Cannot send to yourself", + "Sending_balance_success": "Sending balance success", + "From": "From", + "To": "To", + "insufficient_balance": "insufficient balance", + "Send_Balance": "Send Balance", + "Received_Balance": "Received Balance", + "Minimum_Balance_Transfer": "Minimum Balance Transfer", + "Minimum_Transfer": "Minimum Transfer", + "Company_Logo": "Company Logo", + "Expired_IP_Pool": "Expired IP Pool", + "Proxy": "Proxy", + "Proxy_Server": "Proxy Server", + "Proxy_Server_Login": "Proxy Server Login", + "Hotspot_Plan": "Hotspot Plan", + "PPPOE_Plan": "PPPOE Plan", + "UNKNOWN": "UNKNOWN", + "Are_You_Sure_": "Are You Sure?", + "Success_to_send_package": "Success to send package", + "Target_has_active_plan__different_with_current_plant_": "Target has active plan, different with current plant.", + "Recharge_a_friend": "Recharge a friend", + "Buy_for_friend": "Buy for friend", + "Buy_this_for_friend_account_": "Buy this for friend account?", + "Review_package_before_recharge": "Review package before recharge", + "Activate": "Activate", + "Deactivate": "Deactivate", + "Sync": "Sync", + "Failed_to_create_PaymeTrust_transaction_": "Failed to create PaymeTrust transaction.", + "Location": "Location", + "Radius_Plans": "Radius Plans", + "Change_title_in_user_Plan_order": "Change title in user Plan order", + "Logs": "Logs", + "Voucher_Format": "Voucher Format", + "Resend_To_Customer": "Resend To Customer", + "Your_friend_do_not_have_active_package": "Your friend do not have active package", + "Service_Type": "Service Type", + "Others": "Others", + "PPPoE": "PPPoE", + "Hotspot": "Hotspot", + "Disable_Registration": "Disable Registration", + "Customer_just_Login_with_Phone_number_and_Voucher_Code__Voucher_will_be_password": "Customer just Login with Phone number and Voucher Code, Voucher will be password", + "Login___Activate_Voucher": "Login \/ Activate Voucher", + "After_Customer_activate_voucher_or_login__customer_will_be_redirected_to_this_url": "After Customer activate voucher or login, customer will be redirected to this url", + "Voucher_Prefix": "Voucher Prefix", + "Voucher_activation_success__now_you_can_login": "Voucher activation success, now you can login", + "Buy_this__your_active_package_will_be_overwritten": "Buy this? your active package will be overwritten", + "Pay_this_with_Balance__your_active_package_will_be_overwritten": "Pay this with Balance? your active package will be overwritten", + "Buy_this__your_active_package_will_be_overwrite": "Buy this? your active package will be overwrite", + "Monthly_Registered_Customers": "Monthly Registered Customers", + "Total_Monthly_Sales": "Total Monthly Sales", + "Active_Users": "Active Users", + "All_Users_Insights": "All Users Insights", + "SuperAdmin": "Super Admin", + "Radius": "Radius", + "Radius_NAS": "Radius NAS", + "Translation": "Translation", + "Translation_saved_Successfully": "Translation saved Successfully", + "Language_Editor": "Language Editor", + "year": "year", + "month": "month", + "week": "week", + "day": "day", + "hour": "hour", + "minute": "minute", + "second": "second", + "Attributes": "Attributes", + "Profile": "Profile", + "Phone": "Phone", + "City": "City", + "Sub_District": "Sub District", + "Ward": "Ward", + "Credentials": "Credentials", + "Agent": "Agent", + "This_Token_will_act_as_SuperAdmin_Admin": "This Token will act as SuperAdmin\/Admin", + "Login": "Login", + "Expired_Action": "Expired Action", + "Expired_Address_List_Name": "Expired Address List Name", + "Address_List": "Address List", + "Optional": "Optional", + "Generated_By": "Generated By", + "Admin": "Admin", + "Password_should_be_minimum_6_characters": "Password should be minimum 6 characters", + "Add_User": "Add User", + "Send_Notification": "Send Notification", + "Code": "Code", + "Send_To_Customer": "Send To Customer", + "Prev": "Prev", + "Voucher_Not_Found": "Voucher Not Found", + "Miscellaneous": "Miscellaneous", + "OTP_Required": "OTP Required", + "Change": "Change", + "Change_Phone_Number": "Change Phone Number", + "Current_Number": "Current Number", + "New_Number": "New Number", + "Input_your_phone_number": "Input your phone number", + "OTP": "OTP", + "Enter_OTP_that_was_sent_to_your_phone": "Enter OTP that was sent to your phone", + "Update": "Update", + "OTP_is_required_when_user_want_to_change_phone_number": "OTP is required when user want to change phone number", + "Rate": "Rate", + "Burst": "Burst", + "Editing_Bandwidth_will_not_automatically_update_the_plan__you_need_to_edit_the_plan_then_save_again": "Editing Bandwidth will not automatically update the plan, you need to edit the plan then save again", + "OTP_Method": "OTP Method", + "SMS": "SMS", + "WhatsApp": "WhatsApp", + "SMS_and_WhatsApp": "SMS and WhatsApp", + "The_method_which_OTP_will_be_sent_to_user": "The method which OTP will be sent to user", + "Report_Viewer": "Report Viewer", + "Super_Administrator": "Super Administrator", + "Send_To": "Send To", + "Resend": "Resend", + "Alert": "Alert", + "success": "success", + "Click_Here": "Click Here", + "danger": "danger", + "Logout_Successful": "Logout Successful", + "warning": "warning", + "Users_Announcement": "Users Announcement", + "Customer_Announcement": "Customer Announcement", + "1_Period___1_Month__Expires_the_20th_of_each_month": "1 Period = 1 Month, Expires the 20th of each month", + "Period": "Period", + "Add": "Add", + "Select_Payment_Gateway": "Select Payment Gateway", + "Available_Payment_Gateway": "Available Payment Gateway", + "Pay_Now": "Pay Now", + "Please_select_Payment_Gateway": "Please select Payment Gateway", + "Payment_Gateway_Deleted": "Payment Gateway Deleted", + "Payment_Gateway_not_set__please_set_it_in_Settings": "Payment Gateway not set, please set it in Settings", + "Failed_to_create_Transaction__": "Failed to create Transaction..", + "Show_To_Customer": "Type", + "Using": "Using", + "Default": "Default", + "Customer_Balance": "Customer Balance", + "Vouchers": "Vouchers", + "Refill_Customer": "Refill Customer", + "Recharge_Customer": "Recharge Customer", + "Plans": "Plans", + "PPPOE": "PPPOE", + "Bandwidth": "Bandwidth", + "Customers": "Customers", + "Actives": "Actives", + "Name": "Name", + "Confirm": "Confirm", + "Plan": "Plan", + "Total": "Total", + "Current_Cycle": "Current Cycle", + "Additional_Cost": "Additional Cost", + "Remaining": "Remaining", + "Not_Found": "Not Found", + "Cash": "Cash", + "Payment_not_found": "Payment not found", + "If_your_friend_have_Additional_Cost__you_will_pay_for_that_too": "If your friend have Additional Cost, you will pay for that too", + "Cache_cleared_successfully_": "Cache cleared successfully!", + "Paid": "Paid", + "Send_Message": "Send Message", + "Send_Personal_Message": "Send Personal Message", + "Send_Via": "Send Via", + "Compose_your_message___": "Compose your message...", + "Use_placeholders_": "Use placeholders:", + "Customer_Name": "Customer Name", + "Customer_Username": "Customer Username", + "Customer_Phone": "Customer Phone", + "Your_Company_Name": "Your Company Name", + "Message_Sent_Successfully": "Message Sent Successfully", + "Send_Bulk_Message": "Send Bulk Message", + "Group": "Group", + "All_Customers": "All Customers", + "New_Customers": "New Customers", + "Expired_Customers": "Expired Customers", + "Active_Customers": "Active Customers", + "Map": "Map", + "Customer_Location": "Customer Location", + "Account_Type": "Account Type", + "Coordinates": "Coordinates", + "Latitude_and_Longitude_coordinates_for_map_must_be_separate_with_comma____": "Latitude and Longitude coordinates for map must be separate with comma ","", + "Customer_Geo_Location_Information": "Customer Geo Location Information", + "List": "List", + "Lists": "Lists", + "Single_Customer": "Single Customer", + "Bulk_Customers": "Bulk Customers", + "Message_per_time": "Message per time", + "5_Messages": "5 Messages", + "10_Messages": "10 Messages", + "15_Messages": "15 Messages", + "20_Messages": "20 Messages", + "30_Messages": "30 Messages", + "40_Messages": "40 Messages", + "50_Messages": "50 Messages", + "60_Messages": "60 Messages", + "Use_20_and_above_if_you_are_sending_to_all_customers_to_avoid_server_time_out": "Use 20 and above if you are sending to all customers to avoid server time out", + "Delay": "Delay", + "No_Delay": "No Delay", + "5_Seconds": "5 Seconds", + "10_Seconds": "10 Seconds", + "15_Seconds": "15 Seconds", + "20_Seconds": "20 Seconds", + "Use_at_least_5_secs_if_you_are_sending_to_all_customers_to_avoid_being_banned_by_your_message_provider": "Use at least 5 secs if you are sending to all customers to avoid being banned by your message provider", + "Testing__if_checked_no_real_message_is_sent_": "Testing [if checked no real message is sent]", + "All_fields_are_required": "All fields are required", + "Personal": "Personal", + "Email_Notification": "Email Notification", + "Router_Name___Location": "Router Name \/ Location", + "Plan_Category": "Plan Category", + "ID": "ID", + "Internet_Plan": "Internet Plan", + "Privacy_Policy": "Privacy Policy", + "Terms_and_Conditions": "Terms and Conditions", + "Contact": "Contact", + "will_be_replaced_with_Customer_Name": "will be replaced with Customer Name", + "will_be_replaced_with_Customer_username": "will be replaced with Customer username", + "will_be_replaced_with_Package_name": "will be replaced with Package name", + "will_be_replaced_with_Package_price": "will be replaced with Package price", + "additional_bills_for_customers": "additional bills for customers", + "will_be_replaced_with_Expiration_date": "will be replaced with Expiration date", + "Your_Company_Name_at_Settings": "Your Company Name at Settings", + "Your_Company_Address_at_Settings": "Your Company Address at Settings", + "Your_Company_Phone_at_Settings": "Your Company Phone at Settings", + "Invoice_number": "Invoice number", + "Date_invoice_created": "Date invoice created", + "Payment_gateway_user_paid_from": "Payment gateway user paid from", + "Payment_channel_user_paid_from": "Payment channel user paid from", + "is_Hotspot_or_PPPOE": "is Hotspot or PPPOE", + "Internet_Package": "Internet Package", + "Internet_Package_Prices": "Internet Package Prices", + "Receiver_name": "Receiver name", + "Username_internet": "Username internet", + "User_password": "User password", + "Expired_datetime": "Expired datetime", + "For_Notes_by_admin": "For Notes by admin", + "Transaction_datetime": "Transaction datetime", + "Balance_Before": "Balance Before", + "Balance_After": "Balance After", + "how_much_balance_have_been_send": "how much balance have been send", + "Current_Balance": "Current Balance", + "Sender_name": "Sender name", + "how_much_balance_have_been_received": "how much balance have been received", + "Extend_Postpaid_Expiration": "Extend Postpaid Expiration", + "Allow_Extend": "Allow Extend", + "Extend_Days": "Extend Days", + "Confirmation_Message": "Confirmation Message", + "You_are_already_logged_in": "You are already logged in", + "Extend": "Extend", + "Created___Expired": "Created \/ Expired", + "Bank_Transfer": "Bank Transfer", + "Recharge_Using": "Recharge Using", + "ago": "ago", + "Disabled": "Disabled", + "Banned": "Banned", + "Customer_cannot_login_again": "Customer cannot login again", + "Customer_can_login_but_cannot_buy_internet_plan__Admin_cannot_recharge_customer": "Customer can login but cannot buy internet plan, Admin cannot recharge customer", + "Don_t_forget_to_deactivate_all_active_plan_too": "Don't forget to deactivate all active plan too", + "Ascending": "Ascending", + "Descending": "Descending", + "Created_Date": "Created Date", + "Inactive": "Inactive", + "Suspended": "Suspended", + "Query": "Query", + "Notes": "Notes", + "This_account_status": "This account status", + "Maintenance_Mode": "Maintenance Mode", + "Maintenance_Mode_Settings": "Maintenance Mode Settings", + "Status_": "Status:", + "End_Date_": "End Date:", + "Save": "Save", + "Site_is_temporarily_unavailable_": "Site is temporarily unavailable.", + "Scheduled_maintenance_is_currently_in_progress__Please_check_back_soon_": "Scheduled maintenance is currently in progress. Please check back soon.", + "We_apologize_for_any_inconvenience_": "We apologize for any inconvenience.", + "The": "The", + "Team": "Team", + "Extend_Package_Expiry": "Extend Package Expiry", + "No": "No", + "Yes": "Yes", + "If_user_buy_same_internet_plan__expiry_date_will_extend": "If user buy same internet plan, expiry date will extend", + "Tax_System": "Tax System", + "Enable_Tax_System": "Enable Tax System", + "Tax_will_be_calculated_in_Internet_Plan_Price": "Tax will be calculated in Internet Plan Price", + "Tax_Rate": "Tax Rate", + "0_5_": "0.5%", + "1_": "1%", + "1_5_": "1.5%", + "2_": "2%", + "5_": "5%", + "10_": "10%", + "Custom": "Custom", + "Tax_Rates_in_percentage": "Tax Rates in percentage", + "Custom_Tax_Rate": "Custom Tax Rate", + "Enter_Custom_Tax_Rate": "Enter Custom Tax Rate", + "Enter_the_custom_tax_rate__e_g___3_75_for_3_75__": "Enter the custom tax rate (e.g., 3.75 for 3.75%)", + "Additional_Information": "Additional Information", + "City_of_Resident": "City of Resident", + "District": "District", + "State": "State", + "State_of_Resident": "State of Resident", + "Zip": "Zip", + "Zip_Code": "Zip Code", + "M_Pesa": "M-Pesa", + "sales": "sales", + "Create_Transaction_Success__Please_click_pay_now_to_process_payment": "Create Transaction Success, Please click pay now to process payment", + "Failed_to_send_message": "Failed to send message", + "": "", + "just_now": "just now", + "Backup_Database": "Backup Database", + "Backup_not_found_": "Backup not found.", + "Add_Customer": "Add Customer", + "Clients": "Clients", + "All_Clients": "All Clients", + "New_Client": "New Client", + "Active_Clients": "Active Clients", + "Refill_Client": "Refill Client", + "Recharge_Client": "Recharge Client", + "Top_Up_Wallet": "Top-Up Wallet", + "_Internet_Packages": "Internet Packages", + "Communications": "Communications", + "Single_Client": "Single Client", + "Bulk_Clients": "Bulk Clients", + "Sent_Messages": "Sent Messages", + "Recharge_SMS": "Recharge SMS", + "User_Alerts": "User Alerts", + "Payment_Method": "Payment Method", + "System_Logs": "System Logs", + "Mpesa_Settings": "Mpesa Settings", + "SMS_Balance": "SMS Balance", + "View_Balance": "View Balance", + "Force_Logout_": "Force Logout:", + "Account_Not_Found": "Account Not Found", + "Enter_Username": "Enter Username", + "Enter_Full_Name": "Enter Full Name", + "Enter_Email": "Enter Email", + "Enter_Phone_Number": "Enter Phone Number", + "Enter_Password": "Enter Password", + "Enter_PPPOE_Password": "Enter PPPOE Password", + "Enter_Address": "Enter Address", + "Business": "Business", + "Messages": "Messages", + "Manage_Messages": "Manage Messages", + "Actions": "Actions", + "Download": "Download", + "Uptime": "Uptime", + "Memory_Used_Total": "Memory Used\/Total", + "CPU_Load": "CPU Load", + "Free_Memory": "Free Memory", + "Online_Users": "Online Users", + "Hotspot_Users": "Hotspot Users", + "New_Hotspot_User": "New Hotspot User", + "Server": "Server", + "MAC_Address": "MAC Address", + "Session_Time": "Session Time", + "Rx_Bytes": "Rx Bytes", + "Tx_Bytes": "Tx Bytes", + "Online_Clients": "Online Clients", + "Upload": "Upload", + "Action": "Action", + "Backup_File": "Backup File", + "Are_you_Sure_you_want_to_Restore_this_Database_": "Are you Sure you want to Restore this Database?", + "Restore": "Restore", + "Are_you_Sure_you_want_to_Delete_this_Database_": "Are you Sure you want to Delete this Database?", + "Hotspot_Client": "Hotspot Client", + "Pppoe_Clients": "Pppoe Clients", + "Reboot": "Reboot", + "Close": "Close", + "Today_s_Sales": "Today's Sales", + "Active_Accounts": "Active Accounts", + "Expired_Accounts": "Expired Accounts", + "Account": "Account", + "Enter_Account_Number": "Enter Account Number", + "Online_Hotspot_Users": "Online Hotspot Users", + "View_Hotspot_Users": "View Hotspot Users", + "Online_PPPoE_Users": "Online PPPoE Users", + "View_PPPoE_Users": "View PPPoE Users", + "Data_Usage": "Data Usage", + "View_Data_Usage": "View Data Usage", + "Amount": "Amount", + "Unused": "Unused", + "Used": "Used", + "Quotes": "Quotes", + "Recent_Orders": "Recent Orders", + "Order_ID": "Order ID", + "Add_Client": "Add Client", + "Clients_Map": "Clients Map", + "Admin_Users": "Admin Users", + "Payment_Setup": "Payment Setup", + "Add_New_Client": "Add New Client", + "Acc_Type": "Acc Type", + "Area": "Area", + "Service": "Service", + "Monthly_Customers": "Monthly Customers", + "This_Token_will_act_as_SuperAdmin_Admin_": "This Token will act as SuperAdmin\/Admin.", + "Expired_Users": "Expired Users", + "Fullname": "Fullname", + "Router": "Router", + "IT709": "IT709", + "IT794": "IT794", + "IT889": "IT889", + "Temperature": "Temperature", + "Voltage": "Voltage", + "Wireless_Status": "Wireless Status", + "Interface_Status": "Interface Status", + "Hotspot_Online_Users": "Hotspot Online Users", + "PPPoE_Online_Users": "PPPoE Online Users", + "Traffic_Monitor": "Traffic Monitor", + "Interface_Name": "Interface Name", + "Tx__bytes_Out_": "Tx (bytes Out)", + "Rx__bytes_In_": "Rx (bytes In)", + "Total_Usage": "Total Usage", + "Mac_Address": "Mac Address", + "Session_Time_Left": "Session Time Left", + "Upload__RX_": "Upload (RX)", + "Download__TX_": "Download (TX)", + "Caller_ID": "Caller ID", + "Interface": "Interface", + "Last_Ip": "Last Ip", + "Last_Activity": "Last Activity", + "Signal_Strength": "Signal Strength", + "Tx___Rx_CCQ": "Tx \/ Rx CCQ", + "Rx_Rate": "Rx Rate", + "Tx_Rate": "Tx Rate", + "Interace": "Interace", + "TX": "TX", + "RX": "RX", + "Date_Time": "Date\/Time", + "Topic": "Topic", + "Info": "Info", + "Success": "Success", + "Warning": "Warning", + "Error": "Error", + "IT983": "IT983", + "moha": "moss", + "Username_should_be_between_3_to_45_characters": "Username should be between 3 to 45 characters", + "Full_Name_should_be_between_3_to_45_characters": "Full Name should be between 3 to 45 characters", + "Mpesa_C2B_Settings__Offline_Payment_": "Mpesa C2B Settings [Offline Payment]", + "M_Pesa_C2B_Payment_Gateway": "M-Pesa C2B Payment Gateway", + "M_Pesa_C2B_Environment": "M-Pesa C2B Environment", + "SandBox_or_Testing": "SandBox or Testing", + "Live_or_Production": "Live or Production", + "Sandbox": "Sandbox", + "is_for_testing_purpose__please_switch_to": "is for testing purpose, please switch to", + "Live": "Live", + "in_production_": "in production.", + "Accept_Insufficient_Fee": "Accept Insufficient Fee", + "You_haven_t_registered_your_validation_and_verification_URLs__Please_register_URLs_by_clicking_": "You haven't registered your validation and verification URLs, Please register URLs by clicking", + "Payment_History": "Payment History", + "Transaction_Type": "Transaction Type", + "Transaction_Time": "Transaction Time", + "Amount_Paid": "Amount Paid", + "Package_Name": "Package Name", + "Package_Price": "Package Price", + "Bill_Ref_Number": "Bill Ref Number", + "Company_Balance": "Company Balance", + "_Cleared_the_system_cache_": "Cleared the system cache", + "taxip": "taxi", + "lessa": "lessa", + "brian": "brian", + "hussein": "hussein", + "lucy": "lucy", + "karis": "cook", + "taslim": "surrender", + "sofia": "sofia", + "cynthia": "cynthia", + "husein": "Hussein", + "shad": "shad", + "aliali": "face", + "briton": "briton", + "729632854": "729632854", + "oscar": "oscar" +} \ No newline at end of file diff --git a/system/lan/index.html b/system/lan/index.html new file mode 100644 index 0000000..9757970 --- /dev/null +++ b/system/lan/index.html @@ -0,0 +1,8 @@ + + + 403 Forbidden + + +

Directory access is forbidden.

+ + \ No newline at end of file diff --git a/system/lan/indonesia.json b/system/lan/indonesia.json new file mode 100644 index 0000000..f1ce7be --- /dev/null +++ b/system/lan/indonesia.json @@ -0,0 +1,480 @@ +{ + "Log_in": "Masuk", + "Register": "Daftar", + "Announcement": "Pemberitahuan", + "Registration_Info": "Info Pendaftaran", + "Voucher_not_found__please_buy_voucher_befor_register": "Voucher tidak ditemukan, silakan beli voucher sebelum mendaftar", + "Register_Success__You_can_login_now": "Daftar Sukses! Anda dapat masuk sekarang", + "Log_in_to_Member_Panel": "Masuk ke Panel Anggota", + "Register_as_Member": "Daftar sebagai Anggota", + "Enter_Admin_Area": "Masuk ke Admin Panel", + "PHPNuxBill": "PHPNuxBill", + "Username": "Nama Pengguna", + "Password": "Kata Sandi", + "Passwords_does_not_match": "Kata sandi tidak cocok", + "Account_already_axist": "Akun telah ada", + "Manage": "Mengelola", + "Submit": "Kirim", + "Save_Changes": "Simpan Perubahan", + "Cancel": "Batal", + "Edit": "Sunting", + "Delete": "Hapus", + "Welcome": "Selamat Datang", + "Data_Created_Successfully": "Data Berhasil Dibuat", + "Data_Updated_Successfully": "Data Berhasil Diperbarui", + "Data_Deleted_Successfully": "Data Berhasil Dihapus", + "Static_Pages": "Halaman Statis", + "Failed_to_save_page__make_sure_i_can_write_to_folder_pages___i_chmod_664_pages___html_i_": "Gagal menyimpan halaman, pastikan diperbolehkan menulis file di folder pages, chmod 664 pages\/*.html", + "Saving_page_success": "Menyimpan halaman berhasil", + "Sometimes_you_need_to_refresh_3_times_until_content_change": "Terkadang Anda perlu menyegarkan 3 kali hingga konten berubah", + "Dashboard": "Dasbor", + "Search_Customers___": "Cari Member...", + "My_Account": "Akun Saya", + "My_Profile": "Profil Saya", + "Settings": "Pengaturan", + "Edit_Profile": "Sunting Profil", + "Change_Password": "Ganti kata sandi", + "Logout": "Keluar", + "Services": "Layanan", + "Bandwidth_Plans": "Paket Bandwidth", + "Bandwidth_Name": "Nama Bandwidth", + "New_Bandwidth": "Bandwidth Baru", + "Edit_Bandwidth": "Sunting Bandwidth", + "Add_New_Bandwidth": "Tambahkan Bandwidth Baru", + "Rate_Download": "Nilai Unduhan", + "Rate_Upload": "Nilai Unggahan", + "Name_Bandwidth_Already_Exist": "Nama Bandwidth sudah ada", + "Hotspot_Plans": "Paket Hotspot", + "PPPOE_Plans": "Paket PPPoE", + "Plan_Name": "Nama Paket", + "New_Service_Plan": "Paket Layanan Baru", + "Add_Service_Plan": "Tambah Paket Layanan", + "Edit_Service_Plan": "Sunting Paket Layanan", + "Name_Plan_Already_Exist": "Nama Paket sudah ada", + "Plan_Type": "Jenis Paket", + "Plan_Price": "Harga Paket", + "Limit_Type": "Tipe Batas", + "Unlimited": "Tak Terbatas", + "Limited": "Terbatas", + "Time_Limit": "Batas waktu", + "Data_Limit": "Batas Data", + "Both_Limit": "Membatasi keduanya", + "Plan_Validity": "Waktu Paket", + "Select_Bandwidth": "Pilih Bandwidth", + "Shared_Users": "Berbagi Pelanggan", + "Choose_User_Type_Sales_to_disable_access_to_Settings": "Pilih Sales untuk menonaktifkan akses ke Pengaturan", + "Current_Password": "Kata sandi saat ini", + "New_Password": "Kata sandi baru", + "Administrator": "Administrator", + "Sales": "Sales", + "Member": "Anggota", + "Confirm_New_Password": "Konfirmasi sandi baru", + "Confirm_Password": "Konfirmasi sandi", + "Full_Name": "Nama Lengkap", + "User_Type": "Tipe Pelanggan", + "Address": "Alamat", + "Created_On": "Dibuat pada", + "Expires_On": "Kedaluwarsa pada", + "Phone_Number": "Nomor telepon", + "User_deleted_Successfully": "Pelanggan berhasil dihapus", + "Full_Administrator": "Administrator Penuh", + "Keep_Blank_to_do_not_change_Password": "Biarkan kosong apabila tidak ingin mengubah kata sandi", + "Keep_it_blank_if_you_do_not_want_to_show_currency_code": "Kosongkan jika Anda tidak ingin menampilkan kode mata uang", + "Theme_Style": "Gaya Tema", + "Theme_Color": "Warna Tema", + "Default_Language": "Bahasa Bawaan", + "Network": "Jaringan", + "Routers": "Router", + "IP_Pool": "IP Pool", + "New_Router": "Router baru", + "Add_Router": "Tambahkan Router", + "Edit_Router": "Sunting Router", + "Router_Name": "Nama Router", + "IP_Address": "Alamat IP", + "Router_Secret": "Password Router", + "Description": "Deskrispi", + "IP_Router_Already_Exist": "IP Router sudah ada", + "Name_Pool": "Nama Pool", + "Range_IP": "Rentang IP", + "New_Pool": "Pool baru", + "Add_Pool": "Tambahkan Pool", + "Edit_Pool": "Sunting Pool", + "Pool_Name_Already_Exist": "Nama Pool sudah ada", + "Refill_Account": "Isi Ulang Akun", + "Recharge_Account": "Isi Ulang Akun", + "Select_Account": "Pilih Akun", + "Service_Plan": "Paket Layanan", + "Recharge": "Isi Ulang", + "Method": "Metode", + "Account_Created_Successfully": "Akun berhasil dibuat", + "Database_Status": "Status Database", + "Total_Database_Size": "Ukuran total database", + "Download_Database_Backup": "Unduh cadangan database", + "Table_Name": "Nama Tabel", + "Rows": "Baris", + "Size": "Ukuran", + "Customer": "Pelanggan", + "Add_New_Contact": "Tambahkan Kontak Baru", + "Edit_Contact": "Sunting Kontak", + "List_Contact": "Daftar Kontak", + "Manage_Contact": "Kelola Kontak", + "Reports": "Laporan", + "Daily_Reports": "Laporan Harian", + "Period_Reports": "Laporan Periode", + "All_Transactions": "Semua Transaksi", + "Total_Income": "Jumlah Pemasukan", + "All_Transactions_at_Date": "Semua transaksi pada ganggal", + "Export_for_Print": "Ekspor untuk cetak", + "Print": "Cetak", + "Export_to_PDF": "Ekspor ke PDF", + "Click_Here_to_Print": "Klik Disini untuk mencetak", + "You_can_use_html_tag": "Anda dapat menggunakan tag HTML", + "Date_Format": "Format tanggal", + "Income_Today": "Pendapatan hari ini", + "Income_This_Month": "Penghasilan bulan ini", + "Users_Active": "Pelanggan Aktif", + "Total_Users": "Total Pelanggan", + "Users": "Pelanggan", + "Edit_User": "Sunting Pelanggan", + "Last_Login": "Terakhir Masuk", + "Administrator_Users": "Pengguna Administrator", + "Manage_Administrator": "Kelola Administrator", + "Add_New_Administrator": "Tambahkan Administrator Baru", + "Localisation": "Lokalisasi", + "Backup_Restore": "Cadangkan\/Pulihkan", + "General_Settings": "Pengaturan Umum", + "Date": "Tanggal", + "Login_Successful": "Berhasil Masuk", + "Failed_Login": "Gagal Masuk", + "Settings_Saved_Successfully": "Pengaturan Berhasil Disimpan", + "User_Updated_Successfully": "Pengguna Berhasil Diperbarui", + "User_Expired__Today": "Pengguna Kedaluwarsa, Hari Ini", + "Activity_Log": "Log Aktivitas", + "View_Reports": "Lihat Laporan", + "View_All": "Lihat semua", + "Number_of_Vouchers": "Jumlah Voucher", + "Length_Code": "Panjang Kode", + "Code_Voucher": "Kode Voucher", + "Voucher": "Voucher", + "Hotspot_Voucher": "Voucher Hotspot", + "Status_Voucher": "Voucher Status", + "Add_Vouchers": "Tambah Voucher", + "Create_Vouchers_Successfully": "Buat Voucher Berhasil", + "Generate": "Menghasilkan", + "Print_side_by_side__it_will_easy_to_cut": "Info Cetak", + "From_Date": "Dari tanggal", + "To_Date": "Hingga saat ini", + "New_Service": "Layanan Baru", + "Type": "Jenis", + "Finish": "Menyelesaikan", + "Application_Name__Company_Name": "Nama Aplikasi\/ Nama Perusahaan", + "This_Name_will_be_shown_on_the_Title": "Nama ini akan ditampilkan pada Judul", + "Next": "Berikutnya", + "Last": "Terakhir", + "Timezone": "Zona waktu", + "Decimal_Point": "Titik Desimal", + "Thousands_Separator": "Pemisah Ribuan", + "Currency_Code": "Kode Mata Uang", + "Order_Voucher": "Pesan Voucher", + "Voucher_Activation": "Aktivasi Voucher", + "List_Activated_Voucher": "Daftar Voucher yang diaktifkan", + "Enter_voucher_code_here": "Masukkan kode voucher di sini", + "Private_Message": "Pesan Pribadi", + "Inbox": "Kotak Masuk", + "Outbox": "Kotak Keluar", + "Compose": "Menyusun", + "Send_to": "Kirim ke", + "Title": "Judul", + "Message": "Pesan", + "Your_Account_Information": "Informasi Akun Anda", + "Welcome_to_the_Panel_Members_page__on_this_page_you_can_": "Selamat datang di halaman Anggota Panel, di halaman ini Anda dapat:", + "Invalid_Username_or_Password": "Nama pengguna atau kata sandi salah", + "You_do_not_have_permission_to_access_this_page": "Anda tidak memiliki izin untuk mengakses halaman ini", + "Incorrect_Current_Password": "Kata sandi saat ini salah", + "Password_changed_successfully__Please_login_again": "Kata sandi berhasil diubah, silakan login kembali", + "All_field_is_required": "Semua bidang wajib diisi", + "Voucher_Not_Valid": "Voucher tidak berlaku", + "Activation_Vouchers_Successfully": "Aktivasi Voucher Berhasil", + "Data_Not_Found": "Data tidak ditemukan", + "Search_by_Username": "Cari berdasarkan nama pengguna", + "Search_by_Name": "Cari berdasarkan nama", + "Search_by_Code_Voucher": "Cari berdasarkan kode voucher", + "Search": "Mencari", + "Select_a_customer": "Pilih pelanggan", + "Select_Routers": "Pilih Router", + "Select_Plans": "Pilih Paket", + "Select_Pool": "Pilih Pool", + "Hrs": "Jam", + "Mins": "Menit", + "Days": "Hari", + "Months": "Bulan", + "Add_Language": "Tambahkan Bahasa", + "Language_Name": "Nama Bahasa", + "Folder_Name": "Nama Folder", + "Translator": "Penerjemah", + "Language_Name_Already_Exist": "Nama Bahasa sudah ada", + "Payment_Gateway": "Gerbang Pembayaran", + "Community": "Komunitas", + "1_user_can_be_used_for_many_devices_": "1 pengguna bisa digunakan untuk banyak perangkat?", + "Cannot_be_change_after_saved": "Tidak dapat diubah setelah disimpan", + "Explain_Coverage_of_router": "Jelaskan cakupan router", + "Name_of_Area_that_router_operated": "Nama area tempat router dioperasikan", + "Payment_Notification_URL__Recurring_Notification_URL__Pay_Account_Notification_URL": "URL notifikasi pembayaran, URL notifikasi berulang, URL notifikasi akun bayar", + "Finish_Redirect_URL__Unfinish_Redirect_URL__Error_Redirect_URL": "Selesaikan URL pengalihan, selesaikan URL pengalihan, URL pengalihan kesalahan", + "Status": "Status", + "Plan_Not_found": "Paket tidak ditemukan", + "Failed_to_create_transaction_": "Gagal membuat transaksi.", + "Seller_has_not_yet_setup_Xendit_payment_gateway": "Penjual belum menyiapkan gateway pembayaran Xendit", + "Admin_has_not_yet_setup_Xendit_payment_gateway__please_tell_admin": "Admin belum menyiapkan gerbang pembayaran Xendit, mohon beritahu Admin", + "Buy_this__your_active_package_will_be_overwrite": "Beli ini? Paket aktif Anda akan ditimpa", + "You_already_have_unpaid_transaction__cancel_it_or_pay_it_": "Anda sudah memiliki transaksi yang belum dibayar, batalkan atau bayar.", + "Transaction_Not_found": "Transaksi tidak ditemukan", + "Cancel_it_": "Batalkan itu?", + "expired": "Kedaluwarsa", + "Check_for_Payment": "Periksa Pembayaran", + "Transaction_still_unpaid_": "Transaksi masih belum dibayar.", + "Paid_Date": "Tanggal Pembayaran", + "Transaction_has_been_paid_": "Transaksi telah dibayar.", + "PAID": "DIBAYAR", + "CANCELED": "DIBATALKAN", + "UNPAID": "BELUM DIBAYAR", + "PAY_NOW": "BAYAR SEKARANG", + "Buy_Hotspot_Plan": "Beli Paket Hotspot", + "Buy_PPOE_Plan": "Beli Paket PPPoE", + "Package": "Paket", + "Order_Internet_Package": "Pesan Paket Internet", + "Unknown_Command_": "Perintah tidak diketahui.", + "Checking_payment": "Memeriksa pembayaran", + "Create_Transaction_Success": "Transaksi berhasil dibuat", + "You_have_unpaid_transaction": "Anda memiliki transaksi yang belum dibayar", + "TripayPayment_Channel": "Saluran Pembayaran Tripay", + "Payment_Channel": "Saluran Pembayaran", + "Payment_check_failed_": "Pemeriksaan pembayaran gagal.", + "Order_Package": "Pesan Paket", + "Transactions": "Transaksi", + "Payments": "Pembayaran", + "History": "Riwayat", + "Order_History": "Riwayat Pesanan", + "Gateway": "Gerbang", + "Date_Done": "Tanggal Selesai", + "Unpaid_Order": "Pesanan Belum Dibayar", + "Payment_Gateway_Not_Found": "Gerbang Pembayaran tidak ditemukan", + "Payment_Gateway_saved_successfully": "Gerbang Pembayaran berhasil disimpan", + "ORDER": "MEMESAN", + "Package_History": "Riwayat Paket", + "Buy_History": "Riwayat Beli", + "Activation_History": "Riwayat Aktivasi", + "Buy_Package": "Beli Paket", + "Email": "Email", + "Company_Footer": "Catatan Kaki Perusahaan", + "Will_show_below_user_pages": "Akan ditampilkan dibawah halaman pengguna", + "Request_OTP": "Minta OTP", + "Verification_Code": "Kode Verifikasi", + "SMS_Verification_Code": "Kode Verifikasi SMS", + "Please_enter_your_email_address": "Silakan masukkan alamat email Anda", + "Failed_to_create_Paypal_transaction_": "Gagal membuat transaksi Paypal.", + "Plugin": "Plugin", + "Plugin_Manager": "Manajer Plugin", + "User_Notification": "Pemberitahuan Pelanggan", + "Expired_Notification": "Pemberitahuan Kedaluwarsa", + "User_will_get_notification_when_package_expired": "Pengguna akan mendapat notifikasi ketika paket sudah habis masa berlakunya", + "Expired_Notification_Message": "Pesan Pemberitahuan Kedaluwarsa", + "Payment_Notification": "Notifikasi Pembayaran", + "User_will_get_invoice_notification_when_buy_package_or_package_refilled": "Pengguna akan mendapatkan notifikasi invoice saat membeli paket atau isi ulang paket", + "Current_IP": "IP saat ini", + "Current_MAC": "MAC saat ini", + "Login_Status": "Status Masuk", + "Login_Request_successfully": "Permintaan masuk berhasil", + "Logout_Request_successfully": "Permintaan keluar berhasil", + "Disconnect_Internet_": "Putuskan sambungan internet?", + "Not_Online__Login_now_": "Tidak, masuk sekarang?", + "You_are_Online__Logout_": "Kamu sedang aktif, ingin keluar?", + "Connect_to_Internet_": "Hubungkan ke Internet?", + "Your_account_not_connected_to_internet": "Akun Anda tidak terhubung ke internet", + "Failed_to_create_transaction__": "Gagal membuat transaksi. ", + "Failed_to_check_status_transaction__": "Gagal memeriksa status transaksi.", + "Disable_Voucher": "Nonaktifkan Voucher", + "Balance": "Saldo", + "Balance_System": "Saldo Sistem", + "Enable_System": "Aktifkan Sistem", + "Allow_Transfer": "Izinkan Transfer", + "Telegram_Notification": "Pemberitahuan Telegram", + "SMS_OTP_Registration": "Pendaftaran SMS OTP", + "Whatsapp_Notification": "Pemberitahuan WhatsApp", + "Tawk_to_Chat_Widget": "Widget Obrolan Tawk.to", + "Invoice": "Faktur", + "Country_Code_Phone": "Kode Negara Telepon", + "Voucher_activation_menu_will_be_hidden": "Menu aktivasi voucher akan disembunyikan", + "Customer_can_deposit_money_to_buy_voucher": "Pelanggan dapat menyetor uang untuk membeli voucher", + "Allow_balance_transfer_between_customers": "Izinkan transfer saldo antar pelanggan", + "Reminder_Notification": "Pemberitahuan Pengingat", + "Reminder_Notification_Message": "Pesan Pemberitahuan Pengingat", + "Reminder_7_days": "Pengingat 7 hari", + "Reminder_3_days": "Pengingat 3 hari", + "Reminder_1_day": "Pengingat 1 hari", + "PPPOE_Password": "Kata sandi PPPoE", + "User_Cannot_change_this__only_admin__if_it_Empty_it_will_use_user_password": "Pelanggan tidak dapat mengubah ini, hanya Admin. Jika kosong maka akan menggunakan kata sandi pelanggan", + "Invoice_Balance_Message": "Faktur Pesan Saldo", + "Invoice_Notification_Payment": "Faktur Pemberitahuan Pembayaran", + "Balance_Notification_Payment": "Saldo Pemberitahuan Pembayaran", + "Balance_Plans": "Paket Saldo", + "Buy_Balance": "Beli Saldo", + "Price": "Harga", + "Validity": "Waktu", + "Disable_auto_renewal_": "Nonaktifkan perpanjangan otomatis?", + "Auto_Renewal_On": "Perpanjangan otomatis aktif", + "Enable_auto_renewal_": "Aktifkan perpanjangan otomatis?", + "Auto_Renewal_Off": "Perpanjangan otomatis mati", + "Refill_Balance": "Isi Ulang Saldo", + "Invoice_Footer": "Catatan Kaki Faktur", + "Pay_With_Balance": "Bayar dengan Saldo", + "Pay_this_with_Balance__your_active_package_will_be_overwrite": "Bayar ini dengan Saldo? Paket aktif Anda akan ditimpa", + "Success_to_buy_package": "Berhasil membeli paket", + "Auto_Renewal": "Perpanjangan otomatis", + "View": "Melihat", + "Back": "Kembali", + "Active": "Aktif", + "Transfer_Balance": "Kirim saldo", + "Send_your_balance_": "Kirim saldo Anda?", + "Send": "Kirim", + "Cannot_send_to_yourself": "Tidak dapat mengirim ke diri Anda sendiri", + "Sending_balance_success": "Berhasil mengirim saldo", + "From": "Dari", + "To": "Ke", + "insufficient_balance": "Saldo tidak mencukupi", + "Send_Balance": "Kirim saldo", + "Received_Balance": "Saldo yang diterima", + "Minimum_Balance_Transfer": "Minimal transfer saldo", + "Minimum_Transfer": "Minimal Transfer", + "Company_Logo": "Logo Perusahaan", + "Expired_IP_Pool": "IP Pool Kedaluwarsa", + "Proxy": "Proksi", + "Proxy_Server": "Server Proksi", + "Proxy_Server_Login": "Masuk Server Proksi", + "Hotspot_Plan": "Paket Hotspot", + "PPPOE_Plan": "Paket PPPoE", + "UNKNOWN": "TIDAK DIKENAL", + "Are_You_Sure_": "Apa kamu yakin?", + "Success_to_send_package": "Berhasil mengirim paket", + "Target_has_active_plan__different_with_current_plant_": "Target mempunyai paket aktif, berbeda dengan paket saat ini.", + "Recharge_a_friend": "Isi ulang teman", + "Buy_for_friend": "Beli untuk teman", + "Buy_this_for_friend_account_": "Beli ini untuk akun teman?", + "Review_package_before_recharge": "Tinjau paket sebelum mengisi ulang", + "Activate": "Mengaktifkan paket", + "Deactivate": "Menonaktifkan paket", + "Sync": "Sinkronisasi", + "Failed_to_create_PaymeTrust_transaction_": "Gagal membuat transaksi PaymeTrust.", + "Location": "Lokasi", + "Radius_Plans": "Paket Radius", + "Change_title_in_user_Plan_order": "Ubah Judul dalam urutan paket pelanggan", + "Logs": "Log", + "Voucher_Format": "Format Voucher", + "Resend_To_Customer": "Kirim Ulang Ke Pelanggan", + "Service_Type": "Jenis Layanan", + "Others": "Lainnya", + "PPPoE": "PPPoE", + "Hotspot": "Hotspot", + "Monthly_Registered_Customers": "Pendaftaran Pelanggan perbulan", + "Total_Monthly_Sales": "Total penjualan perbulan", + "Active_Users": "Pelanggan Aktif", + "SuperAdmin": "Super Admin", + "Lists": "Daftar", + "Vouchers": "Voucher", + "Refill_Customer": "Isi Ulang Pelanggan", + "Recharge_Customer": "Isi Ulang Pelanggan", + "Plans": "Paket", + "PPPOE": "PPPOE", + "Bandwidth": "Bandwidth", + "Send_Message": "Mengirim pesan", + "Single_Customer": "Pelanggan Tunggal", + "Bulk_Customers": "Pelanggan Massal", + "Radius": "Radius", + "Radius_NAS": "Radius NAS", + "Customer_Announcement": "Pengumuman Pelanggan", + "Language_Editor": "Editor Bahasa", + "Plan_Category": "Kategori Paket", + "ID": "ID", + "Prev": "Sebelumnya", + "Internet_Plan": "Paket Internet", + "Generated_By": "Dihasilkan oleh", + "All_Users_Insights": "Semua Wawasan Pengguna", + "year": "Tahun", + "month": "Bulan", + "week": "Pekan", + "day": "Hari", + "hour": "Jam", + "minute": "Menit", + "second": "Kedua", + "Account_Type": "Jenis akun", + "Contact": "Kontak", + "Paid": "Dibayar", + "Personal": "Pribadi", + "Coordinates": "Koordinat", + "Confirm": "Mengonfirmasi", + "Name": "Nama", + "Plan": "Paket", + "Using": "Menggunakan", + "Total": "Total", + "Additional_Cost": "Biaya tambahan", + "Resend": "Kirim ulang", + "Login": "Masuk", + "success": "Sukses", + "Click_Here": "Klik disini", + "Your_friend_do_not_have_active_package": "Teman Anda tidak memiliki paket aktif", + "If_your_friend_have_Additional_Cost__you_will_pay_for_that_too": "Jika teman Anda memiliki biaya tambahan, Anda juga akan membayarnya", + "Select_Payment_Gateway": "Pilih Gerbang Pembayaran", + "Available_Payment_Gateway": "Gerbang Pembayaran yang tersedia", + "Pay_Now": "Bayar sekarang", + "Notes": "Catatan", + "will_be_replaced_with_Customer_Name": "akan diganti dengan nama Pelanggan", + "will_be_replaced_with_Customer_username": "akan diganti dengan nama pengguna Pelanggan", + "will_be_replaced_with_Package_name": "akan diganti dengan nama paket", + "will_be_replaced_with_Package_price": "akan diganti dengan harga Paket", + "will_be_replaced_with_Expiration_date": "akan diganti dengan tanggal kedaluwarsa", + "additional_bills_for_customers": "tagihan tambahan untuk pelanggan", + "Your_Company_Name_at_Settings": "Nama Perusahaan Anda di pengaturan", + "Your_Company_Address_at_Settings": "Alamat Perusahaan Anda di pengaturan", + "Your_Company_Phone_at_Settings": "Telepon Perusahaan Anda di pengaturan", + "Invoice_number": "Nomor faktur", + "Date_invoice_created": "Tanggal faktur dibuat", + "Payment_gateway_user_paid_from": "Pengguna gateway pembayaran membayar dari", + "Payment_channel_user_paid_from": "Pengguna saluran pembayaran membayar dari", + "is_Hotspot_or_PPPOE": "adalah Hotspot atau PPPOE", + "Internet_Package": "Paket internet", + "Internet_Package_Prices": "Harga paket internet", + "Receiver_name": "Nama penerima", + "Username_internet": "Nama pengguna internet", + "User_password": "Kata sandi pengguna", + "Transaction_datetime": "Tanggal waktu transaksi", + "Balance_Before": "Saldo sebelumnya", + "Balance_After": "Saldo setelahnya", + "For_Notes_by_admin": "Untuk catatan oleh Admin", + "how_much_balance_have_been_send": "berapa banyak saldo yang telah dikirim", + "Current_Balance": "Saldo saat ini", + "Sender_name": "Nama pengirim", + "Customer_Balance": "Saldo Pelanggan", + "Privacy_Policy": "Kebijakan Privasi", + "Terms_and_Conditions": "Syarat dan Ketentuan", + "Disable_Registration": "Nonaktifkan Pendaftaran", + "Customer_just_Login_with_Phone_number_and_Voucher_Code__Voucher_will_be_password": "Pelanggan cukup masuk dengan nomor telepon dan kode voucher, Voucher akan menjadi kata sandi", + "After_Customer_activate_voucher_or_login__customer_will_be_redirected_to_this_url": "Setelah Pelanggan mengaktifkan voucher atau masuk, Pelanggan akan diarahkan ke URL ini", + "Extend_Postpaid_Expiration": "Perpanjang masa kedaluwarsa pascabayar", + "Allow_Extend": "Izinkan Perpanjang", + "Extend_Days": "Perpanjang Hari", + "Confirmation_Message": "Pesan konfirmasi", + "Email_Notification": "Pemberitahuan Email", + "This_Token_will_act_as_SuperAdmin_Admin": "Token ini akan bertindak sebagai SuperAdmin\/Admin", + "Miscellaneous": "Aneka ragam", + "OTP_Required": "Diperlukan OTP", + "OTP_is_required_when_user_want_to_change_phone_number": "OTP diperlukan ketika pengguna ingin mengganti nomor telepon", + "OTP_Method": "Metode OTP", + "SMS": "SMS", + "WhatsApp": "WhatsApp", + "SMS_and_WhatsApp": "SMS dan WhatsApp", + "The_method_which_OTP_will_be_sent_to_user": "Metode OTP yang akan dikirimkan ke pengguna", + "Disabled": "Dinonaktifkan", + "Banned": "Dicekal", + "Inactive": "Tidak Aktif", + "Suspended": "Disuspend" +} diff --git a/system/lan/spanish.json b/system/lan/spanish.json new file mode 100644 index 0000000..de937f5 --- /dev/null +++ b/system/lan/spanish.json @@ -0,0 +1,377 @@ +{ + "Log_in": "Entrar", + "Register": "Registro", + "Announcement": "Anuncio", + "Registration_Info": "Informaci\u00f3n de registro", + "Voucher_not_found__please_buy_voucher_befor_register": "Cup\u00f3n no encontrado, compre el cup\u00f3n antes de registrarse", + "Register_Success__You_can_login_now": "\u00a1Registro exitoso! Puedes iniciar sesi\u00f3n ahora", + "Log_in_to_Member_Panel": "Log in to Member Panel", + "Register_as_Member": "Reg\u00edstrese como miembro", + "Enter_Admin_Area": "Panel de administraci\u00f3n", + "PHPNuxBill": "DIGITAL-RED", + "Username": "Usuario", + "Password": "Contrase\u00f1a", + "Passwords_does_not_match": "Las contrase\u00f1as no coinciden", + "Account_already_axist": "La cuenta ya existe", + "Manage": "Administrar", + "Submit": "Enviar", + "Save_Changes": "Guardar cambios", + "Cancel": "Cancelar", + "Edit": "Editar", + "Delete": "Eliminar", + "Welcome": "Bienvenido", + "Data_Created_Successfully": "Datos creados con \u00e9xito", + "Data_Updated_Successfully": "Datos actualizados con \u00e9xito", + "Data_Deleted_Successfully": "Datos eliminados con \u00e9xito", + "Static_Pages": "P\u00e1ginas est\u00e1ticas", + "Failed_to_save_page__make_sure_i_can_write_to_folder_pages___i_chmod_664_pages___html_i_": "No se pudo guardar la p\u00e1gina, aseg\u00farese de que pueda escribir en las p\u00e1ginas de la carpeta, chmod 664 pages\/*.html", + "Saving_page_success": "Guardando el \u00e9xito de la p\u00e1gina", + "Sometimes_you_need_to_refresh_3_times_until_content_change": "A veces es necesario actualizar 3 veces hasta que cambie el contenido", + "Dashboard": "Dashboard", + "Search_Customers___": "Buscar clientes...", + "My_Account": "Mi cuenta", + "My_Profile": "Mi perfil", + "Settings": "Ajustes", + "Edit_Profile": "Editar perfil", + "Change_Password": "Cambia la contrase\u00f1a", + "Logout": "Cerrar sesi\u00f3n", + "Services": "Servicios", + "Bandwidth_Plans": "Planes de velocidad", + "Bandwidth_Name": "Nombre de ancho de banda", + "New_Bandwidth": "Nuevo ancho de banda", + "Edit_Bandwidth": "Editar ancho de banda", + "Add_New_Bandwidth": "Agregar nuevo ancho de banda", + "Rate_Download": "Tarifa Descarga", + "Rate_Upload": "Tasa de subida", + "Name_Bandwidth_Already_Exist": "El ancho de banda del nombre ya existe", + "Hotspot_Plans": "Planes de Hotspot", + "PPPOE_Plans": "Planes PPPOE", + "Plan_Name": "Nombre", + "New_Service_Plan": "Nuevo plan de servicio", + "Add_Service_Plan": "Agregar plan de servicio", + "Edit_Service_Plan": "Editar plan de servicio", + "Name_Plan_Already_Exist": "Nombre El plan ya existe", + "Plan_Type": "Tipo de plan", + "Plan_Price": "Precio del plan", + "Limit_Type": "Tipo de l\u00edmite", + "Unlimited": "Ilimitado", + "Limited": "Limitado", + "Time_Limit": "L\u00edmite de tiempo", + "Data_Limit": "L\u00edmite de datos", + "Both_Limit": "Ambos L\u00edmite", + "Plan_Validity": "Validez del Plan", + "Select_Bandwidth": "Seleccionar ancho de banda", + "Shared_Users": "Usuarios compartidos", + "Choose_User_Type_Sales_to_disable_access_to_Settings": "Elija Ventas de tipo de usuario para deshabilitar el acceso a la Configuraci\u00f3n", + "Current_Password": "Contrase\u00f1a actual", + "New_Password": "Nueva contrase\u00f1a", + "Administrator": "Administrador", + "Sales": "Ventas", + "Member": "Usuario", + "Confirm_New_Password": "Confirmar nueva contrase\u00f1a", + "Confirm_Password": "Confirmar contrase\u00f1a", + "Full_Name": "Nombre completo", + "User_Type": "Tipo de usuario", + "Address": "Direcci\u00f3n", + "Created_On": "Creado en", + "Expires_On": "Expira el", + "Phone_Number": "N\u00famero de tel\u00e9fono", + "User_deleted_Successfully": "Usuario eliminado con \u00e9xito", + "Full_Administrator": "Administrador completo", + "Keep_Blank_to_do_not_change_Password": "Mantener en blanco para no cambiar la contrase\u00f1a", + "Keep_it_blank_if_you_do_not_want_to_show_currency_code": "Mant\u00e9ngalo en blanco si no desea mostrar el c\u00f3digo de moneda", + "Theme_Style": "Estilo de tema", + "Theme_Color": "Color del tema", + "Default_Language": "Idioma predeterminado", + "Network": "Red", + "Routers": "Routers", + "IP_Pool": "IP Pool", + "New_Router": "Nuevo Router", + "Add_Router": "Agregar Router", + "Edit_Router": "Editar Router", + "Router_Name": "Nombre del Router", + "IP_Address": "Direccion IP", + "Router_Secret": "Contrase\u00f1a Router", + "Description": "Descripcion", + "IP_Router_Already_Exist": "El enrutador IP ya existe", + "Name_Pool": "Nombre del Pool", + "Range_IP": "Rango de IP", + "New_Pool": "Nuevo Pool", + "Add_Pool": "Agregar Pool", + "Edit_Pool": "Editar Pool", + "Pool_Name_Already_Exist": "Nombre del Pool ya existe", + "Refill_Account": "Recargar Ficha", + "Recharge_Account": "Recargar Cuenta", + "Select_Account": "Seleccionar cuenta", + "Service_Plan": "Plan de servicio", + "Recharge": "Recargar", + "Method": "M\u00e9todo", + "Account_Created_Successfully": "Cuenta creada con \u00e9xito", + "Database_Status": "Estado de la base de datos", + "Total_Database_Size": "Tama\u00f1o total de la base de datos", + "Download_Database_Backup": "Descargar copia de seguridad de la base de datos", + "Table_Name": "Nombre de la tabla", + "Rows": "Filas", + "Size": "Tama\u00f1o", + "Customer": "Clientes", + "Add_New_Contact": "A\u00f1adir nuevo contacto", + "Edit_Contact": "Editar contacto", + "List_Contact": "Lista de contactos", + "Manage_Contact": "Administrar contacto", + "Reports": "Reportes", + "Daily_Reports": "Reportes diarios", + "Period_Reports": "Informes del per\u00edodo", + "All_Transactions": "Todas las transacciones", + "Total_Income": "Ingresos totales", + "All_Transactions_at_Date": "Todas las transacciones en la fecha", + "Export_for_Print": "Exportar para imprimir", + "Print": "Impresi\u00f3n", + "Export_to_PDF": "Exportar a PDF", + "Click_Here_to_Print": "Haga clic aqu\u00ed para imprimir", + "You_can_use_html_tag": "Puedes usar la etiqueta html", + "Date_Format": "Formato de fecha", + "Income_Today": "Ingresos hoy", + "Income_This_Month": "Ingresos este mes", + "Users_Active": "Usuarios activos", + "Total_Users": "Total de usuarios", + "Users": "Usuarios", + "Edit_User": "Editar usuario", + "Last_Login": "\u00daltimo acceso", + "Administrator_Users": "Usuarios administradores", + "Manage_Administrator": "Administrar administrador", + "Add_New_Administrator": "Agregar nuevo administrador", + "Localisation": "Localizaci\u00f3n", + "Backup_Restore": "Copia de seguridad\/restauracion", + "General_Settings": "Configuraci\u00f3n general", + "Date": "Fecha", + "Login_Successful": "Inicio de sesi\u00f3n exitoso", + "Failed_Login": "Inicio de sesi\u00f3n fallido", + "Settings_Saved_Successfully": "Configuraci\u00f3n guardada con \u00e9xito", + "User_Updated_Successfully": "Usuario actualizado con \u00e9xito", + "User_Expired__Today": "Usuario vencido, hoy", + "Activity_Log": "Registro de actividades", + "View_Reports": "Ver los informes", + "View_All": "Ver todo", + "Number_of_Vouchers": "N\u00famero de Fichas", + "Length_Code": "Longitud de codigo", + "Code_Voucher": "Cup\u00f3n de Ficha", + "Voucher": "Ficha", + "Hotspot_Voucher": "Ficha Hotspot", + "Status_Voucher": "Estatado de Ficha", + "Add_Vouchers": "Agregar Ficha", + "Create_Vouchers_Successfully": "Crear Ficha con \u00e9xito", + "Generate": "Generar", + "Print_side_by_side__it_will_easy_to_cut": "Imprimir uno al lado del otro, ser\u00e1 f\u00e1cil de cortar", + "From_Date": "Partir de la fecha", + "To_Date": "Hasta la fecha", + "New_Service": "Nuevo servicio", + "Type": "Tipo", + "Finish": "Finalizar", + "Application_Name__Company_Name": "Nombre de la aplicaci\u00f3n\/ Nombre de la empresa", + "This_Name_will_be_shown_on_the_Title": "Este nombre se mostrar\u00e1 en el t\u00edtulo", + "Next": "Siguiente", + "Last": "Atras", + "Timezone": "Zona horaria", + "Decimal_Point": "Punto decimal", + "Thousands_Separator": "Separador de miles", + "Currency_Code": "C\u00f3digo de moneda", + "Order_Voucher": "Comprobante de pedido", + "Voucher_Activation": "Activaci\u00f3n de Fichas", + "List_Activated_Voucher": "Lista de Fichas activados", + "Enter_voucher_code_here": "Ingrese el c\u00f3digo de la Ficha aqu\u00ed", + "Private_Message": "Mensaje privado", + "Inbox": "Bandeja de entrada", + "Outbox": "Bandeja de salida", + "Compose": "Componer", + "Send_to": "Enviar a", + "Title": "T\u00edtulo", + "Message": "Mensaje", + "Your_Account_Information": "Informaci\u00f3n de su cuenta", + "Welcome_to_the_Panel_Members_page__on_this_page_you_can_": "Bienvenido a la p\u00e1gina de Miembros del Panel, en esta p\u00e1gina puede:", + "Invalid_Username_or_Password": "Usuario o contrase\u00f1a invalido", + "You_do_not_have_permission_to_access_this_page": "Usted no tiene permiso para acceder a esta p\u00e1gina", + "Incorrect_Current_Password": "IContrase\u00f1a actual incorrecta", + "Password_changed_successfully__Please_login_again": "Contrase\u00f1a cambiada con \u00e9xito, por favor inicie sesi\u00f3n de nuevo", + "All_field_is_required": "Todo el campo es requerido", + "Voucher_Not_Valid": "Ficha no v\u00e1lida", + "Activation_Vouchers_Successfully": "Fichas de activaci\u00f3n con \u00e9xito", + "Data_Not_Found": "Datos no encontrados", + "Search_by_Username": "Buscar por nombre de usuario", + "Search_by_Name": "Buscar por nombre", + "Search_by_Code_Voucher": "B\u00fasqueda por c\u00f3digo de Ficha", + "Search": "B\u00fasqueda", + "Select_a_customer": "Seleccione un cliente", + "Select_Routers": "Seleccionar enrutadores", + "Select_Plans": "Seleccionar planes", + "Select_Pool": "Seleccionar Pool", + "Hrs": "Hrs", + "Mins": "Mins", + "Days": "Dias", + "Months": "Meses", + "Add_Language": "Agregar idioma", + "Language_Name": "Nombre del lenguaje", + "Folder_Name": "Nombre de la carpeta", + "Translator": "Traducir", + "Language_Name_Already_Exist": "El nombre del idioma ya existe", + "Payment_Gateway": "Payment Gateway", + "Community": "Community", + "1_user_can_be_used_for_many_devices_": "1 user can be used for many devices?", + "Cannot_be_change_after_saved": "Cannot be change after saved", + "Explain_Coverage_of_router": "Jelaskan Cakupan wilayah hotspot", + "Name_of_Area_that_router_operated": "Nama Lokasi\/Wilayah Router beroperasi", + "Payment_Notification_URL__Recurring_Notification_URL__Pay_Account_Notification_URL": "Payment Notification URL, Recurring Notification URL, Pay Account Notification URL", + "Finish_Redirect_URL__Unfinish_Redirect_URL__Error_Redirect_URL": "Finish Redirect URL, Unfinish Redirect URL, Error Redirect URL", + "Status": "Status", + "Plan_Not_found": "Plan Not found", + "Failed_to_create_transaction_": "Failed to create transaction.", + "Seller_has_not_yet_setup_Xendit_payment_gateway": "Seller has not yet setup Xendit payment gateway", + "Admin_has_not_yet_setup_Xendit_payment_gateway__please_tell_admin": "Admin has not yet setup Xendit payment gateway, please tell admin", + "Buy_this__your_active_package_will_be_overwrite": "Buy this? your active package will be overwrite", + "You_already_have_unpaid_transaction__cancel_it_or_pay_it_": "You already have unpaid transaction, cancel it or pay it.", + "Transaction_Not_found": "Transaction Not found", + "Cancel_it_": "Cancel it?", + "expired": "expired", + "Check_for_Payment": "Check for Payment", + "Transaction_still_unpaid_": "Transaction still unpaid.", + "Paid_Date": "Paid Date", + "Transaction_has_been_paid_": "Transaction has been paid.", + "PAID": "PAID", + "CANCELED": "CANCELED", + "UNPAID": "UNPAID", + "PAY_NOW": "PAY NOW", + "Buy_Hotspot_Plan": "Buy Hotspot Plan", + "Buy_PPOE_Plan": "Buy PPOE Plan", + "Package": "Package", + "Order_Internet_Package": "Order Internet Package", + "Unknown_Command_": "Unknown Command.", + "Checking_payment": "Checking payment", + "Create_Transaction_Success": "Create Transaction Success", + "You_have_unpaid_transaction": "You have unpaid transaction", + "TripayPayment_Channel": "TripayPayment Channel", + "Payment_Channel": "Payment Channel", + "Payment_check_failed_": "Payment check failed.", + "Order_Package": "Order Package", + "Transactions": "Transactions", + "Payments": "Payments", + "History": "History", + "Order_History": "Order History", + "Gateway": "Gateway", + "Date_Done": "Date Done", + "Unpaid_Order": "Unpaid Order", + "Payment_Gateway_Not_Found": "Payment Gateway Not Found", + "Payment_Gateway_saved_successfully": "Payment Gateway saved successfully", + "ORDER": "ORDER", + "Package_History": "Package History", + "Buy_History": "Buy History", + "Activation_History": "Activation History", + "Buy_Package": "Buy Package", + "Email": "Email", + "Company_Footer": "Company Footer", + "Will_show_below_user_pages": "Will show below user pages", + "Request_OTP": "Request OTP", + "Verification_Code": "Verification Code", + "SMS_Verification_Code": "SMS Verification Code", + "Please_enter_your_email_address": "Please enter your email address", + "Failed_to_create_Paypal_transaction_": "Failed to create Paypal transaction.", + "Plugin": "Plugin", + "Plugin_Manager": "Plugin Manager", + "User_Notification": "User Notification", + "Expired_Notification": "Expired Notification", + "User_will_get_notification_when_package_expired": "User will get notification when package expired", + "Expired_Notification_Message": "Expired Notification Message", + "Payment_Notification": "Payment Notification", + "User_will_get_invoice_notification_when_buy_package_or_package_refilled": "User will get invoice notification when buy package or package refilled", + "Current_IP": "Current IP", + "Current_MAC": "Current MAC", + "Login_Status": "Login Status", + "Login_Request_successfully": "Login Request successfully", + "Logout_Request_successfully": "Logout Request successfully", + "Disconnect_Internet_": "Disconnect Internet?", + "Not_Online__Login_now_": "Not Online, Login now?", + "You_are_Online__Logout_": "You are Online, Logout?", + "Connect_to_Internet_": "Connect to Internet?", + "Your_account_not_connected_to_internet": "Your account not connected to internet", + "Balance": "Balance", + "Balance_System": "Balance System", + "Enable_System": "Enable System", + "Allow_Transfer": "Allow Transfer", + "Telegram_Notification": "Telegram Notification", + "SMS_OTP_Registration": "SMS OTP Registration", + "Whatsapp_Notification": "Whatsapp Notification", + "Tawk_to_Chat_Widget": "Tawk.to Chat Widget", + "Invoice": "Invoice", + "Country_Code_Phone": "Country Code Phone", + "Voucher_activation_menu_will_be_hidden": "Voucher activation menu will be hidden", + "Customer_can_deposit_money_to_buy_voucher": "Customer can deposit money to buy voucher", + "Allow_balance_transfer_between_customers": "Allow balance transfer between customers", + "Refill_Balance": "Refill Balance", + "Balance_Plans": "Balance Plans", + "Failed_to_create_transaction__": "Failed to create transaction. ", + "Failed_to_check_status_transaction__": "Failed to check status transaction. ", + "Disable_Voucher": "Disable Voucher", + "Reminder_Notification": "Reminder Notification", + "Reminder_Notification_Message": "Reminder Notification Message", + "Reminder_7_days": "Reminder 7 days", + "Reminder_3_days": "Reminder 3 days", + "Reminder_1_day": "Reminder 1 day", + "PPPOE_Password": "PPPOE Password", + "User_Cannot_change_this__only_admin__if_it_Empty_it_will_use_user_password": "User Cannot change this, only admin. if it Empty it will use user password", + "Invoice_Balance_Message": "Invoice Balance Message", + "Invoice_Notification_Payment": "Invoice Notification Payment", + "Balance_Notification_Payment": "Balance Notification Payment", + "Buy_Balance": "Buy Balance", + "Price": "Price", + "Validity": "Validity", + "Disable_auto_renewal_": "Disable auto renewal?", + "Auto_Renewal_On": "Auto Renewal On", + "Enable_auto_renewal_": "Enable auto renewal?", + "Auto_Renewal_Off": "Auto Renewal Off", + "Invoice_Footer": "Invoice Footer", + "Pay_With_Balance": "Pay With Balance", + "Pay_this_with_Balance__your_active_package_will_be_overwrite": "Pay this with Balance? your active package will be overwrite", + "Success_to_buy_package": "Success to buy package", + "Auto_Renewal": "Auto Renewal", + "View": "View", + "Back": "Back", + "Active": "Active", + "Transfer_Balance": "Transfer Balance", + "Send_your_balance_": "Send your balance?", + "Send": "Send", + "Cannot_send_to_yourself": "Cannot send to yourself", + "Sending_balance_success": "Sending balance success", + "From": "From", + "To": "To", + "insufficient_balance": "insufficient balance", + "Send_Balance": "Send Balance", + "Received_Balance": "Received Balance", + "Minimum_Balance_Transfer": "Minimum Balance Transfer", + "Minimum_Transfer": "Minimum Transfer", + "Company_Logo": "Company Logo", + "Expired_IP_Pool": "Expired IP Pool", + "Proxy": "Proxy", + "Proxy_Server": "Proxy Server", + "Proxy_Server_Login": "Proxy Server Login", + "Hotspot_Plan": "Hotspot Plan", + "PPPOE_Plan": "PPPOE Plan", + "UNKNOWN": "UNKNOWN", + "Are_You_Sure_": "Are You Sure?", + "Success_to_send_package": "Success to send package", + "Target_has_active_plan__different_with_current_plant_": "Target has active plan, different with current plant.", + "Recharge_a_friend": "Recharge a friend", + "Buy_for_friend": "Buy for friend", + "Buy_this_for_friend_account_": "Buy this for friend account?", + "Review_package_before_recharge": "Review package before recharge", + "Activate": "Activate", + "Deactivate": "Deactivate", + "Sync": "Sync", + "Failed_to_create_PaymeTrust_transaction_": "Failed to create PaymeTrust transaction.", + "Location": "Location", + "Voucher_Format": "Voucher Format", + "Service_Type": "Service Type", + "Others": "Others", + "PPPoE": "PPPoE", + "Hotspot": "Hotspot", + "Monthly_Registered_Customers": "Monthly Registered Customers", + "Total_Monthly_Sales": "Total Monthly Sales", + "Active_Users": "Active Users" +} \ No newline at end of file diff --git a/system/lan/swahili.json b/system/lan/swahili.json new file mode 100644 index 0000000..25554df --- /dev/null +++ b/system/lan/swahili.json @@ -0,0 +1,3 @@ +{ + "Settings_Saved_Successfully": "Mipangilio Imehifadhiwa Imefaulu" +} \ No newline at end of file diff --git a/system/lan/turkish.json b/system/lan/turkish.json new file mode 100644 index 0000000..7f9357d --- /dev/null +++ b/system/lan/turkish.json @@ -0,0 +1,372 @@ +{ + "Log_in": "Oturum a\u00e7", + "Register": "Kay\u0131t olmak", + "Announcement": "Duyuru", + "Registration_Info": "Kay\u0131t Bilgisi", + "Voucher_not_found__please_buy_voucher_befor_register": "Kupon bulunamad\u0131, l\u00fctfen kay\u0131t olun ve kay\u0131t olun", + "Register_Success__You_can_login_now": "Kay\u0131t Ba\u015far\u0131l\u0131! \u015eimdi giri\u015f yapabilirsiniz ", + "Log_in_to_Member_Panel": "\u00dcye Paneli'ne giri\u015f yap\u0131n", + "Register_as_Member": "\u00dcye olarak kay\u0131t ol", + "Enter_Admin_Area": "Y\u00f6netici Paneli Giri\u015fi", + "PHPNuxBill": "PHPNuxBill", + "Username": "Kullan\u0131c\u0131 ad\u0131", + "Password": "Parola", + "Passwords_does_not_match": "Parolalar e\u015fle\u015fmiyor", + "Account_already_axist": "Hesap zaten aksanl\u0131", + "Manage": "Y\u00f6net", + "Submit": "G\u00f6nder", + "Save_Changes": "De\u011fi\u015fiklikleri Kaydet", + "Cancel": "\u0130ptal etmek", + "Edit": "D\u00fczenle", + "Delete": "Sil", + "Welcome": "Ho\u015fgeldiniz", + "Data_Created_Successfully": "Veriler Ba\u015far\u0131yla Olu\u015fturuldu ", + "Data_Updated_Successfully": "Veriler Ba\u015far\u0131yla G\u00fcncellendi", + "Data_Deleted_Successfully": "Veri Ba\u015far\u0131yla Silindi", + "Dashboard": "Dashboard", + "Search_Customers___": "M\u00fc\u015fteri Ara ...", + "My_Account": "Hesab\u0131m", + "My_Profile": "Benim profilim", + "Settings": "Ayarlar", + "Edit_Profile": "Profili D\u00fczenle", + "Change_Password": "\u015eifre de\u011fi\u015ftir", + "Logout": "\u00c7\u0131k\u0131\u015f Yap", + "Services": "Hizmetler", + "Bandwidth_Plans": "Bant Geni\u015fli\u011fi Planlar\u0131", + "Bandwidth_Name": "Bant Geni\u015fli\u011fi Ad\u0131", + "New_Bandwidth": "Yeni Bant Geni\u015fli\u011fi", + "Edit_Bandwidth": "Bant Geni\u015fli\u011fini D\u00fczenle", + "Add_New_Bandwidth": "Yeni Bant Geni\u015fli\u011fi Ekle", + "Rate_Download": "\u0130ndirme Oran\u0131", + "Rate_Upload": "\u00dccret Y\u00fckleme", + "Name_Bandwidth_Already_Exist": "Bandwidth Ad\u0131 Zaten Var", + "Hotspot_Plans": "Hotspot Planlar\u0131", + "PPPOE_Plans": "PPPOE Planlar\u0131", + "Plan_Name": "Plan Ad\u0131", + "New_Service_Plan": "Yeni Hizmet Plan\u0131", + "Add_Service_Plan": "Hizmet Plan\u0131 Ekle", + "Edit_Service_Plan": "Hizmet Plan\u0131n\u0131 D\u00fczenle", + "Name_Plan_Already_Exist": "Plan\u0131 \u0130smi Zaten Var", + "Plan_Type": "Plan T\u00fcr\u00fc", + "Plan_Price": "Plan Fiyat\u0131", + "Limit_Type": "S\u0131n\u0131r Tipi", + "Unlimited": "S\u0131n\u0131rs\u0131z", + "Limited": "S\u0131n\u0131rl\u0131", + "Time_Limit": "Zaman s\u0131n\u0131r\u0131", + "Data_Limit": "Veri S\u0131n\u0131r\u0131", + "Both_Limit": "Her \u0130ki S\u0131n\u0131r", + "Plan_Validity": "Plan Ge\u00e7erlili\u011fi", + "Select_Bandwidth": "Bant Geni\u015fli\u011fini Se\u00e7", + "Shared_Users": "Payla\u015f\u0131lan Kullan\u0131c\u0131lar", + "Choose_User_Type_Sales_to_disable_access_to_Settings": "Ayarlar'a eri\u015fimi devre d\u0131\u015f\u0131 b\u0131rakmak i\u00e7in Kullan\u0131c\u0131 T\u00fcr\u00fc Sat\u0131\u015flar\u0131n\u0131 Se\u00e7", + "Current_Password": "\u015eimdiki \u015eifre", + "New_Password": "Yeni \u015eifre", + "Administrator": "Y\u00f6netici", + "Sales": "Sat\u0131\u015f", + "Member": "\u00dcye", + "Confirm_New_Password": "Yeni \u015fifreyi onayla", + "Confirm_Password": "\u015eifreyi Onayla", + "Full_Name": "Ad Soyad", + "User_Type": "Kullan\u0131c\u0131 tipi", + "Address": "Adres", + "Created_On": "Olu\u015fturuldu", + "Expires_On": "Tarihinde sona eriyor", + "Phone_Number": "Telefon numaras\u0131", + "User_deleted_Successfully": "Kullan\u0131c\u0131 Ba\u015far\u0131yla Silindi", + "Full_Administrator": "Tam Y\u00f6netici", + "Keep_Blank_to_do_not_change_Password": "\u015eifreyi de\u011fi\u015ftirmemek i\u00e7in bo\u015f tutun", + "Keep_it_blank_if_you_do_not_want_to_show_currency_code": "Para birimi kodunu g\u00f6stermek istemiyorsan\u0131z bo\u015f b\u0131rak\u0131n", + "Theme_Style": "Tema Stili", + "Theme_Color": "Tema Rengi", + "Default_Language": "Varsay\u0131lan dil", + "Network": "A\u011f", + "Routers": "Y\u00f6nlendiriciler", + "IP_Pool": "IP Havuzu", + "New_Router": "Yeni Y\u00f6nlendirici", + "Add_Router": "Router ekle", + "Edit_Router": "Y\u00f6nlendiriciyi D\u00fczenle", + "Router_Name": "Y\u00f6nlendirici Ad\u0131", + "IP_Address": "IP adresi", + "Router_Secret": "Y\u00f6nlendirici S\u0131rr\u0131", + "Description": "A\u00e7\u0131klama", + "IP_Router_Already_Exist": "IP Router Zaten Var", + "Name_Pool": "\u0130sim Havuzu", + "Range_IP": "Aral\u0131k \u0130P", + "New_Pool": "Yeni Havuz", + "Add_Pool": "Havuz ekle", + "Edit_Pool": "Havuzu D\u00fczenle", + "Pool_Name_Already_Exist": "Havuz Ad\u0131 \u200b\u200bZaten Var", + "Refill_Account": "Hesab\u0131 Yenile", + "Recharge_Account": "Hesab\u0131 Yeniden \u015earj Et", + "Select_Account": "Hesap Se\u00e7", + "Service_Plan": "Servis plan\u0131", + "Recharge": "\u015earj", + "Method": "Y\u00f6ntem", + "Account_Created_Successfully": "Hesap ba\u015far\u0131yla olu\u015fturuldu", + "Database_Status": "Veritaban\u0131 Durumu", + "Total_Database_Size": "Toplam Veritaban\u0131 Boyutu", + "Download_Database_Backup": "Veritaban\u0131 Yedekleme \u0130ndir", + "Table_Name": "Tablo ismi", + "Rows": "Sat\u0131r", + "Size": "Boyut", + "Customer": "M\u00fc\u015fteri", + "Add_New_Contact": "Yeni \u0130leti\u015fim Ekle", + "Edit_Contact": "\u0130leti\u015fim D\u00fczenle", + "List_Contact": "Liste \u0130rtibat", + "Manage_Contact": "Ki\u015fiyi Y\u00f6netin", + "Reports": "Raporlar", + "Daily_Reports": "G\u00fcnl\u00fck raporlar", + "Period_Reports": "D\u00f6nem Raporlar\u0131", + "All_Transactions": "T\u00fcm \u0130\u015flemler", + "Total_Income": "Toplam gelir", + "All_Transactions_at_Date": "Tarihte T\u00fcm \u0130\u015flemler", + "Export_for_Print": "Bask\u0131 i\u00e7in \u0130hracat", + "Print": "Bask\u0131", + "Export_to_PDF": "PDF'ye Aktar", + "Click_Here_to_Print": "Yazd\u0131rmak i\u00e7in Buraya T\u0131klay\u0131n", + "You_can_use_html_tag": "Html etiketini kullanabilirsiniz", + "Date_Format": "Tarih format\u0131", + "Income_Today": "Gelir Bug\u00fcn", + "Income_This_Month": "Bu Ay Gelir", + "Users_Active": "Kullan\u0131c\u0131lar Aktif", + "Total_Users": "Toplam Kullan\u0131c\u0131", + "Users": "Kullan\u0131c\u0131lar", + "Edit_User": "Kullan\u0131c\u0131y\u0131 d\u00fczenle", + "Last_Login": "Son giri\u015f", + "Administrator_Users": "Y\u00f6netici Kullan\u0131c\u0131lar\u0131", + "Manage_Administrator": "Y\u00f6netici Y\u00f6net", + "Add_New_Administrator": "Yeni Y\u00f6netici Ekleyin", + "Localisation": "Lokalizasyon", + "Backup_Restore": "Yedekleme \/ Geri", + "General_Settings": "Genel Ayarlar", + "Date": "Tarih", + "Login_Successful": "Giri\u015f ba\u015far\u0131l\u0131", + "Failed_Login": "Ba\u015far\u0131s\u0131z oturum a\u00e7ma", + "Settings_Saved_Successfully": "Ayarlar ba\u015far\u0131yla kaydedildi", + "User_Updated_Successfully": "Kullan\u0131c\u0131 Ba\u015far\u0131yla G\u00fcncellendi", + "User_Expired__Today": "Kullan\u0131c\u0131 S\u00fcresi Doldu, Bug\u00fcn", + "Activity_Log": "Etkinlik G\u00fcnl\u00fc\u011f\u00fc", + "View_Reports": "Raporlar\u0131 G\u00f6r\u00fcnt\u00fcle", + "View_All": "Hepsini g\u00f6r", + "Number_of_Vouchers": "Kuponlar\u0131n Say\u0131s\u0131", + "Length_Code": "Uzunluk Kodu", + "Code_Voucher": "Kod Makbuzu", + "Voucher": "Fi\u015f", + "Hotspot_Voucher": "Hotspot Kuponu", + "Status_Voucher": "Durum Makbuzu", + "Add_Vouchers": "Kupon Ekle", + "Create_Vouchers_Successfully": "Kuponlar\u0131 ba\u015far\u0131yla olu\u015ftur", + "Generate": "Genel", + "Print_side_by_side__it_will_easy_to_cut": "Yanyana yazd\u0131r\u0131rsan\u0131z, kesmesi daha kolay olacakt\u0131r.", + "From_Date": "\u0130tibaren", + "To_Date": "Bug\u00fcne kadar", + "New_Service": "Yeni Servis", + "Type": "T\u00fcr", + "Finish": "Biti\u015f", + "Application_Name__Company_Name": "Uygulama Ad\u0131 \/ \u015eirket Ad\u0131", + "This_Name_will_be_shown_on_the_Title": "Bu \u0130sim Ba\u015fl\u0131kta g\u00f6sterilecek", + "Next": "Sonraki", + "Last": "Son", + "Timezone": "Saat dilimi", + "Decimal_Point": "Ondal\u0131k nokta", + "Thousands_Separator": "Bin Ay\u0131r\u0131c\u0131", + "Currency_Code": "Para Birimi Kodu", + "Order_Voucher": "Sipari\u015f Makbuzu", + "Voucher_Activation": "Kupon Aktivasyonu", + "List_Activated_Voucher": "Aktif Fi\u015f Listesi", + "Enter_voucher_code_here": "Kupon kodunu buraya girin", + "Private_Message": "\u00d6zel mesaj", + "Inbox": "Gelen kutusu", + "Outbox": "Giden", + "Compose": "Olu\u015fturma", + "Send_to": "G\u00f6nderildi", + "Title": "Ba\u015fl\u0131k", + "Message": "Mesaj", + "Your_Account_Information": "Hesap Bilgileriniz", + "Invalid_Username_or_Password": "Ge\u00e7ersiz kullan\u0131c\u0131 ad\u0131 veya \u015fifre", + "You_do_not_have_permission_to_access_this_page": "Bu sayfaya eri\u015fim izniniz yok", + "Incorrect_Current_Password": "Yanl\u0131\u015f Ge\u00e7erli \u015eifre", + "Password_changed_successfully__Please_login_again": "\u015eifre ba\u015far\u0131yla de\u011fi\u015ftirildi, L\u00fctfen tekrar giri\u015f yap\u0131n", + "All_field_is_required": "T\u00fcm alan gerekli", + "Voucher_Not_Valid": "Kupon Ge\u00e7erli De\u011fil", + "Activation_Vouchers_Successfully": "Aktivasyon Kuponlar\u0131 Ba\u015far\u0131yla", + "Data_Not_Found": "Veri bulunamad\u0131", + "Search_by_Username": "Kullan\u0131c\u0131 Ad\u0131na G\u00f6re Ara", + "Search_by_Name": "\u0130sme G\u00f6re Ara", + "Search_by_Code_Voucher": "Kod Makbuzuna G\u00f6re Ara", + "Search": "Arama", + "Select_a_customer": "Bir m\u00fc\u015fteri se\u00e7in", + "Select_Routers": "Router'lar\u0131 Se\u00e7", + "Select_Plans": "Planlar\u0131 Se\u00e7", + "Select_Pool": "Havuz Se\u00e7", + "Hrs": "Saat", + "Mins": "Dk", + "Days": "G\u00fcn", + "Months": "Ay", + "Add_Language": "Dil Ekle", + "Language_Name": "Dil ad\u0131", + "Folder_Name": "Klas\u00f6r ad\u0131", + "Translator": "\u00c7evirmen", + "Language_Name_Already_Exist": "Dil Ad\u0131 Zaten Var", + "Payment_Gateway": "Payment Gateway", + "Community": "Community", + "1_user_can_be_used_for_many_devices_": "1 user can be used for many devices?", + "Cannot_be_change_after_saved": "Cannot be change after saved", + "Explain_Coverage_of_router": "Jelaskan Cakupan wilayah hotspot", + "Name_of_Area_that_router_operated": "Nama Lokasi\/Wilayah Router beroperasi", + "Payment_Notification_URL__Recurring_Notification_URL__Pay_Account_Notification_URL": "Payment Notification URL, Recurring Notification URL, Pay Account Notification URL", + "Finish_Redirect_URL__Unfinish_Redirect_URL__Error_Redirect_URL": "Finish Redirect URL, Unfinish Redirect URL, Error Redirect URL", + "Status": "Status", + "Plan_Not_found": "Plan Not found", + "Failed_to_create_transaction_": "Failed to create transaction.", + "Seller_has_not_yet_setup_Xendit_payment_gateway": "Seller has not yet setup Xendit payment gateway", + "Admin_has_not_yet_setup_Xendit_payment_gateway__please_tell_admin": "Admin has not yet setup Xendit payment gateway, please tell admin", + "Buy_this__your_active_package_will_be_overwrite": "Buy this? your active package will be overwrite", + "You_already_have_unpaid_transaction__cancel_it_or_pay_it_": "You already have unpaid transaction, cancel it or pay it.", + "Transaction_Not_found": "Transaction Not found", + "Cancel_it_": "Cancel it?", + "expired": "expired", + "Check_for_Payment": "Check for Payment", + "Transaction_still_unpaid_": "Transaction still unpaid.", + "Paid_Date": "Paid Date", + "Transaction_has_been_paid_": "Transaction has been paid.", + "PAID": "PAID", + "CANCELED": "CANCELED", + "UNPAID": "UNPAID", + "PAY_NOW": "PAY NOW", + "Buy_Hotspot_Plan": "Buy Hotspot Plan", + "Buy_PPOE_Plan": "Buy PPOE Plan", + "Package": "Package", + "Order_Internet_Package": "Order Internet Package", + "Unknown_Command_": "Unknown Command.", + "Checking_payment": "Checking payment", + "Create_Transaction_Success": "Create Transaction Success", + "You_have_unpaid_transaction": "You have unpaid transaction", + "TripayPayment_Channel": "TripayPayment Channel", + "Payment_Channel": "Payment Channel", + "Payment_check_failed_": "Payment check failed.", + "Order_Package": "Order Package", + "Transactions": "Transactions", + "Payments": "Payments", + "History": "History", + "Order_History": "Order History", + "Gateway": "Gateway", + "Date_Done": "Date Done", + "Unpaid_Order": "Unpaid Order", + "Payment_Gateway_Not_Found": "Payment Gateway Not Found", + "Payment_Gateway_saved_successfully": "Payment Gateway saved successfully", + "ORDER": "ORDER", + "Package_History": "Package History", + "Buy_History": "Buy History", + "Activation_History": "Activation History", + "Buy_Package": "Buy Package", + "Email": "Email", + "Company_Footer": "Company Footer", + "Will_show_below_user_pages": "Will show below user pages", + "Request_OTP": "Request OTP", + "Verification_Code": "Verification Code", + "SMS_Verification_Code": "SMS Verification Code", + "Please_enter_your_email_address": "Please enter your email address", + "Failed_to_create_Paypal_transaction_": "Failed to create Paypal transaction.", + "Plugin": "Plugin", + "Plugin_Manager": "Plugin Manager", + "User_Notification": "User Notification", + "Expired_Notification": "Expired Notification", + "User_will_get_notification_when_package_expired": "User will get notification when package expired", + "Expired_Notification_Message": "Expired Notification Message", + "Payment_Notification": "Payment Notification", + "User_will_get_invoice_notification_when_buy_package_or_package_refilled": "User will get invoice notification when buy package or package refilled", + "Current_IP": "Current IP", + "Current_MAC": "Current MAC", + "Login_Status": "Login Status", + "Login_Request_successfully": "Login Request successfully", + "Logout_Request_successfully": "Logout Request successfully", + "Disconnect_Internet_": "Disconnect Internet?", + "Not_Online__Login_now_": "Not Online, Login now?", + "You_are_Online__Logout_": "You are Online, Logout?", + "Connect_to_Internet_": "Connect to Internet?", + "Your_account_not_connected_to_internet": "Your account not connected to internet", + "Balance": "Balance", + "Balance_System": "Balance System", + "Enable_System": "Enable System", + "Allow_Transfer": "Allow Transfer", + "Telegram_Notification": "Telegram Notification", + "SMS_OTP_Registration": "SMS OTP Registration", + "Whatsapp_Notification": "Whatsapp Notification", + "Tawk_to_Chat_Widget": "Tawk.to Chat Widget", + "Invoice": "Invoice", + "Country_Code_Phone": "Country Code Phone", + "Voucher_activation_menu_will_be_hidden": "Voucher activation menu will be hidden", + "Customer_can_deposit_money_to_buy_voucher": "Customer can deposit money to buy voucher", + "Allow_balance_transfer_between_customers": "Allow balance transfer between customers", + "Failed_to_create_transaction__": "Failed to create transaction. ", + "Failed_to_check_status_transaction__": "Failed to check status transaction. ", + "Disable_Voucher": "Disable Voucher", + "Reminder_Notification": "Reminder Notification", + "Reminder_Notification_Message": "Reminder Notification Message", + "Reminder_7_days": "Reminder 7 days", + "Reminder_3_days": "Reminder 3 days", + "Reminder_1_day": "Reminder 1 day", + "PPPOE_Password": "PPPOE Password", + "User_Cannot_change_this__only_admin__if_it_Empty_it_will_use_user_password": "User Cannot change this, only admin. if it Empty it will use user password", + "Invoice_Balance_Message": "Invoice Balance Message", + "Invoice_Notification_Payment": "Invoice Notification Payment", + "Balance_Notification_Payment": "Balance Notification Payment", + "Balance_Plans": "Balance Plans", + "Buy_Balance": "Buy Balance", + "Price": "Price", + "Validity": "Validity", + "Disable_auto_renewal_": "Disable auto renewal?", + "Auto_Renewal_On": "Auto Renewal On", + "Enable_auto_renewal_": "Enable auto renewal?", + "Auto_Renewal_Off": "Auto Renewal Off", + "Refill_Balance": "Refill Balance", + "Invoice_Footer": "Invoice Footer", + "Pay_With_Balance": "Pay With Balance", + "Pay_this_with_Balance__your_active_package_will_be_overwrite": "Pay this with Balance? your active package will be overwrite", + "Success_to_buy_package": "Success to buy package", + "Auto_Renewal": "Auto Renewal", + "View": "View", + "Back": "Back", + "Active": "Active", + "Transfer_Balance": "Transfer Balance", + "Send_your_balance_": "Send your balance?", + "Send": "Send", + "Cannot_send_to_yourself": "Cannot send to yourself", + "Sending_balance_success": "Sending balance success", + "From": "From", + "To": "To", + "insufficient_balance": "insufficient balance", + "Send_Balance": "Send Balance", + "Received_Balance": "Received Balance", + "Minimum_Balance_Transfer": "Minimum Balance Transfer", + "Minimum_Transfer": "Minimum Transfer", + "Company_Logo": "Company Logo", + "Expired_IP_Pool": "Expired IP Pool", + "Proxy": "Proxy", + "Proxy_Server": "Proxy Server", + "Proxy_Server_Login": "Proxy Server Login", + "Hotspot_Plan": "Hotspot Plan", + "PPPOE_Plan": "PPPOE Plan", + "UNKNOWN": "UNKNOWN", + "Are_You_Sure_": "Are You Sure?", + "Success_to_send_package": "Success to send package", + "Target_has_active_plan__different_with_current_plant_": "Target has active plan, different with current plant.", + "Recharge_a_friend": "Recharge a friend", + "Buy_for_friend": "Buy for friend", + "Buy_this_for_friend_account_": "Buy this for friend account?", + "Review_package_before_recharge": "Review package before recharge", + "Activate": "Activate", + "Deactivate": "Deactivate", + "Sync": "Sync", + "Failed_to_create_PaymeTrust_transaction_": "Failed to create PaymeTrust transaction.", + "Location": "Location", + "Voucher_Format": "Voucher Format", + "Service_Type": "Service Type", + "Others": "Others", + "PPPoE": "PPPoE", + "Hotspot": "Hotspot", + "Monthly_Registered_Customers": "Monthly Registered Customers", + "Total_Monthly_Sales": "Total Monthly Sales", + "Active_Users": "Active Users" +} \ No newline at end of file diff --git a/system/mpesa/verifyPayment.php b/system/mpesa/verifyPayment.php new file mode 100644 index 0000000..6b7a4a9 --- /dev/null +++ b/system/mpesa/verifyPayment.php @@ -0,0 +1,86 @@ + 'error', 'code' => 400, 'message' => 'missing CheckoutRequestID fields']); + return; + } + + $CheckoutRequestID = $postData['CheckoutRequestID']; + + $consumerKey = '3AmVP1WFDQn7GrDH8GcSSKxcAvnJdZGC'; // Fill with your app Consumer Key + $consumerSecret = '71Lybl6jUtxM0F35'; // Fill with your app Secret + + $headers = ['Content-Type:application/json; charset=utf8']; + + $access_token_url = 'https://api.safaricom.co.ke/oauth/v1/generate?grant_type=client_credentials'; + $curl = curl_init($access_token_url); + curl_setopt($curl, CURLOPT_HTTPHEADER, $headers); + curl_setopt($curl, CURLOPT_RETURNTRANSFER, TRUE); + curl_setopt($curl, CURLOPT_HEADER, FALSE); + curl_setopt($curl, CURLOPT_USERPWD, $consumerKey.':'.$consumerSecret); + $result = curl_exec($curl); + $status = curl_getinfo($curl, CURLINFO_HTTP_CODE); + $result = json_decode($result); + + $access_token = $result->access_token; + + date_default_timezone_set('Africa/Nairobi'); + $query_url = 'https://api.safaricom.co.ke/mpesa/stkpushquery/v1/query'; + $BusinessShortCode = '4122323'; + $Passkey = 'aaebecea73082fa56af852606106b1316d5b4dfa2f12d0088800b0b88e4bb6e3'; + $Timestamp = date('YmdHis'); + + // ENCRYPT DATA TO GET PASSWORD + $Password = base64_encode($BusinessShortCode . $Passkey . $Timestamp); + + // THIS IS THE UNIQUE ID THAT WAS GENERATED WHEN STK REQUEST INITIATED SUCCESSFULLY + $queryheader = ['Content-Type:application/json', 'Authorization:Bearer ' . $access_token]; + + // Initiating the transaction + $curl = curl_init(); + curl_setopt($curl, CURLOPT_URL, $query_url); + curl_setopt($curl, CURLOPT_HTTPHEADER, $queryheader); // Setting custom header + $curl_post_data = array( + 'BusinessShortCode' => $BusinessShortCode, + 'Password' => $Password, + 'Timestamp' => $Timestamp, + 'CheckoutRequestID' => $CheckoutRequestID + ); + $data_string = json_encode($curl_post_data); + curl_setopt($curl, CURLOPT_RETURNTRANSFER, true); + curl_setopt($curl, CURLOPT_POST, true); + curl_setopt($curl, CURLOPT_POSTFIELDS, $data_string); + $curl_response = curl_exec($curl); + $data_to = json_decode($curl_response, true); + + // Handle response + if (isset($data_to['ResultCode'])) { + $ResultCode = $data_to['ResultCode']; + if ($ResultCode == '1037') { + $message = "1037 Timeout in completing transaction"; + } elseif ($ResultCode == '1032') { + $message = "1032 Transaction has been cancelled by user"; + } elseif ($ResultCode == '1') { + $message = "1 The balance is insufficient for the transaction"; + } elseif ($ResultCode == '0') { + $message = "0 The transaction is successful"; + } else { + $message = "Unknown Result Code: $ResultCode"; + } + } else { + $message = "Error in the response received from the M-Pesa API"; + } + + // Sending the response back + echo json_encode([ + 'message' => $message, + 'result' => $data_to + ]); +} +?> diff --git a/system/paymentgateway/BankStkPush.php b/system/paymentgateway/BankStkPush.php new file mode 100644 index 0000000..1c3347d --- /dev/null +++ b/system/paymentgateway/BankStkPush.php @@ -0,0 +1,205 @@ +assign('_title', 'Bank Stk Push - ' . $config['CompanyName']); + $ui->display('bankstkpush.tpl'); +} + +function BankStkPush_save_config() +{ + global $admin, $_L; + $bankacc = _post('account'); + $bankname = _post('bankname'); + $d = ORM::for_table('tbl_appconfig')->where('setting', 'Stkbankacc')->find_one(); + if ($d) { + $d->value = $bankacc; + $d->save(); + } else { + $d = ORM::for_table('tbl_appconfig')->create(); + $d->setting = 'Stkbankacc'; + $d->value = $bankacc; + $d->save(); + } + $d = ORM::for_table('tbl_appconfig')->where('setting', 'Stkbankname')->find_one(); + if ($d) { + $d->value = $bankname; + $d->save(); + } else { + $d = ORM::for_table('tbl_appconfig')->create(); + $d->setting = 'Stkbankname'; + $d->value = $bankname; + $d->save(); + } + + _log('[' . $admin['username'] . ']: Stk Bank details ' . $_L['Settings_Saved_Successfully'], 'Admin', $admin['id']); + + r2(U . 'paymentgateway/BankStkPush', 's', $_L['Settings_Saved_Successfully']); +} + + +function BankStkPush_create_transaction($trx, $user ) +{ + $url=(U. "plugin/initiatebankstk"); + + $d = ORM::for_table('tbl_payment_gateway') + ->where('username', $user['username']) + ->where('status', 1) + ->find_one(); + $d->gateway_trx_id = ''; + $d->payment_method = 'Bank Stk Push'; + $d->pg_url_payment = $url; + $d->pg_request = ''; + $d->expired_date = date('Y-m-d H:i:s', strtotime("+5 minutes")); + $d->save(); + + r2(U . "order/view/" . $d['id'], 's', Lang::T("Create Transaction Success, Please click pay now to process payment")); + + die(); +} + +function BankStkPush_payment_notification() +{ + $captureLogs = file_get_contents("php://input"); + + $analizzare = json_decode($captureLogs); + /// sleep(10); + file_put_contents('back.log',$captureLogs,FILE_APPEND); + $response_code = $analizzare->Body->stkCallback->ResultCode; + $resultDesc = ($analizzare->Body->stkCallback->ResultDesc); + $merchant_req_id = ($analizzare->Body->stkCallback->MerchantRequestID); + $checkout_req_id = ($analizzare->Body->stkCallback->CheckoutRequestID); + + $amount_paid = ($analizzare->Body->stkCallback->CallbackMetadata->Item['0']->Value);//get the amount value + $mpesa_code = ($analizzare->Body->stkCallback->CallbackMetadata->Item['1']->Value);//mpesa transaction code.. + $sender_phone = ($analizzare->Body->stkCallback->CallbackMetadata->Item['4']->Value);//Telephone Number + + $PaymentGatewayRecord = ORM::for_table('tbl_payment_gateway') + ->where('checkout', $checkout_req_id) + ->where('status', 1) // Add this line to filter by status + ->order_by_desc('id') + ->find_one(); + + $uname=$PaymentGatewayRecord->username; + $plan_id=$PaymentGatewayRecord->plan_id; + $mac_address=$PaymentGatewayRecord->mac_address; + $user=$PaymentGatewayRecord; + + $userid = ORM::for_table('tbl_customers') + ->where('username', $uname) + ->order_by_desc('id') + ->find_one(); + + $userid->username=$uname; + $userid->save(); + $plans = ORM::for_table('tbl_plans') + ->where('id', $plan_id) + + ->order_by_desc('id') + ->find_one(); + + if ($response_code=="1032") + { + $now = date('Y-m-d H:i:s'); + $PaymentGatewayRecord->paid_date = $now; + $PaymentGatewayRecord->status = 4; + $PaymentGatewayRecord->save(); + + exit(); + } + if($response_code=="1037"){ + $PaymentGatewayRecord->status = 1; + $PaymentGatewayRecord->pg_paid_response = 'User failed to enter pin'; + $PaymentGatewayRecord->save(); + + exit(); + } + + if($response_code=="1"){ + $PaymentGatewayRecord->status = 1; + $PaymentGatewayRecord->pg_paid_response = 'Not enough balance'; + $PaymentGatewayRecord->save(); + + exit(); + } + + if($response_code=="2001"){ + $PaymentGatewayRecord->status = 1; + $PaymentGatewayRecord->pg_paid_response = 'Wrong Mpesa pin'; + $PaymentGatewayRecord->save(); + + exit(); + } + + if($response_code=="0"){ + + $now = date('Y-m-d H:i:s'); + $date = date('Y-m-d'); + $time= date('H:i:s'); + + $check_mpesa = ORM::for_table('tbl_payment_gateway') + ->where('gateway_trx_id', $mpesa_code) + ->find_one(); + + if($check_mpesa){ + echo "double callback, ignore one"; + + die; + } + + $plan_type=$plans->type; + $UserId=$userid->id; + + if (!Package::rechargeUser($UserId, $user['routers'], $user['plan_id'], $user['gateway'], $mpesa_code)){ + $PaymentGatewayRecord->status = 2; + $PaymentGatewayRecord->paid_date = $now; + $PaymentGatewayRecord->gateway_trx_id = $mpesa_code; + $PaymentGatewayRecord->save(); + $username = $PaymentGatewayRecord->username; + + // Check if a transaction with the same gateway_trx_id already exists + $existingTransaction = ORM::for_table('tbl_transactions') + ->where('mpesacode', $mpesa_code) + ->find_one(); + + if (!$existingTransaction) { + // Save transaction data to tbl_transactions + $transaction = ORM::for_table('tbl_transactions')->create(); + $transaction->invoice = $PaymentGatewayRecord->gateway_trx_id; // Set invoice to gateway_trx_id value + $transaction->username = $PaymentGatewayRecord->username; + $transaction->plan_name = $PaymentGatewayRecord->plan_name; + $transaction->price = $amount_paid; + $transaction->recharged_on = $date; + $transaction->recharged_time = $time; + $transaction->expiration = $now; + $transaction->time = $now; + $transaction->method = $PaymentGatewayRecord->payment_method; + $transaction->routers = 0; + $transaction->Type = 'Balance'; + $transaction->mpesacode = $mpesa_code; + $transaction->save(); + } else { + error_log("Duplicate transaction entry detected for gateway_trx_id: " . $PaymentGatewayRecord->gateway_trx_id); + } + } else { + // Update tbl_recharges + $PaymentGatewayRecord->status = 2; + $PaymentGatewayRecord->paid_date = $now; + $PaymentGatewayRecord->gateway_trx_id = $mpesa_code; + $PaymentGatewayRecord->save(); + } + + + } +} diff --git a/system/paymentgateway/MpesatillStk.php b/system/paymentgateway/MpesatillStk.php new file mode 100644 index 0000000..aac06d3 --- /dev/null +++ b/system/paymentgateway/MpesatillStk.php @@ -0,0 +1,423 @@ +assign('env', json_decode(file_get_contents('system/paymentgateway/mpesa_env.json'), true)); + $ui->assign('_title', 'M-Pesa - Payment Gateway (for till number only) - ' . $config['CompanyName']); + $ui->display('mpesatill.tpl'); +} + + +function MpesatillStk_save_config() +{ + global $admin, $_L; + $mpesa_consumer_key = _post('mpesa_consumer_key'); + $mpesa_consumer_secret = _post('mpesa_consumer_secret'); + $mpesa_business_code = _post('mpesa_business_code'); + $mpesa_till = _post('mpesa_till'); + $mpesa_pass_key = _post('mpesa_pass_key'); + $mpesa_env = _post('mpesa_env'); + $d = ORM::for_table('tbl_appconfig')->where('setting', 'mpesa_till_consumer_key')->find_one(); + if ($d) { + $d->value = $mpesa_consumer_key; + $d->save(); + } else { + $d = ORM::for_table('tbl_appconfig')->create(); + $d->setting = 'mpesa_till_consumer_key'; + $d->value = $mpesa_consumer_key; + $d->save(); + } + $d = ORM::for_table('tbl_appconfig')->where('setting', 'mpesa_till_consumer_secret')->find_one(); + if ($d) { + $d->value = $mpesa_consumer_secret; + $d->save(); + } else { + $d = ORM::for_table('tbl_appconfig')->create(); + $d->setting = 'mpesa_till_consumer_secret'; + $d->value = $mpesa_consumer_secret; + $d->save(); + } + + $d = ORM::for_table('tbl_appconfig')->where('setting', 'mpesa_till_shortcode_code')->find_one(); + if ($d) { + $d->value = $mpesa_business_code; + $d->save(); + } else { + $d = ORM::for_table('tbl_appconfig')->create(); + $d->setting = 'mpesa_till_shortcode_code'; + $d->value = $mpesa_business_code; + $d->save(); + } + + $d = ORM::for_table('tbl_appconfig')->where('setting', 'mpesa_till_partyb')->find_one(); + if ($d) { + $d->value = $mpesa_till; + $d->save(); + } else { + $d = ORM::for_table('tbl_appconfig')->create(); + $d->setting = 'mpesa_till_partyb'; + $d->value = $mpesa_till; + $d->save(); + } + + $d = ORM::for_table('tbl_appconfig')->where('setting', 'mpesa_till_pass_key')->find_one(); + if ($d) { + $d->value = $mpesa_pass_key; + $d->save(); + } else { + $d = ORM::for_table('tbl_appconfig')->create(); + $d->setting = 'mpesa_till_pass_key'; + $d->value = $mpesa_pass_key; + $d->save(); + } + $d = ORM::for_table('tbl_appconfig')->where('setting', 'mpesa_env')->find_one(); + if ($d) { + $d->value = $mpesa_env; + $d->save(); + } else { + $d = ORM::for_table('tbl_appconfig')->create(); + $d->setting = 'mpesa_env'; + $d->value = $mpesa_env; + $d->save(); + } + + _log('[' . $admin['username'] . ']: M-Pesa ' . $_L['Settings_Saved_Successfully'] . json_encode($_POST['mpesa_channel']), 'Admin', $admin['id']); + + r2(U . 'paymentgateway/MpesatillStk', 's', $_L['Settings_Saved_Successfully']); +} + + +function MpesatillStk_create_transaction($trx, $user ) +{ + + + $url=(U. "plugin/initiatetillstk"); + + $d = ORM::for_table('tbl_payment_gateway') + ->where('username', $user['username']) + ->where('status', 1) + ->find_one(); + $d->gateway_trx_id = ''; + $d->payment_method = 'Mpesa till STK'; + $d->pg_url_payment = $url; + $d->pg_request = ''; + $d->expired_date = date('Y-m-d H:i:s', strtotime("+5 minutes")); + $d->save(); + + r2(U . "order/view/" . $d['id'], 's', Lang::T("Create Transaction Success, Please click pay now to process payment")); + + die(); + + + + + + +} + + + + +function MpesatillStk_payment_notification() +{ + $captureLogs = file_get_contents("php://input"); + + $analizzare = json_decode($captureLogs); +/// sleep(10); + file_put_contents('back.log',$captureLogs,FILE_APPEND); + $response_code = $analizzare->Body->stkCallback->ResultCode; + $resultDesc = ($analizzare->Body->stkCallback->ResultDesc); + $merchant_req_id = ($analizzare->Body->stkCallback->MerchantRequestID); + $checkout_req_id = ($analizzare->Body->stkCallback->CheckoutRequestID); + + + $amount_paid = ($analizzare->Body->stkCallback->CallbackMetadata->Item['0']->Value);//get the amount value + $mpesa_code = ($analizzare->Body->stkCallback->CallbackMetadata->Item['1']->Value);//mpesa transaction code.. + $sender_phone = ($analizzare->Body->stkCallback->CallbackMetadata->Item['4']->Value);//Telephone Number + + + + + + + $PaymentGatewayRecord = ORM::for_table('tbl_payment_gateway') + ->where('checkout', $checkout_req_id) + ->where('status', 1) // Add this line to filter by status + ->order_by_desc('id') + ->find_one(); + + $uname=$PaymentGatewayRecord->username; + + + $plan_id=$PaymentGatewayRecord->plan_id; + + + $mac_address=$PaymentGatewayRecord->mac_address; + + $user=$PaymentGatewayRecord; + + + $userid = ORM::for_table('tbl_customers') + ->where('username', $uname) + ->order_by_desc('id') + ->find_one(); + + $userid->username=$uname; + $userid->save(); + + + + + $plans = ORM::for_table('tbl_plans') + ->where('id', $plan_id) + + ->order_by_desc('id') + ->find_one(); + + + + + + + + + + + + if ($response_code=="1032") + { + $now = date('Y-m-d H:i:s'); + $PaymentGatewayRecord->paid_date = $now; + $PaymentGatewayRecord->status = 4; + $PaymentGatewayRecord->save(); + + exit(); + + } + + + + + if($response_code=="1037"){ + + + $PaymentGatewayRecord->status = 1; + $PaymentGatewayRecord->pg_paid_response = 'User failed to enter pin'; + $PaymentGatewayRecord->save(); + + exit(); + + + } + + if($response_code=="1"){ + + + $PaymentGatewayRecord->status = 1; + $PaymentGatewayRecord->pg_paid_response = 'Not enough balance'; + $PaymentGatewayRecord->save(); + + exit(); + + + } + + + if($response_code=="2001"){ + + + $PaymentGatewayRecord->status = 1; + $PaymentGatewayRecord->pg_paid_response = 'Wrong Mpesa pin'; + $PaymentGatewayRecord->save(); + + exit(); + + + } + + if($response_code=="0"){ + + + $now = date('Y-m-d H:i:s'); + + $date = date('Y-m-d'); + $time= date('H:i:s'); + + + + + + + $check_mpesa = ORM::for_table('tbl_payment_gateway') + ->where('gateway_trx_id', $mpesa_code) + ->find_one(); + + +if($check_mpesa){ + + echo "double callback, ignore one"; + + die; + + +} + + + + + $plan_type=$plans->type; + + $UserId=$userid->id; + + + + + if (!Package::rechargeUser($UserId, $user['routers'], $user['plan_id'], $user['gateway'], $mpesa_code)){ + + + + + + + $PaymentGatewayRecord->status = 2; + $PaymentGatewayRecord->paid_date = $now; + $PaymentGatewayRecord->gateway_trx_id = $mpesa_code; + $PaymentGatewayRecord->save(); + + + + + + $username=$PaymentGatewayRecord->username; + + // Save transaction data to tbl_transactions + $transaction = ORM::for_table('tbl_transactions')->create(); + $transaction->invoice = $mpesa_code; + $transaction->username = $PaymentGatewayRecord->username; + $transaction->plan_name = $PaymentGatewayRecord->plan_name; + $transaction->price = $amount_paid; + $transaction->recharged_on = $date; + $transaction->recharged_time = $time; + $transaction->expiration = $now; + $transaction->time = $now; + $transaction->method = $PaymentGatewayRecord->payment_method; + $transaction->routers = 0; + $transaction->Type = 'Balance'; + $transaction->save(); + + + } else{ + + + //lets update tbl_recharges +/* + $transaction = ORM::for_table('tbl_transactions')->create(); + $transaction->invoice = $mpesa_code; + $transaction->username = $PaymentGatewayRecord->username; + $transaction->plan_name = $PaymentGatewayRecord->plan_name; + $transaction->price = $amount_paid; + $transaction->recharged_on = $date; + $transaction->recharged_time = $time; + $transaction->expiration = $now; + $transaction->time = $now; + $transaction->method = $PaymentGatewayRecord->payment_method; + $transaction->routers = 0; + $transaction->Type = $PaymentGatewayRecord->routers; + $transaction->save(); + +*/ + + + + + $PaymentGatewayRecord->status = 2; + $PaymentGatewayRecord->paid_date = $now; + $PaymentGatewayRecord->gateway_trx_id = $mpesa_code; + $PaymentGatewayRecord->save(); + + + } + + + + + + + + + + + + /* + + + $checkid = ORM::for_table('tbl_customers') + ->where('username', $username) + ->find_one(); + + + + + + $customerid=$checkid->id; + + + + + + + + + $recharge = ORM::for_table('tbl_user_recharges')->create(); + $recharge->customer_id = $customerid; + $recharge->username = $PaymentGatewayRecord->username; + $recharge->plan_id = $PaymentGatewayRecord->plan_id; + $recharge->price = $amount_paid; + $recharge->recharged_on = $date; + $recharge->recharged_time = $time; + $recharge->expiration = $now; + $recharge->time = $now; + $recharge->method = $PaymentGatewayRecord->payment_method; + $recharge->routers = 0; + $recharge->Type = 'Balance'; + $recharge->save(); + + + + */ + + + + + // $user = ORM::for_table('tbl_customers') + // ->where('username', $username) + // ->find_one(); + + // $currentBalance = $user->balance; + + // $user->balance = $currentBalance + $amount_paid; + // $user->save(); + + // exit(); + + + + } + + + + + + +} diff --git a/system/paymentgateway/flutterwave.php b/system/paymentgateway/flutterwave.php new file mode 100644 index 0000000..7754b49 --- /dev/null +++ b/system/paymentgateway/flutterwave.php @@ -0,0 +1,234 @@ +assign('_title', 'Flutterwave - Payment Gateway'); + $ui->assign('cur', json_decode(file_get_contents('system/paymentgateway/flutterwave_currency.json'), true)); + $ui->assign('channel', json_decode(file_get_contents('system/paymentgateway/flutterwave_channel.json'), true)); + $ui->display('flutterwave.tpl'); + } + + + function flutterwave_save_config() + { + global $admin, $_L; + $flutterwave_secret_key = _post('flutterwave_secret_key'); + $flutterwave_currency = _post('flutterwave_currency'); + $d = ORM::for_table('tbl_appconfig')->where('setting', 'flutterwave_secret_key')->find_one(); + if ($d) { + $d->value = $flutterwave_secret_key; + $d->save(); + } else { + $d = ORM::for_table('tbl_appconfig')->create(); + $d->setting = 'flutterwave_secret_key'; + $d->value = $flutterwave_secret_key; + $d->save(); + } + $d = ORM::for_table('tbl_appconfig')->where('setting', 'flutterwave_currency')->find_one(); + if ($d) { + $d->value = $flutterwave_currency; + $d->save(); + } else { + $d = ORM::for_table('tbl_appconfig')->create(); + $d->setting = 'flutterwave_currency'; + $d->value = $flutterwave_currency; + $d->save(); + } + $d = ORM::for_table('tbl_appconfig')->where('setting', 'flutterwave_channel')->find_one(); + if ($d) { + $d->value = implode(',', $_POST['flutterwave_channel']); + $d->save(); + } else { + $d = ORM::for_table('tbl_appconfig')->create(); + $d->setting = 'flutterwave_channel'; + $d->value = implode(',', $_POST['flutterwave_channel']); + $d->save(); + } + _log('[' . $admin['username'] . ']: Flutterwave ' . $_L['Settings_Saved_Successfully'], 'Admin', $admin['id']); + + r2(U . 'paymentgateway/flutterwave', 's', $_L['Settings_Saved_Successfully']); + } + +function flutterwave_create_transaction($trx, $user) +{ + global $config; + $txref = uniqid('trx'); + $json = [ + 'tx_ref' => $txref, + 'amount' => $trx['price'], + 'currency' => $config['flutterwave_currency'], + 'payment_options' => explode(',', $config['flutterwave_channel']), + 'customer' => [ + 'email' => (empty($user['email'])) ? $user['username'] . '@' . $_SERVER['HTTP_HOST'] : $user['email'], + 'name' => $user['fullname'], + 'phonenumber' => $user['phonenumber'] + ], + 'meta' => [ + 'price' => $trx['price'], + 'username' => $user['username'], + 'trxid' => $trx['id'] + ], + + 'customizations' => [ + 'title' => $trx['plan_name'], + 'description' => $trx['plan_name'], + ], + + 'redirect_url' => U . 'callback/flutterwave' + ]; + // die(json_encode($json,JSON_PRETTY_PRINT)); + + $result = json_decode(Http::postJsonData(flutterwave_get_server() . 'payments', $json,[ + 'Authorization: Bearer ' . $config['flutterwave_secret_key'], + 'Cache-Control: no-cahe' + ], + ), +true); + +//die(json_encode($result,JSON_PRETTY_PRINT)); + +if ($result['status'] == 'error') { + Message::sendTelegram("Flutterwave payment failed\n\n" . json_encode($result, JSON_PRETTY_PRINT)); + r2(U . 'order/package', 'e', Lang::T("Failed to create transaction.\n".$result['message'])); + } + $d = ORM::for_table('tbl_payment_gateway') + ->where('username', $user['username']) + ->where('status', 1) + ->find_one(); + $d->gateway_trx_id = $txref; + $d->pg_url_payment = $result['data']['link']; + $d->pg_request = json_encode($result); + $d->expired_date = date('Y-m-d H:i:s', strtotime("+ 6 HOUR")); + $d->save(); + + header('Location: ' . $result['data']['link']); + exit(); + + r2(U . "order/view/" . $d['id'], 's', Lang::T("Create Transaction Success")); + + +} + +function flutterwave_payment_notification() +{ + global $config; +if(isset($_GET['status'])) + + { + //* check payment status + if($_GET['status'] == 'cancelled') + { + // die(json_encode($txref,JSON_PRETTY_PRINT)); + Message::sendTelegram("Flutterwave Payment Cancelled: \n\n"); + r2(U . 'order/package', 'e', Lang::T("Flutterwave Payment Cancelled.")); + } + elseif($_GET['status'] == 'successful') + { + + $txid = $_GET['transaction_id']; + $result = json_decode(Http::getData(flutterwave_get_server() . 'transactions/' . $txid. '/verify', [ + 'Authorization: Bearer ' . $config['flutterwave_secret_key'], + 'Cache-Control: no-cahe' + ]), true); + //die(json_encode($result,JSON_PRETTY_PRINT)); + { + $id = $result['data']['id']; + $amountPaid = $result['data']['charged_amount']; + $amountToPay = $result['data']['meta']['price']; + $username = $result['data']['meta']['username']; + $trxid = $result['data']['meta']['trxid']; + if($amountPaid >= $amountToPay) + { + // die(json_encode($trxid,JSON_PRETTY_PRINT)); + // echo 'Payment successful'; + $d = ORM::for_table('tbl_payment_gateway') + ->where('username', $username) + ->where('status', 1) + ->find_one(); + $d->gateway_trx_id = $id; + $d->save(); + r2(U . 'order/view/'.$trxid.'/check'); + // r2(U . 'order/package', 's', Lang::T("Flutterwave Payment Completed.")); + exit(); + //* Continue to give item to the user + } + else + { + // echo 'Fraud transactio detected'; + r2(U . 'order/package', 'e', Lang::T("Fraud transactions detected.")); + exit(); + } + } + } + } + } + + + function flutterwave_get_status($trx, $user) + { + global $config; + $trans_id = $trx['gateway_trx_id']; + $result = json_decode(Http::getData(flutterwave_get_server() . 'transactions/' . $trx['gateway_trx_id']. '/verify', [ + 'Authorization: Bearer ' . $config['flutterwave_secret_key'], + 'Cache-Control: no-cahe' + ]), true); + //die(json_encode($result,JSON_PRETTY_PRINT)); + if ($result['status'] == 'error') { + r2(U . "order/view/" . $trx['id'], 'w', Lang::T("Transaction still unpaid.")); + } else if (in_array($result['status'], ['success']) && $trx['status'] != 2) { + if (!Package::rechargeUser($user['id'], $trx['routers'], $trx['plan_id'], $trx['gateway'], 'Flutterwave')) { + r2(U . "order/view/" . $trx['id'], 'd', Lang::T("Failed to activate your Package, please try again later.")); + } + $trx->pg_paid_response = json_encode($result); + $trx->payment_method = 'Flutterwave'; + $trx->payment_channel = $result['data']['payment_type']; + $trx->paid_date = date('Y-m-d H:i:s', strtotime( $result['data']['created_at'])); + $trx->status = 2; + $trx->save(); + + r2(U . "order/view/" . $trx['id'], 's', Lang::T("Transaction successful.")); + } else if ($result['status'] == 'EXPIRED') { + $trx->pg_paid_response = json_encode($result); + $trx->status = 3; + $trx->save(); + r2(U . "order/view/" . $trx['id'], 'd', Lang::T("Transaction expired.")); + } else if ($trx['status'] == 2) { + r2(U . "order/view/" . $trx['id'], 'd', Lang::T("Transaction has been paid..")); + }else{ + Message::sendTelegram("flutterwave_get_status: unknown result\n\n".json_encode($result, JSON_PRETTY_PRINT)); + r2(U . "order/view/" . $trx['id'], 'd', Lang::T("Unknown Command.")); + } + + } + + +function flutterwave_get_server() +{ + global $_app_stage; + if ($_app_stage == 'Live') { + return 'https://api.flutterwave.com/v3/'; + } else { + return 'https://api.flutterwave.com/v3/'; + } +} diff --git a/system/paymentgateway/flutterwave_channel.json b/system/paymentgateway/flutterwave_channel.json new file mode 100644 index 0000000..09e38c1 --- /dev/null +++ b/system/paymentgateway/flutterwave_channel.json @@ -0,0 +1,35 @@ +[ + + { + "id": "card", + "name": "Card Payment" + }, + { + "id": "ussd", + "name": "USSD" + }, + { + "id": "account", + "name": "Bank Account" + }, + { + "id": "banktransfer", + "name": "Bank Transfer" + }, + { + "id": "nqr", + "name": "QR payment" + }, + { + "id": "mpesa", + "name": "M-Pesa" + }, + { + "id": "mobilemoneyghana", + "name": "Mobile money Ghana" + }, + { + "id": "credit", + "name": "Credit payment" + } +] diff --git a/system/paymentgateway/flutterwave_currency.json b/system/paymentgateway/flutterwave_currency.json new file mode 100644 index 0000000..fe716ea --- /dev/null +++ b/system/paymentgateway/flutterwave_currency.json @@ -0,0 +1,30 @@ +[ + { + "id": "NGN", + "name": "Nigerian Naira" + }, + { + "id": "GHC", + "name": "Ghana Cedis" + }, + { + "id": "KES", + "name": "Kenyan Shilling" + }, + { + "id": "ZAR", + "name": "South African Rand" + }, + { + "id": "GBP", + "name": "British Pound Sterling" + }, + { + "id": "USD", + "name": "United States Dollar" + }, + { + "id": "TZS", + "name": "Tanzanian Shilling" + } +] diff --git a/system/paymentgateway/index.html b/system/paymentgateway/index.html new file mode 100644 index 0000000..06d7405 Binary files /dev/null and b/system/paymentgateway/index.html differ diff --git a/system/paymentgateway/iotec.OLD b/system/paymentgateway/iotec.OLD new file mode 100644 index 0000000..f296de5 --- /dev/null +++ b/system/paymentgateway/iotec.OLD @@ -0,0 +1,254 @@ +assign('_title', 'ioTec Pay - Payment Gateway'); + $ui->assign('env', [ + ['id' => 'Sandbox', 'name' => 'Sandbox (Testing)'], + ['id' => 'Live', 'name' => 'Live (Production)'] + ]); + $ui->display('iotec.tpl'); +} + +function iotec_save_config() +{ + global $admin, $_L; + $iotec_client_id = _post('iotec_client_id'); + $iotec_client_secret = _post('iotec_client_secret'); + $iotec_wallet_id = _post('iotec_wallet_id'); + $iotec_env = _post('iotec_env'); + + $d = ORM::for_table('tbl_appconfig')->where('setting', 'iotec_client_id')->find_one(); + if ($d) { + $d->value = $iotec_client_id; + $d->save(); + } else { + $d = ORM::for_table('tbl_appconfig')->create(); + $d->setting = 'iotec_client_id'; + $d->value = $iotec_client_id; + $d->save(); + } + + $d = ORM::for_table('tbl_appconfig')->where('setting', 'iotec_client_secret')->find_one(); + if ($d) { + $d->value = $iotec_client_secret; + $d->save(); + } else { + $d = ORM::for_table('tbl_appconfig')->create(); + $d->setting = 'iotec_client_secret'; + $d->value = $iotec_client_secret; + $d->save(); + } + + $d = ORM::for_table('tbl_appconfig')->where('setting', 'iotec_wallet_id')->find_one(); + if ($d) { + $d->value = $iotec_wallet_id; + $d->save(); + } else { + $d = ORM::for_table('tbl_appconfig')->create(); + $d->setting = 'iotec_wallet_id'; + $d->value = $iotec_wallet_id; + $d->save(); + } + + $d = ORM::for_table('tbl_appconfig')->where('setting', 'iotec_env')->find_one(); + if ($d) { + $d->value = $iotec_env; + $d->save(); + } else { + $d = ORM::for_table('tbl_appconfig')->create(); + $d->setting = 'iotec_env'; + $d->value = $iotec_env; + $d->save(); + } + + _log('[' . $admin['username'] . ']: ioTec Pay ' . $_L['Settings_Saved_Successfully'], 'Admin', $admin['id']); + r2(U . 'paymentgateway/iotec', 's', $_L['Settings_Saved_Successfully']); +} + +function iotec_create_transaction($trx, $user) +{ + global $config; + $externalId = uniqid('bill_'); + + // Obtain access token + $tokenResponse = json_decode(Http::postData(iotec_get_server('auth') . 'connect/token', [ + 'client_id' => $config['iotec_client_id'], + 'client_secret' => $config['iotec_client_secret'], + 'grant_type' => 'client_credentials' + ], [ + 'Content-Type: application/x-www-form-urlencoded' + ]), true); + + if (empty($tokenResponse['access_token'])) { + Message::sendTelegram("ioTec payment failed: Failed to obtain access token\n\n" . json_encode($tokenResponse, JSON_PRETTY_PRINT)); + r2(U . 'order/package', 'e', Lang::T("Failed to authenticate with ioTec.")); + } + + $json = [ + 'category' => 'MobileMoney', + 'currency' => 'ITX', + 'walletId' => $config['iotec_wallet_id'], + 'externalId' => $externalId, + 'payer' => $user['phonenumber'], + 'amount' => $trx['price'], + 'payerNote' => 'Payment for ' . $trx['plan_name'], + 'payeeNote' => 'Hotspot billing', + 'transactionChargesCategory' => 'ChargeCustomer' + ]; + + $result = json_decode(Http::postJsonData(iotec_get_server('api') . 'api/collections/collect', $json, [ + 'Authorization: Bearer ' . $tokenResponse['access_token'], + 'Content-Type: application/json' + ]), true); + + if (empty($result['id'])) { + Message::sendTelegram("ioTec payment failed\n\n" . json_encode($result, JSON_PRETTY_PRINT)); + r2(U . 'order/package', 'e', Lang::T("Failed to create transaction.\n" . ($result['message'] ?? 'Unknown error'))); + } + + $d = ORM::for_table('tbl_payment_gateway') + ->where('username', $user['username']) + ->where('status', 1) + ->find_one(); + $d->gateway_trx_id = $result['id']; + $d->pg_url_payment = 'N/A'; // ioTec doesn't provide a payment URL + $d->pg_request = json_encode($result); + $d->expired_date = date('Y-m-d H:i:s', strtotime("+6 HOUR")); + $d->save(); + + r2(U . "order/view/" . $d['id'], 's', Lang::T("Transaction created. Please authorize the payment on your phone.")); +} + +function iotec_payment_notification() +{ + global $config; + $headers = getallheaders(); + $securityKey = $headers['X-Callback-Security-Key'] ?? ''; + $expectedKey = $config['iotec_callback_security_key'] ?? 'your_callback_security_key'; + + if ($securityKey !== $expectedKey) { + Message::sendTelegram("ioTec callback failed: Invalid security key\n\n" . json_encode($headers, JSON_PRETTY_PRINT)); + http_response_code(401); + exit(json_encode(['status' => 'error', 'message' => 'Invalid security key'])); + } + + $data = json_decode(file_get_contents('php://input'), true); + if (empty($data['id']) || empty($data['status'])) { + Message::sendTelegram("ioTec callback failed: Invalid data\n\n" . json_encode($data, JSON_PRETTY_PRINT)); + http_response_code(400); + exit(json_encode(['status' => 'error', 'message' => 'Invalid callback data'])); + } + + $transactionId = $data['id']; + $status = $data['status']; + $externalId = $data['externalId'] ?? ''; + $amountPaid = $data['amount'] ?? 0; + $username = $data['payer'] ?? ''; // Map to username via lookup if needed + $trxid = $data['externalId'] ?? ''; // Map to transaction ID + + $d = ORM::for_table('tbl_payment_gateway') + ->where('gateway_trx_id', $transactionId) + ->where('status', 1) + ->find_one(); + + if (!$d) { + Message::sendTelegram("ioTec callback failed: Transaction not found\n\n" . json_encode($data, JSON_PRETTY_PRINT)); + http_response_code(404); + exit(json_encode(['status' => 'error', 'message' => 'Transaction not found'])); + } + + if ($status === 'Success') { + $d->gateway_trx_id = $transactionId; + $d->save(); + r2(U . 'order/view/' . $d['id'] . '/check', 's', Lang::T("ioTec Payment Completed.")); + } elseif ($status === 'Failed') { + Message::sendTelegram("ioTec Payment Failed: \n\n" . json_encode($data, JSON_PRETTY_PRINT)); + r2(U . 'order/package', 'e', Lang::T("ioTec Payment Failed.")); + } else { + Message::sendTelegram("ioTec Payment Pending: \n\n" . json_encode($data, JSON_PRETTY_PRINT)); + r2(U . 'order/package', 'w', Lang::T("ioTec Payment Pending.")); + } +} + +function iotec_get_status($trx, $user) +{ + global $config; + $trans_id = $trx['gateway_trx_id']; + + // Obtain access token + $tokenResponse = json_decode(Http::postData(iotec_get_server('auth') . 'connect/token', [ + 'client_id' => $config['iotec_client_id'], + 'client_secret' => $config['iotec_client_secret'], + 'grant_type' => 'client_credentials' + ], [ + 'Content-Type: application/x-www-form-urlencoded' + ]), true); + + if (empty($tokenResponse['access_token'])) { + Message::sendTelegram("ioTec status check failed: Failed to obtain access token\n\n" . json_encode($tokenResponse, JSON_PRETTY_PRINT)); + r2(U . "order/view/" . $trx['id'], 'w', Lang::T("Failed to authenticate with ioTec.")); + } + + $result = json_decode(Http::getData(iotec_get_server('api') . 'api/collections/status/' . $trans_id, [ + 'Authorization: Bearer ' . $tokenResponse['access_token'], + 'Content-Type: application/json' + ]), true); + + if (empty($result['status'])) { + Message::sendTelegram("ioTec status check failed\n\n" . json_encode($result, JSON_PRETTY_PRINT)); + r2(U . "order/view/" . $trx['id'], 'w', Lang::T("Transaction still unpaid.")); + } elseif ($result['status'] === 'Success' && $trx['status'] != 2) { + if (!Package::rechargeUser($user['id'], $trx['routers'], $trx['plan_id'], $trx['gateway'], 'ioTec')) { + r2(U . "order/view/" . $trx['id'], 'd', Lang::T("Failed to activate your Package, please try again later.")); + } + $trx->pg_paid_response = json_encode($result); + $trx->payment_method = 'ioTec'; + $trx->payment_channel = 'MobileMoney'; + $trx->paid_date = date('Y-m-d H:i:s'); + $trx->status = 2; + $trx->save(); + r2(U . "order/view/" . $trx['id'], 's', Lang::T("Transaction successful.")); + } elseif ($result['status'] === 'Failed') { + $trx->pg_paid_response = json_encode($result); + $trx->status = 3; + $trx->save(); + r2(U . "order/view/" . $trx['id'], 'd', Lang::T("Transaction failed.")); + } elseif ($trx['status'] == 2) { + r2(U . "order/view/" . $trx['id'], 'd', Lang::T("Transaction has been paid.")); + } else { + Message::sendTelegram("ioTec get_status: unknown result\n\n" . json_encode($result, JSON_PRETTY_PRINT)); + r2(U . "order/view/" . $trx['id'], 'w', Lang::T("Transaction still pending.")); + } +} + +function iotec_get_server($type = 'api') +{ + global $_app_stage; + if ($_app_stage == 'Live' && $type == 'auth') { + return 'https://id.iotec.io/'; + } elseif ($_app_stage == 'Live' && $type == 'api') { + return 'https://pay.iotec.io/'; + } else { + return $type == 'auth' ? 'https://id.iotec.io/' : 'https://pay.iotec.io/'; + } +} \ No newline at end of file diff --git a/system/paymentgateway/iotec.json b/system/paymentgateway/iotec.json new file mode 100644 index 0000000..21a9af4 --- /dev/null +++ b/system/paymentgateway/iotec.json @@ -0,0 +1,5 @@ +{ + "sandbox": { + "name": "iotecpay-sandbox" + } +} \ No newline at end of file diff --git a/system/paymentgateway/iotec.php b/system/paymentgateway/iotec.php new file mode 100644 index 0000000..91a46c1 --- /dev/null +++ b/system/paymentgateway/iotec.php @@ -0,0 +1,163 @@ + 'error', 'message' => 'ioTec Pay not configured']); + exit; + } +} + +function iotec_show_config() +{ + global $ui; + $ui->assign('_title', 'ioTec Pay - Payment Gateway'); + $ui->assign('env', [ + ['id' => 'Sandbox', 'name' => 'Sandbox (Testing)'], + ['id' => 'Live', 'name' => 'Live (Production)'] + ]); + $ui->display('iotec.tpl'); +} + +function iotec_save_config() +{ + global $admin, $_L; + $iotec_client_id = _post('iotec_client_id'); + $iotec_client_secret = _post('iotec_client_secret'); + $iotec_wallet_id = _post('iotec_wallet_id'); + $iotec_env = _post('iotec_env'); + + $settings = [ + 'iotec_client_id' => $iotec_client_id, + 'iotec_client_secret' => $iotec_client_secret, + 'iotec_wallet_id' => $iotec_wallet_id, + 'iotec_env' => $iotec_env + ]; + + foreach ($settings as $key => $value) { + $d = ORM::for_table('tbl_appconfig')->where('setting', $key)->find_one(); + if ($d) { + $d->value = $value; + $d->save(); + } else { + $d = ORM::for_table('tbl_appconfig')->create(); + $d->setting = $key; + $d->value = $value; + $d->save(); + } + } + + _log('[' . $admin['username'] . ']: ioTec Pay ' . $_L['Settings_Saved_Successfully'], 'Admin', $admin['id']); + header('Content-Type: application/json'); + echo json_encode(['status' => 'success', 'message' => $_L['Settings_Saved_Successfully']]); + exit; +} + +function iotec_create_transaction_json($trx, $user) +{ + global $config; + header('Content-Type: application/json'); + + // Validate required inputs + if (empty($trx['price']) || empty($user['phonenumber']) || empty($user['username']) || empty($trx['plan_name'])) { + http_response_code(400); + echo json_encode([ + 'status' => 'error', + 'message' => 'Missing required input: price, phonenumber, username, or plan_name' + ]); + exit; + } + + $externalId = uniqid('bill_'); + + $tokenResponse = json_decode(Http::postData(iotec_get_server('auth') . 'connect/token', [ + 'client_id' => $config['iotec_client_id'], + 'client_secret' => $config['iotec_client_secret'], + 'grant_type' => 'client_credentials' + ], [ + 'Content-Type: application/x-www-form-urlencoded' + ]), true); + + if (empty($tokenResponse['access_token'])) { + http_response_code(500); + echo json_encode([ + 'status' => 'error', + 'message' => 'Failed to authenticate with ioTec', + 'response' => $tokenResponse + ]); + exit; + } + + $json = [ + 'category' => 'MobileMoney', + 'currency' => 'ITX', + 'walletId' => $config['iotec_wallet_id'], + 'externalId' => $externalId, + 'payer' => $user['phonenumber'], + 'amount' => $trx['price'], + 'payerNote' => 'Payment for ' . $trx['plan_name'], + 'payeeNote' => 'Hotspot billing', + 'transactionChargesCategory' => 'ChargeCustomer' + ]; + + $result = json_decode(Http::postJsonData(iotec_get_server('api') . 'api/collections/collect', $json, [ + 'Authorization: Bearer ' . $tokenResponse['access_token'], + 'Content-Type: application/json' + ]), true); + + if (empty($result['id'])) { + http_response_code(502); + echo json_encode([ + 'status' => 'error', + 'message' => 'Failed to create transaction', + 'response' => $result + ]); + exit; + } + + $d = ORM::for_table('tbl_payment_gateway') + ->where('username', $user['username']) + ->where('status', 1) + ->find_one(); + + if (!$d) { + http_response_code(404); + echo json_encode([ + 'status' => 'error', + 'message' => 'Active payment gateway record not found for user' + ]); + exit; + } + + $d->gateway_trx_id = $result['id']; + $d->pg_url_payment = 'N/A'; + $d->pg_request = json_encode($result); + $d->expired_date = date('Y-m-d H:i:s', strtotime("+6 HOUR")); + $d->save(); + + echo json_encode([ + 'status' => 'success', + 'message' => 'Transaction created. Authorize on phone.', + 'transaction_id' => $result['id'], + 'external_id' => $externalId + ]); + exit; +} + +// Other functions (iotec_payment_notification, iotec_get_status, iotec_get_server, etc.) remain unchanged. diff --git a/system/paymentgateway/iotecold.json b/system/paymentgateway/iotecold.json new file mode 100644 index 0000000..d3b4462 --- /dev/null +++ b/system/paymentgateway/iotecold.json @@ -0,0 +1,6 @@ +[ + { + "id": "MobileMoney", + "name": "Mobile Money" + } +] \ No newline at end of file diff --git a/system/paymentgateway/mpesa.php b/system/paymentgateway/mpesa.php new file mode 100644 index 0000000..43b7af7 --- /dev/null +++ b/system/paymentgateway/mpesa.php @@ -0,0 +1,363 @@ +assign('env', json_decode(file_get_contents('system/paymentgateway/mpesa_env.json'), true)); + $ui->assign('_title', 'M-Pesa - Payment Gateway - ' . $config['CompanyName']); + $ui->display('mpesa.tpl'); +} + +function mpesa_save_config() +{ + global $admin, $_L; + $mpesa_consumer_key = _post('mpesa_consumer_key'); + $mpesa_consumer_secret = _post('mpesa_consumer_secret'); + $mpesa_business_code = _post('mpesa_business_code'); + $mpesa_pass_key = _post('mpesa_pass_key'); + $mpesa_env = _post('mpesa_env'); + $d = ORM::for_table('tbl_appconfig')->where('setting', 'mpesa_consumer_key')->find_one(); + if ($d) { + $d->value = $mpesa_consumer_key; + $d->save(); + } else { + $d = ORM::for_table('tbl_appconfig')->create(); + $d->setting = 'mpesa_consumer_key'; + $d->value = $mpesa_consumer_key; + $d->save(); + } + $d = ORM::for_table('tbl_appconfig')->where('setting', 'mpesa_consumer_secret')->find_one(); + if ($d) { + $d->value = $mpesa_consumer_secret; + $d->save(); + } else { + $d = ORM::for_table('tbl_appconfig')->create(); + $d->setting = 'mpesa_consumer_secret'; + $d->value = $mpesa_consumer_secret; + $d->save(); + } + + $d = ORM::for_table('tbl_appconfig')->where('setting', 'mpesa_business_code')->find_one(); + if ($d) { + $d->value = $mpesa_business_code; + $d->save(); + } else { + $d = ORM::for_table('tbl_appconfig')->create(); + $d->setting = 'mpesa_business_code'; + $d->value = $mpesa_business_code; + $d->save(); + } + $d = ORM::for_table('tbl_appconfig')->where('setting', 'mpesa_pass_key')->find_one(); + if ($d) { + $d->value = $mpesa_pass_key; + $d->save(); + } else { + $d = ORM::for_table('tbl_appconfig')->create(); + $d->setting = 'mpesa_pass_key'; + $d->value = $mpesa_pass_key; + $d->save(); + } + $d = ORM::for_table('tbl_appconfig')->where('setting', 'mpesa_env')->find_one(); + if ($d) { + $d->value = $mpesa_env; + $d->save(); + } else { + $d = ORM::for_table('tbl_appconfig')->create(); + $d->setting = 'mpesa_env'; + $d->value = $mpesa_env; + $d->save(); + } + + _log('[' . $admin['username'] . ']: M-Pesa ' . $_L['Settings_Saved_Successfully'] . json_encode($_POST['mpesa_channel']), 'Admin', $admin['id']); + + r2(U . 'paymentgateway/mpesa', 's', $_L['Settings_Saved_Successfully']); +} + + +function mpesa_create_transaction($trx, $user) +{ + global $config, $routes; + + //select evironment + $environment = $config['mpesa_env']; + $consumer_key = $config['mpesa_consumer_key']; + $consumer_secret = $config['mpesa_consumer_secret']; + $Business_Code = $config['mpesa_business_code']; + $Passkey = $config['mpesa_pass_key']; + $Type_of_Transaction = 'CustomerPayBillOnline'; + $phone_number = $user['phonenumber']; + $total_amount = $trx['price']; + //lets assume this is our callBack url + //$CallBackURL = 'http://alwayson.com.ng/phpnuxbill/index.php?_route=callback/mpesa'; + $CallBackURL = U . 'callback/mpesa'; + $Time_Stamp = date("Ymdhis"); + //password required by api + $password = base64_encode($Business_Code . $Passkey . $Time_Stamp); + //depend on which environment selected + if ($environment == "live") { + $OnlinePayment = 'https://api.safaricom.co.ke/mpesa/stkpush/v1/processrequest'; + $Token_URL = 'https://api.safaricom.co.ke/oauth/v1/generate?grant_type=client_credentials'; + } elseif ($environment == "sandbox") { + $OnlinePayment = 'https://sandbox.safaricom.co.ke/mpesa/stkpush/v1/processrequest'; + $Token_URL = 'https://sandbox.safaricom.co.ke/oauth/v1/generate?grant_type=client_credentials'; + } else { + return json_encode(["Message" => "invalid application status"]); + }; + //lets Create access_token as per required + $curl_Tranfer = curl_init(); + curl_setopt($curl_Tranfer, CURLOPT_URL, $Token_URL); + $credentials = base64_encode($consumer_key . ':' . $consumer_secret); + curl_setopt($curl_Tranfer, CURLOPT_HTTPHEADER, array('Authorization: Basic ' . $credentials)); + curl_setopt($curl_Tranfer, CURLOPT_HEADER, false); + curl_setopt($curl_Tranfer, CURLOPT_RETURNTRANSFER, 1); + curl_setopt($curl_Tranfer, CURLOPT_SSL_VERIFYPEER, false); + $curl_Tranfer_response = curl_exec($curl_Tranfer); + $token = json_decode($curl_Tranfer_response)->access_token; + // die(json_encode($curl_Tranfer2_post_data,JSON_PRETTY_PRINT)); + $curl_Tranfer2 = curl_init(); + curl_setopt($curl_Tranfer2, CURLOPT_URL, $OnlinePayment); + curl_setopt($curl_Tranfer2, CURLOPT_HTTPHEADER, array('Content-Type:application/json', 'Authorization:Bearer ' . $token)); + //lets initiate a Transaction + $curl_Tranfer2_post_data = [ + 'BusinessShortCode' => $Business_Code, + 'Password' => $password, + 'Timestamp' => $Time_Stamp, + 'TransactionType' => $Type_of_Transaction, + 'Amount' => $trx['price'], + 'PartyA' => $phone_number, + 'PartyB' => $Business_Code, + 'PhoneNumber' => $phone_number, + 'CallBackURL' => $CallBackURL, + 'AccountReference' => $phone_number, + 'TransactionDesc' => $trx['plan_name'] + //'Trxid' => $trx['id'], + //'AmountToPay' => $trx['price'], + ]; + //lest check the data that we want to send for error + //die(json_encode($curl_Tranfer2_post_data,JSON_PRETTY_PRINT)); + $data2_string = json_encode($curl_Tranfer2_post_data); + curl_setopt($curl_Tranfer2, CURLOPT_RETURNTRANSFER, true); + curl_setopt($curl_Tranfer2, CURLOPT_POST, true); + curl_setopt($curl_Tranfer2, CURLOPT_POSTFIELDS, $data2_string); + curl_setopt($curl_Tranfer2, CURLOPT_HEADER, false); + curl_setopt($curl_Tranfer2, CURLOPT_SSL_VERIFYPEER, 0); + curl_setopt($curl_Tranfer2, CURLOPT_SSL_VERIFYHOST, 0); + $curl_Tranfer2_response = json_decode(curl_exec($curl_Tranfer2)); + $status = $curl_Tranfer2_response->ResponseCode; + //die(json_encode($curl_Tranfer2_response,JSON_PRETTY_PRINT)); + //die(json_encode($status,JSON_PRETTY_PRINT)); + + /** + * { + * "MerchantRequestID": "26309-129914760-1", + * "CheckoutRequestID": "ws_CO_22092023134957453718167262", + * "ResponseCode": "0", "ResponseDescription": "Success. Request accepted for processing", + * "CustomerMessage": "Success. Request accepted for processing" + * } + * + * + **/ + if ($status == 1) { + sendTelegram("M-Pesa payment failed\n\n" . json_encode($curl_Tranfer2_response, JSON_PRETTY_PRINT)); + r2(U . 'order/package', 'e', Lang::T("Failed to create transaction.")); + } + $d = ORM::for_table('tbl_payment_gateway') + ->where('username', $user['username']) + ->where('status', 1) + ->find_one(); + $d->gateway_trx_id = $curl_Tranfer2_response->CheckoutRequestID; + //lets use this table "pg_url_payment" to save Timestamp because we will need it later to verify transaction + $d->pg_url_payment = $Time_Stamp; + $d->pg_request = $user['id']; + $d->expired_date = date('Y-m-d H:i:s', strtotime("+5 minutes")); + $d->save(); + + r2(U . "order/view/" . $d['id'], 's', Lang::T("Create Transaction Success, Please check your phone to process payment")); +} + + +function mpesa_payment_notification() +{ + + global $config; + //responce from mpesa server after payment is initiated and processed + $callbackJSONData = file_get_contents('php://input'); + $callbackData = json_decode($callbackJSONData); + $resultCode = $callbackData->Body->stkCallback->ResultCode; + $resultDesc = $callbackData->Body->stkCallback->ResultDesc; + $merchantRequestID = $callbackData->Body->stkCallback->MerchantRequestID; + $checkoutRequestID = $callbackData->Body->stkCallback->CheckoutRequestID; + $amount = $callbackData->stkCallback->Body->CallbackMetadata->Item[0]->Value; + $mpesaReceiptNumber = $callbackData->Body->stkCallback->CallbackMetadata->Item[1]->Value; + $balance = $callbackData->stkCallback->Body->CallbackMetadata->Item[2]->Value; + $b2CUtilityAccountAvailableFunds = $callbackData->Body->stkCallback->CallbackMetadata->Item[3]->Value; + $transactionDate = $callbackData->Body->stkCallback->CallbackMetadata->Item[4]->Value; + $phoneNumber = $callbackData->Body->stkCallback->CallbackMetadata->Item[5]->Value; + //$trxid = $callbackData->Body->stkCallback->CallbackMetadata->Item[6]->Value; + //$amountToPay=$callbackData->Body->stkCallback->CallbackMetadata->Item[7]->Value; + $trx = ORM::for_table('tbl_payment_gateway') + ->where('gateway_trx_id', $checkoutRequestID) + ->find_one(); + if (!$trx) { + return; + } + + $user = ORM::for_table('tbl_customers') + ->where('username', $trx['username']) + ->find_one(); + if (!$trx) { + return; + } + //lets check the status of the Payment sent back from mpesa + if ($resultDesc == "Confirmation Service not accepted" || $resultCode == 1) { + $trx->status = 3; + $trx->save(); + exit(); + } + //if Payment is confirmed and Successfull + //lets log the responce from mpesa for audit or any error + //lets save some value to database + + elseif ($resultDesc == "The service request is processed successfully." && $resultCode == 0 && $trx['status'] != 2) { + if (!Package::rechargeUser($user['id'], $trx['routers'], $trx['plan_id'], $trx['gateway'], 'mpesa')) { + _log('[' . $resultDesc . ']: M-Pesa ' . "Payment Successfull,But Failed to activate your Package" . json_encode($callbackData)); + } + _log('[' . $resultDesc . ']: M-Pesa ' . "Payment Successfull" . json_encode($callbackData)); + + $trx->pg_paid_response = json_encode($callbackData); + $trx->payment_method = 'M-Pesa'; + $trx->payment_channel = 'M-Pesa StkPush'; + $trx->paid_date = date('Y-m-d H:i:s'); + $trx->status = 2; + $trx->save(); + } else { + $trx->status = 1; + $trx->save(); + exit(); + } +} + + +function mpesa_get_status($trx, $user) +{ + global $config, $routes; + function mpesa_get_status($trx, $user) +{ + global $config, $routes; + + if ($trx->status == 2){ + r2(U . "order/view/" . $trx['id'], 's', Lang::T("Transaction has been completed.")); + die(); + + }elseif ($trx->status == 1){ + + + $environment = $config['mpesa_env']; + $consumer_key = $config['mpesa_consumer_key']; + $consumer_secret = $config['mpesa_consumer_secret']; + $Business_Code = $config['mpesa_business_code']; + $Passkey = $config['mpesa_pass_key']; + //Timestamp that we save earlier in pg_url_payment database + $Time_Stamp = $trx['pg_url_payment']; + $password = base64_encode($Business_Code . $Passkey . $Time_Stamp); + if ($environment == "live") { + $OnlinePayment = 'https://api.safaricom.co.ke/mpesa/stkpushquery/v1/query'; + $Token_URL = 'https://api.safaricom.co.ke/oauth/v1/generate?grant_type=client_credentials'; + } elseif ($environment == "sandbox") { + $OnlinePayment = 'https://sandbox.safaricom.co.ke/mpesa/stkpushquery/v1/query'; + $Token_URL = 'https://sandbox.safaricom.co.ke/oauth/v1/generate?grant_type=client_credentials'; + } else { + return json_encode(["Message" => "invalid application status"]); + }; + $curl_Tranfer = curl_init(); + curl_setopt($curl_Tranfer, CURLOPT_URL, $Token_URL); + $credentials = base64_encode($consumer_key . ':' . $consumer_secret); + curl_setopt($curl_Tranfer, CURLOPT_HTTPHEADER, array('Authorization: Basic ' . $credentials)); + curl_setopt($curl_Tranfer, CURLOPT_HEADER, false); + curl_setopt($curl_Tranfer, CURLOPT_RETURNTRANSFER, 1); + curl_setopt($curl_Tranfer, CURLOPT_SSL_VERIFYPEER, false); + $curl_Tranfer_response = curl_exec($curl_Tranfer); + $token = json_decode($curl_Tranfer_response)->access_token; + // die(json_encode($curl_Tranfer2_post_data,JSON_PRETTY_PRINT)); + $curl_Tranfer2 = curl_init(); + curl_setopt($curl_Tranfer2, CURLOPT_URL, $OnlinePayment); + curl_setopt($curl_Tranfer2, CURLOPT_HTTPHEADER, array('Content-Type:application/json', 'Authorization:Bearer ' . $token)); + //lest verify the transaction by sending data to mpesa transaction query portal from nuxbil + $curl_Tranfer2_post_data = [ + 'BusinessShortCode' => $Business_Code, + 'Password' => $password, + 'Timestamp' => $Time_Stamp, + 'CheckoutRequestID' => $trx['gateway_trx_id'] + ]; + //die(json_encode($curl_Tranfer2_post_data,JSON_PRETTY_PRINT)); + $data2_string = json_encode($curl_Tranfer2_post_data); + curl_setopt($curl_Tranfer2, CURLOPT_RETURNTRANSFER, true); + curl_setopt($curl_Tranfer2, CURLOPT_POST, true); + curl_setopt($curl_Tranfer2, CURLOPT_POSTFIELDS, $data2_string); + curl_setopt($curl_Tranfer2, CURLOPT_HEADER, false); + curl_setopt($curl_Tranfer2, CURLOPT_SSL_VERIFYPEER, 0); + curl_setopt($curl_Tranfer2, CURLOPT_SSL_VERIFYHOST, 0); + $curl_Tranfer2_response = json_decode(curl_exec($curl_Tranfer2)); + + //server responce will be + /** + * { + * "ResponseCode":"0", + * "ResponseDescription": "The service request has been accepted successfully", + * "MerchantRequestID":"22205-34066-1", + * "CheckoutRequestID": "ws_CO_13012021093521236557", + * "ResultCode":"0", + * "ResultDesc":"The service request is processed successfully.", + * } + * + * + **/ + + + $callbackJSONData = file_get_contents('php://input'); + $callbackData = json_decode($callbackJSONData); + $responseCode = $callbackData->ResponseCode; + $responseDescription = $callbackData->ResponseDescription; + $merchantRequestID = $callbackData->MerchantRequestID; + $checkoutRequestID = $callbackData->CheckoutRequestID; + $resultCode = $callbackData->ResultCode; + $resultDesc = $callbackData->ResultDesc; + //if responce is Failed + if ($responseDescription === "The service request has failed" || $resultDesc === "Request canceled by the user" || $responseCode === 1) { + r2(U . "order/view/" . $trx['id'], 'w', Lang::T("Transaction still unpaid.")); + //if responce is Successfull, activate the plan or balance + } elseif (($responseDescription === "The service request has been accepted successfully." || $resultDesc == "The service request is processed successfully" || $responseCode === 0) && $trx['status'] != 2) { + if (!Package::rechargeUser($user['id'], $trx['routers'], $trx['plan_id'], $trx['gateway'], 'M-Pesa')) { + r2(U . "order/view/" . $trx['id'], 'd', Lang::T("Failed to activate your Package, try again later.")); + } + _log('[' . $checkoutRequestID . ']: M-Pesa ' . "Payment Successfull" . json_encode($callbackData)); + $trx->pg_paid_response = json_encode($callbackData); + $trx->payment_method = 'M-Pesa'; + $trx->payment_channel = 'M-Pesa StkPush'; + $trx->paid_date = date('Y-m-d H:i:s'); + $trx->status = 2; + $trx->save(); + r2(U . "order/view/" . $trx['id'], 's', Lang::T("Transaction has been paid.")); + } else if ($trx['status'] == 2) { + r2(U . "order/view/" . $trx['id'], 'd', Lang::T("Transaction has been paid..")); + } +} +} +} diff --git a/system/paymentgateway/mpesa_env.json b/system/paymentgateway/mpesa_env.json new file mode 100644 index 0000000..220a46f --- /dev/null +++ b/system/paymentgateway/mpesa_env.json @@ -0,0 +1,11 @@ +[ + + { + "id": "sandbox", + "name": "SandBox or Testing" + }, + { + "id": "live", + "name": "Live or Production" + } +] diff --git a/system/paymentgateway/paypal.php b/system/paymentgateway/paypal.php new file mode 100644 index 0000000..4ab66af --- /dev/null +++ b/system/paymentgateway/paypal.php @@ -0,0 +1,210 @@ + + * + **/ + + +function paypal_validate_config() +{ + global $config; + if (empty($config['paypal_client_id']) || empty($config['paypal_secret_key'])) { + sendTelegram("PayPal payment gateway not configured"); + r2(U . 'order/package', 'w', "Admin has not yet setup Paypal payment gateway, please tell admin"); + } +} + +function paypal_show_config() +{ + global $ui; + $ui->assign('_title', 'Paypal - Payment Gateway'); + $ui->assign('currency', json_decode(file_get_contents('system/paymentgateway/paypal_currency.json'), true)); + $ui->display('paypal.tpl'); +} + + +function paypal_save_config() +{ + global $admin, $_L; + $paypal_client_id = _post('paypal_client_id'); + $paypal_secret_key = _post('paypal_secret_key'); + $paypal_currency = _post('paypal_currency'); + $d = ORM::for_table('tbl_appconfig')->where('setting', 'paypal_secret_key')->find_one(); + if ($d) { + $d->value = $paypal_secret_key; + $d->save(); + } else { + $d = ORM::for_table('tbl_appconfig')->create(); + $d->setting = 'paypal_secret_key'; + $d->value = $paypal_secret_key; + $d->save(); + } + $d = ORM::for_table('tbl_appconfig')->where('setting', 'paypal_client_id')->find_one(); + if ($d) { + $d->value = $paypal_client_id; + $d->save(); + } else { + $d = ORM::for_table('tbl_appconfig')->create(); + $d->setting = 'paypal_client_id'; + $d->value = $paypal_client_id; + $d->save(); + } + $d = ORM::for_table('tbl_appconfig')->where('setting', 'paypal_currency')->find_one(); + if ($d) { + $d->value = $paypal_currency; + $d->save(); + } else { + $d = ORM::for_table('tbl_appconfig')->create(); + $d->setting = 'paypal_currency'; + $d->value = $paypal_currency; + $d->save(); + } + _log('[' . $admin['username'] . ']: Paypal ' . Lang::T('Settings_Saved_Successfully'), 'Admin', $admin['id']); + + r2(U . 'paymentgateway/paypal', 's', Lang::T('Settings_Saved_Successfully')); +} + +function paypal_create_transaction($trx, $user) +{ + global $config; + $json = [ + 'intent' => 'CAPTURE', + 'purchase_units' => [ + [ + 'amount' => [ + 'currency_code' => $config['paypal_currency'], + 'value' => strval($trx['price']) + ] + ] + ], + "application_context" => [ + "return_url" => U . "order/view/" . $trx['id'] . '/check', + "cancel_url" => U . "order/view/" . $trx['id'], + ] + ]; + + $result = json_decode( + Http::postJsonData( + paypal_get_server() . 'checkout/orders', + $json, + [ + 'Prefer: return=minimal', + 'PayPal-Request-Id: paypal_' . $trx['id'], + 'Authorization: Bearer ' . paypalGetAccessToken() + ] + ), + true + ); + if (!$result['id']) { + sendTelegram("paypal_create_transaction FAILED: \n\n" . json_encode($result, JSON_PRETTY_PRINT)); + r2(U . 'order/package', 'e', "Failed to create Paypal transaction."); + } + $urlPayment = ""; + foreach ($result['links'] as $link) { + if ($link['rel'] == 'approve') { + $urlPayment = $link['href']; + break; + } + } + $d = ORM::for_table('tbl_payment_gateway') + ->where('username', $user['username']) + ->where('status', 1) + ->find_one(); + $d->gateway_trx_id = $result['id']; + $d->pg_url_payment = $urlPayment; + $d->pg_request = json_encode($result); + $d->expired_date = date('Y-m-d H:i:s', strtotime("+ 6 HOUR")); + $d->save(); + header('Location: ' . $urlPayment); + exit(); +} + +/* +*/ + +function paypal_payment_notification() +{ + // Not yet implemented + die('OK'); +} + +function paypal_get_status($trx, $user) +{ + $capture = []; + if (empty($trx->pg_paid_response)) { + $capture = paypal_capture_transaction($trx['gateway_trx_id']); + } else { + $capture = json_decode($trx->pg_paid_response, true)['paypal_capture']; + if (empty($capture)) { + $capture = paypal_capture_transaction($trx['gateway_trx_id']); + } + } + $result = json_decode(Http::getData(paypal_get_server() . 'checkout/orders/' . $trx['gateway_trx_id'], ['Authorization: Bearer ' . paypalGetAccessToken()]), true); + if (in_array($result['status'], ['APPROVED', 'COMPLETED']) && $trx['status'] != 2) { + if ($capture['status'] == 'COMPLETED' || ($capture['name'] == 'UNPROCESSABLE_ENTITY' && $capture['details'][0]['issue'] == 'ORDER_ALREADY_CAPTURED')) { + if (!Package::rechargeUser($user['id'], $trx['routers'], $trx['plan_id'], $trx['gateway'], 'Paypal')) { + r2(U . "order/view/" . $trx['id'], 'd', "Failed to activate your Package, try again later."); + } + $result['paypal_capture'] = json_encode($capture); + $trx->pg_paid_response = json_encode($result); + $trx->payment_method = 'PAYPAL'; + $trx->payment_channel = 'paypal'; + $trx->paid_date = date('Y-m-d H:i:s', strtotime($result['updated'])); + $trx->status = 2; + $trx->save(); + r2(U . "order/view/" . $trx['id'], 's', "Transaction has been paid."); + } else { + r2(U . "order/view/" . $trx['id'], 'e', "Transaction Success, but not yet captured."); + } + } else if ($result['status'] == 'VOIDED') { + $trx->pg_paid_response = json_encode($result); + $trx->status = 3; + $trx->save(); + r2(U . "order/view/" . $trx['id'], 'd', "Transaction expired."); + } else { + sendTelegram("xendit_get_status: unknown result\n\n" . json_encode($result, JSON_PRETTY_PRINT)); + r2(U . "order/view/" . $trx['id'], 'w', "Transaction status :" . $result['status']); + } +} + +function paypal_capture_transaction($trx_id) +{ + return json_decode( + Http::postJsonData( + paypal_get_server() . 'checkout/orders/' . $trx_id . '/capture', + [], + [ + 'PayPal-Partner-Attribution-Id: <BN-Code>', + 'Authorization: Bearer ' . paypalGetAccessToken() + ] + ), + true + ); +} + +function paypalGetAccessToken() +{ + global $config; + $result = Http::postData(str_replace('v2', 'v1', paypal_get_server()) . 'oauth2/token', [ + "grant_type" => "client_credentials" + ], [], $config['paypal_client_id'] . ":" . $config['paypal_secret_key']); + $json = json_decode($result, true); + return $json['access_token']; +} + + +function paypal_get_server() +{ + global $_app_stage; + if ($_app_stage == 'Live') { + return 'https://api-m.paypal.com/v2/'; + } else { + return 'https://api-m.sandbox.paypal.com/v2/'; + } +} diff --git a/system/paymentgateway/paypal_currency.json b/system/paymentgateway/paypal_currency.json new file mode 100644 index 0000000..0f9881c --- /dev/null +++ b/system/paymentgateway/paypal_currency.json @@ -0,0 +1,103 @@ +[ + + { + "id": "USD", + "name": "United States dollar" + }, + { + "id": "AUD", + "name": "Australian dollar" + }, + { + "id": "BRL", + "name": "Brazilian real **" + }, + { + "id": "CAD", + "name": "Canadian dollar" + }, + { + "id": "CNY", + "name": "Chinese Renmenbi ***" + }, + { + "id": "CZK", + "name": "Czech koruna" + }, + { + "id": "DKK", + "name": "Danish krone" + }, + { + "id": "EUR", + "name": "Euro" + }, + { + "id": "HKD", + "name": "Hong Kong dollar" + }, + { + "id": "HUF", + "name": "Hungarian forint *" + }, + { + "id": "ILS", + "name": "Israeli new shekel" + }, + { + "id": "JPY", + "name": "Japanese yen *" + }, + { + "id": "MYR", + "name": "Malaysian ringgit ***" + }, + { + "id": "MXN", + "name": "Mexican peso" + }, + { + "id": "TWD", + "name": "New Taiwan dollar *" + }, + { + "id": "NZD", + "name": "New Zealand dollar" + }, + { + "id": "NOK", + "name": "Norwegian krone" + }, + { + "id": "PHP", + "name": "Philippine peso" + }, + { + "id": "PLN", + "name": "Polish złoty" + }, + { + "id": "GBP", + "name": "Pound sterling" + }, + { + "id": "RUB", + "name": "Russian ruble" + }, + { + "id": "SGD", + "name": "Singapore dollar" + }, + { + "id": "SEK", + "name": "Swedish krona" + }, + { + "id": "CHF", + "name": "Swiss franc" + }, + { + "id": "THB", + "name": "Thai baht" + } +] \ No newline at end of file diff --git a/system/paymentgateway/paystack.php b/system/paymentgateway/paystack.php new file mode 100644 index 0000000..6a591c2 --- /dev/null +++ b/system/paymentgateway/paystack.php @@ -0,0 +1,184 @@ +assign('_title', 'Paystack - Payment Gateway'); + $ui->assign('cur', json_decode(file_get_contents('system/paymentgateway/paystack_currency.json'), true)); + $ui->assign('channel', json_decode(file_get_contents('system/paymentgateway/paystack_channel.json'), true)); + $ui->display('paystack.tpl'); + } + + + function paystack_save_config() + { + global $admin, $_L; + $paystack_secret_key = _post('paystack_secret_key'); + $paystack_currency = _post('paystack_currency'); + $d = ORM::for_table('tbl_appconfig')->where('setting', 'paystack_secret_key')->find_one(); + if ($d) { + $d->value = $paystack_secret_key; + $d->save(); + } else { + $d = ORM::for_table('tbl_appconfig')->create(); + $d->setting = 'paystack_secret_key'; + $d->value = $paystack_secret_key; + $d->save(); + } + $d = ORM::for_table('tbl_appconfig')->where('setting', 'paystack_currency')->find_one(); + if ($d) { + $d->value = $paystack_currency; + $d->save(); + } else { + $d = ORM::for_table('tbl_appconfig')->create(); + $d->setting = 'paystack_currency'; + $d->value = $paystack_currency; + $d->save(); + } + $d = ORM::for_table('tbl_appconfig')->where('setting', 'paystack_channel')->find_one(); + if ($d) { + $d->value = implode(',', $_POST['paystack_channel']); + $d->save(); + } else { + $d = ORM::for_table('tbl_appconfig')->create(); + $d->setting = 'paystack_channel'; + $d->value = implode(',', $_POST['paystack_channel']); + $d->save(); + } + _log('[' . $admin['username'] . ']: paystack ' . $_L['Settings_Saved_Successfully'], 'Admin', $admin['id']); + + r2(U . 'paymentgateway/paystack', 's', $_L['Settings_Saved_Successfully']); + } + +function paystack_create_transaction($trx, $user) +{ + global $config; + $txref = uniqid('trx'); + $total = $trx['price']*100; + $json = [ + 'reference' => $txref, + 'amount' => $total, + 'currency' => $config['paystack_currency'], + 'channels' => explode(',', $config['paystack_channel']), + 'email' => (empty($user['email'])) ? $user['username'] . '@' . $_SERVER['HTTP_HOST'] : $user['email'], + 'customer' => [ + 'firstname' => $user['fullname'], + 'phone' => $user['phonenumber'] + ], + 'meta' => [ + 'price' => $trx['price'] + ], + + 'customizations' => [ + 'title' => $trx['plan_name'], + 'description' => $trx['plan_name'] + ], + + 'callback_url' => U . 'order/view/' . $trx['id'] . '/check' + ]; +// die(json_encode($json,JSON_PRETTY_PRINT)); + + $result = json_decode(Http::postJsonData(paystack_get_server() . 'initialize', $json,[ + 'Authorization: Bearer ' . $config['paystack_secret_key'], + 'Cache-Control: no-cahe' + ], + ), +true); + +//die(json_encode($result,JSON_PRETTY_PRINT)); + +if ($result['status'] == false) { + Message::sendTelegram("Paystack payment failed\n\n" . json_encode($result, JSON_PRETTY_PRINT)); + r2(U . 'order/package', 'e', Lang::T("Failed to create transaction.\n".$result['message'])); + } + $d = ORM::for_table('tbl_payment_gateway') + ->where('username', $user['username']) + ->where('status', 1) + ->find_one(); + $d->gateway_trx_id = $result['data']['reference']; + $d->pg_url_payment = $result['data']['authorization_url']; + $d->pg_request = json_encode($result); + $d->expired_date = date('Y-m-d H:i:s', strtotime("+ 6 HOUR")); + $d->save(); + + header('Location: ' . $result['data']['authorization_url']); + exit(); + + //r2(U . "order/view/" . $d['id'], 's', Lang::T("Create Transaction Success")); + + +} + +function paystack_payment_notification() +{ + //to be implemented + } + + function paystack_get_status($trx, $user) + { + global $config; + $result = json_decode(Http::getData(paystack_get_server() . 'verify/' . $trx['gateway_trx_id'], [ + 'Authorization: Bearer ' . $config['paystack_secret_key'], + 'Cache-Control: no-cahe' + ]), true); + $amountPaid = $result['data']['amount']; + $amountToPay = $result['data']['requested_amount']; + if ($result['status'] == true && $result['data']['status'] === 'abandoned' || $result['data']['status'] ==='failed' || $amountPaid < $amountToPay ){ + // die(json_encode($result,JSON_PRETTY_PRINT)); + r2(U . "order/view/" . $trx['id'], 'w', Lang::T("Transaction still unpaid.")); + }else if (in_array($result['status'] == true && $result['data']['status'], ['success']) && $trx['status'] != 2) { + if (!Package::rechargeUser($user['id'], $trx['routers'], $trx['plan_id'], $trx['gateway'], $result['data']['channel'])) { + r2(U . "order/view/" . $trx['id'], 'd', Lang::T("Failed to activate your Package, try again later.")); + } + $trx->pg_paid_response = json_encode($result); + $trx->payment_method = 'Paystack'; + $trx->payment_channel = $result['data']['channel']; + $trx->paid_date = date('Y-m-d H:i:s', strtotime( $result['data']['created_at'])); + $trx->status = 2; + $trx->save(); + + r2(U . "order/view/" . $trx['id'], 's', Lang::T("Transaction successful.")); +} else if ($result['status'] == 'EXPIRED') { + $trx->pg_paid_response = json_encode($result); + $trx->status = 3; + $trx->save(); + r2(U . "order/view/" . $trx['id'], 'd', Lang::T("Transaction expired.")); +} else if ($trx['status'] == 2) { + r2(U . "order/view/" . $trx['id'], 'd', Lang::T("Transaction has been paid..")); +}else{ + Message::sendTelegram("flutterwave_get_status: unknown result\n\n".json_encode($result, JSON_PRETTY_PRINT)); + r2(U . "order/view/" . $trx['id'], 'd', Lang::T("Unknown Command.")); +} + +} + + +function paystack_get_server() +{ + global $_app_stage; + if ($_app_stage == 'Live') { + return 'https://api.paystack.co/transaction/'; + } else { + return 'https://api.paystack.co/transaction/'; + } +} diff --git a/system/paymentgateway/paystack_channel.json b/system/paymentgateway/paystack_channel.json new file mode 100644 index 0000000..2ad9572 --- /dev/null +++ b/system/paymentgateway/paystack_channel.json @@ -0,0 +1,27 @@ +[ + + { + "id": "card", + "name": "Card Payment" + }, + { + "id": "ussd", + "name": "USSD" + }, + { + "id": "bank", + "name": "Bank Account" + }, + { + "id": "bank_transfer", + "name": "Bank Transfer" + }, + { + "id": "qr", + "name": "QR payment" + }, + { + "id": "mobile_money", + "name": "Mobile Money" + } +] diff --git a/system/paymentgateway/paystack_currency.json b/system/paymentgateway/paystack_currency.json new file mode 100644 index 0000000..a6a1935 --- /dev/null +++ b/system/paymentgateway/paystack_currency.json @@ -0,0 +1,25 @@ +[ + + { + "id": "NGN", + "name": "Nigerian Naira" + }, + { + "id": "GHC", + "name": "Ghana Cedis" + }, + { + "id": "KES", + "name": "Kenyan Shilling" + }, + { + "id": "ZAR", + "name": "South African Rand" + }, + { + "id": "USD", + "name": "United States Dollar" + } + + +] diff --git a/system/paymentgateway/ui/bankstkpush.tpl b/system/paymentgateway/ui/bankstkpush.tpl new file mode 100644 index 0000000..f914834 --- /dev/null +++ b/system/paymentgateway/ui/bankstkpush.tpl @@ -0,0 +1,42 @@ +{include file="sections/header.tpl"} +
+
+
+
+
+
Fill the details below to complete the bank stk Push
+
+
+ +
+ + +
+
+ +
+ +
+ +
+
+
After aplying these changes, the funds shall be going to the saved bank account, please make sure the bank name and account matches
+
+
+ +
+
+
+ +
+
+ +
+{include file="sections/footer.tpl"} diff --git a/system/paymentgateway/ui/flutterwave.tpl b/system/paymentgateway/ui/flutterwave.tpl new file mode 100644 index 0000000..ba9789c --- /dev/null +++ b/system/paymentgateway/ui/flutterwave.tpl @@ -0,0 +1,59 @@ +{include file="sections/header.tpl"} + +
+
+
+
+
Flutterwave Payment Gateway
+
+ + +
+ +
+ {foreach $channel as $payment_options} + + {/foreach} +
+
+
+ +
+ + Attention +
+
+ +
+
+ +
+
+
/ip hotspot walled-garden
+add dst-host=flutterwave.com
+add dst-host=*.flutterwave.com
+ Set Telegram Bot to get any error and + notification +
+
+ +
+
+
+ +{include file="sections/footer.tpl"} diff --git a/system/paymentgateway/ui/index.html b/system/paymentgateway/ui/index.html new file mode 100644 index 0000000..06d7405 Binary files /dev/null and b/system/paymentgateway/ui/index.html differ diff --git a/system/paymentgateway/ui/iotec.tpl b/system/paymentgateway/ui/iotec.tpl new file mode 100644 index 0000000..a41d9d8 --- /dev/null +++ b/system/paymentgateway/ui/iotec.tpl @@ -0,0 +1,63 @@ +{include file="sections/header.tpl"} + +
+
+
+
+
ioTec Pay
+
+ +
+ +
+ +
+
+
+ +
+ +
+
+
+ +
+ + Sandbox is for testing with test numbers. Switch to Live for production. +
+
+
+ +
+ +

Register this URL with ioTec Support for transaction notifications

+
+
+
+
+ +
+
+
Test Numbers for Sandbox:
+0111777770 to 0111777779 (Success)
+0111777780 to 0111777789 (Pending)
+0111777790 to 0111777799 (SentToVendor)
+0111777990 to 0111777999 (Failed)
+
+
+
+
+
+{include file="sections/footer.tpl"} \ No newline at end of file diff --git a/system/paymentgateway/ui/mpesa.tpl b/system/paymentgateway/ui/mpesa.tpl new file mode 100644 index 0000000..af00a84 --- /dev/null +++ b/system/paymentgateway/ui/mpesa.tpl @@ -0,0 +1,69 @@ +{include file="sections/header.tpl"} + +
+
+
+
+
M-Pesa
+
+
+ + +
+
+ +
+ +
+
+
+ +
+ +
+
+
+ +
+ +
+
+
+ +
+ + Sandbox is for testing purpose, please switch to Live in production. +
+
+ +
+ +
+ +

CallBack URL

+
+
+
+
+ +
+
+
/ip hotspot walled-garden
+                   add dst-host=safaricom.co.ke
+                   add dst-host=*.safaricom.co.ke
+
+
+ +
+
+
+{include file="sections/footer.tpl"} diff --git a/system/paymentgateway/ui/mpesatill.tpl b/system/paymentgateway/ui/mpesatill.tpl new file mode 100644 index 0000000..4b1c461 --- /dev/null +++ b/system/paymentgateway/ui/mpesatill.tpl @@ -0,0 +1,69 @@ +{include file="sections/header.tpl"} + +
+
+
+
+
M-Pesa
+
+
+ + +
+
+ +
+ +
+
+
+ +
+ +
+
+
+ +
+ +
+
+
+ +
+ +
+
+
+ +
+ + Sandbox is for testing purpose, please switch to Live in production. +
+
+ + +
+
+ +
+
+
/ip hotspot walled-garden
+                   add dst-host=safaricom.co.ke
+                   add dst-host=*.safaricom.co.ke
+
+
+ +
+
+
+{include file="sections/footer.tpl"} diff --git a/system/paymentgateway/ui/paypal.tpl b/system/paymentgateway/ui/paypal.tpl new file mode 100644 index 0000000..b4e3ace --- /dev/null +++ b/system/paymentgateway/ui/paypal.tpl @@ -0,0 +1,64 @@ +{include file="sections/header.tpl"} + +
+
+
+
+
PayPal Payment Gateway
+
+ + +
+ +
+ + * This currency does not support decimals. If you pass a decimal amount, an error occurs.
+ ** This currency is supported as a payment currency and a currency balance for in-country PayPal + accounts only. If the receiver of funds is not from Brazil, then PayPal converts funds into the + primary holding currency of the account with the applicable currency conversion rate. The currency + conversion rate includes PayPal's applicable spread or fee.
+ *** This currency is supported as a payment currency and a currency balance for in-country PayPal + accounts only.
+
+
+ +
+
+ +
+
+
/ip hotspot walled-garden
+add dst-host=paypal.com
+add dst-host=*.paypal.com
+ Set Telegram Bot to get any error and + notification +
+
+ +
+
+
+{include file="sections/footer.tpl"} \ No newline at end of file diff --git a/system/paymentgateway/ui/paystack.tpl b/system/paymentgateway/ui/paystack.tpl new file mode 100644 index 0000000..55e4115 --- /dev/null +++ b/system/paymentgateway/ui/paystack.tpl @@ -0,0 +1,59 @@ +{include file="sections/header.tpl"} + +
+
+
+
+
Paystack Payment Gateway
+
+
+ + +
+ +
+ +
+ {foreach $channel as $payment_options} + + {/foreach} +
+
+
+ +
+ + Attention +
+
+ +
+
+ +
+
+
/ip hotspot walled-garden
+add dst-host=paystack.com
+add dst-host=*.paystack.com
+ Set Telegram Bot to get any error and + notification +
+
+ +
+
+
+ +{include file="sections/footer.tpl"} diff --git a/system/plugin/.DS_Store b/system/plugin/.DS_Store new file mode 100644 index 0000000..6662656 Binary files /dev/null and b/system/plugin/.DS_Store differ diff --git a/system/plugin/.gitattributes b/system/plugin/.gitattributes new file mode 100644 index 0000000..dfe0770 --- /dev/null +++ b/system/plugin/.gitattributes @@ -0,0 +1,2 @@ +# Auto detect text files and perform LF normalization +* text=auto diff --git a/system/plugin/CreateHotspotUser.php b/system/plugin/CreateHotspotUser.php new file mode 100644 index 0000000..37828c0 --- /dev/null +++ b/system/plugin/CreateHotspotUser.php @@ -0,0 +1,420 @@ + 'error', 'code' => 400, 'message' => 'The parameter is not present in the URL.']); + } + } + } +} + +function ReconnectVoucher() { + header('Content-Type: application/json'); + + $rawData = file_get_contents('php://input'); + $postData = json_decode($rawData, true); + + if (!isset($postData['voucher_code'], $postData['account_id'])) { + echo json_encode(['status' => 'error', 'code' => 400, 'message' => 'Missing accountId or voucherCode field']); + return; + } + + $accountId = $postData['account_id']; + $voucherCode = $postData['voucher_code']; + + $voucher = ORM::for_table('tbl_voucher') + ->where('code', $voucherCode) + ->where('status', '0') + ->find_one(); + + if (!$voucher) { + echo json_encode([ + 'status' => 'error', + 'Resultcode' => '1', + 'voucher' => 'Not Found', + 'message' => 'Invalid Voucher code' + ]); + exit(); + } + + if ($voucher['status'] == '1') { + echo json_encode([ + 'status' => 'error', + 'Resultcode' => '3', + 'voucher' => 'Used', + 'message' => 'Voucher code is already used' + ]); + exit(); + } + + $planId = $voucher['id_plan']; + $routername = $voucher['routers']; + + $router = ORM::for_table('tbl_routers') + ->where('name', $routername) + ->find_one(); + + if (!$router) { + echo json_encode([ + 'status' => 'error', + 'message' => 'Router not found' + ]); + exit(); + } + + $routerId = $router['id']; + + if (!ORM::for_table('tbl_plans')->where('id', $planId)->count() || !ORM::for_table('tbl_routers')->where('id', $routerId)->count()) { + echo json_encode([ + 'status' => 'error', + 'message' => 'Unable to process your request, please refresh the page' + ]); + exit(); + } + + $user = ORM::for_table('tbl_customers')->where('username', $accountId)->find_one(); + if (!$user) { + // Create a new user if not exists + $user = ORM::for_table('tbl_customers')->create(); + $user->username = $accountId; + $user->password = '1234'; + $user->fullname = $accountId; + $user->email = $accountId . '@gmail.com'; + $user->phonenumber = $accountId; + $user->pppoe_password = '1234'; + $user->address = ''; + $user->service_type = 'Hotspot'; + } + + $user->router_id = $routerId; + $user->save(); + + // Update the voucher with the user ID + $voucher->user = $user->id; + $voucher->status = '1'; // Mark as used + $voucher->save(); + + if (Package::rechargeUser($user->id, $routername, $planId, 'Voucher', $voucherCode)) { + echo json_encode([ + 'status' => 'success', + 'Resultcode' => '2', + 'voucher' => 'activated', + 'message' => 'Voucher code has been activated', + 'username' => $user->username + ]); + } else { + echo json_encode([ + 'status' => 'error', + 'message' => 'Failed to recharge user package' + ]); + } +} + +function ReconnectUser() +{ + header('Content-Type: application/json'); + $rawData = file_get_contents('php://input'); + $postData = json_decode($rawData, true); + if (!$postData) { + echo json_encode(['status' => 'error', 'code' => 400, 'message' => 'Invalid JSON DATA']); + exit(); + } + + if (!isset($postData['mpesa_code'])) { + echo json_encode(['status' => 'error', 'code' => 400, 'message' => 'missing required fields']); + exit(); + } + + $mpesaCode = $postData['mpesa_code']; + + // Query the payment gateway table + $payment = ORM::for_table('tbl_payment_gateway') + ->where('gateway_trx_id', $mpesaCode) + ->find_one(); + + if (!$payment) { + $data = array(['status' => 'error', "Resultcode" => "1", 'user' => "Not Found", 'message' => 'Invalid Mpesa Transaction code']); + echo json_encode($data); + exit(); + } + + $username = $payment['username']; + + // Query the user recharges table + $recharge = ORM::for_table('tbl_user_recharges') + ->where('username', $username) + ->order_by_desc('id') + ->find_one(); + + if ($recharge) { + $status = $recharge['status']; + if ($status == 'on') { + $data = array( + "Resultcode" => "2", + "user" => "Active User", + "username" => $username, + "tyhK" => "1234", // Replace with the actual password or token + "Message" => "We have verified your transaction under the Mpesa Transaction $mpesaCode. Please don't leave this page as we are redirecting you.", + "Status" => "success" + ); + } elseif ($status == "off") { + $data = array( + "Resultcode" => "3", + "user" => "Expired User", + "Message" => "We have verified your transaction under the Mpesa Transaction $mpesaCode. But your Package is already Expired. Please buy a new Package.", + "Status" => "danger" + ); + } else { + $data = array( + "Message" => "Unexpected status value", + "Status" => "error" + ); + } + } else { + $data = array( + "Message" => "Recharge information not found", + "Status" => "error" + ); + } + + echo json_encode($data); + exit(); +} + + +function VerifyHotspot() { + header('Content-Type: application/json'); + $rawData = file_get_contents('php://input'); + $postData = json_decode($rawData, true); + + if (!$postData) { + echo json_encode(['Resultcode' => 'error', 'Message' => 'Invalid JSON data']); + return; + } + + if (!isset($postData['account_id'])) { + echo json_encode(['Resultcode' => 'error', 'Message' => 'Missing required fields']); + return; + } + + $accountId = $postData['account_id']; + $user = ORM::for_table('tbl_payment_gateway') + ->where('username', $accountId) + ->order_by_desc('id') + ->find_one(); + + if ($user) { + $status = $user->status; + $mpesacode = $user->gateway_trx_id; + $res = $user->pg_paid_response; + + if ($status == 2 && !empty($mpesacode)) { + echo json_encode([ + "Resultcode" => "3", + "Message" => "We have received your transaction under the Mpesa Transaction $mpesacode. Please do not leave this page as we are redirecting you.", + "Status" => "success" + ]); + } elseif ($res == "Not enough balance") { + echo json_encode([ + "Resultcode" => "2", + "Message" => "Insufficient Balance for the transaction", + "Status" => "danger" + ]); + } elseif ($res == "Wrong Mpesa pin") { + echo json_encode([ + "Resultcode" => "2", + "Message" => "You entered Wrong Mpesa pin, please resubmit", + "Status" => "danger" + ]); + } elseif ($status == 4) { + echo json_encode([ + "Resultcode" => "2", + "Message" => "You cancelled the transaction, you can enter phone number again to activate", + "Status" => "info" + ]); + } elseif (empty($mpesacode)) { + echo json_encode([ + "Resultcode" => "1", + "Message" => "A payment pop up has been sent to your phone. Please enter PIN to continue (Please do not leave or reload the page until redirected).", + "Status" => "primary" + ]); + } + } else { + echo json_encode([ + "Resultcode" => "error", + "Message" => "User not found" + ]); + } +} + + + +function CreateHostspotUser() +{ + header('Content-Type: application/json'); + $rawData = file_get_contents('php://input'); + $postData = json_decode($rawData, true); + if (!$postData) { + echo json_encode(['status' => 'error', 'code' => 400, 'message' => 'Invalid JSON DATA' . $postData . ' n tes ']); + } else { + $phone = $postData['phone_number']; + $planId = $postData['plan_id']; + $routerId = $postData['router_id']; + $accountId = $postData['account_id']; + + + + if (!isset( $postData['phone_number'], $postData['plan_id'], $postData['router_id'], $postData['account_id'])) { + echo json_encode(['status' => 'error', 'code' => 400, 'message' => 'missing required fields' . $postData, 'phone' => $phone, 'planId' => $planId, 'routerId' => $routerId, 'accountId' => $accountId]); + } else { + $phone = (substr($phone, 0, 1) == '+') ? str_replace('+', '', $phone) : $phone; + $phone = (substr($phone, 0, 1) == '0') ? preg_replace('/^0/', '254', $phone) : $phone; + $phone = (substr($phone, 0, 1) == '7') ? preg_replace('/^7/', '2547', $phone) : $phone; //cater for phone number prefix 2547XXXX + $phone = (substr($phone, 0, 1) == '1') ? preg_replace('/^1/', '2541', $phone) : $phone; //cater for phone number prefix 2541XXXX + $phone = (substr($phone, 0, 1) == '0') ? preg_replace('/^01/', '2541', $phone) : $phone; + $phone = (substr($phone, 0, 1) == '0') ? preg_replace('/^07/', '2547', $phone) : $phone; + if (strlen($phone) !== 12) { + echo json_encode(['status' => 'error', 'code' => 1, 'message' => 'Phone number ' . $phone . ' is invalid. Please confirm.']); + } + if (strlen($phone) == 12 && !empty($planId) && !empty($routerId)) { + $PlanExist = ORM::for_table('tbl_plans')->where('id', $planId)->count() > 0; + $RouterExist = ORM::for_table('tbl_routers')->where('id', $routerId)->count() > 0; + if (!$PlanExist || !$RouterExist) + echo json_encode(["status" => "error", "message" => "Unable to process your request, please refresh the page."]); + } + $Userexist = ORM::for_table('tbl_customers')->where('username', $accountId)->find_one(); + if ($Userexist) { + $Userexist->router_id = $routerId; + $Userexist->save(); + InitiateStkpush($phone, $planId, $accountId, $routerId); + } else { + try { + $defpass = '1234'; + $defaddr = 'netXtreme'; + $defmail = $phone . '@gmail.com'; + $createUser = ORM::for_table('tbl_customers')->create(); + $createUser->username = $accountId; + $createUser->password = $defpass; + $createUser->fullname = $phone; + $createUser->router_id = $routerId; + $createUser->phonenumber = $phone; + $createUser->pppoe_password = $defpass; + $createUser->address = $defaddr; + $createUser->email = $defmail; + $createUser->service_type = 'Hotspot'; + if ($createUser->save()) { + InitiateStkpush($phone, $planId, $accountId, $routerId); + } else { + echo json_encode(["status" => "error", "message" => "There was a system error when registering user, please contact support."]); + } + } catch (Exception $e) { + echo json_encode(["status" => "error", "message" => "Error creating user: " . $e->getMessage()]); + } + } + } + } +} + + +function InitiateStkpush($phone, $planId, $accountId, $routerId) +{ + $gateway = ORM::for_table('tbl_appconfig') + ->where('setting', 'payment_gateway') + ->find_one(); + $gateway = ($gateway) ? $gateway->value : null; + if ($gateway == "MpesatillStk") { + $url = U . "plugin/initiatetillstk"; + } elseif ($gateway == "BankStkPush") { + $url = U . "plugin/initiatebankstk"; + } elseif ($gateway == "mpesa") { + $url = U . "plugin/initiatempesa"; + } else { + $url = null; // or handle the default case appropriately + } + $Planname = ORM::for_table('tbl_plans') + ->where('id', $planId) + ->order_by_desc('id') + ->find_one(); + $Findrouter = ORM::for_table('tbl_routers') + ->where('id', $routerId) + ->order_by_desc('id') + ->find_one(); + $rname = $Findrouter->name; + $price = $Planname->price; + $Planname = $Planname->name_plan; + $Checkorders = ORM::for_table('tbl_payment_gateway') + ->where('username', $accountId) + ->where('status', 1) + ->order_by_desc('id') + ->find_many(); + if ($Checkorders) { + foreach ($Checkorders as $Dorder) { + $Dorder->delete(); + } + } + try { + $d = ORM::for_table('tbl_payment_gateway')->create(); + $d->username = $accountId; + $d->gateway = $gateway; + $d->plan_id = $planId; + $d->plan_name = $Planname; + $d->routers_id = $routerId; + $d->routers = $rname; + $d->price = $price; + $d->payment_method = $gateway; + $d->payment_channel = $gateway; + $d->created_date = date('Y-m-d H:i:s'); + $d->paid_date = date('Y-m-d H:i:s'); + $d->expired_date = date('Y-m-d H:i:s'); + $d->pg_url_payment = $url; + $d->status = 1; + $d->save(); + } catch (Exception $e) { + error_log('Error saving payment gateway record: ' . $e->getMessage()); + throw $e; + } + SendSTKcred($phone, $url, $accountId); +} + +function SendSTKcred($phone, $url, $accountId ) +{ + $link = $url; + $fields = array( + 'username' => $accountId, + 'phone' => $phone, + 'channel' => 'Yes', + ); + $postvars = http_build_query($fields); + $ch = curl_init(); + curl_setopt($ch, CURLOPT_URL, $link); + curl_setopt($ch, CURLOPT_POST, count($fields)); + curl_setopt($ch, CURLOPT_POSTFIELDS, $postvars); + $result = curl_exec($ch); +} + +Alloworigins(); diff --git a/system/plugin/c2b.php b/system/plugin/c2b.php new file mode 100644 index 0000000..1bcaf62 --- /dev/null +++ b/system/plugin/c2b.php @@ -0,0 +1,636 @@ +exec($tableCheckQuery); +} catch (PDOException $e) { + echo "Error creating the table: " . $e->getMessage(); +} catch (Exception $e) { + echo "An unexpected error occurred: " . $e->getMessage(); +} + +function c2b_overview() +{ + global $ui, $config; + _admin(); + $ui->assign('_title', 'Mpesa C2B Payment Overview'); + $ui->assign('_system_menu', ''); + $admin = Admin::_info(); + $ui->assign('_admin', $admin); + + // Check user type for access + if (!in_array($admin['user_type'], ['SuperAdmin', 'Admin', 'Sales'])) { + _alert(Lang::T('You do not have permission to access this page'), 'danger', "dashboard"); + exit; + } + + $query = ORM::for_table('tbl_mpesa_transactions')->order_by_desc('TransTime'); + $payments = $query->find_many(); + + if ( + (empty($config['mpesa_c2b_consumer_key']) || empty($config['mpesa_c2b_consumer_secret']) || empty($config['mpesa_c2b_business_code'])) + && !$config['c2b_registered'] + ) { + $ui->assign('message', '' . Lang::T("You haven't registered your validation and verification URLs. Please register URLs by clicking ") . ' Register URL ' . ''); + } + $ui->assign('payments', $payments); + $ui->assign('xheader', ''); + $ui->display('c2b_overview.tpl'); +} + +function c2b_settings() +{ + global $ui, $admin, $config; + $ui->assign('_title', Lang::T("Mpesa C2B Settings [Offline Payment]")); + $ui->assign('_system_menu', 'settings'); + $admin = Admin::_info(); + $ui->assign('_admin', $admin); + + if (!in_array($admin['user_type'], ['SuperAdmin', 'Admin'])) { + _alert(Lang::T('You do not have permission to access this page'), 'danger', "dashboard"); + } + + if (_post('save') == 'save') { + $mpesa_c2b_consumer_key = _post('mpesa_c2b_consumer_key'); + $mpesa_c2b_consumer_secret = _post('mpesa_c2b_consumer_secret'); + $mpesa_c2b_business_code = _post('mpesa_c2b_business_code'); + $mpesa_c2b_env = _post('mpesa_c2b_env'); + $mpesa_c2b_api = _post('mpesa_c2b_api'); + $mpesa_c2b_low_fee = _post('mpesa_c2b_low_fee') ? 1 : 0; + $mpesa_c2b_bill_ref = _post('mpesa_c2b_bill_ref'); + + $errors = []; + if (empty($mpesa_c2b_consumer_key)) { + $errors[] = Lang::T('Mpesa C2B Consumer Key is required.'); + } + if (empty($mpesa_c2b_consumer_secret)) { + $errors[] = Lang::T('Mpesa C2B Consumer Secret is required.'); + } + if (empty($mpesa_c2b_business_code)) { + $errors[] = Lang::T('Mpesa C2B Business Code is required.'); + } + if (empty($mpesa_c2b_env)) { + $errors[] = Lang::T('Mpesa C2B Environment is required.'); + } + if (empty($mpesa_c2b_api)) { + $errors[] = Lang::T('Mpesa C2B API URL is required.'); + } + + if (empty($mpesa_c2b_bill_ref)) { + $errors[] = Lang::T('Mpesa Bill Ref Number Type is required.'); + } + + if (!empty($errors)) { + $ui->assign('message', implode('
', $errors)); + $ui->display('c2b_settings.tpl'); + return; + } + + $settings = [ + 'mpesa_c2b_consumer_key' => $mpesa_c2b_consumer_key, + 'mpesa_c2b_consumer_secret' => $mpesa_c2b_consumer_secret, + 'mpesa_c2b_business_code' => $mpesa_c2b_business_code, + 'mpesa_c2b_env' => $mpesa_c2b_env, + 'mpesa_c2b_api' => $mpesa_c2b_api, + 'mpesa_c2b_low_fee' => $mpesa_c2b_low_fee, + 'mpesa_c2b_bill_ref' => $mpesa_c2b_bill_ref, + ]; + + // Update or insert settings in the database + foreach ($settings as $key => $value) { + $d = ORM::for_table('tbl_appconfig')->where('setting', $key)->find_one(); + if ($d) { + $d->value = $value; + $d->save(); + } else { + $d = ORM::for_table('tbl_appconfig')->create(); + $d->setting = $key; + $d->value = $value; + $d->save(); + } + } + + if ($admin) { + _log('[' . $admin['username'] . ']: ' . Lang::T('Settings Saved Successfully')); + } + r2(U . 'plugin/c2b_settings', 's', Lang::T('Settings Saved Successfully')); + } + + if (!empty($config['mpesa_c2b_consumer_key'] && $config['mpesa_c2b_consumer_secret'] && $config['mpesa_c2b_business_code']) && !$config['c2b_registered']) { + $ui->assign('message', '' . Lang::T("You haven't registered your validation and verification URLs, Please register URLs by clicking ") . ' Register URL ' . ''); + } + $ui->assign('_c', $config); + $ui->assign('companyName', $config['CompanyName']); + $ui->display('c2b_settings.tpl'); +} + +function c2b_generateAccessToken() +{ + global $config; + $mpesa_c2b_env = $config['mpesa_c2b_env'] ?? null; + $mpesa_c2b_consumer_key = $config['mpesa_c2b_consumer_key'] ?? null; + $mpesa_c2b_consumer_secret = $config['mpesa_c2b_consumer_secret'] ?? null; + $access_token_url = match ($mpesa_c2b_env) { + "live" => 'https://api.safaricom.co.ke/oauth/v1/generate?grant_type=client_credentials', + "sandbox" => 'https://sandbox.safaricom.co.ke/oauth/v1/generate?grant_type=client_credentials', + }; + $headers = ['Content-Type:application/json; charset=utf8']; + $curl = curl_init($access_token_url); + curl_setopt($curl, CURLOPT_HTTPHEADER, $headers); + curl_setopt($curl, CURLOPT_RETURNTRANSFER, TRUE); + curl_setopt($curl, CURLOPT_HEADER, FALSE); + curl_setopt($curl, CURLOPT_USERPWD, "$mpesa_c2b_consumer_key:$mpesa_c2b_consumer_secret"); + $result = curl_exec($curl); + $result = json_decode($result); + if (isset($result->access_token)) { + return $result->access_token; + } else { + return null; + } +} + +function c2b_registerUrl() +{ + global $config; + if ( + (empty($config['mpesa_c2b_consumer_key']) || empty($config['mpesa_c2b_consumer_secret']) || empty($config['mpesa_c2b_business_code'])) + && !$config['c2b_registered'] + ) { + r2(U . 'plugin/c2b_settings', 'e', Lang::T('Please setup your M-Pesa C2B settings first')); + exit; + } + $access_token = c2b_generateAccessToken(); + switch ($access_token) { + case null: + r2(U . 'plugin/c2b_settings', 'e', Lang::T('Failed to generate access token')); + exit; + default: + $BusinessShortCode = $config['mpesa_c2b_business_code'] ?? null; + $mpesa_c2b_env = $config['mpesa_c2b_env'] ?? null; + $confirmationUrl = U . 'plugin/c2b_confirmation'; + $validationUrl = U . 'plugin/c2b_validation'; + $mpesa_c2b_api = $config['mpesa_c2b_api'] ?? null; + $registerurl = match ($mpesa_c2b_env) { + "live" => match ($mpesa_c2b_api) { + "v1" => 'https://api.safaricom.co.ke/mpesa/c2b/v1/registerurl', + "v2" => 'https://api.safaricom.co.ke/mpesa/c2b/v2/registerurl', + }, + "sandbox" => 'https://sandbox.safaricom.co.ke/mpesa/c2b/v1/registerurl', + }; + $curl = curl_init(); + curl_setopt($curl, CURLOPT_URL, $registerurl); + curl_setopt($curl, CURLOPT_HTTPHEADER, [ + 'Content-Type:application/json', + "Authorization:Bearer $access_token" + ]); + $data = [ + 'ShortCode' => $BusinessShortCode, + 'ResponseType' => 'Completed', + 'ConfirmationURL' => $confirmationUrl, + 'ValidationURL' => $validationUrl + ]; + $data_string = json_encode($data); + curl_setopt($curl, CURLOPT_RETURNTRANSFER, true); + curl_setopt($curl, CURLOPT_POST, true); + curl_setopt($curl, CURLOPT_POSTFIELDS, $data_string); + $curl_response = curl_exec($curl); + $data = json_decode($curl_response); + if (isset($data->ResponseCode) && $data->ResponseCode == 0) { + try { + $d = ORM::for_table('tbl_appconfig')->create(); + $d->setting = 'c2b_registered'; + $d->value = '1'; + $d->save(); + } catch (Exception $e) { + _log("Failed to save M-Pesa C2B URL to database.\n\n" . $e->getMessage()); + sendTelegram("Failed to save M-Pesa C2B URL to database.\n\n" . $e->getMessage()); + } + sendTelegram("M-Pesa C2B URL registered successfully"); + r2(U . 'plugin/c2b_settings', 's', "M-Pesa C2B URL registered successfully"); + } else { + $errorMessage = $data->errorMessage; + sendTelegram("Resister M-Pesa C2B URL Failed\n\n" . json_encode($curl_response, JSON_PRETTY_PRINT)); + r2(U . 'plugin/c2b_settings', 'e', "Failed to register M-Pesa C2B URL Error $errorMessage"); + } + break; + } +} + + +function c2b_webhook_log($data) +{ + $logFile = 'pages/mpesa-webhook.html'; + $logEntry = date('Y-m-d H:i:s') . "
" . htmlspecialchars($data, ENT_QUOTES, 'UTF-8') . "
\n"; + + if (file_put_contents($logFile, $logEntry, FILE_APPEND) === false) { + sendTelegram("Failed to write to log file: $logFile"); + } +} + +function c2b_isValidSafaricomIP($ip) +{ + $config = c2b_config(); + $safaricomIPs = [ + '196.201.214.0/24', + '196.201.213.0/24', + '196.201.212.0/24', + '172.69.79.0/24', + '172.69.0.0/24', + '0.0.0.0/0', + ]; + if ($config['mpesa_c2b_env'] == 'sandbox') { + $safaricomIPs[] = '::1'; + } + + foreach ($safaricomIPs as $range) { + if (c2b_ipInRange($ip, $range)) { + return true; + } + } + + return false; +} + +function c2b_ipInRange($ip, $range) +{ + list($subnet, $bits) = explode('/', $range); + $ip = ip2long($ip); + $subnet = ip2long($subnet); + $mask = -1 << (32 - $bits); + $subnet &= $mask; + return ($ip & $mask) == $subnet; +} + +function c2b_confirmation() +{ + + global $config; + header("Content-Type: application/json"); + + $clientIP = $_SERVER['REMOTE_ADDR']; + + if (!c2b_isValidSafaricomIP($clientIP)) { + c2b_logAndNotify("Unauthorized request from IP: {$clientIP}"); + http_response_code(403); + echo json_encode(["ResultCode" => 1, "ResultDesc" => "Unauthorized"]); + return; + } + + $mpesaResponse = file_get_contents('php://input'); + if ($mpesaResponse === false) { + c2b_logAndNotify("Failed to get input stream."); + return; + } + + c2b_webhook_log('Received webhook request'); + c2b_webhook_log($mpesaResponse); + + $content = json_decode($mpesaResponse); + if (json_last_error() !== JSON_ERROR_NONE) { + c2b_logAndNotify("Failed to decode JSON response: " . json_last_error_msg()); + return; + } + c2b_webhook_log('Decoded JSON data successfully'); + + if (!class_exists('Package')) { + c2b_logAndNotify("Error: Package class does not exist."); + return; + } + + if (isset($config['mpesa_c2b_bill_ref'])) { + switch ($config['mpesa_c2b_bill_ref']) { + case 'phone': + $customer = ORM::for_table('tbl_customers') + ->where('phonenumber', $content->BillRefNumber) + ->find_one(); + break; + + case 'username': + $customer = ORM::for_table('tbl_customers') + ->where('username', $content->BillRefNumber) + ->find_one(); + break; + + case 'id': + $customer = ORM::for_table('tbl_customers') + ->where('id', $content->BillRefNumber) + ->find_one(); + break; + + default: + $customer = null; + break; + } + + if (!$customer) { + sendTelegram("Validation failed: No account found for BillRefNumber: $content->BillRefNumber"); + _log("Validation failed: No account found for BillRefNumber: $content->BillRefNumber"); + echo json_encode(["ResultCode" => "C2B00012", "ResultDesc" => "Invalid Account Number"]); + return; + } + } else { + _log("Configuration error: mpesa_c2b_bill_ref not set."); + sendTelegram("Configuration error: mpesa_c2b_bill_ref not set."); + } + + + $bills = c2b_billing($customer->id); + if (!$bills) { + c2b_logAndNotify("No matching bill found for BillRefNumber: {$content->BillRefNumber}"); + return; + } + + foreach ($bills as $bill) { + c2b_handleBillPayment($content, $customer, $bill); + } + + echo json_encode(["ResultCode" => 0, "ResultDesc" => "Accepted"]); +} + + +function c2b_handleBillPayment($content, $customer, $bill) +{ + $amountToPay = $bill['price']; + $amountPaid = $content->TransAmount; + $channel_mode = "Mpesa C2B - {$content->TransID}"; + $customerBalance = $customer->balance; + $currentBalance = $customerBalance + $amountPaid; + $customerID = $customer->id; + + try { + $transaction = c2b_storeTransaction($content, $bill['namebp'], $amountToPay, $customerID); + } catch (Exception $e) { + c2b_handleException("Failed to save transaction", $e); + exit; + } + + if ($currentBalance >= $amountToPay) { + $excessAmount = $currentBalance - $amountToPay; + try { + $result = Package::rechargeUser($customer->id, $bill['routers'], $bill['plan_id'], 'mpesa', $channel_mode); + if (!$result) { + c2b_logAndNotify("Mpesa Payment Successful, but failed to activate the package for customer {$customer->username}."); + } else { + if ($excessAmount > 0) { + $customer->balance = $excessAmount; + $customer->save(); + } else { + $customer->balance = 0; + $customer->save(); + } + c2b_sendPaymentSuccessMessage($customer, $amountPaid, $bill['namebp']); + $transaction->transactionStatus = 'Completed'; + $transaction->save(); + } + } catch (Exception $e) { + c2b_handleException("Error during package activation", $e); + } + } else { + c2b_updateCustomerBalance($customer, $currentBalance, $amountPaid); + $neededToActivate = $amountToPay - $currentBalance; + c2b_sendBalanceUpdateMessage($customer, $amountPaid, $currentBalance, $neededToActivate); + $transaction->transactionStatus = 'Completed'; + $transaction->save(); + } +} + + +function c2b_storeTransaction($content, $packageName, $packagePrice, $customerID) +{ + ORM::get_db()->beginTransaction(); + try { + $transaction = ORM::for_table('tbl_mpesa_transactions') + ->where('TransID', $content->TransID) + ->find_one(); + + if ($transaction) { + // Update existing transaction + $transaction->TransactionType = $content->TransactionType; + $transaction->TransTime = $content->TransTime; + $transaction->TransAmount = $content->TransAmount; + $transaction->BusinessShortCode = $content->BusinessShortCode; + $transaction->BillRefNumber = $content->BillRefNumber; + $transaction->OrgAccountBalance = $content->OrgAccountBalance; + $transaction->MSISDN = $content->MSISDN; + $transaction->FirstName = $content->FirstName; + $transaction->PackageName = $packageName; + $transaction->PackagePrice = $packagePrice; + $transaction->customerID = $customerID; + $transaction->transactionStatus = 'Pending'; + } else { + // Create new transaction + $transaction = ORM::for_table('tbl_mpesa_transactions')->create(); + $transaction->TransID = $content->TransID; + $transaction->TransactionType = $content->TransactionType; + $transaction->TransTime = $content->TransTime; + $transaction->TransAmount = $content->TransAmount; + $transaction->BusinessShortCode = $content->BusinessShortCode; + $transaction->BillRefNumber = $content->BillRefNumber; + $transaction->OrgAccountBalance = $content->OrgAccountBalance; + $transaction->MSISDN = $content->MSISDN; + $transaction->FirstName = $content->FirstName; + $transaction->PackageName = $packageName; + $transaction->PackagePrice = $packagePrice; + $transaction->customerID = $customerID; + $transaction->transactionStatus = 'Pending'; + } + $transaction->save(); + ORM::get_db()->commit(); + return $transaction; + } catch (Exception $e) { + ORM::get_db()->rollBack(); + throw $e; + } +} + +function c2b_logAndNotify($message) +{ + _log($message); + sendTelegram($message); +} + +function c2b_handleException($message, $e) +{ + $fullMessage = "$message: " . $e->getMessage() . " in " . $e->getFile() . " on line " . $e->getLine(); + c2b_logAndNotify($fullMessage); +} + +function c2b_updateCustomerBalance($customer, $newBalance, $amountPaid) +{ + try { + $customer->balance = $newBalance; + $customer->save(); + c2b_logAndNotify("Payment of KES {$amountPaid} has been added to the balance of customer {$customer->username}."); + } catch (Exception $e) { + c2b_handleException("Failed to update customer balance", $e); + } +} + +function c2b_sendPaymentSuccessMessage($customer, $amountPaid, $packageName) +{ + $config = c2b_config(); + $message = "Dear {$customer->fullname}, your payment of KES {$amountPaid} has been received and your plan {$packageName} has been successfully activated. Thank you for choosing {$config['CompanyName']}."; + c2b_sendNotification($customer, $message); +} + +function c2b_sendBalanceUpdateMessage($customer, $amountPaid, $currentBalance, $neededToActivate) +{ + $config = c2b_config(); + $message = "Dear {$customer->fullname}, your payment of KES {$amountPaid} has been received and added to your account balance. Your current balance is KES {$currentBalance}."; + if ($neededToActivate > 0) { + $message .= " To activate your package, you need to add KES {$neededToActivate} more to your account."; + } else { + $message .= " Your current balance is sufficient to activate your package."; + } + $message .= "\n" . $config['CompanyName']; + c2b_sendNotification($customer, $message); +} + +function c2b_sendNotification($customer, $message) +{ + try { + Message::sendSMS($customer->phonenumber, $message); + Message::sendWhatsapp($customer->phonenumber, $message); + } catch (Exception $e) { + c2b_handleException("Failed to send SMS/WhatsApp message", $e); + } +} + + +function c2b_validation() +{ + header("Content-Type: application/json"); + $mpesaResponse = file_get_contents('php://input'); + + $config = c2b_config(); + $content = json_decode($mpesaResponse); + + if (json_last_error() !== JSON_ERROR_NONE) { + sendTelegram("Failed to decode JSON response."); + _log("Failed to decode JSON response."); + echo json_encode(["ResultCode" => "C2B00016", "ResultDesc" => "Invalid JSON format"]); + return; + } + + $BillRefNumber = $content->BillRefNumber; + $TransAmount = $content->TransAmount; + + if (isset($config['mpesa_c2b_bill_ref'])) { + switch ($config['mpesa_c2b_bill_ref']) { + case 'phone': + $customer = ORM::for_table('tbl_customers') + ->where('phonenumber', $content->BillRefNumber) + ->find_one(); + break; + + case 'username': + $customer = ORM::for_table('tbl_customers') + ->where('username', $content->BillRefNumber) + ->find_one(); + break; + + case 'id': + $customer = ORM::for_table('tbl_customers') + ->where('id', $content->BillRefNumber) + ->find_one(); + break; + + default: + $customer = null; + break; + } + + if (!$customer) { + sendTelegram("Validation failed: No account found for BillRefNumber: $BillRefNumber"); + _log("Validation failed: No account found for BillRefNumber: $BillRefNumber"); + echo json_encode(["ResultCode" => "C2B00012", "ResultDesc" => "Invalid Account Number"]); + return; + } + } else { + _log("Configuration error: mpesa_c2b_bill_ref not set."); + sendTelegram("Configuration error: mpesa_c2b_bill_ref not set."); + } + + + $bills = c2b_billing($customer->id); + + if (!$bills) { + sendTelegram("Validation failed: No bill found for BillRefNumber: $BillRefNumber"); + _log("Validation failed: No bill found for BillRefNumber: $BillRefNumber"); + echo json_encode(["ResultCode" => "C2B00012", "ResultDesc" => "Invalid Bill Reference"]); + return; + } + + foreach ($bills as $bill) { + } + + $billAmount = $bill['price']; + if (!$config['mpesa_c2b_low_fee']) { + if ($TransAmount < $billAmount) { + sendTelegram("Validation failed: Insufficient amount. Transferred: $TransAmount, Required: $billAmount"); + _log("Validation failed: Insufficient amount. Transferred: $TransAmount, Required: $billAmount"); + echo json_encode(["ResultCode" => "C2B00013", "ResultDesc" => "Invalid or Insufficient Amount"]); + return; + } + } + + sendTelegram("Validation successful for BillRefNumber: $BillRefNumber with amount: $TransAmount"); + _log("Validation successful for BillRefNumber: $BillRefNumber with amount: $TransAmount"); + echo json_encode(["ResultCode" => 0, "ResultDesc" => "Accepted"]); +} + +function c2b_billing($id) +{ + $d = ORM::for_table('tbl_user_recharges') + ->selects([ + 'customer_id', + 'username', + 'plan_id', + 'namebp', + 'recharged_on', + 'recharged_time', + 'expiration', + 'time', + 'status', + 'method', + 'plan_type', + ['tbl_user_recharges.routers', 'routers'], + ['tbl_user_recharges.type', 'type'], + 'admin_id', + 'prepaid' + ]) + ->select('tbl_plans.price', 'price') + ->left_outer_join('tbl_plans', array('tbl_plans.id', '=', 'tbl_user_recharges.plan_id')) + ->where('customer_id', $id) + ->find_many(); + return $d; +} + +function c2b_config() +{ + $result = ORM::for_table('tbl_appconfig')->find_many(); + foreach ($result as $value) { + $config[$value['setting']] = $value['value']; + } + return $config; +} diff --git a/system/plugin/clear_cache.php b/system/plugin/clear_cache.php new file mode 100644 index 0000000..6a850dc --- /dev/null +++ b/system/plugin/clear_cache.php @@ -0,0 +1,48 @@ +assign('_title', 'Clear Cache'); + $ui->assign('_system_menu', 'settings'); + $admin = Admin::_info(); + $ui->assign('_admin', $admin); + + // Check user type for access + if (!in_array($admin['user_type'], ['SuperAdmin', 'Admin'])) { + _alert(Lang::T('You do not have permission to access this page'), 'danger', "dashboard"); + exit; + } + + $compiledCacheDir = 'ui/compiled'; + $templateCacheDir = 'system/cache'; + + try { + // Clear the compiled cache + $files = scandir($compiledCacheDir); + foreach ($files as $file) { + if ($file !== '.' && $file !== '..' && is_file($compiledCacheDir . '/' . $file)) { + unlink($compiledCacheDir . '/' . $file); + } + } + + // Clear the template cache + $templateCacheFiles = glob($templateCacheDir . '/*.{json,temp}', GLOB_BRACE); + foreach ($templateCacheFiles as $file) { + if (is_file($file)) { + unlink($file); + } + } + + // Cache cleared successfully + _log('[' . ($admin['fullname'] ?? 'Unknown Admin') . ']: ' . Lang::T(' Cleared the system cache '), $admin['user_type']); + r2(U . 'dashboard', 's', Lang::T("Cache cleared successfully!")); + } catch (Exception $e) { + // Error occurred while clearing the cache + _log('[' . ($admin['fullname'] ?? 'Unknown Admin') . ']: ' . Lang::T(' Error occurred while clearing the cache: ' . $e->getMessage()), $admin['user_type']); + r2(U . 'dashboard', 'e', Lang::T("Error occurred while clearing the cache: ") . $e->getMessage()); + } +} diff --git a/system/plugin/download.php b/system/plugin/download.php new file mode 100644 index 0000000..604cc4a --- /dev/null +++ b/system/plugin/download.php @@ -0,0 +1,755 @@ +connect_error) { + die("Connection failed: " . $mysqli->connect_error); +} + +// Function to get a setting value +function getSettingValue($mysqli, $setting) { + $query = $mysqli->prepare("SELECT value FROM tbl_appconfig WHERE setting = ?"); + $query->bind_param("s", $setting); + $query->execute(); + $result = $query->get_result(); + if ($row = $result->fetch_assoc()) { + return $row['value']; + } + return ''; +} + +// Fetch hotspot title and description from tbl_appconfig +$hotspotTitle = getSettingValue($mysqli, 'hotspot_title'); +$description = getSettingValue($mysqli, 'description'); +$phone = getSettingValue($mysqli, 'phone'); +$company = getSettingValue($mysqli, 'CompanyName'); + +// Fetch router name and router ID from tbl_appconfig +$routerName = getSettingValue($mysqli, 'router_name'); +$routerId = getSettingValue($mysqli, 'router_id'); + +// Fetch available plans + +$planQuery = "SELECT id, type, name_plan, price, validity, validity_unit FROM tbl_plans WHERE routers = ? AND type = 'Hotspot'"; +$planStmt = $mysqli->prepare($planQuery); +$planStmt->bind_param("s", $routerName); +$planStmt->execute(); +$planResult = $planStmt->get_result(); + + +$htmlContent = ""; +$htmlContent .= "\n"; +$htmlContent .= "\n"; +$htmlContent .= "\n"; +$htmlContent .= " \n"; +$htmlContent .= " \n"; +$htmlContent .= " $company\n"; +$htmlContent .= " \n"; +$htmlContent .= " \n"; +$htmlContent .= " \n"; +$htmlContent .= " \n"; +$htmlContent .= " \n"; +$htmlContent .= " \n"; +$htmlContent .= " \n"; +$htmlContent .= " \n"; + + + + + +$htmlContent .= "\n"; +$htmlContent .= "\n"; +$htmlContent .= " \n"; +$htmlContent .= "
\n"; +$htmlContent .= "
\n"; +$htmlContent .= " \n"; +$htmlContent .= " \n"; +$htmlContent .= " \n"; +$htmlContent .= " \n"; +$htmlContent .= "
\n"; +$htmlContent .= "

$company HOTSPOT LOGIN

\n"; +$htmlContent .= "
    \n"; +$htmlContent .= "
  1. Click on your preferred package
  2. \n"; +$htmlContent .= "
  3. Enter Mpesa No.
  4. \n"; +$htmlContent .= "
  5. Enter pin
  6. \n"; +$htmlContent .= "
  7. Wait to be connected
  8. \n"; +$htmlContent .= "
\n"; +$htmlContent .= "

For any enquiries contact : $phone

\n"; +$htmlContent .= "
\n"; +$htmlContent .= " \n"; +$htmlContent .= "
\n"; +$htmlContent .= "
\n"; + + + + + + + +$htmlContent .= "
\n"; +$htmlContent .= "
\n"; +$htmlContent .= "
\n"; +$htmlContent .= "
\n"; +$htmlContent .= " \n"; +$htmlContent .= "
\n"; +$htmlContent .= "
\n"; +$htmlContent .= "
\n"; +$htmlContent .= "
\n"; + + + + + + + + + +$htmlContent .= "
\n"; +$htmlContent .= "
\n"; +$htmlContent .= "
\n"; +$htmlContent .= "
\n"; +$htmlContent .= "
\n"; +$htmlContent .= "
\n"; + +// New HTML content added +$htmlContent .= "
\n"; +$htmlContent .= "
\n"; +$htmlContent .= "
\n"; +$htmlContent .= "

Enter code to reconnect

\n"; +$htmlContent .= "
\n"; +$htmlContent .= " \n"; +$htmlContent .= " \n"; +$htmlContent .= " \n"; +$htmlContent .= "
\n"; +$htmlContent .= "
\n"; +$htmlContent .= "
\n"; +$htmlContent .= "
\n"; +$htmlContent .= "
\n"; +$htmlContent .= "

Already Have an Active Package?

\n"; +$htmlContent .= "
\n"; +$htmlContent .= "
\n"; +$htmlContent .= " \n"; +$htmlContent .= " \n"; +$htmlContent .= "
\n"; +$htmlContent .= " \n"; +$htmlContent .= "
\n"; +$htmlContent .= " \n"; +$htmlContent .= " \n"; +$htmlContent .= "
\n"; +$htmlContent .= "
\n"; +$htmlContent .= " \n"; +$htmlContent .= "
\n"; +$htmlContent .= "
\n"; +$htmlContent .= "
\n"; +$htmlContent .= "
\n"; +$htmlContent .= "
\n"; +$htmlContent .= "
\n"; +$htmlContent .= "
\n"; +$htmlContent .= "
\n"; +$htmlContent .= "

© " . date("Y") . ". Powered by NestICT

\n"; +$htmlContent .= "
\n"; +$htmlContent .= "
\n"; +$htmlContent .= "
\n"; +$htmlContent .= "\n"; + +// Add the closing script section as well, if necessary +$htmlContent .= "\n"; + + + + + + + + + + + + + + + + + + + + + + +$htmlContent .= "\n"; + + + + + + + + + + + +$htmlContent .= "\n"; +$htmlContent .= "\n"; + + + + + + + + + + + + + + + + + + + + + + +$htmlContent .= "\n"; +$htmlContent .= "\n"; + + + + + + + + + + + + + + + + + + + +$htmlContent .= "\n"; + + + + + + + + + + + + + + + + + + + + + + +$htmlContent .= "\n"; +$htmlContent .= "\n"; +$htmlContent .= "\n"; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +$planStmt->close(); +$mysqli->close(); +// Check if the download parameter is set +if (isset($_GET['download']) && $_GET['download'] == '1') { + // Prepare the HTML content for download + // ... build your HTML content ... + + // Specify the filename for the download + $filename = "login.html"; + + // Send headers to force download + header('Content-Type: application/octet-stream'); + header('Content-Disposition: attachment; filename='.basename($filename)); + header('Expires: 0'); + header('Cache-Control: must-revalidate'); + header('Pragma: public'); + header('Content-Length: ' . strlen($htmlContent)); + + // Output the content + echo $htmlContent; + + // Prevent any further output + exit; +} + +// Regular page content goes here +// ... HTML and PHP code to display the page ... + + diff --git a/system/plugin/error_log b/system/plugin/error_log new file mode 100644 index 0000000..903f614 --- /dev/null +++ b/system/plugin/error_log @@ -0,0 +1,12 @@ +[06-Jul-2024 15:05:25 UTC] PHP Fatal error: Uncaught Error: Undefined constant "request" in /home/codevibe/kejos.codevibeisp.co.ke/system/plugin/download.php:154 +Stack trace: +#0 {main} + thrown in /home/codevibe/kejos.codevibeisp.co.ke/system/plugin/download.php on line 154 +[06-Jul-2024 15:05:28 UTC] PHP Fatal error: Uncaught Error: Undefined constant "request" in /home/codevibe/kejos.codevibeisp.co.ke/system/plugin/download.php:154 +Stack trace: +#0 {main} + thrown in /home/codevibe/kejos.codevibeisp.co.ke/system/plugin/download.php on line 154 +[06-Jul-2024 17:35:47 UTC] PHP Fatal error: Uncaught Error: Undefined constant "request" in /home/codevibe/kejos.codevibeisp.co.ke/system/plugin/download.php:154 +Stack trace: +#0 {main} + thrown in /home/codevibe/kejos.codevibeisp.co.ke/system/plugin/download.php on line 154 diff --git a/system/plugin/hotspot_plan.php b/system/plugin/hotspot_plan.php new file mode 100644 index 0000000..6c5e06b --- /dev/null +++ b/system/plugin/hotspot_plan.php @@ -0,0 +1,79 @@ +find_many(); + $plans_hotspot = ORM::for_table('tbl_plans')->where('type', 'Hotspot')->find_many(); + + // Fetch bandwidth limits for all plans + $bandwidth_limits = ORM::for_table('tbl_bandwidth')->find_many(); + $bandwidth_map = []; + foreach ($bandwidth_limits as $limit) { + $bandwidth_map[$limit['plan_id']] = [ + 'downlimit' => $limit['rate_down'], + 'uplimit' => $limit['rate_up'], + ]; + } + + // Fetch currency from tbl_appconfig using the correct column names + $currency_config = ORM::for_table('tbl_appconfig')->where('setting', 'currency_code')->find_one(); + $currency = $currency_config ? $currency_config->value : 'Ksh'; // Default to 'Ksh' if not found + + // Initialize empty data array to store router-specific plans + $data = []; + + // Process each router to filter and collect hotspot plans + foreach ($routers as $router) { + if ($router['name'] === $routerName) { // Check if router name matches POSTed routername + $routerData = [ + 'name' => $router['name'], + 'router_id' => $router['id'], + 'description' => $router['description'], + 'plans_hotspot' => [], + ]; + + // Filter and collect hotspot plans associated with the router + foreach ($plans_hotspot as $plan) { + if ($router['name'] == $plan['routers']) { + $plan_id = $plan['id']; + $bandwidth_data = isset($bandwidth_map[$plan_id]) ? $bandwidth_map[$plan_id] : []; + + // Construct payment link using $_url + $paymentlink = "https://codevibeisp.co.ke/index.php?_route=plugin/hotspot_pay&routerName={$router['name']}&planId={$plan['id']}&routerId={$router['id']}"; + + // Prepare plan data to be sent in JSON response + $routerData['plans_hotspot'][] = [ + 'plantype' => $plan['type'], + 'planname' => $plan['name_plan'], + 'currency' => $currency, + 'price' => $plan['price'], + 'validity' => $plan['validity'], + 'device' => $plan['shared_users'], + 'datalimit' => $plan['data_limit'], + 'timelimit' => $plan['validity_unit'] ?? null, + 'downlimit' => $bandwidth_data['downlimit'] ?? null, + 'uplimit' => $bandwidth_data['uplimit'] ?? null, + 'paymentlink' => $paymentlink, + 'planId' => $plan['id'], + 'routerName' => $router['name'], + 'routerId' => $router['id'] + ]; + } + } + + // Add router data to $data array + $data[] = $routerData; + } + } + + // Respond with JSON data + // header('Content-Type: application/json'); + // header('Access-Control-Allow-Origin: *'); // Adjust this based on your CORS requirements + echo json_encode(['data' => $data], JSON_PRETTY_PRINT); + exit(); +} +?> diff --git a/system/plugin/hotspot_settings.php b/system/plugin/hotspot_settings.php new file mode 100644 index 0000000..2a845c5 --- /dev/null +++ b/system/plugin/hotspot_settings.php @@ -0,0 +1,229 @@ +assign('_title', 'Hotspot Dashboard'); + $ui->assign('_admin', $admin); + + // Check if form is submitted + if ($_SERVER['REQUEST_METHOD'] === 'POST') { + // Update Hotspot Title + $newHotspotTitle = isset($_POST['hotspot_title']) ? trim($_POST['hotspot_title']) : ''; + if (!empty($newHotspotTitle)) { + $updateStmt = $conn->prepare("UPDATE tbl_appconfig SET value = ? WHERE setting = 'hotspot_title'"); + $updateStmt->execute([$newHotspotTitle]); + } + + // Add similar logic for FAQ fields here + // FAQ Headline 1 Posting To Database + if ($_SERVER['REQUEST_METHOD'] === 'POST') { + $newFaqHeadline1 = isset($_POST['frequently_asked_questions_headline1']) ? trim($_POST['frequently_asked_questions_headline1']) : ''; + if (!empty($newFaqHeadline1)) { + $updateFaqStmt1 = $conn->prepare("UPDATE tbl_appconfig SET value = ? WHERE setting = 'frequently_asked_questions_headline1'"); + $updateFaqStmt1->execute([$newFaqHeadline1]); + } + } + + // FAQ Headline 2 Posting To Database + if ($_SERVER['REQUEST_METHOD'] === 'POST') { + $newFaqHeadline1 = isset($_POST['frequently_asked_questions_headline2']) ? trim($_POST['frequently_asked_questions_headline2']) : ''; + if (!empty($newFaqHeadline1)) { + $updateFaqStmt1 = $conn->prepare("UPDATE tbl_appconfig SET value = ? WHERE setting = 'frequently_asked_questions_headline2'"); + $updateFaqStmt1->execute([$newFaqHeadline1]); + } +} + + // FAQ Headline 3 Posting To Database + if ($_SERVER['REQUEST_METHOD'] === 'POST') { + $newFaqHeadline1 = isset($_POST['frequently_asked_questions_headline3']) ? trim($_POST['frequently_asked_questions_headline3']) : ''; + if (!empty($newFaqHeadline1)) { + $updateFaqStmt1 = $conn->prepare("UPDATE tbl_appconfig SET value = ? WHERE setting = 'frequently_asked_questions_headline3'"); + $updateFaqStmt1->execute([$newFaqHeadline1]); + } +} + + // FAQ Answer 1 Posting To Database + if ($_SERVER['REQUEST_METHOD'] === 'POST') { + $newFaqHeadline1 = isset($_POST['frequently_asked_questions_answer1']) ? trim($_POST['frequently_asked_questions_answer1']) : ''; + if (!empty($newFaqHeadline1)) { + $updateFaqStmt1 = $conn->prepare("UPDATE tbl_appconfig SET value = ? WHERE setting = 'frequently_asked_questions_answer1'"); + $updateFaqStmt1->execute([$newFaqHeadline1]); + } +} + + + // FAQ Answer 2 Posting To Database + if ($_SERVER['REQUEST_METHOD'] === 'POST') { + $newFaqHeadline1 = isset($_POST['frequently_asked_questions_answer2']) ? trim($_POST['frequently_asked_questions_answer2']) : ''; + if (!empty($newFaqHeadline1)) { + $updateFaqStmt1 = $conn->prepare("UPDATE tbl_appconfig SET value = ? WHERE setting = 'frequently_asked_questions_answer2'"); + $updateFaqStmt1->execute([$newFaqHeadline1]); + } +} + + // FAQ Answer 3 Posting To Database + if ($_SERVER['REQUEST_METHOD'] === 'POST') { + $newFaqHeadline1 = isset($_POST['frequently_asked_questions_answer3']) ? trim($_POST['frequently_asked_questions_answer3']) : ''; + if (!empty($newFaqHeadline1)) { + $updateFaqStmt1 = $conn->prepare("UPDATE tbl_appconfig SET value = ? WHERE setting = 'frequently_asked_questions_answer3'"); + $updateFaqStmt1->execute([$newFaqHeadline1]); + } +} + + // FAQ Description Posting To Database + if ($_SERVER['REQUEST_METHOD'] === 'POST') { + $newFaqHeadline1 = isset($_POST['description']) ? trim($_POST['description']) : ''; + if (!empty($newFaqHeadline1)) { + $updateFaqStmt1 = $conn->prepare("UPDATE tbl_appconfig SET value = ? WHERE setting = 'description'"); + $updateFaqStmt1->execute([$newFaqHeadline1]); + } +} + +if ($_SERVER['REQUEST_METHOD'] === 'POST') { + // Get router name from user input + $routerName = isset($_POST['router_name']) ? trim($_POST['router_name']) : ''; + + if (!empty($routerName)) { + // Fetch the router ID based on the router name + $routerStmt = $conn->prepare("SELECT id FROM tbl_routers WHERE name = :router_name"); + $routerStmt->execute(['router_name' => $routerName]); + $router = $routerStmt->fetch(PDO::FETCH_ASSOC); + + if ($router) { + // Update router_id in tbl_appconfig + $updateRouterIdStmt = $conn->prepare("UPDATE tbl_appconfig SET value = :router_id WHERE setting = 'router_id'"); + $updateRouterIdStmt->execute(['router_id' => $router['id']]); + + // Update router_name in tbl_appconfig + $updateRouterNameStmt = $conn->prepare("UPDATE tbl_appconfig SET value = :router_name WHERE setting = 'router_name'"); + $updateRouterNameStmt->execute(['router_name' => $routerName]); + } else { + // Handle the case where no matching router is found + // For example, you can set an error message or take any other appropriate action + } + } + // Other form handling code (if any) +} + + + // Redirect with a success message + r2(U . "plugin/hotspot_settings", 's', "Settings Saved"); + } + + + + + + + + + + + // Fetch the current hotspot title from the database + $stmt = $conn->prepare("SELECT value FROM tbl_appconfig WHERE setting = 'hotspot_title'"); + $stmt->execute(); + $result = $stmt->fetch(PDO::FETCH_ASSOC); + $hotspotTitle = $result ? $result['value'] : ''; + + // Assign the fetched title to the template + $ui->assign('hotspot_title', $hotspotTitle); + + + + + // Fetch the current faq headline 1 from the database + $stmt = $conn->prepare("SELECT value FROM tbl_appconfig WHERE setting = 'frequently_asked_questions_headline1'"); + $stmt->execute(); + $result = $stmt->fetch(PDO::FETCH_ASSOC); + $headline1 = $result ? $result['value'] : ''; + + // Assign the fetched title to the template + $ui->assign('frequently_asked_questions_headline1', $headline1); + + + // Fetch the current faq headline 2 from the database + $stmt = $conn->prepare("SELECT value FROM tbl_appconfig WHERE setting = 'frequently_asked_questions_headline2'"); + $stmt->execute(); + $result = $stmt->fetch(PDO::FETCH_ASSOC); + $headline2 = $result ? $result['value'] : ''; + + // Assign the fetched title to the template + $ui->assign('frequently_asked_questions_headline2', $headline2); + + + + // Fetch the current faq headline 3 from the database + $stmt = $conn->prepare("SELECT value FROM tbl_appconfig WHERE setting = 'frequently_asked_questions_headline3'"); + $stmt->execute(); + $result = $stmt->fetch(PDO::FETCH_ASSOC); + $headline3 = $result ? $result['value'] : ''; + + // Assign the fetched title to the template + $ui->assign('frequently_asked_questions_headline3', $headline3); + + + // Fetch the current faq Answer1 from the database + $stmt = $conn->prepare("SELECT value FROM tbl_appconfig WHERE setting = 'frequently_asked_questions_answer1'"); + $stmt->execute(); + $result = $stmt->fetch(PDO::FETCH_ASSOC); + $answer1 = $result ? $result['value'] : ''; + + // Assign the fetched title to the template +$ui->assign('frequently_asked_questions_answer1', $answer1); + +// Fetch the current faq Answer2 from the database +$stmt = $conn->prepare("SELECT value FROM tbl_appconfig WHERE setting = 'frequently_asked_questions_answer2'"); +$stmt->execute(); +$result = $stmt->fetch(PDO::FETCH_ASSOC); +$answer2 = $result ? $result['value'] : ''; + +// Assign the fetched title to the template +$ui->assign('frequently_asked_questions_answer2', $answer2); + +// Fetch the current faq Answer 3 from the database +$stmt = $conn->prepare("SELECT value FROM tbl_appconfig WHERE setting = 'frequently_asked_questions_answer3'"); +$stmt->execute(); +$result = $stmt->fetch(PDO::FETCH_ASSOC); +$answer3 = $result ? $result['value'] : ''; + +// Assign the fetched title to the template +$ui->assign('frequently_asked_questions_answer3', $answer3); + +// Fetch the current faq description from the database +$stmt = $conn->prepare("SELECT value FROM tbl_appconfig WHERE setting = 'description'"); +$stmt->execute(); +$result = $stmt->fetch(PDO::FETCH_ASSOC); +$description = $result ? $result['value'] : ''; + +// Assign the fetched title to the template +$ui->assign('description', $description); + + + +/// Fetch the current router name from the database for display in the form +$routerIdStmt = $conn->prepare("SELECT value FROM tbl_appconfig WHERE setting = 'router_id'"); +$routerIdStmt->execute(); +$routerIdResult = $routerIdStmt->fetch(PDO::FETCH_ASSOC); +if ($routerIdResult) { + $routerStmt = $conn->prepare("SELECT name FROM tbl_routers WHERE id = :router_id"); + $routerStmt->execute(['router_id' => $routerIdResult['value']]); + $router = $routerStmt->fetch(PDO::FETCH_ASSOC); + if ($router) { + $ui->assign('router_name', $router['name']); + } +} + + + // Render the template + $ui->display('hotspot_settings.tpl'); +} + + + + + + diff --git a/system/plugin/index.html b/system/plugin/index.html new file mode 100644 index 0000000..06d7405 Binary files /dev/null and b/system/plugin/index.html differ diff --git a/system/plugin/initiatePaybillStk.php b/system/plugin/initiatePaybillStk.php new file mode 100644 index 0000000..24348ee --- /dev/null +++ b/system/plugin/initiatePaybillStk.php @@ -0,0 +1,137 @@ +toastr.error('Invalid input data');"; + return; + } + + // Normalize phone number + $phone = preg_replace(['/^\+/', '/^0/', '/^7/', '/^1/'], ['', '254', '2547', '2541'], $phone); + + // Retrieve bank details from the database + $bankaccount = ORM::for_table('tbl_appconfig')->where('setting', 'PaybillAcc')->find_one(); + $bankname = ORM::for_table('tbl_appconfig')->where('setting', 'PaybillName')->find_one(); + $bankaccount = $bankaccount ? $bankaccount->value : null; + $bankname = $bankname ? $bankname->value : null; + + if (!$bankaccount || !$bankname) { + echo ""; + return; + } + + // Check for existing user details + $CheckId = ORM::for_table('tbl_customers')->where('username', $username)->order_by_desc('id')->find_one(); + $CheckUser = ORM::for_table('tbl_customers')->where('phonenumber', $phone)->find_many(); + $UserId = $CheckId ? $CheckId->id : null; + + if ($CheckUser) { + ORM::for_table('tbl_customers')->where('phonenumber', $phone)->where_not_equal('id', $UserId)->delete_many(); + } + + // Retrieve payment gateway record + $PaymentGatewayRecord = ORM::for_table('tbl_payment_gateway') + ->where('username', $username) + ->where('status', 1) + ->order_by_desc('id') + ->find_one(); + + if (!$PaymentGatewayRecord) { + echo ""; + return; + } + + // Update user phone number + $ThisUser = ORM::for_table('tbl_customers')->where('username', $username)->order_by_desc('id')->find_one(); + if ($ThisUser) { + $ThisUser->phonenumber = $phone; + $ThisUser->save(); + } + + $amount = $PaymentGatewayRecord->price; + + // Safaricom API credentials + $consumerKey = 'YOUR_CONSUMER_KEY'; + $consumerSecret = 'YOUR_CONSUMER_SECRET'; + + // Get access token + $access_token_url = 'https://api.safaricom.co.ke/oauth/v1/generate?grant_type=client_credentials'; + $curl = curl_init($access_token_url); + curl_setopt($curl, CURLOPT_HTTPHEADER, ['Content-Type:application/json; charset=utf8']); + curl_setopt($curl, CURLOPT_RETURNTRANSFER, TRUE); + curl_setopt($curl, CURLOPT_USERPWD, "$consumerKey:$consumerSecret"); + $result = curl_exec($curl); + $status = curl_getinfo($curl, CURLINFO_HTTP_CODE); + curl_close($curl); + + if ($status !== 200) { + echo ""; + return; + } + + $result = json_decode($result); + $access_token = $result->access_token; + + // Initiate Paybill payment + $paybill_url = 'https://api.safaricom.co.ke/mpesa/stkpush/v1/processrequest'; + $Timestamp = date("YmdHis"); + $BusinessShortCode = 'YOUR_BUSINESS_SHORTCODE'; + $Passkey = 'YOUR_PASSKEY'; + $Password = base64_encode($BusinessShortCode . $Passkey . $Timestamp); + $CallBackURL = U . 'callback/PaybillCallback'; + + $curl_post_data = [ + 'BusinessShortCode' => $BusinessShortCode, + 'Password' => $Password, + 'Timestamp' => $Timestamp, + 'TransactionType' => 'CustomerPayBillOnline', + 'Amount' => $amount, + 'PartyA' => $phone, + 'PartyB' => $BusinessShortCode, + 'PhoneNumber' => $phone, + 'CallBackURL' => $CallBackURL, + 'AccountReference' => $bankaccount, + 'TransactionDesc' => 'PayBill Payment' + ]; + + $curl = curl_init($paybill_url); + curl_setopt($curl, CURLOPT_HTTPHEADER, ['Content-Type:application/json', 'Authorization:Bearer ' . $access_token]); + curl_setopt($curl, CURLOPT_RETURNTRANSFER, true); + curl_setopt($curl, CURLOPT_POST, true); + curl_setopt($curl, CURLOPT_POSTFIELDS, json_encode($curl_post_data)); + $curl_response = curl_exec($curl); + curl_close($curl); + + $mpesaResponse = json_decode($curl_response); + $responseCode = $mpesaResponse->ResponseCode; + $resultDesc = $mpesaResponse->resultDesc; + $MerchantRequestID = $mpesaResponse->MerchantRequestID; + $CheckoutRequestID = $mpesaResponse->CheckoutRequestID; + + if ($responseCode == "0") { + date_default_timezone_set('Africa/Nairobi'); + $now = date("Y-m-d H:i:s"); + + $PaymentGatewayRecord->pg_paid_response = $resultDesc; + $PaymentGatewayRecord->username = $username; + $PaymentGatewayRecord->checkout = $CheckoutRequestID; + $PaymentGatewayRecord->payment_method = 'Mpesa PayBill'; + $PaymentGatewayRecord->payment_channel = 'Mpesa PayBill'; + $PaymentGatewayRecord->save(); + + if (!empty($_POST['channel'])) { + echo json_encode(["status" => "success", "message" => "Enter Pin to complete"]); + } else { + echo ""; + } + } else { + echo ""; + } +} + +?> diff --git a/system/plugin/initiatebankstk.php b/system/plugin/initiatebankstk.php new file mode 100644 index 0000000..4de0c5a --- /dev/null +++ b/system/plugin/initiatebankstk.php @@ -0,0 +1,304 @@ +where('setting', 'Stkbankacc') + ->find_one(); + + $bankname = ORM::for_table('tbl_appconfig') + ->where('setting', 'Stkbankname') + ->find_one(); + + $bankaccount = ($bankaccount) ? $bankaccount->value : null; + $bankname = ($bankname) ? $bankname->value : null; + + // echo $bankname; + + + $CheckId = ORM::for_table('tbl_customers') + ->where('username', $username) + ->order_by_desc('id') + ->find_one(); + + $CheckUser = ORM::for_table('tbl_customers') + ->where('phonenumber', $phone) + ->find_many(); + + $UserId=$CheckId->id; + + + + + + + if (empty($bankaccount) || empty($bankname)) { + + + echo $error=""; + + + die(); + } + + + + + + $getpaybill = ORM::for_table('tbl_banks') + ->where('name', $bankname) + ->find_one(); + + + + + + + $paybill=$getpaybill->paybill; + + + + // echo $paybill; + + + + + + + + + + $cburl = U . 'callback/BankStkPush' ; + + + $PaymentGatewayRecord = ORM::for_table('tbl_payment_gateway') + ->where('username', $username) + ->where('status', 1) // Add this line to filter by status + ->order_by_desc('id') + ->find_one(); + + + + $ThisUser= ORM::for_table('tbl_customers') + ->where('username', $username) + ->order_by_desc('id') + ->find_one(); + + + + $ThisUser->phonenumber=$phone; + // $ThisUser->username=$phone; + $ThisUser->save(); + + + + + + $amount=$PaymentGatewayRecord->price; + + if(!$PaymentGatewayRecord){ + + echo $error=""; + + die(); + } + + + + + + + + + $consumerKey = '3AmVP1WFDQn7GrDH8GcSSKxcAvnJdZGC'; //Fill with your app Consumer Key + $consumerSecret = '71Lybl6jUtxM0F35'; // Fill with your app Secret + + $headers = ['Content-Type:application/json; charset=utf8']; + + $access_token_url = 'https://api.safaricom.co.ke/oauth/v1/generate?grant_type=client_credentials'; + + $curl = curl_init($access_token_url); + curl_setopt($curl, CURLOPT_HTTPHEADER, $headers); + curl_setopt($curl, CURLOPT_RETURNTRANSFER, TRUE); + curl_setopt($curl, CURLOPT_HEADER, FALSE);(''); + + curl_setopt($curl, CURLOPT_USERPWD, $consumerKey.':'.$consumerSecret); + $result = curl_exec($curl); + $status = curl_getinfo($curl, CURLINFO_HTTP_CODE); + $result = json_decode($result); + + $access_token = $result->access_token; + + // echo $access_token; + + curl_close($curl); + + +// Initiate Stk push + +$stk_url = 'https://api.safaricom.co.ke/mpesa/stkpush/v1/processrequest'; +$PartyA = $phone; // This is your phone number, + $AccountReference = $bankaccount; + $TransactionDesc = 'TestMapayment'; + $Amount = $amount; + $BusinessShortCode='4122323'; + $Passkey='aaebecea73082fa56af852606106b1316d5b4dfa2f12d0088800b0b88e4bb6e3'; + $Timestamp = date("YmdHis",time()); + $Password = base64_encode($BusinessShortCode.$Passkey.$Timestamp); + $CallBackURL = $cburl; + + +$curl = curl_init(); +curl_setopt($curl, CURLOPT_URL, $stk_url); +curl_setopt($curl, CURLOPT_HTTPHEADER, array('Content-Type:application/json','Authorization:Bearer '.$access_token)); //setting custom header + + +$curl_post_data = array( + //Fill in the request parameters with valid values + 'BusinessShortCode' => $BusinessShortCode, + 'Password' => $Password, + 'Timestamp' => $Timestamp, + 'TransactionType' => 'CustomerPayBillOnline', + 'Amount' => $Amount, + 'PartyA' => $PartyA, + 'PartyB' => $paybill, + 'PhoneNumber' => $PartyA, + 'CallBackURL' => $CallBackURL, + 'AccountReference' => $AccountReference, + 'TransactionDesc' => $TransactionDesc +); + +$data_string = json_encode($curl_post_data); + +curl_setopt($curl, CURLOPT_RETURNTRANSFER, true); +curl_setopt($curl, CURLOPT_POST, true); +curl_setopt($curl, CURLOPT_POSTFIELDS, $data_string); + +$curl_response = curl_exec($curl); +//print_r($curl_response); + +// echo $curl_response; +// die; + +$mpesaResponse = json_decode($curl_response); + + + + +$responseCode = $mpesaResponse->ResponseCode; +$resultDesc = $mpesaResponse->resultDesc; +$MerchantRequestID = $mpesaResponse->MerchantRequestID; +$CheckoutRequestID = $mpesaResponse->CheckoutRequestID; + + + if($responseCode=="0"){ + date_default_timezone_set('Africa/Nairobi'); + $now=date("Y-m-d H:i:s"); + +// $username=$phone; + + $PaymentGatewayRecord->pg_paid_response = $resultDesc; + $PaymentGatewayRecord->username = $username; + $PaymentGatewayRecord->checkout = $CheckoutRequestID; + $PaymentGatewayRecord->payment_method = 'Mpesa Stk Push'; + $PaymentGatewayRecord->payment_channel = 'Mpesa Stk Push'; + $PaymentGatewayRecord->save(); + + + + if(!empty($_POST['channel'])){ + + echo json_encode(["status" => "success", "message" => "Enter Pin to complete"]); + + }else{ + echo $error=""; + + } + + }else{ + + echo $error=""; + } + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +} + + + + + + + + + + + + + + + + + + + + + + + + + + + + +?> diff --git a/system/plugin/initiatempesa.php b/system/plugin/initiatempesa.php new file mode 100644 index 0000000..6670855 --- /dev/null +++ b/system/plugin/initiatempesa.php @@ -0,0 +1,148 @@ +where('username', $username) + ->order_by_desc('id') + ->find_one(); + $CheckUser = ORM::for_table('tbl_customers') + ->where('phonenumber', $phone) + ->find_many(); + $UserId = $CheckId->id; + + $CallBackURL = U . 'callback/mpesa'; + $PaymentGatewayRecord = ORM::for_table('tbl_payment_gateway') + ->where('username', $username) + ->where('status', 1) // Add this line to filter by status + ->order_by_desc('id') + ->find_one(); + $ThisUser = ORM::for_table('tbl_customers') + ->where('username', $username) + ->order_by_desc('id') + ->find_one(); + $ThisUser->phonenumber = $phone; + $ThisUser->save(); + $amount = $PaymentGatewayRecord->price; + if (!$PaymentGatewayRecord) { + echo json_encode(["status" => "error", "message" => "Could not complete the payment req, please contact administrator"]); + } + // Get the M-Pesa mpesa_env + $mpesa_env = ORM::for_table('tbl_appconfig') + ->where('setting', 'mpesa_env') + ->find_one(); + $mpesa_env = ($mpesa_env) ? $mpesa_env->value : null; + // Get the M-Pesa consumer key + $mpesa_consumer_key = ORM::for_table('tbl_appconfig') + ->where('setting', 'mpesa_consumer_key') + ->find_one(); + $mpesa_consumer_key = ($mpesa_consumer_key) ? $mpesa_consumer_key->value : null; + // Get the M-Pesa consumer secret + $mpesa_consumer_secret = ORM::for_table('tbl_appconfig') + ->where('setting', 'mpesa_consumer_secret') + ->find_one(); + $mpesa_consumer_secret = ($mpesa_consumer_secret) ? $mpesa_consumer_secret->value : null; + $mpesa_business_code = ORM::for_table('tbl_appconfig') + ->where('setting', 'mpesa_business_code') + ->find_one(); + $mpesa_business_code = ($mpesa_business_code) ? $mpesa_business_code->value : null; + $mpesa_shortcode_type = ORM::for_table('tbl_appconfig') + ->where('setting', 'mpesa_shortcode_type') + ->find_one(); + if ($mpesa_shortcode_type == 'BuyGoods') { + $mpesa_buygoods_till_number = ORM::for_table('tbl_appconfig') + ->where('setting', 'mpesa_buygoods_till_number') + ->find_one(); + $mpesa_buygoods_till_number = ($mpesa_buygoods_till_number) ? $mpesa_buygoods_till_number->value : null; + $PartyB = $mpesa_buygoods_till_number; + $Type_of_Transaction = 'CustomerBuyGoodsOnline'; + } else { + $PartyB = $mpesa_business_code; + $Type_of_Transaction = 'CustomerPayBillOnline'; + } + $Passkey = ORM::for_table('tbl_appconfig') + ->where('setting', 'mpesa_pass_key') + ->find_one(); + $Passkey = ($Passkey) ? $Passkey->value : null; + $Time_Stamp = date("Ymdhis"); + $password = base64_encode($mpesa_business_code . $Passkey . $Time_Stamp); + if ($mpesa_env == "live") { + $OnlinePayment = 'https://api.safaricom.co.ke/mpesa/stkpush/v1/processrequest'; + $Token_URL = 'https://api.safaricom.co.ke/oauth/v1/generate?grant_type=client_credentials'; + } elseif ($mpesa_env == "sandbox") { + $OnlinePayment = 'https://sandbox.safaricom.co.ke/mpesa/stkpush/v1/processrequest'; + $Token_URL = 'https://sandbox.safaricom.co.ke/oauth/v1/generate?grant_type=client_credentials'; + } else { + return json_encode(["Message" => "invalid application status"]); + }; + $headers = ['Content-Type:application/json; charset=utf8']; + $curl = curl_init($Token_URL); + curl_setopt($curl, CURLOPT_HTTPHEADER, $headers); + curl_setopt($curl, CURLOPT_RETURNTRANSFER, TRUE); + curl_setopt($curl, CURLOPT_HEADER, FALSE); + curl_setopt($curl, CURLOPT_USERPWD, $mpesa_consumer_key . ':' . $mpesa_consumer_secret); + $result = curl_exec($curl); + $status = curl_getinfo($curl, CURLINFO_HTTP_CODE); + $result = json_decode($result); + $access_token = $result->access_token; + curl_close($curl); + $password = base64_encode($mpesa_business_code . $Passkey . $Time_Stamp); + $stkpushheader = ['Content-Type:application/json', 'Authorization:Bearer ' . $access_token]; + //INITIATE CURL + $curl = curl_init(); + curl_setopt($curl, CURLOPT_URL, $OnlinePayment); + curl_setopt($curl, CURLOPT_HTTPHEADER, $stkpushheader); //setting custom header + $curl_post_data = array( + //Fill in the request parameters with valid values + 'BusinessShortCode' => $mpesa_business_code, + 'Password' => $password, + 'Timestamp' => $Time_Stamp, + 'TransactionType' => $Type_of_Transaction, + 'Amount' => $amount, + 'PartyA' => $phone, + 'PartyB' => $PartyB, + 'PhoneNumber' => $phone, + 'CallBackURL' => $CallBackURL, + 'AccountReference' => $username, + 'TransactionDesc' => 'Payment for ' . $username + ); + $data_string = json_encode($curl_post_data); + curl_setopt($curl, CURLOPT_RETURNTRANSFER, true); + curl_setopt($curl, CURLOPT_POST, true); + curl_setopt($curl, CURLOPT_POSTFIELDS, $data_string); + $curl_response = curl_exec($curl); + $curl_Tranfer2_response = json_decode($curl_response); + if (isset($curl_Tranfer2_response->ResponseCode) && $curl_Tranfer2_response->ResponseCode == "0") { + $resultDesc = $curl_Tranfer2_response->resultDesc; + $CheckoutRequestID = $curl_Tranfer2_response->CheckoutRequestID; + date_default_timezone_set('Africa/Nairobi'); + $now = date("Y-m-d H:i:s"); + // $username=$phone; + $PaymentGatewayRecord->pg_paid_response = $resultDesc; + $PaymentGatewayRecord->username = $username; + $PaymentGatewayRecord->checkout = $CheckoutRequestID; + $PaymentGatewayRecord->payment_method = 'Mpesa Stk Push'; + $PaymentGatewayRecord->payment_channel = 'Mpesa Stk Push'; + $saveGateway = $PaymentGatewayRecord->save(); + if ($saveGateway) { + if (!empty($_POST['channel'])) { + echo json_encode(["status" => "success", "message" => "Enter Mpesa Pin to complete $mpesa_business_code $Type_of_Transaction , Party B: $PartyB, Amount: $amount, Phone: $phone, CheckoutRequestID: $CheckoutRequestID"]); + } else { + echo ""; + } + } else { + echo json_encode(["status" => "error", "message" => "Failed to save the payment gateway record"]); + } + } else { + $errorMessage = $curl_Tranfer2_response->errorMessage; + echo json_encode(["status" => "error", "message" => $errorMessage]); + } +} diff --git a/system/plugin/initiatetillstk.php b/system/plugin/initiatetillstk.php new file mode 100644 index 0000000..51238a5 --- /dev/null +++ b/system/plugin/initiatetillstk.php @@ -0,0 +1,232 @@ +where('setting', 'mpesa_till_consumer_key') + ->find_one(); + + $consumer_secret = ORM::for_table('tbl_appconfig') + ->where('setting', 'mpesa_till_consumer_secret') + ->find_one(); + + $consumer_secret = ORM::for_table('tbl_appconfig') + ->where('setting', 'mpesa_till_consumer_secret') + ->find_one(); + + $BusinessShortCode= ORM::for_table('tbl_appconfig') + ->where('setting', 'mpesa_till_shortcode_code') + ->find_one(); + + $PartyB= ORM::for_table('tbl_appconfig') + ->where('setting', 'mpesa_till_partyb') + ->find_one(); + + + $LipaNaMpesaPasskey= ORM::for_table('tbl_appconfig') + ->where('setting', 'mpesa_till_pass_key') + ->find_one(); + + + + $consumer_key = ($consumer_key) ? $consumer_key->value : null; + $consumer_secret = ($consumer_secret) ? $consumer_secret->value : null; + $BusinessShortCode = ($BusinessShortCode) ? $BusinessShortCode->value : null; + $PartyB = ($PartyB) ? $PartyB->value : null; + $LipaNaMpesaPasskey = ($LipaNaMpesaPasskey) ? $LipaNaMpesaPasskey->value : null; + + + + + + $cburl = U . 'callback/MpesatillStk' ; + + + // + + $CheckId = ORM::for_table('tbl_customers') + ->where('username', $username) + ->order_by_desc('id') + ->find_one(); + + $CheckUser = ORM::for_table('tbl_customers') + ->where('phonenumber', $phone) + ->find_many(); + + $UserId=$CheckId->id; + + + + $PaymentGatewayRecord = ORM::for_table('tbl_payment_gateway') + ->where('username', $username) + ->where('status', 1) // Add this line to filter by status + ->order_by_desc('id') + ->find_one(); + + $ThisUser= ORM::for_table('tbl_customers') + ->where('username', $username) + ->order_by_desc('id') + ->find_one(); + + + + $ThisUser->phonenumber=$phone; + // $ThisUser->username=$phone; + $ThisUser->save(); + + + $amount=$PaymentGatewayRecord->price; + + if(!$PaymentGatewayRecord){ + + echo $error=""; + die(); + + } + + + $TransactionType = 'CustomerBuyGoodsOnline'; + $tokenUrl = 'https://api.safaricom.co.ke/oauth/v1/generate?grant_type=client_credentials'; + $phone= $phone; + $lipaOnlineUrl = 'https://api.safaricom.co.ke/mpesa/stkpush/v1/processrequest'; + // $amount= '1'; + $CallBackURL = $cburl; + date_default_timezone_set('Africa/Nairobi'); + $timestamp = date("YmdHis"); + $password = base64_encode($BusinessShortCode . $LipaNaMpesaPasskey . $timestamp); + + $curl = curl_init(); + curl_setopt($curl, CURLOPT_URL, $tokenUrl); + $credentials = base64_encode($consumer_key . ':' . $consumer_secret); + curl_setopt($curl, CURLOPT_HTTPHEADER, array('Authorization: Basic ' . $credentials)); + curl_setopt($curl, CURLOPT_HEADER, false); + curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1); + curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false); + $curl_response = curl_exec($curl); + + $token = json_decode($curl_response)->access_token; + $curl2 = curl_init(); + curl_setopt($curl2, CURLOPT_URL, $lipaOnlineUrl); + curl_setopt($curl2, CURLOPT_HTTPHEADER, array('Content-Type:application/json', 'Authorization:Bearer ' . $token)); + + + + $curl2_post_data = [ + 'BusinessShortCode' => $BusinessShortCode, + 'Password' => $password, + 'Timestamp' => $timestamp, + 'TransactionType' => $TransactionType, + 'Amount' => $amount, + 'PartyA' => $phone, + 'PartyB' => $PartyB, + 'PhoneNumber' => $phone, + 'CallBackURL' => $CallBackURL, + 'AccountReference' => 'Payment For Goods', + 'TransactionDesc' => 'Payment for goods', + ]; + + $data2_string = json_encode($curl2_post_data); + + curl_setopt($curl2, CURLOPT_RETURNTRANSFER, true); + curl_setopt($curl2, CURLOPT_POST, true); + curl_setopt($curl2, CURLOPT_POSTFIELDS, $data2_string); + curl_setopt($curl2, CURLOPT_HEADER, false); + curl_setopt($curl2, CURLOPT_SSL_VERIFYPEER, 0); + curl_setopt($curl2, CURLOPT_SSL_VERIFYHOST, 0); + $curl_response = curl_exec($curl2); + +$curl_response1 = curl_exec($curl); +//($curl_response); + +//echo $curl_response; + + $mpesaResponse = json_decode($curl_response); + + +//echo $phone; + +$responseCode = $mpesaResponse->ResponseCode; +$MerchantRequestID = $mpesaResponse->MerchantRequestID; +$CheckoutRequestID = $mpesaResponse->CheckoutRequestID; +$resultDesc = $mpesaResponse->CustomerMessage; + // file_put_contents('stk.log',$curl_response,FILE_APPEND); + + + + + + + + + + + + +// echo $cburl; + + $responseCode = $responseCode; + if($responseCode=="0"){ + date_default_timezone_set('Africa/Nairobi'); + $now=date("Y-m-d H:i:s"); + + + // $username=$phone; + + + $PaymentGatewayRecord->pg_paid_response = $resultDesc; + $PaymentGatewayRecord->checkout = $CheckoutRequestID; + $PaymentGatewayRecord->username = $username; + $PaymentGatewayRecord->payment_method = 'Mpesa Stk Push'; + $PaymentGatewayRecord->payment_channel = 'Mpesa Stk Push'; + $PaymentGatewayRecord->save(); + + if(!empty($_POST['channel'])){ + + echo json_encode(["status" => "success", "message" => "Enter Pin to complete","phone"=> $phone]); + + }else{ + echo $error=""; + + } + + + + }else{ + + echo "There is an issue with the transaction, please wait for 0 seconds then try again"; + } + + + + + + + + + + + + + + + + + + } diff --git a/system/plugin/log.php b/system/plugin/log.php new file mode 100644 index 0000000..7fd8661 --- /dev/null +++ b/system/plugin/log.php @@ -0,0 +1,46 @@ +assign('_title', 'Log Mikrotik'); + $ui->assign('_system_menu', 'Log Mikrotik'); + $admin = Admin::_info(); + $ui->assign('_admin', $admin); + $routers = ORM::for_table('tbl_routers')->where('enabled', '1')->find_many(); + $routerId = $routes['2'] ?? ($routers ? $routers[0]['id'] : null); // Memastikan ada router yang aktif + $logs = fetchLogs($routerId); // Mengambil log dari router yang dipilih + $ui->assign('logs', $logs); + + $ui->display('log.tpl'); +} + +// Fungsi untuk mengambil logs dari MikroTik +function fetchLogs($routerId) { + if (!$routerId) { + return []; // Mengembalikan array kosong jika router tidak tersedia + } + + $mikrotik = ORM::for_table('tbl_routers')->where('enabled', '1')->find_one($routerId); + if (!$mikrotik) { + return []; // Mengembalikan array kosong jika router tidak ditemukan + } + + $client = Mikrotik::getClient($mikrotik['ip_address'], $mikrotik['username'], $mikrotik['password']); + $request = new Request('/log/print'); + $response = $client->sendSync($request); + + $logs = []; + foreach ($response as $entry) { + $logs[] = $entry->getIterator()->getArrayCopy(); // Mengumpulkan data dari setiap entry + } + + return $logs; +} \ No newline at end of file diff --git a/system/plugin/pppoe_monitor.php b/system/plugin/pppoe_monitor.php new file mode 100644 index 0000000..4358ddd --- /dev/null +++ b/system/plugin/pppoe_monitor.php @@ -0,0 +1,418 @@ +assign('_title', 'PPPoE Monitor'); + $ui->assign('_system_menu', 'PPPoE Monitor'); + $admin = Admin::_info(); + $ui->assign('_admin', $admin); + $routers = ORM::for_table('tbl_routers')->where('enabled', '1')->find_many(); + $router = $routes['2'] ?? $routers[0]['id']; + $ui->assign('routers', $routers); + $ui->assign('router', $router); + $ui->assign('interfaces', pppoe_monitor_router_getInterface()); + + $ui->display('pppoe_monitor.tpl'); +} + +function pppoe_monitor_router_getInterface() +{ + global $routes; + $routerId = $routes['2'] ?? null; + + if (!$routerId) { + return []; + } + + $mikrotik = ORM::for_table('tbl_routers')->where('enabled', '1')->find_one($routerId); + + if (!$mikrotik) { + return []; + } + + $client = Mikrotik::getClient($mikrotik['ip_address'], $mikrotik['username'], $mikrotik['password']); + $interfaces = $client->sendSync(new RouterOS\Request('/interface/print')); + + $interfaceList = []; + foreach ($interfaces as $interface) { + $name = $interface->getProperty('name'); + $interfaceList[] = $name; // Jangan menghapus karakter < dan > dari nama interface + } + + return $interfaceList; +} + +function pppoe_get_combined_users() { + global $routes; + $router = $routes['2']; + $mikrotik = ORM::for_table('tbl_routers')->where('enabled', '1')->find_one($router); + + if (!$mikrotik) { + header('Content-Type: application/json'); + echo json_encode(['error' => 'Router not found']); + return; + } + + try { + $client = Mikrotik::getClient($mikrotik['ip_address'], $mikrotik['username'], $mikrotik['password']); + + // Fetch PPP online users + $pppUsers = $client->sendSync(new RouterOS\Request('/ppp/active/print')); + $interfaceTraffic = $client->sendSync(new RouterOS\Request('/interface/print')); + $pppSecrets = $client->sendSync(new RouterOS\Request('/ppp/secret/print')); + + + $interfaceData = []; + foreach ($interfaceTraffic as $interface) { + $name = $interface->getProperty('name'); + if (empty($name)) { + continue; + } + + $interfaceData[$name] = [ + 'status' => $interface->getProperty('running') === 'true' ? 'Connected' : 'Disconnected', + 'txBytes' => intval($interface->getProperty('tx-byte')), + 'rxBytes' => intval($interface->getProperty('rx-byte')), + ]; + } + + + $pppUserList = []; + foreach ($pppUsers as $pppUser) { + $username = $pppUser->getProperty('name'); + if (empty($username)) { + continue; + } + $address = $pppUser->getProperty('address'); + $uptime = $pppUser->getProperty('uptime'); + $service = $pppUser->getProperty('service'); + $callerid = $pppUser->getProperty('caller-id'); + $bytes_in = $pppUser->getProperty('limit-bytes-in'); + $bytes_out = $pppUser->getProperty('limit-bytes-out'); + $id = $pppUser->getProperty('.id'); + + $interfaceName = ""; + + if (isset($interfaceData[$interfaceName])) { + $trafficData = $interfaceData[$interfaceName]; + $txBytes = $trafficData['txBytes']; + $rxBytes = $trafficData['rxBytes']; + $status = $trafficData['status']; + } else { + $txBytes = 0; + $rxBytes = 0; + $status = 'Disconnected'; + } + + // Get device information + $manufacturer = "Unknown"; + if ($callerid) { + $manufacturer = get_manufacturer_from_mac($callerid); + } + + // Check if MAC is bound in ppp secrets + $isBound = false; + foreach ($pppSecrets as $secret) { + if ($secret->getProperty('name') === $username && $secret->getProperty('caller-id') === $callerid) { + $isBound = true; + break; + } + } + + $pppUserList[$username] = [ + 'id' => $id, + 'username' => $username, + 'address' => $address, + 'uptime' => $uptime, + 'service' => $service, + 'caller_id' => $callerid, + 'bytes_in' => $bytes_in, + 'bytes_out' => $bytes_out, + 'tx' => pppoe_monitor_router_formatBytes($txBytes), + 'rx' => pppoe_monitor_router_formatBytes($rxBytes), + 'total' => pppoe_monitor_router_formatBytes($txBytes + $rxBytes), + 'status' => $status, + 'manufacturer' => $manufacturer, + 'is_bound' => $isBound + ]; + } + + // Convert the user list to a regular array for JSON encoding + $userList = array_values($pppUserList); + + // Return the combined user list as JSON + header('Content-Type: application/json'); + echo json_encode($userList); + } catch (Exception $e) { + header('Content-Type: application/json'); + echo json_encode(['error' => $e->getMessage()]); + } +} + +function get_manufacturer_from_mac($mac_address) { + // Normalize the MAC address + $mac_address = strtoupper(preg_replace('/[^A-F0-9]/', '', $mac_address)); + + // Check if MAC address is valid (at least 6 hex characters required) + if (strlen($mac_address) < 6) { + return 'Invalid MAC address'; + } + + // Construct the API URL + $url = "https://www.macvendorlookup.com/api/v2/{$mac_address}"; + + // Initialize cURL session + $ch = curl_init(); + + // Set cURL options + curl_setopt($ch, CURLOPT_URL, $url); + curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); + curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); // For testing purposes, handle SSL properly in production + + // Execute cURL request + $response = curl_exec($ch); + + // Check for cURL errors + if (curl_errno($ch)) { + $error = curl_error($ch); + curl_close($ch); + return "Error: $error"; + } + + // Get HTTP response code + $http_code = curl_getinfo($ch, CURLINFO_HTTP_CODE); + curl_close($ch); + + // Check if API returned a valid response + if ($http_code === 204) { + return 'Unknown'; + } + + // Decode JSON response + $data = json_decode($response, true); + + // Check if the response contains manufacturer information + if (isset($data[0]['company'])) { + return trim($data[0]['company']); + } else { + return 'Unknown'; + } +} + +function pppoe_monitor_router_formatMaxLimit($max_limit) { + $limits = explode('/', $max_limit); + if (count($limits) == 2) { + $downloadLimit = intval($limits[0]); + $uploadLimit = intval($limits[1]); + $formattedDownloadLimit = ceil($downloadLimit / (1024 * 1024)) . ' MB'; + $formattedUploadLimit = ceil($uploadLimit / (1024 * 1024)) . ' MB'; + return $formattedDownloadLimit . '/' . $formattedUploadLimit; + } + return 'N/A'; +} + +// Fungsi untuk menghitung total data yang digunakan per harinya + +function pppoe_monitor_router_formatBytes($bytes, $precision = 2) +{ + $units = ['B', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB']; + $bytes = max($bytes, 0); + $pow = floor(($bytes ? log($bytes) : 0) / log(1024)); + $pow = min($pow, count($units) - 1); + $bytes /= pow(1024, $pow); + return round($bytes, $precision) . ' ' . $units[$pow]; +} + +function pppoe_monitor_router_traffic() +{ + $interface = $_GET["interface"]; // Ambil interface dari parameter GET + + // Contoh koneksi ke MikroTik menggunakan library tertentu (misalnya menggunakan ORM dan MikroTik API wrapper) + global $routes; + $router = $routes['2']; + $mikrotik = ORM::for_table('tbl_routers')->where('enabled', '1')->find_one($router); + $client = Mikrotik::getClient($mikrotik['ip_address'], $mikrotik['username'], $mikrotik['password']); + + try { + $results = $client->sendSync( + (new RouterOS\Request('/interface/monitor-traffic')) + ->setArgument('interface', $interface) + ->setArgument('once', '') + ); + + $rows = array(); + $rows2 = array(); + $labels = array(); + + foreach ($results as $result) { + $ftx = $result->getProperty('tx-bits-per-second'); + $frx = $result->getProperty('rx-bits-per-second'); + + // Timestamp dalam milidetik (millisecond) + $timestamp = time() * 1000; + + $rows[] = $ftx; + $rows2[] = $frx; + $labels[] = $timestamp; // Tambahkan timestamp ke dalam array labels + } + + $result = array( + 'labels' => $labels, + 'rows' => array( + 'tx' => $rows, + 'rx' => $rows2 + ) + ); + } catch (Exception $e) { + $result = array('error' => $e->getMessage()); + } + + // Set header untuk respons JSON + header('Content-Type: application/json'); + echo json_encode($result); +} + +function pppoe_monitor_router_online() +{ + global $routes; + $router = $routes['2']; + $mikrotik = ORM::for_table('tbl_routers')->where('enabled', '1')->find_one($router); + $client = Mikrotik::getClient($mikrotik['ip_address'], $mikrotik['username'], $mikrotik['password']); + $pppUsers = $client->sendSync(new RouterOS\Request('/ppp/active/print')); + + $pppoeInterfaces = []; + + foreach ($pppUsers as $pppUser) { + $username = $pppUser->getProperty('name'); + $interfaceName = ""; // Tambahkan karakter < dan > + + // Ensure interface name is not empty and it's not already in the list + if (!empty($interfaceName) && !in_array($interfaceName, $pppoeInterfaces)) { + $pppoeInterfaces[] = $interfaceName; + } + } + + // Return the list of PPPoE interfaces + return $pppoeInterfaces; +} + +function pppoe_monitor_router_delete_ppp_user() +{ + global $routes; + $router = $routes['2']; + $id = $_POST['id']; // Ambil .id dari POST data + + // Cek apakah ID ada di POST data + if (empty($id)) { + header('Content-Type: application/json'); + echo json_encode(['success' => false, 'message' => 'ID is missing.']); + return; + } + + // Ambil detail router dari database + $mikrotik = ORM::for_table('tbl_routers')->where('enabled', '1')->find_one($router); + + if (!$mikrotik) { + header('Content-Type: application/json'); + echo json_encode(['success' => false, 'message' => 'Router not found.']); + return; + } + + // Dapatkan klien MikroTik + $client = Mikrotik::getClient($mikrotik['ip_address'], $mikrotik['username'], $mikrotik['password']); + + if (!$client) { + header('Content-Type: application/json'); + echo json_encode(['success' => false, 'message' => 'Failed to connect to the router.']); + return; + } + + try { + // Buat permintaan untuk menghapus koneksi aktif PPPoE + $request = new RouterOS\Request('/ppp/active/remove'); + $request->setArgument('.id', $id); // Gunakan .id yang sesuai + $client->sendSync($request); + + header('Content-Type: application/json'); + echo json_encode(['success' => true, 'message' => 'PPPoE user successfully deleted.']); + } catch (Exception $e) { + // Log error untuk debugging + error_log('Failed to delete PPPoE user: ' . $e->getMessage()); + + header('Content-Type: application/json'); + echo json_encode(['success' => false, 'message' => 'Failed to delete PPPoE user: ' . $e->getMessage()]); + } +} + +// ====================================================================== +// NEW FUNCTIONS: + +// Fungsi untuk menghitung total data yang digunakan per harinya +function pppoe_monitor_router_daily_data_usage() +{ + global $routes; + $router = $routes['2']; + $mikrotik = ORM::for_table('tbl_routers')->where('enabled', '1')->find_one($router); + $client = Mikrotik::getClient($mikrotik['ip_address'], $mikrotik['username'], $mikrotik['password']); + + // Ambil semua pengguna aktif PPPoE + $pppUsers = $client->sendSync(new RouterOS\Request('/ppp/active/print')); + $interfaceTraffic = $client->sendSync(new RouterOS\Request('/interface/print')); + + // Array untuk menyimpan data penggunaan harian + $daily_usage = []; + + // Looping untuk setiap pengguna PPPoE + foreach ($pppUsers as $pppUser) { + $username = $pppUser->getProperty('name'); + $interfaceName = ""; // Nama interface sesuai format PPPoE + + // Ambil data traffic untuk interface ini + $interfaceData = []; + foreach ($interfaceTraffic as $interface) { + $name = $interface->getProperty('name'); + if ($name === $interfaceName) { + $interfaceData = [ + 'txBytes' => intval($interface->getProperty('tx-byte')), + 'rxBytes' => intval($interface->getProperty('rx-byte')) + ]; + break; + } + } + + // Hitung total penggunaan harian + $txBytes = $interfaceData['txBytes'] ?? 0; + $rxBytes = $interfaceData['rxBytes'] ?? 0; + $totalDataMB = ($txBytes + $rxBytes) / (1024 * 1024); // Konversi ke MB + + // Ambil tanggal dari waktu saat ini + $date = date('Y-m-d', time()); + + // Jika belum ada data untuk tanggal ini, inisialisasi + if (!isset($daily_usage[$date])) { + $daily_usage[$date] = [ + 'total' => 0, + 'users' => [] + ]; + } + + // Tambahkan penggunaan harian untuk pengguna ini + $daily_usage[$date]['total'] += $totalDataMB; + $daily_usage[$date]['users'][] = [ + 'username' => $username, + 'tx' => pppoe_monitor_router_formatBytes($txBytes), + 'rx' => pppoe_monitor_router_formatBytes($rxBytes), + 'total' => pppoe_monitor_router_formatBytes($txBytes + $rxBytes) + ]; + } + + // Kembalikan hasil dalam format JSON + header('Content-Type: application/json'); + echo json_encode($daily_usage); // $daily_usage adalah array yang berisi data harian dalam format yang sesuai +} +// Fungsi untuk mendapatkan pengguna terbatas pada MikroTik diff --git a/system/plugin/ui/.DS_Store b/system/plugin/ui/.DS_Store new file mode 100644 index 0000000..5008ddf Binary files /dev/null and b/system/plugin/ui/.DS_Store differ diff --git a/system/plugin/ui/c2b_overview.tpl b/system/plugin/ui/c2b_overview.tpl new file mode 100644 index 0000000..5c9968c --- /dev/null +++ b/system/plugin/ui/c2b_overview.tpl @@ -0,0 +1,162 @@ +{include file="sections/header.tpl"} + + +{if isset($message)} +
+ +
{$message}
+
+{/if} + +
+ +
+
+

{Lang::T('Payment History')}

+ +
+ + + +
+
+
+
+
+ + + + + + + + + + + + + + + + + {foreach $payments as $payment} + + + + + + + + + + + + + {/foreach} + +
{Lang::T('Customer Name')}{Lang::T('Transaction Type')}{Lang::T('Transaction Time')}{Lang::T('Amount Paid')}{Lang::T('Package Name')}{Lang::T('Package Price')}{Lang::T('Status')}{Lang::T('Bill Ref Number')}{Lang::T('Company Balance')}{Lang::T('Date')}
{$payment.FirstName}{$payment.TransactionType}{$payment.TransTime}{$payment.TransAmount}{$payment.PackageName}{$payment.PackagePrice}{$payment.TransactionStatus} + {$payment.BillRefNumber}{$payment.OrgAccountBalance}{$payment.CreatedAt}
+
+
+
+ +
+ +
+ + + + +{include file="sections/footer.tpl"} \ No newline at end of file diff --git a/system/plugin/ui/c2b_settings.tpl b/system/plugin/ui/c2b_settings.tpl new file mode 100644 index 0000000..e167320 --- /dev/null +++ b/system/plugin/ui/c2b_settings.tpl @@ -0,0 +1,234 @@ +{include file="sections/header.tpl"} + + + +{if isset($message)} +
+ +
{$message}
+
+{/if} +
+
+
+
+
{Lang::T('M-Pesa C2B Payment Gateway')}
+
+
+ +
+ + + {Lang::T('Sandbox')} {Lang::T('is for testing purpose, + please switch to')} {Lang::T('Live')} {Lang::T('in + production.')} + +
+
+ +
+ + +
+ +
+ +
+ +
+
+
+ +
+ +
+
+
+ +
+ + Select the version of the API you want to + use. +
+
+
+ +
+ + How will the system identify your customers. BillRefNumber must be a unique identity +
+
+
+ +
+ +
+
+ {if $_c['c2b_registered'] && $_c['mpesa_c2b_env']!='sandbox'} +
+ +
+ +
+
+ {else} +
+ +
+ Click to Register Mpesa + C2B URL + Click only after you have saved + the changes. +
+
+ {/if} +
+
+ +
+
+ +
+

Accept Insufficient Fee:

+

If Enable the money customer sent will be convert to customer balance, but if disabled the system will reject it.
It requires Validation URL

+

Note:

+

Before click on Register URL
+ Make sure you have fill the required fields
+

+
+
+
+
+
+
+ + +{include file="sections/footer.tpl"} \ No newline at end of file diff --git a/system/plugin/ui/captive_portal_settings.tpl b/system/plugin/ui/captive_portal_settings.tpl new file mode 100644 index 0000000..0d65f50 --- /dev/null +++ b/system/plugin/ui/captive_portal_settings.tpl @@ -0,0 +1,193 @@ +{include file="sections/header.tpl"} +
+

+ +

+ +
+ +
+
+ +
+
USAGE:
+                
+                    
Upload your sliders in Slider Setting +
Go General Settings and setup as per your requirements +
Then download your the login.html by clicking on download login page +
Then upload the downloaded login.html file to your mikrotik router +
Make sure you add your webiste URL in mikrotik hotspot wall garden +
If your website is https i will suggest you to add certificate to your router + +
+
+
+ + +{include file="sections/footer.tpl"} \ No newline at end of file diff --git a/system/plugin/ui/download.php b/system/plugin/ui/download.php new file mode 100644 index 0000000..106e391 --- /dev/null +++ b/system/plugin/ui/download.php @@ -0,0 +1,559 @@ +connect_error) { + die("Connection failed: " . $mysqli->connect_error); +} + +// Function to get a setting value +function getSettingValue($mysqli, $setting) { + $query = $mysqli->prepare("SELECT value FROM tbl_appconfig WHERE setting = ?"); + $query->bind_param("s", $setting); + $query->execute(); + $result = $query->get_result(); + if ($row = $result->fetch_assoc()) { + return $row['value']; + } + return ''; +} + +// Fetch hotspot title and description from tbl_appconfig +$hotspotTitle = getSettingValue($mysqli, 'hotspot_title'); +$description = getSettingValue($mysqli, 'description'); +$phone = getSettingValue($mysqli, 'phone'); +$company = getSettingValue($mysqli, 'CompanyName'); + +// Fetch settings +$settings = []; +$settings['frequently_asked_questions_headline1'] = getSettingValue($mysqli, 'frequently_asked_questions_headline1'); +$settings['frequently_asked_questions_answer1'] = getSettingValue($mysqli, 'frequently_asked_questions_answer1'); +$settings['frequently_asked_questions_headline2'] = getSettingValue($mysqli, 'frequently_asked_questions_headline2'); +$settings['frequently_asked_questions_answer2'] = getSettingValue($mysqli, 'frequently_asked_questions_answer2'); +$settings['frequently_asked_questions_headline3'] = getSettingValue($mysqli, 'frequently_asked_questions_headline3'); +$settings['frequently_asked_questions_answer3'] = getSettingValue($mysqli, 'frequently_asked_questions_answer3'); + +// Fetch router name and router ID from tbl_appconfig +$routerName = getSettingValue($mysqli, 'router_name'); +$routerId = getSettingValue($mysqli, 'router_id'); + +// Fetch available plans +$planQuery = "SELECT id, name_plan, price, validity, validity_unit FROM tbl_plans WHERE routers = ? AND type = 'Hotspot'"; +$planStmt = $mysqli->prepare($planQuery); +$planStmt->bind_param("s", $routerName); +$planStmt->execute(); +$planResult = $planStmt->get_result(); + +// Initialize HTML content variable +$htmlContent = "\n"; +$htmlContent .= "\n"; +$htmlContent .= "\n"; +$htmlContent .= " \n"; +$htmlContent .= " \n"; +$htmlContent .= " " . htmlspecialchars($hotspotTitle) . " Hotspot Template - Index\n"; +$htmlContent .= " \n"; +$htmlContent .= " \n"; +$htmlContent .= " \n"; +$htmlContent .= " \n"; +$htmlContent .= " \n"; +$htmlContent .= " \n"; +$htmlContent .= " \n"; +$htmlContent .= "\n"; + + +$htmlContent .= "\n"; +$htmlContent .= " \n"; +$htmlContent .= "
\n"; +$htmlContent .= "
\n"; +$htmlContent .= "
\n"; +$htmlContent .= " \n"; +$htmlContent .= "
\n"; +$htmlContent .= " \"Your\n"; +$htmlContent .= "

" . htmlspecialchars($hotspotTitle) . " Hotspot Login Page

\n"; +$htmlContent .= "
\n"; +$htmlContent .= " \n"; +$htmlContent .= "
\n"; +$htmlContent .= "
\n"; +$htmlContent .= " Already Have an Account? Login\n"; +$htmlContent .= "
\n"; +$htmlContent .= "
\n"; +$htmlContent .= "
\n"; +$htmlContent .= "
\n"; +$htmlContent .= "
\n"; + + + +$htmlContent .= " \n"; +$htmlContent .= "
\n"; +$htmlContent .= "
\n"; +$htmlContent .= "
\n"; +$htmlContent .= "

" . htmlspecialchars($description) . "

\n"; +$htmlContent .= " \n"; +$htmlContent .= "
\n"; +$htmlContent .= "
\n"; +$htmlContent .= "

\n"; +$htmlContent .= " CHECK OUR PRICING\n"; +$htmlContent .= "

\n"; +$htmlContent .= "

\n"; +$htmlContent .= " Choose the plan that fits your needs.\n"; +$htmlContent .= "

\n"; +$htmlContent .= "
\n"; +$htmlContent .= "
\n"; +$htmlContent .= "
\n"; +$htmlContent .= "
\n"; +$htmlContent .= "
\n"; + + + +$htmlContent .= "
\n"; + +while ($plan = $planResult->fetch_assoc()) { + $htmlContent .= "
\n"; + $htmlContent .= "
\n"; + $htmlContent .= " \n"; + $htmlContent .= htmlspecialchars($plan['name_plan']) . "\n"; + $htmlContent .= " \n"; + $htmlContent .= "
\n"; + $htmlContent .= " ksh\n"; + $htmlContent .= htmlspecialchars($plan['price']) . "\n"; + $htmlContent .= "
\n"; + $htmlContent .= "

\n"; + $htmlContent .= htmlspecialchars($plan['validity']) . " " . htmlspecialchars($plan['validity_unit']) . " Unlimited\n"; + $htmlContent .= "

\n"; + $htmlContent .= "
\n"; + $htmlContent .= "
\n"; + $htmlContent .= " \n"; + $htmlContent .= " Click Here To Connect\n"; + $htmlContent .= " \n"; + $htmlContent .= "
\n"; + $htmlContent .= "
\n"; +} + +$htmlContent .= "
\n"; + + + + + + +$htmlContent .= "\n"; +$htmlContent .= "
\n"; +$htmlContent .= "

\n"; +$htmlContent .= " What Our Users Say\n"; +$htmlContent .= "

\n"; +$htmlContent .= "
\n"; +$htmlContent .= "
\n"; +// Testimonial 1 +$htmlContent .= "
\n"; +$htmlContent .= " \"Testimonial\n"; +$htmlContent .= "
\n"; +$htmlContent .= "
Otieno Peter
\n"; +$htmlContent .= "

\"Switching to this service has been a game changer for me. The connection is reliable and fast, making my online work seamless and efficient.\"

\n"; +$htmlContent .= "
\n"; +$htmlContent .= "
\n"; +// Testimonial 2 +$htmlContent .= "
\n"; +$htmlContent .= " \"Testimonial\n"; +$htmlContent .= "
\n"; +$htmlContent .= "
Kiveu
\n"; +$htmlContent .= "

\"I've experienced unparalleled support and service. The team goes above and beyond to ensure customer satisfaction. Highly recommend!\"

\n"; +$htmlContent .= "
\n"; +$htmlContent .= "
\n"; +// Testimonial 3 +$htmlContent .= "
\n"; +$htmlContent .= " \"Testimonial\n"; +$htmlContent .= "
\n"; +$htmlContent .= "
Anonymous User
\n"; +$htmlContent .= "

\"Their commitment to quality and speed is evident. My internet experience has been fantastic ever since I made the switch.\"

\n"; +$htmlContent .= "
\n"; +$htmlContent .= "
\n"; +$htmlContent .= "
\n"; +$htmlContent .= " \n"; +$htmlContent .= " \n"; +$htmlContent .= " \n"; +$htmlContent .= "
\n"; +$htmlContent .= "
\n"; +$htmlContent .= "
\n"; + +// Glider.js script for the Testimonials Section +$htmlContent .= "\n"; + + + + +$htmlContent .= "\n"; +$htmlContent .= "
\n"; +$htmlContent .= "
\n"; +$htmlContent .= "

\n"; +$htmlContent .= " FREQUENTLY ASKED QUESTIONS Will Be Here\n"; +$htmlContent .= "

\n"; +$htmlContent .= "

\n"; +$htmlContent .= " Everything you need to know before getting started.\n"; +$htmlContent .= "

\n"; +$htmlContent .= "
\n"; +$htmlContent .= "
\n"; +$htmlContent .= "
\n"; + +// FAQ 1 +$htmlContent .= "
\n"; +$htmlContent .= "
" . htmlspecialchars($settings['frequently_asked_questions_headline1']) . "
\n"; +$htmlContent .= " \n"; +$htmlContent .= "
\n"; + +// FAQ 2 +$htmlContent .= "
\n"; +$htmlContent .= "
" . htmlspecialchars($settings['frequently_asked_questions_headline2']) . "
\n"; +$htmlContent .= " \n"; +$htmlContent .= "
\n"; + +// FAQ 3 +$htmlContent .= "
\n"; +$htmlContent .= "
" . htmlspecialchars($settings['frequently_asked_questions_headline3']) . "
\n"; +$htmlContent .= " \n"; +$htmlContent .= "
\n"; + +$htmlContent .= "
\n"; +$htmlContent .= "
\n"; +$htmlContent .= "
\n"; + + +$htmlContent .= "
\n"; +$htmlContent .= "
\n"; +$htmlContent .= "
\n"; +$htmlContent .= "
\n"; +$htmlContent .= "
\n"; +$htmlContent .= "

Already Have an Active Package?

\n"; +$htmlContent .= "
\n"; + +$htmlContent .= "
\n"; +$htmlContent .= " \n"; +$htmlContent .= " \n"; +$htmlContent .= "
\n"; +$htmlContent .= " \n"; +$htmlContent .= " \n"; +$htmlContent .= "
\n"; +$htmlContent .= "
\n"; +$htmlContent .= " \n"; +$htmlContent .= " \n"; +$htmlContent .= "
\n"; +$htmlContent .= "
\n"; +$htmlContent .= " \n"; +$htmlContent .= "
\n"; +$htmlContent .= "
\n"; +$htmlContent .= "
\n"; +$htmlContent .= "
\n"; +$htmlContent .= "
\n"; +$htmlContent .= "
\n"; + +$htmlContent .= "\n"; + + + + + +$htmlContent .= "\n"; + + + + + + + + + +$htmlContent .= "\n"; +$htmlContent .= "\n"; + +$htmlContent .= "\n"; +$htmlContent .= "
\n"; +$htmlContent .= "
\n"; +$htmlContent .= "
\n"; +$htmlContent .= "
\n"; +$htmlContent .= "

\n"; +$htmlContent .= " Contact Us\n"; +$htmlContent .= "

\n"; +$htmlContent .= "
    \n"; +$htmlContent .= "
  • \n"; +$htmlContent .= " Address\n"; +$htmlContent .= "
  • \n"; +$htmlContent .= "
  • \n"; +$htmlContent .= " Email: contact@" . htmlspecialchars($company) . "\n"; +$htmlContent .= "
  • \n"; +$htmlContent .= "
  • \n"; +$htmlContent .= " Phone: " . htmlspecialchars($phone) . "\n"; +$htmlContent .= "
  • \n"; +$htmlContent .= "
\n"; +$htmlContent .= "
\n"; + +$htmlContent .= "
\n"; +$htmlContent .= "

\n"; +$htmlContent .= " Quick Links\n"; +$htmlContent .= "

\n"; +$htmlContent .= "
    \n"; +$htmlContent .= "
  • About Us
  • \n"; +$htmlContent .= "
  • Our Services
  • \n"; +$htmlContent .= "
  • FAQ
  • \n"; +$htmlContent .= "
  • Support
  • \n"; +$htmlContent .= "
\n"; +$htmlContent .= "
\n"; + +$htmlContent .= "
\n"; +$htmlContent .= "

\n"; +$htmlContent .= " Follow Us\n"; +$htmlContent .= "

\n"; +$htmlContent .= "
\n"; +$htmlContent .= " \n"; +$htmlContent .= " \n"; +$htmlContent .= " \n"; +$htmlContent .= " \n"; +$htmlContent .= "
\n"; +$htmlContent .= "
\n"; +$htmlContent .= "
\n"; + +$htmlContent .= "
\n"; +$htmlContent .= "
\n"; +$htmlContent .= " Facebook\n"; +$htmlContent .= " Instagram\n"; +$htmlContent .= " Twitter\n"; +$htmlContent .= " LinkedIn\n"; +$htmlContent .= "
\n"; +$htmlContent .= "

\n"; +$htmlContent .= " © 2024 " . htmlspecialchars($company) . " All rights reserved.\n"; +$htmlContent .= "

\n"; +$htmlContent .= "
\n"; +$htmlContent .= "
\n"; +$htmlContent .= "
\n"; + + +$htmlContent .= "\n"; + +$htmlContent .= "\n"; + + + +$htmlContent .= "\n"; + +$htmlContent .= "\n"; + + +$htmlContent .= "\n"; + + + + + + + +$planStmt->close(); +$mysqli->close(); +// Check if the download parameter is set +if (isset($_GET['download']) && $_GET['download'] == '1') { + // Prepare the HTML content for download + // ... build your HTML content ... + + // Specify the filename for the download + $filename = "login.html"; + + // Send headers to force download + header('Content-Type: application/octet-stream'); + header('Content-Disposition: attachment; filename='.basename($filename)); + header('Expires: 0'); + header('Cache-Control: must-revalidate'); + header('Pragma: public'); + header('Content-Length: ' . strlen($htmlContent)); + + // Output the content + echo $htmlContent; + + // Prevent any further output + exit; +} + +// Regular page content goes here +// ... HTML and PHP code to display the page ... + + diff --git a/system/plugin/ui/hotspot_settings.tpl b/system/plugin/ui/hotspot_settings.tpl new file mode 100644 index 0000000..6f65723 --- /dev/null +++ b/system/plugin/ui/hotspot_settings.tpl @@ -0,0 +1,117 @@ +{include file="sections/header.tpl"} +
+

+
+ + + +
+

+ +
+ +
+
+
+ +{include file="sections/footer.tpl"} diff --git a/system/plugin/ui/index.html b/system/plugin/ui/index.html new file mode 100644 index 0000000..06d7405 Binary files /dev/null and b/system/plugin/ui/index.html differ diff --git a/system/plugin/ui/log.tpl b/system/plugin/ui/log.tpl new file mode 100644 index 0000000..e3a618c --- /dev/null +++ b/system/plugin/ui/log.tpl @@ -0,0 +1,154 @@ + + + + + + Log UI + + +{include file="sections/header.tpl"} + +
+
+ +
+ +
+
+ +
+
+ +
+
+ + + + + + + + + + + {assign var=current_page value=$smarty.get.page|default:1} + {assign var=per_page value=$smarty.get.per_page|default:10} + {assign var=start_index value=($current_page - 1) * $per_page} + + {foreach from=$logs|array_reverse item=log name=logLoop} + {if $smarty.foreach.logLoop.index >= $start_index && $smarty.foreach.logLoop.index < ($start_index + $per_page)} + + + + + + {/if} + {/foreach} + +
TimeTopicMessage
{$log.time}{$log.topics} + {if $log.message|lower|strpos:'failed' !== false} + {$log.message} + {elseif $log.message|lower|strpos:'trying' !== false} + {$log.message} + {elseif $log.message|lower|strpos:'logged in' !== false} + {$log.message} + {elseif $log.message|lower|strpos:'login failed' !== false} + {$log.message} + {else} + {$log.message} + {/if} +
+ + {assign var=total_logs value=$logs|@count} + {assign var=last_page value=ceil($total_logs / $per_page)} + + +
+ + + + {include file="sections/footer.tpl"} + + diff --git a/system/plugin/ui/port_tester.tpl b/system/plugin/ui/port_tester.tpl new file mode 100644 index 0000000..f12b83a --- /dev/null +++ b/system/plugin/ui/port_tester.tpl @@ -0,0 +1,34 @@ +{include file="sections/header.tpl"} + +
+
+
+
+
Testing port external
+
+
+ +
+ +
+
+
+
+ +
+
+
+
+ {if $result != ''} +
+
Result
+
+ {Lang::nl2br($result)} +
+
+ {/if} +
+
+
+ +{include file="sections/footer.tpl"} diff --git a/system/plugin/ui/pppoe_monitor.tpl b/system/plugin/ui/pppoe_monitor.tpl new file mode 100644 index 0000000..8ff8e73 --- /dev/null +++ b/system/plugin/ui/pppoe_monitor.tpl @@ -0,0 +1,943 @@ +{include file="sections/header.tpl"} + + + + + + + + + + + + + +
+
+
+ +
+
+ +
+ +
+
+
+
+
+
+ + +
+
+ + +
+
+
+
+
+
+ + + + + + + + + + + + + + + + + + + + +
IDUsernameIP AddressUptimeServiceCaller IDDeviceDownloadUploadTotal UsageStatusActions
+
+
+
+
+
+
+ + + + + +{include file="sections/footer.tpl"} diff --git a/system/plugin/user.png b/system/plugin/user.png new file mode 100644 index 0000000..7af1f56 Binary files /dev/null and b/system/plugin/user.png differ diff --git a/system/uploads/_sysfrm_tmp_/index.html b/system/uploads/_sysfrm_tmp_/index.html new file mode 100644 index 0000000..9757970 --- /dev/null +++ b/system/uploads/_sysfrm_tmp_/index.html @@ -0,0 +1,8 @@ + + + 403 Forbidden + + +

Directory access is forbidden.

+ + \ No newline at end of file diff --git a/system/uploads/admin.default.png b/system/uploads/admin.default.png new file mode 100644 index 0000000..3bc948c Binary files /dev/null and b/system/uploads/admin.default.png differ diff --git a/system/uploads/index.html b/system/uploads/index.html new file mode 100644 index 0000000..9757970 --- /dev/null +++ b/system/uploads/index.html @@ -0,0 +1,8 @@ + + + 403 Forbidden + + +

Directory access is forbidden.

+ + \ No newline at end of file diff --git a/system/uploads/logo.default.png b/system/uploads/logo.default.png new file mode 100644 index 0000000..4b78d24 Binary files /dev/null and b/system/uploads/logo.default.png differ diff --git a/system/uploads/logo.png b/system/uploads/logo.png new file mode 100644 index 0000000..150184a Binary files /dev/null and b/system/uploads/logo.png differ diff --git a/system/uploads/notifications.default.json b/system/uploads/notifications.default.json new file mode 100644 index 0000000..a148543 --- /dev/null +++ b/system/uploads/notifications.default.json @@ -0,0 +1,10 @@ +{ + "expired": "Hello [[name]], your internet package [[package]] has been expired.", + "balance_send": "You sent [[balance]] to [[name]].", + "balance_received": "You have received [[balance]] from [[name]].", + "reminder_7_day": "Hello *[[name]]*, \r\nyour internet package *[[package]]* will be expired in 7 days.", + "reminder_3_day": "Hello *[[name]]*, \r\nyour internet package *[[package]]* will be expired in 3 days.", + "reminder_1_day": "Hello *[[name]]*,\r\n your internet package *[[package]]* will be expired tomorrow.", + "invoice_paid": "*[[company_name]]*\r\n[[address]]\r\n[[phone]]\r\n\r\n\r\nINVOICE: *[[invoice]]*\r\nDate : [[date]]\r\n[[payment_gateway]] [[payment_channel]]\r\n\r\n\r\nType : *[[type]]*\r\nPackage : *[[plan_name]]*\r\nPrice : *[[plan_price]]*\r\n\r\nUsername : *[[user_name]]*\r\nPassword : ***********\r\n\r\nExpired : *[[expired_date]]*\r\n\r\n====================\r\n[[footer]]", + "invoice_balance": "*[[company_name]]*\r\n[[address]]\r\n[[phone]]\r\n\r\n\r\nINVOICE: *[[invoice]]*\r\nDate : [[date]]\r\n[[payment_gateway]] [[payment_channel]]\r\n\r\n\r\nType : *[[type]]*\r\nPackage : *[[plan_name]]*\r\nPrice : *[[plan_price]]*\r\n\r\n====================\r\n[[footer]]" +} diff --git a/system/uploads/notifications.json b/system/uploads/notifications.json new file mode 100644 index 0000000..b903ab3 --- /dev/null +++ b/system/uploads/notifications.json @@ -0,0 +1 @@ +{"expired":"Dear Customer, your subscription of [[package]] has expired.\r\nONLY Home\/Office Users pay using:\r\nPay Bill:4355580\r\nAcc. No:[[username]]\r\nPrice:[[price]]","reminder_7_day":"","reminder_3_day":"","reminder_1_day":"Hello, Your Internet will Expire in 1 Day, Kindly make subscribe to continue using our Services. \r\n","invoice_paid":"Successfully Purchased [[plan_name]]. Expiry: [[expired_date]]. \r\nIf not connected use MPESA message or Account No.:[[user_name]] on the login page.","invoice_balance":""} \ No newline at end of file diff --git a/system/uploads/paymentgateway/BankStkPush.php b/system/uploads/paymentgateway/BankStkPush.php new file mode 100644 index 0000000..1c3347d --- /dev/null +++ b/system/uploads/paymentgateway/BankStkPush.php @@ -0,0 +1,205 @@ +assign('_title', 'Bank Stk Push - ' . $config['CompanyName']); + $ui->display('bankstkpush.tpl'); +} + +function BankStkPush_save_config() +{ + global $admin, $_L; + $bankacc = _post('account'); + $bankname = _post('bankname'); + $d = ORM::for_table('tbl_appconfig')->where('setting', 'Stkbankacc')->find_one(); + if ($d) { + $d->value = $bankacc; + $d->save(); + } else { + $d = ORM::for_table('tbl_appconfig')->create(); + $d->setting = 'Stkbankacc'; + $d->value = $bankacc; + $d->save(); + } + $d = ORM::for_table('tbl_appconfig')->where('setting', 'Stkbankname')->find_one(); + if ($d) { + $d->value = $bankname; + $d->save(); + } else { + $d = ORM::for_table('tbl_appconfig')->create(); + $d->setting = 'Stkbankname'; + $d->value = $bankname; + $d->save(); + } + + _log('[' . $admin['username'] . ']: Stk Bank details ' . $_L['Settings_Saved_Successfully'], 'Admin', $admin['id']); + + r2(U . 'paymentgateway/BankStkPush', 's', $_L['Settings_Saved_Successfully']); +} + + +function BankStkPush_create_transaction($trx, $user ) +{ + $url=(U. "plugin/initiatebankstk"); + + $d = ORM::for_table('tbl_payment_gateway') + ->where('username', $user['username']) + ->where('status', 1) + ->find_one(); + $d->gateway_trx_id = ''; + $d->payment_method = 'Bank Stk Push'; + $d->pg_url_payment = $url; + $d->pg_request = ''; + $d->expired_date = date('Y-m-d H:i:s', strtotime("+5 minutes")); + $d->save(); + + r2(U . "order/view/" . $d['id'], 's', Lang::T("Create Transaction Success, Please click pay now to process payment")); + + die(); +} + +function BankStkPush_payment_notification() +{ + $captureLogs = file_get_contents("php://input"); + + $analizzare = json_decode($captureLogs); + /// sleep(10); + file_put_contents('back.log',$captureLogs,FILE_APPEND); + $response_code = $analizzare->Body->stkCallback->ResultCode; + $resultDesc = ($analizzare->Body->stkCallback->ResultDesc); + $merchant_req_id = ($analizzare->Body->stkCallback->MerchantRequestID); + $checkout_req_id = ($analizzare->Body->stkCallback->CheckoutRequestID); + + $amount_paid = ($analizzare->Body->stkCallback->CallbackMetadata->Item['0']->Value);//get the amount value + $mpesa_code = ($analizzare->Body->stkCallback->CallbackMetadata->Item['1']->Value);//mpesa transaction code.. + $sender_phone = ($analizzare->Body->stkCallback->CallbackMetadata->Item['4']->Value);//Telephone Number + + $PaymentGatewayRecord = ORM::for_table('tbl_payment_gateway') + ->where('checkout', $checkout_req_id) + ->where('status', 1) // Add this line to filter by status + ->order_by_desc('id') + ->find_one(); + + $uname=$PaymentGatewayRecord->username; + $plan_id=$PaymentGatewayRecord->plan_id; + $mac_address=$PaymentGatewayRecord->mac_address; + $user=$PaymentGatewayRecord; + + $userid = ORM::for_table('tbl_customers') + ->where('username', $uname) + ->order_by_desc('id') + ->find_one(); + + $userid->username=$uname; + $userid->save(); + $plans = ORM::for_table('tbl_plans') + ->where('id', $plan_id) + + ->order_by_desc('id') + ->find_one(); + + if ($response_code=="1032") + { + $now = date('Y-m-d H:i:s'); + $PaymentGatewayRecord->paid_date = $now; + $PaymentGatewayRecord->status = 4; + $PaymentGatewayRecord->save(); + + exit(); + } + if($response_code=="1037"){ + $PaymentGatewayRecord->status = 1; + $PaymentGatewayRecord->pg_paid_response = 'User failed to enter pin'; + $PaymentGatewayRecord->save(); + + exit(); + } + + if($response_code=="1"){ + $PaymentGatewayRecord->status = 1; + $PaymentGatewayRecord->pg_paid_response = 'Not enough balance'; + $PaymentGatewayRecord->save(); + + exit(); + } + + if($response_code=="2001"){ + $PaymentGatewayRecord->status = 1; + $PaymentGatewayRecord->pg_paid_response = 'Wrong Mpesa pin'; + $PaymentGatewayRecord->save(); + + exit(); + } + + if($response_code=="0"){ + + $now = date('Y-m-d H:i:s'); + $date = date('Y-m-d'); + $time= date('H:i:s'); + + $check_mpesa = ORM::for_table('tbl_payment_gateway') + ->where('gateway_trx_id', $mpesa_code) + ->find_one(); + + if($check_mpesa){ + echo "double callback, ignore one"; + + die; + } + + $plan_type=$plans->type; + $UserId=$userid->id; + + if (!Package::rechargeUser($UserId, $user['routers'], $user['plan_id'], $user['gateway'], $mpesa_code)){ + $PaymentGatewayRecord->status = 2; + $PaymentGatewayRecord->paid_date = $now; + $PaymentGatewayRecord->gateway_trx_id = $mpesa_code; + $PaymentGatewayRecord->save(); + $username = $PaymentGatewayRecord->username; + + // Check if a transaction with the same gateway_trx_id already exists + $existingTransaction = ORM::for_table('tbl_transactions') + ->where('mpesacode', $mpesa_code) + ->find_one(); + + if (!$existingTransaction) { + // Save transaction data to tbl_transactions + $transaction = ORM::for_table('tbl_transactions')->create(); + $transaction->invoice = $PaymentGatewayRecord->gateway_trx_id; // Set invoice to gateway_trx_id value + $transaction->username = $PaymentGatewayRecord->username; + $transaction->plan_name = $PaymentGatewayRecord->plan_name; + $transaction->price = $amount_paid; + $transaction->recharged_on = $date; + $transaction->recharged_time = $time; + $transaction->expiration = $now; + $transaction->time = $now; + $transaction->method = $PaymentGatewayRecord->payment_method; + $transaction->routers = 0; + $transaction->Type = 'Balance'; + $transaction->mpesacode = $mpesa_code; + $transaction->save(); + } else { + error_log("Duplicate transaction entry detected for gateway_trx_id: " . $PaymentGatewayRecord->gateway_trx_id); + } + } else { + // Update tbl_recharges + $PaymentGatewayRecord->status = 2; + $PaymentGatewayRecord->paid_date = $now; + $PaymentGatewayRecord->gateway_trx_id = $mpesa_code; + $PaymentGatewayRecord->save(); + } + + + } +} diff --git a/system/uploads/paymentgateway/flutterwave.php b/system/uploads/paymentgateway/flutterwave.php new file mode 100644 index 0000000..7754b49 --- /dev/null +++ b/system/uploads/paymentgateway/flutterwave.php @@ -0,0 +1,234 @@ +assign('_title', 'Flutterwave - Payment Gateway'); + $ui->assign('cur', json_decode(file_get_contents('system/paymentgateway/flutterwave_currency.json'), true)); + $ui->assign('channel', json_decode(file_get_contents('system/paymentgateway/flutterwave_channel.json'), true)); + $ui->display('flutterwave.tpl'); + } + + + function flutterwave_save_config() + { + global $admin, $_L; + $flutterwave_secret_key = _post('flutterwave_secret_key'); + $flutterwave_currency = _post('flutterwave_currency'); + $d = ORM::for_table('tbl_appconfig')->where('setting', 'flutterwave_secret_key')->find_one(); + if ($d) { + $d->value = $flutterwave_secret_key; + $d->save(); + } else { + $d = ORM::for_table('tbl_appconfig')->create(); + $d->setting = 'flutterwave_secret_key'; + $d->value = $flutterwave_secret_key; + $d->save(); + } + $d = ORM::for_table('tbl_appconfig')->where('setting', 'flutterwave_currency')->find_one(); + if ($d) { + $d->value = $flutterwave_currency; + $d->save(); + } else { + $d = ORM::for_table('tbl_appconfig')->create(); + $d->setting = 'flutterwave_currency'; + $d->value = $flutterwave_currency; + $d->save(); + } + $d = ORM::for_table('tbl_appconfig')->where('setting', 'flutterwave_channel')->find_one(); + if ($d) { + $d->value = implode(',', $_POST['flutterwave_channel']); + $d->save(); + } else { + $d = ORM::for_table('tbl_appconfig')->create(); + $d->setting = 'flutterwave_channel'; + $d->value = implode(',', $_POST['flutterwave_channel']); + $d->save(); + } + _log('[' . $admin['username'] . ']: Flutterwave ' . $_L['Settings_Saved_Successfully'], 'Admin', $admin['id']); + + r2(U . 'paymentgateway/flutterwave', 's', $_L['Settings_Saved_Successfully']); + } + +function flutterwave_create_transaction($trx, $user) +{ + global $config; + $txref = uniqid('trx'); + $json = [ + 'tx_ref' => $txref, + 'amount' => $trx['price'], + 'currency' => $config['flutterwave_currency'], + 'payment_options' => explode(',', $config['flutterwave_channel']), + 'customer' => [ + 'email' => (empty($user['email'])) ? $user['username'] . '@' . $_SERVER['HTTP_HOST'] : $user['email'], + 'name' => $user['fullname'], + 'phonenumber' => $user['phonenumber'] + ], + 'meta' => [ + 'price' => $trx['price'], + 'username' => $user['username'], + 'trxid' => $trx['id'] + ], + + 'customizations' => [ + 'title' => $trx['plan_name'], + 'description' => $trx['plan_name'], + ], + + 'redirect_url' => U . 'callback/flutterwave' + ]; + // die(json_encode($json,JSON_PRETTY_PRINT)); + + $result = json_decode(Http::postJsonData(flutterwave_get_server() . 'payments', $json,[ + 'Authorization: Bearer ' . $config['flutterwave_secret_key'], + 'Cache-Control: no-cahe' + ], + ), +true); + +//die(json_encode($result,JSON_PRETTY_PRINT)); + +if ($result['status'] == 'error') { + Message::sendTelegram("Flutterwave payment failed\n\n" . json_encode($result, JSON_PRETTY_PRINT)); + r2(U . 'order/package', 'e', Lang::T("Failed to create transaction.\n".$result['message'])); + } + $d = ORM::for_table('tbl_payment_gateway') + ->where('username', $user['username']) + ->where('status', 1) + ->find_one(); + $d->gateway_trx_id = $txref; + $d->pg_url_payment = $result['data']['link']; + $d->pg_request = json_encode($result); + $d->expired_date = date('Y-m-d H:i:s', strtotime("+ 6 HOUR")); + $d->save(); + + header('Location: ' . $result['data']['link']); + exit(); + + r2(U . "order/view/" . $d['id'], 's', Lang::T("Create Transaction Success")); + + +} + +function flutterwave_payment_notification() +{ + global $config; +if(isset($_GET['status'])) + + { + //* check payment status + if($_GET['status'] == 'cancelled') + { + // die(json_encode($txref,JSON_PRETTY_PRINT)); + Message::sendTelegram("Flutterwave Payment Cancelled: \n\n"); + r2(U . 'order/package', 'e', Lang::T("Flutterwave Payment Cancelled.")); + } + elseif($_GET['status'] == 'successful') + { + + $txid = $_GET['transaction_id']; + $result = json_decode(Http::getData(flutterwave_get_server() . 'transactions/' . $txid. '/verify', [ + 'Authorization: Bearer ' . $config['flutterwave_secret_key'], + 'Cache-Control: no-cahe' + ]), true); + //die(json_encode($result,JSON_PRETTY_PRINT)); + { + $id = $result['data']['id']; + $amountPaid = $result['data']['charged_amount']; + $amountToPay = $result['data']['meta']['price']; + $username = $result['data']['meta']['username']; + $trxid = $result['data']['meta']['trxid']; + if($amountPaid >= $amountToPay) + { + // die(json_encode($trxid,JSON_PRETTY_PRINT)); + // echo 'Payment successful'; + $d = ORM::for_table('tbl_payment_gateway') + ->where('username', $username) + ->where('status', 1) + ->find_one(); + $d->gateway_trx_id = $id; + $d->save(); + r2(U . 'order/view/'.$trxid.'/check'); + // r2(U . 'order/package', 's', Lang::T("Flutterwave Payment Completed.")); + exit(); + //* Continue to give item to the user + } + else + { + // echo 'Fraud transactio detected'; + r2(U . 'order/package', 'e', Lang::T("Fraud transactions detected.")); + exit(); + } + } + } + } + } + + + function flutterwave_get_status($trx, $user) + { + global $config; + $trans_id = $trx['gateway_trx_id']; + $result = json_decode(Http::getData(flutterwave_get_server() . 'transactions/' . $trx['gateway_trx_id']. '/verify', [ + 'Authorization: Bearer ' . $config['flutterwave_secret_key'], + 'Cache-Control: no-cahe' + ]), true); + //die(json_encode($result,JSON_PRETTY_PRINT)); + if ($result['status'] == 'error') { + r2(U . "order/view/" . $trx['id'], 'w', Lang::T("Transaction still unpaid.")); + } else if (in_array($result['status'], ['success']) && $trx['status'] != 2) { + if (!Package::rechargeUser($user['id'], $trx['routers'], $trx['plan_id'], $trx['gateway'], 'Flutterwave')) { + r2(U . "order/view/" . $trx['id'], 'd', Lang::T("Failed to activate your Package, please try again later.")); + } + $trx->pg_paid_response = json_encode($result); + $trx->payment_method = 'Flutterwave'; + $trx->payment_channel = $result['data']['payment_type']; + $trx->paid_date = date('Y-m-d H:i:s', strtotime( $result['data']['created_at'])); + $trx->status = 2; + $trx->save(); + + r2(U . "order/view/" . $trx['id'], 's', Lang::T("Transaction successful.")); + } else if ($result['status'] == 'EXPIRED') { + $trx->pg_paid_response = json_encode($result); + $trx->status = 3; + $trx->save(); + r2(U . "order/view/" . $trx['id'], 'd', Lang::T("Transaction expired.")); + } else if ($trx['status'] == 2) { + r2(U . "order/view/" . $trx['id'], 'd', Lang::T("Transaction has been paid..")); + }else{ + Message::sendTelegram("flutterwave_get_status: unknown result\n\n".json_encode($result, JSON_PRETTY_PRINT)); + r2(U . "order/view/" . $trx['id'], 'd', Lang::T("Unknown Command.")); + } + + } + + +function flutterwave_get_server() +{ + global $_app_stage; + if ($_app_stage == 'Live') { + return 'https://api.flutterwave.com/v3/'; + } else { + return 'https://api.flutterwave.com/v3/'; + } +} diff --git a/system/uploads/paymentgateway/flutterwave_channel.json b/system/uploads/paymentgateway/flutterwave_channel.json new file mode 100644 index 0000000..09e38c1 --- /dev/null +++ b/system/uploads/paymentgateway/flutterwave_channel.json @@ -0,0 +1,35 @@ +[ + + { + "id": "card", + "name": "Card Payment" + }, + { + "id": "ussd", + "name": "USSD" + }, + { + "id": "account", + "name": "Bank Account" + }, + { + "id": "banktransfer", + "name": "Bank Transfer" + }, + { + "id": "nqr", + "name": "QR payment" + }, + { + "id": "mpesa", + "name": "M-Pesa" + }, + { + "id": "mobilemoneyghana", + "name": "Mobile money Ghana" + }, + { + "id": "credit", + "name": "Credit payment" + } +] diff --git a/system/uploads/paymentgateway/flutterwave_currency.json b/system/uploads/paymentgateway/flutterwave_currency.json new file mode 100644 index 0000000..fe716ea --- /dev/null +++ b/system/uploads/paymentgateway/flutterwave_currency.json @@ -0,0 +1,30 @@ +[ + { + "id": "NGN", + "name": "Nigerian Naira" + }, + { + "id": "GHC", + "name": "Ghana Cedis" + }, + { + "id": "KES", + "name": "Kenyan Shilling" + }, + { + "id": "ZAR", + "name": "South African Rand" + }, + { + "id": "GBP", + "name": "British Pound Sterling" + }, + { + "id": "USD", + "name": "United States Dollar" + }, + { + "id": "TZS", + "name": "Tanzanian Shilling" + } +] diff --git a/system/uploads/paymentgateway/index.html b/system/uploads/paymentgateway/index.html new file mode 100644 index 0000000..06d7405 Binary files /dev/null and b/system/uploads/paymentgateway/index.html differ diff --git a/system/uploads/sms/index.html b/system/uploads/sms/index.html new file mode 100644 index 0000000..06d7405 Binary files /dev/null and b/system/uploads/sms/index.html differ diff --git a/system/uploads/system/index.html b/system/uploads/system/index.html new file mode 100644 index 0000000..9757970 --- /dev/null +++ b/system/uploads/system/index.html @@ -0,0 +1,8 @@ + + + 403 Forbidden + + +

Directory access is forbidden.

+ + \ No newline at end of file diff --git a/system/uploads/user.default.jpg b/system/uploads/user.default.jpg new file mode 100644 index 0000000..58b0f1d Binary files /dev/null and b/system/uploads/user.default.jpg differ diff --git a/system/vendor/autoload.php b/system/vendor/autoload.php new file mode 100644 index 0000000..472bcbe --- /dev/null +++ b/system/vendor/autoload.php @@ -0,0 +1,25 @@ + 'START', 2 => 'VALUE', 3 => 'NAKED_STRING_VALUE', 4 => 'COMMENT', 5 => 'SECTION', 6 => 'TRIPPLE'); + + /** + * storage for assembled token patterns + * + * @var string + */ + private $yy_global_pattern1 = null; + private $yy_global_pattern2 = null; + private $yy_global_pattern3 = null; + private $yy_global_pattern4 = null; + private $yy_global_pattern5 = null; + private $yy_global_pattern6 = null; + + /** + * token names + * + * @var array + */ + public $smarty_token_names = array( // Text for parser error messages + ); + + /** + * constructor + * + * @param string $data template source + * @param Smarty_Internal_Config_File_Compiler $compiler + */ + public function __construct($data, Smarty_Internal_Config_File_Compiler $compiler) + { + $this->data = $data . "\n"; //now all lines are \n-terminated + $this->dataLength = strlen($data); + $this->counter = 0; + if (preg_match('/^\xEF\xBB\xBF/', $this->data, $match)) { + $this->counter += strlen($match[0]); + } + $this->line = 1; + $this->compiler = $compiler; + $this->smarty = $compiler->smarty; + $this->configBooleanize = $this->smarty->config_booleanize; + } + + public function replace ($input) { + return $input; + } + + public function PrintTrace() + { + $this->yyTraceFILE = fopen('php://output', 'w'); + $this->yyTracePrompt = '
'; + } + + +/*!lex2php +%input $this->data +%counter $this->counter +%token $this->token +%value $this->value +%line $this->line +commentstart = /#|;/ +openB = /\[/ +closeB = /\]/ +section = /.*?(?=[\.=\[\]\r\n])/ +equal = /=/ +whitespace = /[ \t\r]+/ +dot = /\./ +id = /[0-9]*[a-zA-Z_]\w*/ +newline = /\n/ +single_quoted_string = /'[^'\\]*(?:\\.[^'\\]*)*'(?=[ \t\r]*[\n#;])/ +double_quoted_string = /"[^"\\]*(?:\\.[^"\\]*)*"(?=[ \t\r]*[\n#;])/ +tripple_quotes = /"""/ +tripple_quotes_end = /"""(?=[ \t\r]*[\n#;])/ +text = /[\S\s]/ +float = /\d+\.\d+(?=[ \t\r]*[\n#;])/ +int = /\d+(?=[ \t\r]*[\n#;])/ +maybe_bool = /[a-zA-Z]+(?=[ \t\r]*[\n#;])/ +naked_string = /[^\n]+?(?=[ \t\r]*\n)/ +*/ + +/*!lex2php +%statename START + +commentstart { + $this->token = Smarty_Internal_Configfileparser::TPC_COMMENTSTART; + $this->yypushstate(self::COMMENT); +} +openB { + $this->token = Smarty_Internal_Configfileparser::TPC_OPENB; + $this->yypushstate(self::SECTION); +} +closeB { + $this->token = Smarty_Internal_Configfileparser::TPC_CLOSEB; +} +equal { + $this->token = Smarty_Internal_Configfileparser::TPC_EQUAL; + $this->yypushstate(self::VALUE); +} +whitespace { + return false; +} +newline { + $this->token = Smarty_Internal_Configfileparser::TPC_NEWLINE; +} +id { + $this->token = Smarty_Internal_Configfileparser::TPC_ID; +} +text { + $this->token = Smarty_Internal_Configfileparser::TPC_OTHER; +} + +*/ + +/*!lex2php +%statename VALUE + +whitespace { + return false; +} +float { + $this->token = Smarty_Internal_Configfileparser::TPC_FLOAT; + $this->yypopstate(); +} +int { + $this->token = Smarty_Internal_Configfileparser::TPC_INT; + $this->yypopstate(); +} +tripple_quotes { + $this->token = Smarty_Internal_Configfileparser::TPC_TRIPPLE_QUOTES; + $this->yypushstate(self::TRIPPLE); +} +single_quoted_string { + $this->token = Smarty_Internal_Configfileparser::TPC_SINGLE_QUOTED_STRING; + $this->yypopstate(); +} +double_quoted_string { + $this->token = Smarty_Internal_Configfileparser::TPC_DOUBLE_QUOTED_STRING; + $this->yypopstate(); +} +maybe_bool { + if (!$this->configBooleanize || !in_array(strtolower($this->value), array('true', 'false', 'on', 'off', 'yes', 'no')) ) { + $this->yypopstate(); + $this->yypushstate(self::NAKED_STRING_VALUE); + return true; //reprocess in new state + } else { + $this->token = Smarty_Internal_Configfileparser::TPC_BOOL; + $this->yypopstate(); + } +} +naked_string { + $this->token = Smarty_Internal_Configfileparser::TPC_NAKED_STRING; + $this->yypopstate(); +} +newline { + $this->token = Smarty_Internal_Configfileparser::TPC_NAKED_STRING; + $this->value = ''; + $this->yypopstate(); +} + +*/ + +/*!lex2php +%statename NAKED_STRING_VALUE + +naked_string { + $this->token = Smarty_Internal_Configfileparser::TPC_NAKED_STRING; + $this->yypopstate(); +} + +*/ + +/*!lex2php +%statename COMMENT + +whitespace { + return false; +} +naked_string { + $this->token = Smarty_Internal_Configfileparser::TPC_NAKED_STRING; +} +newline { + $this->token = Smarty_Internal_Configfileparser::TPC_NEWLINE; + $this->yypopstate(); +} + +*/ + +/*!lex2php +%statename SECTION + +dot { + $this->token = Smarty_Internal_Configfileparser::TPC_DOT; +} +section { + $this->token = Smarty_Internal_Configfileparser::TPC_SECTION; + $this->yypopstate(); +} + +*/ +/*!lex2php +%statename TRIPPLE + +tripple_quotes_end { + $this->token = Smarty_Internal_Configfileparser::TPC_TRIPPLE_QUOTES_END; + $this->yypopstate(); + $this->yypushstate(self::START); +} +text { + $to = strlen($this->data); + preg_match("/\"\"\"[ \t\r]*[\n#;]/",$this->data,$match,PREG_OFFSET_CAPTURE,$this->counter); + if (isset($match[0][1])) { + $to = $match[0][1]; + } else { + $this->compiler->trigger_config_file_error ('missing or misspelled literal closing tag'); + } + $this->value = substr($this->data,$this->counter,$to-$this->counter); + $this->token = Smarty_Internal_Configfileparser::TPC_TRIPPLE_TEXT; +} +*/ + +} diff --git a/system/vendor/smarty/lexer/smarty_internal_configfileparser.y b/system/vendor/smarty/lexer/smarty_internal_configfileparser.y new file mode 100644 index 0000000..c981b58 --- /dev/null +++ b/system/vendor/smarty/lexer/smarty_internal_configfileparser.y @@ -0,0 +1,346 @@ +/** +* Smarty Internal Plugin Configfileparser +* +* This is the config file parser +* +* +* @package Smarty +* @subpackage Config +* @author Uwe Tews +*/ +%name TPC_ +%declare_class { +/** +* Smarty Internal Plugin Configfileparse +* +* This is the config file parser. +* It is generated from the smarty_internal_configfileparser.y file +* @package Smarty +* @subpackage Compiler +* @author Uwe Tews +*/ +class Smarty_Internal_Configfileparser +} +%include_class +{ + /** + * result status + * + * @var bool + */ + public $successful = true; + /** + * return value + * + * @var mixed + */ + public $retvalue = 0; + /** + * @var + */ + public $yymajor; + /** + * lexer object + * + * @var Smarty_Internal_Configfilelexer + */ + private $lex; + /** + * internal error flag + * + * @var bool + */ + private $internalError = false; + /** + * compiler object + * + * @var Smarty_Internal_Config_File_Compiler + */ + public $compiler = null; + /** + * smarty object + * + * @var Smarty + */ + public $smarty = null; + /** + * copy of config_overwrite property + * + * @var bool + */ + private $configOverwrite = false; + /** + * copy of config_read_hidden property + * + * @var bool + */ + private $configReadHidden = false; + /** + * helper map + * + * @var array + */ + private static $escapes_single = array('\\' => '\\', + '\'' => '\''); + + /** + * constructor + * + * @param Smarty_Internal_Configfilelexer $lex + * @param Smarty_Internal_Config_File_Compiler $compiler + */ + public function __construct(Smarty_Internal_Configfilelexer $lex, Smarty_Internal_Config_File_Compiler $compiler) + { + $this->lex = $lex; + $this->smarty = $compiler->smarty; + $this->compiler = $compiler; + $this->configOverwrite = $this->smarty->config_overwrite; + $this->configReadHidden = $this->smarty->config_read_hidden; + } + + /** + * parse optional boolean keywords + * + * @param string $str + * + * @return bool + */ + private function parse_bool($str) + { + $str = strtolower($str); + if (in_array($str, array('on', 'yes', 'true'))) { + $res = true; + } else { + $res = false; + } + return $res; + } + + /** + * parse single quoted string + * remove outer quotes + * unescape inner quotes + * + * @param string $qstr + * + * @return string + */ + private static function parse_single_quoted_string($qstr) + { + $escaped_string = substr($qstr, 1, strlen($qstr) - 2); //remove outer quotes + + $ss = preg_split('/(\\\\.)/', $escaped_string, - 1, PREG_SPLIT_DELIM_CAPTURE); + + $str = ''; + foreach ($ss as $s) { + if (strlen($s) === 2 && $s[0] === '\\') { + if (isset(self::$escapes_single[$s[1]])) { + $s = self::$escapes_single[$s[1]]; + } + } + $str .= $s; + } + return $str; + } + + /** + * parse double quoted string + * + * @param string $qstr + * + * @return string + */ + private static function parse_double_quoted_string($qstr) + { + $inner_str = substr($qstr, 1, strlen($qstr) - 2); + return stripcslashes($inner_str); + } + + /** + * parse triple quoted string + * + * @param string $qstr + * + * @return string + */ + private static function parse_tripple_double_quoted_string($qstr) + { + return stripcslashes($qstr); + } + + /** + * set a config variable in target array + * + * @param array $var + * @param array $target_array + */ + private function set_var(array $var, array &$target_array) + { + $key = $var['key']; + $value = $var['value']; + + if ($this->configOverwrite || !isset($target_array['vars'][$key])) { + $target_array['vars'][$key] = $value; + } else { + settype($target_array['vars'][$key], 'array'); + $target_array['vars'][$key][] = $value; + } + } + + /** + * add config variable to global vars + * + * @param array $vars + */ + private function add_global_vars(array $vars) + { + if (!isset($this->compiler->config_data['vars'])) { + $this->compiler->config_data['vars'] = array(); + } + foreach ($vars as $var) { + $this->set_var($var, $this->compiler->config_data); + } + } + + /** + * add config variable to section + * + * @param string $section_name + * @param array $vars + */ + private function add_section_vars($section_name, array $vars) + { + if (!isset($this->compiler->config_data['sections'][$section_name]['vars'])) { + $this->compiler->config_data['sections'][$section_name]['vars'] = array(); + } + foreach ($vars as $var) { + $this->set_var($var, $this->compiler->config_data['sections'][$section_name]); + } + } +} + +%token_prefix TPC_ + +%parse_accept +{ + $this->successful = !$this->internalError; + $this->internalError = false; + $this->retvalue = $this->_retvalue; +} + +%syntax_error +{ + $this->internalError = true; + $this->yymajor = $yymajor; + $this->compiler->trigger_config_file_error(); +} + +%stack_overflow +{ + $this->internalError = true; + $this->compiler->trigger_config_file_error('Stack overflow in configfile parser'); +} + +// Complete config file +start(res) ::= global_vars sections. { + res = null; +} + +// Global vars +global_vars(res) ::= var_list(vl). { + $this->add_global_vars(vl); + res = null; +} + +// Sections +sections(res) ::= sections section. { + res = null; +} + +sections(res) ::= . { + res = null; +} + +section(res) ::= OPENB SECTION(i) CLOSEB newline var_list(vars). { + $this->add_section_vars(i, vars); + res = null; +} + +section(res) ::= OPENB DOT SECTION(i) CLOSEB newline var_list(vars). { + if ($this->configReadHidden) { + $this->add_section_vars(i, vars); + } + res = null; +} + +// Var list +var_list(res) ::= var_list(vl) newline. { + res = vl; +} + +var_list(res) ::= var_list(vl) var(v). { + res = array_merge(vl, array(v)); +} + +var_list(res) ::= . { + res = array(); +} + + +// Var +var(res) ::= ID(id) EQUAL value(v). { + res = array('key' => id, 'value' => v); +} + + +value(res) ::= FLOAT(i). { + res = (float) i; +} + +value(res) ::= INT(i). { + res = (int) i; +} + +value(res) ::= BOOL(i). { + res = $this->parse_bool(i); +} + +value(res) ::= SINGLE_QUOTED_STRING(i). { + res = self::parse_single_quoted_string(i); +} + +value(res) ::= DOUBLE_QUOTED_STRING(i). { + res = self::parse_double_quoted_string(i); +} + +value(res) ::= TRIPPLE_QUOTES(i) TRIPPLE_TEXT(c) TRIPPLE_QUOTES_END(ii). { + res = self::parse_tripple_double_quoted_string(c); +} + +value(res) ::= TRIPPLE_QUOTES(i) TRIPPLE_QUOTES_END(ii). { + res = ''; +} + +value(res) ::= NAKED_STRING(i). { + res = i; +} + +// NOTE: this is not a valid rule +// It is added hier to produce a usefull error message on a missing '='; +value(res) ::= OTHER(i). { + res = i; +} + + +// Newline and comments +newline(res) ::= NEWLINE. { + res = null; +} + +newline(res) ::= COMMENTSTART NEWLINE. { + res = null; +} + +newline(res) ::= COMMENTSTART NAKED_STRING NEWLINE. { + res = null; +} diff --git a/system/vendor/smarty/lexer/smarty_internal_templatelexer.plex b/system/vendor/smarty/lexer/smarty_internal_templatelexer.plex new file mode 100644 index 0000000..2cd46df --- /dev/null +++ b/system/vendor/smarty/lexer/smarty_internal_templatelexer.plex @@ -0,0 +1,687 @@ + + */ +class Smarty_Internal_Templatelexer +{ + /** + * Source + * + * @var string + */ + public $data; + + /** + * Source length + * + * @var int + */ + public $dataLength = null; + + /** + * byte counter + * + * @var int + */ + public $counter; + + /** + * token number + * + * @var int + */ + public $token; + + /** + * token value + * + * @var string + */ + public $value; + + /** + * current line + * + * @var int + */ + public $line; + + /** + * tag start line + * + * @var + */ + public $taglineno; + + /** + * php code type + * + * @var string + */ + public $phpType = ''; + + /** + * state number + * + * @var int + */ + public $state = 1; + + /** + * Smarty object + * + * @var Smarty + */ + public $smarty = null; + + /** + * compiler object + * + * @var Smarty_Internal_TemplateCompilerBase + */ + public $compiler = null; + + /** + * trace file + * + * @var resource + */ + public $yyTraceFILE; + + /** + * trace prompt + * + * @var string + */ + public $yyTracePrompt; + + /** + * XML flag true while processing xml + * + * @var bool + */ + public $is_xml = false; + + /** + * state names + * + * @var array + */ + public $state_name = array(1 => 'TEXT', 2 => 'TAG', 3 => 'TAGBODY', 4 => 'LITERAL', 5 => 'DOUBLEQUOTEDSTRING',); + + /** + * token names + * + * @var array + */ + public $smarty_token_names = array( // Text for parser error messages + 'NOT' => '(!,not)', + 'OPENP' => '(', + 'CLOSEP' => ')', + 'OPENB' => '[', + 'CLOSEB' => ']', + 'PTR' => '->', + 'APTR' => '=>', + 'EQUAL' => '=', + 'NUMBER' => 'number', + 'UNIMATH' => '+" , "-', + 'MATH' => '*" , "/" , "%', + 'INCDEC' => '++" , "--', + 'SPACE' => ' ', + 'DOLLAR' => '$', + 'SEMICOLON' => ';', + 'COLON' => ':', + 'DOUBLECOLON' => '::', + 'AT' => '@', + 'HATCH' => '#', + 'QUOTE' => '"', + 'BACKTICK' => '`', + 'VERT' => '"|" modifier', + 'DOT' => '.', + 'COMMA' => '","', + 'QMARK' => '"?"', + 'ID' => 'id, name', + 'TEXT' => 'text', + 'LDELSLASH' => '{/..} closing tag', + 'LDEL' => '{...} Smarty tag', + 'COMMENT' => 'comment', + 'AS' => 'as', + 'TO' => 'to', + 'LOGOP' => '"<", "==" ... logical operator', + 'TLOGOP' => '"lt", "eq" ... logical operator; "is div by" ... if condition', + 'SCOND' => '"is even" ... if condition', + ); + + /** + * literal tag nesting level + * + * @var int + */ + private $literal_cnt = 0; + + /** + * preg token pattern for state TEXT + * + * @var string + */ + private $yy_global_pattern1 = null; + + /** + * preg token pattern for state TAG + * + * @var string + */ + private $yy_global_pattern2 = null; + + /** + * preg token pattern for state TAGBODY + * + * @var string + */ + private $yy_global_pattern3 = null; + + /** + * preg token pattern for state LITERAL + * + * @var string + */ + private $yy_global_pattern4 = null; + + /** + * preg token pattern for state DOUBLEQUOTEDSTRING + * + * @var null + */ + private $yy_global_pattern5 = null; + + /** + * preg token pattern for text + * + * @var null + */ + private $yy_global_text = null; + + /** + * preg token pattern for literal + * + * @var null + */ + private $yy_global_literal = null; + + /** + * constructor + * + * @param string $source template source + * @param Smarty_Internal_TemplateCompilerBase $compiler + */ + public function __construct($source, Smarty_Internal_TemplateCompilerBase $compiler) + { + $this->data = $source; + $this->dataLength = strlen($this->data); + $this->counter = 0; + if (preg_match('/^\xEF\xBB\xBF/i', $this->data, $match)) { + $this->counter += strlen($match[0]); + } + $this->line = 1; + $this->smarty = $compiler->template->smarty; + $this->compiler = $compiler; + $this->compiler->initDelimiterPreg(); + $this->smarty_token_names['LDEL'] = $this->smarty->getLeftDelimiter(); + $this->smarty_token_names['RDEL'] = $this->smarty->getRightDelimiter(); + } + + /** + * open lexer/parser trace file + * + */ + public function PrintTrace() + { + $this->yyTraceFILE = fopen('php://output', 'w'); + $this->yyTracePrompt = '
'; + } + + /** + * replace placeholders with runtime preg code + * + * @param string $preg + * + * @return string + */ + public function replace($preg) + { + return $this->compiler->replaceDelimiter($preg); + } + + /** + * check if current value is an autoliteral left delimiter + * + * @return bool + */ + public function isAutoLiteral() + { + return $this->smarty->getAutoLiteral() && isset($this->value[ $this->compiler->getLdelLength() ]) ? + strpos(" \n\t\r", $this->value[ $this->compiler->getLdelLength() ]) !== false : false; + } + + /*!lex2php + %input $this->data + %counter $this->counter + %token $this->token + %value $this->value + %line $this->line + userliteral = ~(SMARTYldel)SMARTYautoliteral\s+SMARTYliteral~ + char = ~[\S\s]~ + textdoublequoted = ~([^"\\]*?)((?:\\.[^"\\]*?)*?)(?=((SMARTYldel)SMARTYal|\$|`\$|"SMARTYliteral))~ + namespace = ~([0-9]*[a-zA-Z_]\w*)?(\\[0-9]*[a-zA-Z_]\w*)+~ + emptyjava = ~[{][}]~ + slash = ~[/]~ + ldel = ~(SMARTYldel)SMARTYal~ + rdel = ~\s*SMARTYrdel~ + nocacherdel = ~(\s+nocache)?\s*SMARTYrdel~ + smartyblockchildparent = ~[\$]smarty\.block\.(child|parent)~ + integer = ~\d+~ + hex = ~0[xX][0-9a-fA-F]+~ + math = ~\s*([*]{1,2}|[%/^&]|[<>]{2})\s*~ + comment = ~(SMARTYldel)SMARTYal[*]~ + incdec = ~([+]|[-]){2}~ + unimath = ~\s*([+]|[-])\s*~ + openP = ~\s*[(]\s*~ + closeP = ~\s*[)]~ + openB = ~\[\s*~ + closeB = ~\s*\]~ + dollar = ~[$]~ + dot = ~[.]~ + comma = ~\s*[,]\s*~ + doublecolon = ~[:]{2}~ + colon = ~\s*[:]\s*~ + at = ~[@]~ + hatch = ~[#]~ + semicolon = ~\s*[;]\s*~ + equal = ~\s*[=]\s*~ + space = ~\s+~ + ptr = ~\s*[-][>]\s*~ + aptr = ~\s*[=][>]\s*~ + singlequotestring = ~'[^'\\]*(?:\\.[^'\\]*)*'~ + backtick = ~[`]~ + vert = ~[|][@]?~ + qmark = ~\s*[?]\s*~ + constant = ~[_]+[A-Z0-9][0-9A-Z_]*|[A-Z][0-9A-Z_]*(?![0-9A-Z_]*[a-z])~ + attr = ~\s+[0-9]*[a-zA-Z_][a-zA-Z0-9_\-:]*\s*[=]\s*~ + id = ~[0-9]*[a-zA-Z_]\w*~ + literal = ~literal~ + strip = ~strip~ + lop = ~\s*([!=][=]{1,2}|[<][=>]?|[>][=]?|[&|]{2})\s*~ + slop = ~\s+(eq|ne|neq|gt|ge|gte|lt|le|lte|mod|and|or|xor)\s+~ + tlop = ~\s+is\s+(not\s+)?(odd|even|div)\s+by\s+~ + scond = ~\s+is\s+(not\s+)?(odd|even)~ + isin = ~\s+is\s+in\s+~ + as = ~\s+as\s+~ + to = ~\s+to\s+~ + step = ~\s+step\s+~ + if = ~(if|elseif|else if|while)\s+~ + for = ~for\s+~ + makenocache = ~make_nocache\s+~ + array = ~array~ + foreach = ~foreach(?![^\s])~ + setfilter = ~setfilter\s+~ + instanceof = ~\s+instanceof\s+~ + not = ~[!]\s*|not\s+~ + typecast = ~[(](int(eger)?|bool(ean)?|float|double|real|string|binary|array|object)[)]\s*~ + double_quote = ~["]~ + */ + /*!lex2php + %statename TEXT + emptyjava { + $this->token = Smarty_Internal_Templateparser::TP_TEXT; + } + comment { + $to = $this->dataLength; + preg_match("/[*]{$this->compiler->getRdelPreg()}[\n]?/",$this->data,$match,PREG_OFFSET_CAPTURE,$this->counter); + if (isset($match[0][1])) { + $to = $match[0][1] + strlen($match[0][0]); + } else { + $this->compiler->trigger_template_error ("missing or misspelled comment closing tag '{$this->smarty->getRightDelimiter()}'"); + } + $this->value = substr($this->data,$this->counter,$to-$this->counter); + return false; + } + userliteral { + $this->token = Smarty_Internal_Templateparser::TP_TEXT; + } + ldel literal rdel { + $this->token = Smarty_Internal_Templateparser::TP_LITERALSTART; + $this->yypushstate(self::LITERAL); + } + ldel slash literal rdel { + $this->token = Smarty_Internal_Templateparser::TP_LITERALEND; + $this->yypushstate(self::LITERAL); + } + ldel { + $this->yypushstate(self::TAG); + return true; + } + char { + if (!isset($this->yy_global_text)) { + $this->yy_global_text = $this->replace('/(SMARTYldel)SMARTYal/isS'); + } + $to = $this->dataLength; + preg_match($this->yy_global_text, $this->data,$match,PREG_OFFSET_CAPTURE,$this->counter); + if (isset($match[0][1])) { + $to = $match[0][1]; + } + $this->value = substr($this->data,$this->counter,$to-$this->counter); + $this->token = Smarty_Internal_Templateparser::TP_TEXT; + } + */ + /*!lex2php + %statename TAG + ldel if { + $this->token = Smarty_Internal_Templateparser::TP_LDELIF; + $this->yybegin(self::TAGBODY); + $this->taglineno = $this->line; + } + ldel for { + $this->token = Smarty_Internal_Templateparser::TP_LDELFOR; + $this->yybegin(self::TAGBODY); + $this->taglineno = $this->line; + } + ldel foreach { + $this->token = Smarty_Internal_Templateparser::TP_LDELFOREACH; + $this->yybegin(self::TAGBODY); + $this->taglineno = $this->line; + } + ldel setfilter { + $this->token = Smarty_Internal_Templateparser::TP_LDELSETFILTER; + $this->yybegin(self::TAGBODY); + $this->taglineno = $this->line; + } + ldel makenocache { + $this->token = Smarty_Internal_Templateparser::TP_LDELMAKENOCACHE; + $this->yybegin(self::TAGBODY); + $this->taglineno = $this->line; + } + ldel id nocacherdel { + $this->yypopstate(); + $this->token = Smarty_Internal_Templateparser::TP_SIMPLETAG; + $this->taglineno = $this->line; + } + ldel smartyblockchildparent rdel { + $this->yypopstate(); + $this->token = Smarty_Internal_Templateparser::TP_SMARTYBLOCKCHILDPARENT; + $this->taglineno = $this->line; + } + ldel slash id rdel { + $this->yypopstate(); + $this->token = Smarty_Internal_Templateparser::TP_CLOSETAG; + $this->taglineno = $this->line; + } + ldel dollar id nocacherdel { + if ($this->_yy_stack[count($this->_yy_stack)-1] === self::TEXT) { + $this->yypopstate(); + $this->token = Smarty_Internal_Templateparser::TP_SIMPELOUTPUT; + $this->taglineno = $this->line; + } else { + $this->value = $this->smarty->getLeftDelimiter(); + $this->token = Smarty_Internal_Templateparser::TP_LDEL; + $this->yybegin(self::TAGBODY); + $this->taglineno = $this->line; + } + } + ldel slash { + $this->token = Smarty_Internal_Templateparser::TP_LDELSLASH; + $this->yybegin(self::TAGBODY); + $this->taglineno = $this->line; + } + ldel { + $this->token = Smarty_Internal_Templateparser::TP_LDEL; + $this->yybegin(self::TAGBODY); + $this->taglineno = $this->line; + } + */ + /*!lex2php + %statename TAGBODY + rdel { + $this->token = Smarty_Internal_Templateparser::TP_RDEL; + $this->yypopstate(); + } + ldel { + $this->yypushstate(self::TAG); + return true; + } + double_quote { + $this->token = Smarty_Internal_Templateparser::TP_QUOTE; + $this->yypushstate(self::DOUBLEQUOTEDSTRING); + $this->compiler->enterDoubleQuote(); + } + singlequotestring { + $this->token = Smarty_Internal_Templateparser::TP_SINGLEQUOTESTRING; + } + dollar id { + $this->token = Smarty_Internal_Templateparser::TP_DOLLARID; + } + dollar { + $this->token = Smarty_Internal_Templateparser::TP_DOLLAR; + } + isin { + $this->token = Smarty_Internal_Templateparser::TP_ISIN; + } + as { + $this->token = Smarty_Internal_Templateparser::TP_AS; + } + to { + $this->token = Smarty_Internal_Templateparser::TP_TO; + } + step { + $this->token = Smarty_Internal_Templateparser::TP_STEP; + } + instanceof { + $this->token = Smarty_Internal_Templateparser::TP_INSTANCEOF; + } + lop { + $this->token = Smarty_Internal_Templateparser::TP_LOGOP; + } + slop { + $this->token = Smarty_Internal_Templateparser::TP_SLOGOP; + } + tlop { + $this->token = Smarty_Internal_Templateparser::TP_TLOGOP; + } + scond { + $this->token = Smarty_Internal_Templateparser::TP_SINGLECOND; + } + not{ + $this->token = Smarty_Internal_Templateparser::TP_NOT; + } + typecast { + $this->token = Smarty_Internal_Templateparser::TP_TYPECAST; + } + openP { + $this->token = Smarty_Internal_Templateparser::TP_OPENP; + } + closeP { + $this->token = Smarty_Internal_Templateparser::TP_CLOSEP; + } + openB { + $this->token = Smarty_Internal_Templateparser::TP_OPENB; + } + closeB { + $this->token = Smarty_Internal_Templateparser::TP_CLOSEB; + } + ptr { + $this->token = Smarty_Internal_Templateparser::TP_PTR; + } + aptr { + $this->token = Smarty_Internal_Templateparser::TP_APTR; + } + equal { + $this->token = Smarty_Internal_Templateparser::TP_EQUAL; + } + incdec { + $this->token = Smarty_Internal_Templateparser::TP_INCDEC; + } + unimath { + $this->token = Smarty_Internal_Templateparser::TP_UNIMATH; + } + math { + $this->token = Smarty_Internal_Templateparser::TP_MATH; + } + at { + $this->token = Smarty_Internal_Templateparser::TP_AT; + } + array openP { + $this->token = Smarty_Internal_Templateparser::TP_ARRAYOPEN; + } + hatch { + $this->token = Smarty_Internal_Templateparser::TP_HATCH; + } + attr { + // resolve conflicts with shorttag and right_delimiter starting with '=' + if (substr($this->data, $this->counter + strlen($this->value) - 1, $this->compiler->getRdelLength()) === $this->smarty->getRightDelimiter()) { + preg_match('/\s+/',$this->value,$match); + $this->value = $match[0]; + $this->token = Smarty_Internal_Templateparser::TP_SPACE; + } else { + $this->token = Smarty_Internal_Templateparser::TP_ATTR; + } + } + namespace { + $this->token = Smarty_Internal_Templateparser::TP_NAMESPACE; + } + id { + $this->token = Smarty_Internal_Templateparser::TP_ID; + } + integer { + $this->token = Smarty_Internal_Templateparser::TP_INTEGER; + } + backtick { + $this->token = Smarty_Internal_Templateparser::TP_BACKTICK; + $this->yypopstate(); + } + vert { + $this->token = Smarty_Internal_Templateparser::TP_VERT; + } + dot { + $this->token = Smarty_Internal_Templateparser::TP_DOT; + } + comma { + $this->token = Smarty_Internal_Templateparser::TP_COMMA; + } + semicolon { + $this->token = Smarty_Internal_Templateparser::TP_SEMICOLON; + } + doublecolon { + $this->token = Smarty_Internal_Templateparser::TP_DOUBLECOLON; + } + colon { + $this->token = Smarty_Internal_Templateparser::TP_COLON; + } + qmark { + $this->token = Smarty_Internal_Templateparser::TP_QMARK; + } + hex { + $this->token = Smarty_Internal_Templateparser::TP_HEX; + } + space { + $this->token = Smarty_Internal_Templateparser::TP_SPACE; + } + char { + $this->token = Smarty_Internal_Templateparser::TP_TEXT; + } + */ + + /*!lex2php + %statename LITERAL + ldel literal rdel { + $this->literal_cnt++; + $this->token = Smarty_Internal_Templateparser::TP_LITERAL; + } + ldel slash literal rdel { + if ($this->literal_cnt) { + $this->literal_cnt--; + $this->token = Smarty_Internal_Templateparser::TP_LITERAL; + } else { + $this->token = Smarty_Internal_Templateparser::TP_LITERALEND; + $this->yypopstate(); + } + } + char { + if (!isset($this->yy_global_literal)) { + $this->yy_global_literal = $this->replace('/(SMARTYldel)SMARTYal[\/]?literalSMARTYrdel/isS'); + } + $to = $this->dataLength; + preg_match($this->yy_global_literal, $this->data,$match,PREG_OFFSET_CAPTURE,$this->counter); + if (isset($match[0][1])) { + $to = $match[0][1]; + } else { + $this->compiler->trigger_template_error ("missing or misspelled literal closing tag"); + } + $this->value = substr($this->data,$this->counter,$to-$this->counter); + $this->token = Smarty_Internal_Templateparser::TP_LITERAL; + } + */ + /*!lex2php + %statename DOUBLEQUOTEDSTRING + userliteral { + $this->token = Smarty_Internal_Templateparser::TP_TEXT; + } + ldel literal rdel { + $this->token = Smarty_Internal_Templateparser::TP_TEXT; + } + ldel slash literal rdel { + $this->token = Smarty_Internal_Templateparser::TP_TEXT; + } + ldel slash { + $this->yypushstate(self::TAG); + return true; + } + ldel id { + $this->yypushstate(self::TAG); + return true; + } + ldel { + $this->token = Smarty_Internal_Templateparser::TP_LDEL; + $this->taglineno = $this->line; + $this->yypushstate(self::TAGBODY); + } + double_quote { + $this->token = Smarty_Internal_Templateparser::TP_QUOTE; + $this->yypopstate(); + } + backtick dollar { + $this->token = Smarty_Internal_Templateparser::TP_BACKTICK; + $this->value = substr($this->value,0,-1); + $this->yypushstate(self::TAGBODY); + $this->taglineno = $this->line; + } + dollar id { + $this->token = Smarty_Internal_Templateparser::TP_DOLLARID; + } + dollar { + $this->token = Smarty_Internal_Templateparser::TP_TEXT; + } + textdoublequoted { + $this->token = Smarty_Internal_Templateparser::TP_TEXT; + } + char { + $to = $this->dataLength; + $this->value = substr($this->data,$this->counter,$to-$this->counter); + $this->token = Smarty_Internal_Templateparser::TP_TEXT; + } + */ + } + + \ No newline at end of file diff --git a/system/vendor/smarty/lexer/smarty_internal_templateparser.y b/system/vendor/smarty/lexer/smarty_internal_templateparser.y new file mode 100644 index 0000000..6204987 --- /dev/null +++ b/system/vendor/smarty/lexer/smarty_internal_templateparser.y @@ -0,0 +1,1269 @@ +/* + * This file is part of Smarty. + * + * (c) 2015 Uwe Tews + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +%stack_size 500 +%name TP_ +%declare_class { +/** +* Smarty Template Parser Class +* +* This is the template parser. +* It is generated from the smarty_internal_templateparser.y file +* +* @author Uwe Tews +*/ +class Smarty_Internal_Templateparser +} +%include_class +{ + const ERR1 = 'Security error: Call to private object member not allowed'; + const ERR2 = 'Security error: Call to dynamic object member not allowed'; + + /** + * result status + * + * @var bool + */ + public $successful = true; + + /** + * return value + * + * @var mixed + */ + public $retvalue = 0; + + /** + * @var + */ + public $yymajor; + + /** + * last index of array variable + * + * @var mixed + */ + public $last_index; + + /** + * last variable name + * + * @var string + */ + public $last_variable; + + /** + * root parse tree buffer + * + * @var Smarty_Internal_ParseTree_Template + */ + public $root_buffer; + + /** + * current parse tree object + * + * @var Smarty_Internal_ParseTree + */ + public $current_buffer; + + /** + * lexer object + * + * @var Smarty_Internal_Templatelexer + */ + public $lex; + + /** + * internal error flag + * + * @var bool + */ + private $internalError = false; + + /** + * {strip} status + * + * @var bool + */ + public $strip = false; + /** + * compiler object + * + * @var Smarty_Internal_TemplateCompilerBase + */ + public $compiler = null; + + /** + * smarty object + * + * @var Smarty + */ + public $smarty = null; + + /** + * template object + * + * @var Smarty_Internal_Template + */ + public $template = null; + + /** + * block nesting level + * + * @var int + */ + public $block_nesting_level = 0; + + /** + * security object + * + * @var Smarty_Security + */ + public $security = null; + + /** + * template prefix array + * + * @var \Smarty_Internal_ParseTree[] + */ + public $template_prefix = array(); + + /** + * template prefix array + * + * @var \Smarty_Internal_ParseTree[] + */ + public $template_postfix = array(); + + /** + * constructor + * + * @param Smarty_Internal_Templatelexer $lex + * @param Smarty_Internal_TemplateCompilerBase $compiler + */ + public function __construct(Smarty_Internal_Templatelexer $lex, Smarty_Internal_TemplateCompilerBase $compiler) + { + $this->lex = $lex; + $this->compiler = $compiler; + $this->template = $this->compiler->template; + $this->smarty = $this->template->smarty; + $this->security = isset($this->smarty->security_policy) ? $this->smarty->security_policy : false; + $this->current_buffer = $this->root_buffer = new Smarty_Internal_ParseTree_Template(); + } + + /** + * insert PHP code in current buffer + * + * @param string $code + */ + public function insertPhpCode($code) + { + $this->current_buffer->append_subtree($this, new Smarty_Internal_ParseTree_Tag($this, $code)); + } + + /** + * error rundown + * + */ + public function errorRunDown() + { + while ($this->yystack !== array()) { + $this->yy_pop_parser_stack(); + } + if (is_resource($this->yyTraceFILE)) { + fclose($this->yyTraceFILE); + } + } + + /** + * merge PHP code with prefix code and return parse tree tag object + * + * @param string $code + * + * @return Smarty_Internal_ParseTree_Tag + */ + public function mergePrefixCode($code) + { + $tmp = ''; + foreach ($this->compiler->prefix_code as $preCode) { + $tmp .= $preCode; + } + $this->compiler->prefix_code = array(); + $tmp .= $code; + return new Smarty_Internal_ParseTree_Tag($this, $this->compiler->processNocacheCode($tmp, true)); + } + +} + +%token_prefix TP_ + +%parse_accept +{ + $this->successful = !$this->internalError; + $this->internalError = false; + $this->retvalue = $this->_retvalue; +} + +%syntax_error +{ + $this->internalError = true; + $this->yymajor = $yymajor; + $this->compiler->trigger_template_error(); +} + +%stack_overflow +{ + $this->internalError = true; + $this->compiler->trigger_template_error('Stack overflow in template parser'); +} + + +%right VERT. +%left COLON. + + + // + // complete template + // +start(res) ::= template. { + $this->root_buffer->prepend_array($this, $this->template_prefix); + $this->root_buffer->append_array($this, $this->template_postfix); + res = $this->root_buffer->to_smarty_php($this); +} + + // template text +template ::= template TEXT(B). { + $text = $this->yystack[ $this->yyidx + 0 ]->minor; + + if ((string)$text == '') { + $this->current_buffer->append_subtree($this, null); + } + + $this->current_buffer->append_subtree($this, new Smarty_Internal_ParseTree_Text($text, $this->strip)); +} + // strip on +template ::= template STRIPON. { + $this->strip = true; +} + // strip off +template ::= template STRIPOFF. { + $this->strip = false; +} + + // Literal +template ::= template LITERALSTART literal_e2(B) LITERALEND. { + $this->current_buffer->append_subtree($this, new Smarty_Internal_ParseTree_Text(B)); +} + + +literal_e2(A) ::= literal_e1(B) LITERALSTART literal_e1(C) LITERALEND. { + A = B.C; +} +literal_e2(A) ::= literal_e1(B). { + A = B; +} + +literal_e1(A) ::= literal_e1(B) LITERAL(C). { + A = B.C; + +} + +literal_e1(A) ::= . { + A = ''; +} + // Smarty tag +template ::= template smartytag(B). { + if ($this->compiler->has_code) { + $this->current_buffer->append_subtree($this, $this->mergePrefixCode(B)); + } + $this->compiler->has_variable_string = false; + $this->block_nesting_level = count($this->compiler->_tag_stack); +} + + + // empty template +template ::= . + +smartytag(A) ::= SIMPELOUTPUT(B). { + $var = trim(substr(B, $this->compiler->getLdelLength(), -$this->compiler->getRdelLength()), ' $'); + if (preg_match('/^(.*)(\s+nocache)$/', $var, $match)) { + A = $this->compiler->compileTag('private_print_expression',array('nocache'),array('value'=>$this->compiler->compileVariable('\''.$match[1].'\''))); + } else { + A = $this->compiler->compileTag('private_print_expression',array(),array('value'=>$this->compiler->compileVariable('\''.$var.'\''))); + } +} + +// simple tag like {name} +smartytag(A)::= SIMPLETAG(B). { + $tag = trim(substr(B, $this->compiler->getLdelLength(), -$this->compiler->getRdelLength())); + if ($tag == 'strip') { + $this->strip = true; + A = null; + } else { + if (defined($tag)) { + if ($this->security) { + $this->security->isTrustedConstant($tag, $this->compiler); + } + A = $this->compiler->compileTag('private_print_expression',array(),array('value'=>$tag)); + } else { + if (preg_match('/^(.*)(\s+nocache)$/', $tag, $match)) { + A = $this->compiler->compileTag($match[1],array('\'nocache\'')); + } else { + A = $this->compiler->compileTag($tag,array()); + } + } + } +} + // {$smarty.block.child} or {$smarty.block.parent} +smartytag(A) ::= SMARTYBLOCKCHILDPARENT(i). { + $j = strrpos(i,'.'); + if (i[$j+1] == 'c') { + // {$smarty.block.child} + A = $this->compiler->compileTag('child',array(),array(i)); + } else { + // {$smarty.block.parent} + A = $this->compiler->compileTag('parent',array(),array(i)); + } +} + +smartytag(A) ::= LDEL tagbody(B) RDEL. { + A = B; +} + + smartytag(A) ::= tag(B) RDEL. { + A = B; + } + // output with optional attributes +tagbody(A) ::= outattr(B). { + A = $this->compiler->compileTag('private_print_expression',B[1],array('value'=>B[0])); +} + +// +// Smarty tags start here +// + + // assign new style +tagbody(A) ::= DOLLARID(B) eqoutattr(C). { + A = $this->compiler->compileTag('assign',array_merge(array(array('value'=>C[0]),array('var'=>'\''.substr(B,1).'\'')),C[1])); +} + +tagbody(A) ::= varindexed(B) eqoutattr(C). { + A = $this->compiler->compileTag('assign',array_merge(array(array('value'=>C[0]),array('var'=>B['var'])),C[1]),array('smarty_internal_index'=>B['smarty_internal_index'])); +} + +eqoutattr(A) ::= EQUAL outattr(B). { + A = B; +} + +outattr(A) ::= output(B) attributes(C). { + A = array(B,C); +} + +output(A) ::= variable(B). { + A = B; +} +output(A) ::= value(B). { + A = B; +} +output(A) ::= expr(B). { + A = B; +} + + // tag with optional Smarty2 style attributes +tag(res) ::= LDEL ID(i) attributes(a). { + if (defined(i)) { + if ($this->security) { + $this->security->isTrustedConstant(i, $this->compiler); + } + res = $this->compiler->compileTag('private_print_expression',a,array('value'=>i)); + } else { + res = $this->compiler->compileTag(i,a); + } +} +tag(res) ::= LDEL ID(i). { + if (defined(i)) { + if ($this->security) { + $this->security->isTrustedConstant(i, $this->compiler); + } + res = $this->compiler->compileTag('private_print_expression',array(),array('value'=>i)); + } else { + res = $this->compiler->compileTag(i,array()); + } +} + + + // tag with modifier and optional Smarty2 style attributes +tag(res) ::= LDEL ID(i) modifierlist(l)attributes(a). { + if (defined(i)) { + if ($this->security) { + $this->security->isTrustedConstant(i, $this->compiler); + } + res = $this->compiler->compileTag('private_print_expression',a,array('value'=>i, 'modifierlist'=>l)); + } else { + res = $this->compiler->compileTag(i,a, array('modifierlist'=>l)); + } +} + + // registered object tag +tag(res) ::= LDEL ID(i) PTR ID(m) attributes(a). { + res = $this->compiler->compileTag(i,a,array('object_method'=>m)); +} + + // registered object tag with modifiers +tag(res) ::= LDEL ID(i) PTR ID(me) modifierlist(l) attributes(a). { + res = $this->compiler->compileTag(i,a,array('modifierlist'=>l, 'object_method'=>me)); +} + + // nocache tag +tag(res) ::= LDELMAKENOCACHE DOLLARID(i). { + res = $this->compiler->compileTag('make_nocache',array(array('var'=>'\''.substr(i,1).'\''))); +} + + // {if}, {elseif} and {while} tag +tag(res) ::= LDELIF(i) expr(ie). { + $tag = trim(substr(i,$this->compiler->getLdelLength())); + res = $this->compiler->compileTag(($tag === 'else if')? 'elseif' : $tag,array(),array('if condition'=>ie)); +} + +tag(res) ::= LDELIF(i) expr(ie) attributes(a). { + $tag = trim(substr(i,$this->compiler->getLdelLength())); + res = $this->compiler->compileTag(($tag === 'else if')? 'elseif' : $tag,a,array('if condition'=>ie)); +} + +tag(res) ::= LDELIF(i) statement(ie). { + $tag = trim(substr(i,$this->compiler->getLdelLength())); + res = $this->compiler->compileTag(($tag === 'else if')? 'elseif' : $tag,array(),array('if condition'=>ie)); +} + +tag(res) ::= LDELIF(i) statement(ie) attributes(a). { + $tag = trim(substr(i,$this->compiler->getLdelLength())); + res = $this->compiler->compileTag(($tag === 'else if')? 'elseif' : $tag,a,array('if condition'=>ie)); +} + + // {for} tag +tag(res) ::= LDELFOR statements(st) SEMICOLON expr(ie) SEMICOLON varindexed(v2) foraction(e2) attributes(a). { + res = $this->compiler->compileTag('for',array_merge(a,array(array('start'=>st),array('ifexp'=>ie),array('var'=>v2),array('step'=>e2))),1); +} + + foraction(res) ::= EQUAL expr(e). { + res = '='.e; +} + + foraction(res) ::= INCDEC(e). { + res = e; +} + +tag(res) ::= LDELFOR statement(st) TO expr(v) attributes(a). { + res = $this->compiler->compileTag('for',array_merge(a,array(array('start'=>st),array('to'=>v))),0); +} + +tag(res) ::= LDELFOR statement(st) TO expr(v) STEP expr(v2) attributes(a). { + res = $this->compiler->compileTag('for',array_merge(a,array(array('start'=>st),array('to'=>v),array('step'=>v2))),0); +} + + // {foreach} tag +tag(res) ::= LDELFOREACH SPACE expr(e) AS varvar(v0) attributes(a). { + res = $this->compiler->compileTag('foreach',array_merge(a,array(array('from'=>e),array('item'=>v0)))); +} + +tag(res) ::= LDELFOREACH SPACE expr(e) AS varvar(v1) APTR varvar(v0) attributes(a). { + res = $this->compiler->compileTag('foreach',array_merge(a,array(array('from'=>e),array('item'=>v0),array('key'=>v1)))); +} +tag(res) ::= LDELFOREACH attributes(a). { + res = $this->compiler->compileTag('foreach',a); +} + + // {setfilter} +tag(res) ::= LDELSETFILTER ID(m) modparameters(p). { + res = $this->compiler->compileTag('setfilter',array(),array('modifier_list'=>array(array_merge(array(m),p)))); +} + +tag(res) ::= LDELSETFILTER ID(m) modparameters(p) modifierlist(l). { + res = $this->compiler->compileTag('setfilter',array(),array('modifier_list'=>array_merge(array(array_merge(array(m),p)),l))); +} + + + // end of block tag {/....} +smartytag(res)::= CLOSETAG(t). { + $tag = trim(substr(t, $this->compiler->getLdelLength(), -$this->compiler->getRdelLength()), ' /'); + if ($tag === 'strip') { + $this->strip = false; + res = null; + } else { + res = $this->compiler->compileTag($tag.'close',array()); + } + } +tag(res) ::= LDELSLASH ID(i). { + res = $this->compiler->compileTag(i.'close',array()); +} + +tag(res) ::= LDELSLASH ID(i) modifierlist(l). { + res = $this->compiler->compileTag(i.'close',array(),array('modifier_list'=>l)); +} + + // end of block object tag {/....} +tag(res) ::= LDELSLASH ID(i) PTR ID(m). { + res = $this->compiler->compileTag(i.'close',array(),array('object_method'=>m)); +} + +tag(res) ::= LDELSLASH ID(i) PTR ID(m) modifierlist(l). { + res = $this->compiler->compileTag(i.'close',array(),array('object_method'=>m, 'modifier_list'=>l)); +} + +// +//Attributes of Smarty tags +// + // list of attributes +attributes(res) ::= attributes(a1) attribute(a2). { + res = a1; + res[] = a2; +} + + // single attribute +attributes(res) ::= attribute(a). { + res = array(a); +} + + // no attributes +attributes(res) ::= . { + res = array(); +} + + // attribute +attribute(res) ::= SPACE ID(v) EQUAL ID(id). { + if (defined(id)) { + if ($this->security) { + $this->security->isTrustedConstant(id, $this->compiler); + } + res = array(v=>id); + } else { + res = array(v=>'\''.id.'\''); + } +} + +attribute(res) ::= ATTR(v) expr(e). { + res = array(trim(v," =\n\r\t")=>e); +} + +attribute(res) ::= ATTR(v) value(e). { + res = array(trim(v," =\n\r\t")=>e); +} + +attribute(res) ::= SPACE ID(v). { + res = '\''.v.'\''; +} + +attribute(res) ::= SPACE expr(e). { + res = e; +} + +attribute(res) ::= SPACE value(v). { + res = v; +} + +attribute(res) ::= SPACE INTEGER(i) EQUAL expr(e). { + res = array(i=>e); +} + + + +// +// statement +// +statements(res) ::= statement(s). { + res = array(s); +} + +statements(res) ::= statements(s1) COMMA statement(s). { + s1[]=s; + res = s1; +} + +statement(res) ::= DOLLARID(i) EQUAL INTEGER(e). { + res = array('var' => '\''.substr(i,1).'\'', 'value'=>e); +} +statement(res) ::= DOLLARID(i) EQUAL expr(e). { + res = array('var' => '\''.substr(i,1).'\'', 'value'=>e); +} + +statement(res) ::= varindexed(vi) EQUAL expr(e). { + res = array('var' => vi, 'value'=>e); +} + +statement(res) ::= OPENP statement(st) CLOSEP. { + res = st; +} + + +// +// expressions +// + + // single value +expr(res) ::= value(v). { + res = v; +} + + // ternary +expr(res) ::= ternary(v). { + res = v; +} + + // resources/streams +expr(res) ::= DOLLARID(i) COLON ID(i2). { + res = '$_smarty_tpl->getStreamVariable(\''.substr(i,1).'://' . i2 . '\')'; +} + + // arithmetic expression +expr(res) ::= expr(e) MATH(m) value(v). { + res = e . trim(m) . v; +} + +expr(res) ::= expr(e) UNIMATH(m) value(v). { + res = e . trim(m) . v; +} + +// if expression + // special conditions +expr(res) ::= expr(e1) tlop(c) value(e2). { + res = c['pre']. e1.c['op'].e2 .')'; +} + // simple expression +expr(res) ::= expr(e1) lop(c) expr(e2). { + res = e1.c.e2; +} + +expr(res) ::= expr(e1) scond(c). { + res = c . e1 . ')'; +} + +expr(res) ::= expr(e1) ISIN array(a). { + res = 'in_array('.e1.','.a.')'; +} + +expr(res) ::= expr(e1) ISIN value(v). { + res = 'in_array('.e1.',(array)'.v.')'; +} + + +// +// ternary +// +ternary(res) ::= OPENP expr(v) CLOSEP QMARK DOLLARID(e1) COLON expr(e2). { + res = v.' ? '. $this->compiler->compileVariable('\''.substr(e1,1).'\'') . ' : '.e2; +} + +ternary(res) ::= OPENP expr(v) CLOSEP QMARK expr(e1) COLON expr(e2). { + res = v.' ? '.e1.' : '.e2; +} + + // value +value(res) ::= variable(v). { + res = v; +} + + // +/- value +value(res) ::= UNIMATH(m) value(v). { + res = m.v; +} + + // logical negation +value(res) ::= NOT value(v). { + res = '!'.v; +} + +value(res) ::= TYPECAST(t) value(v). { + res = t.v; +} + +value(res) ::= variable(v) INCDEC(o). { + res = v.o; +} + + // numeric +value(res) ::= HEX(n). { + res = n; +} + +value(res) ::= INTEGER(n). { + res = n; +} + +value(res) ::= INTEGER(n1) DOT INTEGER(n2). { + res = n1.'.'.n2; +} + +value(res) ::= INTEGER(n1) DOT. { + res = n1.'.'; +} + +value(res) ::= DOT INTEGER(n1). { + res = '.'.n1; +} + + // ID, true, false, null +value(res) ::= ID(id). { + if (defined(id)) { + if ($this->security) { + $this->security->isTrustedConstant(id, $this->compiler); + } + res = id; + } else { + res = '\''.id.'\''; + } +} + + // function call +value(res) ::= function(f). { + res = f; +} + + // expression +value(res) ::= OPENP expr(e) CLOSEP. { + res = '('. e .')'; +} + +value(res) ::= variable(v1) INSTANCEOF(i) ns1(v2). { + res = v1.i.v2; +} +value(res) ::= variable(v1) INSTANCEOF(i) variable(v2). { + res = v1.i.v2; +} + + // singele quoted string +value(res) ::= SINGLEQUOTESTRING(t). { + res = t; +} + + // double quoted string +value(res) ::= doublequoted_with_quotes(s). { + res = s; +} + + +value(res) ::= varindexed(vi) DOUBLECOLON static_class_access(r). { + if ($this->security && $this->security->static_classes !== array()) { + $this->compiler->trigger_template_error('dynamic static class not allowed by security setting'); + } + $prefixVar = $this->compiler->getNewPrefixVariable(); + if (vi['var'] === '\'smarty\'') { + $this->compiler->appendPrefixCode("compiler->compileTag('private_special_variable',array(),vi['smarty_internal_index']).';?>'); + } else { + $this->compiler->appendPrefixCode("compiler->compileVariable(vi['var']).vi['smarty_internal_index'].';?>'); + } + res = $prefixVar .'::'.r[0].r[1]; +} + + // Smarty tag +value(res) ::= smartytag(st). { + $prefixVar = $this->compiler->getNewPrefixVariable(); + $tmp = $this->compiler->appendCode('', st); + $this->compiler->appendPrefixCode($this->compiler->appendCode($tmp, "")); + res = $prefixVar; +} + +value(res) ::= value(v) modifierlist(l). { + res = $this->compiler->compileTag('private_modifier',array(),array('value'=>v,'modifierlist'=>l)); +} + // name space constant +value(res) ::= NAMESPACE(c). { + res = c; +} + + // array +value(res) ::= arraydef(a). { + res = a; +} + // static class access +value(res) ::= ns1(c)DOUBLECOLON static_class_access(s). { + if (!in_array(strtolower(c), array('self', 'parent')) && (!$this->security || $this->security->isTrustedStaticClassAccess(c, s, $this->compiler))) { + if (isset($this->smarty->registered_classes[c])) { + res = $this->smarty->registered_classes[c].'::'.s[0].s[1]; + } else { + res = c.'::'.s[0].s[1]; + } + } else { + $this->compiler->trigger_template_error ('static class \''.c.'\' is undefined or not allowed by security setting'); + } +} +// +// namespace stuff +// + +ns1(res) ::= ID(i). { + res = i; +} + +ns1(res) ::= NAMESPACE(i). { + res = i; + } + + + + +// +// variables +// + // Smarty variable (optional array) +variable(res) ::= DOLLARID(i). { + res = $this->compiler->compileVariable('\''.substr(i,1).'\''); +} +variable(res) ::= varindexed(vi). { + if (vi['var'] === '\'smarty\'') { + $smarty_var = $this->compiler->compileTag('private_special_variable',array(),vi['smarty_internal_index']); + res = $smarty_var; + } else { + // used for array reset,next,prev,end,current + $this->last_variable = vi['var']; + $this->last_index = vi['smarty_internal_index']; + res = $this->compiler->compileVariable(vi['var']).vi['smarty_internal_index']; + } +} + + // variable with property +variable(res) ::= varvar(v) AT ID(p). { + res = '$_smarty_tpl->tpl_vars['. v .']->'.p; +} + + // object +variable(res) ::= object(o). { + res = o; +} + + // config variable +variable(res) ::= HATCH ID(i) HATCH. { + res = $this->compiler->compileConfigVariable('\'' . i . '\''); +} + +variable(res) ::= HATCH ID(i) HATCH arrayindex(a). { + res = '(is_array($tmp = ' . $this->compiler->compileConfigVariable('\'' . i . '\'') . ') ? $tmp'.a.' :null)'; +} + +variable(res) ::= HATCH variable(v) HATCH. { + res = $this->compiler->compileConfigVariable(v); +} + +variable(res) ::= HATCH variable(v) HATCH arrayindex(a). { + res = '(is_array($tmp = ' . $this->compiler->compileConfigVariable(v) . ') ? $tmp'.a.' : null)'; +} + +varindexed(res) ::= DOLLARID(i) arrayindex(a). { + res = array('var'=>'\''.substr(i,1).'\'', 'smarty_internal_index'=>a); +} +varindexed(res) ::= varvar(v) arrayindex(a). { + res = array('var'=>v, 'smarty_internal_index'=>a); +} + +// +// array index +// + // multiple array index +arrayindex(res) ::= arrayindex(a1) indexdef(a2). { + res = a1.a2; +} + + // no array index +arrayindex ::= . { + return; +} + +// single index definition + // Smarty2 style index +indexdef(res) ::= DOT DOLLARID(i). { + res = '['.$this->compiler->compileVariable('\''.substr(i,1).'\'').']'; +} +indexdef(res) ::= DOT varvar(v). { + res = '['.$this->compiler->compileVariable(v).']'; +} + +indexdef(res) ::= DOT varvar(v) AT ID(p). { + res = '['.$this->compiler->compileVariable(v).'->'.p.']'; +} + +indexdef(res) ::= DOT ID(i). { + res = '[\''. i .'\']'; +} + +indexdef(res) ::= DOT INTEGER(n). { + res = '['. n .']'; +} + + +indexdef(res) ::= DOT LDEL expr(e) RDEL. { + res = '['. e .']'; +} + + // section tag index +indexdef(res) ::= OPENB ID(i)CLOSEB. { + res = '['.$this->compiler->compileTag('private_special_variable',array(),'[\'section\'][\''.i.'\'][\'index\']').']'; +} + +indexdef(res) ::= OPENB ID(i) DOT ID(i2) CLOSEB. { + res = '['.$this->compiler->compileTag('private_special_variable',array(),'[\'section\'][\''.i.'\'][\''.i2.'\']').']'; +} +indexdef(res) ::= OPENB SINGLEQUOTESTRING(s) CLOSEB. { + res = '['.s.']'; +} +indexdef(res) ::= OPENB INTEGER(n) CLOSEB. { + res = '['.n.']'; +} +indexdef(res) ::= OPENB DOLLARID(i) CLOSEB. { + res = '['.$this->compiler->compileVariable('\''.substr(i,1).'\'').']'; +} +indexdef(res) ::= OPENB variable(v) CLOSEB. { + res = '['.v.']'; +} +indexdef(res) ::= OPENB value(v) CLOSEB. { + res = '['.v.']'; +} + + // PHP style index +indexdef(res) ::= OPENB expr(e) CLOSEB. { + res = '['. e .']'; +} + + // for assign append array +indexdef(res) ::= OPENB CLOSEB. { + res = '[]'; +} + + +// +// variable variable names +// + + // singel identifier element +varvar(res) ::= DOLLARID(i). { + res = '\''.substr(i,1).'\''; +} + // single $ +varvar(res) ::= DOLLAR. { + res = '\'\''; +} + + // sequence of identifier elements +varvar(res) ::= varvar(v1) varvarele(v2). { + res = v1.'.'.v2; +} + + // fix sections of element +varvarele(res) ::= ID(s). { + res = '\''.s.'\''; +} +varvarele(res) ::= SIMPELOUTPUT(i). { + $var = trim(substr(i, $this->compiler->getLdelLength(), -$this->compiler->getRdelLength()), ' $'); + res = $this->compiler->compileVariable('\''.$var.'\''); +} + + // variable sections of element +varvarele(res) ::= LDEL expr(e) RDEL. { + res = '('.e.')'; +} + +// +// objects +// +object(res) ::= varindexed(vi) objectchain(oc). { + if (vi['var'] === '\'smarty\'') { + res = $this->compiler->compileTag('private_special_variable',array(),vi['smarty_internal_index']).oc; + } else { + res = $this->compiler->compileVariable(vi['var']).vi['smarty_internal_index'].oc; + } +} + + // single element +objectchain(res) ::= objectelement(oe). { + res = oe; +} + + // chain of elements +objectchain(res) ::= objectchain(oc) objectelement(oe). { + res = oc.oe; +} + + // variable +objectelement(res)::= PTR ID(i) arrayindex(a). { + if ($this->security && substr(i,0,1) === '_') { + $this->compiler->trigger_template_error (self::ERR1); + } + res = '->'.i.a; +} + +objectelement(res)::= PTR varvar(v) arrayindex(a). { + if ($this->security) { + $this->compiler->trigger_template_error (self::ERR2); + } + res = '->{'.$this->compiler->compileVariable(v).a.'}'; +} + +objectelement(res)::= PTR LDEL expr(e) RDEL arrayindex(a). { + if ($this->security) { + $this->compiler->trigger_template_error (self::ERR2); + } + res = '->{'.e.a.'}'; +} + +objectelement(res)::= PTR ID(ii) LDEL expr(e) RDEL arrayindex(a). { + if ($this->security) { + $this->compiler->trigger_template_error (self::ERR2); + } + res = '->{\''.ii.'\'.'.e.a.'}'; +} + + // method +objectelement(res)::= PTR method(f). { + res = '->'.f; +} + + +// +// function +// +function(res) ::= ns1(f) OPENP params(p) CLOSEP. { + res = $this->compiler->compilePHPFunctionCall(f, p); +} + + +// +// method +// +method(res) ::= ID(f) OPENP params(p) CLOSEP. { + if ($this->security && substr(f,0,1) === '_') { + $this->compiler->trigger_template_error (self::ERR1); + } + res = f . '('. implode(',',p) .')'; +} + +method(res) ::= DOLLARID(f) OPENP params(p) CLOSEP. { + if ($this->security) { + $this->compiler->trigger_template_error (self::ERR2); + } + $prefixVar = $this->compiler->getNewPrefixVariable(); + $this->compiler->appendPrefixCode("compiler->compileVariable('\''.substr(f,1).'\'').';?>'); + res = $prefixVar .'('. implode(',',p) .')'; +} + +// function/method parameter + // multiple parameters +params(res) ::= params(p) COMMA expr(e). { + res = array_merge(p,array(e)); +} + + // single parameter +params(res) ::= expr(e). { + res = array(e); +} + + // kein parameter +params(res) ::= . { + res = array(); +} + +// +// modifier +// +modifierlist(res) ::= modifierlist(l) modifier(m) modparameters(p). { + res = array_merge(l,array(array_merge(m,p))); +} + +modifierlist(res) ::= modifier(m) modparameters(p). { + res = array(array_merge(m,p)); +} + +modifier(res) ::= VERT AT ID(m). { + res = array(m); +} + +modifier(res) ::= VERT ID(m). { + res = array(m); +} + +// +// modifier parameter +// + // multiple parameter +modparameters(res) ::= modparameters(mps) modparameter(mp). { + res = array_merge(mps,mp); +} + + // no parameter +modparameters(res) ::= . { + res = array(); +} + + // parameter expression +modparameter(res) ::= COLON value(mp). { + res = array(mp); +} +modparameter(res) ::= COLON UNIMATH(m) value(mp). { + res = array(trim(m).mp); +} + +modparameter(res) ::= COLON array(mp). { + res = array(mp); +} + + // static class methode call +static_class_access(res) ::= method(m). { + res = array(m, '', 'method'); +} + + // static class methode call with object chainig +static_class_access(res) ::= method(m) objectchain(oc). { + res = array(m, oc, 'method'); +} + + // static class constant +static_class_access(res) ::= ID(v). { + res = array(v, ''); +} + + // static class variables +static_class_access(res) ::= DOLLARID(v) arrayindex(a). { + res = array(v, a, 'property'); +} + + // static class variables with object chain +static_class_access(res) ::= DOLLARID(v) arrayindex(a) objectchain(oc). { + res = array(v, a.oc, 'property'); +} + + +// if conditions and operators +lop(res) ::= LOGOP(o). { + res = ' '. trim(o) . ' '; +} + +lop(res) ::= SLOGOP(o). { + static $lops = array( + 'eq' => ' == ', + 'ne' => ' != ', + 'neq' => ' != ', + 'gt' => ' > ', + 'ge' => ' >= ', + 'gte' => ' >= ', + 'lt' => ' < ', + 'le' => ' <= ', + 'lte' => ' <= ', + 'mod' => ' % ', + 'and' => ' && ', + 'or' => ' || ', + 'xor' => ' xor ', + ); + $op = strtolower(preg_replace('/\s*/', '', o)); + res = $lops[$op]; +} +tlop(res) ::= TLOGOP(o). { + static $tlops = array( + 'isdivby' => array('op' => ' % ', 'pre' => '!('), + 'isnotdivby' => array('op' => ' % ', 'pre' => '('), + 'isevenby' => array('op' => ' / ', 'pre' => '!(1 & '), + 'isnotevenby' => array('op' => ' / ', 'pre' => '(1 & '), + 'isoddby' => array('op' => ' / ', 'pre' => '(1 & '), + 'isnotoddby' => array('op' => ' / ', 'pre' => '!(1 & '), + ); + $op = strtolower(preg_replace('/\s*/', '', o)); + res = $tlops[$op]; + } + +scond(res) ::= SINGLECOND(o). { + static $scond = array ( + 'iseven' => '!(1 & ', + 'isnoteven' => '(1 & ', + 'isodd' => '(1 & ', + 'isnotodd' => '!(1 & ', + ); + $op = strtolower(str_replace(' ', '', o)); + res = $scond[$op]; +} + +// +// ARRAY element assignment +// +arraydef(res) ::= OPENB arrayelements(a) CLOSEB. { + res = 'array('.a.')'; +} +arraydef(res) ::= ARRAYOPEN arrayelements(a) CLOSEP. { + res = 'array('.a.')'; +} + +arrayelements(res) ::= arrayelement(a). { + res = a; +} + +arrayelements(res) ::= arrayelements(a1) COMMA arrayelement(a). { + res = a1.','.a; +} + +arrayelements ::= . { + return; +} + +arrayelement(res) ::= value(e1) APTR expr(e2). { + res = e1.'=>'.e2; +} + +arrayelement(res) ::= ID(i) APTR expr(e2). { + res = '\''.i.'\'=>'.e2; +} + +arrayelement(res) ::= expr(e). { + res = e; +} + + +// +// double quoted strings +// +doublequoted_with_quotes(res) ::= QUOTE QUOTE. { + res = '\'\''; +} + +doublequoted_with_quotes(res) ::= QUOTE doublequoted(s) QUOTE. { + $this->compiler->leaveDoubleQuote(); + res = s->to_smarty_php($this); +} + + +doublequoted(res) ::= doublequoted(o1) doublequotedcontent(o2). { + o1->append_subtree($this, o2); + res = o1; +} + +doublequoted(res) ::= doublequotedcontent(o). { + res = new Smarty_Internal_ParseTree_Dq($this, o); +} + +doublequotedcontent(res) ::= BACKTICK variable(v) BACKTICK. { + res = new Smarty_Internal_ParseTree_Code('(string)'.v); +} + +doublequotedcontent(res) ::= BACKTICK expr(e) BACKTICK. { + res = new Smarty_Internal_ParseTree_Code('(string)('.e.')'); +} + +doublequotedcontent(res) ::= DOLLARID(i). { + res = new Smarty_Internal_ParseTree_Code('(string)$_smarty_tpl->tpl_vars[\''. substr(i,1) .'\']->value'); +} + +doublequotedcontent(res) ::= LDEL variable(v) RDEL. { + res = new Smarty_Internal_ParseTree_Code('(string)'.v); +} + +doublequotedcontent(res) ::= LDEL expr(e) RDEL. { + res = new Smarty_Internal_ParseTree_Code('(string)('.e.')'); +} + +doublequotedcontent(res) ::= smartytag(st). { + res = new Smarty_Internal_ParseTree_Tag($this, st); +} + +doublequotedcontent(res) ::= TEXT(o). { + res = new Smarty_Internal_ParseTree_DqContent(o); +} + diff --git a/system/vendor/smarty/libs/Autoloader.php b/system/vendor/smarty/libs/Autoloader.php new file mode 100644 index 0000000..da7e32a --- /dev/null +++ b/system/vendor/smarty/libs/Autoloader.php @@ -0,0 +1,111 @@ + 'Smarty.class.php'); + + /** + * Registers Smarty_Autoloader backward compatible to older installations. + * + * @param bool $prepend Whether to prepend the autoloader or not. + */ + public static function registerBC($prepend = false) + { + /** + * register the class autoloader + */ + if (!defined('SMARTY_SPL_AUTOLOAD')) { + define('SMARTY_SPL_AUTOLOAD', 0); + } + if (SMARTY_SPL_AUTOLOAD + && set_include_path(get_include_path() . PATH_SEPARATOR . SMARTY_SYSPLUGINS_DIR) !== false + ) { + $registeredAutoLoadFunctions = spl_autoload_functions(); + if (!isset($registeredAutoLoadFunctions[ 'spl_autoload' ])) { + spl_autoload_register(); + } + } else { + self::register($prepend); + } + } + + /** + * Registers Smarty_Autoloader as an SPL autoloader. + * + * @param bool $prepend Whether to prepend the autoloader or not. + */ + public static function register($prepend = false) + { + self::$SMARTY_DIR = defined('SMARTY_DIR') ? SMARTY_DIR : __DIR__ . DIRECTORY_SEPARATOR; + self::$SMARTY_SYSPLUGINS_DIR = defined('SMARTY_SYSPLUGINS_DIR') ? SMARTY_SYSPLUGINS_DIR : + self::$SMARTY_DIR . 'sysplugins' . DIRECTORY_SEPARATOR; + spl_autoload_register(array(__CLASS__, 'autoload'), true, $prepend); + } + + /** + * Handles auto loading of classes. + * + * @param string $class A class name. + */ + public static function autoload($class) + { + if ($class[ 0 ] !== 'S' || strpos($class, 'Smarty') !== 0) { + return; + } + $_class = smarty_strtolower_ascii($class); + if (isset(self::$rootClasses[ $_class ])) { + $file = self::$SMARTY_DIR . self::$rootClasses[ $_class ]; + if (is_file($file)) { + include $file; + } + } else { + $file = self::$SMARTY_SYSPLUGINS_DIR . $_class . '.php'; + if (is_file($file)) { + include $file; + } + } + return; + } +} diff --git a/system/vendor/smarty/libs/Smarty.class.php b/system/vendor/smarty/libs/Smarty.class.php new file mode 100644 index 0000000..81dc6ab --- /dev/null +++ b/system/vendor/smarty/libs/Smarty.class.php @@ -0,0 +1,1405 @@ + + * @author Uwe Tews + * @author Rodney Rehm + * @package Smarty + */ +/** + * set SMARTY_DIR to absolute path to Smarty library files. + * Sets SMARTY_DIR only if user application has not already defined it. + */ +if (!defined('SMARTY_DIR')) { + /** + * + */ + define('SMARTY_DIR', __DIR__ . DIRECTORY_SEPARATOR); +} +/** + * set SMARTY_SYSPLUGINS_DIR to absolute path to Smarty internal plugins. + * Sets SMARTY_SYSPLUGINS_DIR only if user application has not already defined it. + */ +if (!defined('SMARTY_SYSPLUGINS_DIR')) { + /** + * + */ + define('SMARTY_SYSPLUGINS_DIR', SMARTY_DIR . 'sysplugins' . DIRECTORY_SEPARATOR); +} +if (!defined('SMARTY_PLUGINS_DIR')) { + /** + * + */ + define('SMARTY_PLUGINS_DIR', SMARTY_DIR . 'plugins' . DIRECTORY_SEPARATOR); +} +if (!defined('SMARTY_MBSTRING')) { + /** + * + */ + define('SMARTY_MBSTRING', function_exists('mb_get_info')); +} + +/** + * Load helper functions + */ +if (!defined('SMARTY_HELPER_FUNCTIONS_LOADED')) { + include __DIR__ . '/functions.php'; +} + +/** + * Load Smarty_Autoloader + */ +if (!class_exists('Smarty_Autoloader')) { + include __DIR__ . '/bootstrap.php'; +} + +/** + * Load always needed external class files + */ +require_once SMARTY_SYSPLUGINS_DIR . 'smarty_internal_data.php'; +require_once SMARTY_SYSPLUGINS_DIR . 'smarty_internal_extension_handler.php'; +require_once SMARTY_SYSPLUGINS_DIR . 'smarty_internal_templatebase.php'; +require_once SMARTY_SYSPLUGINS_DIR . 'smarty_internal_template.php'; +require_once SMARTY_SYSPLUGINS_DIR . 'smarty_resource.php'; +require_once SMARTY_SYSPLUGINS_DIR . 'smarty_variable.php'; +require_once SMARTY_SYSPLUGINS_DIR . 'smarty_template_source.php'; +require_once SMARTY_SYSPLUGINS_DIR . 'smarty_template_resource_base.php'; +require_once SMARTY_SYSPLUGINS_DIR . 'smarty_internal_resource_file.php'; + +/** + * This is the main Smarty class + * + * @package Smarty + * + * The following methods will be dynamically loaded by the extension handler when they are called. + * They are located in a corresponding Smarty_Internal_Method_xxxx class + * + * @method int clearAllCache(int $exp_time = null, string $type = null) + * @method int clearCache(string $template_name, string $cache_id = null, string $compile_id = null, int $exp_time = null, string $type = null) + * @method int compileAllTemplates(string $extension = '.tpl', bool $force_compile = false, int $time_limit = 0, $max_errors = null) + * @method int compileAllConfig(string $extension = '.conf', bool $force_compile = false, int $time_limit = 0, $max_errors = null) + * @method int clearCompiledTemplate($resource_name = null, $compile_id = null, $exp_time = null) + */ +class Smarty extends Smarty_Internal_TemplateBase +{ + /** + * smarty version + */ + const SMARTY_VERSION = '4.3.1'; + /** + * define variable scopes + */ + const SCOPE_LOCAL = 1; + const SCOPE_PARENT = 2; + const SCOPE_TPL_ROOT = 4; + const SCOPE_ROOT = 8; + const SCOPE_SMARTY = 16; + const SCOPE_GLOBAL = 32; + /** + * define caching modes + */ + const CACHING_OFF = 0; + const CACHING_LIFETIME_CURRENT = 1; + const CACHING_LIFETIME_SAVED = 2; + /** + * define constant for clearing cache files be saved expiration dates + */ + const CLEAR_EXPIRED = -1; + /** + * define compile check modes + */ + const COMPILECHECK_OFF = 0; + const COMPILECHECK_ON = 1; + const COMPILECHECK_CACHEMISS = 2; + /** + * define debug modes + */ + const DEBUG_OFF = 0; + const DEBUG_ON = 1; + const DEBUG_INDIVIDUAL = 2; + + /** + * filter types + */ + const FILTER_POST = 'post'; + const FILTER_PRE = 'pre'; + const FILTER_OUTPUT = 'output'; + const FILTER_VARIABLE = 'variable'; + /** + * plugin types + */ + const PLUGIN_FUNCTION = 'function'; + const PLUGIN_BLOCK = 'block'; + const PLUGIN_COMPILER = 'compiler'; + const PLUGIN_MODIFIER = 'modifier'; + const PLUGIN_MODIFIERCOMPILER = 'modifiercompiler'; + + /** + * assigned global tpl vars + */ + public static $global_tpl_vars = array(); + + /** + * Flag denoting if Multibyte String functions are available + */ + public static $_MBSTRING = SMARTY_MBSTRING; + + /** + * The character set to adhere to (e.g. "UTF-8") + */ + public static $_CHARSET = SMARTY_MBSTRING ? 'UTF-8' : 'ISO-8859-1'; + + /** + * The date format to be used internally + * (accepts date() and strftime()) + */ + public static $_DATE_FORMAT = '%b %e, %Y'; + + /** + * Flag denoting if PCRE should run in UTF-8 mode + */ + public static $_UTF8_MODIFIER = 'u'; + + /** + * Flag denoting if operating system is windows + */ + public static $_IS_WINDOWS = false; + + /** + * auto literal on delimiters with whitespace + * + * @var boolean + */ + public $auto_literal = true; + + /** + * display error on not assigned variables + * + * @var boolean + */ + public $error_unassigned = false; + + /** + * look up relative file path in include_path + * + * @var boolean + */ + public $use_include_path = false; + + /** + * flag if template_dir is normalized + * + * @var bool + */ + public $_templateDirNormalized = false; + + /** + * joined template directory string used in cache keys + * + * @var string + */ + public $_joined_template_dir = null; + + /** + * flag if config_dir is normalized + * + * @var bool + */ + public $_configDirNormalized = false; + + /** + * joined config directory string used in cache keys + * + * @var string + */ + public $_joined_config_dir = null; + + /** + * default template handler + * + * @var callable + */ + public $default_template_handler_func = null; + + /** + * default config handler + * + * @var callable + */ + public $default_config_handler_func = null; + + /** + * default plugin handler + * + * @var callable + */ + public $default_plugin_handler_func = null; + + /** + * flag if template_dir is normalized + * + * @var bool + */ + public $_compileDirNormalized = false; + + /** + * flag if plugins_dir is normalized + * + * @var bool + */ + public $_pluginsDirNormalized = false; + + /** + * flag if template_dir is normalized + * + * @var bool + */ + public $_cacheDirNormalized = false; + + /** + * force template compiling? + * + * @var boolean + */ + public $force_compile = false; + + /** + * use sub dirs for compiled/cached files? + * + * @var boolean + */ + public $use_sub_dirs = false; + + /** + * allow ambiguous resources (that are made unique by the resource handler) + * + * @var boolean + */ + public $allow_ambiguous_resources = false; + + /** + * merge compiled includes + * + * @var boolean + */ + public $merge_compiled_includes = false; + + /* + * flag for behaviour when extends: resource and {extends} tag are used simultaneous + * if false disable execution of {extends} in templates called by extends resource. + * (behaviour as versions < 3.1.28) + * + * @var boolean + */ + public $extends_recursion = true; + + /** + * force cache file creation + * + * @var boolean + */ + public $force_cache = false; + + /** + * template left-delimiter + * + * @var string + */ + public $left_delimiter = "{"; + + /** + * template right-delimiter + * + * @var string + */ + public $right_delimiter = "}"; + + /** + * array of strings which shall be treated as literal by compiler + * + * @var array string + */ + public $literals = array(); + + /** + * class name + * This should be instance of Smarty_Security. + * + * @var string + * @see Smarty_Security + */ + public $security_class = 'Smarty_Security'; + + /** + * implementation of security class + * + * @var Smarty_Security + */ + public $security_policy = null; + + /** + * controls if the php template file resource is allowed + * + * @var bool + */ + public $allow_php_templates = false; + + /** + * debug mode + * Setting this to true enables the debug-console. + * + * @var boolean + */ + public $debugging = false; + + /** + * This determines if debugging is enable-able from the browser. + *
    + *
  • NONE => no debugging control allowed
  • + *
  • URL => enable debugging when SMARTY_DEBUG is found in the URL.
  • + *
+ * + * @var string + */ + public $debugging_ctrl = 'NONE'; + + /** + * Name of debugging URL-param. + * Only used when $debugging_ctrl is set to 'URL'. + * The name of the URL-parameter that activates debugging. + * + * @var string + */ + public $smarty_debug_id = 'SMARTY_DEBUG'; + + /** + * Path of debug template. + * + * @var string + */ + public $debug_tpl = null; + + /** + * When set, smarty uses this value as error_reporting-level. + * + * @var int + */ + public $error_reporting = null; + + /** + * Controls whether variables with the same name overwrite each other. + * + * @var boolean + */ + public $config_overwrite = true; + + /** + * Controls whether config values of on/true/yes and off/false/no get converted to boolean. + * + * @var boolean + */ + public $config_booleanize = true; + + /** + * Controls whether hidden config sections/vars are read from the file. + * + * @var boolean + */ + public $config_read_hidden = false; + + /** + * locking concurrent compiles + * + * @var boolean + */ + public $compile_locking = true; + + /** + * Controls whether cache resources should use locking mechanism + * + * @var boolean + */ + public $cache_locking = false; + + /** + * seconds to wait for acquiring a lock before ignoring the write lock + * + * @var float + */ + public $locking_timeout = 10; + + /** + * resource type used if none given + * Must be an valid key of $registered_resources. + * + * @var string + */ + public $default_resource_type = 'file'; + + /** + * caching type + * Must be an element of $cache_resource_types. + * + * @var string + */ + public $caching_type = 'file'; + + /** + * config type + * + * @var string + */ + public $default_config_type = 'file'; + + /** + * check If-Modified-Since headers + * + * @var boolean + */ + public $cache_modified_check = false; + + /** + * registered plugins + * + * @var array + */ + public $registered_plugins = array(); + + /** + * registered objects + * + * @var array + */ + public $registered_objects = array(); + + /** + * registered classes + * + * @var array + */ + public $registered_classes = array(); + + /** + * registered filters + * + * @var array + */ + public $registered_filters = array(); + + /** + * registered resources + * + * @var array + */ + public $registered_resources = array(); + + /** + * registered cache resources + * + * @var array + */ + public $registered_cache_resources = array(); + + /** + * autoload filter + * + * @var array + */ + public $autoload_filters = array(); + + /** + * default modifier + * + * @var array + */ + public $default_modifiers = array(); + + /** + * autoescape variable output + * + * @var boolean + */ + public $escape_html = false; + + /** + * start time for execution time calculation + * + * @var int + */ + public $start_time = 0; + + /** + * required by the compiler for BC + * + * @var string + */ + public $_current_file = null; + + /** + * internal flag to enable parser debugging + * + * @var bool + */ + public $_parserdebug = false; + + /** + * This object type (Smarty = 1, template = 2, data = 4) + * + * @var int + */ + public $_objType = 1; + + /** + * Debug object + * + * @var Smarty_Internal_Debug + */ + public $_debug = null; + + /** + * template directory + * + * @var array + */ + protected $template_dir = array('./templates/'); + + /** + * flags for normalized template directory entries + * + * @var array + */ + protected $_processedTemplateDir = array(); + + /** + * config directory + * + * @var array + */ + protected $config_dir = array('./configs/'); + + /** + * flags for normalized template directory entries + * + * @var array + */ + protected $_processedConfigDir = array(); + + /** + * compile directory + * + * @var string + */ + protected $compile_dir = './templates_c/'; + + /** + * plugins directory + * + * @var array + */ + protected $plugins_dir = array(); + + /** + * cache directory + * + * @var string + */ + protected $cache_dir = './cache/'; + + /** + * removed properties + * + * @var string[] + */ + protected $obsoleteProperties = array( + 'resource_caching', 'template_resource_caching', 'direct_access_security', + '_dir_perms', '_file_perms', 'plugin_search_order', + 'inheritance_merge_compiled_includes', 'resource_cache_mode', + ); + + /** + * List of private properties which will call getter/setter on a direct access + * + * @var string[] + */ + protected $accessMap = array( + 'template_dir' => 'TemplateDir', 'config_dir' => 'ConfigDir', + 'plugins_dir' => 'PluginsDir', 'compile_dir' => 'CompileDir', + 'cache_dir' => 'CacheDir', + ); + + /** + * PHP7 Compatibility mode + * @var bool + */ + private $isMutingUndefinedOrNullWarnings = false; + + /** + * Initialize new Smarty object + */ + public function __construct() + { + $this->_clearTemplateCache(); + parent::__construct(); + if (is_callable('mb_internal_encoding')) { + mb_internal_encoding(Smarty::$_CHARSET); + } + $this->start_time = microtime(true); + if (isset($_SERVER[ 'SCRIPT_NAME' ])) { + Smarty::$global_tpl_vars[ 'SCRIPT_NAME' ] = new Smarty_Variable($_SERVER[ 'SCRIPT_NAME' ]); + } + // Check if we're running on windows + Smarty::$_IS_WINDOWS = strtoupper(substr(PHP_OS, 0, 3)) === 'WIN'; + // let PCRE (preg_*) treat strings as ISO-8859-1 if we're not dealing with UTF-8 + if (Smarty::$_CHARSET !== 'UTF-8') { + Smarty::$_UTF8_MODIFIER = ''; + } + } + + /** + * Check if a template resource exists + * + * @param string $resource_name template name + * + * @return bool status + * @throws \SmartyException + */ + public function templateExists($resource_name) + { + // create source object + $source = Smarty_Template_Source::load(null, $this, $resource_name); + return $source->exists; + } + + /** + * Loads security class and enables security + * + * @param string|Smarty_Security $security_class if a string is used, it must be class-name + * + * @return Smarty current Smarty instance for chaining + * @throws \SmartyException + */ + public function enableSecurity($security_class = null) + { + Smarty_Security::enableSecurity($this, $security_class); + return $this; + } + + /** + * Disable security + * + * @return Smarty current Smarty instance for chaining + */ + public function disableSecurity() + { + $this->security_policy = null; + return $this; + } + + /** + * Add template directory(s) + * + * @param string|array $template_dir directory(s) of template sources + * @param string $key of the array element to assign the template dir to + * @param bool $isConfig true for config_dir + * + * @return Smarty current Smarty instance for chaining + */ + public function addTemplateDir($template_dir, $key = null, $isConfig = false) + { + if ($isConfig) { + $processed = &$this->_processedConfigDir; + $dir = &$this->config_dir; + $this->_configDirNormalized = false; + } else { + $processed = &$this->_processedTemplateDir; + $dir = &$this->template_dir; + $this->_templateDirNormalized = false; + } + if (is_array($template_dir)) { + foreach ($template_dir as $k => $v) { + if (is_int($k)) { + // indexes are not merged but appended + $dir[] = $v; + } else { + // string indexes are overridden + $dir[ $k ] = $v; + unset($processed[ $key ]); + } + } + } else { + if ($key !== null) { + // override directory at specified index + $dir[ $key ] = $template_dir; + unset($processed[ $key ]); + } else { + // append new directory + $dir[] = $template_dir; + } + } + return $this; + } + + /** + * Get template directories + * + * @param mixed $index index of directory to get, null to get all + * @param bool $isConfig true for config_dir + * + * @return array|string list of template directories, or directory of $index + */ + public function getTemplateDir($index = null, $isConfig = false) + { + if ($isConfig) { + $dir = &$this->config_dir; + } else { + $dir = &$this->template_dir; + } + if ($isConfig ? !$this->_configDirNormalized : !$this->_templateDirNormalized) { + $this->_normalizeTemplateConfig($isConfig); + } + if ($index !== null) { + return isset($dir[ $index ]) ? $dir[ $index ] : null; + } + return $dir; + } + + /** + * Set template directory + * + * @param string|array $template_dir directory(s) of template sources + * @param bool $isConfig true for config_dir + * + * @return \Smarty current Smarty instance for chaining + */ + public function setTemplateDir($template_dir, $isConfig = false) + { + if ($isConfig) { + $this->config_dir = array(); + $this->_processedConfigDir = array(); + } else { + $this->template_dir = array(); + $this->_processedTemplateDir = array(); + } + $this->addTemplateDir($template_dir, null, $isConfig); + return $this; + } + + /** + * Add config directory(s) + * + * @param string|array $config_dir directory(s) of config sources + * @param mixed $key key of the array element to assign the config dir to + * + * @return Smarty current Smarty instance for chaining + */ + public function addConfigDir($config_dir, $key = null) + { + return $this->addTemplateDir($config_dir, $key, true); + } + + /** + * Get config directory + * + * @param mixed $index index of directory to get, null to get all + * + * @return array configuration directory + */ + public function getConfigDir($index = null) + { + return $this->getTemplateDir($index, true); + } + + /** + * Set config directory + * + * @param $config_dir + * + * @return Smarty current Smarty instance for chaining + */ + public function setConfigDir($config_dir) + { + return $this->setTemplateDir($config_dir, true); + } + + /** + * Adds directory of plugin files + * + * @param null|array|string $plugins_dir + * + * @return Smarty current Smarty instance for chaining + */ + public function addPluginsDir($plugins_dir) + { + if (empty($this->plugins_dir)) { + $this->plugins_dir[] = SMARTY_PLUGINS_DIR; + } + $this->plugins_dir = array_merge($this->plugins_dir, (array)$plugins_dir); + $this->_pluginsDirNormalized = false; + return $this; + } + + /** + * Get plugin directories + * + * @return array list of plugin directories + */ + public function getPluginsDir() + { + if (empty($this->plugins_dir)) { + $this->plugins_dir[] = SMARTY_PLUGINS_DIR; + $this->_pluginsDirNormalized = false; + } + if (!$this->_pluginsDirNormalized) { + if (!is_array($this->plugins_dir)) { + $this->plugins_dir = (array)$this->plugins_dir; + } + foreach ($this->plugins_dir as $k => $v) { + $this->plugins_dir[ $k ] = $this->_realpath(rtrim($v ?? '', '/\\') . DIRECTORY_SEPARATOR, true); + } + $this->_cache[ 'plugin_files' ] = array(); + $this->_pluginsDirNormalized = true; + } + return $this->plugins_dir; + } + + /** + * Set plugins directory + * + * @param string|array $plugins_dir directory(s) of plugins + * + * @return Smarty current Smarty instance for chaining + */ + public function setPluginsDir($plugins_dir) + { + $this->plugins_dir = (array)$plugins_dir; + $this->_pluginsDirNormalized = false; + return $this; + } + + /** + * Get compiled directory + * + * @return string path to compiled templates + */ + public function getCompileDir() + { + if (!$this->_compileDirNormalized) { + $this->_normalizeDir('compile_dir', $this->compile_dir); + $this->_compileDirNormalized = true; + } + return $this->compile_dir; + } + + /** + * + * @param string $compile_dir directory to store compiled templates in + * + * @return Smarty current Smarty instance for chaining + */ + public function setCompileDir($compile_dir) + { + $this->_normalizeDir('compile_dir', $compile_dir); + $this->_compileDirNormalized = true; + return $this; + } + + /** + * Get cache directory + * + * @return string path of cache directory + */ + public function getCacheDir() + { + if (!$this->_cacheDirNormalized) { + $this->_normalizeDir('cache_dir', $this->cache_dir); + $this->_cacheDirNormalized = true; + } + return $this->cache_dir; + } + + /** + * Set cache directory + * + * @param string $cache_dir directory to store cached templates in + * + * @return Smarty current Smarty instance for chaining + */ + public function setCacheDir($cache_dir) + { + $this->_normalizeDir('cache_dir', $cache_dir); + $this->_cacheDirNormalized = true; + return $this; + } + + /** + * creates a template object + * + * @param string $template the resource handle of the template file + * @param mixed $cache_id cache id to be used with this template + * @param mixed $compile_id compile id to be used with this template + * @param object $parent next higher level of Smarty variables + * @param boolean $do_clone flag is Smarty object shall be cloned + * + * @return \Smarty_Internal_Template template object + * @throws \SmartyException + */ + public function createTemplate($template, $cache_id = null, $compile_id = null, $parent = null, $do_clone = true) + { + if ($cache_id !== null && (is_object($cache_id) || is_array($cache_id))) { + $parent = $cache_id; + $cache_id = null; + } + if ($parent !== null && is_array($parent)) { + $data = $parent; + $parent = null; + } else { + $data = null; + } + if (!$this->_templateDirNormalized) { + $this->_normalizeTemplateConfig(false); + } + $_templateId = $this->_getTemplateId($template, $cache_id, $compile_id); + $tpl = null; + if ($this->caching && isset(Smarty_Internal_Template::$isCacheTplObj[ $_templateId ])) { + $tpl = $do_clone ? clone Smarty_Internal_Template::$isCacheTplObj[ $_templateId ] : + Smarty_Internal_Template::$isCacheTplObj[ $_templateId ]; + $tpl->inheritance = null; + $tpl->tpl_vars = $tpl->config_vars = array(); + } elseif (!$do_clone && isset(Smarty_Internal_Template::$tplObjCache[ $_templateId ])) { + $tpl = clone Smarty_Internal_Template::$tplObjCache[ $_templateId ]; + $tpl->inheritance = null; + $tpl->tpl_vars = $tpl->config_vars = array(); + } else { + /* @var Smarty_Internal_Template $tpl */ + $tpl = new $this->template_class($template, $this, null, $cache_id, $compile_id, null, null); + $tpl->templateId = $_templateId; + } + if ($do_clone) { + $tpl->smarty = clone $tpl->smarty; + } + $tpl->parent = $parent ? $parent : $this; + // fill data if present + if (!empty($data) && is_array($data)) { + // set up variable values + foreach ($data as $_key => $_val) { + $tpl->tpl_vars[ $_key ] = new Smarty_Variable($_val); + } + } + if ($this->debugging || $this->debugging_ctrl === 'URL') { + $tpl->smarty->_debug = new Smarty_Internal_Debug(); + // check URL debugging control + if (!$this->debugging && $this->debugging_ctrl === 'URL') { + $tpl->smarty->_debug->debugUrl($tpl->smarty); + } + } + return $tpl; + } + + /** + * Takes unknown classes and loads plugin files for them + * class name format: Smarty_PluginType_PluginName + * plugin filename format: plugintype.pluginname.php + * + * @param string $plugin_name class plugin name to load + * @param bool $check check if already loaded + * + * @return string |boolean filepath of loaded file or false + * @throws \SmartyException + */ + public function loadPlugin($plugin_name, $check = true) + { + return $this->ext->loadPlugin->loadPlugin($this, $plugin_name, $check); + } + + /** + * Get unique template id + * + * @param string $template_name + * @param null|mixed $cache_id + * @param null|mixed $compile_id + * @param null $caching + * @param \Smarty_Internal_Template $template + * + * @return string + * @throws \SmartyException + */ + public function _getTemplateId( + $template_name, + $cache_id = null, + $compile_id = null, + $caching = null, + Smarty_Internal_Template $template = null + ) { + $template_name = (strpos($template_name, ':') === false) ? "{$this->default_resource_type}:{$template_name}" : + $template_name; + $cache_id = $cache_id === null ? $this->cache_id : $cache_id; + $compile_id = $compile_id === null ? $this->compile_id : $compile_id; + $caching = (int)($caching === null ? $this->caching : $caching); + if ((isset($template) && strpos($template_name, ':.') !== false) || $this->allow_ambiguous_resources) { + $_templateId = + Smarty_Resource::getUniqueTemplateName((isset($template) ? $template : $this), $template_name) . + "#{$cache_id}#{$compile_id}#{$caching}"; + } else { + $_templateId = $this->_joined_template_dir . "#{$template_name}#{$cache_id}#{$compile_id}#{$caching}"; + } + if (isset($_templateId[ 150 ])) { + $_templateId = sha1($_templateId); + } + return $_templateId; + } + + /** + * Normalize path + * - remove /./ and /../ + * - make it absolute if required + * + * @param string $path file path + * @param bool $realpath if true - convert to absolute + * false - convert to relative + * null - keep as it is but + * remove /./ /../ + * + * @return string + */ + public function _realpath($path, $realpath = null) + { + $nds = array('/' => '\\', '\\' => '/'); + preg_match( + '%^(?(?:[[:alpha:]]:[\\\\/]|/|[\\\\]{2}[[:alpha:]]+|[[:print:]]{2,}:[/]{2}|[\\\\])?)(?(.*))$%u', + $path, + $parts + ); + $path = $parts[ 'path' ]; + if ($parts[ 'root' ] === '\\') { + $parts[ 'root' ] = substr(getcwd(), 0, 2) . $parts[ 'root' ]; + } else { + if ($realpath !== null && !$parts[ 'root' ]) { + $path = getcwd() . DIRECTORY_SEPARATOR . $path; + } + } + // normalize DIRECTORY_SEPARATOR + $path = str_replace($nds[ DIRECTORY_SEPARATOR ], DIRECTORY_SEPARATOR, $path); + $parts[ 'root' ] = str_replace($nds[ DIRECTORY_SEPARATOR ], DIRECTORY_SEPARATOR, $parts[ 'root' ]); + do { + $path = preg_replace( + array('#[\\\\/]{2}#', '#[\\\\/][.][\\\\/]#', '#[\\\\/]([^\\\\/.]+)[\\\\/][.][.][\\\\/]#'), + DIRECTORY_SEPARATOR, + $path, + -1, + $count + ); + } while ($count > 0); + return $realpath !== false ? $parts[ 'root' ] . $path : str_ireplace(getcwd(), '.', $parts[ 'root' ] . $path); + } + + /** + * Empty template objects cache + */ + public function _clearTemplateCache() + { + Smarty_Internal_Template::$isCacheTplObj = array(); + Smarty_Internal_Template::$tplObjCache = array(); + } + + /** + * @param boolean $use_sub_dirs + */ + public function setUseSubDirs($use_sub_dirs) + { + $this->use_sub_dirs = $use_sub_dirs; + } + + /** + * @param int $error_reporting + */ + public function setErrorReporting($error_reporting) + { + $this->error_reporting = $error_reporting; + } + + /** + * @param boolean $escape_html + */ + public function setEscapeHtml($escape_html) + { + $this->escape_html = $escape_html; + } + + /** + * Return auto_literal flag + * + * @return boolean + */ + public function getAutoLiteral() + { + return $this->auto_literal; + } + + /** + * Set auto_literal flag + * + * @param boolean $auto_literal + */ + public function setAutoLiteral($auto_literal = true) + { + $this->auto_literal = $auto_literal; + } + + /** + * @param boolean $force_compile + */ + public function setForceCompile($force_compile) + { + $this->force_compile = $force_compile; + } + + /** + * @param boolean $merge_compiled_includes + */ + public function setMergeCompiledIncludes($merge_compiled_includes) + { + $this->merge_compiled_includes = $merge_compiled_includes; + } + + /** + * Get left delimiter + * + * @return string + */ + public function getLeftDelimiter() + { + return $this->left_delimiter; + } + + /** + * Set left delimiter + * + * @param string $left_delimiter + */ + public function setLeftDelimiter($left_delimiter) + { + $this->left_delimiter = $left_delimiter; + } + + /** + * Get right delimiter + * + * @return string $right_delimiter + */ + public function getRightDelimiter() + { + return $this->right_delimiter; + } + + /** + * Set right delimiter + * + * @param string + */ + public function setRightDelimiter($right_delimiter) + { + $this->right_delimiter = $right_delimiter; + } + + /** + * @param boolean $debugging + */ + public function setDebugging($debugging) + { + $this->debugging = $debugging; + } + + /** + * @param boolean $config_overwrite + */ + public function setConfigOverwrite($config_overwrite) + { + $this->config_overwrite = $config_overwrite; + } + + /** + * @param boolean $config_booleanize + */ + public function setConfigBooleanize($config_booleanize) + { + $this->config_booleanize = $config_booleanize; + } + + /** + * @param boolean $config_read_hidden + */ + public function setConfigReadHidden($config_read_hidden) + { + $this->config_read_hidden = $config_read_hidden; + } + + /** + * @param boolean $compile_locking + */ + public function setCompileLocking($compile_locking) + { + $this->compile_locking = $compile_locking; + } + + /** + * @param string $default_resource_type + */ + public function setDefaultResourceType($default_resource_type) + { + $this->default_resource_type = $default_resource_type; + } + + /** + * @param string $caching_type + */ + public function setCachingType($caching_type) + { + $this->caching_type = $caching_type; + } + + /** + * Test install + * + * @param null $errors + */ + public function testInstall(&$errors = null) + { + Smarty_Internal_TestInstall::testInstall($this, $errors); + } + + /** + * Get Smarty object + * + * @return Smarty + */ + public function _getSmartyObj() + { + return $this; + } + + /** + * <> Generic getter. + * Calls the appropriate getter function. + * Issues an E_USER_NOTICE if no valid getter is found. + * + * @param string $name property name + * + * @return mixed + */ + public function __get($name) + { + if (isset($this->accessMap[ $name ])) { + $method = 'get' . $this->accessMap[ $name ]; + return $this->{$method}(); + } elseif (isset($this->_cache[ $name ])) { + return $this->_cache[ $name ]; + } elseif (in_array($name, $this->obsoleteProperties)) { + return null; + } else { + trigger_error('Undefined property: ' . get_class($this) . '::$' . $name, E_USER_NOTICE); + } + return null; + } + + /** + * <> Generic setter. + * Calls the appropriate setter function. + * Issues an E_USER_NOTICE if no valid setter is found. + * + * @param string $name property name + * @param mixed $value parameter passed to setter + * + */ + public function __set($name, $value) + { + if (isset($this->accessMap[ $name ])) { + $method = 'set' . $this->accessMap[ $name ]; + $this->{$method}($value); + } elseif (in_array($name, $this->obsoleteProperties)) { + return; + } elseif (is_object($value) && method_exists($value, $name)) { + $this->$name = $value; + } else { + trigger_error('Undefined property: ' . get_class($this) . '::$' . $name, E_USER_NOTICE); + } + } + + /** + * Normalize and set directory string + * + * @param string $dirName cache_dir or compile_dir + * @param string $dir filepath of folder + */ + private function _normalizeDir($dirName, $dir) + { + $this->{$dirName} = $this->_realpath(rtrim($dir ?? '', "/\\") . DIRECTORY_SEPARATOR, true); + } + + /** + * Normalize template_dir or config_dir + * + * @param bool $isConfig true for config_dir + */ + private function _normalizeTemplateConfig($isConfig) + { + if ($isConfig) { + $processed = &$this->_processedConfigDir; + $dir = &$this->config_dir; + } else { + $processed = &$this->_processedTemplateDir; + $dir = &$this->template_dir; + } + if (!is_array($dir)) { + $dir = (array)$dir; + } + foreach ($dir as $k => $v) { + if (!isset($processed[ $k ])) { + $dir[ $k ] = $v = $this->_realpath(rtrim($v ?? '', "/\\") . DIRECTORY_SEPARATOR, true); + $processed[ $k ] = true; + } + } + $isConfig ? $this->_configDirNormalized = true : $this->_templateDirNormalized = true; + $isConfig ? $this->_joined_config_dir = join('#', $this->config_dir) : + $this->_joined_template_dir = join('#', $this->template_dir); + } + + /** + * Mutes errors for "undefined index", "undefined array key" and "trying to read property of null". + * + * @void + */ + public function muteUndefinedOrNullWarnings(): void { + $this->isMutingUndefinedOrNullWarnings = true; + } + + /** + * Indicates if Smarty will mute errors for "undefined index", "undefined array key" and "trying to read property of null". + * @bool + */ + public function isMutingUndefinedOrNullWarnings(): bool { + return $this->isMutingUndefinedOrNullWarnings; + } + +} diff --git a/system/vendor/smarty/libs/bootstrap.php b/system/vendor/smarty/libs/bootstrap.php new file mode 100644 index 0000000..a226ac0 --- /dev/null +++ b/system/vendor/smarty/libs/bootstrap.php @@ -0,0 +1,16 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +/** + * Load and register Smarty Autoloader + */ +if (!class_exists('Smarty_Autoloader')) { + include __DIR__ . '/Autoloader.php'; +} +Smarty_Autoloader::register(true); diff --git a/system/vendor/smarty/libs/debug.tpl b/system/vendor/smarty/libs/debug.tpl new file mode 100644 index 0000000..4f82a58 --- /dev/null +++ b/system/vendor/smarty/libs/debug.tpl @@ -0,0 +1,175 @@ +{capture name='_smarty_debug' assign=debug_output} + + + + Smarty Debug Console + + + + +

Smarty {Smarty::SMARTY_VERSION} Debug Console + - {if isset($template_name)}{$template_name|debug_print_var nofilter} {/if}{if !empty($template_data)}Total Time {$execution_time|string_format:"%.5f"}{/if}

+ + {if !empty($template_data)} +

included templates & config files (load time in seconds)

+
+ {foreach $template_data as $template} + {$template.name} +
   + (compile {$template['compile_time']|string_format:"%.5f"}) (render {$template['render_time']|string_format:"%.5f"}) (cache {$template['cache_time']|string_format:"%.5f"}) + +
+ {/foreach} +
+ {/if} + +

assigned template variables

+ + + {foreach $assigned_vars as $vars} + + + + + {/foreach} +
+

${$vars@key}

+ {if isset($vars['nocache'])}Nocache
{/if} + {if isset($vars['scope'])}Origin: {$vars['scope']|debug_print_var nofilter}{/if} +
+

Value

+ {$vars['value']|debug_print_var:10:80 nofilter} +
+ {if isset($vars['attributes'])} +

Attributes

+ {$vars['attributes']|debug_print_var nofilter} + {/if} +
+ +

assigned config file variables

+ + + {foreach $config_vars as $vars} + + + + + {/foreach} + +
+

#{$vars@key}#

+ {if isset($vars['scope'])}Origin: {$vars['scope']|debug_print_var nofilter}{/if} +
+ {$vars['value']|debug_print_var:10:80 nofilter} +
+ + +{/capture} + diff --git a/system/vendor/smarty/libs/functions.php b/system/vendor/smarty/libs/functions.php new file mode 100644 index 0000000..bac00e5 --- /dev/null +++ b/system/vendor/smarty/libs/functions.php @@ -0,0 +1,51 @@ + + * @throws \SmartyException + */ +function smarty_block_textformat($params, $content, Smarty_Internal_Template $template, &$repeat) +{ + if (is_null($content)) { + return; + } + if (Smarty::$_MBSTRING) { + $template->_checkPlugins( + array( + array( + 'function' => 'smarty_modifier_mb_wordwrap', + 'file' => SMARTY_PLUGINS_DIR . 'modifier.mb_wordwrap.php' + ) + ) + ); + } + $style = null; + $indent = 0; + $indent_first = 0; + $indent_char = ' '; + $wrap = 80; + $wrap_char = "\n"; + $wrap_cut = false; + $assign = null; + foreach ($params as $_key => $_val) { + switch ($_key) { + case 'style': + case 'indent_char': + case 'wrap_char': + case 'assign': + $$_key = (string)$_val; + break; + case 'indent': + case 'indent_first': + case 'wrap': + $$_key = (int)$_val; + break; + case 'wrap_cut': + $$_key = (bool)$_val; + break; + default: + trigger_error("textformat: unknown attribute '{$_key}'"); + } + } + if ($style === 'email') { + $wrap = 72; + } + // split into paragraphs + $_paragraphs = preg_split('![\r\n]{2}!', $content); + foreach ($_paragraphs as &$_paragraph) { + if (!$_paragraph) { + continue; + } + // convert mult. spaces & special chars to single space + $_paragraph = + preg_replace( + array( + '!\s+!' . Smarty::$_UTF8_MODIFIER, + '!(^\s+)|(\s+$)!' . Smarty::$_UTF8_MODIFIER + ), + array( + ' ', + '' + ), + $_paragraph + ); + // indent first line + if ($indent_first > 0) { + $_paragraph = str_repeat($indent_char, $indent_first) . $_paragraph; + } + // wordwrap sentences + if (Smarty::$_MBSTRING) { + $_paragraph = smarty_modifier_mb_wordwrap($_paragraph, $wrap - $indent, $wrap_char, $wrap_cut); + } else { + $_paragraph = wordwrap($_paragraph, $wrap - $indent, $wrap_char, $wrap_cut); + } + // indent lines + if ($indent > 0) { + $_paragraph = preg_replace('!^!m', str_repeat($indent_char, $indent), $_paragraph); + } + } + $_output = implode($wrap_char . $wrap_char, $_paragraphs); + if ($assign) { + $template->assign($assign, $_output); + } else { + return $_output; + } +} diff --git a/system/vendor/smarty/libs/plugins/function.counter.php b/system/vendor/smarty/libs/plugins/function.counter.php new file mode 100644 index 0000000..5479545 --- /dev/null +++ b/system/vendor/smarty/libs/plugins/function.counter.php @@ -0,0 +1,62 @@ + + * @link https://www.smarty.net/manual/en/language.function.counter.php {counter} + * (Smarty online manual) + * + * @param array $params parameters + * @param Smarty_Internal_Template $template template object + * + * @return string|null + */ +function smarty_function_counter($params, $template) +{ + static $counters = array(); + $name = (isset($params[ 'name' ])) ? $params[ 'name' ] : 'default'; + if (!isset($counters[ $name ])) { + $counters[ $name ] = array('start' => 1, 'skip' => 1, 'direction' => 'up', 'count' => 1); + } + $counter =& $counters[ $name ]; + if (isset($params[ 'start' ])) { + $counter[ 'start' ] = $counter[ 'count' ] = (int)$params[ 'start' ]; + } + if (!empty($params[ 'assign' ])) { + $counter[ 'assign' ] = $params[ 'assign' ]; + } + if (isset($counter[ 'assign' ])) { + $template->assign($counter[ 'assign' ], $counter[ 'count' ]); + } + if (isset($params[ 'print' ])) { + $print = (bool)$params[ 'print' ]; + } else { + $print = empty($counter[ 'assign' ]); + } + if ($print) { + $retval = $counter[ 'count' ]; + } else { + $retval = null; + } + if (isset($params[ 'skip' ])) { + $counter[ 'skip' ] = $params[ 'skip' ]; + } + if (isset($params[ 'direction' ])) { + $counter[ 'direction' ] = $params[ 'direction' ]; + } + if ($counter[ 'direction' ] === 'down') { + $counter[ 'count' ] -= $counter[ 'skip' ]; + } else { + $counter[ 'count' ] += $counter[ 'skip' ]; + } + return $retval; +} diff --git a/system/vendor/smarty/libs/plugins/function.cycle.php b/system/vendor/smarty/libs/plugins/function.cycle.php new file mode 100644 index 0000000..7935699 --- /dev/null +++ b/system/vendor/smarty/libs/plugins/function.cycle.php @@ -0,0 +1,92 @@ + + * @author credit to Mark Priatel + * @author credit to Gerard + * @author credit to Jason Sweat + * @version 1.3 + * + * @param array $params parameters + * @param Smarty_Internal_Template $template template object + * + * @return string|null + */ +function smarty_function_cycle($params, $template) +{ + static $cycle_vars; + $name = (empty($params[ 'name' ])) ? 'default' : $params[ 'name' ]; + $print = (isset($params[ 'print' ])) ? (bool)$params[ 'print' ] : true; + $advance = (isset($params[ 'advance' ])) ? (bool)$params[ 'advance' ] : true; + $reset = (isset($params[ 'reset' ])) ? (bool)$params[ 'reset' ] : false; + if (!isset($params[ 'values' ])) { + if (!isset($cycle_vars[ $name ][ 'values' ])) { + trigger_error('cycle: missing \'values\' parameter'); + return; + } + } else { + if (isset($cycle_vars[ $name ][ 'values' ]) && $cycle_vars[ $name ][ 'values' ] !== $params[ 'values' ]) { + $cycle_vars[ $name ][ 'index' ] = 0; + } + $cycle_vars[ $name ][ 'values' ] = $params[ 'values' ]; + } + if (isset($params[ 'delimiter' ])) { + $cycle_vars[ $name ][ 'delimiter' ] = $params[ 'delimiter' ]; + } elseif (!isset($cycle_vars[ $name ][ 'delimiter' ])) { + $cycle_vars[ $name ][ 'delimiter' ] = ','; + } + if (is_array($cycle_vars[ $name ][ 'values' ])) { + $cycle_array = $cycle_vars[ $name ][ 'values' ]; + } else { + $cycle_array = explode($cycle_vars[ $name ][ 'delimiter' ], $cycle_vars[ $name ][ 'values' ]); + } + if (!isset($cycle_vars[ $name ][ 'index' ]) || $reset) { + $cycle_vars[ $name ][ 'index' ] = 0; + } + if (isset($params[ 'assign' ])) { + $print = false; + $template->assign($params[ 'assign' ], $cycle_array[ $cycle_vars[ $name ][ 'index' ] ]); + } + if ($print) { + $retval = $cycle_array[ $cycle_vars[ $name ][ 'index' ] ]; + } else { + $retval = null; + } + if ($advance) { + if ($cycle_vars[ $name ][ 'index' ] >= count($cycle_array) - 1) { + $cycle_vars[ $name ][ 'index' ] = 0; + } else { + $cycle_vars[ $name ][ 'index' ]++; + } + } + return $retval; +} diff --git a/system/vendor/smarty/libs/plugins/function.fetch.php b/system/vendor/smarty/libs/plugins/function.fetch.php new file mode 100644 index 0000000..4a3e881 --- /dev/null +++ b/system/vendor/smarty/libs/plugins/function.fetch.php @@ -0,0 +1,204 @@ + + * + * @param array $params parameters + * @param Smarty_Internal_Template $template template object + * + * @throws SmartyException + * @return string|null if the assign parameter is passed, Smarty assigns the result to a template variable + */ +function smarty_function_fetch($params, $template) +{ + if (empty($params[ 'file' ])) { + trigger_error('[plugin] fetch parameter \'file\' cannot be empty', E_USER_NOTICE); + return; + } + // strip file protocol + if (stripos($params[ 'file' ], 'file://') === 0) { + $params[ 'file' ] = substr($params[ 'file' ], 7); + } + $protocol = strpos($params[ 'file' ], '://'); + if ($protocol !== false) { + $protocol = strtolower(substr($params[ 'file' ], 0, $protocol)); + } + if (isset($template->smarty->security_policy)) { + if ($protocol) { + // remote resource (or php stream, …) + if (!$template->smarty->security_policy->isTrustedUri($params[ 'file' ])) { + return; + } + } else { + // local file + if (!$template->smarty->security_policy->isTrustedResourceDir($params[ 'file' ])) { + return; + } + } + } + $content = ''; + if ($protocol === 'http') { + // http fetch + if ($uri_parts = parse_url($params[ 'file' ])) { + // set defaults + $host = $server_name = $uri_parts[ 'host' ]; + $timeout = 30; + $accept = 'image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, */*'; + $agent = 'Smarty Template Engine ' . Smarty::SMARTY_VERSION; + $referer = ''; + $uri = !empty($uri_parts[ 'path' ]) ? $uri_parts[ 'path' ] : '/'; + $uri .= !empty($uri_parts[ 'query' ]) ? '?' . $uri_parts[ 'query' ] : ''; + $_is_proxy = false; + if (empty($uri_parts[ 'port' ])) { + $port = 80; + } else { + $port = $uri_parts[ 'port' ]; + } + if (!empty($uri_parts[ 'user' ])) { + $user = $uri_parts[ 'user' ]; + } + if (!empty($uri_parts[ 'pass' ])) { + $pass = $uri_parts[ 'pass' ]; + } + // loop through parameters, setup headers + foreach ($params as $param_key => $param_value) { + switch ($param_key) { + case 'file': + case 'assign': + case 'assign_headers': + break; + case 'user': + if (!empty($param_value)) { + $user = $param_value; + } + break; + case 'pass': + if (!empty($param_value)) { + $pass = $param_value; + } + break; + case 'accept': + if (!empty($param_value)) { + $accept = $param_value; + } + break; + case 'header': + if (!empty($param_value)) { + if (!preg_match('![\w\d-]+: .+!', $param_value)) { + trigger_error("[plugin] invalid header format '{$param_value}'", E_USER_NOTICE); + return; + } else { + $extra_headers[] = $param_value; + } + } + break; + case 'proxy_host': + if (!empty($param_value)) { + $proxy_host = $param_value; + } + break; + case 'proxy_port': + if (!preg_match('!\D!', $param_value)) { + $proxy_port = (int)$param_value; + } else { + trigger_error("[plugin] invalid value for attribute '{$param_key }'", E_USER_NOTICE); + return; + } + break; + case 'agent': + if (!empty($param_value)) { + $agent = $param_value; + } + break; + case 'referer': + if (!empty($param_value)) { + $referer = $param_value; + } + break; + case 'timeout': + if (!preg_match('!\D!', $param_value)) { + $timeout = (int)$param_value; + } else { + trigger_error("[plugin] invalid value for attribute '{$param_key}'", E_USER_NOTICE); + return; + } + break; + default: + trigger_error("[plugin] unrecognized attribute '{$param_key}'", E_USER_NOTICE); + return; + } + } + if (!empty($proxy_host) && !empty($proxy_port)) { + $_is_proxy = true; + $fp = fsockopen($proxy_host, $proxy_port, $errno, $errstr, $timeout); + } else { + $fp = fsockopen($server_name, $port, $errno, $errstr, $timeout); + } + if (!$fp) { + trigger_error("[plugin] unable to fetch: $errstr ($errno)", E_USER_NOTICE); + return; + } else { + if ($_is_proxy) { + fputs($fp, 'GET ' . $params[ 'file' ] . " HTTP/1.0\r\n"); + } else { + fputs($fp, "GET $uri HTTP/1.0\r\n"); + } + if (!empty($host)) { + fputs($fp, "Host: $host\r\n"); + } + if (!empty($accept)) { + fputs($fp, "Accept: $accept\r\n"); + } + if (!empty($agent)) { + fputs($fp, "User-Agent: $agent\r\n"); + } + if (!empty($referer)) { + fputs($fp, "Referer: $referer\r\n"); + } + if (isset($extra_headers) && is_array($extra_headers)) { + foreach ($extra_headers as $curr_header) { + fputs($fp, $curr_header . "\r\n"); + } + } + if (!empty($user) && !empty($pass)) { + fputs($fp, 'Authorization: BASIC ' . base64_encode("$user:$pass") . "\r\n"); + } + fputs($fp, "\r\n"); + while (!feof($fp)) { + $content .= fgets($fp, 4096); + } + fclose($fp); + $csplit = preg_split("!\r\n\r\n!", $content, 2); + $content = $csplit[ 1 ]; + if (!empty($params[ 'assign_headers' ])) { + $template->assign($params[ 'assign_headers' ], preg_split("!\r\n!", $csplit[ 0 ])); + } + } + } else { + trigger_error("[plugin fetch] unable to parse URL, check syntax", E_USER_NOTICE); + return; + } + } else { + $content = @file_get_contents($params[ 'file' ]); + if ($content === false) { + throw new SmartyException("{fetch} cannot read resource '" . $params[ 'file' ] . "'"); + } + } + if (!empty($params[ 'assign' ])) { + $template->assign($params[ 'assign' ], $content); + } else { + return $content; + } +} diff --git a/system/vendor/smarty/libs/plugins/function.html_checkboxes.php b/system/vendor/smarty/libs/plugins/function.html_checkboxes.php new file mode 100644 index 0000000..a8e7a07 --- /dev/null +++ b/system/vendor/smarty/libs/plugins/function.html_checkboxes.php @@ -0,0 +1,286 @@ +' output=$names} + * {html_checkboxes values=$ids checked=$checked separator='
' output=$names} + * + * Params: + * + * - name (optional) - string default "checkbox" + * - values (required) - array + * - options (optional) - associative array + * - checked (optional) - array default not set + * - separator (optional) - ie
or   + * - output (optional) - the output next to each checkbox + * - assign (optional) - assign the output as an array to this variable + * - escape (optional) - escape the content (not value), defaults to true + * + * @link https://www.smarty.net/manual/en/language.function.html.checkboxes.php {html_checkboxes} + * (Smarty online manual) + * @author Christopher Kvarme + * @author credits to Monte Ohrt + * @version 1.0 + * + * @param array $params parameters + * @param Smarty_Internal_Template $template template object + * + * @return string + * @uses smarty_function_escape_special_chars() + * @throws \SmartyException + */ +function smarty_function_html_checkboxes($params, Smarty_Internal_Template $template) +{ + $template->_checkPlugins( + array( + array( + 'function' => 'smarty_function_escape_special_chars', + 'file' => SMARTY_PLUGINS_DIR . 'shared.escape_special_chars.php' + ) + ) + ); + $name = 'checkbox'; + $values = null; + $options = null; + $selected = array(); + $separator = ''; + $escape = true; + $labels = true; + $label_ids = false; + $output = null; + $extra = ''; + foreach ($params as $_key => $_val) { + switch ($_key) { + case 'name': + case 'separator': + $$_key = (string)$_val; + break; + case 'escape': + case 'labels': + case 'label_ids': + $$_key = (bool)$_val; + break; + case 'options': + $$_key = (array)$_val; + break; + case 'values': + case 'output': + $$_key = array_values((array)$_val); + break; + case 'checked': + case 'selected': + if (is_array($_val)) { + $selected = array(); + foreach ($_val as $_sel) { + if (is_object($_sel)) { + if (method_exists($_sel, '__toString')) { + $_sel = smarty_function_escape_special_chars((string)$_sel->__toString()); + } else { + trigger_error( + 'html_checkboxes: selected attribute contains an object of class \'' . + get_class($_sel) . '\' without __toString() method', + E_USER_NOTICE + ); + continue; + } + } else { + $_sel = smarty_function_escape_special_chars((string)$_sel); + } + $selected[ $_sel ] = true; + } + } elseif (is_object($_val)) { + if (method_exists($_val, '__toString')) { + $selected = smarty_function_escape_special_chars((string)$_val->__toString()); + } else { + trigger_error( + 'html_checkboxes: selected attribute is an object of class \'' . get_class($_val) . + '\' without __toString() method', + E_USER_NOTICE + ); + } + } else { + $selected = smarty_function_escape_special_chars((string)$_val); + } + break; + case 'checkboxes': + trigger_error( + 'html_checkboxes: the use of the "checkboxes" attribute is deprecated, use "options" instead', + E_USER_WARNING + ); + $options = (array)$_val; + break; + case 'assign': + break; + case 'strict': + break; + case 'disabled': + case 'readonly': + if (!empty($params[ 'strict' ])) { + if (!is_scalar($_val)) { + trigger_error( + "html_options: {$_key} attribute must be a scalar, only boolean true or string '{$_key}' will actually add the attribute", + E_USER_NOTICE + ); + } + if ($_val === true || $_val === $_key) { + $extra .= ' ' . $_key . '="' . smarty_function_escape_special_chars($_key) . '"'; + } + break; + } + // omit break; to fall through! + // no break + default: + if (!is_array($_val)) { + $extra .= ' ' . $_key . '="' . smarty_function_escape_special_chars($_val) . '"'; + } else { + trigger_error("html_checkboxes: extra attribute '{$_key}' cannot be an array", E_USER_NOTICE); + } + break; + } + } + if (!isset($options) && !isset($values)) { + return ''; + } /* raise error here? */ + $_html_result = array(); + if (isset($options)) { + foreach ($options as $_key => $_val) { + $_html_result[] = + smarty_function_html_checkboxes_output( + $name, + $_key, + $_val, + $selected, + $extra, + $separator, + $labels, + $label_ids, + $escape + ); + } + } else { + foreach ($values as $_i => $_key) { + $_val = isset($output[ $_i ]) ? $output[ $_i ] : ''; + $_html_result[] = + smarty_function_html_checkboxes_output( + $name, + $_key, + $_val, + $selected, + $extra, + $separator, + $labels, + $label_ids, + $escape + ); + } + } + if (!empty($params[ 'assign' ])) { + $template->assign($params[ 'assign' ], $_html_result); + } else { + return implode("\n", $_html_result); + } +} + +/** + * @param $name + * @param $value + * @param $output + * @param $selected + * @param $extra + * @param $separator + * @param $labels + * @param $label_ids + * @param bool $escape + * + * @return string + */ +function smarty_function_html_checkboxes_output( + $name, + $value, + $output, + $selected, + $extra, + $separator, + $labels, + $label_ids, + $escape = true +) { + $_output = ''; + if (is_object($value)) { + if (method_exists($value, '__toString')) { + $value = (string)$value->__toString(); + } else { + trigger_error( + 'html_options: value is an object of class \'' . get_class($value) . + '\' without __toString() method', + E_USER_NOTICE + ); + return ''; + } + } else { + $value = (string)$value; + } + if (is_object($output)) { + if (method_exists($output, '__toString')) { + $output = (string)$output->__toString(); + } else { + trigger_error( + 'html_options: output is an object of class \'' . get_class($output) . + '\' without __toString() method', + E_USER_NOTICE + ); + return ''; + } + } else { + $output = (string)$output; + } + if ($labels) { + if ($label_ids) { + $_id = smarty_function_escape_special_chars( + preg_replace( + '![^\w\-\.]!' . Smarty::$_UTF8_MODIFIER, + '_', + $name . '_' . $value + ) + ); + $_output .= '