software_update_user, "clientsecret" => software_update_pw), JSON_UNESCAPED_UNICODE); $responses = ioAPIv2('/v2/authorization', $data,''); if (!empty($responses)){$responses = json_decode($responses,true);}else{$responses = '400';} $clientsecret = $responses['token']; //+++++++++++++++++++++++++++++++++++++++++++++++++++++ // BASEURL is required for invoice template //+++++++++++++++++++++++++++++++++++++++++++++++++++++ $base_url = 'https://'.$_SERVER['SERVER_NAME'].'/'; define('base_url', $base_url); //+++++++++++++++++++++++++++++++++++++++++++++++++++++ // Initialize DomPDF for invoice generation //+++++++++++++++++++++++++++++++++++++++++++++++++++++ use Dompdf\Dompdf; use Dompdf\Options; $options = new Options(); $options->set('isRemoteEnabled', true); $dompdf = new Dompdf($options); //+++++++++++++++++++++++++++++++++++++++++++++++++++++ // Language mapping for invoices //+++++++++++++++++++++++++++++++++++++++++++++++++++++ $available_languages = [ 'NL' => 'NL', 'BE' => 'NL', 'US' => 'US', 'GB' => 'US', 'DE' => 'DE', 'FR' => 'FR', 'ES' => 'ES' ]; try { //+++++++++++++++++++++++++++++++++++++++++++++++++++++ // Initialize the Mollie API library //+++++++++++++++++++++++++++++++++++++++++++++++++++++ require "initialize.php"; // Mollie initialization //+++++++++++++++++++++++++++++++++++++++++++++++++++++ // DEBUG MODE - Handle fake payment IDs //+++++++++++++++++++++++++++++++++++++++++++++++++++++ if (debug && isset($_POST["id"]) && strpos($_POST["id"], 'DEBUG_') === 0) { // In DEBUG mode, simulate webhook callback $payment_id = $_POST["id"]; $orderId = $payment_id; // Simulate payment status as paid $payment_status = 1; // Paid } else { //+++++++++++++++++++++++++++++++++++++++++++++++++++++ // PRODUCTION MODE - Retrieve the payment's current state from Mollie //+++++++++++++++++++++++++++++++++++++++++++++++++++++ $payment = $mollie->payments->get($_POST["id"]); $orderId = $payment->metadata->order_id; $payment_status = null; if ($payment->isPaid() && !$payment->hasRefunds() && !$payment->hasChargebacks()) { $payment_status = 1; // Paid } elseif ($payment->isOpen() || $payment->isPending()) { $payment_status = 101; // Open/Pending } elseif ($payment->isFailed()) { $payment_status = 102; // Failed } elseif ($payment->isExpired()) { $payment_status = 103; // Expired } elseif ($payment->isCanceled()) { $payment_status = 999; // Canceled } } //+++++++++++++++++++++++++++++++++++++++++++++++++++++ // Update transaction status via API //+++++++++++++++++++++++++++++++++++++++++++++++++++++ if ($payment_status !== null) { $payload = json_encode(array("txn_id" => $orderId, "payment_status" => $payment_status), JSON_UNESCAPED_UNICODE); $transaction = ioAPIv2('/v2/transactions/',$payload,$clientsecret); $transaction = json_decode($transaction,true); //+++++++++++++++++++++++++++++++++++++++++++++++++++++ // Only create license and invoice if payment is PAID //+++++++++++++++++++++++++++++++++++++++++++++++++++++ if ($payment_status == 1 && $transaction !== null && !empty($transaction)) { if(count($transaction) > 0) { //+++++++++++++++++++++++++++++++++++++++++++++++++++++ // CREATE LICENSE for software upgrade //+++++++++++++++++++++++++++++++++++++++++++++++++++++ $pdo = dbConnect($dbname); // Fetch transaction items to find software upgrade $sql = 'SELECT * FROM transactions_items WHERE txn_id = ?'; $stmt = $pdo->prepare($sql); $stmt->execute([$orderId]); $items = $stmt->fetchAll(PDO::FETCH_ASSOC); foreach ($items as $item) { if (!empty($item['item_options'])) { $options = json_decode($item['item_options'], true); // Check if this is a software upgrade (has serial_number and equipment_id) if (isset($options['serial_number']) && isset($options['equipment_id'])) { // Check if license already exists for this transaction $sql = 'SELECT rowID FROM products_software_licenses WHERE transaction_id = ?'; $stmt = $pdo->prepare($sql); $stmt->execute([$orderId]); $existing_license = $stmt->fetch(PDO::FETCH_ASSOC); if (!$existing_license) { // Generate unique license key $license_key = generateUniqueLicenseKey(); // Create license $sql = 'INSERT INTO products_software_licenses (license_key, equipment_id, license_type, status, start_at, expires_at, transaction_id, created, createdby) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)'; $stmt = $pdo->prepare($sql); $stmt->execute([ $license_key, $options['equipment_id'], 'upgrade', 1, // active date('Y-m-d H:i:s'), '2099-12-31 23:59:59', // effectively permanent $orderId, date('Y-m-d H:i:s'), 'webhook' // created by webhook ]); // Update equipment.sw_version_license $sql = 'UPDATE equipment SET sw_version_license = ? WHERE rowID = ?'; $stmt = $pdo->prepare($sql); $stmt->execute([$license_key, $options['equipment_id']]); } } } } //+++++++++++++++++++++++++++++++++++++++++++++++++++++ // Generate INVOICE via API //+++++++++++++++++++++++++++++++++++++++++++++++++++++ $payload = json_encode(array("txn_id" => $transaction['transaction_id']), JSON_UNESCAPED_UNICODE); $invoice = ioAPIv2('/v2/invoice/',$payload,$clientsecret); $invoice = json_decode($invoice,true); if ($invoice !== null && !empty($invoice)) { // Fetch full invoice data with customer details $invoice_cust = ioAPIv2('/v2/invoice/list=invoice&id='.$invoice['invoice_id'],'',$clientsecret); $invoice_cust = json_decode($invoice_cust,true); // Determine invoice language if (!empty($invoice_cust['customer']['language'])) { $invoice_language = strtoupper($invoice_cust['customer']['language']); } elseif (!empty($invoice_cust['customer']['country']) && isset($available_languages[strtoupper($invoice_cust['customer']['country'])])) { $invoice_language = $available_languages[strtoupper($invoice_cust['customer']['country'])]; } else { $invoice_language = 'US'; // Default fallback } // Generate invoice HTML (using custom template for software upgrades) list($data,$customer_email,$order_id) = generateSoftwareInvoice($invoice_cust,$orderId,$invoice_language); //+++++++++++++++++++++++++++++++++++++++++++++++++++++ //CREATE PDF using DomPDF //+++++++++++++++++++++++++++++++++++++++++++++++++++++ $dompdf->loadHtml($data); $dompdf->setPaper('A4', 'portrait'); $dompdf->render(); $subject = 'Software Upgrade - Invoice: '.$order_id; $attachment = $dompdf->output(); //+++++++++++++++++++++++++++++++++++++++++++++++++++++ //Send email via PHPMailer //+++++++++++++++++++++++++++++++++++++++++++++++++++++ send_mail($customer_email, $subject, $data, $attachment, $subject); // Send to bookkeeping if configured if(invoice_bookkeeping){ send_mail(email_bookkeeping, $subject, $data, $attachment, $subject); } } } } } // Return 200 OK to Mollie http_response_code(200); echo "OK"; } catch (\Mollie\Api\Exceptions\ApiException $e) { error_log("Webhook API call failed: " . htmlspecialchars($e->getMessage())); http_response_code(500); } catch (Exception $e) { error_log("Webhook error: " . htmlspecialchars($e->getMessage())); http_response_code(500); } ?>