Pisah server penyimpanan dan update payment gateway

This commit is contained in:
WD - Dev
2025-11-10 17:44:35 +07:00
parent 6017dfd369
commit 4a7c248fff
3044 changed files with 1586515 additions and 481 deletions
+349
View File
@@ -0,0 +1,349 @@
<?php
require('fpdf/fpdf.php');
class BA_Template extends FPDF
{
protected $content;
protected $isFirstPage = true;
protected $B = 0;
protected $I = 0;
protected $U = 0;
public function __construct($content)
{
parent::__construct();
$this->content = $content;
$this->SetMargins(20, 25, 20);
$this->AddPage();
}
// ===========================================================
// ✅ WriteHTML() — mendukung <b><i><u><br><p> + justify tanpa pecah kalimat
// ===========================================================
function WriteHTML($html)
{
$html = str_replace("\n", ' ', $html);
$html = preg_replace('/\s+/', ' ', $html);
// Pisah berdasarkan tag HTML
$a = preg_split('/<(.*)>/U', $html, -1, PREG_SPLIT_DELIM_CAPTURE);
$buffer = ''; // simpan teks inline sementara
foreach ($a as $i => $e) {
if ($i % 2 == 0) {
// Konten teks biasa
$buffer .= html_entity_decode($e, ENT_QUOTES, 'UTF-8');
} else {
// Tag HTML
if ($e[0] == '/') {
// Tag tutup
$tag = strtoupper(substr($e, 1));
if (in_array($tag, ['B', 'I', 'U'])) {
$this->SetStyle($tag, false);
} elseif ($tag == 'P') {
if (trim($buffer) != '') {
$this->MultiCell(0, 6, trim($buffer), 0, 'J');
$buffer = '';
}
$this->Ln(6);
}
} else {
// Tag buka
$a2 = explode(' ', $e);
$tag = strtoupper(array_shift($a2));
$attr = [];
foreach ($a2 as $v) {
if (preg_match('/([^=]*)=["\']?([^"\']*)/', $v, $a3))
$attr[strtoupper($a3[1])] = $a3[2];
}
if (in_array($tag, ['B', 'I', 'U'])) {
$this->SetStyle($tag, true);
} elseif ($tag == 'BR') {
// Flush teks sebelum ganti baris
if (trim($buffer) != '') {
$this->MultiCell(0, 6, trim($buffer), 0, 'J');
$buffer = '';
}
$this->Ln(6);
} elseif ($tag == 'P') {
// Flush sebelum paragraf baru
if (trim($buffer) != '') {
$this->MultiCell(0, 6, trim($buffer), 0, 'J');
$buffer = '';
}
$this->Ln(6);
}
}
}
}
// flush sisa buffer terakhir
if (trim($buffer) != '') {
$this->MultiCell(0, 6, trim($buffer), 0, 'J');
}
}
// ===========================================================
// SetStyle untuk <b><i><u>
// ===========================================================
function SetStyle($tag, $enable)
{
$this->$tag += ($enable ? 1 : -1);
$style = '';
foreach (['B', 'I', 'U'] as $s) {
if ($this->$s > 0) $style .= $s;
}
$this->SetFont('', $style);
}
// ===========================================================
// HEADER
// ===========================================================
function Header()
{
$header = $this->content['header'];
if (file_exists('controller/surat_pdf/bg-pdf.png')) {
$this->Image('controller/surat_pdf/bg-pdf.png', 0, 0, 210, 297);
}
if ($this->isFirstPage) {
if (!empty($header['imglogo']) && file_exists($header['imglogo'])) {
$this->Image($header['imglogo'], 25, 5, 45);
}
$this->SetY(12);
$this->SetFont('Arial', 'B', 12);
$this->SetTextColor(255, 102, 0);
$this->Cell(0, 7, strtoupper($header['nama_perusahaan']), 0, 1, 'R');
$this->SetFont('Arial', '', 10);
$this->SetTextColor(80, 80, 80);
$this->SetX(130);
$this->Cell(0, 5, $header['kantor'], 0, 1, 'R');
$this->Ln(1);
$iconSize = 4;
$lineHeight = 5.5;
$lineKosong = ' ';
$startX = 160;
$this->SetFont('Arial', '', 9);
$this->SetTextColor(90, 90, 90);
// Telp
$this->SetX(120);
$this->Cell(0, $lineHeight, $header['telp'] . $lineKosong, 0, 0, 'R');
if (file_exists('controller/surat_pdf/icon-phone.png')) {
$this->Image('controller/surat_pdf/icon-phone.png', $startX + 25, $this->GetY() + 0.5, $iconSize);
}
$this->Ln($lineHeight);
// Email
$this->SetX(120);
$this->Cell(0, $lineHeight, $header['email'] . $lineKosong, 0, 0, 'R');
if (file_exists('controller/surat_pdf/icon-mail.png')) {
$this->Image('controller/surat_pdf/icon-mail.png', $startX + 25, $this->GetY() + 0.5, $iconSize);
}
$this->Ln($lineHeight);
// Website
$this->SetX(120);
$this->Cell(0, $lineHeight, $header['website'] . $lineKosong, 0, 0, 'R');
if (file_exists('controller/surat_pdf/icon-web.png')) {
$this->Image('controller/surat_pdf/icon-web.png', $startX + 25, $this->GetY() + 0.5, $iconSize);
}
$this->Ln($lineHeight);
$this->SetDrawColor(128, 128, 128);
$this->SetLineWidth(0.7);
$this->Line(21, 45, 130, 45);
$this->SetDrawColor(255, 102, 0);
$this->Line(132, 45, 189, 45);
$this->Ln(12);
$this->isFirstPage = false;
}
}
// ===========================================================
// FOOTER
// ===========================================================
function Footer()
{
$footer = $this->content['footer'];
$this->SetY(-15);
$this->SetFont('Arial', 'I', 8);
$this->SetTextColor(100, 100, 100);
$this->Cell(0, 10, ($footer['text'] ?? 'Surat') . ' | Halaman ' . $this->PageNo(), 0, 0, 'R');
}
// ===========================================================
// Section Title
// ===========================================================
function SectionTitle($title)
{
$this->Ln(5);
$this->SetFont('Arial', '', 11);
$this->SetTextColor(255, 102, 0);
$this->Cell(0, 8, strtoupper($title), 0, 1, 'L');
$this->SetTextColor(0, 0, 0);
$this->Ln(2);
}
// ===========================================================
// Body Content
// ===========================================================
function BodyContent()
{
$body = $this->content['body'];
if (!empty($body['bodyHead']['text'])) {
$this->SetFont('Arial', '', 11);
$this->WriteHTML($body['bodyHead']['text']);
$this->Ln(5);
}
foreach ($body['bodyData'] as $key => $value) {
$this->SetX(30);
$this->SetFont('Arial', 'B', 11);
$this->Cell(50, 8, $key, 0, 0);
$this->SetFont('Arial', '', 11);
$this->MultiCell(0, 8, ': ' . $value, 0, 'L');
}
foreach ($body['bodyNote'] as $note) {
$this->SectionTitle($note['judul']);
$this->SetFont('Arial', '', 11);
$this->WriteHTML($note['text']);
}
$ttd = $body['bodyTTD'];
$this->Ln(15);
$this->Cell(0, 6, 'Hormat Kami,', 0, 1, 'L');
$this->Ln(20);
if (!empty($ttd['imgttd']) && file_exists($ttd['imgttd'])) {
$this->Image($ttd['imgttd'], 20, $this->GetY() - 20, 35);
}
$this->SetFont('Arial', 'B', 11);
$this->Cell(0, 6, $ttd['nama'], 0, 1, 'L');
$this->SetFont('Arial', '', 10);
$this->Cell(0, 6, $ttd['jabatan'], 0, 1, 'L');
}
}
// ==========================================================
// 🔸 TEMPLATE + FUNCTION
// ==========================================================
function getTemplate($tempalateName)
{
if ($tempalateName == 'ba_pemasangan') {
$template = [
'header' => [
],
'body' => [
'bodyHead' => [
'text' => 'Terimakasih, Anda Telah Berlangganan Layanan Internet di {{1}}<br>Berikut Konfirmasi Detail Data sbb :'
],
'bodyData' => [
],
'bodyNote' => [
[
'judul' => 'CATATAN PENTING',
'text' => 'Untuk biaya pemasangan {{1}},- dibayar setelah pemasangan kepada teknisi. Tidak ada biaya tambahan, jika ada mohon laporkan kepada kami. Pembayaran bulanan dimulai bulan {{2}}. Internet dari tanggal {{3}} adalah gratis.<br>Kami menggunakan sistem pembayaran PRABAYAR, di mana pembayaran bulan {{4}} digunakan untuk layanan bulan tersebut. Wajib berlangganan minimal 6 bulan, jika berhenti sebelum 6 bulan akan dikenakan denda maksimal Rp. 500.000 (disesuaikan). Semua telah dijelaskan oleh teknisi dan diverifikasi oleh tim admin.'
],
[
'judul' => 'CARA PEMBAYARAN',
'text' => 'Pembayaran dapat dilakukan dengan mengklik tombol "Bayar Sekarang" atau melalui tautan yang dikirimkan pada pesan tagihan WhatsApp Official kami mulai bulan {{1}}.'
],
[
'judul' => 'LAYANAN PELANGGAN',
'text' => 'Jika ada kendala, silahkan hubungi Customer Service kami melalui WhatsApp : 081211610233 Dengan menyebutkan Nomor Layanan : {{1}} (tertera di stiker modem).'
],
[
'judul' => 'TENTANG KAMI',
'text' => 'PT. LINTAS JARINGAN NUSANTARA Kantor Layanan Cikembar adalah Penyedia Layanan Internet berbasis Fiber Optic dan Wireless. Kami melayani Corporate, Rumahan, serta Agency Hotspot Unlimited Kuota dengan berbagai pilihan paket menarik dan harga terjangkau. Selain itu kami juga menyediakan jasa setting jaringan LAN, Fiber Optic, Wireless, Web Designer, CCTV, dan lain sebagainya. Kami berkomitmen memberikan pelayanan terbaik, cepat, dan berkualitas kepada seluruh pelanggan kami.'
]
],
'bodyTTD' => [
]
],
'footer' => [
'text' => 'PT. LINTAS JARINGAN NUSANTARA'
]
];
}
elseif ($tempalateName == 'ba_perbaikan') {
$template = [
'header' => [
'imglogo' => 'assets/logo.png',
'nama_perusahaan' => 'PT. LINTAS JARINGAN NUSANTARA',
'kantor' => 'Jl. Raya Sukamaju No. 77, Cimahi',
'telp' => '0813-5678-9876',
'email' => 'support@lnj.co.id',
'website' => 'www.lnj.co.id',
],
'footer' => [
'text' => 'Dokumen Berita Acara Perbaikan',
]
];
}
else {
$template = null;
}
return $template;
}
function mergeTemplateWithData($data)
{
$template = getTemplate($data['template_name']);
$result = $data;
// Header override
$result['header'] = array_merge($template['header'], $data['header']);
// BodyHead: replace {{1}}, {{2}} dst dengan parameter
if (!empty($template['body']['bodyHead']['text'])) {
$text = $template['body']['bodyHead']['text'];
$params = $data['body']['bodyHead']['parameter'] ?? [];
foreach ($params as $i => $val) {
$text = str_replace('{{' . ($i + 1) . '}}', $val, $text);
}
$result['body']['bodyHead']['text'] = $text;
}
// BodyData ambil dari data
$result['body']['bodyData'] = $data['body']['bodyData'];
// BodyNote
foreach ($template['body']['bodyNote'] as $i => $note) {
$text = $note['text'];
$params = $data['body']['bodyNote'][$i]['parameter'] ?? [];
foreach ($params as $p => $v) {
$text = str_replace('{{' . ($p + 1) . '}}', $v, $text);
}
$result['body']['bodyNote'][$i]['text'] = $text;
}
// BodyTTD override data (jika ada gambar)
$result['body']['bodyTTD'] = array_merge($template['body']['bodyTTD'], $data['body']['bodyTTD']);
// Footer
$result['footer'] = array_merge($template['footer'], $data['footer']);
return $result;
}
?>
Binary file not shown.

