diff --git a/airtime_mvc/application/Bootstrap.php b/airtime_mvc/application/Bootstrap.php index fc9f6c7e4..d66c680c5 100644 --- a/airtime_mvc/application/Bootstrap.php +++ b/airtime_mvc/application/Bootstrap.php @@ -14,6 +14,7 @@ require_once "DateHelper.php"; require_once "OsPath.php"; require_once "Database.php"; require_once "Timezone.php"; +require_once "Auth.php"; require_once __DIR__.'/forms/helpers/ValidationTypes.php'; require_once __DIR__.'/controllers/plugins/RabbitMqPlugin.php'; require_once __DIR__.'/controllers/plugins/Maintenance.php'; diff --git a/airtime_mvc/application/configs/constants.php b/airtime_mvc/application/configs/constants.php index 9e2563d0f..69ce78d19 100644 --- a/airtime_mvc/application/configs/constants.php +++ b/airtime_mvc/application/configs/constants.php @@ -64,3 +64,9 @@ define('UI_BLOCK_SESSNAME', 'BLOCK');*/ define('SOUNDCLOUD_NOT_UPLOADED_YET' , -1); define('SOUNDCLOUD_PROGRESS' , -2); define('SOUNDCLOUD_ERROR' , -3); + + +//WHMCS integration +define("WHMCS_API_URL", "https://account.sourcefabric.com/includes/api.php"); +define("SUBDOMAIN_WHMCS_CUSTOM_FIELD_NAME", "Choose your domain"); + diff --git a/airtime_mvc/application/controllers/BillingController.php b/airtime_mvc/application/controllers/BillingController.php index ffe90234f..e8aeea0f5 100644 --- a/airtime_mvc/application/controllers/BillingController.php +++ b/airtime_mvc/application/controllers/BillingController.php @@ -12,6 +12,7 @@ class BillingController extends Zend_Controller_Action { $CC_CONFIG = Config::getConfig(); $baseUrl = Application_Common_OsPath::getBaseDir(); $this->view->headLink()->appendStylesheet($baseUrl.'css/billing.css?'.$CC_CONFIG['airtime_version']); + BillingController::ensureClientIdIsValid(); $request = $this->getRequest(); $form = new Application_Form_BillingUpgradeDowngrade(); @@ -35,7 +36,7 @@ class BillingController extends Zend_Controller_Action { $postfields["action"] = "upgradeproduct"; $postfields["clientid"] = Application_Model_Preference::GetClientId(); - $postfields["serviceid"] = self::getClientServiceId(); + $postfields["serviceid"] = self::getClientInstanceId(); $postfields["type"] = "product"; $postfields["newproductid"] = $formData["newproductid"]; $postfields["newproductbillingcycle"] = $formData["newproductbillingcycle"]; @@ -175,6 +176,7 @@ class BillingController extends Zend_Controller_Action { { $request = $this->getRequest(); $form = new Application_Form_BillingClient(); + BillingController::ensureClientIdIsValid(); if ($request->isPost()) { $formData = $request->getPost(); if ($form->isValid($formData)) { @@ -218,6 +220,7 @@ class BillingController extends Zend_Controller_Action { public function invoicesAction() { + BillingController::ensureClientIdIsValid(); $credentials = self::getAPICredentials(); $postfields = array(); @@ -237,6 +240,7 @@ class BillingController extends Zend_Controller_Action { public function invoiceAction() { + BillingController::ensureClientIdIsValid(); $request = $this->getRequest(); $invoice_id = $request->getParam('invoiceid'); self::viewInvoice($invoice_id); @@ -259,10 +263,52 @@ class BillingController extends Zend_Controller_Action { $result = self::makeRequest($credentials["url"], $query_string); Logging::info($result); + + if ($_SERVER['SERVER_NAME'] == "airtime.localhost") { + return "1384"; + } + //This code must run on airtime.pro for it to work... it's trying to match + //the server's hostname with the client subdomain. + foreach ($result["products"] as $product) + { + if (strpos($product[0]["groupname"], "Airtime") === FALSE) + { + //Ignore non-Airtime products + continue; + } + else + { + if ($product[0]["status"] === "Active") { + $airtimeProduct = $product[0]; + $subdomain = ''; + + foreach ($airtimeProduct['customfields']['customfield'] as $customField) + { + if ($customField['name'] === SUBDOMAIN_WHMCS_CUSTOM_FIELD_NAME) + { + $subdomain = $customField['value']; + if (($subdomain . ".airtime.pro") === $_SERVER['SERVER_NAME']) + { + return $airtimeProduct['id']; + } + } + } + } + } + } + throw new Exception("Unable to match subdomain to a service ID"); } public static function getProducts() { + //Making this static to cache the products during a single HTTP request. + //This saves us roundtrips to WHMCS if getProducts() is called multiple times. + static $result = array(); + if (!empty($result)) + { + return $result["products"]["product"]; + } + $credentials = self::getAPICredentials(); $postfields = array(); @@ -279,6 +325,21 @@ class BillingController extends Zend_Controller_Action { $result = self::makeRequest($credentials["url"], $query_string); return $result["products"]["product"]; } + + public static function getProductPricesAndTypes() + { + $products = BillingController::getProducts(); + + foreach ($products as $k => $p) { + $productPrices[$p["name"]] = array( + "monthly" => $p["pricing"]["USD"]["monthly"], + "annually" => $p["pricing"]["USD"]["annually"] + ); + $productTypes[$p["pid"]] = $p["name"] . " ($" . $productPrices[$p['name']]['monthly'] . "/mo)"; + } + return array($productPrices, $productTypes); + } + public static function getClientDetails() { @@ -325,4 +386,12 @@ class BillingController extends Zend_Controller_Action { Logging::info($e->getMessage()); } } + + private static function ensureClientIdIsValid() + { + if (Application_Model_Preference::GetClientId() == null) + { + throw new Exception("Invalid client ID: " . Application_Model_Preference::GetClientId()); + } + } } \ No newline at end of file diff --git a/airtime_mvc/application/controllers/WhmcsLoginController.php b/airtime_mvc/application/controllers/WhmcsLoginController.php index 0f0e327de..2f78ce5ed 100644 --- a/airtime_mvc/application/controllers/WhmcsLoginController.php +++ b/airtime_mvc/application/controllers/WhmcsLoginController.php @@ -1,8 +1,5 @@ setLabel(_('Company Name:')) ->setValue($client["companyname"]) ->setAttrib('class', 'input_text') - ->setRequired(true) + ->setRequired(false) ->addValidator($notEmptyValidator) ->addFilter('StringTrim'); $this->addElement($companyname); @@ -85,7 +85,7 @@ class Application_Form_BillingClient extends Zend_Form $this->addElement($state); $postcode = new Zend_Form_Element_Text('postcode'); - $postcode->setLabel(_('Zip Code:')) + $postcode->setLabel(_('Zip Code / Postal Code:')) ->setValue($client["postcode"]) ->setAttrib('class', 'input_text') ->setRequired(true) diff --git a/airtime_mvc/application/forms/BillingUpgradeDowngrade.php b/airtime_mvc/application/forms/BillingUpgradeDowngrade.php index 10f2b8be7..b89136689 100644 --- a/airtime_mvc/application/forms/BillingUpgradeDowngrade.php +++ b/airtime_mvc/application/forms/BillingUpgradeDowngrade.php @@ -4,17 +4,9 @@ class Application_Form_BillingUpgradeDowngrade extends Zend_Form public function init() { $productPrices = array(); - $productTypes = array(); - $products = BillingController::getProducts(); - - foreach ($products as $k => $p) { - $productPrices[$p["name"]] = array( - "monthly" => $p["pricing"]["USD"]["monthly"], - "annualy" => $p["pricing"]["USD"]["annually"] - ); - $productTypes[$p["pid"]] = $p["name"]; - } - + $productTypes = array(); + list($productPrices, $productTypes) = BillingController::getProductPricesAndTypes(); + //$currentPlanType = ucfirst(Application_Model_Preference::GetPlanLevel()); $currentPlanType = "Hobbyist"; if (($key = array_search($currentPlanType, $productTypes)) !== false) { @@ -30,7 +22,7 @@ class Application_Form_BillingUpgradeDowngrade extends Zend_Form $billingcycle = new Zend_Form_Element_Radio('newproductbillingcycle'); $billingcycle->setLabel(_('Billing cycle:')) - ->setMultiOptions(array('monthly' => 'monthly', 'annually' => 'annually')) + ->setMultiOptions(array('monthly' => 'Monthly', 'annually' => 'Annually')) ->setRequired(true) ->setValue('monthly'); $this->addElement($billingcycle); @@ -50,6 +42,8 @@ class Application_Form_BillingUpgradeDowngrade extends Zend_Form $this->addElement($submit);*/ $client = new Application_Form_BillingClient(); + $client->removeElement("password2"); + $client->removeElement("password2verify"); $this->addSubForm($client, 'billing_client_info'); } } diff --git a/airtime_mvc/application/views/scripts/billing/client.phtml b/airtime_mvc/application/views/scripts/billing/client.phtml index 980288c81..a38b8f685 100644 --- a/airtime_mvc/application/views/scripts/billing/client.phtml +++ b/airtime_mvc/application/views/scripts/billing/client.phtml @@ -1,4 +1,5 @@
+

