divido.php (9565B)
1 <?php 2 class ModelExtensionPaymentDivido extends Model { 3 const CACHE_KEY_PLANS = 'divido_plans'; 4 5 public function setMerchant($api_key) { 6 if ($api_key) { 7 Divido::setMerchant($api_key); 8 } 9 } 10 11 public function getMethod($payment_address, $total) { 12 $this->load->language('extension/payment/divido'); 13 $this->load->model('localisation/currency'); 14 15 if (!$this->isEnabled()) { 16 return array(); 17 } 18 19 if ($this->session->data['currency'] != 'GBP') { 20 return array(); 21 } 22 23 if ($payment_address['iso_code_2'] != 'GB') { 24 return array(); 25 } 26 27 $cart_threshold = $this->config->get('payment_divido_cart_threshold'); 28 if ($cart_threshold > $total) { 29 return array(); 30 } 31 32 $plans = $this->getCartPlans($this->cart); 33 $has_plan = false; 34 35 foreach ($plans as $plan) { 36 $planMinTotal = $total - ($total * ($plan->min_deposit / 100)); 37 if ($plan->min_amount <= $planMinTotal) { 38 $has_plan = true; 39 break; 40 } 41 } 42 43 if (!$has_plan) { 44 return array(); 45 } 46 47 $title = $this->language->get('text_checkout_title'); 48 if ($title_override = $this->config->get('payment_divido_title')) { 49 $title = $title_override; 50 } 51 52 $method_data = array( 53 'code' => 'divido', 54 'title' => $title, 55 'terms' => '', 56 'sort_order' => $this->config->get('payment_divido_sort_order') 57 ); 58 59 return $method_data; 60 } 61 62 public function getProductSettings($product_id) { 63 return $this->db->query("SELECT `display`, `plans` FROM `" . DB_PREFIX . "divido_product` WHERE `product_id` = '" . (int)$product_id . "'")->row; 64 } 65 66 public function isEnabled() { 67 $api_key = $this->config->get('payment_divido_api_key'); 68 $enabled = $this->config->get('payment_divido_status'); 69 70 return !empty($api_key) && $enabled == 1; 71 } 72 73 public function hashOrderId($order_id, $salt) { 74 return hash('sha256', $order_id . $salt); 75 } 76 77 public function saveLookup($order_id, $salt, $proposal_id = null, $application_id = null, $deposit_amount = null) { 78 $order_id = (int)$order_id; 79 $salt = $this->db->escape($salt); 80 $proposal_id = $this->db->escape($proposal_id); 81 $application_id = $this->db->escape($application_id); 82 $deposit_amount = $this->db->escape($deposit_amount); 83 84 $query_get_lookup = "SELECT `application_id` from `" . DB_PREFIX . "divido_lookup` WHERE order_id = " . $order_id; 85 $result_get_lookup = $this->db->query($query_get_lookup); 86 87 if ($result_get_lookup->num_rows == 0) { 88 $proposal_id = ($proposal_id) ? "'" . $proposal_id . "'" : 'NULL'; 89 $application_id = ($application_id) ? "'" . $application_id . "'" : 'NULL'; 90 $deposit_amount = ($deposit_amount) ? $deposit_amount : 'NULL'; 91 92 $query_upsert = "INSERT INTO `" . DB_PREFIX . "divido_lookup` (`order_id`, `salt`, `proposal_id`, `application_id`, `deposit_amount`) VALUES (" . $order_id . ", '" . $salt . "', " . $proposal_id . ", " . $application_id . ", " . $deposit_amount . ")"; 93 } else { 94 $query_upsert = "UPDATE `" . DB_PREFIX . "divido_lookup` SET `salt` = '" . $salt . "'"; 95 96 if ($proposal_id) { 97 $query_upsert .= ", `proposal_id` = '" . $proposal_id . "'"; 98 } 99 100 if ($application_id) { 101 $query_upsert .= ", `application_id` = '" . $application_id . "'"; 102 } 103 104 if ($deposit_amount) { 105 $query_upsert .= ", `deposit_amount` = " . $deposit_amount; 106 } 107 108 $query_upsert .= " WHERE `order_id` = " . $order_id; 109 } 110 111 $this->db->query($query_upsert); 112 } 113 114 public function getLookupByOrderId($order_id) { 115 return $this->db->query("SELECT * FROM `" . DB_PREFIX . "divido_lookup` WHERE `order_id` = " . $order_id); 116 } 117 public function getGlobalSelectedPlans() { 118 $all_plans = $this->getAllPlans(); 119 $display_plans = $this->config->get('payment_divido_planselection'); 120 121 if ($display_plans == 'all' || empty($display_plans)) { 122 return $all_plans; 123 } 124 125 $selected_plans = $this->config->get('payment_divido_plans_selected'); 126 if (!$selected_plans) { 127 return array(); 128 } 129 130 $plans = array(); 131 foreach ($all_plans as $plan) { 132 if (in_array($plan->id, $selected_plans)) { 133 $plans[] = $plan; 134 } 135 } 136 137 return $plans; 138 } 139 140 public function getAllPlans() { 141 if ($plans = $this->cache->get(self::CACHE_KEY_PLANS)) { 142 // OpenCart 2.1 decodes json objects to associative arrays so we 143 // need to make sure we're getting a list of simple objects back. 144 $plans = array_map(function ($plan) { 145 return (object)$plan; 146 }, $plans); 147 148 return $plans; 149 } 150 151 $api_key = $this->config->get('payment_divido_api_key'); 152 if (!$api_key) { 153 throw new Exception("No Divido api-key defined"); 154 } 155 156 Divido::setMerchant($api_key); 157 158 $response = Divido_Finances::all(); 159 if ($response->status != 'ok') { 160 throw new Exception("Can't get list of finance plans from Divido!"); 161 } 162 163 $plans = $response->finances; 164 165 // OpenCart 2.1 switched to json for their file storage cache, so 166 // we need to convert to a simple object. 167 $plans_plain = array(); 168 foreach ($plans as $plan) { 169 $plan_copy = new stdClass(); 170 $plan_copy->id = $plan->id; 171 $plan_copy->text = $plan->text; 172 $plan_copy->country = $plan->country; 173 $plan_copy->min_amount = $plan->min_amount; 174 $plan_copy->min_deposit = $plan->min_deposit; 175 $plan_copy->max_deposit = $plan->max_deposit; 176 $plan_copy->interest_rate = $plan->interest_rate; 177 $plan_copy->deferral_period = $plan->deferral_period; 178 $plan_copy->agreement_duration = $plan->agreement_duration; 179 180 $plans_plain[] = $plan_copy; 181 } 182 183 $this->cache->set(self::CACHE_KEY_PLANS, $plans_plain); 184 185 return $plans_plain; 186 } 187 188 public function getCartPlans($cart) { 189 $plans = array(); 190 $products = $cart->getProducts(); 191 foreach ($products as $product) { 192 $product_plans = $this->getProductPlans($product['product_id']); 193 if ($product_plans) { 194 $plans = array_merge($plans, $product_plans); 195 } 196 } 197 198 return $plans; 199 } 200 201 public function getPlans($default_plans) { 202 if ($default_plans) { 203 $plans = $this->getGlobalSelectedPlans(); 204 } else { 205 $plans = $this->getAllPlans(); 206 } 207 208 return $plans; 209 } 210 211 public function getOrderTotals() { 212 $totals = array(); 213 $taxes = $this->cart->getTaxes(); 214 $total = 0; 215 216 // Because __call can not keep var references so we put them into an array. 217 $total_data = array( 218 'totals' => &$totals, 219 'taxes' => &$taxes, 220 'total' => &$total 221 ); 222 223 $this->load->model('setting/extension'); 224 225 $sort_order = array(); 226 227 $results = $this->model_setting_extension->getExtensions('total'); 228 229 foreach ($results as $key => $value) { 230 $sort_order[$key] = $this->config->get('total_' . $value['code'] . '_sort_order'); 231 } 232 233 array_multisort($sort_order, SORT_ASC, $results); 234 235 foreach ($results as $result) { 236 if ($this->config->get('total_' . $result['code'] . '_status')) { 237 $this->load->model('extension/total/' . $result['code']); 238 239 // We have to put the totals in an array so that they pass by reference. 240 $this->{'model_extension_total_' . $result['code']}->getTotal($total_data); 241 } 242 } 243 244 $sort_order = array(); 245 246 foreach ($totals as $key => $value) { 247 $sort_order[$key] = $value['sort_order']; 248 } 249 250 array_multisort($sort_order, SORT_ASC, $totals); 251 252 return array($total, $totals); 253 } 254 255 public function getProductPlans($product_id) { 256 $this->load->model('catalog/product'); 257 258 $product_info = $this->model_catalog_product->getProduct($product_id); 259 $settings = $this->getProductSettings($product_id); 260 $product_selection = $this->config->get('payment_divido_productselection'); 261 $divido_categories = $this->config->get('payment_divido_categories'); 262 $price_threshold = $this->config->get('payment_divido_price_threshold'); 263 264 if ($divido_categories) { 265 $product_categories = $this->model_catalog_product->getCategories($product_id); 266 267 $all_categories = array(); 268 foreach ($product_categories as $product_category) { 269 $all_categories[] = $product_category['category_id']; 270 } 271 $category_matches = array_intersect($all_categories, $divido_categories); 272 273 if (!$category_matches) { 274 return null; 275 } 276 } 277 278 if (empty($settings)) { 279 $settings = array( 280 'display' => 'default', 281 'plans' => '', 282 ); 283 } 284 285 if ($product_selection == 'selected' && $settings['display'] == 'custom' && empty($settings['plans'])) { 286 return null; 287 } 288 289 $price = 0; 290 if (($this->config->get('config_customer_price') && $this->customer->isLogged()) || !$this->config->get('config_customer_price')) { 291 $base_price = !empty($product_info['special']) ? $product_info['special'] : $product_info['price']; 292 $price = $this->tax->calculate($base_price, $product_info['tax_class_id'], $this->config->get('config_tax')); 293 } 294 295 if ($product_selection == 'threshold' && !empty($price_threshold) && $price < $price_threshold) { 296 return null; 297 } 298 299 if ($settings['display'] == 'default') { 300 $plans = $this->getPlans(true); 301 return $plans; 302 } 303 304 // If the product has non-default plans, fetch all of them. 305 $available_plans = $this->getPlans(false); 306 $selected_plans = explode(',', $settings['plans']); 307 308 $plans = array(); 309 foreach ($available_plans as $plan) { 310 if (in_array($plan->id, $selected_plans)) { 311 $plans[] = $plan; 312 } 313 } 314 315 if (empty($plans)) { 316 return null; 317 } 318 319 return $plans; 320 } 321 322 }