After

Width:  |  Height:  |  Size: 55 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 57 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 56 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 30 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 40 KiB

+94
View File
@@ -0,0 +1,94 @@
<?php
include '../config/connect.php';
require '../payment/flip/Flip/Transaction.php';
try {
$sql = "
SELECT
a.id,
a.transaction_id,
b.apikey_payment_gateway,
b.url_payment_gateway
FROM
tagihan a
LEFT JOIN
data_server b
ON a.id_data_server = b.id
WHERE
a.status = 'lewat'
AND a.transaction_id != ''
AND a.transaction_status = 'ACTIVE'
AND b.payment_gateway = 'flip'
AND b.status_payment_gateway = 'ACTIVE'
AND YEAR(a.limit_pembayaran) = YEAR(NOW())
AND MONTH(a.limit_pembayaran) = MONTH(NOW())
ORDER BY a.limit_pembayaran ASC
LIMIT 5
";
$stmt = $pdo->prepare($sql);
$stmt->execute();
$data = $stmt->fetchAll(PDO::FETCH_ASSOC);
$results = [];
foreach ($data as $row) {
// Pastikan class FlipPaymentGateway ada di Transaction.php
$flip = new FlipPaymentGateway($row['apikey_payment_gateway'], $row['url_payment_gateway']);
// Ambil status bill
$response = $flip->getBillStatus($row['transaction_id']);
// Cek apakah respon valid dan mengandung link_id
if (!is_array($response) || empty($response['link_id'])) {
$results[] = [
'id' => $row['id'],
'transaction_id' => $row['transaction_id'],
'status' => 'error',
'message' => 'Invalid or missing response from Flip API'
];
continue;
}
// Tampilkan respon dari Flip (opsional)
// print_r($response);
// Edit bill menjadi INACTIVE
// $delete = $flip->editBill(
// $response['link_id'],
// 'INACTIVE',
// $response['title'] ?? '',
// $response['amount'] ?? 0
// );
$results[] = [
'id' => $row['id'],
'transaction_id' => $row['transaction_id'],
'flip_response' => $response
];
// // Jika berhasil, update status di database
// if ($delete) {
// $update = $pdo->prepare("UPDATE tagihan SET transaction_status = :status WHERE id = :id");
// $update->execute([
// ':status' => 'INACTIVE',
// ':id' => $row['id']
// ]);
// }
}
// Tampilkan hasil dari Flip (bukan data dari DB)
header('Content-Type: application/json');
echo json_encode($results, JSON_PRETTY_PRINT);
} catch (PDOException $e) {
echo json_encode([
'status' => 'error',
'message' => $e->getMessage()
]);
} catch (Exception $e) {
echo json_encode([
'status' => 'error',
'message' => $e->getMessage()
]);
}
+99
View File
@@ -0,0 +1,99 @@
<?php
require_once __DIR__ . '/../minio/vendor/autoload.php';
use Aws\S3\S3Client;
use Aws\Exception\AwsException;
/**
* Upload file ke MinIO storage
*/
// function uploadToMinioStorageRaw($imageData, $objectPath) {
// $minio = new S3Client([
// 'version' => 'latest',
// 'region' => 'us-east-1',
// 'endpoint' => 'https://storage.manjapro.net',
// 'use_path_style_endpoint' => true,
// 'credentials' => [
// 'key' => 'admin',
// 'secret' => '@P4ssw0rd',
// ],
// ]);
// $bucket = 'files';
// try {
// $result = $minio->putObject([
// 'Bucket' => $bucket,
// 'Key' => $objectPath,
// 'Body' => $imageData, // <== langsung dari memori, bukan file
// 'ContentType' => 'image/png',
// 'ACL' => 'public-read',
// ]);
// return $result['ObjectURL'];
// } catch (Exception $e) {
// error_log('Upload MinIO gagal: ' . $e->getMessage());
// return false;
// }
// }
function uploadToMinioStorageRaw($fileData, $objectPath)
{
// --- Inisialisasi koneksi MinIO ---
$minio = new S3Client([
'version' => 'latest',
'region' => 'us-east-1',
'endpoint' => 'https://storage.manjapro.net', // URL MinIO kamu
'use_path_style_endpoint' => true,
'credentials' => [
'key' => 'admin', // Ganti sesuai kredensial kamu
'secret' => '@P4ssw0rd', // Ganti sesuai kredensial kamu
],
'suppress_php_deprecation_warning' => true
]);
$bucket = 'files';
// --- Tentukan Content-Type berdasarkan ekstensi file ---
$ext = strtolower(pathinfo($objectPath, PATHINFO_EXTENSION));
switch ($ext) {
case 'jpg':
case 'jpeg':
$contentType = 'image/jpeg';
break;
case 'png':
$contentType = 'image/png';
break;
case 'pdf':
$contentType = 'application/pdf';
break;
case 'txt':
$contentType = 'text/plain';
break;
case 'json':
$contentType = 'application/json';
break;
default:
$contentType = 'application/octet-stream';
}
try {
// --- Upload langsung dari memori ke MinIO ---
$result = $minio->putObject([
'Bucket' => $bucket,
'Key' => $objectPath,
'Body' => $fileData,
'ContentType' => $contentType,
'ACL' => 'public-read', // agar bisa diakses publik
]);
return $result['ObjectURL'];
} catch (AwsException $e) {
error_log('Upload MinIO gagal: ' . $e->getMessage());
return false;
} catch (Exception $e) {
error_log('Kesalahan umum: ' . $e->getMessage());
return false;
}
}
?>
+106 -10
View File
@@ -1,12 +1,85 @@
<?php
header("Content-Type: application/json");
// header("Content-Type: application/json");
// direktori upload
$uploadDir = __DIR__ . "/../img/pesan/";
if (!file_exists($uploadDir)) {
mkdir($uploadDir, 0777, true);
// // direktori upload
// $uploadDir = __DIR__ . "/../img/pesan/";
// if (!file_exists($uploadDir)) {
// mkdir($uploadDir, 0777, true);
// }
// if (!isset($_FILES['file'])) {
// echo json_encode(["status" => "error", "message" => "No file uploaded"]);
// exit;
// }
// $file = $_FILES['file'];
// $ext = strtolower(pathinfo($file['name'], PATHINFO_EXTENSION));
// $allowed = ['jpg', 'jpeg', 'png', 'gif'];
// if (!in_array($ext, $allowed)) {
// echo json_encode(["status" => "error", "message" => "Invalid file type"]);
// exit;
// }
// $newName = uniqid("img_") . "." . $ext;
// $target = $uploadDir . $newName;
// if (move_uploaded_file($file['tmp_name'], $target)) {
// $url = "https://manjapro.net/img/pesan/" . $newName;
// echo json_encode(["status" => "success", "url" => $url]);
// } else {
// echo json_encode(["status" => "error", "message" => "Failed to move file"]);
// }
header("Content-Type: application/json");
require_once __DIR__ . '/../minio/vendor/autoload.php';
use Aws\S3\S3Client;
use Aws\Exception\AwsException;
/**
* Upload file langsung ke MinIO storage
*/
function uploadToMinioStorageRawPesan($fileData, $objectPath, $contentType)
{
$minio = new S3Client([
'version' => 'latest',
'region' => 'us-east-1',
'endpoint' => 'https://storage.manjapro.net',
'use_path_style_endpoint' => true,
'credentials' => [
'key' => 'admin', // Ganti sesuai kredensial kamu
'secret' => '@P4ssw0rd', // Ganti sesuai kredensial kamu
],
'suppress_php_deprecation_warning' => true
]);
$bucket = 'files';
try {
$result = $minio->putObject([
'Bucket' => $bucket,
'Key' => $objectPath,
'Body' => $fileData,
'ContentType' => $contentType,
'ACL' => 'public-read',
]);
return $result['ObjectURL'];
} catch (AwsException $e) {
error_log('Upload MinIO gagal: ' . $e->getMessage());
return false;
} catch (Exception $e) {
error_log('Kesalahan umum: ' . $e->getMessage());
return false;
}
}
// ------------------------------------------------------------
// PROSES UPLOAD
// ------------------------------------------------------------
if (!isset($_FILES['file'])) {
echo json_encode(["status" => "error", "message" => "No file uploaded"]);
exit;
@@ -21,13 +94,36 @@ if (!in_array($ext, $allowed)) {
exit;
}
$newName = uniqid("img_") . "." . $ext;
$target = $uploadDir . $newName;
// Tentukan Content-Type
switch ($ext) {
case 'jpg':
case 'jpeg':
$contentType = 'image/jpeg';
break;
case 'png':
$contentType = 'image/png';
break;
case 'gif':
$contentType = 'image/gif';
break;
default:
$contentType = 'application/octet-stream';
}
if (move_uploaded_file($file['tmp_name'], $target)) {
$url = "https://manjapro.net/img/pesan/" . $newName;
// Buat nama baru unik
$newName = uniqid("img_") . "." . $ext;
$objectPath = "pesan/" . $newName;
// Baca isi file dari temporary upload
$fileData = file_get_contents($file['tmp_name']);
// Upload langsung ke MinIO
$url = uploadToMinioStorageRawPesan($fileData, $objectPath, $contentType);
// Hasil respon
if ($url) {
echo json_encode(["status" => "success", "url" => $url]);
} else {
echo json_encode(["status" => "error", "message" => "Failed to move file"]);
echo json_encode(["status" => "error", "message" => "Failed to upload to MinIO"]);
}
?>