As you might know, whmcs has a problem with stripe: when the payment is not immediately confirmed by stripe (but requires to clic "capture" on stripe dashboard), whmcs does not record the order and the customer details and does not even send any notification to whmcs admin or to the customer.
We solved with a hook that sends us an email with the order details, so that:
- we know that there was a order attempt
- we know that there might be a payment in stripe that requires manual "capture"
- if necessary, we have all the client and order details in order to recreate the both client account and order.
Here is the hook.
<?php
if (!defined("WHMCS")) {
die("This file cannot be accessed directly");
}
/**
* Save all checkout data to a TXT file
* AND email it to admin
* Runs BEFORE order/invoice creation, and before redirect to Stripe.
*/
add_hook('ShoppingCartValidateCheckout', 1, function ($vars) {
// --- 1. Clone and sanitise incoming data -------------------------------
$data = $vars;
// Mask any possible card data (good practice even if Stripe never posts it)
$sensitiveFields = [
'ccnumber',
'cccvv',
'ccexpirymonth',
'ccexpiryyear',
'password',
'password2',
];
foreach ($sensitiveFields as $field) {
if (!empty($data[$field])) {
$data[$field] = '***masked***';
}
}
// --- 2. Attach cart contents from session (products, domains, etc.) ---
$cart = isset($_SESSION['cart']) ? $_SESSION['cart'] : [];
$payload = [
'timestamp' => date('Y-m-d H:i:s'),
'ip' => $_SERVER['REMOTE_ADDR'] ?? null,
'user_agent' => $_SERVER['HTTP_USER_AGENT'] ?? null,
'checkoutFields' => $data,
'cart' => $cart,
];
// --- 3. Build a text representation (for file & email) ----------------
$entry = "==============================\n";
$entry .= "Checkout submitted: " . $payload['timestamp'] . "\n";
$entry .= "IP: " . ($payload['ip'] ?? 'N/A') . "\n";
$entry .= "User-Agent: " . ($payload['user_agent'] ?? 'N/A') . "\n\n";
$entry .= "DATA:\n" . print_r($payload, true) . "\n\n";
// --- 4. Save to TXT file ----------------------------------------------
$logDir = __DIR__ . '/../../logs';
$logFile = $logDir . '/pre_stripe_checkout.txt';
if (!is_dir($logDir)) {
@mkdir($logDir, 0700, true);
}
@file_put_contents($logFile, $entry, FILE_APPEND);
// --- 5. Send email to admin -------------------------------------------
// This uses WHMCS' built-in admin notification helper.
// The "system" type means it goes to the system email / admin notifications.
if (function_exists('sendAdminNotification')) {
$subject = 'Pre-Stripe Checkout Captured';
// Use <pre> so the print_r formatting is readable in HTML email
$message = nl2br(htmlspecialchars($entry));
sendAdminNotification('system', $subject, '<pre>' . $message . '</pre>');
}
// IMPORTANT: Do NOT return an error. Just let checkout continue.
return;
});
I suggest to implement it.
It would be great if it would offer some sort of customization in the admin area.