645 lines
26 KiB
PHP
645 lines
26 KiB
PHP
<?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;
|
|
}
|
|
}
|
|
}
|