Account Details

errorMessage)) {?>
errorMessage ?>
successMessage)) {?> diff --git a/airtime_mvc/application/views/scripts/billing/upgrade.phtml b/airtime_mvc/application/views/scripts/billing/upgrade.phtml index c111765b5..8a482ea80 100644 --- a/airtime_mvc/application/views/scripts/billing/upgrade.phtml +++ b/airtime_mvc/application/views/scripts/billing/upgrade.phtml @@ -1,19 +1,162 @@ form; $form->setAttrib('id', 'upgrade-downgrade'); + ?> -
-

Account Plans

+ + +
+

+

-pricing grid here + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
HobbyistStarterPlusPremium
1 Stream + 2 Streams + 2 Streams + 3 Streams +
64kbps Stream Quality + 64kbps and 128kbps Stream Quality + 64kbps and 196kbps Stream Quality + 64kbps, 128kbps, and 196kbps Stream Quality +
5 Listeners + 40 Listeners per stream + 100 Listeners per stream + 500 Listeners per stream +
2GB Storage + 5GB Storage + 30GB Storage + 150GB Storage +
Ticket, Email, Forum Support + Live Chat, Ticket, Email, Forum Support + Live Chat, Ticket, Email, Forum Support + Live Chat, Ticket, Email, Forum Support +
+ Save 15% if paid annually + Save 15% if paid annually + Save 15% if paid annually +
+ + + +
-errorMessage)) {?> -
errorMessage ?>
- -
Plan Level:
- - + +

Current Plan: +

+

Choose a plan:

@@ -23,36 +166,51 @@ pricing grid here
newproductbillingcycle ?>
-
- paymentmethod ?> +
+ Save 15% on annual plans (Hobbyist plan excluded). +
+
+
Total:
+ +
+ Plus VAT if you are an EU resident without a valid VAT number.
-
+

Enter your payment details:

+ errorMessage)) {?> +
errorMessage ?>
+ + + getSubform("billing_client_info") ?> -
+
firstname?>
-
+
lastname?>
-
+
+
companyname?>
-
+
email?>
-
+
+
address1?>
-
+
address2?> -
-
+
+
+
city?>
-
+
state?>
+
postcode?>
@@ -68,19 +226,30 @@ pricing grid here
securityqans?>
+

VAT will be added to your invoice if you are an EU resident without a valid VAT number.

+
getElement("7"); ?>
+
+
- getElement("71"); ?> + getElement("71"); ?> +
+ getElement("71")->renderViewHelper(); ?> +
+ getElement("71")->renderLabel(); ?>
-
- password2?> +
+ +

After submitting your order, you will be redirected to an invoice with payment buttons.

-
- password2verify?> +
+ paymentmethod ?>
- + +
+ +
-



\ No newline at end of file diff --git a/airtime_mvc/application/views/scripts/partialviews/trialBox.phtml b/airtime_mvc/application/views/scripts/partialviews/trialBox.phtml index 691d2983a..c0abffc89 100644 --- a/airtime_mvc/application/views/scripts/partialviews/trialBox.phtml +++ b/airtime_mvc/application/views/scripts/partialviews/trialBox.phtml @@ -6,7 +6,7 @@
diff --git a/airtime_mvc/public/css/billing.css b/airtime_mvc/public/css/billing.css index da9ab49be..c34e8ad49 100644 --- a/airtime_mvc/public/css/billing.css +++ b/airtime_mvc/public/css/billing.css @@ -1,5 +1,28 @@ @CHARSET "UTF-8"; +.billing-panel +{ + width: 400px; + margin: 0 auto; + margin-bottom: 30px; +} + +#upgrade-downgrade +{ + border: 0px solid #000; + margin: 0 auto; + color: #000; +} + +#upgrade-downgrade label +{ + color: rgb(28,28,28); +} +#upgrade-downgrade label.disabled +{ + color: rgb(108,108,108); +} + #upgrade-downgrade dl { width: 300px; @@ -15,19 +38,101 @@ margin-bottom: 10px; } +.pricing-grid table +{ + border-spacing: 0px; + border-collapse: separate; + border: 1px solid #777; + width: 600px; + margin-left: -100px; + /*background-color: #555;*/ + table-layout: fixed; + margin-top: 20px; + margin-bottom: 20px; + box-shadow: 0px 5px 5px rgba(0,0,0,0.5); +} + +.pricing-grid td, .pricing-grid th +{ + border-bottom: 1px solid #999; + border-right: 1px solid #bbb; + background-color: #ccc; + padding: 10px; +} + +.pricing-grid th +{ + border-top-left-radius: 5px; + border-top-right-radius: 5px; + border: 0px; +} + + +.pricing-grid tr.price td +{ + text-align: right; + background-color: #ddd; + font-weight: bold; +} + +#current_plan +{ + text-align: center; +} + #plantype { - float: left; - + float: left; } #billingcycle { float: left; + margin-left: 30px; +} + +#billingcycle_disclaimer +{ + float: left; + margin-left: 30px; + width: 200px; +} + +#vat_disclaimer +{ + text-align: right; + font-size: 0.9em; + margin-bottom: 30px; +} + +#total_box +{ + text-align: right; + margin-top: 30px; + margin-bottom: 10px; + border: 1px solid #777; + background: #ccc; + padding: 5px; } #paymentmethod { - float: left; - +} + +.billing_col1, .billing_col2 +{ + float: left; + margin-right: 10px; +} + +.billing_checkbox +{ + float: left; + margin-right: 5px; + margin-bottom: 10px; +} + +#upgrade-downgrade input[type=submit] +{ + float: right; } \ No newline at end of file