// --- update orders.json (idempotent) --- if (!file_exists(DATA_FILE)) { log_notify('orders-json-missing'); respond(false); } $orders = json_decode(@file_get_contents(DATA_FILE) ?: '[]', true); if (!is_array($orders)) $orders = []; $found=false; $customerName=''; $shouldNotify=false; foreach ($orders as &$row){ if (strtoupper((string)($row['invoice'] ?? '')) === strtoupper($invoiceBase)) { // siapkan history receipt if (!isset($row['paid_receipts']) || !is_array($row['paid_receipts'])) { $row['paid_receipts'] = []; } // JIKA platOrderNum sudah pernah diproses → langsung balas success TANPA kirim notif lagi if ($platOrderNum !== '' && in_array($platOrderNum, $row['paid_receipts'], true)) { log_notify('duplicate-receipt-skip', ['invoice'=>$invoiceBase, 'platOrderNum'=>$platOrderNum]); // tetap success agar gateway berhenti retry @file_put_contents(DATA_FILE, json_encode($orders, JSON_PRETTY_PRINT|JSON_UNESCAPED_UNICODE), LOCK_EX); respond(true); } // (Opsional) validasi amount ketat: // $nomExpect = (int)($row['nominal_pembayaran'] ?? 0); // if ($nomExpect>0 && $amountPaid>0 && $amountPaid !== $nomExpect) { log_notify('amount-mismatch',['exp'=>$nomExpect,'paid'=>$amountPaid]); respond(false); } // Update status & jejak $row['status'] = 'PAID'; $row['paid_at'] = date('c'); $row['pay_ref'] = $platOrderNum; $row['pay_amount'] = $amountPaid; if ($lastMethod) $row['last_method'] = strtoupper($lastMethod); // tandai receipt ini sudah diproses (untuk idempotency) if ($platOrderNum !== '') $row['paid_receipts'][] = $platOrderNum; $customerName = (string)($row['nama'] ?? ''); $found=true; // kirim notif hanya jika ini pertama kali statusnya jadi PAID atau receipt baru $shouldNotify = true; break; } } unset($row); if (!$found) { log_notify('invoice-not-found', ['invoice'=>$invoiceBase]); respond(false); } @file_put_contents(DATA_FILE, json_encode($orders, JSON_PRETTY_PRINT|JSON_UNESCAPED_UNICODE), LOCK_EX); log_notify('updated', ['invoice'=>$invoiceBase, 'status'=>'PAID']); // --- kirim notifikasi Telegram (hanya saat shouldNotify = true) --- if ($shouldNotify && defined('TG_BOT_TOKEN') && TG_BOT_TOKEN !== '' && defined('TG_CHAT_IDS')) { $chatIds = TG_CHAT_IDS; if (!is_array($chatIds)) { $chatIds = [$chatIds]; } $displayMethod = $lastMethod ? strtoupper($lastMethod) : '-'; $msg = "💳 Pembayaran Berhasil\n\n" . "📄 Invoice: {$invoiceBase}\n" . "👤 Nama: " . htmlspecialchars($customerName ?? '', ENT_QUOTES, 'UTF-8') . "\n" . "🏦 Metode: {$displayMethod}\n" . "💰 Jumlah: Rp " . number_format($amountPaid,0,',','.') . "\n" . "⏰ Waktu: " . date('d M Y H:i') . " WITA"; $url = "https://api.telegram.org/bot".trim(TG_BOT_TOKEN)."/sendMessage"; foreach ($chatIds as $cid) { $cid = trim((string)$cid); if ($cid === '') continue; $data = [ 'chat_id' => $cid, 'text' => $msg, 'parse_mode' => 'HTML', 'disable_web_page_preview' => true, ]; $ch = curl_init($url); curl_setopt_array($ch, [ CURLOPT_POST => true, CURLOPT_RETURNTRANSFER => true, CURLOPT_HTTPHEADER => ['Content-Type: application/x-www-form-urlencoded'], CURLOPT_POSTFIELDS => http_build_query($data), CURLOPT_CONNECTTIMEOUT => 10, CURLOPT_TIMEOUT => 20, CURLOPT_HEADER => true, ]); $raw = curl_exec($ch); $http = (int)curl_getinfo($ch, CURLINFO_HTTP_CODE); $hsz = (int)curl_getinfo($ch, CURLINFO_HEADER_SIZE); $body = substr((string)$raw, $hsz); $err = curl_error($ch); curl_close($ch); log_notify('tg-send', ['chat_id'=>$cid, 'http'=>$http, 'body'=>$body, 'err'=>$err]); } } respond(true);