htmlspecialchars((string)$v, ENT_QUOTES, 'UTF-8'); // ───────────────────────────────────────────────────────────── // Config: where CP gets trial notifications // ───────────────────────────────────────────────────────────── const CP_EMAIL = 'askklinflow@gmail.com'; // Control Panel / team inbox const FROM_EMAIL = 'no-reply@klinflow.com'; // domain email (SPF/DKIM) // ───────────────────────────────────────────────────────────── // Helper functions // ───────────────────────────────────────────────────────────── function pdo(): PDO { return DB::pdo(); } function normalise_slug(string $slug): string { $slug = strtolower(trim($slug)); $slug = preg_replace('/[^a-z0-9-]+/', '-', $slug) ?? ''; $slug = preg_replace('/-+/', '-', $slug) ?? ''; return trim($slug, '-'); } function reserved_slugs(): array { return [ 'www','web','app','apps','api','cp','admin','root','system', 'tenant','login','signup','pricing','public','static','assets' ]; } function slug_taken(string $slug): ?string { $pdo = pdo(); // Existing organizations $stmt = $pdo->prepare('SELECT id FROM cp_organizations WHERE slug = :slug LIMIT 1'); $stmt->execute(['slug' => $slug]); if ($stmt->fetchColumn()) { return 'taken'; } // Pending signups try { $stmt2 = $pdo->prepare('SELECT id FROM cp_trial_signups WHERE slug = :slug LIMIT 1'); $stmt2->execute(['slug' => $slug]); if ($stmt2->fetchColumn()) { return 'pending'; } } catch (Throwable $e) { // If cp_trial_signups not yet created, ignore } return null; // available } /** * Notify KlinFlow CP that a new trial signup was created. */ function notify_cp( int $signupId, string $company, string $slug, string $contactName, string $email, array $modules, string $notes, string $ip, string $ua ): void { $to = CP_EMAIL; $subject = "[KlinFlow • Trial Signup] {$company} ({$slug})"; $from = FROM_EMAIL; $mods = $modules ? implode(', ', $modules) : '(none)'; $notesText = $notes !== '' ? $notes : '(no additional notes)'; $body = "New trial signup received:\n\n" . "Signup ID: {$signupId}\n" . "Company: {$company}\n" . "Slug: {$slug}\n" . "Contact: {$contactName}\n" . "Email: {$email}\n" . "Modules: {$mods}\n" . "Notes: {$notesText}\n\n" . "IP: {$ip}\n" . "User-Agent:\n{$ua}\n\n" . "Next steps (manual):\n" . "1) Validate the org and contact.\n" . "2) Create cp_organizations row with slug='{$slug}'.\n" . "3) Create tenant user using stored password_hash from cp_trial_signups.\n" . "4) Enable requested modules in Control Panel.\n"; $headers = "From: KlinFlow Trials <{$from}>\r\n"; $headers .= "Reply-To: {$email}\r\n"; $headers .= "Content-Type: text/plain; charset=UTF-8\r\n"; @mail($to, $subject, $body, $headers); } /** * Send a “we got your trial request” email to the requester, * using the unified App\Services\Mailer. */ function send_trial_welcome_email( string $toEmail, string $contactName, string $company, string $slug, array $modules ): void { try { $mailer = new Mailer(); $safeName = trim($contactName) !== '' ? $contactName : ucfirst((string)strtok((string)$toEmail, '@')); $scheme = (!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off') ? 'https' : 'http'; $host = $_SERVER['HTTP_HOST'] ?? 'klinflow.com'; $base = $scheme.'://'.$host; $logoUrl = $base . '/assets/img/logo/klinflow.png'; $brandColor = '#228B22'; $modulesLabel = $modules ? implode(', ', $modules) : '(no modules selected)'; $tenantUrl = $base . '/t/' . rawurlencode($slug) . '/dashboard'; ob_start(); ?> Your KlinFlow trial request
KlinFlow
 

Thank you for your KlinFlow trial request

Dear ,

We’ve received your request to create a KlinFlow trial tenant for .

Requested tenant slug: /t//apps/pos

Modules you requested:

What happens next:

  • Our team will review your request and validate the details.
  • We’ll provision your tenant and initial admin user.
  • You’ll receive another welcome email with your login link and password once everything is ready.

Once your tenant is activated, your dashboard will be available at:

— Team KlinFlow

