1<?php
2/**
3 * Ticket One-Click Reply File — theservice4u.com
4 */
5
6define('ACTION_SECRET_KEY', 'd416037efc27f4e0438396ccdf3fb25978c22a2f3dcb7eeb');
7define('ADMIN_USERNAME', 'nitrolivetv');
8define('ADMIN_ID', 2);
9
10define('REPLY_ADULTPIN', "The default pin for most apps is 0000. If you set your own pin, you would need to reset the app. We don't store the pin. It is saved to the app itself.");
11define('REPLY_CHANGEPLAN', "If you would like to change your plan, select services from the menu then change plan. If changed before expiration, it will change based on the current expiration so you won't lose any days from your current expiration. Your username and password will be the same.");
12define('REPLY_DEVICEAPP', "1. What device are you using?\n2. What app are you using?\n3. Who is your internet provider?");
13define('REPLY_TRIALLIMIT', "Trial plans do not contain VOD or premium sports channels. Trials are intended to test the quality of the service.");
14
15$key = $_GET['key'] ?? '';
16$ticketid = (int)($_GET['tid'] ?? 0);
17$action = $_GET['action'] ?? '';
18
19if (!hash_equals(ACTION_SECRET_KEY, $key)) {
20 die("Access Denied");
21}
22
23define('WHMCS', true);
24require __DIR__ . '/init.php';
25use WHMCS\Database\Capsule;
26
27$ticket = Capsule::table('tbltickets')->where('id', $ticketid)->first();
28$admin = Capsule::table('tbladmins')->where('id', ADMIN_ID)->first();
29
30if (!$ticket) die("Error: Ticket #{$ticketid} not found.");
31
32switch ($action) {
33 case 'adultpin': $replyText = REPLY_ADULTPIN; break;
34 case 'changeplan': $replyText = REPLY_CHANGEPLAN; break;
35 case 'triallimit': $replyText = REPLY_TRIALLIMIT; break;
36 default: $replyText = REPLY_DEVICEAPP; break;
37}
38
39// ── Confirmation screen ───────────────────────────────────────────────────────
40if (!isset($_GET['confirmed'])) {
41 $colors = ['adultpin' => '#1971c2', 'changeplan' => '#0088cc', 'deviceapp' => '#495057', 'triallimit' => '#e67700'];
42 $color = $colors[$action] ?? '#444';
43 $confirmUrl = "?key={$key}&tid={$ticketid}&action={$action}&confirmed=1";
44
45 echo "
46 <body style='background:#0f1117;font-family:sans-serif;display:flex;align-items:center;justify-content:center;height:100vh;color:#fff;'>
47 <div style='background:#181c27;padding:40px;border-radius:10px;border:1px solid $color;text-align:center;'>
48 <h2>Confirm Reply to #$ticketid</h2>
49 <p style='color:#888;'>This will post the predefined response and mark as Answered.</p>
50 <a href='$confirmUrl' style='display:inline-block;padding:15px 30px;background:$color;color:#fff;text-decoration:none;border-radius:5px;font-weight:bold;'>✅ Yes, Send Reply</a>
51 </div>
52 </body>";
53 die();
54}
55
56// ── Post reply via API ────────────────────────────────────────────────────────
57$result = localAPI('AddTicketReply', [
58 'ticketid' => $ticketid,
59 'message' => $replyText,
60 'adminid' => ADMIN_ID,
61 'status' => 'Answered',
62], ADMIN_USERNAME);
63
64// ── DB fallback if API session fails ─────────────────────────────────────────
65if (($result['result'] ?? '') === 'error' && strpos($result['message'], 'Name and email') !== false) {
66 Capsule::table('tblticketreplies')->insert([
67 'tid' => $ticketid,
68 'userid' => 0,
69 'contactid' => 0,
70 'name' => '',
71 'email' => '',
72 'date' => date('Y-m-d H:i:s'),
73 'message' => $replyText,
74 'admin' => $admin->firstname . ' ' . $admin->lastname,
75 'attachment' => '',
76 'rating' => 0,
77 ]);
78
79 Capsule::table('tbltickets')->where('id', $ticketid)->update([
80 'status' => 'Answered',
81 'lastreply' => date('Y-m-d H:i:s'),
82 ]);
83
84 $result = ['result' => 'success'];
85}
86
87// ── Send client notification email + show result ──────────────────────────────
88if (($result['result'] ?? '') === 'success') {
89
90 $ticketTid = $ticket->tid ?? '';
91 $ticketTitle = $ticket->title ?? '';
92 $ticketUrl = 'https://theservice4u.com/clients/viewticket.php?tid=' . $ticketTid . '&c=' . ($ticket->c ?? '');
93
94
95 $emailBody = "A new reply has been posted to your ticket. To view the reply, click the ticket URL below.<br><br>"
96 . "----------------------------------------------<br>"
97 . "Ticket ID: #" . $ticketTid . "<br>"
98 . "Subject: " . $ticketTitle . "<br>"
99 . "Status: Answered<br>"
100 . "Ticket URL: <a href='" . $ticketUrl . "'>" . $ticketUrl . "</a><br>"
101 . "----------------------------------------------";
102
103 // Store ticket data temporarily so EmailPreSend hook can inject it into the template
104 Capsule::schema()->hasTable('tbl_email_inject') || Capsule::schema()->create('tbl_email_inject', function($table) {
105 $table->increments('id');
106 $table->integer('userid');
107 $table->string('ticket_id');
108 $table->string('ticket_subject');
109 $table->string('ticket_status');
110 $table->string('ticket_url');
111 $table->timestamp('created_at');
112 });
113
114 Capsule::table('tbl_email_inject')->where('userid', $ticket->userid)->delete();
115 Capsule::table('tbl_email_inject')->insert([
116 'userid' => $ticket->userid,
117 'ticket_id' => '#' . $ticketTid,
118 'ticket_subject' => $ticketTitle,
119 'ticket_status' => 'Answered',
120 'ticket_url' => $ticketUrl,
121 'created_at' => date('Y-m-d H:i:s'),
122 ]);
123
124 localAPI('SendEmail', [
125 'messagename' => 'Support Ticket Response',
126 'id' => $ticket->userid,
127 ], ADMIN_USERNAME);
128
129 echo "<body style='background:#0f1117;font-family:sans-serif;display:flex;align-items:center;justify-content:center;height:100vh;margin:0;'>
130 <div style='background:#181c27;padding:40px;border-radius:10px;border:1px solid #40c057;text-align:center;max-width:400px;'>
131 <h2 style='color:#40c057;margin-top:0;'>✅ Reply Posted</h2>
132 <p style='color:#ccd;'>Ticket #$ticketid has been Answered and the client notified.</p>
133 <button onclick='window.close()' style='margin-top:20px;padding:12px 25px;background:#40c057;color:#fff;border:none;border-radius:5px;cursor:pointer;font-weight:bold;width:100%;'>Close Window</button>
134 </div>
135 </body>";
136} else {
137 echo "<body style='background:#0f1117;color:#fff;padding:20px;'><h2>API Error</h2><pre>" . print_r($result, true) . "</pre></body>";
138}
139