- Introduced the `CaBundle.php` class for managing CA certificates. - Updated `installed.json` and `installed.php` to include the new `composer/ca-bundle` dependency. - Added `platform_check.php` to enforce PHP version requirements. - Created `initialize.php` for initializing the Mollie API client with the API key. - Implemented `webhook_mollie.php` to handle webhook callbacks for software upgrade payments, including transaction status updates and invoice generation. - Integrated DomPDF for generating invoices and sending them via email.
183 lines
7.3 KiB
PHP
183 lines
7.3 KiB
PHP
<?php
|
|
defined(page_security_key) or exit;
|
|
|
|
if (debug && debug_id == $_SESSION['id']){
|
|
ini_set('display_errors', '1');
|
|
ini_set('display_startup_errors', '1');
|
|
error_reporting(E_ALL);
|
|
}
|
|
|
|
$page = 'softwaretool';
|
|
//Check if allowed
|
|
if (isAllowed($page,$_SESSION['profile'],$_SESSION['permission'],'R') === 0){
|
|
header('location: index.php');
|
|
exit;
|
|
}
|
|
$bearertoken = createCommunicationToken($_SESSION['userkey']);
|
|
|
|
//+++++++++++++++++++++++++++++++++++++++++++++++++++++
|
|
// PAYMENT RETURN DETECTION
|
|
//+++++++++++++++++++++++++++++++++++++++++++++++++++++
|
|
$payment_return = isset($_GET['payment_id']) ? $_GET['payment_id'] : null;
|
|
$payment_return_status = isset($_GET['payment_return']) ? $_GET['payment_return'] : null;
|
|
|
|
template_header('Softwaretool', 'softwaretool','view');
|
|
|
|
// Show payment return message if returning from payment
|
|
if ($payment_return && $payment_return_status) {
|
|
$view = '
|
|
<div class="content-title">
|
|
<div style="background: #d4edda; border: 1px solid #c3e6cb; color: #155724; padding: 15px; border-radius: 6px; margin-bottom: 20px;">
|
|
<i class="fa-solid fa-check-circle"></i>
|
|
<strong>Payment Successful!</strong>
|
|
<p style="margin: 10px 0 0 0;">Your payment has been processed. Please reconnect your device to apply the software upgrade.</p>
|
|
<p style="margin: 5px 0 0 0; font-size: 12px; color: #666;">Payment ID: '.htmlspecialchars($payment_return).'</p>
|
|
</div>
|
|
</div>';
|
|
} else {
|
|
$view = '';
|
|
}
|
|
|
|
$view .= '
|
|
<div class="content-title">
|
|
<div class="title">
|
|
<i class="fa-solid fa-box-open"></i>
|
|
<div class="txt">
|
|
<h2>'.$softwaretool_h2 .'</h2>
|
|
<p>'.$softwaretool_p.'</p>
|
|
</div>
|
|
</div>';
|
|
|
|
|
|
if (isset($_GET['equipmentID'])){$returnpage = 'equipment&equipmentID='.$_GET['equipmentID']; } else {$returnpage = 'dashboard';}
|
|
|
|
|
|
//SHOW BACK BUTTON ONLY FOR PORTAL USERS
|
|
if (isAllowed('dashboard',$_SESSION['profile'],$_SESSION['permission'],'R') != 0){
|
|
$view .= '
|
|
<div class="title-actions">
|
|
<a href="index.php?page='.$returnpage.'" class="btn alt mar-right-2"><i class="fa-solid fa-arrow-left"></i></a>
|
|
<button class="btn" onclick="showInstructions()" style="">
|
|
<i class="fa-solid fa-circle-question"></i>
|
|
</button>
|
|
</div>
|
|
';
|
|
}
|
|
|
|
$view .= '
|
|
</div>';
|
|
|
|
$view .= '<div class="content-block">
|
|
|
|
<p id="servicetoken" value="" hidden>'.$bearertoken.'</p>
|
|
|
|
<div id="connectdevice" style="display:flex; gap: 10px; margin-bottom: 20px;">
|
|
<button class="btn" id="connectButton" onClick="connectDeviceForSoftware()" style="min-width: 150px;">
|
|
<i class="fa-solid fa-plug"></i>Connect
|
|
</button>
|
|
<div id="readStatus" style="flex: 1; background-color: #f1f1f1; border-radius: 4px; overflow: hidden;">
|
|
<div id="readBar" style="height: 100%; transition: width 0.3s ease;"></div>
|
|
</div>
|
|
</div>
|
|
|
|
<div id="Device_output" style="display:none;">
|
|
<div id="serialResults" style="font-family: monospace;white-space: pre;padding: 10px;background-color:#f1f1f1;display:none;"></div>
|
|
|
|
<div id="softwareCheckStatus" style="margin: 20px 0; padding: 20px; background-color:#f8f9fa; border-radius: 8px; text-align: center; display:none;">
|
|
<i class="fa-solid fa-spinner fa-spin" style="font-size: 24px; color: #04AA6D; margin-bottom: 10px;"></i>
|
|
<p id="checkingMessage" style="margin: 0; font-size: 16px;">'.$softwaretool_checking.'</p>
|
|
</div>
|
|
|
|
<div id="softwareOptions" style="margin-top: 20px; display:none;">
|
|
<h3 style="margin-bottom: 20px; color: #333;">'.$softwaretool_select_upgrade.'</h3>
|
|
<div id="softwareOptionsGrid" style="display: grid; grid-template-columns: repeat(auto-fill, minmax(300px, 1fr)); gap: 20px;">
|
|
</div>
|
|
</div>
|
|
|
|
<div id="noUpdatesMessage" style="margin: 20px 0; padding: 30px; background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); color: white; border-radius: 12px; text-align: center; display:none;">
|
|
<i class="fa-solid fa-check-circle" style="font-size: 48px; margin-bottom: 15px;"></i>
|
|
<p style="margin: 0; font-size: 18px; font-weight: 500;"><strong>'.$softwaretool_no_updates.'</strong></p>
|
|
<p style="margin: 10px 0 0 0; opacity: 0.9;">Your device is up to date</p>
|
|
</div>
|
|
|
|
<div id="uploadSection" style="margin-top: 10px; display:none;">
|
|
<button class="btn" id="uploadSoftware" style="display:none;"
|
|
emergencyPlug-update verify
|
|
board="emergencyPlug"
|
|
port-filters= "[{usbVendorId: 1027, usbProductId: 24597}];"
|
|
disabled>Install Software
|
|
<span class="upload-progress"></span>
|
|
</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Help Modal -->
|
|
<div id="helpModal" style="display:none; position: fixed; top: 0; left: 0; width: 100%; height: 100%; background: rgba(0,0,0,0.5); z-index: 1000; align-items: center; justify-content: center;">
|
|
<div style="background: white; border-radius: 12px; max-width: 600px; max-height: 80vh; overflow-y: auto; margin: 20px; box-shadow: 0 10px 40px rgba(0,0,0,0.3);">
|
|
<div style="padding: 25px; border-bottom: 1px solid #e0e0e0; display: flex; justify-content: space-between; align-items: center;">
|
|
<h3 style="margin: 0; color: #333;"><i class="fa-solid fa-circle-question"></i> '.$softwaretool_step.'</h3>
|
|
<button onclick="closeInstructions()" style="background: transparent; border: none; font-size: 20px; cursor: pointer; color: #666;"><i class="fa-solid fa-times"></i></button>
|
|
</div>
|
|
<div style="padding: 25px;">
|
|
<ol style="line-height: 1.8; color: #555;">
|
|
<li style="margin-bottom: 15px;">'.$softwaretool_step_1.'</li>
|
|
<li style="margin-bottom: 15px;">'.$softwaretool_step_2.'</li>
|
|
<li style="margin-bottom: 15px;">'.$softwaretool_step_3.'</li>
|
|
<li style="margin-bottom: 15px;">'.$softwaretool_step_4.'</li>
|
|
<li style="margin-bottom: 15px;">'.$softwaretool_step_5.'</li>
|
|
<li style="margin-bottom: 15px;">'.$softwaretool_step_6.'</li>
|
|
<li style="margin-bottom: 15px;">'.$softwaretool_step_7.'</li>
|
|
<li style="margin-bottom: 15px;">'.$softwaretool_step_8.'</li>
|
|
</ol>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
';
|
|
|
|
$view .= '
|
|
</div>
|
|
</div>
|
|
';
|
|
|
|
$view .= '</div>';
|
|
//OUTPUT
|
|
echo $view;
|
|
|
|
|
|
echo '
|
|
<script src="assets/upload.js?'.script_version.'"></script>
|
|
<script src="assets/softwaretool.js?'.script_version.'"></script>
|
|
<script>
|
|
var link = "'.$baseurl.'";
|
|
var DEBUG = '.(debug ? 'true' : 'false').';
|
|
var port, textEncoder, writableStreamClosed, writer, historyIndex = -1;
|
|
const lineHistory = [];
|
|
|
|
// Modal functions - defined globally for inline onclick
|
|
window.showInstructions = function() {
|
|
const modal = document.getElementById("helpModal");
|
|
if (modal) {
|
|
modal.style.display = "flex";
|
|
}
|
|
};
|
|
|
|
window.closeInstructions = function() {
|
|
const modal = document.getElementById("helpModal");
|
|
if (modal) {
|
|
modal.style.display = "none";
|
|
}
|
|
};
|
|
|
|
// Close modal on background click
|
|
document.addEventListener("click", function(e) {
|
|
const modal = document.getElementById("helpModal");
|
|
if (modal && e.target === modal) {
|
|
closeInstructions();
|
|
}
|
|
});
|
|
</script>';
|
|
|
|
template_footer();
|
|
?>
|