KlinFlow
House 12, Road 34, Gulshan, Dhaka 1212
support@klinflow.com ·
© KlinFlow. All rights reserved.
sendWelcome($toEmail, $subject, $html, $text); } catch (\Throwable $e) { error_log('[signup] trial welcome mail failed: '.$e->getMessage()); } } // ───────────────────────────────────────────────────────────── // Handle POST // ───────────────────────────────────────────────────────────── $errors = []; $success = false; // Keep old values for sticky form $old = [ 'company' => '', 'slug' => '', 'name' => '', 'email' => '', 'notes' => '', 'modules' => [], ]; if ($_SERVER['REQUEST_METHOD'] === 'POST') { $company = trim((string)($_POST['company'] ?? '')); $slugRaw = (string)($_POST['slug'] ?? ''); $slug = normalise_slug($slugRaw); $contactName = trim((string)($_POST['name'] ?? '')); $email = trim((string)($_POST['email'] ?? '')); $passwordPlain = (string)($_POST['password'] ?? ''); $confirm = (string)($_POST['confirm'] ?? ''); $modules = isset($_POST['modules']) && is_array($_POST['modules']) ? array_values($_POST['modules']) : []; $notes = trim((string)($_POST['notes'] ?? '')); $termsAccepted = isset($_POST['terms']); $source = 'public-trial-signup'; $old = [ 'company' => $company, 'slug' => $slug, 'name' => $contactName, 'email' => $email, 'notes' => $notes, 'modules' => $modules, ]; // Validation if ($company === '') { $errors['company'] = 'Company/organization is required.'; } if ($slug === '') { $errors['slug'] = 'Slug is required.'; } elseif (strlen($slug) < 3) { $errors['slug'] = 'Slug must be at least 3 characters.'; } elseif (strlen($slug) > 40) { $errors['slug'] = 'Slug may not exceed 40 characters.'; } elseif (in_array($slug, reserved_slugs(), true)) { $errors['slug'] = 'This slug is reserved by KlinFlow.'; } else { $status = slug_taken($slug); if ($status === 'taken') { $errors['slug'] = 'This slug is already in use by an existing tenant.'; } elseif ($status === 'pending') { $errors['slug'] = 'A trial request already exists for this slug.'; } } if ($contactName === '') { $errors['name'] = 'Your name is required.'; } if ($email === '' || !filter_var($email, FILTER_VALIDATE_EMAIL)) { $errors['email'] = 'A valid email address is required.'; } if ($passwordPlain === '' || strlen($passwordPlain) < 8) { $errors['password'] = 'Password must be at least 8 characters.'; } if ($confirm === '' || $confirm !== $passwordPlain) { $errors['confirm'] = 'Passwords must match.'; } if (count($modules) === 0) { $errors['modules'] = 'Please select at least one module.'; } if (!$termsAccepted) { $errors['terms'] = 'You must accept the terms to continue.'; } if (!$errors) { $pdo = pdo(); $passwordHash = password_hash($passwordPlain, PASSWORD_DEFAULT); $ip = $_SERVER['REMOTE_ADDR'] ?? ''; $ua = $_SERVER['HTTP_USER_AGENT'] ?? ''; try { $stmt = $pdo->prepare( 'INSERT INTO cp_trial_signups (company, slug, contact_name, email, password_hash, modules, notes, source, created_at, ip_address, user_agent, status) VALUES (:company, :slug, :contact_name, :email, :password_hash, :modules, :notes, :source, NOW(), :ip, :ua, :status)' ); $stmt->execute([ 'company' => $company, 'slug' => $slug, 'contact_name' => $contactName, 'email' => $email, 'password_hash' => $passwordHash, 'modules' => json_encode($modules, JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE), 'notes' => $notes, 'source' => $source, 'ip' => $ip, 'ua' => $ua, 'status' => 'pending', ]); $signupId = (int)$pdo->lastInsertId(); // Notify CP team inbox notify_cp($signupId, $company, $slug, $contactName, $email, $modules, $notes, $ip, $ua); // Send confirmation email to requester send_trial_welcome_email($email, $contactName, $company, $slug, $modules); $success = true; // Reset sensitive fields $old['password'] = ''; $old['confirm'] = ''; } catch (Throwable $e) { error_log('[signup] save failed: '.$e->getMessage()); $errors['__global'] = 'Failed to save your request. Please try again later.'; } } } ?> Start your 14-day Free Trial — KlinFlow Skip to main
14-Day Free Trial

Start your journey with KlinFlow

Join 100+ businesses running on Bangladesh's most advanced multi-tenant ERP platform. No credit card required.

  • Access to all premium modules
  • Dedicated slug (your-org.klinflow.com)
  • Priority local support

Trusted by

Request Sent!

Check your email for login details. We will activate your tenant shortly.

klinflow.com/t/

Only lowercase letters, numbers, and hyphens.

'fa-cash-register', 'HotelFlow' => 'fa-hotel', 'Bhata' => 'fa-cubes-stacked', 'School' => 'fa-graduation-cap', 'MedFlow' => 'fa-pills', 'BizFlow' => 'fa-briefcase' ]; ?> $icon): ?>

Already have an account? Sign in here