Initial commit: API Wipay dengan fix CORS untuk GET request
This commit is contained in:
68
src/Controllers/ApiController.php
Normal file
68
src/Controllers/ApiController.php
Normal file
@@ -0,0 +1,68 @@
|
||||
<?php
|
||||
|
||||
namespace App\Controllers;
|
||||
|
||||
use App\Config\Database;
|
||||
use App\Helpers\ResponseHelper;
|
||||
use Psr\Http\Message\ResponseInterface as Response;
|
||||
use Psr\Http\Message\ServerRequestInterface as Request;
|
||||
|
||||
class ApiController
|
||||
{
|
||||
private $db;
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this->db = Database::getInstance();
|
||||
}
|
||||
|
||||
/**
|
||||
* GET /api/mandiri/{tanggal}
|
||||
* Data catat meter Mandiri berdasarkan tanggal
|
||||
*/
|
||||
public function mandiri(Request $request, Response $response, array $args): Response
|
||||
{
|
||||
$tanggal = $args['tanggal'] ?? '';
|
||||
|
||||
if (empty($tanggal)) {
|
||||
$response->getBody()->write('DATE NOT SPECIFIED');
|
||||
return $response->withStatus(400);
|
||||
}
|
||||
|
||||
// Parse tanggal format ddmmyyyy
|
||||
$format = "dmY";
|
||||
$date = \DateTime::createFromFormat($format, $tanggal);
|
||||
|
||||
if ($date) {
|
||||
$tanggal_cari = $date->format('Y-m-d');
|
||||
} else {
|
||||
$tanggal_cari = date('Y-m-d');
|
||||
}
|
||||
|
||||
// Get base URL from environment or request
|
||||
$baseUrl = $_ENV['BASE_URL'] ??
|
||||
($request->getUri()->getScheme() . '://' . $request->getUri()->getHost());
|
||||
|
||||
// Query data
|
||||
$sql = "SELECT cm.no_sl, pt.no_hp, cm.tanggal_catat as tanggal_baca,
|
||||
cm.angka_meter,
|
||||
CONCAT(:base_url, '/assets/uploads/catat_meter/', cm.photo) as photo
|
||||
FROM catat_meter cm
|
||||
LEFT JOIN pengguna_timo pt ON cm.token = pt.id_pengguna_timo
|
||||
WHERE DATE(cm.tanggal_catat) = :tanggal_cari";
|
||||
|
||||
$data = $this->db->fetchAll($sql, [
|
||||
'base_url' => $baseUrl,
|
||||
'tanggal_cari' => $tanggal_cari
|
||||
]);
|
||||
|
||||
// Format response sama dengan API lama: status: 1 (bukan 200)
|
||||
$responseData = [
|
||||
'status' => 1,
|
||||
'date' => $tanggal,
|
||||
'data' => $data
|
||||
];
|
||||
|
||||
return ResponseHelper::json($response, $responseData, 200);
|
||||
}
|
||||
}
|
||||
272
src/Controllers/AuthController.php
Normal file
272
src/Controllers/AuthController.php
Normal file
@@ -0,0 +1,272 @@
|
||||
<?php
|
||||
|
||||
namespace App\Controllers;
|
||||
|
||||
use App\Helpers\ResponseHelper;
|
||||
use App\Models\UserModel;
|
||||
use App\Services\AuthService;
|
||||
use Psr\Http\Message\ResponseInterface as Response;
|
||||
use Psr\Http\Message\ServerRequestInterface as Request;
|
||||
|
||||
class AuthController
|
||||
{
|
||||
private $authService;
|
||||
private $userModel;
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this->authService = new AuthService();
|
||||
$this->userModel = new UserModel();
|
||||
}
|
||||
|
||||
public function daftar(Request $request, Response $response): Response
|
||||
{
|
||||
try {
|
||||
$data = $request->getParsedBody();
|
||||
|
||||
$nama = $data['nama'] ?? '';
|
||||
$username = $data['username'] ?? '';
|
||||
$email = $data['email'] ?? '';
|
||||
$no_hp = $data['no_hp'] ?? '';
|
||||
$password = $data['password'] ?? '';
|
||||
|
||||
// Format response awal sama dengan API lama
|
||||
$responseData = [
|
||||
'status' => 404,
|
||||
'pesan' => '-'
|
||||
];
|
||||
|
||||
if (empty($username) || empty($password) || empty($email) || empty($no_hp)) {
|
||||
$responseData['pesan'] = 'Data tidak lengkap';
|
||||
return ResponseHelper::custom($response, $responseData, 404);
|
||||
}
|
||||
|
||||
// Cek username sudah ada
|
||||
$cekUsername = $this->userModel->findByUsername($username);
|
||||
if ($cekUsername) {
|
||||
$responseData['pesan'] = 'Username yang anda pilih tidak bisa digunakan';
|
||||
return ResponseHelper::custom($response, $responseData, 404);
|
||||
}
|
||||
|
||||
// Cek email sudah ada
|
||||
$cekEmail = $this->userModel->findByEmail($email);
|
||||
if ($cekEmail) {
|
||||
$responseData['pesan'] = 'Email yang anda masukan sudah ada yang menggunakan!, silahkan gunakan email lain';
|
||||
return ResponseHelper::custom($response, $responseData, 404);
|
||||
}
|
||||
|
||||
// Default biaya admin (sesuai backend lama: 2500)
|
||||
$biayaAdmin = 2500; // Default value dari config.php: default_biaya_admin
|
||||
|
||||
$userData = [
|
||||
'nama_lengkap' => $nama,
|
||||
'username' => $username,
|
||||
'password' => md5($password),
|
||||
'email' => $email,
|
||||
'no_hp' => $no_hp,
|
||||
'biaya_admin' => $biayaAdmin,
|
||||
];
|
||||
|
||||
$this->userModel->create($userData);
|
||||
|
||||
// Format response sukses sama dengan API lama
|
||||
$responseData = [
|
||||
'status' => 200,
|
||||
'pesan' => 'Akun berhasil dibuat, silahkan login'
|
||||
];
|
||||
|
||||
return ResponseHelper::custom($response, $responseData, 200);
|
||||
} catch (\Exception $e) {
|
||||
error_log("Error in daftar: " . $e->getMessage());
|
||||
return ResponseHelper::custom($response, [
|
||||
'status' => 404,
|
||||
'pesan' => 'Gagal membuat akun: ' . $e->getMessage()
|
||||
], 404);
|
||||
}
|
||||
}
|
||||
|
||||
public function login(Request $request, Response $response): Response
|
||||
{
|
||||
$data = $request->getParsedBody();
|
||||
|
||||
$username = $data['username'] ?? '';
|
||||
$password = $data['password'] ?? '';
|
||||
$fcm_token = $data['fcm_token'] ?? '';
|
||||
|
||||
if (empty($username) || empty($password)) {
|
||||
return ResponseHelper::error($response, 'Username dan password harus diisi', 404);
|
||||
}
|
||||
|
||||
$user = $this->userModel->findByUsername($username);
|
||||
|
||||
if (!$user || $user->password !== md5($password)) {
|
||||
return ResponseHelper::error($response, 'Akun tidak ditemukan, pastikan username dan password yang anda masukan sudah terdaftar', 404);
|
||||
}
|
||||
|
||||
// Update FCM token
|
||||
if (!empty($fcm_token)) {
|
||||
$this->userModel->update($user->id_pengguna_timo, ['ftoken' => $fcm_token]);
|
||||
}
|
||||
|
||||
// Get SL list
|
||||
$slList = $this->userModel->getSLList($user->id_pengguna_timo);
|
||||
|
||||
// Convert user object ke array
|
||||
$userArray = [
|
||||
'id_pengguna_timo' => $user->id_pengguna_timo,
|
||||
'nama_lengkap' => $user->nama_lengkap ?? '',
|
||||
'username' => $user->username ?? '',
|
||||
'email' => $user->email ?? '',
|
||||
'no_hp' => $user->no_hp ?? '',
|
||||
'biaya_admin' => $user->biaya_admin ?? '1500',
|
||||
'photo' => $user->photo ?? '',
|
||||
'ftoken' => $user->ftoken ?? '',
|
||||
];
|
||||
|
||||
// Convert SL list objects ke array
|
||||
$slListArray = [];
|
||||
foreach ($slList as $sl) {
|
||||
$slListArray[] = [
|
||||
'pel_no' => $sl->pel_no ?? '',
|
||||
'pel_nama' => $sl->pel_nama ?? '',
|
||||
'pel_alamat' => $sl->pel_alamat ?? '',
|
||||
'dkd_kd' => $sl->dkd_kd ?? '',
|
||||
'rek_gol' => $sl->rek_gol ?? '',
|
||||
];
|
||||
}
|
||||
|
||||
return ResponseHelper::success($response, 'Selamat Datang ' . $user->nama_lengkap, [
|
||||
'user' => $userArray,
|
||||
'data_sl' => $slListArray
|
||||
], 200);
|
||||
}
|
||||
|
||||
public function loginToken(Request $request, Response $response): Response
|
||||
{
|
||||
$data = $request->getParsedBody();
|
||||
|
||||
$username = $data['username'] ?? '';
|
||||
$password = $data['password'] ?? ''; // Password sudah di-hash
|
||||
$fcm_token = $data['fcm_token'] ?? '';
|
||||
|
||||
// Format response awal sama dengan API lama
|
||||
$responseData = [
|
||||
'status' => 404,
|
||||
'pesan' => '-'
|
||||
];
|
||||
|
||||
if (empty($username) || empty($password)) {
|
||||
$responseData['pesan'] = 'Username dan password harus diisi';
|
||||
return ResponseHelper::custom($response, $responseData, 404);
|
||||
}
|
||||
|
||||
$user = $this->userModel->findByUsername($username);
|
||||
|
||||
if (!$user || $user->password !== $password) {
|
||||
$responseData['pesan'] = 'Akun tidak ditemukan, pastikan username dan password yang anda masukan sudah terdaftar';
|
||||
return ResponseHelper::custom($response, $responseData, 404);
|
||||
}
|
||||
|
||||
// Update FCM token
|
||||
if (!empty($fcm_token)) {
|
||||
$this->userModel->update($user->id_pengguna_timo, ['ftoken' => $fcm_token]);
|
||||
}
|
||||
|
||||
// Get SL list
|
||||
$slList = $this->userModel->getSLList($user->id_pengguna_timo);
|
||||
|
||||
// Format response sama dengan API lama: status, pesan, user, data_sl langsung di root
|
||||
$responseData = [
|
||||
'status' => 200,
|
||||
'pesan' => 'Selamat Datang ' . $user->nama_lengkap,
|
||||
'user' => $user,
|
||||
'data_sl' => $slList
|
||||
];
|
||||
|
||||
return ResponseHelper::custom($response, $responseData, 200);
|
||||
}
|
||||
|
||||
public function updateAkun(Request $request, Response $response): Response
|
||||
{
|
||||
$data = $request->getParsedBody();
|
||||
$token = $data['token'] ?? '';
|
||||
$nama = $data['nama'] ?? '';
|
||||
$email = $data['email'] ?? '';
|
||||
$hp = $data['hp'] ?? '';
|
||||
|
||||
// Format response awal sama dengan API lama
|
||||
$responseData = [
|
||||
'status' => 404,
|
||||
'pesan' => 'Gagal ubah data, silahkan coba beberapa saat lagi'
|
||||
];
|
||||
|
||||
if (empty($token)) {
|
||||
$responseData['pesan'] = 'Token harus diisi';
|
||||
return ResponseHelper::custom($response, $responseData, 404);
|
||||
}
|
||||
|
||||
$pengguna = $this->userModel->findById($token);
|
||||
if (!$pengguna) {
|
||||
$responseData['pesan'] = 'Token tidak Valid. Silahkan Login dan Ulangi transaksi. Terima kasih';
|
||||
return ResponseHelper::custom($response, $responseData, 404);
|
||||
}
|
||||
|
||||
// Update fields
|
||||
$updateData = [];
|
||||
if (!empty($nama)) $updateData['nama_lengkap'] = $nama;
|
||||
if (!empty($email)) $updateData['email'] = $email;
|
||||
if (!empty($hp)) $updateData['no_hp'] = $hp;
|
||||
|
||||
if (!empty($updateData)) {
|
||||
$this->userModel->update($token, $updateData);
|
||||
}
|
||||
|
||||
// Get updated user data
|
||||
$updatedUser = $this->userModel->findById($token);
|
||||
|
||||
$responseData = [
|
||||
'status' => 200,
|
||||
'pesan' => 'Data berhasil di ubah',
|
||||
'data' => $updatedUser
|
||||
];
|
||||
|
||||
return ResponseHelper::custom($response, $responseData, 200);
|
||||
}
|
||||
|
||||
public function updatePassword(Request $request, Response $response): Response
|
||||
{
|
||||
$data = $request->getParsedBody();
|
||||
$token = $data['token'] ?? '';
|
||||
$passlama = $data['passlama'] ?? '';
|
||||
$passbaru = $data['passbaru'] ?? '';
|
||||
|
||||
// Format response awal sama dengan API lama
|
||||
$responseData = [
|
||||
'status' => 404,
|
||||
'pesan' => 'Gagal ubah data, silahkan coba beberapa saat lagi'
|
||||
];
|
||||
|
||||
if (empty($token) || empty($passlama) || empty($passbaru)) {
|
||||
$responseData['pesan'] = 'Data tidak lengkap';
|
||||
return ResponseHelper::custom($response, $responseData, 404);
|
||||
}
|
||||
|
||||
$pengguna = $this->userModel->findById($token);
|
||||
if (!$pengguna) {
|
||||
$responseData['pesan'] = 'Token tidak Valid. Silahkan Login dan Ulangi transaksi. Terima kasih';
|
||||
return ResponseHelper::custom($response, $responseData, 404);
|
||||
}
|
||||
|
||||
if (md5($passlama) == $pengguna->password) {
|
||||
$this->userModel->update($token, ['password' => md5($passbaru)]);
|
||||
$responseData = [
|
||||
'status' => 200,
|
||||
'pesan' => 'Password berhasil di ubah'
|
||||
];
|
||||
} else {
|
||||
$responseData['pesan'] = 'Password lama tidak sesuai, silahkan coba lagi';
|
||||
}
|
||||
|
||||
return ResponseHelper::custom($response, $responseData, $responseData['status']);
|
||||
}
|
||||
}
|
||||
635
src/Controllers/FastController.php
Normal file
635
src/Controllers/FastController.php
Normal file
@@ -0,0 +1,635 @@
|
||||
<?php
|
||||
|
||||
namespace App\Controllers;
|
||||
|
||||
use App\Config\Database;
|
||||
use App\Helpers\HttpHelper;
|
||||
use App\Helpers\ResponseHelper;
|
||||
use App\Models\ApiKeyModel;
|
||||
use Psr\Http\Message\ResponseInterface as Response;
|
||||
use Psr\Http\Message\ServerRequestInterface as Request;
|
||||
|
||||
class FastController
|
||||
{
|
||||
private $db;
|
||||
private $apiKeyModel;
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this->db = Database::getInstance();
|
||||
$this->apiKeyModel = new ApiKeyModel();
|
||||
}
|
||||
|
||||
/**
|
||||
* GET /fast/test
|
||||
* Test endpoint (tidak perlu auth)
|
||||
*/
|
||||
public function test(Request $request, Response $response): Response
|
||||
{
|
||||
$baseUrl = $_ENV['BASE_URL'] ??
|
||||
($request->getUri()->getScheme() . '://' . $request->getUri()->getHost());
|
||||
|
||||
return ResponseHelper::json($response, [
|
||||
'status' => 'success',
|
||||
'message' => 'Fast WIPAY API is working!',
|
||||
'timestamp' => date('Y-m-d H:i:s'),
|
||||
'controller' => 'Fast',
|
||||
'method' => 'test',
|
||||
'url' => $baseUrl . $request->getUri()->getPath()
|
||||
], 200);
|
||||
}
|
||||
|
||||
/**
|
||||
* POST /fast/check_bill
|
||||
* Cek tagihan PDAM
|
||||
*/
|
||||
public function checkBill(Request $request, Response $response): Response
|
||||
{
|
||||
try {
|
||||
// Get API key from request attributes (set by middleware)
|
||||
$apiKey = $request->getAttribute('api_key');
|
||||
if (!$apiKey) {
|
||||
return ResponseHelper::json($response, [
|
||||
'status' => 'error',
|
||||
'message' => 'Invalid API key'
|
||||
], 401);
|
||||
}
|
||||
|
||||
// Get input from multiple sources
|
||||
$data = $request->getParsedBody() ?? [];
|
||||
$query = $request->getQueryParams();
|
||||
$no_sl = $data['no_sl'] ?? $query['no_sl'] ?? '';
|
||||
|
||||
if (empty($no_sl)) {
|
||||
return ResponseHelper::json($response, [
|
||||
'status' => 'error',
|
||||
'message' => 'No SL is required'
|
||||
], 400);
|
||||
}
|
||||
|
||||
// Get admin user and timo user
|
||||
$adminUser = $this->db->fetchOne(
|
||||
"SELECT * FROM admin_users WHERE id = :id LIMIT 1",
|
||||
['id' => $apiKey->admin_user_id]
|
||||
);
|
||||
|
||||
if (!$adminUser || !$adminUser->timo_user) {
|
||||
return ResponseHelper::json($response, [
|
||||
'status' => 'error',
|
||||
'message' => 'Admin user tidak memiliki user TIMO'
|
||||
], 404);
|
||||
}
|
||||
|
||||
$timoUser = $this->db->fetchOne(
|
||||
"SELECT * FROM pengguna_timo WHERE id_pengguna_timo = :id LIMIT 1",
|
||||
['id' => $adminUser->timo_user]
|
||||
);
|
||||
|
||||
if (!$timoUser) {
|
||||
return ResponseHelper::json($response, [
|
||||
'status' => 'error',
|
||||
'message' => 'User TIMO tidak ditemukan'
|
||||
], 404);
|
||||
}
|
||||
|
||||
// Get WIPAY user (optional for check_bill)
|
||||
$wipayUser = null;
|
||||
if ($timoUser->wipay) {
|
||||
$wipayUser = $this->db->fetchOne(
|
||||
"SELECT * FROM wipay_pengguna WHERE id_wipay = :id LIMIT 1",
|
||||
['id' => $timoUser->wipay]
|
||||
);
|
||||
}
|
||||
|
||||
// Call TIMO API untuk cek tagihan
|
||||
$timoUrl = 'https://timo.tirtaintan.co.id/enquiry/' . $no_sl;
|
||||
$timoResponse = HttpHelper::doCurl($timoUrl, 'GET');
|
||||
|
||||
// Handle response format - HttpHelper returns object with status/body or decoded JSON
|
||||
if (!$timoResponse) {
|
||||
$this->apiKeyModel->logApiUsage($apiKey->id, 'check_bill', 'failed', [
|
||||
'no_sl' => $no_sl,
|
||||
'error' => 'Failed to connect to TIMO API'
|
||||
]);
|
||||
|
||||
return ResponseHelper::json($response, [
|
||||
'status' => 'error',
|
||||
'message' => 'Gagal cek tagihan: Tidak dapat menghubungi server TIMO'
|
||||
], 500);
|
||||
}
|
||||
|
||||
// Check if it's an HTTP error response
|
||||
if (is_object($timoResponse) && isset($timoResponse->status) && $timoResponse->status != 200) {
|
||||
$this->apiKeyModel->logApiUsage($apiKey->id, 'check_bill', 'failed', [
|
||||
'no_sl' => $no_sl,
|
||||
'error' => $timoResponse->error ?? 'HTTP Error'
|
||||
]);
|
||||
|
||||
return ResponseHelper::json($response, [
|
||||
'status' => 'error',
|
||||
'message' => 'Gagal cek tagihan: ' . ($timoResponse->error ?? 'HTTP Error')
|
||||
], $timoResponse->status);
|
||||
}
|
||||
|
||||
// Normal response with errno
|
||||
if (isset($timoResponse->errno)) {
|
||||
// Log API usage
|
||||
$this->apiKeyModel->logApiUsage($apiKey->id, 'check_bill',
|
||||
$timoResponse->errno == 0 ? 'success' : 'api_error', [
|
||||
'no_sl' => $no_sl,
|
||||
'timo_user_id' => $timoUser->id_pengguna_timo,
|
||||
'wipay_user_id' => $wipayUser ? $wipayUser->id_wipay : null
|
||||
]);
|
||||
|
||||
return ResponseHelper::json($response, [
|
||||
'status' => 'success',
|
||||
'data' => $timoResponse,
|
||||
'message' => 'Tagihan berhasil dicek'
|
||||
], 200);
|
||||
} else {
|
||||
// Log failed API call
|
||||
$this->apiKeyModel->logApiUsage($apiKey->id, 'check_bill', 'failed', [
|
||||
'no_sl' => $no_sl,
|
||||
'error' => 'Failed to connect to TIMO API'
|
||||
]);
|
||||
|
||||
return ResponseHelper::json($response, [
|
||||
'status' => 'error',
|
||||
'message' => 'Gagal cek tagihan: Tidak dapat menghubungi server TIMO'
|
||||
], 500);
|
||||
}
|
||||
} catch (\Exception $e) {
|
||||
error_log("Error in checkBill: " . $e->getMessage());
|
||||
return ResponseHelper::json($response, [
|
||||
'status' => 'error',
|
||||
'message' => 'Gagal cek tagihan: ' . $e->getMessage()
|
||||
], 500);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* POST /fast/process_payment
|
||||
* Proses pembayaran PDAM
|
||||
*/
|
||||
public function processPayment(Request $request, Response $response): Response
|
||||
{
|
||||
try {
|
||||
// Get API key
|
||||
$apiKey = $request->getAttribute('api_key');
|
||||
if (!$apiKey) {
|
||||
return ResponseHelper::json($response, [
|
||||
'status' => 'error',
|
||||
'message' => 'Invalid API key'
|
||||
], 401);
|
||||
}
|
||||
|
||||
// Get input
|
||||
$data = $request->getParsedBody() ?? [];
|
||||
$query = $request->getQueryParams();
|
||||
$no_sl = $data['no_sl'] ?? $query['no_sl'] ?? '';
|
||||
$amount = $data['amount'] ?? $query['amount'] ?? 0;
|
||||
$token = $data['token'] ?? $query['token'] ?? '';
|
||||
|
||||
if (empty($no_sl) || empty($amount) || empty($token)) {
|
||||
return ResponseHelper::json($response, [
|
||||
'status' => 'error',
|
||||
'message' => 'No SL, amount, and token are required'
|
||||
], 400);
|
||||
}
|
||||
|
||||
if (!is_numeric($amount)) {
|
||||
return ResponseHelper::json($response, [
|
||||
'status' => 'error',
|
||||
'message' => 'Amount must be a valid number'
|
||||
], 400);
|
||||
}
|
||||
|
||||
$amount = (float)$amount;
|
||||
|
||||
// Get admin user and timo user
|
||||
$adminUser = $this->db->fetchOne(
|
||||
"SELECT * FROM admin_users WHERE id = :id LIMIT 1",
|
||||
['id' => $apiKey->admin_user_id]
|
||||
);
|
||||
|
||||
if (!$adminUser || !$adminUser->timo_user) {
|
||||
return ResponseHelper::json($response, [
|
||||
'status' => 'error',
|
||||
'message' => 'Admin user tidak memiliki user TIMO'
|
||||
], 404);
|
||||
}
|
||||
|
||||
$timoUser = $this->db->fetchOne(
|
||||
"SELECT * FROM pengguna_timo WHERE id_pengguna_timo = :id LIMIT 1",
|
||||
['id' => $adminUser->timo_user]
|
||||
);
|
||||
|
||||
if (!$timoUser) {
|
||||
return ResponseHelper::json($response, [
|
||||
'status' => 'error',
|
||||
'message' => 'User TIMO tidak ditemukan'
|
||||
], 404);
|
||||
}
|
||||
|
||||
// Get WIPAY user
|
||||
$wipayUser = $this->db->fetchOne(
|
||||
"SELECT * FROM wipay_pengguna WHERE id_wipay = :id LIMIT 1",
|
||||
['id' => $timoUser->wipay]
|
||||
);
|
||||
|
||||
if (!$wipayUser) {
|
||||
return ResponseHelper::json($response, [
|
||||
'status' => 'error',
|
||||
'message' => 'User tidak memiliki akun WIPAY'
|
||||
], 400);
|
||||
}
|
||||
|
||||
// Get current saldo
|
||||
$saldo = $this->getWipaySaldo($wipayUser->id_wipay);
|
||||
|
||||
// Calculate total payment
|
||||
$biayaAdmin = $timoUser->biaya_admin ?: 0;
|
||||
$totalPayment = $amount + $biayaAdmin;
|
||||
|
||||
// Validate saldo
|
||||
if ($saldo < $totalPayment) {
|
||||
return ResponseHelper::json($response, [
|
||||
'status' => 'error',
|
||||
'message' => 'Saldo WIPAY tidak mencukupi. Saldo: Rp ' . number_format($saldo, 0, ',', '.') . ', Total: Rp ' . number_format($totalPayment, 0, ',', '.')
|
||||
], 400);
|
||||
}
|
||||
|
||||
// Get tagihan detail from PDAM API
|
||||
$timoUrl = 'https://timo.tirtaintan.co.id/enquiry/' . $no_sl;
|
||||
$enquiryResponse = HttpHelper::doCurl($timoUrl, 'GET');
|
||||
|
||||
// Handle HTTP error
|
||||
if (is_object($enquiryResponse) && isset($enquiryResponse->status) && $enquiryResponse->status != 200) {
|
||||
return ResponseHelper::json($response, [
|
||||
'status' => 'error',
|
||||
'message' => 'Gagal mendapatkan data tagihan dari PDAM'
|
||||
], 500);
|
||||
}
|
||||
|
||||
if (!$enquiryResponse || !isset($enquiryResponse->data)) {
|
||||
return ResponseHelper::json($response, [
|
||||
'status' => 'error',
|
||||
'message' => 'Data tagihan tidak valid'
|
||||
], 500);
|
||||
}
|
||||
|
||||
// Prepare payment data for PDAM
|
||||
$pdamData = [];
|
||||
foreach ($enquiryResponse->data as $d) {
|
||||
$pdamData[] = [
|
||||
'rek_nomor' => $d->rek_nomor ?? $d->rek_no ?? '',
|
||||
'rek_total' => $d->rek_total ?? 0,
|
||||
'serial' => '#TM' . time(),
|
||||
'byr_tgl' => date('YmdHis'),
|
||||
'loket' => 'TIMO',
|
||||
];
|
||||
}
|
||||
|
||||
$paymentPost = [
|
||||
'token' => $token,
|
||||
'data' => $pdamData
|
||||
];
|
||||
|
||||
// Send payment to PDAM API
|
||||
$timoPaymentUrl = 'https://timo.tirtaintan.co.id/payment/' . $token;
|
||||
$paymentResponse = HttpHelper::doCurl($timoPaymentUrl, 'POST', $paymentPost, true);
|
||||
|
||||
if ($paymentResponse && isset($paymentResponse->errno) && $paymentResponse->errno == 0) {
|
||||
// Payment successful - Record to database
|
||||
$pembayaranData = [
|
||||
'no_trx' => '#TIMO' . $token,
|
||||
'token' => $adminUser->timo_user,
|
||||
'no_sl' => $no_sl,
|
||||
'nama_bank' => 'WIPAY',
|
||||
'no_rekening' => $wipayUser->no_hp ?? '',
|
||||
'jumlah_tagihan' => (string)$amount,
|
||||
'biaya_admin' => (string)$biayaAdmin,
|
||||
'jumlah_unik' => '0',
|
||||
'promo' => '0',
|
||||
'raw_data' => json_encode($enquiryResponse->data),
|
||||
'waktu_expired' => date('Y-m-d H:i:s', strtotime('+1 days')),
|
||||
'status_bayar' => 'DIBAYAR',
|
||||
'tanggal_bayar' => date('Y-m-d H:i:s'),
|
||||
'jumlah_bayar' => (string)$totalPayment,
|
||||
'bukti_transfer' => '',
|
||||
'tanggal_request' => date('Y-m-d H:i:s'),
|
||||
'respon_wa' => '',
|
||||
'admin_2' => '0',
|
||||
'raw_bayar' => json_encode($paymentResponse),
|
||||
'banyak_cek' => '0'
|
||||
];
|
||||
|
||||
$pembayaranId = $this->db->insert('pembayaran', $pembayaranData);
|
||||
|
||||
// Deduct WIPAY saldo
|
||||
$this->db->insert('wipay_mutasi', [
|
||||
'wipay_user' => $wipayUser->id_wipay,
|
||||
'waktu_transaksi' => date('Y-m-d H:i:s'),
|
||||
'jumlah_mutasi' => $totalPayment * -1,
|
||||
'saldo_akhir' => $saldo - $totalPayment,
|
||||
'ket_mutasi' => "PEMBAYARAN PDAM SL $no_sl via Fast API",
|
||||
'detail_transaksi' => serialize($pembayaranData),
|
||||
'sumber_transaksi' => 'TRANSAKSI',
|
||||
]);
|
||||
|
||||
// Update WIPAY saldo
|
||||
$this->db->update('wipay_pengguna', [
|
||||
'saldo' => $saldo - $totalPayment
|
||||
], 'id_wipay = :id', ['id' => $wipayUser->id_wipay]);
|
||||
|
||||
// Log API usage
|
||||
$this->apiKeyModel->logApiUsage($apiKey->id, 'process_payment', 'success', [
|
||||
'no_sl' => $no_sl,
|
||||
'amount' => $amount,
|
||||
'token' => $token,
|
||||
'pembayaran_id' => $pembayaranId
|
||||
]);
|
||||
|
||||
return ResponseHelper::json($response, [
|
||||
'status' => 'success',
|
||||
'message' => 'Pembayaran berhasil diproses',
|
||||
'data' => [
|
||||
'pembayaran_id' => $pembayaranId,
|
||||
'no_trx' => $pembayaranData['no_trx'],
|
||||
'no_sl' => $no_sl,
|
||||
'amount' => $amount,
|
||||
'biaya_admin' => $biayaAdmin,
|
||||
'total_payment' => $totalPayment,
|
||||
'saldo_akhir' => $saldo - $totalPayment,
|
||||
'status' => 'DIBAYAR',
|
||||
'tanggal_pembayaran' => date('Y-m-d H:i:s')
|
||||
]
|
||||
], 200);
|
||||
} else {
|
||||
// Payment failed
|
||||
$this->apiKeyModel->logApiUsage($apiKey->id, 'process_payment', 'failed', [
|
||||
'no_sl' => $no_sl,
|
||||
'amount' => $amount,
|
||||
'token' => $token,
|
||||
'error' => json_encode($paymentResponse)
|
||||
]);
|
||||
|
||||
return ResponseHelper::json($response, [
|
||||
'status' => 'error',
|
||||
'message' => 'Gagal proses pembayaran ke PDAM: ' . ($paymentResponse->error ?? 'Unknown error')
|
||||
], 500);
|
||||
}
|
||||
} catch (\Exception $e) {
|
||||
error_log("Error in processPayment: " . $e->getMessage());
|
||||
return ResponseHelper::json($response, [
|
||||
'status' => 'error',
|
||||
'message' => 'Gagal proses pembayaran: ' . $e->getMessage()
|
||||
], 500);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* GET /fast/process_payment_get
|
||||
* Proses pembayaran via GET (temporary workaround)
|
||||
*/
|
||||
public function processPaymentGet(Request $request, Response $response): Response
|
||||
{
|
||||
// Same logic as processPayment but get data from query params
|
||||
$query = $request->getQueryParams();
|
||||
$request = $request->withParsedBody($query);
|
||||
return $this->processPayment($request, $response);
|
||||
}
|
||||
|
||||
/**
|
||||
* GET /fast/payment_status
|
||||
* Cek status pembayaran
|
||||
*/
|
||||
public function paymentStatus(Request $request, Response $response): Response
|
||||
{
|
||||
try {
|
||||
// Get API key
|
||||
$apiKey = $request->getAttribute('api_key');
|
||||
if (!$apiKey) {
|
||||
return ResponseHelper::json($response, [
|
||||
'status' => 'error',
|
||||
'message' => 'Invalid API key'
|
||||
], 401);
|
||||
}
|
||||
|
||||
// Get transaction_id
|
||||
$data = $request->getParsedBody() ?? [];
|
||||
$query = $request->getQueryParams();
|
||||
$transactionId = $data['transaction_id'] ?? $query['transaction_id'] ?? '';
|
||||
|
||||
if (empty($transactionId)) {
|
||||
return ResponseHelper::json($response, [
|
||||
'status' => 'error',
|
||||
'message' => 'Transaction ID is required'
|
||||
], 400);
|
||||
}
|
||||
|
||||
// Check payment status
|
||||
$payment = $this->db->fetchOne(
|
||||
"SELECT * FROM pembayaran WHERE id_pembayaran = :id LIMIT 1",
|
||||
['id' => $transactionId]
|
||||
);
|
||||
|
||||
if ($payment) {
|
||||
return ResponseHelper::json($response, [
|
||||
'status' => 'success',
|
||||
'data' => [
|
||||
'transaction_id' => $payment->id_pembayaran,
|
||||
'no_sl' => $payment->no_sl,
|
||||
'amount' => $payment->jumlah_tagihan,
|
||||
'status' => $payment->status_bayar,
|
||||
'created_at' => $payment->tanggal_request
|
||||
]
|
||||
], 200);
|
||||
} else {
|
||||
return ResponseHelper::json($response, [
|
||||
'status' => 'error',
|
||||
'message' => 'Transaction not found'
|
||||
], 404);
|
||||
}
|
||||
} catch (\Exception $e) {
|
||||
error_log("Error in paymentStatus: " . $e->getMessage());
|
||||
return ResponseHelper::json($response, [
|
||||
'status' => 'error',
|
||||
'message' => 'Gagal cek status pembayaran: ' . $e->getMessage()
|
||||
], 500);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* GET /fast/check_wipay_saldo
|
||||
* Cek saldo WIPAY
|
||||
*/
|
||||
public function checkWipaySaldo(Request $request, Response $response): Response
|
||||
{
|
||||
try {
|
||||
// Get API key
|
||||
$apiKey = $request->getAttribute('api_key');
|
||||
if (!$apiKey) {
|
||||
return ResponseHelper::json($response, [
|
||||
'status' => 'error',
|
||||
'message' => 'Invalid API key'
|
||||
], 401);
|
||||
}
|
||||
|
||||
// Get admin user and timo user
|
||||
$adminUser = $this->db->fetchOne(
|
||||
"SELECT * FROM admin_users WHERE id = :id LIMIT 1",
|
||||
['id' => $apiKey->admin_user_id]
|
||||
);
|
||||
|
||||
if (!$adminUser || !$adminUser->timo_user) {
|
||||
return ResponseHelper::json($response, [
|
||||
'status' => 'error',
|
||||
'message' => 'Admin user tidak memiliki data TIMO'
|
||||
], 404);
|
||||
}
|
||||
|
||||
$timoUser = $this->db->fetchOne(
|
||||
"SELECT * FROM pengguna_timo WHERE id_pengguna_timo = :id LIMIT 1",
|
||||
['id' => $adminUser->timo_user]
|
||||
);
|
||||
|
||||
if (!$timoUser) {
|
||||
return ResponseHelper::json($response, [
|
||||
'status' => 'error',
|
||||
'message' => 'User TIMO tidak ditemukan'
|
||||
], 404);
|
||||
}
|
||||
|
||||
if (!$timoUser->wipay || $timoUser->wipay <= 0) {
|
||||
return ResponseHelper::json($response, [
|
||||
'status' => 'error',
|
||||
'message' => 'User tidak memiliki akun WIPAY'
|
||||
], 400);
|
||||
}
|
||||
|
||||
$wipayUser = $this->db->fetchOne(
|
||||
"SELECT * FROM wipay_pengguna WHERE id_wipay = :id LIMIT 1",
|
||||
['id' => $timoUser->wipay]
|
||||
);
|
||||
|
||||
if (!$wipayUser) {
|
||||
return ResponseHelper::json($response, [
|
||||
'status' => 'error',
|
||||
'message' => 'Data WIPAY user tidak ditemukan'
|
||||
], 400);
|
||||
}
|
||||
|
||||
$saldo = $this->getWipaySaldo($wipayUser->id_wipay);
|
||||
|
||||
// Log API usage
|
||||
$this->apiKeyModel->logApiUsage($apiKey->id, 'check_wipay_saldo', 'success', [
|
||||
'user_id' => $apiKey->admin_user_id,
|
||||
'wipay_user_id' => $wipayUser->id_wipay
|
||||
]);
|
||||
|
||||
return ResponseHelper::json($response, [
|
||||
'status' => 'success',
|
||||
'message' => 'Saldo WIPAY berhasil dicek',
|
||||
'data' => [
|
||||
'user_id' => $apiKey->admin_user_id,
|
||||
'wipay_user_id' => $wipayUser->id_wipay,
|
||||
'nama_lengkap' => $wipayUser->nama_lengkap ?? '',
|
||||
'no_hp' => $wipayUser->no_hp ?? '',
|
||||
'saldo' => $saldo,
|
||||
'saldo_formatted' => 'Rp ' . number_format($saldo, 0, ',', '.'),
|
||||
'biaya_admin' => $timoUser->biaya_admin ?: 0
|
||||
]
|
||||
], 200);
|
||||
} catch (\Exception $e) {
|
||||
error_log("Error in checkWipaySaldo: " . $e->getMessage());
|
||||
return ResponseHelper::json($response, [
|
||||
'status' => 'error',
|
||||
'message' => 'Gagal cek saldo WIPAY: ' . $e->getMessage()
|
||||
], 500);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* GET /fast/check_wipay_saldo_get
|
||||
* Cek saldo WIPAY via GET
|
||||
*/
|
||||
public function checkWipaySaldoGet(Request $request, Response $response): Response
|
||||
{
|
||||
// Same as checkWipaySaldo
|
||||
return $this->checkWipaySaldo($request, $response);
|
||||
}
|
||||
|
||||
/**
|
||||
* GET /fast/mandiri/{tanggal}
|
||||
* Data Mandiri (mirip dengan /api/mandiri)
|
||||
*/
|
||||
public function mandiri(Request $request, Response $response, array $args): Response
|
||||
{
|
||||
$tanggal = $args['tanggal'] ?? '';
|
||||
|
||||
if (empty($tanggal)) {
|
||||
$response->getBody()->write('DATE NOT SPECIFIED');
|
||||
return $response->withStatus(400);
|
||||
}
|
||||
|
||||
// Parse tanggal format ddmmyyyy
|
||||
$format = "dmY";
|
||||
$date = \DateTime::createFromFormat($format, $tanggal);
|
||||
|
||||
if ($date) {
|
||||
$tanggal_cari = $date->format('Y-m-d');
|
||||
} else {
|
||||
$tanggal_cari = date('Y-m-d');
|
||||
}
|
||||
|
||||
// Get base URL
|
||||
$baseUrl = $_ENV['BASE_URL'] ??
|
||||
($request->getUri()->getScheme() . '://' . $request->getUri()->getHost());
|
||||
|
||||
// Query data
|
||||
$sql = "SELECT cm.no_sl, pt.no_hp, cm.tanggal_catat as tanggal_baca,
|
||||
cm.angka_meter,
|
||||
CONCAT(:base_url, '/assets/uploads/catat_meter/', cm.photo) as photo
|
||||
FROM catat_meter cm
|
||||
LEFT JOIN pengguna_timo pt ON cm.token = pt.id_pengguna_timo
|
||||
WHERE DATE(cm.tanggal_catat) = :tanggal_cari";
|
||||
|
||||
$data = $this->db->fetchAll($sql, [
|
||||
'base_url' => $baseUrl,
|
||||
'tanggal_cari' => $tanggal_cari
|
||||
]);
|
||||
|
||||
return ResponseHelper::json($response, [
|
||||
'status' => 1,
|
||||
'date' => $tanggal,
|
||||
'data' => $data
|
||||
], 200);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get WIPAY saldo
|
||||
*/
|
||||
private function getWipaySaldo($wipayUserId)
|
||||
{
|
||||
// Get latest saldo from mutasi or wipay_pengguna
|
||||
$mutasi = $this->db->fetchOne(
|
||||
"SELECT saldo_akhir FROM wipay_mutasi
|
||||
WHERE wipay_user = :id
|
||||
ORDER BY waktu_transaksi DESC LIMIT 1",
|
||||
['id' => $wipayUserId]
|
||||
);
|
||||
|
||||
if ($mutasi && isset($mutasi->saldo_akhir)) {
|
||||
return (float)$mutasi->saldo_akhir;
|
||||
}
|
||||
|
||||
// Fallback to wipay_pengguna saldo
|
||||
$wipayUser = $this->db->fetchOne(
|
||||
"SELECT saldo FROM wipay_pengguna WHERE id_wipay = :id LIMIT 1",
|
||||
['id' => $wipayUserId]
|
||||
);
|
||||
|
||||
return $wipayUser ? (float)($wipayUser->saldo ?? 0) : 0;
|
||||
}
|
||||
}
|
||||
88
src/Controllers/LaporanController.php
Normal file
88
src/Controllers/LaporanController.php
Normal file
@@ -0,0 +1,88 @@
|
||||
<?php
|
||||
|
||||
namespace App\Controllers;
|
||||
|
||||
use App\Config\Database;
|
||||
use App\Helpers\ResponseHelper;
|
||||
use App\Models\UserModel;
|
||||
use Psr\Http\Message\ResponseInterface as Response;
|
||||
use Psr\Http\Message\ServerRequestInterface as Request;
|
||||
|
||||
class LaporanController
|
||||
{
|
||||
private $db;
|
||||
private $userModel;
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this->db = Database::getInstance();
|
||||
$this->userModel = new UserModel();
|
||||
}
|
||||
|
||||
public function jenisLaporan(Request $request, Response $response): Response
|
||||
{
|
||||
// Format response awal sama dengan API lama
|
||||
$responseData = [
|
||||
'status' => 404,
|
||||
'pesan' => 'Error 404'
|
||||
];
|
||||
|
||||
$riwayat = $this->db->fetchAll(
|
||||
"SELECT * FROM jenis_gangguan ORDER BY tipe",
|
||||
[]
|
||||
);
|
||||
|
||||
if ($riwayat) {
|
||||
$responseData = [
|
||||
'status' => 200,
|
||||
'pesan' => '',
|
||||
'data' => $riwayat
|
||||
];
|
||||
}
|
||||
|
||||
return ResponseHelper::custom($response, $responseData, $responseData['status']);
|
||||
}
|
||||
|
||||
public function historyGangguan(Request $request, Response $response): Response
|
||||
{
|
||||
$data = $request->getParsedBody();
|
||||
$token = $data['token'] ?? '';
|
||||
|
||||
// Format response awal sama dengan API lama
|
||||
$responseData = [
|
||||
'status' => 404,
|
||||
'pesan' => 'Gagal mendapatkan detail Tagihan anda, silahkan coba beberapa saat lagi'
|
||||
];
|
||||
|
||||
if (empty($token)) {
|
||||
$responseData['pesan'] = 'Token harus diisi';
|
||||
return ResponseHelper::custom($response, $responseData, 404);
|
||||
}
|
||||
|
||||
$pengguna = $this->userModel->findById($token);
|
||||
if (!$pengguna) {
|
||||
$responseData['pesan'] = 'Token tidak Valid. Silahkan Login dan Ulangi transaksi. Terima kasih';
|
||||
return ResponseHelper::custom($response, $responseData, 404);
|
||||
}
|
||||
|
||||
// API lama menggunakan JOIN dengan jenis_gangguan dan ORDER BY waktu_laporan DESC
|
||||
$riwayat = $this->db->fetchAll(
|
||||
"SELECT g.*, jg.* FROM gangguan g
|
||||
LEFT JOIN jenis_gangguan jg ON g.jenis_gangguan = jg.id_jenis_gangguan
|
||||
WHERE g.token = :token
|
||||
ORDER BY g.waktu_laporan DESC
|
||||
LIMIT 20",
|
||||
['token' => $token]
|
||||
);
|
||||
|
||||
if ($riwayat) {
|
||||
$responseData = [
|
||||
'status' => 200,
|
||||
'pesan' => '',
|
||||
'data' => $riwayat
|
||||
];
|
||||
}
|
||||
|
||||
return ResponseHelper::custom($response, $responseData, $responseData['status']);
|
||||
}
|
||||
}
|
||||
194
src/Controllers/OtherController.php
Normal file
194
src/Controllers/OtherController.php
Normal file
@@ -0,0 +1,194 @@
|
||||
<?php
|
||||
|
||||
namespace App\Controllers;
|
||||
|
||||
use App\Config\Database;
|
||||
use App\Helpers\HttpHelper;
|
||||
use App\Helpers\ResponseHelper;
|
||||
use App\Models\UserModel;
|
||||
use Psr\Http\Message\ResponseInterface as Response;
|
||||
use Psr\Http\Message\ServerRequestInterface as Request;
|
||||
|
||||
class OtherController
|
||||
{
|
||||
private $db;
|
||||
private $userModel;
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this->db = Database::getInstance();
|
||||
$this->userModel = new UserModel();
|
||||
}
|
||||
|
||||
public function promo(Request $request, Response $response): Response
|
||||
{
|
||||
// Format response awal sama dengan API lama
|
||||
$responseData = [
|
||||
'status' => 404,
|
||||
'pesan' => 'Tidak ada Promo'
|
||||
];
|
||||
|
||||
// API lama menggunakan timo_promo dengan status_promo = 'AKTIF' dan berakhir_promo >= sekarang
|
||||
$promo = $this->db->fetchAll(
|
||||
"SELECT * FROM timo_promo WHERE status_promo = 'AKTIF' AND berakhir_promo >= NOW() ORDER BY id_promo DESC",
|
||||
[]
|
||||
);
|
||||
|
||||
if ($promo) {
|
||||
$responseData = [
|
||||
'status' => 200,
|
||||
'pesan' => '',
|
||||
'data' => $promo
|
||||
];
|
||||
}
|
||||
|
||||
return ResponseHelper::custom($response, $responseData, $responseData['status']);
|
||||
}
|
||||
|
||||
public function riwayatPasang(Request $request, Response $response): Response
|
||||
{
|
||||
$data = $request->getParsedBody();
|
||||
$token = $data['token'] ?? '';
|
||||
|
||||
// Format response awal sama dengan API lama
|
||||
$responseData = [
|
||||
'status' => 404,
|
||||
'pesan' => '-'
|
||||
];
|
||||
|
||||
if (empty($token)) {
|
||||
$responseData['pesan'] = 'Token harus diisi';
|
||||
return ResponseHelper::custom($response, $responseData, 404);
|
||||
}
|
||||
|
||||
$pengguna = $this->userModel->findById($token);
|
||||
if (!$pengguna) {
|
||||
$responseData['pesan'] = 'Token tidak Valid';
|
||||
return ResponseHelper::custom($response, $responseData, 404);
|
||||
}
|
||||
|
||||
$riwayat = $this->db->fetchAll(
|
||||
"SELECT * FROM pasang_baru WHERE token = :token ORDER BY id_pasang_baru DESC",
|
||||
['token' => $token]
|
||||
);
|
||||
|
||||
$responseData = [
|
||||
'status' => 200,
|
||||
'data' => $riwayat
|
||||
];
|
||||
|
||||
return ResponseHelper::custom($response, $responseData, 200);
|
||||
}
|
||||
|
||||
public function jadwalCatatMeter(Request $request, Response $response): Response
|
||||
{
|
||||
$data = $request->getParsedBody();
|
||||
$token = $data['token'] ?? '';
|
||||
|
||||
// Format response awal sama dengan API lama
|
||||
$responseData = [
|
||||
'status' => 404,
|
||||
'pesan' => '-'
|
||||
];
|
||||
|
||||
if (empty($token)) {
|
||||
$responseData['pesan'] = 'Token harus diisi';
|
||||
return ResponseHelper::custom($response, $responseData, 404);
|
||||
}
|
||||
|
||||
$pengguna = $this->userModel->findById($token);
|
||||
if (!$pengguna) {
|
||||
$responseData['pesan'] = 'Token tidak Valid. Silahkan Login dan Ulangi transaksi. Terima kasih';
|
||||
return ResponseHelper::custom($response, $responseData, 404);
|
||||
}
|
||||
|
||||
// Get jadwal dari pengaturan
|
||||
$jadwal = $this->db->fetchOne(
|
||||
"SELECT * FROM pengaturan WHERE kata_kunci = 'WAKTU_CATAT_METER' LIMIT 1",
|
||||
[]
|
||||
);
|
||||
|
||||
if ($jadwal) {
|
||||
// Get riwayat catat meter
|
||||
$riwayat = $this->db->fetchAll(
|
||||
"SELECT * FROM catat_meter WHERE token = :token ORDER BY id_catat_meter DESC LIMIT 50",
|
||||
['token' => $token]
|
||||
);
|
||||
|
||||
$responseData = [
|
||||
'status' => 200,
|
||||
'awal' => (int)$jadwal->val_1,
|
||||
'akhir' => (int)$jadwal->val_2,
|
||||
'riwayat' => $riwayat
|
||||
];
|
||||
}
|
||||
|
||||
return ResponseHelper::custom($response, $responseData, $responseData['status']);
|
||||
}
|
||||
|
||||
public function requestOrderBacaMandiri(Request $request, Response $response): Response
|
||||
{
|
||||
$data = $request->getParsedBody();
|
||||
$token = $data['token'] ?? '';
|
||||
$no_sl = $data['no_sl'] ?? '';
|
||||
|
||||
// Format response awal sama dengan API lama
|
||||
$responseData = [
|
||||
'status' => 404,
|
||||
'pesan' => '-'
|
||||
];
|
||||
|
||||
if (empty($token) || empty($no_sl)) {
|
||||
$responseData['pesan'] = 'Token dan nomor SL harus diisi';
|
||||
return ResponseHelper::custom($response, $responseData, 404);
|
||||
}
|
||||
|
||||
$pengguna = $this->userModel->findById($token);
|
||||
if (!$pengguna) {
|
||||
$responseData['pesan'] = 'Token tidak Valid';
|
||||
return ResponseHelper::custom($response, $responseData, 404);
|
||||
}
|
||||
|
||||
// Request order ke API eksternal (sesuai API lama: sendBacaMandiriRequest)
|
||||
$url = 'https://rasamala.tirtaintan.co.id/timo/order-cater/' . $no_sl;
|
||||
$postData = [
|
||||
'kar_id' => 'timo'
|
||||
];
|
||||
|
||||
// API lama menggunakan form-urlencoded, bukan JSON
|
||||
$headers = [
|
||||
'Content-Type: application/x-www-form-urlencoded',
|
||||
'Accept: application/json'
|
||||
];
|
||||
$apiResponse = HttpHelper::doCurl($url, 'POST', $postData, false, $headers, 30, 10);
|
||||
|
||||
// Handle response - bisa array atau object
|
||||
if ($apiResponse) {
|
||||
if (is_array($apiResponse) && !empty($apiResponse)) {
|
||||
$responseData = [
|
||||
'status' => 200,
|
||||
'pesan' => 'Order baca mandiri berhasil diambil',
|
||||
'data' => $apiResponse
|
||||
];
|
||||
} elseif (is_object($apiResponse) && isset($apiResponse->data)) {
|
||||
$responseData = [
|
||||
'status' => 200,
|
||||
'pesan' => 'Order baca mandiri berhasil diambil',
|
||||
'data' => $apiResponse->data
|
||||
];
|
||||
} elseif (is_object($apiResponse) && !empty((array)$apiResponse)) {
|
||||
$responseData = [
|
||||
'status' => 200,
|
||||
'pesan' => 'Order baca mandiri berhasil diambil',
|
||||
'data' => $apiResponse
|
||||
];
|
||||
} else {
|
||||
$responseData['pesan'] = 'Tidak ada order baca mandiri untuk SL ini';
|
||||
}
|
||||
} else {
|
||||
$responseData['pesan'] = 'Tidak ada order baca mandiri untuk SL ini';
|
||||
}
|
||||
|
||||
return ResponseHelper::custom($response, $responseData, $responseData['status']);
|
||||
}
|
||||
}
|
||||
644
src/Controllers/PembayaranController.php
Normal file
644
src/Controllers/PembayaranController.php
Normal file
@@ -0,0 +1,644 @@
|
||||
<?php
|
||||
|
||||
namespace App\Controllers;
|
||||
|
||||
use App\Helpers\HttpHelper;
|
||||
use App\Helpers\KodeHelper;
|
||||
use App\Helpers\QrisHelper;
|
||||
use App\Helpers\ResponseHelper;
|
||||
use App\Helpers\TelegramHelper;
|
||||
use App\Helpers\WhatsAppHelper;
|
||||
use App\Config\Database;
|
||||
use App\Models\PembayaranModel;
|
||||
use App\Models\UserModel;
|
||||
use Psr\Http\Message\ResponseInterface as Response;
|
||||
use Psr\Http\Message\ServerRequestInterface as Request;
|
||||
|
||||
class PembayaranController
|
||||
{
|
||||
private $pembayaranModel;
|
||||
private $userModel;
|
||||
private $db;
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this->pembayaranModel = new PembayaranModel();
|
||||
$this->userModel = new UserModel();
|
||||
$this->db = Database::getInstance();
|
||||
}
|
||||
|
||||
public function requestPembayaran(Request $request, Response $response): Response
|
||||
{
|
||||
$data = $request->getParsedBody();
|
||||
|
||||
$token = $data['token'] ?? '';
|
||||
$no_sl = $data['no_sl'] ?? '';
|
||||
$nama_bank = $data['nama_bank'] ?? '';
|
||||
$no_rek = $data['no_rek'] ?? '';
|
||||
$payment_method = $data['payment_method'] ?? 'transfer'; // transfer, qris
|
||||
|
||||
// Format response awal sama dengan API lama
|
||||
$responseData = [
|
||||
'status' => 404,
|
||||
'pesan' => 'Gagal mendapatkan detail Tagihan anda, silahkan coba beberapa saat lagi'
|
||||
];
|
||||
|
||||
if (empty($token) || empty($no_sl)) {
|
||||
$responseData['pesan'] = 'Token dan nomor SL harus diisi';
|
||||
return ResponseHelper::custom($response, $responseData, 404);
|
||||
}
|
||||
|
||||
$pengguna = $this->userModel->findById($token);
|
||||
if (!$pengguna) {
|
||||
$responseData['pesan'] = 'Token tidak Valid. Silahkan Login dan Ulangi transaksi. Terima kasih';
|
||||
return ResponseHelper::custom($response, $responseData, 404);
|
||||
}
|
||||
|
||||
// Cek apakah ada pembayaran yang masih aktif
|
||||
$cek_pembayaran = $this->pembayaranModel->findByTokenAndSL($token, $no_sl, 'DIBUAT');
|
||||
if ($cek_pembayaran && strtotime($cek_pembayaran->waktu_expired) > time()) {
|
||||
$responseData = [
|
||||
'status' => 200,
|
||||
'pesan' => '',
|
||||
'data' => $cek_pembayaran
|
||||
];
|
||||
return ResponseHelper::custom($response, $responseData, 200);
|
||||
}
|
||||
|
||||
// Jika ada pembayaran yang expired, update status
|
||||
if ($cek_pembayaran) {
|
||||
$this->pembayaranModel->update($cek_pembayaran->id_pembayaran, ['status_bayar' => 'EXPIRED']);
|
||||
}
|
||||
|
||||
// Buat pembayaran baru
|
||||
$biaya_admin = 0;
|
||||
$promo = 0;
|
||||
$jumlah_unik = 0; // QRIS tidak pakai kode unik
|
||||
|
||||
// Cek tagihan dari API TIMO
|
||||
$respon = HttpHelper::doCurl('https://timo.tirtaintan.co.id/enquiry/' . $no_sl);
|
||||
|
||||
if (!$respon || $respon->errno != 0) {
|
||||
$responseData['pesan'] = 'Gagal mendapatkan data tagihan dari server';
|
||||
return ResponseHelper::custom($response, $responseData, 404);
|
||||
}
|
||||
|
||||
if (count($respon->data) > 0) {
|
||||
$total_tagihan = 0;
|
||||
foreach ($respon->data as $d) {
|
||||
$total_tagihan += $d->rek_total;
|
||||
$biaya_admin += $pengguna->biaya_admin;
|
||||
}
|
||||
|
||||
$total_pembayaran = $total_tagihan + $biaya_admin;
|
||||
|
||||
// Validasi QRIS: hanya untuk transaksi < 70 ribu
|
||||
if ($payment_method === 'qris') {
|
||||
if ($total_pembayaran > 70000) {
|
||||
$responseData['pesan'] = 'QRIS hanya tersedia untuk transaksi di bawah Rp 70.000';
|
||||
return ResponseHelper::custom($response, $responseData, 404);
|
||||
}
|
||||
// QRIS tidak pakai kode unik
|
||||
$jumlah_unik = 0;
|
||||
} else {
|
||||
// BRI/Manual pakai kode unik
|
||||
$jumlah_unik = KodeHelper::generateKodeUnikPrioritas();
|
||||
}
|
||||
|
||||
$ins = [
|
||||
'no_trx' => '#TIMO' . $respon->token,
|
||||
'token' => $token,
|
||||
'no_sl' => $no_sl,
|
||||
'nama_bank' => $payment_method === 'qris' ? 'QRIS' : $nama_bank,
|
||||
'no_rekening' => $no_rek,
|
||||
'jumlah_tagihan' => (string)$total_tagihan,
|
||||
'biaya_admin' => (string)$biaya_admin,
|
||||
'jumlah_unik' => (string)$jumlah_unik,
|
||||
'promo' => (string)$promo,
|
||||
'raw_data' => json_encode($respon->data),
|
||||
'waktu_expired' => date('Y-m-d H:i:s', strtotime('+1 days')),
|
||||
'status_bayar' => 'DIBUAT',
|
||||
'tanggal_bayar' => '0000-00-00 00:00:00',
|
||||
'jumlah_bayar' => '0',
|
||||
'bukti_transfer' => '',
|
||||
'tanggal_request' => date('Y-m-d H:i:s'),
|
||||
];
|
||||
|
||||
$pembayaranId = $this->pembayaranModel->create($ins);
|
||||
|
||||
// Jika QRIS, generate QR code
|
||||
if ($payment_method === 'qris' && $pembayaranId) {
|
||||
$qrisResponse = QrisHelper::createInvoice($ins['no_trx'], (int)$total_pembayaran, false);
|
||||
|
||||
if ($qrisResponse && isset($qrisResponse['data'])) {
|
||||
$qrisData = $qrisResponse['data'];
|
||||
$qrisRequestDate = date('Y-m-d H:i:s');
|
||||
$expiredMinutes = QrisHelper::getExpiredMinutes();
|
||||
$expiredAt = date('Y-m-d H:i:s', strtotime("+{$expiredMinutes} minutes"));
|
||||
|
||||
// Update pembayaran dengan data QRIS
|
||||
$this->db->update('pembayaran', [
|
||||
'qris_qr_code' => $qrisData['qris_content'] ?? '',
|
||||
'qris_invoiceid' => $qrisData['qris_invoiceid'] ?? '',
|
||||
'qris_nmid' => $qrisData['qris_nmid'] ?? QrisHelper::getNmid(),
|
||||
'qris_request_date' => $qrisRequestDate,
|
||||
'qris_expired_at' => $expiredAt,
|
||||
'qris_check_count' => 0,
|
||||
'qris_last_check_at' => null,
|
||||
'qris_status' => 'unpaid' // Initial status
|
||||
], 'id_pembayaran = :id', ['id' => $pembayaranId]);
|
||||
|
||||
$ins['qris_qr_code'] = $qrisData['qris_content'] ?? '';
|
||||
$ins['qris_invoiceid'] = $qrisData['qris_invoiceid'] ?? '';
|
||||
$ins['qris_nmid'] = $qrisData['qris_nmid'] ?? QrisHelper::getNmid();
|
||||
$ins['qris_request_date'] = $qrisRequestDate;
|
||||
$ins['qris_expired_at'] = $expiredAt;
|
||||
$ins['qris_status'] = 'unpaid';
|
||||
} else {
|
||||
$responseData['pesan'] = 'Gagal generate QRIS, silahkan coba lagi';
|
||||
return ResponseHelper::custom($response, $responseData, 404);
|
||||
}
|
||||
}
|
||||
|
||||
if ($total_tagihan > 0) {
|
||||
$responseData = [
|
||||
'status' => 200,
|
||||
'pesan' => '',
|
||||
'data' => $ins
|
||||
];
|
||||
} else {
|
||||
$responseData['pesan'] = "Tidak ada tagihan untuk no SL $no_sl";
|
||||
}
|
||||
} else {
|
||||
$responseData['pesan'] = "Tidak ada tagihan untuk no SL $no_sl";
|
||||
}
|
||||
|
||||
return ResponseHelper::custom($response, $responseData, $responseData['status']);
|
||||
}
|
||||
|
||||
public function cekPembayaran(Request $request, Response $response): Response
|
||||
{
|
||||
$data = $request->getParsedBody();
|
||||
|
||||
$token = $data['token'] ?? '';
|
||||
$no_sl = $data['no_sl'] ?? '';
|
||||
|
||||
// Format response awal sama dengan API lama
|
||||
$responseData = [
|
||||
'status' => 404,
|
||||
'pesan' => 'Gagal mendapatkan detail Tagihan anda, silahkan coba beberapa saat lagi'
|
||||
];
|
||||
|
||||
if (empty($token) || empty($no_sl)) {
|
||||
$responseData['pesan'] = 'Token dan nomor SL harus diisi';
|
||||
return ResponseHelper::custom($response, $responseData, 404);
|
||||
}
|
||||
|
||||
$pengguna = $this->userModel->findById($token);
|
||||
if (!$pengguna) {
|
||||
$responseData['pesan'] = 'Token tidak Valid. Silahkan Login dan Ulangi transaksi. Terima kasih';
|
||||
return ResponseHelper::custom($response, $responseData, 404);
|
||||
}
|
||||
|
||||
// Cek pembayaran dengan status DIBUAT atau MENUNGGU VERIFIKASI
|
||||
$cek_pembayaran = $this->pembayaranModel->findByTokenAndSL($token, $no_sl, ['DIBUAT', 'MENUNGGU VERIFIKASI']);
|
||||
|
||||
if ($cek_pembayaran && strtotime($cek_pembayaran->waktu_expired) > time()) {
|
||||
$responseData = [
|
||||
'status' => 200,
|
||||
'pesan' => '',
|
||||
'data' => $cek_pembayaran
|
||||
];
|
||||
}
|
||||
|
||||
return ResponseHelper::custom($response, $responseData, $responseData['status']);
|
||||
}
|
||||
|
||||
public function cekTransfer(Request $request, Response $response): Response
|
||||
{
|
||||
$data = $request->getParsedBody();
|
||||
|
||||
$token = $data['token'] ?? '';
|
||||
$no_rek = $data['no_rek'] ?? '';
|
||||
|
||||
// Format response awal sama dengan API lama
|
||||
$responseData = [
|
||||
'status' => 404,
|
||||
'pesan' => 'Gagal membatalkan pembayaran, silahkan coba beberapa saat lagi'
|
||||
];
|
||||
|
||||
if (empty($token) || empty($no_rek)) {
|
||||
$responseData['pesan'] = 'Token dan nomor rekening harus diisi';
|
||||
return ResponseHelper::custom($response, $responseData, 404);
|
||||
}
|
||||
|
||||
$pengguna = $this->userModel->findById($token);
|
||||
if (!$pengguna) {
|
||||
$responseData['pesan'] = 'Token tidak Valid. Silahkan Login dan Ulangi transaksi. Terima kasih';
|
||||
return ResponseHelper::custom($response, $responseData, 404);
|
||||
}
|
||||
|
||||
$cek_pembayaran = $this->pembayaranModel->findByNoTrx($token, $no_rek);
|
||||
if ($cek_pembayaran) {
|
||||
$responseData = [
|
||||
'status' => 200,
|
||||
'pesan' => '',
|
||||
'data' => $cek_pembayaran
|
||||
];
|
||||
}
|
||||
|
||||
return ResponseHelper::custom($response, $responseData, $responseData['status']);
|
||||
}
|
||||
|
||||
public function batalPembayaran(Request $request, Response $response): Response
|
||||
{
|
||||
$data = $request->getParsedBody();
|
||||
|
||||
$token = $data['token'] ?? '';
|
||||
$no_rek = $data['no_rek'] ?? '';
|
||||
|
||||
// Format response awal sama dengan API lama
|
||||
$responseData = [
|
||||
'status' => 404,
|
||||
'pesan' => 'Gagal membatalkan pembayaran, silahkan coba beberapa saat lagi'
|
||||
];
|
||||
|
||||
if (empty($token) || empty($no_rek)) {
|
||||
$responseData['pesan'] = 'Token dan nomor rekening harus diisi';
|
||||
return ResponseHelper::custom($response, $responseData, 404);
|
||||
}
|
||||
|
||||
$pengguna = $this->userModel->findById($token);
|
||||
if (!$pengguna) {
|
||||
$responseData['pesan'] = 'Token tidak Valid. Silahkan Login dan Ulangi transaksi. Terima kasih';
|
||||
return ResponseHelper::custom($response, $responseData, 404);
|
||||
}
|
||||
|
||||
$cek_pembayaran = $this->pembayaranModel->findByNoTrx($token, $no_rek);
|
||||
if ($cek_pembayaran) {
|
||||
$this->pembayaranModel->update($cek_pembayaran->id_pembayaran, ['status_bayar' => 'DIBATALKAN']);
|
||||
// Format response sama dengan API lama: status 200, pesan tetap ada (tidak diubah)
|
||||
$responseData['status'] = 200;
|
||||
// Pesan tetap dengan nilai default, tidak diubah (sesuai API lama)
|
||||
} else {
|
||||
$responseData['pesan'] = 'Tidak ada data dengan no SL $';
|
||||
}
|
||||
|
||||
return ResponseHelper::custom($response, $responseData, $responseData['status']);
|
||||
}
|
||||
|
||||
public function confirmPembayaran(Request $request, Response $response): Response
|
||||
{
|
||||
$data = $request->getParsedBody();
|
||||
|
||||
$token = $data['token'] ?? '';
|
||||
$no_rek = $data['no_rek'] ?? ''; // API lama menggunakan no_rek (no_trx)
|
||||
|
||||
// Format response awal sama dengan API lama
|
||||
$responseData = [
|
||||
'status' => 404,
|
||||
'pesan' => 'Gagal membatalkan pembayaran, silahkan coba beberapa saat lagi'
|
||||
];
|
||||
|
||||
if (empty($token) || empty($no_rek)) {
|
||||
$responseData['pesan'] = 'Token dan nomor rekening harus diisi';
|
||||
return ResponseHelper::custom($response, $responseData, 404);
|
||||
}
|
||||
|
||||
$pengguna = $this->userModel->findById($token);
|
||||
if (!$pengguna) {
|
||||
$responseData['pesan'] = 'Token tidak Valid. Silahkan Login dan Ulangi transaksi. Terima kasih';
|
||||
return ResponseHelper::custom($response, $responseData, 404);
|
||||
}
|
||||
|
||||
// Cari pembayaran berdasarkan no_trx (no_rek)
|
||||
$cek_pembayaran = $this->pembayaranModel->findByNoTrx($token, $no_rek);
|
||||
if ($cek_pembayaran) {
|
||||
// Update status ke MENUNGGU VERIFIKASI
|
||||
$this->pembayaranModel->update($cek_pembayaran->id_pembayaran, [
|
||||
'status_bayar' => 'MENUNGGU VERIFIKASI'
|
||||
]);
|
||||
|
||||
// Kirim notifikasi Telegram
|
||||
$pesan = "🔔 *TRANSAKSI BARU*\n\n"
|
||||
. "No. Transaksi: " . $cek_pembayaran->no_trx . "\n"
|
||||
. "No. SL: " . $cek_pembayaran->no_sl . "\n"
|
||||
. "Jumlah: Rp " . number_format($cek_pembayaran->jumlah_tagihan + $cek_pembayaran->biaya_admin, 0, ',', '.') . "\n"
|
||||
. "Status: MENUNGGU VERIFIKASI\n\n"
|
||||
. "Silahkan verifikasi pembayaran.";
|
||||
TelegramHelper::sendToTransactionAdmin($pesan);
|
||||
|
||||
// Update respon_wa field
|
||||
$this->pembayaranModel->update($cek_pembayaran->id_pembayaran, [
|
||||
'respon_wa' => 'TELEGRAM_SENT_' . date('Y-m-d H:i:s') . ' | SUCCESS'
|
||||
]);
|
||||
|
||||
// Format response sama dengan API lama: status 200, pesan tetap ada (tidak diubah)
|
||||
$responseData['status'] = 200;
|
||||
// Pesan tetap dengan nilai default, tidak diubah (sesuai API lama)
|
||||
}
|
||||
|
||||
return ResponseHelper::custom($response, $responseData, $responseData['status']);
|
||||
}
|
||||
|
||||
public function historyBayar(Request $request, Response $response): Response
|
||||
{
|
||||
$data = $request->getParsedBody();
|
||||
|
||||
$token = $data['token'] ?? '';
|
||||
|
||||
// Format response awal sama dengan API lama
|
||||
$responseData = [
|
||||
'status' => 404,
|
||||
'pesan' => '-'
|
||||
];
|
||||
|
||||
if (empty($token)) {
|
||||
$responseData['pesan'] = 'Token harus diisi';
|
||||
return ResponseHelper::custom($response, $responseData, 404);
|
||||
}
|
||||
|
||||
$pengguna = $this->userModel->findById($token);
|
||||
if (!$pengguna) {
|
||||
$responseData['pesan'] = 'Token tidak Valid';
|
||||
return ResponseHelper::custom($response, $responseData, 404);
|
||||
}
|
||||
|
||||
// History bayar hanya menampilkan yang status DIBAYAR (sama dengan API lama)
|
||||
$history = $this->pembayaranModel->getHistoryByToken($token, 'DIBAYAR', 20);
|
||||
|
||||
$responseData = [
|
||||
'status' => 200,
|
||||
'pesan' => '',
|
||||
'data' => $history
|
||||
];
|
||||
|
||||
return ResponseHelper::custom($response, $responseData, 200);
|
||||
}
|
||||
|
||||
/**
|
||||
* POST /timo/cek_status_qris
|
||||
* Check QRIS payment status (user-triggered)
|
||||
*/
|
||||
public function cekStatusQris(Request $request, Response $response): Response
|
||||
{
|
||||
$data = $request->getParsedBody();
|
||||
|
||||
$token = $data['token'] ?? '';
|
||||
$no_sl = $data['no_sl'] ?? '';
|
||||
|
||||
$responseData = [
|
||||
'status' => 404,
|
||||
'pesan' => 'Gagal cek status QRIS'
|
||||
];
|
||||
|
||||
if (empty($token) || empty($no_sl)) {
|
||||
$responseData['pesan'] = 'Token dan nomor SL harus diisi';
|
||||
return ResponseHelper::custom($response, $responseData, 404);
|
||||
}
|
||||
|
||||
$pengguna = $this->userModel->findById($token);
|
||||
if (!$pengguna) {
|
||||
$responseData['pesan'] = 'Token tidak Valid';
|
||||
return ResponseHelper::custom($response, $responseData, 404);
|
||||
}
|
||||
|
||||
// Cari pembayaran QRIS dengan status DIBUAT
|
||||
$pembayaran = $this->db->fetchOne(
|
||||
"SELECT * FROM pembayaran
|
||||
WHERE token = :token AND no_sl = :no_sl
|
||||
AND nama_bank = 'QRIS'
|
||||
AND status_bayar = 'DIBUAT'
|
||||
AND qris_invoiceid IS NOT NULL
|
||||
ORDER BY id_pembayaran DESC LIMIT 1",
|
||||
['token' => $token, 'no_sl' => $no_sl]
|
||||
);
|
||||
|
||||
if (!$pembayaran) {
|
||||
$responseData['pesan'] = 'Pembayaran QRIS tidak ditemukan';
|
||||
return ResponseHelper::custom($response, $responseData, 404);
|
||||
}
|
||||
|
||||
// Cek apakah sudah expired
|
||||
if ($pembayaran->qris_expired_at && strtotime($pembayaran->qris_expired_at) < time()) {
|
||||
// Update status ke expired
|
||||
$this->db->update('pembayaran', [
|
||||
'qris_status' => 'expired'
|
||||
], 'id_pembayaran = :id', ['id' => $pembayaran->id_pembayaran]);
|
||||
|
||||
$responseData['pesan'] = 'QRIS sudah expired';
|
||||
$responseData['data'] = [
|
||||
'status' => 'expired',
|
||||
'message' => 'QRIS sudah expired. Silahkan buat pembayaran baru.'
|
||||
];
|
||||
return ResponseHelper::custom($response, $responseData, 404);
|
||||
}
|
||||
|
||||
// Cek apakah sudah mencapai max attempts (3)
|
||||
$checkCount = ($pembayaran->qris_check_count ?? 0);
|
||||
if ($checkCount >= 3) {
|
||||
$responseData = [
|
||||
'status' => 200,
|
||||
'pesan' => 'Silahkan upload bukti pembayaran atau hubungi customer service',
|
||||
'data' => [
|
||||
'status' => 'pending_verification',
|
||||
'check_count' => $checkCount,
|
||||
'message' => 'Pembayaran belum terdeteksi. Silahkan upload bukti pembayaran atau hubungi CS.',
|
||||
'show_upload_proof' => true,
|
||||
'show_contact_cs' => true
|
||||
]
|
||||
];
|
||||
return ResponseHelper::custom($response, $responseData, 200);
|
||||
}
|
||||
|
||||
// Cek status dari QRIS API dengan retry mechanism
|
||||
$totalBayar = (int)$pembayaran->jumlah_tagihan + (int)$pembayaran->biaya_admin;
|
||||
$transactionDate = $pembayaran->qris_request_date ?? $pembayaran->tanggal_request;
|
||||
$transactionDate = date('Y-m-d', strtotime($transactionDate)); // Format: YYYY-MM-DD
|
||||
|
||||
// Gunakan checkStatusWithRetry (max 3 attempts, 15 seconds interval)
|
||||
$qrisStatus = QrisHelper::checkStatusWithRetry(
|
||||
(int)$pembayaran->qris_invoiceid,
|
||||
$totalBayar,
|
||||
$transactionDate
|
||||
);
|
||||
|
||||
// Update check count
|
||||
$checkCount = $checkCount + 1;
|
||||
$this->db->update('pembayaran', [
|
||||
'qris_check_count' => $checkCount,
|
||||
'qris_last_check_at' => date('Y-m-d H:i:s')
|
||||
], 'id_pembayaran = :id', ['id' => $pembayaran->id_pembayaran]);
|
||||
|
||||
// Check response
|
||||
if ($qrisStatus && isset($qrisStatus['status']) && $qrisStatus['status'] == 'success') {
|
||||
$qrisData = $qrisStatus['data'] ?? [];
|
||||
$paymentStatus = $qrisData['qris_status'] ?? 'unpaid';
|
||||
|
||||
if ($paymentStatus == 'paid') {
|
||||
// Payment sudah dibayar, auto approve
|
||||
$this->autoApproveQris($pembayaran->id_pembayaran, $qrisData);
|
||||
|
||||
$responseData = [
|
||||
'status' => 200,
|
||||
'pesan' => 'Pembayaran berhasil',
|
||||
'data' => [
|
||||
'status' => 'paid',
|
||||
'message' => 'Pembayaran QRIS berhasil diverifikasi',
|
||||
'payment_method' => $qrisData['qris_payment_methodby'] ?? '',
|
||||
'customer_name' => $qrisData['qris_payment_customername'] ?? ''
|
||||
]
|
||||
];
|
||||
} else {
|
||||
// Masih unpaid
|
||||
if ($checkCount >= 3) {
|
||||
$responseData = [
|
||||
'status' => 200,
|
||||
'pesan' => 'Silahkan upload bukti pembayaran atau hubungi customer service',
|
||||
'data' => [
|
||||
'status' => 'pending_verification',
|
||||
'check_count' => $checkCount,
|
||||
'message' => 'Pembayaran belum terdeteksi setelah 3x pengecekan. Silahkan upload bukti pembayaran.',
|
||||
'show_upload_proof' => true,
|
||||
'show_contact_cs' => true
|
||||
]
|
||||
];
|
||||
} else {
|
||||
$responseData = [
|
||||
'status' => 200,
|
||||
'pesan' => 'Menunggu pembayaran',
|
||||
'data' => [
|
||||
'status' => 'unpaid',
|
||||
'check_count' => $checkCount,
|
||||
'remaining_attempts' => 3 - $checkCount,
|
||||
'message' => 'Silahkan scan QR code dan lakukan pembayaran'
|
||||
]
|
||||
];
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// Request gagal atau response tidak valid
|
||||
if ($checkCount >= 3) {
|
||||
$responseData = [
|
||||
'status' => 200,
|
||||
'pesan' => 'Silahkan upload bukti pembayaran atau hubungi customer service',
|
||||
'data' => [
|
||||
'status' => 'pending_verification',
|
||||
'check_count' => $checkCount,
|
||||
'message' => 'Gagal mengecek status pembayaran. Silahkan upload bukti pembayaran.',
|
||||
'show_upload_proof' => true,
|
||||
'show_contact_cs' => true
|
||||
]
|
||||
];
|
||||
} else {
|
||||
$responseData = [
|
||||
'status' => 200,
|
||||
'pesan' => 'Menunggu pembayaran',
|
||||
'data' => [
|
||||
'status' => 'unpaid',
|
||||
'check_count' => $checkCount,
|
||||
'remaining_attempts' => 3 - $checkCount,
|
||||
'message' => 'Silahkan scan QR code dan lakukan pembayaran'
|
||||
]
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
return ResponseHelper::custom($response, $responseData, 200);
|
||||
}
|
||||
|
||||
/**
|
||||
* Auto approve QRIS payment setelah verified paid
|
||||
*
|
||||
* @param int $pembayaranId ID pembayaran
|
||||
* @param array $qrisData Data dari QRIS API response
|
||||
*/
|
||||
private function autoApproveQris($pembayaranId, $qrisData = [])
|
||||
{
|
||||
try {
|
||||
$pembayaran = $this->db->fetchOne(
|
||||
"SELECT * FROM pembayaran WHERE id_pembayaran = :id LIMIT 1",
|
||||
['id' => $pembayaranId]
|
||||
);
|
||||
|
||||
if (!$pembayaran || $pembayaran->status_bayar !== 'DIBUAT') {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Update status ke MENUNGGU VERIFIKASI (sementara)
|
||||
$this->db->update('pembayaran', [
|
||||
'status_bayar' => 'MENUNGGU VERIFIKASI',
|
||||
'qris_status' => 'paid',
|
||||
'qris_payment_method' => $qrisData['qris_payment_methodby'] ?? '',
|
||||
'qris_payment_customer_name' => $qrisData['qris_payment_customername'] ?? ''
|
||||
], 'id_pembayaran = :id', ['id' => $pembayaranId]);
|
||||
|
||||
// Approve ke PDAM (sama seperti SiteController::approve)
|
||||
$token = str_replace('#TIMO', '', $pembayaran->no_trx);
|
||||
$url = "https://timo.tirtaintan.co.id/payment/$token";
|
||||
|
||||
$data = [];
|
||||
$rincian = json_decode($pembayaran->raw_data);
|
||||
|
||||
if (is_array($rincian) && count($rincian) > 0) {
|
||||
foreach ($rincian as $r) {
|
||||
$data[] = [
|
||||
'rek_nomor' => $r->rek_nomor ?? $r->rek_no ?? '',
|
||||
'rek_total' => $r->rek_total ?? 0,
|
||||
'serial' => '#TM' . time(),
|
||||
'byr_tgl' => date('YmdHis'),
|
||||
'loket' => 'TIMO',
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
$post = [
|
||||
'token' => $token,
|
||||
'data' => $data
|
||||
];
|
||||
|
||||
$headers = [
|
||||
'Content-Type: application/json',
|
||||
'Accept-Encoding: gzip, deflate',
|
||||
'Cache-Control: max-age=0',
|
||||
'Connection: keep-alive',
|
||||
'Accept-Language: en-US,en;q=0.8,id;q=0.6'
|
||||
];
|
||||
|
||||
$paymentResponse = HttpHelper::doCurl($url, 'POST', $post, true, $headers);
|
||||
|
||||
if ($paymentResponse && isset($paymentResponse->errno) && $paymentResponse->errno == 0) {
|
||||
$totalBayar = (int)$pembayaran->jumlah_tagihan + (int)$pembayaran->biaya_admin;
|
||||
$paidAt = date('Y-m-d H:i:s');
|
||||
|
||||
$this->db->update('pembayaran', [
|
||||
'status_bayar' => 'DIBAYAR',
|
||||
'tanggal_bayar' => $paidAt,
|
||||
'jumlah_bayar' => (string)$totalBayar,
|
||||
'raw_bayar' => json_encode($paymentResponse),
|
||||
'qris_paid_at' => $paidAt
|
||||
], 'id_pembayaran = :id', ['id' => $pembayaranId]);
|
||||
|
||||
// Kirim notifikasi WhatsApp ke user
|
||||
$user = $this->userModel->findById($pembayaran->token);
|
||||
if ($user && $user->no_hp) {
|
||||
$pesan = "✅ *Pembayaran Berhasil*\n\n"
|
||||
. "No. Transaksi: " . $pembayaran->no_trx . "\n"
|
||||
. "No. SL: " . $pembayaran->no_sl . "\n"
|
||||
. "Jumlah: Rp " . number_format($totalBayar, 0, ',', '.') . "\n"
|
||||
. "Metode: QRIS\n"
|
||||
. "E-Wallet: " . ($qrisData['qris_payment_methodby'] ?? '-') . "\n\n"
|
||||
. "Terima kasih telah melakukan pembayaran.";
|
||||
WhatsAppHelper::sendWa($user->no_hp, $pesan);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
} catch (\Exception $e) {
|
||||
error_log("Error in autoApproveQris: " . $e->getMessage());
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
179
src/Controllers/ResetPasswordController.php
Normal file
179
src/Controllers/ResetPasswordController.php
Normal file
@@ -0,0 +1,179 @@
|
||||
<?php
|
||||
|
||||
namespace App\Controllers;
|
||||
|
||||
use App\Config\Database;
|
||||
use App\Helpers\KodeHelper;
|
||||
use App\Helpers\ResponseHelper;
|
||||
use App\Helpers\WhatsAppHelper;
|
||||
use App\Models\UserModel;
|
||||
use Psr\Http\Message\ResponseInterface as Response;
|
||||
use Psr\Http\Message\ServerRequestInterface as Request;
|
||||
|
||||
class ResetPasswordController
|
||||
{
|
||||
private $db;
|
||||
private $userModel;
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this->db = Database::getInstance();
|
||||
$this->userModel = new UserModel();
|
||||
}
|
||||
|
||||
public function buatKode(Request $request, Response $response): Response
|
||||
{
|
||||
$data = $request->getParsedBody();
|
||||
$email = $data['email'] ?? '';
|
||||
|
||||
// Format response awal sama dengan API lama
|
||||
$responseData = [
|
||||
'status' => 404,
|
||||
'pesan' => 'Kami sedang melakukan peningkatan sistem, silahkan coba beberapa saat lagi'
|
||||
];
|
||||
|
||||
if (empty($email)) {
|
||||
$responseData['pesan'] = 'Email/No HP harus diisi';
|
||||
return ResponseHelper::custom($response, $responseData, 404);
|
||||
}
|
||||
|
||||
// Cari user berdasarkan no_hp (email di API lama sebenarnya no_hp)
|
||||
$pengguna = $this->db->fetchOne(
|
||||
"SELECT * FROM pengguna_timo WHERE no_hp = :no_hp LIMIT 1",
|
||||
['no_hp' => $email]
|
||||
);
|
||||
|
||||
if (!$pengguna) {
|
||||
$responseData['pesan'] = 'No HP tidak terdaftar. Silahkan buat akun atau masukan kembali email yang terdaftar. Terima kasih';
|
||||
return ResponseHelper::custom($response, $responseData, 404);
|
||||
}
|
||||
|
||||
// Generate kode verifikasi (6 digit)
|
||||
$kode_verifikasi = KodeHelper::generateRandomString(6);
|
||||
|
||||
// Insert kode verifikasi
|
||||
$this->db->insert('kode_verifikasi_timo', [
|
||||
'email' => $pengguna->email,
|
||||
'kode' => (string)$kode_verifikasi,
|
||||
'waktu_ver' => date('Y-m-d H:i:s'),
|
||||
'waktu_exp' => date('Y-m-d H:i:s', strtotime('+10 minute')),
|
||||
'status_reset' => 'DIBUAT'
|
||||
]);
|
||||
|
||||
// Kirim WhatsApp
|
||||
if ($pengguna && !empty($pengguna->no_hp)) {
|
||||
$wa_pesan = "Halo {$pengguna->nama_lengkap},\n\n"
|
||||
. "Kode verifikasi untuk reset password Anda adalah: *{$kode_verifikasi}*\n\n"
|
||||
. "Kode ini berlaku selama 10 menit.\n"
|
||||
. "Jangan berikan kode ini kepada siapapun.\n\n"
|
||||
. "Terima kasih.";
|
||||
WhatsAppHelper::sendWa($pengguna->no_hp, $wa_pesan);
|
||||
}
|
||||
|
||||
$responseData = [
|
||||
'status' => 200,
|
||||
'pesan' => 'Kode Berhasil'
|
||||
];
|
||||
|
||||
return ResponseHelper::custom($response, $responseData, 200);
|
||||
}
|
||||
|
||||
public function cekKode(Request $request, Response $response): Response
|
||||
{
|
||||
$data = $request->getParsedBody();
|
||||
$kode = $data['kode'] ?? '';
|
||||
|
||||
// Format response awal sama dengan API lama
|
||||
$responseData = [
|
||||
'status' => 404,
|
||||
'pesan' => 'Kami sedang melakukan peningkatan sistem, silahkan coba beberapa saat lagi'
|
||||
];
|
||||
|
||||
if (empty($kode)) {
|
||||
$responseData['pesan'] = 'Kode harus diisi';
|
||||
return ResponseHelper::custom($response, $responseData, 404);
|
||||
}
|
||||
|
||||
// Cek kode verifikasi
|
||||
$verifikasi = $this->db->fetchOne(
|
||||
"SELECT * FROM kode_verifikasi_timo
|
||||
WHERE kode = :kode
|
||||
AND waktu_exp >= :waktu_exp
|
||||
AND status_reset = 'DIBUAT'
|
||||
LIMIT 1",
|
||||
[
|
||||
'kode' => $kode,
|
||||
'waktu_exp' => date('Y-m-d H:i:s')
|
||||
]
|
||||
);
|
||||
|
||||
if (!$verifikasi) {
|
||||
$responseData['pesan'] = 'Kode verifikasi Kadaluarsa, silahkan coba lagi dengan mengekan tombol Lupa Password. Terima Kasih';
|
||||
return ResponseHelper::custom($response, $responseData, 404);
|
||||
}
|
||||
|
||||
$responseData = [
|
||||
'status' => 200,
|
||||
'pesan' => 'Kode Ada'
|
||||
];
|
||||
|
||||
return ResponseHelper::custom($response, $responseData, 200);
|
||||
}
|
||||
|
||||
public function resetKode(Request $request, Response $response): Response
|
||||
{
|
||||
$data = $request->getParsedBody();
|
||||
$kode = $data['kode'] ?? '';
|
||||
$password = $data['password'] ?? '';
|
||||
|
||||
// Format response awal sama dengan API lama
|
||||
$responseData = [
|
||||
'status' => 404,
|
||||
'pesan' => 'Kami sedang melakukan peningkatan sistem, silahkan coba beberapa saat lagi'
|
||||
];
|
||||
|
||||
if (empty($kode) || empty($password)) {
|
||||
$responseData['pesan'] = 'Kode dan password harus diisi';
|
||||
return ResponseHelper::custom($response, $responseData, 404);
|
||||
}
|
||||
|
||||
// Cek kode verifikasi
|
||||
$verifikasi = $this->db->fetchOne(
|
||||
"SELECT * FROM kode_verifikasi_timo
|
||||
WHERE kode = :kode
|
||||
AND waktu_exp >= :waktu_exp
|
||||
AND status_reset = 'DIBUAT'
|
||||
LIMIT 1",
|
||||
[
|
||||
'kode' => $kode,
|
||||
'waktu_exp' => date('Y-m-d H:i:s')
|
||||
]
|
||||
);
|
||||
|
||||
if (!$verifikasi) {
|
||||
$responseData['pesan'] = 'Kode verifikasi Kadaluarsa, silahkan coba lagi dengan mengekan tombol Lupa Password. Terima Kasih';
|
||||
return ResponseHelper::custom($response, $responseData, 404);
|
||||
}
|
||||
|
||||
// Update password user
|
||||
$this->db->update('pengguna_timo',
|
||||
['password' => md5($password)],
|
||||
'email = :email',
|
||||
['email' => $verifikasi->email]
|
||||
);
|
||||
|
||||
// Update status kode verifikasi
|
||||
$this->db->update('kode_verifikasi_timo',
|
||||
['status_reset' => 'DIRESET'],
|
||||
'id_kode_verifikasi_timo = :id',
|
||||
['id' => $verifikasi->id_kode_verifikasi_timo]
|
||||
);
|
||||
|
||||
$responseData = [
|
||||
'status' => 200,
|
||||
'pesan' => 'Berhasil Ada'
|
||||
];
|
||||
|
||||
return ResponseHelper::custom($response, $responseData, 200);
|
||||
}
|
||||
}
|
||||
207
src/Controllers/SLController.php
Normal file
207
src/Controllers/SLController.php
Normal file
@@ -0,0 +1,207 @@
|
||||
<?php
|
||||
|
||||
namespace App\Controllers;
|
||||
|
||||
use App\Helpers\HttpHelper;
|
||||
use App\Helpers\ResponseHelper;
|
||||
use App\Models\SLModel;
|
||||
use Psr\Http\Message\ResponseInterface as Response;
|
||||
use Psr\Http\Message\ServerRequestInterface as Request;
|
||||
|
||||
class SLController
|
||||
{
|
||||
private $slModel;
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this->slModel = new SLModel();
|
||||
}
|
||||
|
||||
public function cekSL(Request $request, Response $response): Response
|
||||
{
|
||||
$data = $request->getParsedBody();
|
||||
$token = $data['token'] ?? '';
|
||||
$no_sl = $data['no_sl'] ?? '';
|
||||
|
||||
// Format response awal sama dengan API lama
|
||||
$responseData = [
|
||||
'status' => 404,
|
||||
'pesan' => '-'
|
||||
];
|
||||
|
||||
if (empty($token) || empty($no_sl)) {
|
||||
$responseData['pesan'] = 'Token dan nomor SL harus diisi';
|
||||
return ResponseHelper::custom($response, $responseData, 404);
|
||||
}
|
||||
|
||||
// Cek apakah SL sudah terdaftar oleh user lain
|
||||
$sudahAda = $this->slModel->findByNoSL($no_sl);
|
||||
if ($sudahAda) {
|
||||
$responseData = [
|
||||
'status' => 300,
|
||||
'pesan' => "NO SL \"{$no_sl}\" sudah didaftarkan oleh AKUN Lain"
|
||||
];
|
||||
return ResponseHelper::custom($response, $responseData, 300);
|
||||
}
|
||||
|
||||
// Cek apakah SL sudah terdaftar di akun user ini
|
||||
$cek = $this->slModel->findByTokenAndSL($token, $no_sl);
|
||||
if ($cek) {
|
||||
$responseData = [
|
||||
'status' => 300,
|
||||
'pesan' => "NO SL \"{$no_sl}\" sudah terdaftar di akun anda. Silahkan cek di daftar SL"
|
||||
];
|
||||
return ResponseHelper::custom($response, $responseData, 300);
|
||||
}
|
||||
|
||||
// Cek ke API TIMO
|
||||
$respon = HttpHelper::doCurl('https://timo.tirtaintan.co.id/enquiry-dil/' . $no_sl);
|
||||
|
||||
// Handle response yang bisa berupa array atau object
|
||||
if (!$respon) {
|
||||
$responseData['pesan'] = 'Data pelanggan tidak ditemukan';
|
||||
return ResponseHelper::custom($response, $responseData, 404);
|
||||
}
|
||||
|
||||
// Convert to array untuk konsistensi
|
||||
if (is_object($respon)) {
|
||||
$respon = (array)$respon;
|
||||
}
|
||||
|
||||
// Check for error
|
||||
if (isset($respon['errno']) && $respon['errno'] != 0) {
|
||||
$responseData['pesan'] = $respon['error'] ?? 'Data pelanggan tidak ditemukan';
|
||||
return ResponseHelper::custom($response, $responseData, 404);
|
||||
}
|
||||
|
||||
// Check for HTTP error status
|
||||
if (isset($respon['status']) && $respon['status'] != 200) {
|
||||
$responseData['pesan'] = $respon['error'] ?? 'Data pelanggan tidak ditemukan';
|
||||
return ResponseHelper::custom($response, $responseData, 404);
|
||||
}
|
||||
|
||||
// Get data - bisa dari 'data' key atau langsung dari response
|
||||
$data = $respon['data'] ?? $respon;
|
||||
|
||||
// Format response sukses sama dengan API lama: status, pesan, data langsung di root
|
||||
$responseData = [
|
||||
'status' => 200,
|
||||
'data' => $data
|
||||
];
|
||||
|
||||
return ResponseHelper::custom($response, $responseData, 200);
|
||||
}
|
||||
|
||||
public function confirmSL(Request $request, Response $response): Response
|
||||
{
|
||||
$data = $request->getParsedBody();
|
||||
$token = $data['token'] ?? '';
|
||||
$no_sl = $data['no_sl'] ?? '';
|
||||
|
||||
// Format response awal sama dengan API lama
|
||||
$responseData = [
|
||||
'status' => 404,
|
||||
'pesan' => '-'
|
||||
];
|
||||
|
||||
if (empty($token) || empty($no_sl)) {
|
||||
$responseData['pesan'] = 'Token dan nomor SL harus diisi';
|
||||
return ResponseHelper::custom($response, $responseData, 404);
|
||||
}
|
||||
|
||||
// Cek apakah sudah terdaftar
|
||||
$cek = $this->slModel->findByTokenAndSL($token, $no_sl);
|
||||
if ($cek) {
|
||||
$responseData = [
|
||||
'status' => 300,
|
||||
'pesan' => "NO SL \"{$no_sl}\" sudah terdaftar di akun anda. Silahkan cek di daftar SL"
|
||||
];
|
||||
return ResponseHelper::custom($response, $responseData, 300);
|
||||
}
|
||||
|
||||
// Cek ke API TIMO
|
||||
$respon = HttpHelper::doCurl('https://timo.tirtaintan.co.id/enquiry-dil/' . $no_sl);
|
||||
|
||||
// Handle response yang bisa berupa array atau object
|
||||
if (!$respon) {
|
||||
$responseData['pesan'] = 'Data pelanggan tidak ditemukan';
|
||||
return ResponseHelper::custom($response, $responseData, 404);
|
||||
}
|
||||
|
||||
// Convert to array untuk konsistensi
|
||||
if (is_object($respon)) {
|
||||
$respon = (array)$respon;
|
||||
}
|
||||
|
||||
// Check for error
|
||||
if (isset($respon['errno']) && $respon['errno'] != 0) {
|
||||
$responseData['pesan'] = $respon['error'] ?? 'Data pelanggan tidak ditemukan';
|
||||
return ResponseHelper::custom($response, $responseData, 404);
|
||||
}
|
||||
|
||||
// Check for HTTP error status
|
||||
if (isset($respon['status']) && $respon['status'] != 200) {
|
||||
$responseData['pesan'] = $respon['error'] ?? 'Data pelanggan tidak ditemukan';
|
||||
return ResponseHelper::custom($response, $responseData, 404);
|
||||
}
|
||||
|
||||
// Get data - bisa dari 'data' key atau langsung dari response
|
||||
$data = $respon['data'] ?? $respon;
|
||||
|
||||
// Extract data untuk simpan ke database
|
||||
$pelNama = is_array($data) ? ($data['pel_nama'] ?? '') : ($data->pel_nama ?? '');
|
||||
$pelAlamat = is_array($data) ? ($data['pel_alamat'] ?? '') : ($data->pel_alamat ?? '');
|
||||
$dkdKd = is_array($data) ? ($data['dkd_kd'] ?? '') : ($data->dkd_kd ?? '');
|
||||
$rekGol = is_array($data) ? ($data['rek_gol'] ?? '') : ($data->rek_gol ?? '');
|
||||
|
||||
// Simpan ke database
|
||||
$this->slModel->create([
|
||||
'token' => $token,
|
||||
'no_sl' => $no_sl,
|
||||
'nama' => $pelNama,
|
||||
'alamat' => $pelAlamat,
|
||||
'cabang' => $dkdKd,
|
||||
'golongan' => $rekGol,
|
||||
]);
|
||||
|
||||
// Format response sukses sama dengan API lama: status, data langsung di root
|
||||
$responseData = [
|
||||
'status' => 200,
|
||||
'data' => $data
|
||||
];
|
||||
|
||||
return ResponseHelper::custom($response, $responseData, 200);
|
||||
}
|
||||
|
||||
public function hapusSL(Request $request, Response $response): Response
|
||||
{
|
||||
$data = $request->getParsedBody();
|
||||
$token = $data['token'] ?? '';
|
||||
$no_sl = $data['no_sl'] ?? '';
|
||||
|
||||
// Format response awal sama dengan API lama
|
||||
$responseData = [
|
||||
'status' => 404,
|
||||
'pesan' => 'Invalid Operation!'
|
||||
];
|
||||
|
||||
if (empty($token) || empty($no_sl)) {
|
||||
return ResponseHelper::custom($response, $responseData, 404);
|
||||
}
|
||||
|
||||
$cek = $this->slModel->findByTokenAndSL($token, $no_sl);
|
||||
if (!$cek) {
|
||||
return ResponseHelper::custom($response, $responseData, 404);
|
||||
}
|
||||
|
||||
$this->slModel->delete($token, $no_sl);
|
||||
|
||||
// Format response sukses sama dengan API lama
|
||||
$responseData = [
|
||||
'status' => 200,
|
||||
'pesan' => "NO SL \"{$no_sl}\" berhasil dihapus dari di akun anda."
|
||||
];
|
||||
|
||||
return ResponseHelper::custom($response, $responseData, 200);
|
||||
}
|
||||
}
|
||||
370
src/Controllers/SiteController.php
Normal file
370
src/Controllers/SiteController.php
Normal file
@@ -0,0 +1,370 @@
|
||||
<?php
|
||||
|
||||
namespace App\Controllers;
|
||||
|
||||
use App\Config\Database;
|
||||
use App\Helpers\HttpHelper;
|
||||
use App\Helpers\ResponseHelper;
|
||||
use App\Helpers\WhatsAppHelper;
|
||||
use App\Models\UserModel;
|
||||
use Psr\Http\Message\ResponseInterface as Response;
|
||||
use Psr\Http\Message\ServerRequestInterface as Request;
|
||||
|
||||
class SiteController
|
||||
{
|
||||
private $db;
|
||||
private $userModel;
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this->db = Database::getInstance();
|
||||
$this->userModel = new UserModel();
|
||||
}
|
||||
|
||||
/**
|
||||
* POST /site/verify_bri
|
||||
* Verifikasi pembayaran BRI
|
||||
*/
|
||||
public function verifyBri(Request $request, Response $response): Response
|
||||
{
|
||||
try {
|
||||
// Get BRI token (from config or env)
|
||||
$briToken = $this->getBriToken();
|
||||
if (!$briToken) {
|
||||
return ResponseHelper::json($response, [
|
||||
'status' => 'error',
|
||||
'message' => 'BRI token tidak tersedia'
|
||||
], 500);
|
||||
}
|
||||
|
||||
// Get pembayaran yang menunggu verifikasi BRI
|
||||
$konf = $this->db->fetchOne(
|
||||
"SELECT p.*, pt.nama_lengkap
|
||||
FROM pembayaran p
|
||||
LEFT JOIN pengguna_timo pt ON p.token = pt.id_pengguna_timo
|
||||
WHERE p.status_bayar = 'MENUNGGU VERIFIKASI'
|
||||
AND p.nama_bank = 'Bank BRI'
|
||||
AND p.banyak_cek < 2
|
||||
ORDER BY p.tanggal_cek_bayar ASC
|
||||
LIMIT 1"
|
||||
);
|
||||
|
||||
$pesan = "CEK PEMBAYARAN: <br>";
|
||||
|
||||
if ($konf) {
|
||||
$pesan .= "Mengecek:" . $konf->no_trx . ": ";
|
||||
|
||||
// Get mutasi from BRI
|
||||
$dataMutasi = $this->getMutasi($briToken);
|
||||
|
||||
if (isset($dataMutasi->data)) {
|
||||
foreach ($dataMutasi->data as $d) {
|
||||
$update = [
|
||||
'tanggal_cek_bayar' => date('Y-m-d H:i:s'),
|
||||
'banyak_cek' => ($konf->banyak_cek ?? 0) + 1
|
||||
];
|
||||
|
||||
$totalBayar = $konf->jumlah_tagihan + $konf->biaya_admin + $konf->jumlah_unik - $konf->promo;
|
||||
|
||||
if ($totalBayar == ($d->creditAmount ?? 0)) {
|
||||
$update['status_bayar'] = 'DIBAYAR';
|
||||
$update['jumlah_bayar'] = $d->creditAmount ?? $totalBayar;
|
||||
$pesan .= " Sudah Dibayar, ";
|
||||
|
||||
// Approve pembayaran
|
||||
$this->approve($konf->id_pembayaran);
|
||||
} else {
|
||||
$pesan .= " Belum Dibayar, ";
|
||||
}
|
||||
|
||||
$this->db->update('pembayaran', $update, 'id_pembayaran = :id', [
|
||||
'id' => $konf->id_pembayaran
|
||||
]);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
$pesan .= " Tidak ada pembayaran BRI yang bisa di proses";
|
||||
}
|
||||
|
||||
// Return HTML response (sesuai API lama)
|
||||
$response->getBody()->write($pesan);
|
||||
return $response->withHeader('Content-Type', 'text/html');
|
||||
} catch (\Exception $e) {
|
||||
error_log("Error in verifyBri: " . $e->getMessage());
|
||||
$response->getBody()->write("Error: " . $e->getMessage());
|
||||
return $response->withStatus(500)->withHeader('Content-Type', 'text/html');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* POST /site/approve/{id_trx}
|
||||
* Approve transaksi
|
||||
*/
|
||||
public function approve(Request $request, Response $response, array $args): Response
|
||||
{
|
||||
try {
|
||||
$idTrx = $args['id_trx'] ?? 0;
|
||||
|
||||
if (empty($idTrx)) {
|
||||
return ResponseHelper::json($response, [
|
||||
'status' => 'error',
|
||||
'message' => 'ID transaksi tidak valid'
|
||||
], 400);
|
||||
}
|
||||
|
||||
// Get pembayaran
|
||||
$cekPembayaran = $this->db->fetchOne(
|
||||
"SELECT * FROM pembayaran WHERE id_pembayaran = :id AND status_bayar = 'MENUNGGU VERIFIKASI' LIMIT 1",
|
||||
['id' => $idTrx]
|
||||
);
|
||||
|
||||
if (!$cekPembayaran) {
|
||||
return ResponseHelper::json($response, [
|
||||
'status' => 'error',
|
||||
'message' => 'Pembayaran tidak ditemukan atau sudah diproses'
|
||||
], 404);
|
||||
}
|
||||
|
||||
$token = str_replace('#TIMO', '', $cekPembayaran->no_trx);
|
||||
$url = "https://timo.tirtaintan.co.id/payment/$token";
|
||||
|
||||
// Prepare payment data
|
||||
$data = [];
|
||||
$rincian = json_decode($cekPembayaran->raw_data);
|
||||
|
||||
if (is_array($rincian) && count($rincian) > 0) {
|
||||
foreach ($rincian as $r) {
|
||||
$data[] = [
|
||||
'rek_nomor' => $r->rek_nomor ?? $r->rek_no ?? '',
|
||||
'rek_total' => $r->rek_total ?? 0,
|
||||
'serial' => '#TM' . time(),
|
||||
'byr_tgl' => date('YmdHis'),
|
||||
'loket' => 'TIMO',
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
$post = [
|
||||
'token' => $token,
|
||||
'data' => $data
|
||||
];
|
||||
|
||||
// Headers sesuai API lama (Site.php approve)
|
||||
$headers = [
|
||||
'Content-Type: application/json',
|
||||
'Accept-Encoding: gzip, deflate',
|
||||
'Cache-Control: max-age=0',
|
||||
'Connection: keep-alive',
|
||||
'Accept-Language: en-US,en;q=0.8,id;q=0.6'
|
||||
];
|
||||
|
||||
// Send payment to PDAM
|
||||
$paymentResponse = HttpHelper::doCurl($url, 'POST', $post, true, $headers);
|
||||
|
||||
// Update database
|
||||
$this->db->update('pembayaran', [
|
||||
'raw_bayar' => json_encode($paymentResponse)
|
||||
], 'id_pembayaran = :id', ['id' => $idTrx]);
|
||||
|
||||
if ($paymentResponse && isset($paymentResponse->errno) && $paymentResponse->errno == 0) {
|
||||
$totalBayar = $cekPembayaran->jumlah_tagihan + $cekPembayaran->biaya_admin +
|
||||
$cekPembayaran->jumlah_unik - $cekPembayaran->promo;
|
||||
|
||||
$this->db->update('pembayaran', [
|
||||
'status_bayar' => 'DIBAYAR',
|
||||
'tanggal_bayar' => date('Y-m-d H:i:s'),
|
||||
'jumlah_bayar' => (string)$totalBayar
|
||||
], 'id_pembayaran = :id', ['id' => $idTrx]);
|
||||
|
||||
// Kirim notifikasi WhatsApp ke user (sesuai backend lama)
|
||||
$this->sendPaymentNotification($cekPembayaran->token, 'DIBAYAR', [
|
||||
'no_trx' => $cekPembayaran->no_trx,
|
||||
'no_sl' => $cekPembayaran->no_sl,
|
||||
'jumlah_bayar' => $totalBayar,
|
||||
'tanggal_bayar' => date('Y-m-d H:i:s'),
|
||||
'id_pembayaran' => $idTrx
|
||||
]);
|
||||
|
||||
return ResponseHelper::json($response, [
|
||||
'status' => 'success',
|
||||
'message' => 'Pembayaran berhasil diapprove',
|
||||
'data' => [
|
||||
'id_pembayaran' => $idTrx,
|
||||
'status' => 'DIBAYAR'
|
||||
]
|
||||
], 200);
|
||||
} else {
|
||||
return ResponseHelper::json($response, [
|
||||
'status' => 'error',
|
||||
'message' => 'Gagal approve pembayaran ke PDAM'
|
||||
], 500);
|
||||
}
|
||||
} catch (\Exception $e) {
|
||||
error_log("Error in approve: " . $e->getMessage());
|
||||
return ResponseHelper::json($response, [
|
||||
'status' => 'error',
|
||||
'message' => 'Gagal approve: ' . $e->getMessage()
|
||||
], 500);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get BRI token
|
||||
*/
|
||||
private function getBriToken()
|
||||
{
|
||||
$briKey = $_ENV['BRI_KEY'] ?? '';
|
||||
$briSecret = $_ENV['BRI_SECRET'] ?? '';
|
||||
$briUrlToken = $_ENV['BRI_URL_TOKEN'] ?? '';
|
||||
|
||||
if (empty($briKey) || empty($briSecret) || empty($briUrlToken)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$ch = curl_init();
|
||||
curl_setopt_array($ch, [
|
||||
CURLOPT_URL => $briUrlToken,
|
||||
CURLOPT_RETURNTRANSFER => true,
|
||||
CURLOPT_ENCODING => '',
|
||||
CURLOPT_MAXREDIRS => 10,
|
||||
CURLOPT_TIMEOUT => 0, // No timeout (sesuai API lama)
|
||||
CURLOPT_FOLLOWLOCATION => true,
|
||||
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
|
||||
CURLOPT_CUSTOMREQUEST => 'POST',
|
||||
CURLOPT_POSTFIELDS => "client_id={$briKey}&client_secret={$briSecret}",
|
||||
CURLOPT_HTTPHEADER => ['Content-Type: application/x-www-form-urlencoded'],
|
||||
]);
|
||||
|
||||
$response = curl_exec($ch);
|
||||
curl_close($ch);
|
||||
|
||||
if ($response) {
|
||||
$json = json_decode($response);
|
||||
return $json->access_token ?? null;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get mutasi from BRI API
|
||||
*/
|
||||
private function getMutasi($token = '')
|
||||
{
|
||||
if (empty($token)) {
|
||||
return (object)['data' => []];
|
||||
}
|
||||
|
||||
$briRekening = $_ENV['BRI_REKENING'] ?? '';
|
||||
$briSecret = $_ENV['BRI_SECRET'] ?? '';
|
||||
$briUrlMutasi = $_ENV['BRI_URL_MUTASI'] ?? '';
|
||||
|
||||
if (empty($briRekening) || empty($briSecret) || empty($briUrlMutasi)) {
|
||||
return (object)['data' => []];
|
||||
}
|
||||
|
||||
// Body sesuai API lama: string JSON langsung (bukan dari array)
|
||||
// Format: {"accountNumber":"...", "startDate":"...", "endDate":"..."}
|
||||
$body = '{"accountNumber":"' . $briRekening . '", "startDate":"' . date('Y-m-d') . '", "endDate":"' . date('Y-m-d') . '"}';
|
||||
|
||||
$verb = 'POST';
|
||||
$path = '/v2.0/statement';
|
||||
$timestamp = gmdate('Y-m-d\TH:i:s.000\Z');
|
||||
$sig = $this->generateSignature($path, $verb, $token, $timestamp, $body, $briSecret);
|
||||
|
||||
$ch = curl_init();
|
||||
curl_setopt_array($ch, [
|
||||
CURLOPT_URL => $briUrlMutasi,
|
||||
CURLOPT_RETURNTRANSFER => true,
|
||||
CURLOPT_ENCODING => '',
|
||||
CURLOPT_MAXREDIRS => 10,
|
||||
CURLOPT_TIMEOUT => 0, // No timeout (sesuai API lama)
|
||||
CURLOPT_FOLLOWLOCATION => true,
|
||||
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
|
||||
CURLOPT_CUSTOMREQUEST => 'POST',
|
||||
CURLOPT_POSTFIELDS => $body,
|
||||
CURLOPT_HTTPHEADER => [
|
||||
'BRI-Timestamp: ' . $timestamp,
|
||||
'BRI-Signature: ' . $sig,
|
||||
'Content-Type: application/json',
|
||||
'BRI-External-Id: 1234',
|
||||
"Authorization: Bearer $token",
|
||||
],
|
||||
]);
|
||||
|
||||
$response = curl_exec($ch);
|
||||
curl_close($ch);
|
||||
|
||||
return json_decode($response) ?: (object)['data' => []];
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate BRI signature
|
||||
*/
|
||||
private function generateSignature($path, $verb, $token, $timestamp, $body, $secret)
|
||||
{
|
||||
$payload = "path=$path&verb=$verb&token=Bearer $token×tamp=$timestamp&body=$body";
|
||||
$signPayload = hash_hmac('sha256', $payload, $secret, true);
|
||||
return base64_encode($signPayload);
|
||||
}
|
||||
|
||||
/**
|
||||
* Send payment notification to user via WhatsApp
|
||||
* Sesuai dengan backend lama (Site.php sendPaymentNotification)
|
||||
*/
|
||||
private function sendPaymentNotification($token = null, $status = null, $data = null)
|
||||
{
|
||||
if (empty($token) || empty($status) || empty($data)) {
|
||||
error_log('SiteController::sendPaymentNotification - Invalid parameters');
|
||||
return false;
|
||||
}
|
||||
|
||||
$pengguna = $this->userModel->findById($token);
|
||||
if (!$pengguna || empty($pengguna->no_hp)) {
|
||||
error_log('SiteController::sendPaymentNotification - User not found or no phone: ' . $token);
|
||||
return false;
|
||||
}
|
||||
|
||||
$noHp = $pengguna->no_hp;
|
||||
|
||||
switch ($status) {
|
||||
case 'DIBAYAR':
|
||||
$pesan = "*PEMBAYARAN BERHASIL*\n\n"
|
||||
. "Pembayaran tagihan Anda telah berhasil diverifikasi.\n\n"
|
||||
. "*Detail Pembayaran:*\n"
|
||||
. "No TRX: `" . ($data['no_trx'] ?? '') . "`\n"
|
||||
. "No SL: `" . ($data['no_sl'] ?? '') . "`\n"
|
||||
. "Total: Rp " . number_format($data['jumlah_bayar'] ?? 0, 0, ',', '.') . "\n"
|
||||
. "Tanggal: " . date('d/m/Y H:i', strtotime($data['tanggal_bayar'] ?? 'now')) . "\n\n"
|
||||
. "Terima kasih telah menggunakan layanan TIMO!";
|
||||
|
||||
// Tambahkan link cetak invoice jika ID pembayaran tersedia
|
||||
if (isset($data['id_pembayaran']) && $data['id_pembayaran']) {
|
||||
$link_invoice = "https://timo.wipay.id/invoice/download/" . $data['id_pembayaran'];
|
||||
$pesan .= "\n\n📄 *Struk Pembayaran:*\n"
|
||||
. "Silakan klik link berikut untuk mengunduh struk pembayaran:\n"
|
||||
. "$link_invoice";
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
error_log('SiteController::sendPaymentNotification - Invalid status: ' . $status);
|
||||
return false;
|
||||
}
|
||||
|
||||
error_log('SiteController::sendPaymentNotification - Sending to: ' . $noHp . ' for TRX: ' . ($data['no_trx'] ?? ''));
|
||||
$result = WhatsAppHelper::sendWa($noHp, $pesan);
|
||||
|
||||
if ($result) {
|
||||
// Update database untuk menandai notifikasi sudah dikirim
|
||||
if (isset($data['id_pembayaran']) && $data['id_pembayaran']) {
|
||||
$this->db->update('pembayaran', [
|
||||
'respon_wa' => 'NOTIFICATION_SENT_' . date('Y-m-d H:i:s')
|
||||
], 'id_pembayaran = :id', ['id' => $data['id_pembayaran']]);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
116
src/Controllers/TagihanController.php
Normal file
116
src/Controllers/TagihanController.php
Normal file
@@ -0,0 +1,116 @@
|
||||
<?php
|
||||
|
||||
namespace App\Controllers;
|
||||
|
||||
use App\Helpers\HttpHelper;
|
||||
use App\Helpers\ResponseHelper;
|
||||
use Psr\Http\Message\ResponseInterface as Response;
|
||||
use Psr\Http\Message\ServerRequestInterface as Request;
|
||||
|
||||
class TagihanController
|
||||
{
|
||||
public function history(Request $request, Response $response, array $args): Response
|
||||
{
|
||||
$sl = $args['sl'] ?? '';
|
||||
$periode = $args['periode'] ?? '';
|
||||
|
||||
// Format response awal sama dengan API lama
|
||||
$responseData = [
|
||||
'status' => 404,
|
||||
'pesan' => '-'
|
||||
];
|
||||
|
||||
if (empty($sl) || empty($periode)) {
|
||||
$responseData['pesan'] = 'SL dan periode harus diisi';
|
||||
return ResponseHelper::custom($response, $responseData, 404);
|
||||
}
|
||||
|
||||
$respon = HttpHelper::doCurl('https://timo.tirtaintan.co.id/enquiry-his/' . $sl . '/' . $periode);
|
||||
|
||||
// Handle response yang bisa berupa array atau object
|
||||
if (!$respon) {
|
||||
$responseData['pesan'] = 'Data tidak ditemukan';
|
||||
return ResponseHelper::custom($response, $responseData, 404);
|
||||
}
|
||||
|
||||
// Convert to array untuk konsistensi
|
||||
if (is_object($respon)) {
|
||||
$respon = (array)$respon;
|
||||
}
|
||||
|
||||
// Check for error
|
||||
if (isset($respon['errno']) && $respon['errno'] != 0) {
|
||||
$responseData['pesan'] = $respon['error'] ?? 'Data tidak ditemukan';
|
||||
return ResponseHelper::custom($response, $responseData, 404);
|
||||
}
|
||||
|
||||
// Check for HTTP error status
|
||||
if (isset($respon['status']) && $respon['status'] != 200) {
|
||||
$responseData['pesan'] = $respon['error'] ?? 'Data tidak ditemukan';
|
||||
return ResponseHelper::custom($response, $responseData, 404);
|
||||
}
|
||||
|
||||
// Get data - bisa dari 'data' key atau langsung dari response
|
||||
$data = $respon['data'] ?? $respon;
|
||||
|
||||
// Format response sukses sama dengan API lama: status, data langsung di root
|
||||
$responseData = [
|
||||
'status' => 200,
|
||||
'data' => $data
|
||||
];
|
||||
|
||||
return ResponseHelper::custom($response, $responseData, 200);
|
||||
}
|
||||
|
||||
public function tagihan(Request $request, Response $response, array $args): Response
|
||||
{
|
||||
$sl = $args['sl'] ?? '';
|
||||
|
||||
// Format response awal sama dengan API lama
|
||||
$responseData = [
|
||||
'status' => 404,
|
||||
'pesan' => '-'
|
||||
];
|
||||
|
||||
if (empty($sl)) {
|
||||
$responseData['pesan'] = 'SL harus diisi';
|
||||
return ResponseHelper::custom($response, $responseData, 404);
|
||||
}
|
||||
|
||||
$respon = HttpHelper::doCurl('https://timo.tirtaintan.co.id/enquiry/' . $sl);
|
||||
|
||||
// Handle response yang bisa berupa array atau object
|
||||
if (!$respon) {
|
||||
$responseData['pesan'] = 'Data tidak ditemukan';
|
||||
return ResponseHelper::custom($response, $responseData, 404);
|
||||
}
|
||||
|
||||
// Convert to array untuk konsistensi
|
||||
if (is_object($respon)) {
|
||||
$respon = (array)$respon;
|
||||
}
|
||||
|
||||
// Check for error
|
||||
if (isset($respon['errno']) && $respon['errno'] != 0) {
|
||||
$responseData['pesan'] = $respon['error'] ?? 'Data tidak ditemukan';
|
||||
return ResponseHelper::custom($response, $responseData, 404);
|
||||
}
|
||||
|
||||
// Check for HTTP error status
|
||||
if (isset($respon['status']) && $respon['status'] != 200) {
|
||||
$responseData['pesan'] = $respon['error'] ?? 'Data tidak ditemukan';
|
||||
return ResponseHelper::custom($response, $responseData, 404);
|
||||
}
|
||||
|
||||
// Get data - bisa dari 'data' key atau langsung dari response
|
||||
$data = $respon['data'] ?? $respon;
|
||||
|
||||
// Format response sukses sama dengan API lama: status, data langsung di root
|
||||
$responseData = [
|
||||
'status' => 200,
|
||||
'data' => $data
|
||||
];
|
||||
|
||||
return ResponseHelper::custom($response, $responseData, 200);
|
||||
}
|
||||
}
|
||||
684
src/Controllers/UploadController.php
Normal file
684
src/Controllers/UploadController.php
Normal file
@@ -0,0 +1,684 @@
|
||||
<?php
|
||||
|
||||
namespace App\Controllers;
|
||||
|
||||
use App\Config\Database;
|
||||
use App\Helpers\FileHelper;
|
||||
use App\Helpers\GeocodingHelper;
|
||||
use App\Helpers\HttpHelper;
|
||||
use App\Helpers\ResponseHelper;
|
||||
use App\Helpers\TelegramHelper;
|
||||
use App\Models\PembayaranModel;
|
||||
use App\Models\SLModel;
|
||||
use App\Models\UserModel;
|
||||
use Psr\Http\Message\ResponseInterface as Response;
|
||||
use Psr\Http\Message\ServerRequestInterface as Request;
|
||||
|
||||
class UploadController
|
||||
{
|
||||
private $db;
|
||||
private $userModel;
|
||||
private $slModel;
|
||||
private $pembayaranModel;
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this->db = Database::getInstance();
|
||||
$this->userModel = new UserModel();
|
||||
$this->slModel = new SLModel();
|
||||
$this->pembayaranModel = new PembayaranModel();
|
||||
}
|
||||
|
||||
public function uploadCatatMeter(Request $request, Response $response): Response
|
||||
{
|
||||
$data = $request->getParsedBody();
|
||||
|
||||
$token = $data['token'] ?? '';
|
||||
$no_sl = $data['no_sl'] ?? '';
|
||||
$nama_photo = $data['nama_photo'] ?? '';
|
||||
$img = $data['photo'] ?? '';
|
||||
$angka = $data['angka'] ?? '';
|
||||
|
||||
// Format response awal sama dengan API lama
|
||||
$responseData = [
|
||||
'status' => 404,
|
||||
'pesan' => 'Gagal upload catat meter, silahkan coba beberapa saat lagi'
|
||||
];
|
||||
|
||||
// Validasi parameter wajib
|
||||
if (!$token || !$no_sl || !$nama_photo || !$img || !$angka) {
|
||||
$responseData['pesan'] = 'Parameter tidak lengkap. Token, no_sl, nama_photo, photo, dan angka wajib diisi.';
|
||||
return ResponseHelper::custom($response, $responseData, 404);
|
||||
}
|
||||
|
||||
$pengguna = $this->userModel->findById($token);
|
||||
if (!$pengguna) {
|
||||
$responseData['pesan'] = 'Token tidak Valid. Silahkan Login dan Ulangi transaksi. Terima kasih';
|
||||
return ResponseHelper::custom($response, $responseData, 404);
|
||||
}
|
||||
|
||||
// Validasi apakah user sudah pernah melakukan catat meter sebelumnya
|
||||
$previous_catat = $this->db->fetchOne(
|
||||
"SELECT * FROM catat_meter WHERE token = :token LIMIT 1",
|
||||
['token' => $token]
|
||||
);
|
||||
|
||||
if (!$previous_catat) {
|
||||
// User baru - cek apakah no_sl sudah pernah digunakan oleh user lain
|
||||
$existing_sl = $this->db->fetchOne(
|
||||
"SELECT * FROM catat_meter WHERE no_sl = :no_sl LIMIT 1",
|
||||
['no_sl' => $no_sl]
|
||||
);
|
||||
|
||||
if ($existing_sl) {
|
||||
$responseData['pesan'] = "Nomor SL {$no_sl} sudah digunakan oleh user lain. Silahkan gunakan nomor SL yang berbeda atau hubungi admin.";
|
||||
return ResponseHelper::custom($response, $responseData, 404);
|
||||
}
|
||||
} else {
|
||||
// User lama - validasi apakah nomor SL yang dikirim sesuai dengan nomor SL yang pernah digunakan user
|
||||
if ($previous_catat->no_sl !== $no_sl) {
|
||||
$responseData['pesan'] = "Nomor SL tidak sesuai dengan data Anda. Nomor SL Anda: {$previous_catat->no_sl}";
|
||||
return ResponseHelper::custom($response, $responseData, 404);
|
||||
}
|
||||
}
|
||||
|
||||
// Upload file
|
||||
$filename = FileHelper::generateFilename($nama_photo);
|
||||
$uploadPath = __DIR__ . '/../../public/assets/uploads/catat_meter';
|
||||
|
||||
if (!FileHelper::saveBase64Image($img, $uploadPath, $filename)) {
|
||||
$responseData['pesan'] = 'Photo Catat Meter GAGAL upload';
|
||||
return ResponseHelper::custom($response, $responseData, 404);
|
||||
}
|
||||
|
||||
// Simpan ke database
|
||||
$this->db->insert('catat_meter', [
|
||||
'token' => $token,
|
||||
'no_sl' => $no_sl,
|
||||
'photo' => $filename,
|
||||
'angka_meter' => $angka,
|
||||
'tanggal_catat' => date('Y-m-d H:i:s')
|
||||
]);
|
||||
|
||||
// Kirim ke external API upload-catat-meter
|
||||
$this->sendCatatMeterToExternalAPI($token, $no_sl, $pengguna, $angka, $filename);
|
||||
|
||||
$responseData = [
|
||||
'status' => 200,
|
||||
'pesan' => 'Catat meter mandiri berhasil di upload'
|
||||
];
|
||||
|
||||
return ResponseHelper::custom($response, $responseData, 200);
|
||||
}
|
||||
|
||||
/**
|
||||
* Send catat meter to external API
|
||||
*/
|
||||
private function sendCatatMeterToExternalAPI($token, $no_sl, $pengguna, $angka, $filename)
|
||||
{
|
||||
try {
|
||||
// Payload sesuai API lama: photo adalah filename, bukan URL
|
||||
$payload = [
|
||||
'token' => $token,
|
||||
'no_sl' => $no_sl,
|
||||
'nama_pelanggan' => $pengguna->nama_lengkap ?? '',
|
||||
'alamat' => ($pengguna->alamat ?? '') ?: 'Tidak diisi',
|
||||
'angka_meter' => $angka,
|
||||
'photo' => $filename,
|
||||
'uploaded_at' => date('Y-m-d H:i:s')
|
||||
];
|
||||
|
||||
$url = 'https://rasamala.tirtaintan.co.id/timo/upload-catat-meter/' . $no_sl;
|
||||
// Headers sesuai API lama: sendExternalAPIRequest
|
||||
$headers = [
|
||||
'Content-Type: application/json',
|
||||
'Accept: application/json',
|
||||
'User-Agent: TIMO-External-API/1.0'
|
||||
];
|
||||
$response = HttpHelper::doCurl($url, 'POST', $payload, true, $headers, 60, 30);
|
||||
|
||||
if ($response && isset($response->status) && $response->status == 'success') {
|
||||
// Update database
|
||||
$this->db->update('catat_meter', [
|
||||
'external_api_sent' => 1,
|
||||
'external_api_response' => json_encode($response),
|
||||
'external_api_sent_at' => date('Y-m-d H:i:s')
|
||||
], 'token = :token AND no_sl = :no_sl AND angka_meter = :angka', [
|
||||
'token' => $token,
|
||||
'no_sl' => $no_sl,
|
||||
'angka' => $angka
|
||||
]);
|
||||
} else {
|
||||
// Update database untuk menandai gagal
|
||||
$this->db->update('catat_meter', [
|
||||
'external_api_sent' => 0,
|
||||
'external_api_response' => json_encode($response),
|
||||
'external_api_sent_at' => date('Y-m-d H:i:s')
|
||||
], 'token = :token AND no_sl = :no_sl AND angka_meter = :angka', [
|
||||
'token' => $token,
|
||||
'no_sl' => $no_sl,
|
||||
'angka' => $angka
|
||||
]);
|
||||
}
|
||||
} catch (\Exception $e) {
|
||||
error_log('External API Catat Meter - Exception: ' . $e->getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
public function uploadPp(Request $request, Response $response): Response
|
||||
{
|
||||
$data = $request->getParsedBody();
|
||||
|
||||
$token = $data['token'] ?? '';
|
||||
$nama_photo = $data['nama_photo'] ?? '';
|
||||
$img = $data['photo'] ?? '';
|
||||
|
||||
// Format response awal sama dengan API lama
|
||||
$responseData = [
|
||||
'status' => 404,
|
||||
'pesan' => 'Gagal upload catat meter, silahkan coba beberapa saat lagi'
|
||||
];
|
||||
|
||||
$pengguna = $this->userModel->findById($token);
|
||||
if (!$pengguna) {
|
||||
$responseData['pesan'] = 'Token tidak Valid. Silahkan Login dan Ulangi transaksi. Terima kasih';
|
||||
return ResponseHelper::custom($response, $responseData, 404);
|
||||
}
|
||||
|
||||
// Upload file
|
||||
$filename = FileHelper::generateFilename($nama_photo);
|
||||
$uploadPath = __DIR__ . '/../../public/assets/uploads/pengguna';
|
||||
|
||||
if (!FileHelper::saveBase64Image($img, $uploadPath, $filename)) {
|
||||
$responseData['pesan'] = 'Photo profil GAGAL upload';
|
||||
return ResponseHelper::custom($response, $responseData, 404);
|
||||
}
|
||||
|
||||
// Update database
|
||||
$this->userModel->update($token, ['photo' => $filename]);
|
||||
|
||||
// Hapus foto lama jika ada
|
||||
if ($pengguna->photo != '') {
|
||||
$oldFile = $uploadPath . '/' . $pengguna->photo;
|
||||
FileHelper::deleteFile($oldFile);
|
||||
}
|
||||
|
||||
// Get updated user data
|
||||
$updatedUser = $this->userModel->findById($token);
|
||||
|
||||
$responseData = [
|
||||
'status' => 200,
|
||||
'pesan' => 'Photo profil berhasil di upload',
|
||||
'data' => $updatedUser
|
||||
];
|
||||
|
||||
return ResponseHelper::custom($response, $responseData, 200);
|
||||
}
|
||||
|
||||
public function hapusPp(Request $request, Response $response): Response
|
||||
{
|
||||
$data = $request->getParsedBody();
|
||||
$token = $data['token'] ?? '';
|
||||
|
||||
// Format response awal sama dengan API lama
|
||||
$responseData = [
|
||||
'status' => 404,
|
||||
'pesan' => 'Gagal upload catat meter, silahkan coba beberapa saat lagi'
|
||||
];
|
||||
|
||||
$pengguna = $this->userModel->findById($token);
|
||||
if (!$pengguna) {
|
||||
$responseData['pesan'] = 'Token tidak Valid. Silahkan Login dan Ulangi transaksi. Terima kasih';
|
||||
return ResponseHelper::custom($response, $responseData, 404);
|
||||
}
|
||||
|
||||
// Hapus foto jika ada
|
||||
if ($pengguna->photo != '') {
|
||||
$oldFile = __DIR__ . '/../../public/assets/uploads/pengguna/' . $pengguna->photo;
|
||||
FileHelper::deleteFile($oldFile);
|
||||
}
|
||||
|
||||
// Update database
|
||||
$this->userModel->update($token, ['photo' => '']);
|
||||
|
||||
// Get updated user data
|
||||
$updatedUser = $this->userModel->findById($token);
|
||||
|
||||
$responseData = [
|
||||
'status' => 200,
|
||||
'pesan' => 'Photo profil berhasil di dihapus',
|
||||
'data' => $updatedUser
|
||||
];
|
||||
|
||||
return ResponseHelper::custom($response, $responseData, 200);
|
||||
}
|
||||
|
||||
public function uploadGangguan(Request $request, Response $response): Response
|
||||
{
|
||||
$data = $request->getParsedBody();
|
||||
|
||||
$token = $data['token'] ?? '';
|
||||
$gangguan = $data['gangguan'] ?? '';
|
||||
$no_sl = $data['no_sl'] ?? '';
|
||||
$nama_photo = $data['nama_photo'] ?? '';
|
||||
$img = $data['photo'] ?? '';
|
||||
$feedback = $data['feedback'] ?? '';
|
||||
$lokasi = $data['lokasi'] ?? '';
|
||||
|
||||
// Format response awal sama dengan API lama
|
||||
$responseData = [
|
||||
'status' => 404,
|
||||
'pesan' => 'Gagal kirim gangguan, silahkan coba beberapa saat lagi'
|
||||
];
|
||||
|
||||
$pengguna = $this->userModel->findById($token);
|
||||
if (!$pengguna) {
|
||||
$responseData['pesan'] = 'Token tidak Valid. Silahkan Login dan Ulangi transaksi. Terima kasih';
|
||||
return ResponseHelper::custom($response, $responseData, 404);
|
||||
}
|
||||
|
||||
// Get jenis gangguan
|
||||
$dt_gangguan = $this->db->fetchOne(
|
||||
"SELECT * FROM jenis_gangguan WHERE id_jenis_gangguan = :id LIMIT 1",
|
||||
['id' => $gangguan]
|
||||
);
|
||||
|
||||
// Insert gangguan
|
||||
$id_gangguan = $this->db->insert('gangguan', [
|
||||
'token' => $token,
|
||||
'no_sl' => $no_sl,
|
||||
'jenis_gangguan' => $gangguan,
|
||||
'waktu_laporan' => date('Y-m-d H:i:s'),
|
||||
'photo_gangguan' => '',
|
||||
'feedback' => $feedback,
|
||||
'status' => 'DILAPORKAN',
|
||||
'lokasi' => $lokasi,
|
||||
'respon' => 'Laporan anda akan segera kami tindaklanjuti oleh bagian terkait. Terima kasih',
|
||||
]);
|
||||
|
||||
// Upload foto jika harus ada foto
|
||||
if ($dt_gangguan && $dt_gangguan->harus_ada_foto == 'YA' && !empty($img)) {
|
||||
$filename = FileHelper::generateFilename($nama_photo);
|
||||
$uploadPath = __DIR__ . '/../../public/assets/uploads/gangguan';
|
||||
|
||||
if (FileHelper::saveBase64Image($img, $uploadPath, $filename)) {
|
||||
$this->db->update('gangguan', ['photo_gangguan' => $filename], 'id_gangguan = :id', ['id' => $id_gangguan]);
|
||||
} else {
|
||||
$responseData['pesan'] = 'Photo Gangguan GAGAL upload';
|
||||
return ResponseHelper::custom($response, $responseData, 404);
|
||||
}
|
||||
}
|
||||
|
||||
// Kirim ke external API pengaduan
|
||||
$this->sendGangguanToExternalAPI($id_gangguan, $pengguna, $dt_gangguan, $no_sl, $feedback, $lokasi);
|
||||
|
||||
// Kirim notifikasi Telegram ke admin gangguan
|
||||
$pesan = "🚨 *LAPORAN GANGGUAN BARU*\n\n"
|
||||
. "No. SL: " . $no_sl . "\n"
|
||||
. "Jenis: " . ($dt_gangguan->nama_jenis_gangguan ?? '') . "\n"
|
||||
. "Pelapor: " . ($pengguna->nama_lengkap ?? '') . "\n"
|
||||
. "Lokasi: " . ($lokasi ?? '-') . "\n"
|
||||
. "Feedback: " . substr($feedback ?? '', 0, 100) . "\n\n"
|
||||
. "*Harap segera ditindaklanjuti*\n\n"
|
||||
. "Hubungi pelapor untuk informasi lebih lanjut";
|
||||
TelegramHelper::sendToGangguanAdmin($pesan);
|
||||
|
||||
$responseData = [
|
||||
'status' => 200,
|
||||
'pesan' => 'Laporan anda telah kami terima dan sudah diteruskan kebagian terkait'
|
||||
];
|
||||
|
||||
return ResponseHelper::custom($response, $responseData, 200);
|
||||
}
|
||||
|
||||
/**
|
||||
* Send gangguan to external API
|
||||
*/
|
||||
private function sendGangguanToExternalAPI($id_gangguan, $pengguna, $dt_gangguan, $no_sl, $feedback, $lokasi)
|
||||
{
|
||||
try {
|
||||
// Mapping jenis gangguan
|
||||
$jenisMapping = $this->getJenisGangguanMapping($dt_gangguan->nama_jenis_gangguan ?? '');
|
||||
|
||||
// Format nomor telepon sesuai API lama (formatPhoneNumber)
|
||||
$telepon = preg_replace('/[^0-9]/', '', $pengguna->no_hp ?? '');
|
||||
if (substr($telepon, 0, 2) === '08') {
|
||||
$telepon = '62' . substr($telepon, 1); // '08...' -> '628...'
|
||||
} elseif (substr($telepon, 0, 1) === '8') {
|
||||
$telepon = '62' . $telepon; // '8...' -> '628...'
|
||||
} elseif (substr($telepon, 0, 2) === '62') {
|
||||
$telepon = $telepon; // Sudah format 62
|
||||
} elseif (substr($telepon, 0, 1) === '0') {
|
||||
$telepon = '62' . substr($telepon, 1); // '0...' -> '62...'
|
||||
}
|
||||
|
||||
// Prepare payload
|
||||
$payload = [
|
||||
'id' => $id_gangguan,
|
||||
'nama' => $pengguna->nama_lengkap ?? '',
|
||||
'alamat' => $pengguna->alamat ?? 'Tidak diisi',
|
||||
'telepon' => $telepon,
|
||||
'jenis' => $jenisMapping,
|
||||
'judul' => 'Laporan Gangguan - ' . ($dt_gangguan->nama_jenis_gangguan ?? ''),
|
||||
'uraian' => $feedback
|
||||
];
|
||||
|
||||
// Send to external API (sesuai API lama: sendExternalAPIRequest)
|
||||
$url = 'https://timo.tirtaintan.co.id/pengaduan/' . $no_sl;
|
||||
$headers = [
|
||||
'Content-Type: application/json',
|
||||
'Accept: application/json',
|
||||
'User-Agent: TIMO-External-API/1.0'
|
||||
];
|
||||
$response = HttpHelper::doCurl($url, 'POST', $payload, true, $headers, 60, 30);
|
||||
|
||||
// Check response
|
||||
$isSuccess = false;
|
||||
$token = null;
|
||||
|
||||
if ($response) {
|
||||
if (isset($response->errno) && $response->errno == '0') {
|
||||
$isSuccess = true;
|
||||
$token = $response->token ?? null;
|
||||
} elseif (isset($response->success) && $response->success === true) {
|
||||
$isSuccess = true;
|
||||
$token = $response->token ?? null;
|
||||
} elseif (isset($response->status) && $response->status == 'success') {
|
||||
$isSuccess = true;
|
||||
$token = $response->token ?? null;
|
||||
} elseif (isset($response->token) && !empty($response->token)) {
|
||||
$isSuccess = true;
|
||||
$token = $response->token;
|
||||
}
|
||||
}
|
||||
|
||||
// Update database
|
||||
$updateData = [
|
||||
'external_api_sent' => $isSuccess ? 1 : 2,
|
||||
'external_api_token' => $token,
|
||||
'external_api_response' => json_encode($response),
|
||||
'external_api_sent_at' => date('Y-m-d H:i:s'),
|
||||
'external_api_error' => $isSuccess ? null : (json_encode($response) ?? 'Unknown error')
|
||||
];
|
||||
|
||||
if ($isSuccess) {
|
||||
$updateData['status'] = 'DIPROSES';
|
||||
}
|
||||
|
||||
$this->db->update('gangguan', $updateData, 'id_gangguan = :id', ['id' => $id_gangguan]);
|
||||
|
||||
} catch (\Exception $e) {
|
||||
error_log('External API Gangguan - Exception: ' . $e->getMessage());
|
||||
$this->db->update('gangguan', [
|
||||
'external_api_sent' => 2,
|
||||
'external_api_error' => 'Exception: ' . $e->getMessage(),
|
||||
'external_api_sent_at' => date('Y-m-d H:i:s')
|
||||
], 'id_gangguan = :id', ['id' => $id_gangguan]);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get jenis gangguan mapping
|
||||
*/
|
||||
private function getJenisGangguanMapping($namaJenis)
|
||||
{
|
||||
$mapping = [
|
||||
'Tidak Ada Air' => '1',
|
||||
'Pengaliran' => '2',
|
||||
'Tagihan' => '3',
|
||||
'Tarif' => '4',
|
||||
'Pelayanan' => '5',
|
||||
'Kebocoran' => '6',
|
||||
'Meteran' => '7'
|
||||
];
|
||||
|
||||
return $mapping[$namaJenis] ?? '1';
|
||||
}
|
||||
|
||||
public function uploadPasangBaru(Request $request, Response $response): Response
|
||||
{
|
||||
try {
|
||||
$data = $request->getParsedBody();
|
||||
|
||||
$token = $data['token'] ?? '';
|
||||
$no_sl = $data['no_sl'] ?? '';
|
||||
$nama_photo = $data['nama_photo'] ?? '';
|
||||
$img = $data['photo'] ?? '';
|
||||
$nama = $data['nama'] ?? '';
|
||||
$email = $data['email'] ?? '';
|
||||
$telepon = $data['telepon'] ?? '';
|
||||
$nik = $data['nik'] ?? '';
|
||||
$alamat = $data['alamat'] ?? '';
|
||||
|
||||
// Format response awal sama dengan API lama
|
||||
$responseData = [
|
||||
'status' => 404,
|
||||
'pesan' => 'Gagal upload catat meter, silahkan coba beberapa saat lagi'
|
||||
];
|
||||
|
||||
$pengguna = $this->userModel->findById($token);
|
||||
if (!$pengguna) {
|
||||
$responseData['pesan'] = 'Token tidak Valid. Silahkan Login dan Ulangi transaksi. Terima kasih';
|
||||
return ResponseHelper::custom($response, $responseData, 404);
|
||||
}
|
||||
|
||||
// Upload file
|
||||
$filename = FileHelper::generateFilename($nama_photo);
|
||||
$uploadPath = __DIR__ . '/../../public/assets/uploads/pasang_baru';
|
||||
|
||||
if (!FileHelper::saveBase64Image($img, $uploadPath, $filename)) {
|
||||
$responseData['pesan'] = 'Photo Pasang Baru GAGAL upload';
|
||||
return ResponseHelper::custom($response, $responseData, 404);
|
||||
}
|
||||
|
||||
// Insert ke database
|
||||
$id = $this->db->insert('pasang_baru', [
|
||||
'token' => $token,
|
||||
'photo' => $filename,
|
||||
'nama_lengkap' => $nama,
|
||||
'email' => $email,
|
||||
'telepon' => $telepon,
|
||||
'nik' => $nik,
|
||||
'alamat' => $alamat,
|
||||
]);
|
||||
|
||||
// Kirim ke API eksternal (sesuai API lama: pasangBaruCURl)
|
||||
$detail = [
|
||||
'reg_id' => '0',
|
||||
'reg_unit' => '00',
|
||||
'reg_name' => $nama,
|
||||
'reg_address' => $alamat,
|
||||
'reg_phone' => $telepon,
|
||||
'reg_email' => $email,
|
||||
'reg_identity' => $nik,
|
||||
'reg_tgl' => date('Y-m-d H:i:s'),
|
||||
];
|
||||
|
||||
// Payload sesuai API lama: { data: {...} }
|
||||
$post = ['data' => $detail];
|
||||
|
||||
// Headers sesuai API lama
|
||||
$headers = [
|
||||
'Content-Type: application/json',
|
||||
'Accept-Encoding: gzip, deflate',
|
||||
'Cache-Control: max-age=0',
|
||||
'Connection: keep-alive',
|
||||
'Accept-Language: en-US,en;q=0.8,id;q=0.6'
|
||||
];
|
||||
|
||||
// Kirim request dengan timeout 15 detik (sesuai API lama)
|
||||
$respon = HttpHelper::doCurl('https://timo.tirtaintan.co.id/push-registrasi', 'POST', $post, true, $headers, 15, 15);
|
||||
|
||||
// API lama mengembalikan string, perlu decode
|
||||
$responString = is_string($respon) ? $respon : (is_object($respon) && isset($respon->body) ? $respon->body : json_encode($respon));
|
||||
$hasil = json_decode($responString);
|
||||
|
||||
$no_reg = '0';
|
||||
if ($responString && is_object($hasil) && isset($hasil->errno)) {
|
||||
if ($hasil->errno == '0' || $hasil->errno == 0) {
|
||||
$no_reg = isset($hasil->reg_id) ? $hasil->reg_id : '0';
|
||||
}
|
||||
}
|
||||
|
||||
// Update database (sesuai API lama: simpan string response)
|
||||
$this->db->update('pasang_baru', [
|
||||
'no_reg' => $no_reg,
|
||||
'respon' => $responString
|
||||
], 'id_pasang_baru = :id', ['id' => $id]);
|
||||
|
||||
// Insert ke daftar_sl
|
||||
if (!empty($no_reg) && $no_reg != '0') {
|
||||
$this->slModel->create([
|
||||
'token' => $token,
|
||||
'no_sl' => $no_reg,
|
||||
'nama' => $nama,
|
||||
'alamat' => $alamat,
|
||||
'cabang' => '-',
|
||||
'golongan' => '-',
|
||||
]);
|
||||
}
|
||||
|
||||
$responseData = [
|
||||
'status' => 200,
|
||||
'pesan' => 'Data Pasang Baru berhasil di upload'
|
||||
];
|
||||
|
||||
return ResponseHelper::custom($response, $responseData, 200);
|
||||
} catch (\Exception $e) {
|
||||
error_log("Error in uploadPasangBaru: " . $e->getMessage());
|
||||
return ResponseHelper::custom($response, [
|
||||
'status' => 404,
|
||||
'pesan' => 'Gagal upload pasang baru: ' . $e->getMessage()
|
||||
], 404);
|
||||
}
|
||||
}
|
||||
|
||||
public function uploadBuktiTransfer(Request $request, Response $response): Response
|
||||
{
|
||||
$data = $request->getParsedBody();
|
||||
|
||||
$token = $data['token'] ?? '';
|
||||
$no_sl = $data['no_sl'] ?? '';
|
||||
$nama_photo = $data['nama_photo'] ?? '';
|
||||
$img = $data['photo'] ?? '';
|
||||
$pembayaran = $data['pembayaran'] ?? '';
|
||||
|
||||
// Format response awal sama dengan API lama
|
||||
$responseData = [
|
||||
'status' => 404,
|
||||
'pesan' => 'Gagal upload catat meter, silahkan coba beberapa saat lagi'
|
||||
];
|
||||
|
||||
$pengguna = $this->userModel->findById($token);
|
||||
if (!$pengguna) {
|
||||
$responseData['pesan'] = 'Token tidak Valid. Silahkan Login dan Ulangi transaksi. Terima kasih';
|
||||
return ResponseHelper::custom($response, $responseData, 404);
|
||||
}
|
||||
|
||||
// Upload file
|
||||
$filename = FileHelper::generateFilename($nama_photo);
|
||||
$uploadPath = __DIR__ . '/../../public/assets/uploads/bukti_transfer';
|
||||
|
||||
if (!FileHelper::saveBase64Image($img, $uploadPath, $filename)) {
|
||||
$responseData['pesan'] = 'Bukti Transfer GAGAL upload';
|
||||
return ResponseHelper::custom($response, $responseData, 404);
|
||||
}
|
||||
|
||||
// Update pembayaran
|
||||
$pembayaranData = $this->pembayaranModel->findByNoTrx($token, $pembayaran);
|
||||
if ($pembayaranData) {
|
||||
$this->pembayaranModel->update($pembayaranData->id_pembayaran, ['bukti_transfer' => $filename]);
|
||||
}
|
||||
|
||||
$responseData = [
|
||||
'status' => 200,
|
||||
'pesan' => 'Bukti Transfer berhasil di upload'
|
||||
];
|
||||
|
||||
return ResponseHelper::custom($response, $responseData, 200);
|
||||
}
|
||||
|
||||
public function uploadBacaMandiri(Request $request, Response $response): Response
|
||||
{
|
||||
try {
|
||||
$data = $request->getParsedBody();
|
||||
|
||||
$token = $data['token'] ?? '';
|
||||
$wrute_id = $data['wrute_id'] ?? '';
|
||||
$stand_baca = $data['stand_baca'] ?? '';
|
||||
$abnorm_wm = $data['abnorm_wm'] ?? '';
|
||||
$abnorm_env = $data['abnorm_env'] ?? '';
|
||||
$note = $data['note'] ?? '';
|
||||
$lonkor = $data['lonkor'] ?? '';
|
||||
$latkor = $data['latkor'] ?? '';
|
||||
|
||||
// Format response awal sama dengan API lama
|
||||
$responseData = [
|
||||
'status' => 404,
|
||||
'pesan' => 'Gagal upload baca mandiri, silahkan coba beberapa saat lagi'
|
||||
];
|
||||
|
||||
$pengguna = $this->userModel->findById($token);
|
||||
if (!$pengguna) {
|
||||
$responseData['pesan'] = 'Token tidak Valid. Silahkan Login dan Ulangi transaksi. Terima kasih';
|
||||
return ResponseHelper::custom($response, $responseData, 404);
|
||||
}
|
||||
|
||||
// Get valid coordinates with priority: GPS > Geocoding > Default
|
||||
$coordinates = GeocodingHelper::getValidCoordinates($lonkor, $latkor, $pengguna->alamat ?? '');
|
||||
$lonkor = $coordinates['longitude'];
|
||||
$latkor = $coordinates['latitude'];
|
||||
|
||||
// Kirim ke API eksternal (sesuai API lama: sendBacaMandiriRequest)
|
||||
$url = 'https://rasamala.tirtaintan.co.id/timo/upload-cater/' . $wrute_id;
|
||||
$post_data = [
|
||||
'wmmr_id' => $wrute_id,
|
||||
'wmmr_standbaca' => $stand_baca,
|
||||
'wmmr_abnormwm' => $abnorm_wm,
|
||||
'wmmr_abnormenv' => $abnorm_env,
|
||||
'wmmr_note' => $note,
|
||||
'lonkor' => $lonkor,
|
||||
'latkor' => $latkor
|
||||
];
|
||||
|
||||
// API lama menggunakan form-urlencoded, bukan JSON
|
||||
$headers = [
|
||||
'Content-Type: application/x-www-form-urlencoded',
|
||||
'Accept: application/json'
|
||||
];
|
||||
$apiResponse = HttpHelper::doCurl($url, 'POST', $post_data, false, $headers, 30, 10);
|
||||
|
||||
if ($apiResponse) {
|
||||
// Simpan ke database lokal
|
||||
$this->db->insert('baca_mandiri_log', [
|
||||
'token' => $token,
|
||||
'wrute_id' => $wrute_id,
|
||||
'stand_baca' => $stand_baca,
|
||||
'abnorm_wm' => $abnorm_wm,
|
||||
'abnorm_env' => $abnorm_env,
|
||||
'note' => $note,
|
||||
'lonkor' => $lonkor,
|
||||
'latkor' => $latkor,
|
||||
'response' => json_encode($apiResponse),
|
||||
'created_at' => date('Y-m-d H:i:s')
|
||||
]);
|
||||
|
||||
$responseData = [
|
||||
'status' => 200,
|
||||
'pesan' => 'Data baca mandiri berhasil diupload',
|
||||
'data' => $apiResponse
|
||||
];
|
||||
} else {
|
||||
$responseData['pesan'] = 'Gagal mengupload data baca mandiri';
|
||||
}
|
||||
|
||||
return ResponseHelper::custom($response, $responseData, $responseData['status']);
|
||||
} catch (\Exception $e) {
|
||||
error_log("Error in uploadBacaMandiri: " . $e->getMessage());
|
||||
return ResponseHelper::custom($response, [
|
||||
'status' => 404,
|
||||
'pesan' => 'Gagal upload baca mandiri: ' . $e->getMessage()
|
||||
], 404);
|
||||
}
|
||||
}
|
||||
}
|
||||
68
src/Controllers/WipayController.php
Normal file
68
src/Controllers/WipayController.php
Normal file
@@ -0,0 +1,68 @@
|
||||
<?php
|
||||
|
||||
namespace App\Controllers;
|
||||
|
||||
use App\Config\Database;
|
||||
use App\Helpers\KodeHelper;
|
||||
use App\Helpers\ResponseHelper;
|
||||
use App\Models\PembayaranModel;
|
||||
use App\Models\UserModel;
|
||||
use Psr\Http\Message\ResponseInterface as Response;
|
||||
use Psr\Http\Message\ServerRequestInterface as Request;
|
||||
|
||||
class WipayController
|
||||
{
|
||||
private $db;
|
||||
private $userModel;
|
||||
private $pembayaranModel;
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this->db = Database::getInstance();
|
||||
$this->userModel = new UserModel();
|
||||
$this->pembayaranModel = new PembayaranModel();
|
||||
}
|
||||
|
||||
public function cekWipay(Request $request, Response $response): Response
|
||||
{
|
||||
$data = $request->getParsedBody();
|
||||
$token = $data['token'] ?? '';
|
||||
|
||||
// Format response awal sama dengan API lama
|
||||
$responseData = [
|
||||
'status' => 404,
|
||||
'wipay' => 0,
|
||||
'pesan' => 'Gagal kirim gangguan, silahkan coba beberapa saat lagi'
|
||||
];
|
||||
|
||||
if (empty($token)) {
|
||||
$responseData['pesan'] = 'Token harus diisi';
|
||||
return ResponseHelper::custom($response, $responseData, 404);
|
||||
}
|
||||
|
||||
$pengguna = $this->userModel->findById($token);
|
||||
if (!$pengguna) {
|
||||
$responseData['pesan'] = 'Token tidak Valid. Silahkan Login dan Ulangi transaksi. Terima kasih';
|
||||
return ResponseHelper::custom($response, $responseData, 404);
|
||||
}
|
||||
|
||||
// Cek saldo WIPAY - API lama menggunakan pengguna->wipay (bukan wipay_user)
|
||||
$wipay = $this->db->fetchOne(
|
||||
"SELECT * FROM wipay_pengguna WHERE id_wipay = :id_wipay",
|
||||
['id_wipay' => $pengguna->wipay ?? 0]
|
||||
);
|
||||
|
||||
if ($wipay) {
|
||||
// Format response sama dengan API lama: status tetap 404, wipay = 1, data = wipay object
|
||||
$responseData['wipay'] = 1;
|
||||
$responseData['data'] = $wipay;
|
||||
} else {
|
||||
$responseData['pesan'] = 'Tidak ada akun wipay yang terkait';
|
||||
}
|
||||
|
||||
return ResponseHelper::custom($response, $responseData, 404);
|
||||
}
|
||||
|
||||
// Note: buat_kode, cek_kode, reset_kode sudah digunakan untuk reset password
|
||||
// Kode unik pembayaran otomatis di-generate saat request_pembayaran
|
||||
}
|
||||
Reference in New Issue
Block a user