aboutsummaryrefslogtreecommitdiffstats
path: root/public/admin/model/extension
diff options
context:
space:
mode:
authorJesús <heckyel@hyperbola.info>2019-08-18 21:14:58 -0500
committerJesús <heckyel@hyperbola.info>2019-08-18 21:14:58 -0500
commit2eed7b082f83630301e51f57ca8394de228a8605 (patch)
tree1d19962d22d30f99317d9276e4bae7744fc93fc2 /public/admin/model/extension
downloadlibrecart-2eed7b082f83630301e51f57ca8394de228a8605.tar.lz
librecart-2eed7b082f83630301e51f57ca8394de228a8605.tar.xz
librecart-2eed7b082f83630301e51f57ca8394de228a8605.zip
first commit
Diffstat (limited to 'public/admin/model/extension')
-rw-r--r--public/admin/model/extension/advertise/google.php697
-rw-r--r--public/admin/model/extension/dashboard/activity.php8
-rw-r--r--public/admin/model/extension/dashboard/chart.php214
-rw-r--r--public/admin/model/extension/dashboard/map.php20
-rw-r--r--public/admin/model/extension/dashboard/online.php24
-rw-r--r--public/admin/model/extension/dashboard/sale.php438
-rw-r--r--public/admin/model/extension/feed/google_base.php97
-rw-r--r--public/admin/model/extension/fraud/fraudlabspro.php125
-rw-r--r--public/admin/model/extension/fraud/ip.php50
-rw-r--r--public/admin/model/extension/fraud/maxmind.php73
-rw-r--r--public/admin/model/extension/openbay/amazon.php741
-rw-r--r--public/admin/model/extension/openbay/amazon_listing.php231
-rw-r--r--public/admin/model/extension/openbay/amazonus.php720
-rw-r--r--public/admin/model/extension/openbay/amazonus_listing.php197
-rw-r--r--public/admin/model/extension/openbay/ebay.php832
-rw-r--r--public/admin/model/extension/openbay/ebay_product.php101
-rw-r--r--public/admin/model/extension/openbay/ebay_profile.php106
-rw-r--r--public/admin/model/extension/openbay/ebay_template.php51
-rw-r--r--public/admin/model/extension/openbay/etsy.php73
-rw-r--r--public/admin/model/extension/openbay/etsy_product.php75
-rw-r--r--public/admin/model/extension/openbay/fba.php65
-rw-r--r--public/admin/model/extension/openbay/openbay.php761
-rw-r--r--public/admin/model/extension/openbay/order.php228
-rw-r--r--public/admin/model/extension/openbay/version.php7
-rw-r--r--public/admin/model/extension/payment/amazon_login_pay.php452
-rw-r--r--public/admin/model/extension/payment/bluepay_hosted.php235
-rw-r--r--public/admin/model/extension/payment/bluepay_redirect.php228
-rw-r--r--public/admin/model/extension/payment/cardconnect.php328
-rw-r--r--public/admin/model/extension/payment/cardinity.php98
-rw-r--r--public/admin/model/extension/payment/divido.php81
-rw-r--r--public/admin/model/extension/payment/eway.php227
-rw-r--r--public/admin/model/extension/payment/firstdata.php222
-rw-r--r--public/admin/model/extension/payment/firstdata_remote.php278
-rw-r--r--public/admin/model/extension/payment/g2apay.php145
-rw-r--r--public/admin/model/extension/payment/globalpay.php265
-rw-r--r--public/admin/model/extension/payment/globalpay_remote.php260
-rw-r--r--public/admin/model/extension/payment/klarna_checkout.php226
-rw-r--r--public/admin/model/extension/payment/laybuy.php362
-rw-r--r--public/admin/model/extension/payment/pilibaba.php165
-rw-r--r--public/admin/model/extension/payment/pp_braintree.php168
-rw-r--r--public/admin/model/extension/payment/pp_express.php376
-rw-r--r--public/admin/model/extension/payment/pp_payflow_iframe.php136
-rw-r--r--public/admin/model/extension/payment/pp_pro_iframe.php261
-rw-r--r--public/admin/model/extension/payment/realex.php265
-rw-r--r--public/admin/model/extension/payment/realex_remote.php260
-rw-r--r--public/admin/model/extension/payment/sagepay_direct.php265
-rw-r--r--public/admin/model/extension/payment/sagepay_server.php266
-rw-r--r--public/admin/model/extension/payment/securetrading_pp.php208
-rw-r--r--public/admin/model/extension/payment/securetrading_ws.php351
-rw-r--r--public/admin/model/extension/payment/squareup.php117
-rw-r--r--public/admin/model/extension/payment/worldpay.php175
-rw-r--r--public/admin/model/extension/report/activity.php8
-rw-r--r--public/admin/model/extension/report/coupon.php60
-rw-r--r--public/admin/model/extension/report/customer.php380
-rw-r--r--public/admin/model/extension/report/customer_transaction.php62
-rw-r--r--public/admin/model/extension/report/marketing.php60
-rw-r--r--public/admin/model/extension/report/product.php96
-rw-r--r--public/admin/model/extension/report/return.php100
-rw-r--r--public/admin/model/extension/report/sale.php438
59 files changed, 13558 insertions, 0 deletions
diff --git a/public/admin/model/extension/advertise/google.php b/public/admin/model/extension/advertise/google.php
new file mode 100644
index 0000000..467e90b
--- /dev/null
+++ b/public/admin/model/extension/advertise/google.php
@@ -0,0 +1,697 @@
+<?php
+
+use \googleshopping\exception\Connection as ConnectionException;
+use \googleshopping\Googleshopping;
+
+class ModelExtensionAdvertiseGoogle extends Model {
+ private $events = array(
+ 'admin/view/common/column_left/before' => array(
+ 'extension/advertise/google/admin_link',
+ ),
+ 'admin/model/catalog/product/addProduct/after' => array(
+ 'extension/advertise/google/addProduct',
+ ),
+ 'admin/model/catalog/product/copyProduct/after' => array(
+ 'extension/advertise/google/copyProduct',
+ ),
+ 'admin/model/catalog/product/deleteProduct/after' => array(
+ 'extension/advertise/google/deleteProduct',
+ ),
+ 'catalog/controller/checkout/success/before' => array(
+ 'extension/advertise/google/before_checkout_success'
+ ),
+ 'catalog/view/common/header/after' => array(
+ 'extension/advertise/google/google_global_site_tag'
+ ),
+ 'catalog/view/common/success/after' => array(
+ 'extension/advertise/google/google_dynamic_remarketing_purchase'
+ ),
+ 'catalog/view/product/product/after' => array(
+ 'extension/advertise/google/google_dynamic_remarketing_product'
+ ),
+ 'catalog/view/product/search/after' => array(
+ 'extension/advertise/google/google_dynamic_remarketing_searchresults'
+ ),
+ 'catalog/view/product/category/after' => array(
+ 'extension/advertise/google/google_dynamic_remarketing_category'
+ ),
+ 'catalog/view/common/home/after' => array(
+ 'extension/advertise/google/google_dynamic_remarketing_home'
+ ),
+ 'catalog/view/checkout/cart/after' => array(
+ 'extension/advertise/google/google_dynamic_remarketing_cart'
+ )
+ );
+
+ private $rename_tables = array(
+ 'advertise_google_target' => 'googleshopping_target',
+ 'category_to_google_product_category' => 'googleshopping_category',
+ 'product_advertise_google_status' => 'googleshopping_product_status',
+ 'product_advertise_google_target' => 'googleshopping_product_target',
+ 'product_advertise_google' => 'googleshopping_product'
+ );
+
+ private $table_columns = array(
+ 'googleshopping_target' => array(
+ 'advertise_google_target_id',
+ 'store_id',
+ 'campaign_name',
+ 'country',
+ 'budget',
+ 'feeds',
+ 'status'
+ ),
+ 'googleshopping_category' => array(
+ 'google_product_category',
+ 'store_id',
+ 'category_id'
+ ),
+ 'googleshopping_product_status' => array(
+ 'product_id',
+ 'store_id',
+ 'product_variation_id',
+ 'destination_statuses',
+ 'data_quality_issues',
+ 'item_level_issues',
+ 'google_expiration_date'
+ ),
+ 'googleshopping_product_target' => array(
+ 'product_id',
+ 'store_id',
+ 'advertise_google_target_id'
+ ),
+ 'googleshopping_product' => array(
+ 'product_advertise_google_id',
+ 'product_id',
+ 'store_id',
+ 'has_issues',
+ 'destination_status',
+ 'impressions',
+ 'clicks',
+ 'conversions',
+ 'cost',
+ 'conversion_value',
+ 'google_product_category',
+ 'condition',
+ 'adult',
+ 'multipack',
+ 'is_bundle',
+ 'age_group',
+ 'color',
+ 'gender',
+ 'size_type',
+ 'size_system',
+ 'size',
+ 'is_modified'
+ )
+ );
+
+ public function isAppIdUsed($app_id, $store_id) {
+ $sql = "SELECT `store_id` FROM `" . DB_PREFIX . "setting` WHERE `key`='advertise_google_app_id' AND `value`='" . $this->db->escape($store_id) . "' AND `store_id`!=" . (int)$store_id . " LIMIT 1";
+
+ $result = $this->db->query($sql);
+
+ if ($result->num_rows > 0) {
+ try {
+ $googleshopping = new Googleshopping($this->registry, (int)$result->row['store_id']);
+
+ return $googleshopping->isConnected();
+ } catch (\RuntimeException $e) {
+ return false;
+ }
+ }
+
+ return false;
+ }
+
+ public function getFinalProductId() {
+ $sql = "SELECT product_id FROM `" . DB_PREFIX . "product` ORDER BY product_id DESC LIMIT 1";
+
+ $result = $this->db->query($sql);
+
+ if ($result->num_rows > 0) {
+ return (int)$result->row['product_id'];
+ }
+
+ return null;
+ }
+
+ public function isAnyProductCategoryModified($store_id) {
+ $sql = "SELECT pag.is_modified FROM `" . DB_PREFIX . "googleshopping_product` pag WHERE pag.google_product_category IS NOT NULL AND pag.store_id=" . (int)$store_id . " LIMIT 0,1";
+
+ return $this->db->query($sql)->num_rows > 0;
+ }
+
+ public function getAdvertisedCount($store_id) {
+ $result = $this->db->query("SELECT COUNT(product_id) as total FROM `" . DB_PREFIX . "googleshopping_product_target` WHERE store_id=" . (int)$store_id . " GROUP BY `product_id`");
+
+ return $result->num_rows > 0 ? (int)$result->row['total'] : 0;
+ }
+
+ public function getMapping($store_id) {
+ $sql = "SELECT * FROM `" . DB_PREFIX . "googleshopping_category` WHERE store_id=" . (int)$store_id;
+
+ return $this->db->query($sql)->rows;
+ }
+
+ public function setCategoryMapping($google_product_category, $store_id, $category_id) {
+ $sql = "INSERT INTO `" . DB_PREFIX . "googleshopping_category` SET `google_product_category`='" . $this->db->escape($google_product_category) . "', `store_id`=" . (int)$store_id . ", `category_id`=" . (int)$category_id . " ON DUPLICATE KEY UPDATE `category_id`=" . (int)$category_id;
+
+ $this->db->query($sql);
+ }
+
+ public function getMappedCategory($google_product_category, $store_id) {
+ $sql = "SELECT GROUP_CONCAT(cd.name ORDER BY cp.level SEPARATOR '&nbsp;&nbsp;&gt;&nbsp;&nbsp;') AS name, cp.category_id FROM " . DB_PREFIX . "category_path cp LEFT JOIN " . DB_PREFIX . "category_description cd ON (cp.path_id = cd.category_id) LEFT JOIN `" . DB_PREFIX . "googleshopping_category` c2gpc ON (c2gpc.category_id = cp.category_id) WHERE cd.language_id=" . (int)$this->config->get('config_language_id') . " AND c2gpc.google_product_category='" . $this->db->escape($google_product_category) . "' AND c2gpc.store_id=" . (int)$store_id;
+
+ $result = $this->db->query($sql);
+
+ if ($result->num_rows > 0) {
+ return $result->row;
+ }
+
+ return null;
+ }
+
+ public function getProductByProductAdvertiseGoogleId($product_advertise_google_id) {
+ $sql = "SELECT pag.product_id FROM `" . DB_PREFIX . "googleshopping_product` pag WHERE pag.product_advertise_google_id=" . (int)$product_advertise_google_id;
+
+ $result = $this->db->query($sql);
+
+ if ($result->num_rows) {
+ $this->load->model('catalog/product');
+
+ return $this->model_catalog_product->getProduct($result->row['product_id']);
+ }
+ }
+
+ public function getProductAdvertiseGoogle($product_advertise_google_id) {
+ $sql = "SELECT pag.* FROM `" . DB_PREFIX . "googleshopping_product` pag WHERE pag.product_advertise_google_id=" . (int)$product_advertise_google_id;
+
+ return $this->db->query($sql)->row;
+ }
+
+ public function hasActiveTarget($store_id) {
+ $sql = "SELECT agt.advertise_google_target_id FROM `" . DB_PREFIX . "googleshopping_target` agt WHERE agt.store_id=" . (int)$store_id . " AND agt.status='active' LIMIT 1";
+
+ return $this->db->query($sql)->num_rows > 0;
+ }
+
+ public function getRequiredFieldsByProductIds($product_ids, $store_id) {
+ $this->load->config('googleshopping/googleshopping');
+
+ $result = array();
+ $countries = $this->getTargetCountriesByProductIds($product_ids, $store_id);
+
+ foreach ($countries as $country) {
+ foreach ($this->config->get('advertise_google_country_required_fields') as $field => $requirements) {
+ if (
+ (!empty($requirements['countries']) && in_array($country, $requirements['countries']))
+ ||
+ (is_array($requirements['countries']) && empty($requirements['countries']))
+ ) {
+ $result[$field] = $requirements;
+ }
+ }
+ }
+
+ return $result;
+ }
+
+ public function getRequiredFieldsByFilter($data, $store_id) {
+ $this->load->config('googleshopping/googleshopping');
+
+ $result = array();
+ $countries = $this->getTargetCountriesByFilter($data, $store_id);
+
+ foreach ($countries as $country) {
+ foreach ($this->config->get('advertise_google_country_required_fields') as $field => $requirements) {
+ if (
+ (!empty($requirements['countries']) && in_array($country, $requirements['countries']))
+ ||
+ (is_array($requirements['countries']) && empty($requirements['countries']))
+ ) {
+ $result[$field] = $requirements;
+ }
+ }
+ }
+
+ return $result;
+ }
+
+ public function getTargetCountriesByProductIds($product_ids, $store_id) {
+ $sql = "SELECT DISTINCT agt.country FROM `" . DB_PREFIX . "googleshopping_product_target` pagt LEFT JOIN `" . DB_PREFIX . "googleshopping_target` agt ON (agt.advertise_google_target_id = pagt.advertise_google_target_id AND agt.store_id = pagt.store_id) WHERE pagt.product_id IN (" . $this->googleshopping->productIdsToIntegerExpression($product_ids) . ") AND pagt.store_id=" . (int)$store_id;
+
+ return array_map(array($this, 'country'), $this->db->query($sql)->rows);
+ }
+
+ public function getTargetCountriesByFilter($data, $store_id) {
+ $sql = "SELECT DISTINCT agt.country FROM `" . DB_PREFIX . "googleshopping_product_target` pagt LEFT JOIN `" . DB_PREFIX . "googleshopping_target` agt ON (agt.advertise_google_target_id = pagt.advertise_google_target_id AND agt.store_id = pagt.store_id) LEFT JOIN `" . DB_PREFIX . "product` p ON (pagt.product_id = p.product_id) LEFT JOIN `" . DB_PREFIX . "product_description` pd ON (pd.product_id = pagt.product_id) WHERE pagt.store_id=" . (int)$store_id . " AND pd.language_id=" . (int)$this->config->get('config_language_id');
+
+ $this->googleshopping->applyFilter($sql, $data);
+
+ return array_map(array($this, 'country'), $this->db->query($sql)->rows);
+ }
+
+ public function getProductOptionsByProductIds($product_ids) {
+ $sql = "SELECT po.option_id, od.name FROM `" . DB_PREFIX . "product_option` po LEFT JOIN `" . DB_PREFIX . "option_description` od ON (od.option_id=po.option_id AND od.language_id=" . (int)$this->config->get('config_language_id') . ") LEFT JOIN `" . DB_PREFIX . "option` o ON (o.option_id = po.option_id) WHERE o.type IN ('select', 'radio') AND po.product_id IN (" . $this->googleshopping->productIdsToIntegerExpression($product_ids) . ")";
+
+ return $this->db->query($sql)->rows;
+ }
+
+ public function getProductOptionsByFilter($data) {
+ $sql = "SELECT DISTINCT po.option_id, od.name FROM `" . DB_PREFIX . "product_option` po LEFT JOIN `" . DB_PREFIX . "option_description` od ON (od.option_id=po.option_id AND od.language_id=" . (int)$this->config->get('config_language_id') . ") LEFT JOIN `" . DB_PREFIX . "option` o ON (o.option_id = po.option_id) LEFT JOIN `" . DB_PREFIX . "product` p ON (po.product_id = p.product_id) LEFT JOIN `" . DB_PREFIX . "product_description` pd ON (pd.product_id = po.product_id) WHERE o.type IN ('select', 'radio') AND pd.language_id=" . (int)$this->config->get('config_language_id');
+
+ $this->googleshopping->applyFilter($sql, $data);
+
+ return $this->db->query($sql)->rows;
+ }
+
+ public function addTarget($target, $store_id) {
+ $sql = "INSERT INTO `" . DB_PREFIX . "googleshopping_target` SET `store_id`=" . (int)$store_id . ", `campaign_name`='" . $this->db->escape($target['campaign_name']) . "', `country`='" . $this->db->escape($target['country']) . "', `budget`='" . (float)$target['budget'] . "', `feeds`='" . $this->db->escape(json_encode($target['feeds'])) . "', `date_added`=NOW(), `roas`=" . (int)$target['roas'] . " , `status`='" . $this->db->escape($target['status']) . "'";
+
+ $this->db->query($sql);
+
+ return $this->db->getLastId();
+ }
+
+ public function deleteProducts($product_ids) {
+ $sql = "DELETE FROM `" . DB_PREFIX . "googleshopping_product` WHERE `product_id` IN (" . $this->googleshopping->productIdsToIntegerExpression($product_ids) . ")";
+
+ $this->db->query($sql);
+
+ $sql = "DELETE FROM `" . DB_PREFIX . "googleshopping_product_target` WHERE `product_id` IN (" . $this->googleshopping->productIdsToIntegerExpression($product_ids) . ")";
+
+ $this->db->query($sql);
+
+ $sql = "DELETE FROM `" . DB_PREFIX . "googleshopping_product_status` WHERE `product_id` IN (" . $this->googleshopping->productIdsToIntegerExpression($product_ids) . ")";
+
+ $this->db->query($sql);
+
+ return true;
+ }
+
+ public function setAdvertisingBySelect($post_product_ids, $post_target_ids, $store_id) {
+ if (!empty($post_product_ids)) {
+ $product_ids = array_map(array($this->googleshopping, 'integer'), $post_product_ids);
+
+ $product_ids_expression = implode(',', $product_ids);
+
+ $this->db->query("DELETE FROM `" . DB_PREFIX . "googleshopping_product_target` WHERE product_id IN (" . $product_ids_expression . ") AND store_id=" . (int)$store_id);
+
+ if (!empty($post_target_ids)) {
+ $target_ids = array_map(array($this->googleshopping, 'integer'), $post_target_ids);
+
+ $values = array();
+
+ foreach ($product_ids as $product_id) {
+ foreach ($target_ids as $target_id) {
+ $values[] = '(' . $product_id . ',' . $store_id . ',' . $target_id . ')';
+ }
+ }
+
+ $sql = "INSERT INTO `" . DB_PREFIX . "googleshopping_product_target` (`product_id`, `store_id`, `advertise_google_target_id`) VALUES " . implode(',', $values);
+
+ $this->db->query($sql);
+ }
+ }
+ }
+
+ public function setAdvertisingByFilter($data, $post_target_ids, $store_id) {
+ $sql = "DELETE pagt FROM `" . DB_PREFIX . "googleshopping_product_target` pagt LEFT JOIN `" . DB_PREFIX . "product` p ON (pagt.product_id = p.product_id) LEFT JOIN `" . DB_PREFIX . "product_description` pd ON (pd.product_id = p.product_id) WHERE pd.language_id=" . (int)$this->config->get('config_language_id');
+
+ $this->googleshopping->applyFilter($sql, $data);
+
+ $this->db->query($sql);
+
+ if (!empty($post_target_ids)) {
+ $target_ids = array_map(array($this->googleshopping, 'integer'), $post_target_ids);
+
+ $insert_sql = "SELECT p.product_id, " . (int)$store_id . " as store_id, '{TARGET_ID}' as advertise_google_target_id FROM `" . DB_PREFIX . "product` p LEFT JOIN `" . DB_PREFIX . "product_description` pd ON (pd.product_id = p.product_id) WHERE pd.language_id=" . (int)$this->config->get('config_language_id');
+
+ $this->googleshopping->applyFilter($insert_sql, $data);
+
+ foreach ($target_ids as $target_id) {
+ $sql = "INSERT INTO `" . DB_PREFIX . "googleshopping_product_target` (`product_id`, `store_id`, `advertise_google_target_id`) " . str_replace('{TARGET_ID}', (string)$target_id, $insert_sql);
+
+ $this->db->query($sql);
+ }
+ }
+ }
+
+ public function insertNewProducts($product_ids = array(), $store_id) {
+ $sql = "INSERT INTO `" . DB_PREFIX . "googleshopping_product` (`product_id`, `store_id`, `google_product_category`) SELECT p.product_id, p2s.store_id, (SELECT c2gpc.google_product_category FROM `" . DB_PREFIX . "product_to_category` p2c LEFT JOIN `" . DB_PREFIX . "category_path` cp ON (p2c.category_id = cp.category_id) LEFT JOIN `" . DB_PREFIX . "googleshopping_category` c2gpc ON (c2gpc.category_id = cp.path_id AND c2gpc.store_id = " . (int)$store_id . ") WHERE p2c.product_id = p.product_id AND c2gpc.google_product_category IS NOT NULL ORDER BY cp.level DESC LIMIT 0,1) as `google_product_category` FROM `" . DB_PREFIX . "product` p LEFT JOIN `" . DB_PREFIX . "product_to_store` p2s ON (p2s.product_id = p.product_id AND p2s.store_id = " . (int)$store_id . ") LEFT JOIN `" . DB_PREFIX . "googleshopping_product` pag ON (pag.product_id = p.product_id AND pag.store_id=p2s.store_id) WHERE pag.product_id IS NULL AND p2s.store_id IS NOT NULL";
+
+ if (!empty($product_ids)) {
+ $sql .= " AND p.product_id IN (" . $this->googleshopping->productIdsToIntegerExpression($product_ids) . ")";
+ }
+
+ $this->db->query($sql);
+ }
+
+ public function updateGoogleProductCategoryMapping($store_id) {
+ $sql = "INSERT INTO `" . DB_PREFIX . "googleshopping_product` (`product_id`, `store_id`, `google_product_category`) SELECT p.product_id, " . (int)$store_id . " as store_id, (SELECT c2gpc.google_product_category FROM `" . DB_PREFIX . "product_to_category` p2c LEFT JOIN `" . DB_PREFIX . "category_path` cp ON (p2c.category_id = cp.category_id) LEFT JOIN `" . DB_PREFIX . "googleshopping_category` c2gpc ON (c2gpc.category_id = cp.path_id AND c2gpc.store_id = " . (int)$store_id . ") WHERE p2c.product_id = p.product_id AND c2gpc.google_product_category IS NOT NULL ORDER BY cp.level DESC LIMIT 0,1) as `google_product_category` FROM `" . DB_PREFIX . "product` p LEFT JOIN `" . DB_PREFIX . "googleshopping_product` pag ON (pag.product_id = p.product_id) WHERE pag.product_id IS NOT NULL ON DUPLICATE KEY UPDATE `google_product_category`=VALUES(`google_product_category`)";
+
+ $this->db->query($sql);
+ }
+
+ public function updateSingleProductFields($data) {
+ $values = array();
+
+ $entry = array();
+ $entry['product_id'] = (int)$data['product_id'];
+ $entry = array_merge($entry, $this->makeInsertData($data));
+
+ $values[] = "(" . implode(",", $entry) . ")";
+
+ $sql = "INSERT INTO `" . DB_PREFIX . "googleshopping_product` (`product_id`, `store_id`, `google_product_category`, `condition`, `adult`, `multipack`, `is_bundle`, `age_group`, `color`, `gender`, `size_type`, `size_system`, `size`, `is_modified`) VALUES " . implode(',', $values) . " ON DUPLICATE KEY UPDATE " . $this->makeOnDuplicateKeyData();
+
+ $this->db->query($sql);
+ }
+
+ public function updateMultipleProductFields($filter_data, $data) {
+ $insert_sql = "SELECT p.product_id, {INSERT_DATA} FROM `" . DB_PREFIX . "product` p LEFT JOIN `" . DB_PREFIX . "product_description` pd ON (pd.product_id = p.product_id) WHERE pd.language_id=" . (int)$this->config->get('config_language_id');
+
+ $this->googleshopping->applyFilter($insert_sql, $filter_data);
+
+ $insert_data = array();
+ $keys[] = "`product_id`";
+
+ foreach ($this->makeInsertData($data) as $key => $value) {
+ $insert_data[] = $value . " as `" . $key . "`";
+ $keys[] = "`" . $key . "`";
+ }
+
+ $sql = "INSERT INTO `" . DB_PREFIX . "googleshopping_product` (" . implode(", ", $keys) . ") " . str_replace('{INSERT_DATA}', implode(", ", $insert_data), $insert_sql) . " ON DUPLICATE KEY UPDATE " . $this->makeOnDuplicateKeyData();
+
+ $this->db->query($sql);
+ }
+
+ protected function makeInsertData($data) {
+ $insert_data = array();
+
+ $insert_data['store_id'] = (int)$data['store_id'];
+ $insert_data['google_product_category'] = "'" . $this->db->escape($data['google_product_category']) . "'";
+ $insert_data['condition'] = "'" . $this->db->escape($data['condition']) . "'";
+ $insert_data['adult'] = (int)$data['adult'];
+ $insert_data['multipack'] = (int)$data['multipack'];
+ $insert_data['is_bundle'] = (int)$data['is_bundle'];
+ $insert_data['age_group'] = "'" . $this->db->escape($data['age_group']) . "'";
+ $insert_data['color'] = (int)$data['color'];
+ $insert_data['gender'] = "'" . $this->db->escape($data['gender']) . "'";
+ $insert_data['size_type'] = "'" . $this->db->escape($data['size_type']) . "'";
+ $insert_data['size_system'] = "'" . $this->db->escape($data['size_system']) . "'";
+ $insert_data['size'] = (int)$data['size'];
+ $insert_data['is_modified'] = 1;
+
+ return $insert_data;
+ }
+
+ protected function makeOnDuplicateKeyData() {
+ return "`google_product_category`=VALUES(`google_product_category`), `condition`=VALUES(`condition`), `adult`=VALUES(`adult`), `multipack`=VALUES(`multipack`), `is_bundle`=VALUES(`is_bundle`), `age_group`=VALUES(`age_group`), `color`=VALUES(`color`), `gender`=VALUES(`gender`), `size_type`=VALUES(`size_type`), `size_system`=VALUES(`size_system`), `size`=VALUES(`size`), `is_modified`=VALUES(`is_modified`)";
+ }
+
+ public function getCategories($data = array(), $store_id) {
+ $sql = "SELECT cp.category_id AS category_id, GROUP_CONCAT(cd1.name ORDER BY cp.level SEPARATOR '&nbsp;&nbsp;&gt;&nbsp;&nbsp;') AS name, c1.parent_id, c1.sort_order FROM " . DB_PREFIX . "category_path cp LEFT JOIN `" . DB_PREFIX . "category_to_store` c2s ON (c2s.category_id = cp.category_id AND c2s.store_id=" . (int)$store_id . ") LEFT JOIN " . DB_PREFIX . "category c1 ON (cp.category_id = c1.category_id) LEFT JOIN " . DB_PREFIX . "category c2 ON (cp.path_id = c2.category_id) LEFT JOIN " . DB_PREFIX . "category_description cd1 ON (cp.path_id = cd1.category_id) LEFT JOIN " . DB_PREFIX . "category_description cd2 ON (cp.category_id = cd2.category_id) WHERE c2s.store_id IS NOT NULL AND cd1.language_id = '" . (int)$this->config->get('config_language_id') . "' AND cd2.language_id = '" . (int)$this->config->get('config_language_id') . "'";
+
+ if (!empty($data['filter_name'])) {
+ $sql .= " AND cd2.name LIKE '%" . $this->db->escape($data['filter_name']) . "%'";
+ }
+
+ $sql .= " GROUP BY cp.category_id";
+
+ $sort_data = array(
+ 'name',
+ 'sort_order'
+ );
+
+ if (isset($data['sort']) && in_array($data['sort'], $sort_data)) {
+ $sql .= " ORDER BY " . $data['sort'];
+ } else {
+ $sql .= " ORDER BY sort_order";
+ }
+
+ if (isset($data['order']) && ($data['order'] == 'DESC')) {
+ $sql .= " DESC";
+ } else {
+ $sql .= " ASC";
+ }
+
+ if (isset($data['start']) || isset($data['limit'])) {
+ if ($data['start'] < 0) {
+ $data['start'] = 0;
+ }
+
+ if ($data['limit'] < 1) {
+ $data['limit'] = 20;
+ }
+
+ $sql .= " LIMIT " . (int)$data['start'] . "," . (int)$data['limit'];
+ }
+
+ $query = $this->db->query($sql);
+
+ return $query->rows;
+ }
+
+ public function getProductCampaigns($product_id, $store_id) {
+ $sql = "SELECT agt.advertise_google_target_id, agt.campaign_name FROM `" . DB_PREFIX . "googleshopping_product_target` pagt LEFT JOIN `" . DB_PREFIX . "googleshopping_target` agt ON (pagt.advertise_google_target_id = agt.advertise_google_target_id) WHERE pagt.product_id=" . (int)$product_id . " AND pagt.store_id=" . (int)$store_id;
+
+ return $this->db->query($sql)->rows;
+ }
+
+ public function getProductIssues($product_id, $store_id) {
+ $this->load->model('localisation/language');
+
+ $sql = "SELECT pag.color, pag.size, pd.name, p.model FROM `" . DB_PREFIX . "googleshopping_product` pag LEFT JOIN `" . DB_PREFIX . "product` p ON (p.product_id = pag.product_id) LEFT JOIN `" . DB_PREFIX . "product_description` pd ON (pd.product_id = pag.product_id AND pd.language_id=" . (int)$this->config->get('config_language_id') . ") WHERE pag.product_id=" . (int)$product_id . " AND pag.store_id=" . (int)$store_id;
+
+ $product_info = $this->db->query($sql)->row;
+
+ if (!empty($product_info)) {
+ $result = array();
+ $result['name'] = $product_info['name'];
+ $result['model'] = $product_info['model'];
+ $result['entries'] = array();
+
+ foreach ($this->model_localisation_language->getLanguages() as $language) {
+ $language_id = $language['language_id'];
+ $groups = $this->googleshopping->getGroups($product_id, $language_id, $product_info['color'], $product_info['size']);
+
+ $result['entries'][$language_id] = array(
+ 'language_name' => $language['name'],
+ 'issues' => array()
+ );
+
+ foreach ($groups as $id => $group) {
+ $issues = $this->db->query("SELECT * FROM `" . DB_PREFIX . "googleshopping_product_status` WHERE product_id=" . (int)$product_id . " AND store_id=" . (int)$store_id . " AND product_variation_id='" . $this->db->escape($id) . "'")->row;
+
+ $destination_statuses = !empty($issues['destination_statuses']) ? json_decode($issues['destination_statuses'], true) : array();
+ $data_quality_issues = !empty($issues['data_quality_issues']) ? json_decode($issues['data_quality_issues'], true) : array();
+ $item_level_issues = !empty($issues['item_level_issues']) ? json_decode($issues['item_level_issues'], true) : array();
+ $google_expiration_date = !empty($issues['google_expiration_date']) ? date($this->language->get('datetime_format'), $issues['google_expiration_date']) : $this->language->get('text_na');
+
+ $result['entries'][$language_id]['issues'][] = array(
+ 'color' => $group['color'] != "" ? $group['color'] : $this->language->get('text_na'),
+ 'size' => $group['size'] != "" ? $group['size'] : $this->language->get('text_na'),
+ 'destination_statuses' => $destination_statuses,
+ 'data_quality_issues' => $data_quality_issues,
+ 'item_level_issues' => $item_level_issues,
+ 'google_expiration_date' => $google_expiration_date
+ );
+ }
+ }
+
+ return $result;
+ }
+
+ return null;
+ }
+
+ /*
+ * Shortly after releasing the extension,
+ * we learned that the table names are actually
+ * clashing with third-party extensions.
+ * Hence, this renaming script was created.
+ */
+ public function renameTables() {
+ foreach ($this->rename_tables as $old_table => $new_table) {
+ $new_table_name = DB_PREFIX . $new_table;
+ $old_table_name = DB_PREFIX . $old_table;
+
+ if ($this->tableExists($old_table_name) && !$this->tableExists($new_table_name) && $this->tableColumnsMatch($old_table_name, $this->table_columns[$new_table])) {
+ $this->db->query("RENAME TABLE `" . $old_table_name . "` TO `" . $new_table_name . "`");
+ }
+ }
+ }
+
+ private function tableExists($table) {
+ return $this->db->query("SHOW TABLES LIKE '" . $table . "'")->num_rows > 0;
+ }
+
+ private function tableColumnsMatch($table, $columns) {
+ $num_columns = $this->db->query("SHOW COLUMNS FROM `" . $table . "` WHERE Field IN (" . implode(',', $this->wrap($columns, '"')) . ")")->num_rows;
+
+ return $num_columns == count($columns);
+ }
+
+ private function wrap($text, $char) {
+ if (is_array($text)) {
+ foreach ($text as &$string) {
+ $string = $char . $string . $char;
+ }
+
+ return $text;
+ } else {
+ return $char . $text . $char;
+ }
+ }
+
+ public function createTables() {
+ $this->db->query("CREATE TABLE IF NOT EXISTS `" . DB_PREFIX . "googleshopping_product` (
+ `product_advertise_google_id` INT(11) UNSIGNED NOT NULL AUTO_INCREMENT,
+ `product_id` INT(11),
+ `store_id` INT(11) NOT NULL DEFAULT '0',
+ `has_issues` TINYINT(1),
+ `destination_status` ENUM('pending','approved','disapproved') NOT NULL DEFAULT 'pending',
+ `impressions` INT(11) NOT NULL DEFAULT '0',
+ `clicks` INT(11) NOT NULL DEFAULT '0',
+ `conversions` INT(11) NOT NULL DEFAULT '0.0000',
+ `cost` decimal(15,4) NOT NULL DEFAULT '0.0000',
+ `conversion_value` decimal(15,4) NOT NULL DEFAULT '0.0000',
+ `google_product_category` VARCHAR(10),
+ `condition` ENUM('new','refurbished','used'),
+ `adult` TINYINT(1),
+ `multipack` INT(11),
+ `is_bundle` TINYINT(1),
+ `age_group` ENUM('newborn','infant','toddler','kids','adult'),
+ `color` INT(11),
+ `gender` ENUM('male','female','unisex'),
+ `size_type` ENUM('regular','petite','plus','big and tall','maternity'),
+ `size_system` ENUM('AU','BR','CN','DE','EU','FR','IT','JP','MEX','UK','US'),
+ `size` INT(11),
+ `is_modified` TINYINT(1) NOT NULL DEFAULT '0',
+ PRIMARY KEY (`product_advertise_google_id`),
+ UNIQUE `product_id_store_id` (`product_id`, `store_id`)
+ ) ENGINE=MyISAM DEFAULT CHARSET=utf8");
+
+ $this->db->query("CREATE TABLE IF NOT EXISTS `" . DB_PREFIX . "googleshopping_product_status` (
+ `product_id` INT(11),
+ `store_id` INT(11) NOT NULL DEFAULT '0',
+ `product_variation_id` varchar(64),
+ `destination_statuses` TEXT NOT NULL,
+ `data_quality_issues` TEXT NOT NULL,
+ `item_level_issues` TEXT NOT NULL,
+ `google_expiration_date` INT(11) NOT NULL DEFAULT '0',
+ PRIMARY KEY (`product_id`, `store_id`, `product_variation_id`)
+ ) ENGINE=MyISAM DEFAULT CHARSET=utf8");
+
+ $this->db->query("CREATE TABLE IF NOT EXISTS `" . DB_PREFIX . "googleshopping_product_target` (
+ `product_id` INT(11) NOT NULL,
+ `store_id` INT(11) NOT NULL DEFAULT '0',
+ `advertise_google_target_id` INT(11) UNSIGNED NOT NULL,
+ PRIMARY KEY (`product_id`, `advertise_google_target_id`)
+ ) ENGINE=MyISAM DEFAULT CHARSET=utf8");
+
+ $this->db->query("CREATE TABLE IF NOT EXISTS `" . DB_PREFIX . "googleshopping_category` (
+ `google_product_category` VARCHAR(10) NOT NULL,
+ `store_id` INT(11) NOT NULL DEFAULT '0',
+ `category_id` INT(11) NOT NULL,
+ INDEX `category_id_store_id` (`category_id`, `store_id`),
+ PRIMARY KEY (`google_product_category`, `store_id`)
+ ) ENGINE=MyISAM DEFAULT CHARSET=utf8");
+
+ $this->db->query("CREATE TABLE IF NOT EXISTS `" . DB_PREFIX . "googleshopping_target` (
+ `advertise_google_target_id` INT(11) UNSIGNED NOT NULL AUTO_INCREMENT,
+ `store_id` INT(11) NOT NULL DEFAULT '0',
+ `campaign_name` varchar(255) NOT NULL DEFAULT '',
+ `country` varchar(2) NOT NULL DEFAULT '',
+ `budget` decimal(15,4) NOT NULL DEFAULT '0.0000',
+ `feeds` text NOT NULL,
+ `date_added` DATE,
+ `roas` INT(11) NOT NULL DEFAULT '0',
+ `status` ENUM('paused','active') NOT NULL DEFAULT 'paused',
+ INDEX `store_id` (`store_id`),
+ PRIMARY KEY (`advertise_google_target_id`)
+ ) ENGINE=MyISAM DEFAULT CHARSET=utf8");
+ }
+
+ public function fixColumns() {
+ $has_auto_increment = $this->db->query("SHOW COLUMNS FROM `" . DB_PREFIX . "googleshopping_product` WHERE Field='product_advertise_google_id' AND Extra LIKE '%auto_increment%'")->num_rows > 0;
+
+ if (!$has_auto_increment) {
+ $this->db->query("ALTER TABLE " . DB_PREFIX . "googleshopping_product MODIFY COLUMN product_advertise_google_id INT(11) UNSIGNED NOT NULL AUTO_INCREMENT");
+ }
+
+ $has_unique_key = $this->db->query("SHOW INDEX FROM `" . DB_PREFIX . "googleshopping_product` WHERE Key_name='product_id_store_id' AND Non_unique=0")->num_rows == 2;
+
+ if (!$has_unique_key) {
+ $index_exists = $this->db->query("SHOW INDEX FROM `" . DB_PREFIX . "googleshopping_product` WHERE Key_name='product_id_store_id'")->num_rows > 0;
+
+ if ($index_exists) {
+ $this->db->query("ALTER TABLE `" . DB_PREFIX . "googleshopping_product` DROP INDEX product_id_store_id;");
+ }
+
+ $this->db->query("CREATE UNIQUE INDEX product_id_store_id ON `" . DB_PREFIX . "googleshopping_product` (product_id, store_id)");
+ }
+
+ $has_date_added_column = $this->db->query("SHOW COLUMNS FROM `" . DB_PREFIX . "googleshopping_target` WHERE Field='date_added'")->num_rows > 0;
+
+ if (!$has_date_added_column) {
+ $this->db->query("ALTER TABLE " . DB_PREFIX . "googleshopping_target ADD COLUMN date_added DATE");
+
+ $this->db->query("UPDATE " . DB_PREFIX . "googleshopping_target SET date_added = NOW() WHERE date_added IS NULL");
+ }
+
+ $has_roas_column = $this->db->query("SHOW COLUMNS FROM `" . DB_PREFIX . "googleshopping_target` WHERE Field='roas'")->num_rows > 0;
+
+ if (!$has_roas_column) {
+ $this->db->query("ALTER TABLE " . DB_PREFIX . "googleshopping_target ADD COLUMN roas INT(11) NOT NULL DEFAULT '0'");
+ }
+ }
+
+ public function dropTables() {
+ $this->db->query("DROP TABLE IF EXISTS `" . DB_PREFIX . "googleshopping_target`");
+ $this->db->query("DROP TABLE IF EXISTS `" . DB_PREFIX . "googleshopping_category`");
+ $this->db->query("DROP TABLE IF EXISTS `" . DB_PREFIX . "googleshopping_product_status`");
+ $this->db->query("DROP TABLE IF EXISTS `" . DB_PREFIX . "googleshopping_product_target`");
+ $this->db->query("DROP TABLE IF EXISTS `" . DB_PREFIX . "googleshopping_product`");
+ }
+
+ public function deleteEvents() {
+ $this->load->model('setting/event');
+
+ $this->model_setting_event->deleteEventByCode('advertise_google');
+ }
+
+ public function createEvents() {
+ $this->load->model('setting/event');
+
+ foreach ($this->events as $trigger => $actions) {
+ foreach ($actions as $action) {
+ $this->model_setting_event->addEvent('advertise_google', $trigger, $action, 1, 0);
+ }
+ }
+ }
+
+ public function getAllowedTargets() {
+ $this->load->config('googleshopping/googleshopping');
+
+ $result = array();
+
+ foreach ($this->config->get('advertise_google_targets') as $target) {
+ $result[] = array(
+ 'country' => array(
+ 'code' => $target['country'],
+ 'name' => $this->googleshopping->getCountryName($target['country'])
+ ),
+ 'languages' => $this->googleshopping->getLanguages($target['languages']),
+ 'currencies' => $this->googleshopping->getCurrencies($target['currencies'])
+ );
+ }
+
+ return $result;
+ }
+
+ protected function country($row) {
+ return $row['country'];
+ }
+}
diff --git a/public/admin/model/extension/dashboard/activity.php b/public/admin/model/extension/dashboard/activity.php
new file mode 100644
index 0000000..2ed8cc9
--- /dev/null
+++ b/public/admin/model/extension/dashboard/activity.php
@@ -0,0 +1,8 @@
+<?php
+class ModelExtensionDashboardActivity extends Model {
+ public function getActivities() {
+ $query = $this->db->query("SELECT `key`, `data`, `date_added` FROM `" . DB_PREFIX . "customer_activity` ORDER BY `date_added` DESC LIMIT 0,5");
+
+ return $query->rows;
+ }
+} \ No newline at end of file
diff --git a/public/admin/model/extension/dashboard/chart.php b/public/admin/model/extension/dashboard/chart.php
new file mode 100644
index 0000000..6e3f495
--- /dev/null
+++ b/public/admin/model/extension/dashboard/chart.php
@@ -0,0 +1,214 @@
+<?php
+class ModelExtensionDashboardChart extends Model {
+ public function getTotalOrdersByDay() {
+ $implode = array();
+
+ foreach ($this->config->get('config_complete_status') as $order_status_id) {
+ $implode[] = "'" . (int)$order_status_id . "'";
+ }
+
+ $order_data = array();
+
+ for ($i = 0; $i < 24; $i++) {
+ $order_data[$i] = array(
+ 'hour' => $i,
+ 'total' => 0
+ );
+ }
+
+ $query = $this->db->query("SELECT COUNT(*) AS total, HOUR(date_added) AS hour FROM `" . DB_PREFIX . "order` WHERE order_status_id IN(" . implode(",", $implode) . ") AND DATE(date_added) = DATE(NOW()) GROUP BY HOUR(date_added) ORDER BY date_added ASC");
+
+ foreach ($query->rows as $result) {
+ $order_data[$result['hour']] = array(
+ 'hour' => $result['hour'],
+ 'total' => $result['total']
+ );
+ }
+
+ return $order_data;
+ }
+
+ public function getTotalOrdersByWeek() {
+ $implode = array();
+
+ foreach ($this->config->get('config_complete_status') as $order_status_id) {
+ $implode[] = "'" . (int)$order_status_id . "'";
+ }
+
+ $order_data = array();
+
+ $date_start = strtotime('-' . date('w') . ' days');
+
+ for ($i = 0; $i < 7; $i++) {
+ $date = date('Y-m-d', $date_start + ($i * 86400));
+
+ $order_data[date('w', strtotime($date))] = array(
+ 'day' => date('D', strtotime($date)),
+ 'total' => 0
+ );
+ }
+
+ $query = $this->db->query("SELECT COUNT(*) AS total, date_added FROM `" . DB_PREFIX . "order` WHERE order_status_id IN(" . implode(",", $implode) . ") AND DATE(date_added) >= DATE('" . $this->db->escape(date('Y-m-d', $date_start)) . "') GROUP BY DAYNAME(date_added)");
+
+ foreach ($query->rows as $result) {
+ $order_data[date('w', strtotime($result['date_added']))] = array(
+ 'day' => date('D', strtotime($result['date_added'])),
+ 'total' => $result['total']
+ );
+ }
+
+ return $order_data;
+ }
+
+ public function getTotalOrdersByMonth() {
+ $implode = array();
+
+ foreach ($this->config->get('config_complete_status') as $order_status_id) {
+ $implode[] = "'" . (int)$order_status_id . "'";
+ }
+
+ $order_data = array();
+
+ for ($i = 1; $i <= date('t'); $i++) {
+ $date = date('Y') . '-' . date('m') . '-' . $i;
+
+ $order_data[date('j', strtotime($date))] = array(
+ 'day' => date('d', strtotime($date)),
+ 'total' => 0
+ );
+ }
+
+ $query = $this->db->query("SELECT COUNT(*) AS total, date_added FROM `" . DB_PREFIX . "order` WHERE order_status_id IN(" . implode(",", $implode) . ") AND DATE(date_added) >= '" . $this->db->escape(date('Y') . '-' . date('m') . '-1') . "' GROUP BY DATE(date_added)");
+
+ foreach ($query->rows as $result) {
+ $order_data[date('j', strtotime($result['date_added']))] = array(
+ 'day' => date('d', strtotime($result['date_added'])),
+ 'total' => $result['total']
+ );
+ }
+
+ return $order_data;
+ }
+
+ public function getTotalOrdersByYear() {
+ $implode = array();
+
+ foreach ($this->config->get('config_complete_status') as $order_status_id) {
+ $implode[] = "'" . (int)$order_status_id . "'";
+ }
+
+ $order_data = array();
+
+ for ($i = 1; $i <= 12; $i++) {
+ $order_data[$i] = array(
+ 'month' => date('M', mktime(0, 0, 0, $i)),
+ 'total' => 0
+ );
+ }
+
+ $query = $this->db->query("SELECT COUNT(*) AS total, date_added FROM `" . DB_PREFIX . "order` WHERE order_status_id IN(" . implode(",", $implode) . ") AND YEAR(date_added) = YEAR(NOW()) GROUP BY MONTH(date_added)");
+
+ foreach ($query->rows as $result) {
+ $order_data[date('n', strtotime($result['date_added']))] = array(
+ 'month' => date('M', strtotime($result['date_added'])),
+ 'total' => $result['total']
+ );
+ }
+
+ return $order_data;
+ }
+
+ public function getTotalCustomersByDay() {
+ $customer_data = array();
+
+ for ($i = 0; $i < 24; $i++) {
+ $customer_data[$i] = array(
+ 'hour' => $i,
+ 'total' => 0
+ );
+ }
+
+ $query = $this->db->query("SELECT COUNT(*) AS total, HOUR(date_added) AS hour FROM `" . DB_PREFIX . "customer` WHERE DATE(date_added) = DATE(NOW()) GROUP BY HOUR(date_added) ORDER BY date_added ASC");
+
+ foreach ($query->rows as $result) {
+ $customer_data[$result['hour']] = array(
+ 'hour' => $result['hour'],
+ 'total' => $result['total']
+ );
+ }
+
+ return $customer_data;
+ }
+
+ public function getTotalCustomersByWeek() {
+ $customer_data = array();
+
+ $date_start = strtotime('-' . date('w') . ' days');
+
+ for ($i = 0; $i < 7; $i++) {
+ $date = date('Y-m-d', $date_start + ($i * 86400));
+
+ $customer_data[date('w', strtotime($date))] = array(
+ 'day' => date('D', strtotime($date)),
+ 'total' => 0
+ );
+ }
+
+ $query = $this->db->query("SELECT COUNT(*) AS total, date_added FROM `" . DB_PREFIX . "customer` WHERE DATE(date_added) >= DATE('" . $this->db->escape(date('Y-m-d', $date_start)) . "') GROUP BY DAYNAME(date_added)");
+
+ foreach ($query->rows as $result) {
+ $customer_data[date('w', strtotime($result['date_added']))] = array(
+ 'day' => date('D', strtotime($result['date_added'])),
+ 'total' => $result['total']
+ );
+ }
+
+ return $customer_data;
+ }
+
+ public function getTotalCustomersByMonth() {
+ $customer_data = array();
+
+ for ($i = 1; $i <= date('t'); $i++) {
+ $date = date('Y') . '-' . date('m') . '-' . $i;
+
+ $customer_data[date('j', strtotime($date))] = array(
+ 'day' => date('d', strtotime($date)),
+ 'total' => 0
+ );
+ }
+
+ $query = $this->db->query("SELECT COUNT(*) AS total, date_added FROM `" . DB_PREFIX . "customer` WHERE DATE(date_added) >= '" . $this->db->escape(date('Y') . '-' . date('m') . '-1') . "' GROUP BY DATE(date_added)");
+
+ foreach ($query->rows as $result) {
+ $customer_data[date('j', strtotime($result['date_added']))] = array(
+ 'day' => date('d', strtotime($result['date_added'])),
+ 'total' => $result['total']
+ );
+ }
+
+ return $customer_data;
+ }
+
+ public function getTotalCustomersByYear() {
+ $customer_data = array();
+
+ for ($i = 1; $i <= 12; $i++) {
+ $customer_data[$i] = array(
+ 'month' => date('M', mktime(0, 0, 0, $i)),
+ 'total' => 0
+ );
+ }
+
+ $query = $this->db->query("SELECT COUNT(*) AS total, date_added FROM `" . DB_PREFIX . "customer` WHERE YEAR(date_added) = YEAR(NOW()) GROUP BY MONTH(date_added)");
+
+ foreach ($query->rows as $result) {
+ $customer_data[date('n', strtotime($result['date_added']))] = array(
+ 'month' => date('M', strtotime($result['date_added'])),
+ 'total' => $result['total']
+ );
+ }
+
+ return $customer_data;
+ }
+} \ No newline at end of file
diff --git a/public/admin/model/extension/dashboard/map.php b/public/admin/model/extension/dashboard/map.php
new file mode 100644
index 0000000..b108156
--- /dev/null
+++ b/public/admin/model/extension/dashboard/map.php
@@ -0,0 +1,20 @@
+<?php
+class ModelExtensionDashboardMap extends Model {
+ public function getTotalOrdersByCountry() {
+ $implode = array();
+
+ if (is_array($this->config->get('config_complete_status'))) {
+ foreach ($this->config->get('config_complete_status') as $order_status_id) {
+ $implode[] = (int)$order_status_id;
+ }
+ }
+
+ if ($implode) {
+ $query = $this->db->query("SELECT COUNT(*) AS total, SUM(o.total) AS amount, c.iso_code_2 FROM `" . DB_PREFIX . "order` o LEFT JOIN `" . DB_PREFIX . "country` c ON (o.payment_country_id = c.country_id) WHERE o.order_status_id IN('" . (int)implode(',', $implode) . "') GROUP BY o.payment_country_id");
+
+ return $query->rows;
+ } else {
+ return array();
+ }
+ }
+} \ No newline at end of file
diff --git a/public/admin/model/extension/dashboard/online.php b/public/admin/model/extension/dashboard/online.php
new file mode 100644
index 0000000..6cf7415
--- /dev/null
+++ b/public/admin/model/extension/dashboard/online.php
@@ -0,0 +1,24 @@
+<?php
+class ModelExtensionDashboardOnline extends Model {
+ public function getTotalOnline($data = array()) {
+ $sql = "SELECT COUNT(*) AS total FROM `" . DB_PREFIX . "customer_online` co LEFT JOIN " . DB_PREFIX . "customer c ON (co.customer_id = c.customer_id)";
+
+ $implode = array();
+
+ if (!empty($data['filter_ip'])) {
+ $implode[] = "co.ip LIKE '" . $this->db->escape($data['filter_ip']) . "'";
+ }
+
+ if (!empty($data['filter_customer'])) {
+ $implode[] = "co.customer_id > 0 AND CONCAT(c.firstname, ' ', c.lastname) LIKE '" . $this->db->escape($data['filter_customer']) . "'";
+ }
+
+ if ($implode) {
+ $sql .= " WHERE " . implode(" AND ", $implode);
+ }
+
+ $query = $this->db->query($sql);
+
+ return $query->row['total'];
+ }
+} \ No newline at end of file
diff --git a/public/admin/model/extension/dashboard/sale.php b/public/admin/model/extension/dashboard/sale.php
new file mode 100644
index 0000000..8732ba9
--- /dev/null
+++ b/public/admin/model/extension/dashboard/sale.php
@@ -0,0 +1,438 @@
+<?php
+class ModelExtensionDashboardSale extends Model {
+ public function getTotalSales($data = array()) {
+ $sql = "SELECT SUM(total) AS total FROM `" . DB_PREFIX . "order` WHERE order_status_id > '0'";
+
+ if (!empty($data['filter_date_added'])) {
+ $sql .= " AND DATE(date_added) = DATE('" . $this->db->escape($data['filter_date_added']) . "')";
+ }
+
+ $query = $this->db->query($sql);
+
+ return $query->row['total'];
+ }
+
+ public function getTotalOrdersByCountry() {
+ $query = $this->db->query("SELECT COUNT(*) AS total, SUM(o.total) AS amount, c.iso_code_2 FROM `" . DB_PREFIX . "order` o LEFT JOIN `" . DB_PREFIX . "country` c ON (o.payment_country_id = c.country_id) WHERE o.order_status_id > '0' GROUP BY o.payment_country_id");
+
+ return $query->rows;
+ }
+
+ public function getTotalOrdersByDay() {
+ $implode = array();
+
+ foreach ($this->config->get('config_complete_status') as $order_status_id) {
+ $implode[] = "'" . (int)$order_status_id . "'";
+ }
+
+ $order_data = array();
+
+ for ($i = 0; $i < 24; $i++) {
+ $order_data[$i] = array(
+ 'hour' => $i,
+ 'total' => 0
+ );
+ }
+
+ $query = $this->db->query("SELECT COUNT(*) AS total, HOUR(date_added) AS hour FROM `" . DB_PREFIX . "order` WHERE order_status_id IN(" . implode(",", $implode) . ") AND DATE(date_added) = DATE(NOW()) GROUP BY HOUR(date_added) ORDER BY date_added ASC");
+
+ foreach ($query->rows as $result) {
+ $order_data[$result['hour']] = array(
+ 'hour' => $result['hour'],
+ 'total' => $result['total']
+ );
+ }
+
+ return $order_data;
+ }
+
+ public function getTotalOrdersByWeek() {
+ $implode = array();
+
+ foreach ($this->config->get('config_complete_status') as $order_status_id) {
+ $implode[] = "'" . (int)$order_status_id . "'";
+ }
+
+ $order_data = array();
+
+ $date_start = strtotime('-' . date('w') . ' days');
+
+ for ($i = 0; $i < 7; $i++) {
+ $date = date('Y-m-d', $date_start + ($i * 86400));
+
+ $order_data[date('w', strtotime($date))] = array(
+ 'day' => date('D', strtotime($date)),
+ 'total' => 0
+ );
+ }
+
+ $query = $this->db->query("SELECT COUNT(*) AS total, date_added FROM `" . DB_PREFIX . "order` WHERE order_status_id IN(" . implode(",", $implode) . ") AND DATE(date_added) >= DATE('" . $this->db->escape(date('Y-m-d', $date_start)) . "') GROUP BY DAYNAME(date_added)");
+
+ foreach ($query->rows as $result) {
+ $order_data[date('w', strtotime($result['date_added']))] = array(
+ 'day' => date('D', strtotime($result['date_added'])),
+ 'total' => $result['total']
+ );
+ }
+
+ return $order_data;
+ }
+
+ public function getTotalOrdersByMonth() {
+ $implode = array();
+
+ foreach ($this->config->get('config_complete_status') as $order_status_id) {
+ $implode[] = "'" . (int)$order_status_id . "'";
+ }
+
+ $order_data = array();
+
+ for ($i = 1; $i <= date('t'); $i++) {
+ $date = date('Y') . '-' . date('m') . '-' . $i;
+
+ $order_data[date('j', strtotime($date))] = array(
+ 'day' => date('d', strtotime($date)),
+ 'total' => 0
+ );
+ }
+
+ $query = $this->db->query("SELECT COUNT(*) AS total, date_added FROM `" . DB_PREFIX . "order` WHERE order_status_id IN(" . implode(",", $implode) . ") AND DATE(date_added) >= '" . $this->db->escape(date('Y') . '-' . date('m') . '-1') . "' GROUP BY DATE(date_added)");
+
+ foreach ($query->rows as $result) {
+ $order_data[date('j', strtotime($result['date_added']))] = array(
+ 'day' => date('d', strtotime($result['date_added'])),
+ 'total' => $result['total']
+ );
+ }
+
+ return $order_data;
+ }
+
+ public function getTotalOrdersByYear() {
+ $implode = array();
+
+ foreach ($this->config->get('config_complete_status') as $order_status_id) {
+ $implode[] = "'" . (int)$order_status_id . "'";
+ }
+
+ $order_data = array();
+
+ for ($i = 1; $i <= 12; $i++) {
+ $order_data[$i] = array(
+ 'month' => date('M', mktime(0, 0, 0, $i)),
+ 'total' => 0
+ );
+ }
+
+ $query = $this->db->query("SELECT COUNT(*) AS total, date_added FROM `" . DB_PREFIX . "order` WHERE order_status_id IN(" . implode(",", $implode) . ") AND YEAR(date_added) = YEAR(NOW()) GROUP BY MONTH(date_added)");
+
+ foreach ($query->rows as $result) {
+ $order_data[date('n', strtotime($result['date_added']))] = array(
+ 'month' => date('M', strtotime($result['date_added'])),
+ 'total' => $result['total']
+ );
+ }
+
+ return $order_data;
+ }
+
+ public function getOrders($data = array()) {
+ $sql = "SELECT MIN(o.date_added) AS date_start, MAX(o.date_added) AS date_end, COUNT(*) AS `orders`, SUM((SELECT SUM(op.quantity) FROM `" . DB_PREFIX . "order_product` op WHERE op.order_id = o.order_id GROUP BY op.order_id)) AS products, SUM((SELECT SUM(ot.value) FROM `" . DB_PREFIX . "order_total` ot WHERE ot.order_id = o.order_id AND ot.code = 'tax' GROUP BY ot.order_id)) AS tax, SUM(o.total) AS `total` FROM `" . DB_PREFIX . "order` o";
+
+ if (!empty($data['filter_order_status_id'])) {
+ $sql .= " WHERE o.order_status_id = '" . (int)$data['filter_order_status_id'] . "'";
+ } else {
+ $sql .= " WHERE o.order_status_id > '0'";
+ }
+
+ if (!empty($data['filter_date_start'])) {
+ $sql .= " AND DATE(o.date_added) >= '" . $this->db->escape($data['filter_date_start']) . "'";
+ }
+
+ if (!empty($data['filter_date_end'])) {
+ $sql .= " AND DATE(o.date_added) <= '" . $this->db->escape($data['filter_date_end']) . "'";
+ }
+
+ if (!empty($data['filter_group'])) {
+ $group = $data['filter_group'];
+ } else {
+ $group = 'week';
+ }
+
+ switch($group) {
+ case 'day';
+ $sql .= " GROUP BY YEAR(o.date_added), MONTH(o.date_added), DAY(o.date_added)";
+ break;
+ default:
+ case 'week':
+ $sql .= " GROUP BY YEAR(o.date_added), WEEK(o.date_added)";
+ break;
+ case 'month':
+ $sql .= " GROUP BY YEAR(o.date_added), MONTH(o.date_added)";
+ break;
+ case 'year':
+ $sql .= " GROUP BY YEAR(o.date_added)";
+ break;
+ }
+
+ $sql .= " ORDER BY o.date_added DESC";
+
+ if (isset($data['start']) || isset($data['limit'])) {
+ if ($data['start'] < 0) {
+ $data['start'] = 0;
+ }
+
+ if ($data['limit'] < 1) {
+ $data['limit'] = 20;
+ }
+
+ $sql .= " LIMIT " . (int)$data['start'] . "," . (int)$data['limit'];
+ }
+
+ $query = $this->db->query($sql);
+
+ return $query->rows;
+ }
+
+ public function getTotalOrders($data = array()) {
+ if (!empty($data['filter_group'])) {
+ $group = $data['filter_group'];
+ } else {
+ $group = 'week';
+ }
+
+ switch($group) {
+ case 'day';
+ $sql = "SELECT COUNT(DISTINCT YEAR(date_added), MONTH(date_added), DAY(date_added)) AS total FROM `" . DB_PREFIX . "order`";
+ break;
+ default:
+ case 'week':
+ $sql = "SELECT COUNT(DISTINCT YEAR(date_added), WEEK(date_added)) AS total FROM `" . DB_PREFIX . "order`";
+ break;
+ case 'month':
+ $sql = "SELECT COUNT(DISTINCT YEAR(date_added), MONTH(date_added)) AS total FROM `" . DB_PREFIX . "order`";
+ break;
+ case 'year':
+ $sql = "SELECT COUNT(DISTINCT YEAR(date_added)) AS total FROM `" . DB_PREFIX . "order`";
+ break;
+ }
+
+ if (!empty($data['filter_order_status_id'])) {
+ $sql .= " WHERE order_status_id = '" . (int)$data['filter_order_status_id'] . "'";
+ } else {
+ $sql .= " WHERE order_status_id > '0'";
+ }
+
+ if (!empty($data['filter_date_start'])) {
+ $sql .= " AND DATE(date_added) >= '" . $this->db->escape($data['filter_date_start']) . "'";
+ }
+
+ if (!empty($data['filter_date_end'])) {
+ $sql .= " AND DATE(date_added) <= '" . $this->db->escape($data['filter_date_end']) . "'";
+ }
+
+ $query = $this->db->query($sql);
+
+ return $query->row['total'];
+ }
+
+ public function getTaxes($data = array()) {
+ $sql = "SELECT MIN(o.date_added) AS date_start, MAX(o.date_added) AS date_end, ot.title, SUM(ot.value) AS total, COUNT(o.order_id) AS `orders` FROM `" . DB_PREFIX . "order` o LEFT JOIN `" . DB_PREFIX . "order_total` ot ON (ot.order_id = o.order_id) WHERE ot.code = 'tax'";
+
+ if (!empty($data['filter_order_status_id'])) {
+ $sql .= " AND o.order_status_id = '" . (int)$data['filter_order_status_id'] . "'";
+ } else {
+ $sql .= " AND o.order_status_id > '0'";
+ }
+
+ if (!empty($data['filter_date_start'])) {
+ $sql .= " AND DATE(o.date_added) >= '" . $this->db->escape($data['filter_date_start']) . "'";
+ }
+
+ if (!empty($data['filter_date_end'])) {
+ $sql .= " AND DATE(o.date_added) <= '" . $this->db->escape($data['filter_date_end']) . "'";
+ }
+
+ if (!empty($data['filter_group'])) {
+ $group = $data['filter_group'];
+ } else {
+ $group = 'week';
+ }
+
+ switch($group) {
+ case 'day';
+ $sql .= " GROUP BY YEAR(o.date_added), MONTH(o.date_added), DAY(o.date_added), ot.title";
+ break;
+ default:
+ case 'week':
+ $sql .= " GROUP BY YEAR(o.date_added), WEEK(o.date_added), ot.title";
+ break;
+ case 'month':
+ $sql .= " GROUP BY YEAR(o.date_added), MONTH(o.date_added), ot.title";
+ break;
+ case 'year':
+ $sql .= " GROUP BY YEAR(o.date_added), ot.title";
+ break;
+ }
+
+ if (isset($data['start']) || isset($data['limit'])) {
+ if ($data['start'] < 0) {
+ $data['start'] = 0;
+ }
+
+ if ($data['limit'] < 1) {
+ $data['limit'] = 20;
+ }
+
+ $sql .= " LIMIT " . (int)$data['start'] . "," . (int)$data['limit'];
+ }
+
+ $query = $this->db->query($sql);
+
+ return $query->rows;
+ }
+
+ public function getTotalTaxes($data = array()) {
+ if (!empty($data['filter_group'])) {
+ $group = $data['filter_group'];
+ } else {
+ $group = 'week';
+ }
+
+ switch($group) {
+ case 'day';
+ $sql = "SELECT COUNT(DISTINCT YEAR(o.date_added), MONTH(o.date_added), DAY(o.date_added), ot.title) AS total FROM `" . DB_PREFIX . "order` o";
+ break;
+ default:
+ case 'week':
+ $sql = "SELECT COUNT(DISTINCT YEAR(o.date_added), WEEK(o.date_added), ot.title) AS total FROM `" . DB_PREFIX . "order` o";
+ break;
+ case 'month':
+ $sql = "SELECT COUNT(DISTINCT YEAR(o.date_added), MONTH(o.date_added), ot.title) AS total FROM `" . DB_PREFIX . "order` o";
+ break;
+ case 'year':
+ $sql = "SELECT COUNT(DISTINCT YEAR(o.date_added), ot.title) AS total FROM `" . DB_PREFIX . "order` o";
+ break;
+ }
+
+ $sql .= " LEFT JOIN `" . DB_PREFIX . "order_total` ot ON (o.order_id = ot.order_id) WHERE ot.code = 'tax'";
+
+ if (!empty($data['filter_order_status_id'])) {
+ $sql .= " AND o.order_status_id = '" . (int)$data['filter_order_status_id'] . "'";
+ } else {
+ $sql .= " AND o.order_status_id > '0'";
+ }
+
+ if (!empty($data['filter_date_start'])) {
+ $sql .= " AND DATE(o.date_added) >= '" . $this->db->escape($data['filter_date_start']) . "'";
+ }
+
+ if (!empty($data['filter_date_end'])) {
+ $sql .= " AND DATE(o.date_added) <= '" . $this->db->escape($data['filter_date_end']) . "'";
+ }
+
+ $query = $this->db->query($sql);
+
+ return $query->row['total'];
+ }
+
+ public function getShipping($data = array()) {
+ $sql = "SELECT MIN(o.date_added) AS date_start, MAX(o.date_added) AS date_end, ot.title, SUM(ot.value) AS total, COUNT(o.order_id) AS `orders` FROM `" . DB_PREFIX . "order` o LEFT JOIN `" . DB_PREFIX . "order_total` ot ON (o.order_id = ot.order_id) WHERE ot.code = 'shipping'";
+
+ if (!empty($data['filter_order_status_id'])) {
+ $sql .= " AND o.order_status_id = '" . (int)$data['filter_order_status_id'] . "'";
+ } else {
+ $sql .= " AND o.order_status_id > '0'";
+ }
+
+ if (!empty($data['filter_date_start'])) {
+ $sql .= " AND DATE(o.date_added) >= '" . $this->db->escape($data['filter_date_start']) . "'";
+ }
+
+ if (!empty($data['filter_date_end'])) {
+ $sql .= " AND DATE(o.date_added) <= '" . $this->db->escape($data['filter_date_end']) . "'";
+ }
+
+ if (!empty($data['filter_group'])) {
+ $group = $data['filter_group'];
+ } else {
+ $group = 'week';
+ }
+
+ switch($group) {
+ case 'day';
+ $sql .= " GROUP BY YEAR(o.date_added), MONTH(o.date_added), DAY(o.date_added), ot.title";
+ break;
+ default:
+ case 'week':
+ $sql .= " GROUP BY YEAR(o.date_added), WEEK(o.date_added), ot.title";
+ break;
+ case 'month':
+ $sql .= " GROUP BY YEAR(o.date_added), MONTH(o.date_added), ot.title";
+ break;
+ case 'year':
+ $sql .= " GROUP BY YEAR(o.date_added), ot.title";
+ break;
+ }
+
+ if (isset($data['start']) || isset($data['limit'])) {
+ if ($data['start'] < 0) {
+ $data['start'] = 0;
+ }
+
+ if ($data['limit'] < 1) {
+ $data['limit'] = 20;
+ }
+
+ $sql .= " LIMIT " . (int)$data['start'] . "," . (int)$data['limit'];
+ }
+
+ $query = $this->db->query($sql);
+
+ return $query->rows;
+ }
+
+ public function getTotalShipping($data = array()) {
+ if (!empty($data['filter_group'])) {
+ $group = $data['filter_group'];
+ } else {
+ $group = 'week';
+ }
+
+ switch($group) {
+ case 'day';
+ $sql = "SELECT COUNT(DISTINCT YEAR(o.date_added), MONTH(o.date_added), DAY(o.date_added), ot.title) AS total FROM `" . DB_PREFIX . "order` o";
+ break;
+ default:
+ case 'week':
+ $sql = "SELECT COUNT(DISTINCT YEAR(o.date_added), WEEK(o.date_added), ot.title) AS total FROM `" . DB_PREFIX . "order` o";
+ break;
+ case 'month':
+ $sql = "SELECT COUNT(DISTINCT YEAR(o.date_added), MONTH(o.date_added), ot.title) AS total FROM `" . DB_PREFIX . "order` o";
+ break;
+ case 'year':
+ $sql = "SELECT COUNT(DISTINCT YEAR(o.date_added), ot.title) AS total FROM `" . DB_PREFIX . "order` o";
+ break;
+ }
+
+ $sql .= " LEFT JOIN `" . DB_PREFIX . "order_total` ot ON (o.order_id = ot.order_id) WHERE ot.code = 'shipping'";
+
+ if (!empty($data['filter_order_status_id'])) {
+ $sql .= " AND order_status_id = '" . (int)$data['filter_order_status_id'] . "'";
+ } else {
+ $sql .= " AND order_status_id > '0'";
+ }
+
+ if (!empty($data['filter_date_start'])) {
+ $sql .= " AND DATE(o.date_added) >= '" . $this->db->escape($data['filter_date_start']) . "'";
+ }
+
+ if (!empty($data['filter_date_end'])) {
+ $sql .= " AND DATE(o.date_added) <= '" . $this->db->escape($data['filter_date_end']) . "'";
+ }
+
+ $query = $this->db->query($sql);
+
+ return $query->row['total'];
+ }
+} \ No newline at end of file
diff --git a/public/admin/model/extension/feed/google_base.php b/public/admin/model/extension/feed/google_base.php
new file mode 100644
index 0000000..b54f1b1
--- /dev/null
+++ b/public/admin/model/extension/feed/google_base.php
@@ -0,0 +1,97 @@
+<?php
+class ModelExtensionFeedGoogleBase extends Model {
+ public function install() {
+ $this->db->query("
+ CREATE TABLE `" . DB_PREFIX . "google_base_category` (
+ `google_base_category_id` INT(11) NOT NULL AUTO_INCREMENT,
+ `name` varchar(255) NOT NULL,
+ PRIMARY KEY (`google_base_category_id`)
+ ) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_general_ci;
+ ");
+
+ $this->db->query("
+ CREATE TABLE `" . DB_PREFIX . "google_base_category_to_category` (
+ `google_base_category_id` INT(11) NOT NULL,
+ `category_id` INT(11) NOT NULL,
+ PRIMARY KEY (`google_base_category_id`, `category_id`)
+ ) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_general_ci;
+ ");
+ }
+
+ public function uninstall() {
+ $this->db->query("DROP TABLE IF EXISTS `" . DB_PREFIX . "google_base_category`");
+ $this->db->query("DROP TABLE IF EXISTS `" . DB_PREFIX . "google_base_category_to_category`");
+ }
+
+ public function import($string) {
+ $this->db->query("DELETE FROM " . DB_PREFIX . "google_base_category");
+
+ $lines = explode("\n", $string);
+
+ foreach ($lines as $line) {
+ if (substr($line, 0, 1) != '#') {
+ $part = explode(' - ', $line, 2);
+
+ if (isset($part[1])) {
+ $this->db->query("INSERT INTO " . DB_PREFIX . "google_base_category SET google_base_category_id = '" . (int)$part[0] . "', name = '" . $this->db->escape($part[1]) . "'");
+ }
+ }
+ }
+ }
+
+ public function getGoogleBaseCategories($data = array()) {
+ $sql = "SELECT * FROM `" . DB_PREFIX . "google_base_category` WHERE name LIKE '%" . $this->db->escape($data['filter_name']) . "%' ORDER BY name ASC";
+
+ if (isset($data['start']) || isset($data['limit'])) {
+ if ($data['start'] < 0) {
+ $data['start'] = 0;
+ }
+
+ if ($data['limit'] < 1) {
+ $data['limit'] = 20;
+ }
+
+ $sql .= " LIMIT " . (int)$data['start'] . "," . (int)$data['limit'];
+ }
+
+ $query = $this->db->query($sql);
+
+ return $query->rows;
+ }
+
+ public function addCategory($data) {
+ $this->db->query("DELETE FROM " . DB_PREFIX . "google_base_category_to_category WHERE category_id = '" . (int)$data['category_id'] . "'");
+
+ $this->db->query("INSERT INTO " . DB_PREFIX . "google_base_category_to_category SET google_base_category_id = '" . (int)$data['google_base_category_id'] . "', category_id = '" . (int)$data['category_id'] . "'");
+ }
+
+ public function deleteCategory($category_id) {
+ $this->db->query("DELETE FROM " . DB_PREFIX . "google_base_category_to_category WHERE category_id = '" . (int)$category_id . "'");
+ }
+
+ public function getCategories($data = array()) {
+ $sql = "SELECT google_base_category_id, (SELECT name FROM `" . DB_PREFIX . "google_base_category` gbc WHERE gbc.google_base_category_id = gbc2c.google_base_category_id) AS google_base_category, category_id, (SELECT name FROM `" . DB_PREFIX . "category_description` cd WHERE cd.category_id = gbc2c.category_id AND cd.language_id = '" . (int)$this->config->get('config_language_id') . "') AS category FROM `" . DB_PREFIX . "google_base_category_to_category` gbc2c ORDER BY google_base_category ASC";
+
+ if (isset($data['start']) || isset($data['limit'])) {
+ if ($data['start'] < 0) {
+ $data['start'] = 0;
+ }
+
+ if ($data['limit'] < 1) {
+ $data['limit'] = 20;
+ }
+
+ $sql .= " LIMIT " . (int)$data['start'] . "," . (int)$data['limit'];
+ }
+
+ $query = $this->db->query($sql);
+
+ return $query->rows;
+ }
+
+ public function getTotalCategories() {
+ $query = $this->db->query("SELECT COUNT(*) AS total FROM `" . DB_PREFIX . "google_base_category_to_category`");
+
+ return $query->row['total'];
+ }
+}
diff --git a/public/admin/model/extension/fraud/fraudlabspro.php b/public/admin/model/extension/fraud/fraudlabspro.php
new file mode 100644
index 0000000..b7a80b2
--- /dev/null
+++ b/public/admin/model/extension/fraud/fraudlabspro.php
@@ -0,0 +1,125 @@
+<?php
+class ModelExtensionFraudFraudLabsPro extends Model {
+ public function install() {
+ $this->db->query("
+ CREATE TABLE IF NOT EXISTS `" . DB_PREFIX . "fraudlabspro` (
+ `order_id` VARCHAR(11) NOT NULL,
+ `is_country_match` CHAR(2) NOT NULL,
+ `is_high_risk_country` CHAR(2) NOT NULL,
+ `distance_in_km` VARCHAR(10) NOT NULL,
+ `distance_in_mile` VARCHAR(10) NOT NULL,
+ `ip_address` VARCHAR(15) NOT NULL,
+ `ip_country` VARCHAR(2) NOT NULL,
+ `ip_continent` VARCHAR(20) NOT NULL,
+ `ip_region` VARCHAR(21) NOT NULL,
+ `ip_city` VARCHAR(21) NOT NULL,
+ `ip_latitude` VARCHAR(21) NOT NULL,
+ `ip_longitude` VARCHAR(21) NOT NULL,
+ `ip_timezone` VARCHAR(10) NOT NULL,
+ `ip_elevation` VARCHAR(10) NOT NULL,
+ `ip_domain` VARCHAR(50) NOT NULL,
+ `ip_mobile_mnc` VARCHAR(100) NOT NULL,
+ `ip_mobile_mcc` VARCHAR(100) NOT NULL,
+ `ip_mobile_brand` VARCHAR(100) NOT NULL,
+ `ip_netspeed` VARCHAR(10) NOT NULL,
+ `ip_isp_name` VARCHAR(50) NOT NULL,
+ `ip_usage_type` VARCHAR(30) NOT NULL,
+ `is_free_email` CHAR(2) NOT NULL,
+ `is_new_domain_name` CHAR(2) NOT NULL,
+ `is_proxy_ip_address` CHAR(2) NOT NULL,
+ `is_bin_found` CHAR(2) NOT NULL,
+ `is_bin_country_match` CHAR(2) NOT NULL,
+ `is_bin_name_match` CHAR(2) NOT NULL,
+ `is_bin_phone_match` CHAR(2) NOT NULL,
+ `is_bin_prepaid` CHAR(2) NOT NULL,
+ `is_address_ship_forward` CHAR(2) NOT NULL,
+ `is_bill_ship_city_match` CHAR(2) NOT NULL,
+ `is_bill_ship_state_match` CHAR(2) NOT NULL,
+ `is_bill_ship_country_match` CHAR(2) NOT NULL,
+ `is_bill_ship_postal_match` CHAR(2) NOT NULL,
+ `is_ip_blacklist` CHAR(2) NOT NULL,
+ `is_email_blacklist` CHAR(2) NOT NULL,
+ `is_credit_card_blacklist` CHAR(2) NOT NULL,
+ `is_device_blacklist` CHAR(2) NOT NULL,
+ `is_user_blacklist` CHAR(2) NOT NULL,
+ `fraudlabspro_score` CHAR(3) NOT NULL,
+ `fraudlabspro_distribution` CHAR(3) NOT NULL,
+ `fraudlabspro_status` CHAR(10) NOT NULL,
+ `fraudlabspro_id` CHAR(15) NOT NULL,
+ `fraudlabspro_error` CHAR(3) NOT NULL,
+ `fraudlabspro_message` VARCHAR(50) NOT NULL,
+ `fraudlabspro_credits` VARCHAR(10) NOT NULL,
+ `api_key` CHAR(32) NOT NULL,
+ PRIMARY KEY (`order_id`)
+ ) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_general_ci;
+ ");
+
+ $this->db->query("INSERT INTO `" . DB_PREFIX . "order_status` (`language_id`, `name`) VALUES (1, 'Fraud');");
+ $status_fraud_id = $this->db->getLastId();
+
+ $this->db->query("INSERT INTO `" . DB_PREFIX . "order_status` (`language_id`, `name`) VALUES (1, 'Fraud Review');");
+
+ $status_fraud_review_id = $this->db->getLastId();
+
+ $this->db->query("INSERT INTO `" . DB_PREFIX . "setting` (`code`, `key`, `value`, `serialized`) VALUES ('fraudlabspro', 'fraud_fraudlabspro_score', '80', '0');");
+ $this->db->query("INSERT INTO `" . DB_PREFIX . "setting` (`code`, `key`, `value`, `serialized`) VALUES ('fraudlabspro', 'fraud_fraudlabspro_order_status_id', '" . (int)$status_fraud_id . "', '0');");
+ $this->db->query("INSERT INTO `" . DB_PREFIX . "setting` (`code`, `key`, `value`, `serialized`) VALUES ('fraudlabspro', 'fraud_fraudlabspro_review_status_id', '" . (int)$status_fraud_review_id . "', '0');");
+ $this->db->query("INSERT INTO `" . DB_PREFIX . "setting` (`code`, `key`, `value`, `serialized`) VALUES ('fraudlabspro', 'fraud_fraudlabspro_approve_status_id', '2', '0');");
+ $this->db->query("INSERT INTO `" . DB_PREFIX . "setting` (`code`, `key`, `value`, `serialized`) VALUES ('fraudlabspro', 'fraud_fraudlabspro_reject_status_id', '8', '0');");
+
+ $this->cache->delete('order_status.' . (int)$this->config->get('config_language_id'));
+ }
+
+ public function uninstall() {
+ //$this->db->query("DROP TABLE IF EXISTS `" . DB_PREFIX . "fraudlabspro`");
+ $this->db->query("DELETE FROM `" . DB_PREFIX . "order_status` WHERE `name` = 'Fraud'");
+ $this->db->query("DELETE FROM `" . DB_PREFIX . "order_status` WHERE `name` = 'Fraud Review'");
+ }
+
+ public function getOrder($order_id) {
+ $query = $this->db->query("SELECT * FROM `" . DB_PREFIX . "fraudlabspro` WHERE order_id = '" . (int)$order_id . "'");
+
+ return $query->row;
+ }
+
+ public function addOrderHistory($order_id, $data, $store_id = 0) {
+ $json = array();
+
+ $this->load->model('setting/store');
+
+ $store_info = $this->model_setting_store->getStore($store_id);
+
+ if ($store_info) {
+ $url = $store_info['ssl'];
+ } else {
+ $url = HTTPS_CATALOG;
+ }
+
+ if (isset($this->session->data['cookie'])) {
+ $curl = curl_init();
+
+ // Set SSL if required
+ if (substr($url, 0, 5) == 'https') {
+ curl_setopt($curl, CURLOPT_PORT, 443);
+ }
+
+ curl_setopt($curl, CURLOPT_HEADER, false);
+ curl_setopt($curl, CURLINFO_HEADER_OUT, true);
+ curl_setopt($curl, CURLOPT_USERAGENT, $this->request->server['HTTP_USER_AGENT']);
+ curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, false);
+ curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false);
+ curl_setopt($curl, CURLOPT_FORBID_REUSE, false);
+ curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
+ curl_setopt($curl, CURLOPT_URL, $url . 'index.php?route=api/order/history&order_id=' . $order_id);
+ curl_setopt($curl, CURLOPT_POST, true);
+ curl_setopt($curl, CURLOPT_POSTFIELDS, http_build_query($data));
+ curl_setopt($curl, CURLOPT_COOKIE, session_name() . '=' . $this->session->data['cookie'] . ';');
+
+ $json = curl_exec($curl);
+
+ curl_close($curl);
+ }
+
+ return $json;
+ }
+} \ No newline at end of file
diff --git a/public/admin/model/extension/fraud/ip.php b/public/admin/model/extension/fraud/ip.php
new file mode 100644
index 0000000..3e01bdf
--- /dev/null
+++ b/public/admin/model/extension/fraud/ip.php
@@ -0,0 +1,50 @@
+<?php
+class ModelExtensionFraudIp extends Model {
+ public function install() {
+ $this->db->query("
+ CREATE TABLE IF NOT EXISTS `" . DB_PREFIX . "fraud_ip` (
+ `ip` varchar(40) NOT NULL,
+ `date_added` datetime NOT NULL,
+ PRIMARY KEY (`ip`)
+ ) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_general_ci;
+ ");
+ }
+
+ public function uninstall() {
+ $this->db->query("DROP TABLE IF EXISTS `" . DB_PREFIX . "ip`");
+ }
+
+ public function addIp($ip) {
+ $this->db->query("INSERT INTO `" . DB_PREFIX . "fraud_ip` SET `ip` = '" . $this->db->escape($ip) . "', date_added = NOW()");
+ }
+
+ public function removeIp($ip) {
+ $this->db->query("DELETE FROM `" . DB_PREFIX . "fraud_ip` WHERE `ip` = '" . $this->db->escape($ip) . "'");
+ }
+
+ public function getIps($start = 0, $limit = 10) {
+ if ($start < 0) {
+ $start = 0;
+ }
+
+ if ($limit < 1) {
+ $limit = 10;
+ }
+
+ $query = $this->db->query("SELECT * FROM `" . DB_PREFIX . "fraud_ip` ORDER BY `ip` ASC LIMIT " . (int)$start . "," . (int)$limit);
+
+ return $query->rows;
+ }
+
+ public function getTotalIps() {
+ $query = $this->db->query("SELECT COUNT(*) AS total FROM `" . DB_PREFIX . "fraud_ip`");
+
+ return $query->row['total'];
+ }
+
+ public function getTotalIpsByIp($ip) {
+ $query = $this->db->query("SELECT COUNT(*) AS total FROM `" . DB_PREFIX . "fraud_ip` WHERE ip = '" . $this->db->escape($ip) . "'");
+
+ return $query->row['total'];
+ }
+}
diff --git a/public/admin/model/extension/fraud/maxmind.php b/public/admin/model/extension/fraud/maxmind.php
new file mode 100644
index 0000000..ad2134f
--- /dev/null
+++ b/public/admin/model/extension/fraud/maxmind.php
@@ -0,0 +1,73 @@
+<?php
+class ModelExtensionFraudMaxMind extends Model {
+ public function install() {
+ $this->db->query("
+ CREATE TABLE IF NOT EXISTS `" . DB_PREFIX . "maxmind` (
+ `order_id` int(11) NOT NULL,
+ `customer_id` int(11) NOT NULL,
+ `country_match` varchar(3) NOT NULL,
+ `country_code` varchar(2) NOT NULL,
+ `high_risk_country` varchar(3) NOT NULL,
+ `distance` int(11) NOT NULL,
+ `ip_region` varchar(255) NOT NULL,
+ `ip_city` varchar(255) NOT NULL,
+ `ip_latitude` decimal(10,6) NOT NULL,
+ `ip_longitude` decimal(10,6) NOT NULL,
+ `ip_isp` varchar(255) NOT NULL,
+ `ip_org` varchar(255) NOT NULL,
+ `ip_asnum` int(11) NOT NULL,
+ `ip_user_type` varchar(255) NOT NULL,
+ `ip_country_confidence` varchar(3) NOT NULL,
+ `ip_region_confidence` varchar(3) NOT NULL,
+ `ip_city_confidence` varchar(3) NOT NULL,
+ `ip_postal_confidence` varchar(3) NOT NULL,
+ `ip_postal_code` varchar(10) NOT NULL,
+ `ip_accuracy_radius` int(11) NOT NULL,
+ `ip_net_speed_cell` varchar(255) NOT NULL,
+ `ip_metro_code` int(3) NOT NULL,
+ `ip_area_code` int(3) NOT NULL,
+ `ip_time_zone` varchar(255) NOT NULL,
+ `ip_region_name` varchar(255) NOT NULL,
+ `ip_domain` varchar(255) NOT NULL,
+ `ip_country_name` varchar(255) NOT NULL,
+ `ip_continent_code` varchar(2) NOT NULL,
+ `ip_corporate_proxy` varchar(3) NOT NULL,
+ `anonymous_proxy` varchar(3) NOT NULL,
+ `proxy_score` int(3) NOT NULL,
+ `is_trans_proxy` varchar(3) NOT NULL,
+ `free_mail` varchar(3) NOT NULL,
+ `carder_email` varchar(3) NOT NULL,
+ `high_risk_username` varchar(3) NOT NULL,
+ `high_risk_password` varchar(3) NOT NULL,
+ `bin_match` varchar(10) NOT NULL,
+ `bin_country` varchar(2) NOT NULL,
+ `bin_name_match` varchar(3) NOT NULL,
+ `bin_name` varchar(255) NOT NULL,
+ `bin_phone_match` varchar(3) NOT NULL,
+ `bin_phone` varchar(32) NOT NULL,
+ `customer_phone_in_billing_location` varchar(8) NOT NULL,
+ `ship_forward` varchar(3) NOT NULL,
+ `city_postal_match` varchar(3) NOT NULL,
+ `ship_city_postal_match` varchar(3) NOT NULL,
+ `score` decimal(10,5) NOT NULL,
+ `explanation` text NOT NULL,
+ `risk_score` decimal(10,5) NOT NULL,
+ `queries_remaining` int(11) NOT NULL,
+ `maxmind_id` varchar(8) NOT NULL,
+ `error` text NOT NULL,
+ `date_added` datetime NOT NULL,
+ PRIMARY KEY (`order_id`)
+ ) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_general_ci;
+ ");
+ }
+
+ public function uninstall() {
+ $this->db->query("DROP TABLE IF EXISTS `" . DB_PREFIX . "maxmind`");
+ }
+
+ public function getOrder($order_id) {
+ $query = $this->db->query("SELECT * FROM `" . DB_PREFIX . "maxmind` WHERE order_id = '" . (int)$order_id . "'");
+
+ return $query->row;
+ }
+} \ No newline at end of file
diff --git a/public/admin/model/extension/openbay/amazon.php b/public/admin/model/extension/openbay/amazon.php
new file mode 100644
index 0000000..a323ab9
--- /dev/null
+++ b/public/admin/model/extension/openbay/amazon.php
@@ -0,0 +1,741 @@
+<?php
+class ModelExtensionOpenBayAmazon extends Model {
+ public function install() {
+ $this->load->model('setting/event');
+
+ $this->model_setting_event->addEvent('openbay_amazon_add_order', 'catalog/model/checkout/order/addOrderHistory/after', 'extension/openbay/amazon/eventAddOrderHistory');
+
+ $this->db->query("
+ CREATE TABLE IF NOT EXISTS `" . DB_PREFIX . "amazon_order` (
+ `order_id` int(11) NOT NULL ,
+ `amazon_order_id` char(19) NOT NULL ,
+ `courier_id` varchar(255) NOT NULL ,
+ `courier_other` tinyint(1) NOT NULL,
+ `tracking_no` varchar(255) NOT NULL ,
+ PRIMARY KEY (`order_id`, `amazon_order_id`)
+ ) DEFAULT COLLATE=utf8_general_ci;");
+
+ $this->db->query("
+ CREATE TABLE IF NOT EXISTS `" . DB_PREFIX . "amazon_order_product` (
+ `order_product_id` int(11) NOT NULL ,
+ `amazon_order_item_id` varchar(255) NOT NULL,
+ PRIMARY KEY(`order_product_id`, `amazon_order_item_id`)
+ );");
+
+ $this->db->query("
+ CREATE TABLE IF NOT EXISTS `" . DB_PREFIX . "amazon_product_unshipped` (
+ `order_id` int(11) NOT NULL,
+ `product_id` int(11) NOT NULL,
+ `quantity` int(11) NOT NULL DEFAULT '0',
+ PRIMARY KEY (`order_id`,`product_id`)
+ ) DEFAULT COLLATE=utf8_general_ci;");
+
+ $this->db->query("
+ CREATE TABLE IF NOT EXISTS `" . DB_PREFIX . "amazon_product` (
+ `version` int(11) NOT NULL DEFAULT 2,
+ `product_id` int(11) NOT NULL ,
+ `category` varchar(255) NOT NULL ,
+ `sku` varchar(255) NOT NULL ,
+ `insertion_id` varchar(255) NOT NULL ,
+ `data` text NOT NULL ,
+ `status` enum('saved','uploaded','ok','error') NOT NULL ,
+ `price` decimal(15,4) NOT NULL COMMENT 'Price on Amazon' ,
+ `var` char(100) NOT NULL DEFAULT '',
+ `marketplaces` text NOT NULL ,
+ `messages` text NOT NULL,
+ PRIMARY KEY (`product_id`, `var`)
+ );");
+
+ $this->db->query("
+ CREATE TABLE IF NOT EXISTS `" . DB_PREFIX . "amazon_product_error` (
+ `error_id` int(11) NOT NULL AUTO_INCREMENT,
+ `sku` varchar(255) NOT NULL ,
+ `insertion_id` varchar(255) NOT NULL ,
+ `error_code` int(11) NOT NULL ,
+ `message` text NOT NULL ,
+ PRIMARY KEY (`error_id`)
+ );");
+
+ $this->db->query("
+ CREATE TABLE IF NOT EXISTS `" . DB_PREFIX . "amazon_product_link` (
+ `id` int(11) NOT NULL AUTO_INCREMENT,
+ `amazon_sku` varchar(255) NOT NULL,
+ `var` char(100) NOT NULL DEFAULT '',
+ `product_id` int(11) NOT NULL,
+ PRIMARY KEY (`id`)
+ ) DEFAULT COLLATE=utf8_general_ci;");
+
+ $this->db->query("
+ CREATE TABLE IF NOT EXISTS `" . DB_PREFIX . "amazon_product_search` (
+ `product_id` int(11) NOT NULL,
+ `marketplace` enum('uk','de','es','it','fr') NOT NULL,
+ `status` enum('searching','finished') NOT NULL,
+ `matches` int(11) DEFAULT NULL,
+ `data` text,
+ PRIMARY KEY (`product_id`,`marketplace`)
+ ) DEFAULT COLLATE=utf8_general_ci;");
+
+ $this->db->query("
+ CREATE TABLE IF NOT EXISTS `" . DB_PREFIX . "amazon_listing_report` (
+ `marketplace` enum('uk','de','fr','es','it') NOT NULL,
+ `sku` varchar(255) NOT NULL,
+ `quantity` int(10) unsigned NOT NULL,
+ `asin` varchar(255) NOT NULL,
+ `price` decimal(10,4) NOT NULL,
+ PRIMARY KEY (`marketplace`,`sku`)
+ ) DEFAULT COLLATE=utf8_general_ci;");
+ }
+
+ public function uninstall() {
+ $this->db->query("DROP TABLE IF EXISTS `" . DB_PREFIX . "amazon_order`");
+ $this->db->query("DROP TABLE IF EXISTS `" . DB_PREFIX . "amazon_order_product`");
+ $this->db->query("DROP TABLE IF EXISTS `" . DB_PREFIX . "amazon_product2`");
+ $this->db->query("DROP TABLE IF EXISTS `" . DB_PREFIX . "amazon_product`");
+ $this->db->query("DROP TABLE IF EXISTS `" . DB_PREFIX . "amazon_product_link`");
+ $this->db->query("DROP TABLE IF EXISTS `" . DB_PREFIX . "amazon_product_unshipped`");
+ $this->db->query("DROP TABLE IF EXISTS `" . DB_PREFIX . "amazon_product_error`");
+ $this->db->query("DROP TABLE IF EXISTS `" . DB_PREFIX . "amazon_process`");
+ $this->db->query("DROP TABLE IF EXISTS `" . DB_PREFIX . "amazon_product_unshipped`");
+ $this->db->query("DROP TABLE IF EXISTS `" . DB_PREFIX . "amazon_product_search`");
+ $this->db->query("DROP TABLE IF EXISTS `" . DB_PREFIX . "amazon_listing_report`");
+
+ $this->db->query("DELETE FROM `" . DB_PREFIX . "setting` WHERE `code` = 'openbay_amazon'");
+
+ $this->load->model('setting/event');
+ $this->model_setting_event->deleteEventByCode('openbay_amazon_add_order');
+ }
+
+ public function patch() {
+ if ($this->config->get('openbay_amazon_status') == 1) {
+
+ }
+ }
+
+ public function verifyConfig($data) {
+ $log = new Log('amazon.log');
+
+ $request_xml = new SimpleXMLElement("<Request></Request>");
+ $request_xml->addChild("ResponseURL", HTTP_CATALOG . 'index.php?route=extension/openbay/amazon/order');
+
+ $marketplace_ids = $request_xml->addChild("MarketplaceIDs");
+
+ foreach ($data['openbay_amazon_orders_marketplace_ids'] as $marketplace_id) {
+ $marketplace_ids->addChild("MarketplaceID", $marketplace_id);
+ }
+
+ $response = $this->openbay->amazon->call('order/scheduleOrders', $request_xml->asXML(), false);
+
+ libxml_use_internal_errors(true);
+ $response_xml = simplexml_load_string($response);
+ libxml_use_internal_errors(false);
+
+ if ($response_xml && $response_xml->Status == '0') {
+ $log->write('Scheduling orders call was successful');
+ return true;
+ }
+
+ $log->write('Failed to schedule orders. Response: ' . $response);
+
+ return false;
+ }
+
+ public function saveProduct($product_id, $data_array) {
+ if (isset($data_array['fields']['item-price'])) {
+ $price = $data_array['fields']['item-price'];
+ } else if (isset($data_array['fields']['price'])) {
+ $price = $data_array['fields']['price'];
+ } else if (isset($data_array['fields']['StandardPrice'])) {
+ $price = $data_array['fields']['StandardPrice'];
+ } else {
+ $price = 0;
+ }
+
+ $category = (isset($data_array['category'])) ? $data_array['category'] : "";
+ $sku = (isset($data_array['fields']['sku'])) ? $data_array['fields']['sku'] : "";
+ if (isset($data_array['fields']['sku'])) {
+ $sku = $data_array['fields']['sku'];
+ } else if (isset($data_array['fields']['SKU'])) {
+ $sku = $data_array['fields']['SKU'];
+ }
+
+ $var = isset($data_array['optionVar']) ? $data_array['optionVar'] : '';
+
+ $marketplaces = isset($data_array['marketplace_ids']) ? serialize($data_array['marketplace_ids']) : serialize(array());
+
+ $data_encoded = json_encode(array('fields' => $data_array['fields']));
+
+ $this->db->query("
+ REPLACE INTO `" . DB_PREFIX . "amazon_product`
+ SET `product_id` = '" . (int)$product_id . "',
+ `sku` = '" . $this->db->escape($sku) . "',
+ `category` = '" . $this->db->escape($category) . "',
+ `data` = '" . $this->db->escape($data_encoded) . "',
+ `status` = 'saved',
+ `insertion_id` = '',
+ `price` = '" . $price . "',
+ `var` = '" . $this->db->escape($var) . "',
+ `marketplaces` = '" . $this->db->escape($marketplaces) . "'");
+ }
+
+ public function deleteSaved($product_id, $var = '') {
+ $this->db->query("DELETE FROM `" . DB_PREFIX . "amazon_product`
+ WHERE `product_id` = '" . (int)$product_id . "' AND `var` = '" . $this->db->escape($var) . "'");
+ }
+
+ public function getSavedProducts() {
+ return $this->db->query("
+ SELECT `ap`.`status`, `ap`.`product_id`, `ap`.`sku` as `amazon_sku`, `pd`.`name` as `product_name`, `p`.`model` as `product_model`, `p`.`sku` as `product_sku`, `ap`.`var` as `var`
+ FROM `" . DB_PREFIX . "amazon_product` as `ap`
+ LEFT JOIN `" . DB_PREFIX . "product_description` as `pd`
+ ON `ap`.`product_id` = `pd`.`product_id`
+ LEFT JOIN `" . DB_PREFIX . "product` as `p`
+ ON `ap`.`product_id` = `p`.`product_id`
+ WHERE `ap`.`status` = 'saved'
+ AND `pd`.`language_id` = '" . (int)$this->config->get('config_language_id') . "'")->rows;
+ }
+
+ public function getSavedProductsData() {
+ return $this->db->query("
+ SELECT * FROM `" . DB_PREFIX . "amazon_product`
+ WHERE `status` = 'saved' AND `version` = 2")->rows;
+ }
+
+ public function getProduct($product_id, $var = '') {
+ return $this->db->query("
+ SELECT * FROM `" . DB_PREFIX . "amazon_product`
+ WHERE `product_id` = '" . (int)$product_id . "' AND `var` = '" . $this->db->escape($var) . "' AND `version` = 2")->row;
+ }
+
+ public function getProductCategory($product_id, $var = '') {
+ $row = $this->db->query("
+ SELECT `category` FROM `" . DB_PREFIX . "amazon_product`
+ WHERE `product_id` = '" . (int)$product_id . "' AND `var` = '" . $this->db->escape($var) . "' AND `version` = 2")->row;
+ if (isset($row['category'])) {
+ return $row['category'];
+ } else {
+ return "";
+ }
+ }
+
+ public function setProductUploaded($product_id, $insertion_id, $var = '') {
+ $this->db->query(
+ "UPDATE `" . DB_PREFIX . "amazon_product`
+ SET `status` = 'uploaded', `insertion_id` = '" . $this->db->escape($insertion_id) . "'
+ WHERE `product_id` = '" . (int)$product_id . "' AND `var` = '" . $this->db->escape($var) . "' AND `version` = 2");
+ }
+
+ public function resetUploaded($insertion_id) {
+ $this->db->query(
+ "UPDATE `" . DB_PREFIX . "amazon_product`
+ SET `status` = 'saved', `insertion_id` = ''
+ WHERE `insertion_id` = '" . $this->db->escape($insertion_id) . "' AND `version` = 2");
+ }
+
+ public function getProductStatus($product_id) {
+
+ $rows_uploaded = $this->db->query("
+ SELECT COUNT(*) count
+ FROM `" . DB_PREFIX . "amazon_product`
+ WHERE `product_id` = '" . (int)$product_id . "' AND status = 'uploaded'")->row;
+ $rows_uploaded = $rows_uploaded['count'];
+
+ $rows_ok = $this->db->query("
+ SELECT COUNT(*) count
+ FROM `" . DB_PREFIX . "amazon_product`
+ WHERE `product_id` = '" . (int)$product_id . "' AND status = 'ok'")->row;
+ $rows_ok = $rows_ok['count'];
+
+ $rows_error = $this->db->query("
+ SELECT COUNT(*) count
+ FROM `" . DB_PREFIX . "amazon_product`
+ WHERE `product_id` = '" . (int)$product_id . "' AND status = 'error'")->row;
+ $rows_error = $rows_error['count'];
+
+ $rows_saved = $this->db->query("
+ SELECT COUNT(*) count
+ FROM `" . DB_PREFIX . "amazon_product`
+ WHERE `product_id` = '" . (int)$product_id . "' AND status = 'saved'")->row;
+ $rows_saved = $rows_saved['count'];
+
+ $rows_total = $rows_uploaded + $rows_ok + $rows_error + $rows_saved;
+
+ $links = $this->db->query("
+ SELECT COUNT(*) as count
+ FROM `" . DB_PREFIX . "amazon_product_link`
+ WHERE `product_id` = '" . (int)$product_id . "'")->row;
+ $links = $links['count'];
+
+ if ($rows_total === 0 && $links > 0) {
+ return 'linked';
+ } else if ($rows_total == 0) {
+ return false;
+ }
+
+ if ($rows_uploaded > 0) {
+ return 'processing';
+ }
+
+ if ($rows_uploaded == 0 && $rows_ok > 0 && $rows_error == 0) {
+ return 'ok';
+ }
+
+ if ($rows_saved > 0) {
+ return 'saved';
+ }
+
+ if ($rows_uploaded == 0 && $rows_error > 0 && $rows_ok == 0) {
+ $quick = $this->db->query("SELECT * FROM `" . DB_PREFIX . "amazon_product` WHERE `product_id` = " . (int)$product_id . " AND `version` = 3")->row;
+
+ if ($quick) {
+ return 'error_quick';
+ } else {
+ return 'error_advanced';
+ }
+ } else {
+ return 'error_few';
+ }
+
+ return false;
+ }
+
+ public function getProductErrors($product_id, $version = 2) {
+ if ($version == 3) {
+ $message_row = $this->db->query("SELECT `messages` FROM `" . DB_PREFIX . "amazon_product` WHERE `product_id` = '" . (int)$product_id . "' AND `version` = 3")->row;
+
+ return json_decode($message_row['messages']);
+ }
+
+ $result = array();
+
+ $insertion_rows = $this->db->query("SELECT `sku`, `insertion_id` FROM `" . DB_PREFIX . "amazon_product` WHERE `product_id` = '" . (int)$product_id . "' AND `version` = 2")->rows;
+
+ if (!empty($insertion_rows)) {
+ foreach($insertion_rows as $insertion_row) {
+ $error_rows = $this->db->query("SELECT * FROM `" . DB_PREFIX . "amazon_product_error` WHERE `sku` = '" . $this->db->escape($insertion_row['sku']) . "' AND `insertion_id` = '" . $this->db->escape($insertion_row['insertion_id']) . "'")->rows;
+
+ foreach($error_rows as $error_row) {
+ $result[] = $error_row;
+ }
+ }
+ }
+ return $result;
+ }
+
+ public function getProductsWithErrors() {
+ return $this->db->query("
+ SELECT `product_id`, `sku` FROM `" . DB_PREFIX . "amazon_product`
+ WHERE `status` = 'error' AND `version` = 2")->rows;
+ }
+
+ public function deleteProduct($product_id) {
+ $this->db->query(
+ "DELETE FROM `" . DB_PREFIX . "amazon_product`
+ WHERE `product_id` = '" . (int)$product_id . "'");
+ }
+
+ public function linkProduct($amazon_sku, $product_id, $var = '') {
+ $count = $this->db->query("SELECT COUNT(*) as `count` FROM `" . DB_PREFIX . "amazon_product_link` WHERE `product_id` = '" . (int)$product_id . "' AND `amazon_sku` = '" . $this->db->escape($amazon_sku) . "' AND `var` = '" . $this->db->escape($var) . "' LIMIT 1")->row;
+
+ if ($count['count'] == 0) {
+ $this->db->query("INSERT INTO `" . DB_PREFIX . "amazon_product_link` SET `product_id` = '" . (int)$product_id . "', `amazon_sku` = '" . $this->db->escape($amazon_sku) . "', `var` = '" . $this->db->escape($var) . "'");
+ }
+ }
+
+ public function removeProductLink($amazon_sku) {
+ $this->db->query(
+ "DELETE FROM `" . DB_PREFIX . "amazon_product_link`
+ WHERE `amazon_sku` = '" . $this->db->escape($amazon_sku) . "'");
+ }
+
+ public function removeAdvancedErrors($product_id) {
+ $product_rows = $this->db->query("
+ SELECT `insertion_id` FROM `" . DB_PREFIX . "amazon_product`
+ WHERE `product_id` = '" . (int)$product_id . "' AND `version` = 2")->rows;
+
+ foreach ($product_rows as $product) {
+ $this->db->query(
+ "DELETE FROM `" . DB_PREFIX . "amazon_product_error`
+ WHERE `insertion_id` = '" . $this->db->escape($product['insertion_id']) . "'");
+ }
+
+ $this->db->query(
+ "UPDATE `" . DB_PREFIX . "amazon_product`
+ SET `status` = 'saved', `insertion_id` = ''
+ WHERE `product_id` = '" . (int)$product_id . "' AND `status` = 'error' AND `version` = 2");
+ }
+
+ public function getProductLinks($product_id = 'all') {
+ $query = "
+ SELECT `apl`.`product_id`, `pd`.`name` as `product_name`, `p`.`model`, `apl`.`amazon_sku`, `p`.`sku`, `apl`.`var`, '' as `combination`
+ FROM `" . DB_PREFIX . "amazon_product_link` as `apl`
+ LEFT JOIN `" . DB_PREFIX . "product_description` as `pd`
+ ON `apl`.`product_id` = `pd`.`product_id`
+ LEFT JOIN `" . DB_PREFIX . "product` as `p`
+ ON `apl`.`product_id` = `p`.`product_id`";
+
+ if ($product_id != 'all') {
+ $query .= " WHERE `apl`.`product_id` = '" . (int)$product_id . "' AND `pd`.`language_id` = '" . (int)$this->config->get('config_language_id') . "'";
+ } else {
+ $query .= "WHERE `pd`.`language_id` = '" . (int)$this->config->get('config_language_id') . "'";
+ }
+
+ $product_links = $this->db->query($query)->rows;
+
+ if ($this->openbay->addonLoad('openstock')) {
+ $this->load->model('extension/module/openstock');
+ $this->load->model('tool/image');
+
+ foreach ($product_links as $key => $product_link) {
+ $variants = $this->model_setting_module_openstock->getVariants($product_link['product_id']);
+
+ if (!empty($variants)) {
+ foreach($variants as $variant) {
+ if ($variant['sku'] == $product_link['var']) {
+ $product_links[$key]['combination'] = $variant['combination'];
+ break;
+ }
+ }
+ }
+ }
+
+ return $product_links;
+ } else {
+ return $product_links;
+ }
+ }
+
+ public function getUnlinkedProducts() {
+ if ($this->openbay->addonLoad('openstock')) {
+ $rows = $this->db->query("
+ SELECT `p`.`product_id`, `p`.`model`, `p`.`sku`, `pd`.`name` as `product_name`, '' as `var`, '' as `combination`, `p`.`has_option`
+ FROM `" . DB_PREFIX . "product` as `p`
+ LEFT JOIN `" . DB_PREFIX . "product_description` as `pd`
+ ON `p`.`product_id` = `pd`.`product_id`
+ AND `pd`.`language_id` = '" . (int)$this->config->get('config_language_id') . "'")->rows;
+
+ $result = array();
+ $this->load->model('extension/module/openstock');
+ $this->load->model('tool/image');
+ foreach($rows as $row) {
+ if ($row['has_option'] == 1) {
+ $stock_opts = $this->model_setting_module_openstock->getVariants($row['product_id']);
+ foreach($stock_opts as $opt) {
+ if ($this->productLinkExists($row['product_id'], $opt['sku'])) {
+ continue;
+ }
+ $row['combination'] = $opt['combination'];
+ $row['sku'] = $opt['sku'];
+ $result[] = $row;
+ }
+ } else {
+ if (!$this->productLinkExists($row['product_id'], $row['sku'])) {
+ $result[] = $row;
+ }
+ }
+ }
+ } else {
+ $result = $this->db->query("
+ SELECT `p`.`product_id`, `p`.`model`, `p`.`sku`, `pd`.`name` as `product_name`, '' as `var`, '' as `combination`
+ FROM `" . DB_PREFIX . "product` as `p`
+ LEFT JOIN `" . DB_PREFIX . "product_description` as `pd`
+ ON `p`.`product_id` = `pd`.`product_id`
+ LEFT JOIN `" . DB_PREFIX . "amazon_product_link` as `apl`
+ ON `apl`.`product_id` = `p`.`product_id`
+ WHERE `apl`.`amazon_sku` IS NULL
+ AND `pd`.`language_id` = '" . (int)$this->config->get('config_language_id') . "'")->rows;
+ }
+
+ return $result;
+ }
+
+ private function productLinkExists($product_id, $var) {
+ $link = $this->db->query("SELECT * FROM `" . DB_PREFIX . "amazon_product_link` WHERE `product_id` = " . (int)$product_id . " AND var = '" . $this->db->escape($var) . "'")->row;
+
+ if (empty($link)) {
+ return false;
+ } else {
+ return true;
+ }
+ }
+
+ public function getOrderStatusString($order_id) {
+ $row = $this->db->query("
+ SELECT `s`.`key`
+ FROM `" . DB_PREFIX . "order` `o`
+ JOIN `" . DB_PREFIX . "setting` `s` ON `o`.`order_id` = " . (int)$order_id . " AND `s`.`value` = `o`.`order_status_id`
+ WHERE `s`.`key` = 'openbay_amazon_order_status_shipped' OR `s`.`key` = 'openbay_amazon_order_status_canceled'
+ LIMIT 1")->row;
+
+ if (!isset($row['key']) || empty($row['key'])) {
+ return null;
+ }
+
+ $key = $row['key'];
+
+ switch ($key) {
+ case 'openbay_amazon_order_status_shipped':
+ $order_status = 'shipped';
+ break;
+ case 'openbay_amazon_order_status_canceled':
+ $order_status = 'canceled';
+ break;
+
+ default:
+ $order_status = null;
+ break;
+ }
+
+ return $order_status;
+ }
+
+ public function updateAmazonOrderTracking($order_id, $courier_id, $courier_from_list, $tracking_no) {
+ $this->db->query("UPDATE `" . DB_PREFIX . "amazon_order` SET `courier_id` = '" . $this->db->escape($courier_id) . "', `courier_other` = " . (int)!$courier_from_list . ", `tracking_no` = '" . $this->db->escape($tracking_no) . "' WHERE `order_id` = " . (int)$order_id . "");
+ }
+
+ public function getAmazonOrderId($order_id) {
+ $row = $this->db->query("
+ SELECT `amazon_order_id`
+ FROM `" . DB_PREFIX . "amazon_order`
+ WHERE `order_id` = " . (int)$order_id . "
+ LIMIT 1")->row;
+
+ if (isset($row['amazon_order_id']) && !empty($row['amazon_order_id'])) {
+ return $row['amazon_order_id'];
+ }
+
+ return null;
+ }
+
+ public function getAmazonOrderedProducts($order_id) {
+ return $this->db->query("
+ SELECT `aop`.`amazon_order_item_id`, `op`.`quantity`
+ FROM `" . DB_PREFIX . "amazon_order_product` `aop`
+ JOIN `" . DB_PREFIX . "order_product` `op` ON `op`.`order_product_id` = `aop`.`order_product_id`
+ AND `op`.`order_id` = " . (int)$order_id)->rows;
+ }
+
+ public function getProductQuantity($product_id, $var = '') {
+ $result = null;
+
+ if ($var !== '' && $this->openbay->addonLoad('openstock')) {
+ $this->load->model('tool/image');
+ $this->load->model('extension/module/openstock');
+ $option_stocks = $this->model_setting_module_openstock->getVariants($product_id);
+
+ $option = null;
+ foreach ($option_stocks as $option_iterator) {
+ if ($option_iterator['sku'] === $var) {
+ $option = $option_iterator;
+ break;
+ }
+ }
+
+ if ($option != null) {
+ $result = $option['stock'];
+ }
+ } else {
+ $this->load->model('catalog/product');
+ $product_info = $this->model_catalog_product->getProduct($product_id);
+
+ if (isset($product_info['quantity'])) {
+ $result = $product_info['quantity'];
+ }
+ }
+ return $result;
+ }
+
+ public function getProductSearchTotal($data = array()) {
+ $sql = "
+ SELECT COUNT(*) AS product_total
+ FROM " . DB_PREFIX . "product p
+ LEFT JOIN " . DB_PREFIX . "amazon_product_search aps ON p.product_id = aps.product_id AND aps.marketplace = '" . $this->db->escape($data['filter_marketplace']) . "'
+ LEFT JOIN " . DB_PREFIX . "amazon_product_link apl ON p.product_id = apl.product_id
+ LEFT JOIN " . DB_PREFIX . "amazon_product ap ON p.product_id = ap.product_id
+ WHERE apl.product_id IS NULL AND ap.product_id IS NULL ";
+
+ if (!empty($data['status'])) {
+ $sql .= " AND aps.status = '" . $this->db->escape($data['status']) . "'";
+ }
+
+ return $this->db->query($sql)->row['product_total'];
+ }
+
+ public function getProductSearch($data = array()) {
+ $sql = "
+ SELECT p.product_id, marketplace, aps.status, aps.data, aps.matches
+ FROM " . DB_PREFIX . "product p
+ LEFT JOIN " . DB_PREFIX . "amazon_product_search aps ON p.product_id = aps.product_id AND aps.marketplace = '" . $this->db->escape($data['filter_marketplace']) . "'
+ LEFT JOIN " . DB_PREFIX . "amazon_product_link apl ON p.product_id = apl.product_id
+ LEFT JOIN " . DB_PREFIX . "amazon_product ap ON p.product_id = ap.product_id
+ WHERE apl.product_id IS NULL AND ap.product_id IS NULL ";
+
+ if (!empty($data['status'])) {
+ $sql .= " AND aps.status = '" . $this->db->escape($data['status']) . "'";
+ }
+
+ $sql .= " LIMIT " . (int)$data['start'] . ", " . (int)$data['limit'];
+
+ $results = array();
+
+ $rows = $this->db->query($sql)->rows;
+
+ foreach ($rows as $row) {
+ $results[] = array(
+ 'product_id' => $row['product_id'],
+ 'marketplace' => $row['marketplace'],
+ 'status' => $row['status'],
+ 'matches' => $row['matches'],
+ 'data' => json_decode($row['data'], 1),
+ );
+ }
+
+ return $results;
+ }
+
+ public function updateAmazonSkusQuantities($skus) {
+ $sku_array = array();
+
+ foreach ($skus as $sku) {
+ $sku_array[] = "'" . $this->db->escape($sku) . "'";
+ }
+
+ if ($this->openbay->addonLoad('openstock')) {
+ $rows = $this->db->query("SELECT apl.amazon_sku, if (pov.product_id IS NULL, p.quantity, pov.stock) AS 'quantity' FROM " . DB_PREFIX . "amazon_product_link apl JOIN " . DB_PREFIX . "product p ON apl.product_id = p.product_id LEFT JOIN " . DB_PREFIX . "product_option_variant pov ON apl.product_id = pov.product_id AND apl.var = pov.sku WHERE apl.amazon_sku IN (" . implode(',', $sku_array) . ")")->rows;
+ } else {
+ $rows = $this->db->query("SELECT apl.amazon_sku, p.quantity FROM " . DB_PREFIX . "amazon_product_link apl JOIN " . DB_PREFIX . "product p ON apl.product_id = p.product_id WHERE apl.amazon_sku IN (" . implode(',', $sku_array) . ")")->rows;
+ }
+
+ $return = array();
+
+ foreach ($rows as $row) {
+ $return[$row['amazon_sku']] = $row['quantity'];
+ }
+
+ $this->openbay->amazon->updateQuantities($return);
+ }
+
+ public function deleteListingReports($marketplace) {
+ $this->db->query("DELETE FROM " . DB_PREFIX . "amazon_listing_report WHERE marketplace = '" . $this->db->escape($marketplace) . "'");
+ }
+
+ public function getTotalUnlinkedItemsFromReport($marketplace) {
+ if ($this->openbay->addonLoad('openstock')) {
+
+ $sql = "
+ SELECT alr.sku AS 'amazon_sku', alr.quantity AS 'amazon_quantity', alr.asin, alr.price AS 'amazon_price', oc_sku.product_id, pd.name, oc_sku.sku, oc_sku.var, oc_sku.quantity, oc_sku.pov_id
+ FROM " . DB_PREFIX . "amazon_listing_report alr
+ LEFT JOIN (
+ SELECT p.product_id, if (por.product_id IS NULL, p.sku, por.sku) AS 'sku', if (por.product_id IS NULL, NULL, por.sku) AS 'var', if (por.product_id IS NULL, p.quantity, por.stock) AS 'quantity', por.product_option_variant_id AS pov_id
+ FROM " . DB_PREFIX . "product p
+ LEFT JOIN " . DB_PREFIX . "product_option_variant por USING(product_id)
+ ) AS oc_sku ON alr.sku = oc_sku.sku
+ LEFT JOIN " . DB_PREFIX . "amazon_product_link apl ON (oc_sku.var IS NULL AND oc_sku.product_id = apl.product_id) OR (oc_sku.var IS NOT NULL AND oc_sku.product_id = apl.product_id AND oc_sku.var = apl.var)
+ LEFT JOIN " . DB_PREFIX . "product_description pd ON oc_sku.product_id = pd.product_id AND pd.language_id = " . (int)$this->config->get('config_language_id') . "
+ WHERE apl.product_id IS NULL AND alr.marketplace = '" . $this->db->escape($marketplace) . "'
+ ORDER BY alr.sku
+ ";
+
+ $result = $this->db->query($sql);
+ } else {
+ $result = $this->db->query("
+ SELECT alr.sku AS 'amazon_sku', alr.quantity AS 'amazon_quantity', alr.asin, alr.price AS 'amazon_price', oc_sku.product_id, pd.name, oc_sku.sku, oc_sku.var, oc_sku.quantity
+ FROM " . DB_PREFIX . "amazon_listing_report alr
+ LEFT JOIN (
+ SELECT p.product_id, p.sku, NULL AS 'var', p.quantity
+ FROM " . DB_PREFIX . "product p
+ ) AS oc_sku ON alr.sku = oc_sku.sku
+ LEFT JOIN " . DB_PREFIX . "amazon_product_link apl ON (oc_sku.var IS NULL AND oc_sku.product_id = apl.product_id) OR (oc_sku.var IS NOT NULL AND oc_sku.product_id = apl.product_id AND oc_sku.var = apl.var)
+ LEFT JOIN " . DB_PREFIX . "product_description pd ON oc_sku.product_id = pd.product_id AND pd.language_id = " . (int)$this->config->get('config_language_id') . "
+ WHERE apl.product_id IS NULL AND alr.marketplace = '" . $this->db->escape($marketplace) . "'
+ ORDER BY alr.sku
+ ");
+ }
+
+ return (int)$result->num_rows;
+ }
+
+ public function getUnlinkedItemsFromReport($marketplace, $limit = 100, $page = 1) {
+ $start = $limit * ($page - 1);
+
+ if ($this->openbay->addonLoad('openstock')) {
+ $this->load->model('extension/module/openstock');
+ $rows = $this->db->query("
+ SELECT alr.sku AS 'amazon_sku', alr.quantity AS 'amazon_quantity', alr.asin, alr.price AS 'amazon_price', oc_sku.product_id, pd.name, oc_sku.sku, oc_sku.var, oc_sku.quantity, oc_sku.pov_id
+ FROM " . DB_PREFIX . "amazon_listing_report alr
+ LEFT JOIN (
+ SELECT p.product_id, if (por.product_id IS NULL, p.sku, por.sku) AS 'sku', if (por.product_id IS NULL, NULL, por.sku) AS 'var', if (por.product_id IS NULL, p.quantity, por.stock) AS 'quantity', por.product_option_variant_id AS pov_id
+ FROM " . DB_PREFIX . "product p
+ LEFT JOIN " . DB_PREFIX . "product_option_variant por USING(product_id)
+ ) AS oc_sku ON alr.sku = oc_sku.sku
+ LEFT JOIN " . DB_PREFIX . "amazon_product_link apl ON (oc_sku.var IS NULL AND oc_sku.product_id = apl.product_id) OR (oc_sku.var IS NOT NULL AND oc_sku.product_id = apl.product_id AND oc_sku.var = apl.var)
+ LEFT JOIN " . DB_PREFIX . "product_description pd ON oc_sku.product_id = pd.product_id AND pd.language_id = " . (int)$this->config->get('config_language_id') . "
+ WHERE apl.product_id IS NULL AND alr.marketplace = '" . $this->db->escape($marketplace) . "'
+ ORDER BY alr.sku
+ LIMIT " . (int)$start . "," . (int)$limit)->rows;
+ } else {
+ $rows = $this->db->query("
+ SELECT alr.sku AS 'amazon_sku', alr.quantity AS 'amazon_quantity', alr.asin, alr.price AS 'amazon_price', oc_sku.product_id, pd.name, oc_sku.sku, oc_sku.var, oc_sku.quantity
+ FROM " . DB_PREFIX . "amazon_listing_report alr
+ LEFT JOIN (
+ SELECT p.product_id, p.sku, NULL AS 'var', p.quantity
+ FROM " . DB_PREFIX . "product p
+ ) AS oc_sku ON alr.sku = oc_sku.sku
+ LEFT JOIN " . DB_PREFIX . "amazon_product_link apl ON (oc_sku.var IS NULL AND oc_sku.product_id = apl.product_id) OR (oc_sku.var IS NOT NULL AND oc_sku.product_id = apl.product_id AND oc_sku.var = apl.var)
+ LEFT JOIN " . DB_PREFIX . "product_description pd ON oc_sku.product_id = pd.product_id AND pd.language_id = " . (int)$this->config->get('config_language_id') . "
+ WHERE apl.product_id IS NULL AND alr.marketplace = '" . $this->db->escape($marketplace) . "'
+ ORDER BY alr.sku
+ LIMIT " . (int)$start . "," . (int)$limit)->rows;
+ }
+
+ $products = array();
+
+ foreach ($rows as $row) {
+ $combinations = array();
+
+ if (isset($row['pov_id']) && !empty($row['pov_id'])) {
+ $variants = (isset($row['pov_id']) ? $this->model_setting_module_openstock->getVariant($row['pov_id']) : '');
+
+ foreach ($variants as $variant) {
+ $combinations[] = $variant['option_value_name'];
+ }
+ }
+
+ $products[] = array(
+ 'product_id' => $row['product_id'],
+ 'name' => $row['name'],
+ 'sku' => $row['sku'],
+ 'var' => $row['var'],
+ 'quantity' => $row['quantity'],
+ 'amazon_sku' => $row['amazon_sku'],
+ 'amazon_quantity' => $row['amazon_quantity'],
+ 'amazon_price' => number_format($row['amazon_price'], 2, '.', ''),
+ 'asin' => $row['asin'],
+ 'combination' => implode(' > ', $combinations),
+ );
+ }
+
+ return $products;
+ }
+
+ public function getAsinLink($asin, $marketplace) {
+ switch ($marketplace) {
+ case 'uk':
+ $link = 'https://www.amazon.co.uk/dp/' . $asin . '/';
+ break;
+ case 'de':
+ $link = 'https://www.amazon.de/dp/' . $asin . '/';
+ break;
+ case 'fr':
+ $link = 'https://www.amazon.fr/dp/' . $asin . '/';
+ break;
+ case 'it':
+ $link = 'https://www.amazon.it/dp/' . $asin . '/';
+ break;
+ case 'es':
+ $link = 'https://www.amazon.es/dp/' . $asin . '/';
+ break;
+ }
+
+ return $link;
+ }
+}
diff --git a/public/admin/model/extension/openbay/amazon_listing.php b/public/admin/model/extension/openbay/amazon_listing.php
new file mode 100644
index 0000000..a4ad286
--- /dev/null
+++ b/public/admin/model/extension/openbay/amazon_listing.php
@@ -0,0 +1,231 @@
+<?php
+class ModelExtensionOpenBayAmazonListing extends Model {
+ private $tabs = array();
+
+ public function search($search_string, $marketplace) {
+ $search_params = array(
+ 'search_string' => $search_string,
+ 'marketplace' => $marketplace,
+ );
+
+ $results = json_decode($this->openbay->amazon->call('productv3/search', $search_params), 1);
+
+ $products = array();
+
+ if (!empty($results)) {
+ foreach ($results['Products'] as $result) {
+ if ($result['price']['amount'] && $result['price']['currency']) {
+ $price = $result['price']['amount'] . ' ' . $result['price']['currency'];
+ } else {
+ $price = '-';
+ }
+
+ $link = '';
+
+ switch ($marketplace) {
+ case 'uk':
+ $link = 'https://www.amazon.co.uk/dp/' . $result['asin'] . '/';
+ break;
+ case 'de':
+ $link = 'https://www.amazon.de/dp/' . $result['asin'] . '/';
+ break;
+ case 'fr':
+ $link = 'https://www.amazon.fr/dp/' . $result['asin'] . '/';
+ break;
+ case 'it':
+ $link = 'https://www.amazon.it/dp/' . $result['asin'] . '/';
+ break;
+ case 'es':
+ $link = 'https://www.amazon.es/dp/' . $result['asin'] . '/';
+ break;
+ }
+
+ $products[] = array(
+ 'name' => $result['name'],
+ 'asin' => $result['asin'],
+ 'image' => $result['image'],
+ 'price' => $price,
+ 'link' => $link,
+ );
+ }
+ }
+
+ return $products;
+ }
+
+ public function getProductByAsin($asin, $market) {
+ $data = array(
+ 'asin' => $asin,
+ 'marketplace' => $market,
+ );
+
+ $results = json_decode($this->openbay->amazon->call('productv3/getProduct', $data), 1);
+
+ return $results;
+ }
+
+ public function getBestPrice($asin, $condition, $marketplace) {
+ $search_params = array(
+ 'asin' => $asin,
+ 'condition' => $condition,
+ 'marketplace' => $marketplace,
+ );
+
+ $best_price = '';
+
+ $result = json_decode($this->openbay->amazon->call('productv3/getPrice', $search_params), 1);
+
+ if (isset($result['Price']['Amount']) && $result['Price']['Currency'] && $this->currency->has($result['Price']['Currency'])) {
+ $best_price['amount'] = number_format($this->currency->convert($result['Price']['Amount'], $result['Price']['Currency'], $this->config->get('config_currency')), 2, '.', '');
+ $best_price['shipping'] = number_format($this->currency->convert($result['Price']['Shipping'], $result['Price']['Currency'], $this->config->get('config_currency')), 2, '.', '');
+ $best_price['currency'] = $result['Price']['Currency'];
+ }
+
+ return $best_price;
+ }
+
+ public function simpleListing($data) {
+ $request = array(
+ 'asin' => $data['asin'],
+ 'sku' => $data['sku'],
+ 'quantity' => $data['quantity'],
+ 'price' => $data['price'],
+ 'sale' => array(
+ 'price' => $data['sale_price'],
+ 'from' => $data['sale_from'],
+ 'to' => $data['sale_to'],
+ ),
+ 'condition' => $data['condition'],
+ 'condition_note' => $data['condition_note'],
+ 'start_selling' => $data['start_selling'],
+ 'restock_date' => $data['restock_date'],
+ 'marketplace' => $data['marketplace'],
+ 'response_url' => HTTPS_CATALOG . 'index.php?route=extension/openbay/amazon/listing',
+ 'product_id' => $data['product_id'],
+ );
+
+ $response = $this->openbay->amazon->call('productv3/simpleListing', $request);
+ $response = json_decode($response);
+
+ if (empty($response)) {
+ return array(
+ 'status' => 0,
+ 'message' => 'Problem connecting OpenBay: API'
+ );
+ }
+
+ $response = (array)$response;
+
+ if (($response['status'] === 1)) {
+ $this->db->query("
+ REPLACE INTO `" . DB_PREFIX . "amazon_product`
+ SET `product_id` = " . (int)$data['product_id'] . ",
+ `status` = 'uploaded',
+ `marketplaces` = '" . $this->db->escape($data['marketplace']) . "',
+ `version` = 3,
+ `var` = ''
+ ");
+ }
+
+ return $response;
+ }
+
+ public function getBrowseNodes($request) {
+ return $this->openbay->amazon->call('productv3/getBrowseNodes', $request);
+ }
+
+ public function doBulkSearch($search_data) {
+ foreach ($search_data as $products) {
+ foreach ($products as $product) {
+ $this->db->query("
+ REPLACE INTO " . DB_PREFIX . "amazon_product_search (product_id, `status`, marketplace)
+ VALUES (" . (int)$product['product_id'] . ", 'searching', '" . $this->db->escape($product['marketplace']) . "')");
+ }
+ }
+
+ $request_data = array(
+ 'search' => $search_data,
+ 'response_url' => HTTPS_CATALOG . 'index.php?route=extension/openbay/amazon/search'
+ );
+
+ $this->openbay->amazon->call('productv3/bulkSearch', $request_data);
+ }
+
+ public function deleteSearchResults($marketplace, $product_ids) {
+ $imploded_ids = array();
+
+ foreach ($product_ids as $product_id) {
+ $imploded_ids[] = (int)$product_id;
+ }
+
+ $imploded_ids = implode(',', $imploded_ids);
+
+ $this->db->query("
+ DELETE FROM " . DB_PREFIX . "amazon_product_search
+ WHERE marketplace = '" . $this->db->escape($marketplace) . "' AND product_id IN ($imploded_ids)
+ ");
+ }
+
+ public function doBulkListing($data) {
+ $this->load->model('catalog/product');
+ $request = array();
+
+ $marketplace_mapping = array(
+ 'uk' => 'A1F83G8C2ARO7P',
+ 'de' => 'A1PA6795UKMFR9',
+ 'fr' => 'A13V1IB3VIYZZH',
+ 'it' => 'APJ6JRA9NG5V4',
+ 'es' => 'A1RKKUPIHCS9HS',
+ );
+
+ foreach($data['products'] as $product_id => $asin) {
+ $product = $this->model_catalog_product->getProduct($product_id);
+
+ if ($product) {
+ $price = $product['price'];
+
+ if ($this->config->get('openbay_amazon_listing_tax_added') && $this->config->get('openbay_amazon_listing_tax_added') > 0) {
+ $price += $price * ($this->config->get('openbay_amazon_listing_tax_added') / 100);
+ }
+
+ $request[] = array(
+ 'asin' => $asin,
+ 'sku' => $product['sku'],
+ 'quantity' => $product['quantity'],
+ 'price' => number_format($price, 2, '.', ''),
+ 'sale' => array(),
+ 'condition' => (isset($data['condition']) ? $data['condition'] : ''),
+ 'condition_note' => (isset($data['condition_note']) ? $data['condition_note'] : ''),
+ 'start_selling' => (isset($data['start_selling']) ? $data['start_selling'] : ''),
+ 'restock_date' => '',
+ 'marketplace' => $data['marketplace'],
+ 'response_url' => HTTPS_CATALOG . 'index.php?route=extension/openbay/amazon/listing',
+ 'product_id' => $product['product_id'],
+ );
+ }
+ }
+
+ if ($request) {
+ $response = $this->openbay->amazon->call('productv3/bulkListing', $request);
+
+ $response = json_decode($response, 1);
+
+ if ($response['status'] == 1) {
+ foreach ($request as $product) {
+ $this->db->query("
+ REPLACE INTO `" . DB_PREFIX . "amazon_product`
+ SET `product_id` = " . (int)$product['product_id'] . ",
+ `status` = 'uploaded',
+ `marketplaces` = '" . $this->db->escape($data['marketplace']) . "',
+ `version` = 3,
+ `var` = ''
+ ");
+ }
+
+ return true;
+ }
+ }
+
+ return false;
+ }
+} \ No newline at end of file
diff --git a/public/admin/model/extension/openbay/amazonus.php b/public/admin/model/extension/openbay/amazonus.php
new file mode 100644
index 0000000..ccc4a78
--- /dev/null
+++ b/public/admin/model/extension/openbay/amazonus.php
@@ -0,0 +1,720 @@
+<?php
+class ModelExtensionOpenBayAmazonus extends Model {
+ public function install() {
+ $this->load->model('setting/event');
+
+ $this->model_setting_event->addEvent('openbay_amazonus_add_order', 'catalog/model/checkout/order/addOrderHistory/after', 'extension/openbay/amazonus/eventAddOrderHistory');
+
+ $this->db->query("
+ CREATE TABLE IF NOT EXISTS `" . DB_PREFIX . "amazonus_order` (
+ `order_id` int(11) NOT NULL ,
+ `amazonus_order_id` char(19) NOT NULL ,
+ `courier_id` varchar(255) NOT NULL ,
+ `courier_other` tinyint(1) NOT NULL,
+ `tracking_no` varchar(255) NOT NULL ,
+ PRIMARY KEY (`order_id`, `amazonus_order_id`)
+ ) DEFAULT COLLATE=utf8_general_ci;");
+
+ $this->db->query("
+ CREATE TABLE IF NOT EXISTS `" . DB_PREFIX . "amazonus_order_product` (
+ `order_product_id` int(11) NOT NULL ,
+ `amazonus_order_item_id` varchar(255) NOT NULL,
+ PRIMARY KEY(`order_product_id`, `amazonus_order_item_id`)
+ );");
+
+ $this->db->query("
+ CREATE TABLE IF NOT EXISTS `" . DB_PREFIX . "amazonus_product_unshipped` (
+ `order_id` int(11) NOT NULL,
+ `product_id` int(11) NOT NULL,
+ `quantity` int(11) NOT NULL DEFAULT '0',
+ PRIMARY KEY (`order_id`,`product_id`)
+ ) DEFAULT COLLATE=utf8_general_ci;");
+
+ $this->db->query("
+ CREATE TABLE IF NOT EXISTS `" . DB_PREFIX . "amazonus_product` (
+ `version` int(11) NOT NULL DEFAULT 2,
+ `product_id` int(11) NOT NULL ,
+ `category` varchar(255) NOT NULL ,
+ `sku` varchar(255) NOT NULL ,
+ `insertion_id` varchar(255) NOT NULL ,
+ `data` text NOT NULL ,
+ `status` enum('saved','uploaded','ok','error') NOT NULL ,
+ `price` decimal(15,4) NOT NULL COMMENT 'Price on Amazonus' ,
+ `var` char(100) NOT NULL DEFAULT '',
+ `marketplaces` text NOT NULL ,
+ `messages` text NOT NULL,
+ PRIMARY KEY (`product_id`, `var`)
+ );");
+
+ $this->db->query("
+ CREATE TABLE IF NOT EXISTS `" . DB_PREFIX . "amazonus_product_error` (
+ `error_id` int(11) NOT NULL AUTO_INCREMENT,
+ `sku` varchar(255) NOT NULL ,
+ `insertion_id` varchar(255) NOT NULL ,
+ `error_code` int(11) NOT NULL ,
+ `message` text NOT NULL ,
+ PRIMARY KEY (`error_id`)
+ );");
+
+ $this->db->query("
+ CREATE TABLE IF NOT EXISTS `" . DB_PREFIX . "amazonus_product_link` (
+ `id` int(11) NOT NULL AUTO_INCREMENT,
+ `amazonus_sku` varchar(255) NOT NULL,
+ `var` char(100) NOT NULL DEFAULT '',
+ `product_id` int(11) NOT NULL,
+ PRIMARY KEY (`id`)
+ ) DEFAULT COLLATE=utf8_general_ci;");
+
+ $this->db->query("
+ CREATE TABLE IF NOT EXISTS `" . DB_PREFIX . "amazonus_product_search` (
+ `product_id` int(11) NOT NULL,
+ `status` enum('searching','finished') NOT NULL,
+ `matches` int(11) DEFAULT NULL,
+ `data` text,
+ PRIMARY KEY (`product_id`)
+ ) DEFAULT COLLATE=utf8_general_ci;");
+
+ $this->db->query("
+ CREATE TABLE IF NOT EXISTS`" . DB_PREFIX . "amazonus_listing_report` (
+ `sku` varchar(255) NOT NULL,
+ `quantity` int(10) unsigned NOT NULL,
+ `asin` varchar(255) NOT NULL,
+ `price` decimal(10,4) NOT NULL,
+ PRIMARY KEY (`sku`)
+ ) DEFAULT COLLATE=utf8_general_ci;
+ ");
+ }
+
+ public function uninstall() {
+ $this->db->query("DROP TABLE IF EXISTS `" . DB_PREFIX . "amazonus_order`");
+ $this->db->query("DROP TABLE IF EXISTS `" . DB_PREFIX . "amazonus_order_product`");
+ $this->db->query("DROP TABLE IF EXISTS `" . DB_PREFIX . "amazonus_product2`");
+ $this->db->query("DROP TABLE IF EXISTS `" . DB_PREFIX . "amazonus_product`");
+ $this->db->query("DROP TABLE IF EXISTS `" . DB_PREFIX . "amazonus_product_link`");
+ $this->db->query("DROP TABLE IF EXISTS `" . DB_PREFIX . "amazonus_product_unshipped`");
+ $this->db->query("DROP TABLE IF EXISTS `" . DB_PREFIX . "amazonus_product_error`");
+ $this->db->query("DROP TABLE IF EXISTS `" . DB_PREFIX . "amazonus_process`");
+ $this->db->query("DROP TABLE IF EXISTS `" . DB_PREFIX . "amazonus_product_search`");
+ $this->db->query("DROP TABLE IF EXISTS `" . DB_PREFIX . "amazonus_listing_report`");
+
+ $this->db->query("DELETE FROM `" . DB_PREFIX . "setting` WHERE `code` = 'openbay_amazonus'");
+
+ $this->load->model('setting/event');
+ $this->model_setting_event->deleteEventByCode('openbay_amazonus_add_order');
+ }
+
+ public function patch() {
+ if ($this->config->get('openbay_amazonus_status') == 1) {
+
+ }
+ }
+
+ public function verifyConfig($data) {
+ $log = new Log('amazonus.log');
+
+ $request_xml = new SimpleXMLElement("<Request></Request>");
+ $request_xml->addChild("ResponseURL", HTTP_CATALOG . 'index.php?route=extension/openbay/amazonus/order');
+
+ $response = $this->openbay->amazonus->call('order/scheduleOrders', $request_xml->asXML(), false);
+
+ libxml_use_internal_errors(true);
+ $response_xml = simplexml_load_string($response);
+ libxml_use_internal_errors(false);
+
+ if ($response_xml && $response_xml->Status == '0') {
+ $log->write('Scheduling orders call was successful');
+ return true;
+ }
+
+ $log->write('Failed to schedule orders. Response: ' . $response);
+
+ return false;
+ }
+
+ public function saveProduct($product_id, $data_array) {
+ if (isset($data_array['fields']['item-price'])) {
+ $price = $data_array['fields']['item-price'];
+ } else if (isset($data_array['fields']['price'])) {
+ $price = $data_array['fields']['price'];
+ } else if (isset($data_array['fields']['StandardPrice'])) {
+ $price = $data_array['fields']['StandardPrice'];
+ } else {
+ $price = 0;
+ }
+
+ $category = (isset($data_array['category'])) ? $data_array['category'] : "";
+ $sku = (isset($data_array['fields']['sku'])) ? $data_array['fields']['sku'] : "";
+ if (isset($data_array['fields']['sku'])) {
+ $sku = $data_array['fields']['sku'];
+ } else if (isset($data_array['fields']['SKU'])) {
+ $sku = $data_array['fields']['SKU'];
+ }
+
+ $var = isset($data_array['optionVar']) ? $data_array['optionVar'] : '';
+
+ $marketplaces = isset($data_array['marketplace_ids']) ? serialize($data_array['marketplace_ids']) : serialize(array());
+
+ $data_encoded = json_encode(array('fields' => $data_array['fields']));
+
+ $this->db->query("
+ REPLACE INTO `" . DB_PREFIX . "amazonus_product`
+ SET `product_id` = '" . (int)$product_id . "',
+ `sku` = '" . $this->db->escape($sku) . "',
+ `category` = '" . $this->db->escape($category) . "',
+ `data` = '" . $this->db->escape($data_encoded) . "',
+ `status` = 'saved',
+ `insertion_id` = '',
+ `price` = '" . $price . "',
+ `var` = '" . $this->db->escape($var) . "',
+ `marketplaces` = '" . $this->db->escape($marketplaces) . "'");
+ }
+
+ public function deleteSaved($product_id, $var = '') {
+ $this->db->query("DELETE FROM `" . DB_PREFIX . "amazonus_product`
+ WHERE `product_id` = '" . (int)$product_id . "' AND `var` = '" . $this->db->escape($var) . "'");
+ }
+
+ public function getSavedProducts() {
+ return $this->db->query("
+ SELECT `ap`.`status`, `ap`.`product_id`, `ap`.`sku` as `amazonus_sku`, `pd`.`name` as `product_name`, `p`.`model` as `product_model`, `p`.`sku` as `product_sku`, `ap`.`var` as `var`
+ FROM `" . DB_PREFIX . "amazonus_product` as `ap`
+ LEFT JOIN `" . DB_PREFIX . "product_description` as `pd`
+ ON `ap`.`product_id` = `pd`.`product_id`
+ LEFT JOIN `" . DB_PREFIX . "product` as `p`
+ ON `ap`.`product_id` = `p`.`product_id`
+ WHERE `ap`.`status` = 'saved'
+ AND `pd`.`language_id` = '" . (int)$this->config->get('config_language_id') . "'")->rows;
+ }
+
+ public function getSavedProductsData() {
+ return $this->db->query("
+ SELECT * FROM `" . DB_PREFIX . "amazonus_product`
+ WHERE `status` = 'saved' AND `version` = 2")->rows;
+ }
+
+ public function getProduct($product_id, $var = '') {
+ return $this->db->query("
+ SELECT * FROM `" . DB_PREFIX . "amazonus_product`
+ WHERE `product_id` = '" . (int)$product_id . "' AND `var` = '" . $this->db->escape($var) . "' AND `version` = 2")->row;
+ }
+
+ public function getProductCategory($product_id, $var = '') {
+ $row = $this->db->query("
+ SELECT `category` FROM `" . DB_PREFIX . "amazonus_product`
+ WHERE `product_id` = '" . (int)$product_id . "' AND `var` = '" . $this->db->escape($var) . "' AND `version` = 2")->row;
+ if (isset($row['category'])) {
+ return $row['category'];
+ } else {
+ return "";
+ }
+ }
+
+ public function setProductUploaded($product_id, $insertion_id, $var = '') {
+ $this->db->query(
+ "UPDATE `" . DB_PREFIX . "amazonus_product`
+ SET `status` = 'uploaded', `insertion_id` = '" . $this->db->escape($insertion_id) . "'
+ WHERE `product_id` = '" . (int)$product_id . "' AND `var` = '" . $this->db->escape($var) . "' AND `version` = 2");
+ }
+
+ public function resetUploaded($insertion_id) {
+ $this->db->query(
+ "UPDATE `" . DB_PREFIX . "amazonus_product`
+ SET `status` = 'saved', `insertion_id` = ''
+ WHERE `insertion_id` = '" . $this->db->escape($insertion_id) . "' AND `version` = 2");
+ }
+
+ public function getProductStatus($product_id) {
+
+ $rows_uploaded = $this->db->query("
+ SELECT COUNT(*) count
+ FROM `" . DB_PREFIX . "amazonus_product`
+ WHERE `product_id` = '" . (int)$product_id . "' AND status = 'uploaded'")->row;
+ $rows_uploaded = $rows_uploaded['count'];
+
+ $rows_ok = $this->db->query("
+ SELECT COUNT(*) count
+ FROM `" . DB_PREFIX . "amazonus_product`
+ WHERE `product_id` = '" . (int)$product_id . "' AND status = 'ok'")->row;
+ $rows_ok = $rows_ok['count'];
+
+ $rows_error = $this->db->query("
+ SELECT COUNT(*) count
+ FROM `" . DB_PREFIX . "amazonus_product`
+ WHERE `product_id` = '" . (int)$product_id . "' AND status = 'error'")->row;
+ $rows_error = $rows_error['count'];
+
+ $rows_saved = $this->db->query("
+ SELECT COUNT(*) count
+ FROM `" . DB_PREFIX . "amazonus_product`
+ WHERE `product_id` = '" . (int)$product_id . "' AND status = 'saved'")->row;
+ $rows_saved = $rows_saved['count'];
+
+ $rows_total = $rows_uploaded + $rows_ok + $rows_error + $rows_saved;
+
+ $links = $this->db->query("
+ SELECT COUNT(*) as count
+ FROM `" . DB_PREFIX . "amazonus_product_link`
+ WHERE `product_id` = '" . (int)$product_id . "'")->row;
+ $links = $links['count'];
+
+ if ($rows_total === 0 && $links > 0) {
+ return 'linked';
+ } else if ($rows_total == 0) {
+ return false;
+ }
+
+ if ($rows_uploaded > 0) {
+ return 'processing';
+ }
+
+ if ($rows_uploaded == 0 && $rows_ok > 0 && $rows_error == 0) {
+ return 'ok';
+ }
+
+ if ($rows_saved > 0) {
+ return 'saved';
+ }
+
+ if ($rows_uploaded == 0 && $rows_error > 0 && $rows_ok == 0) {
+ $quick = $this->db->query("SELECT * FROM `" . DB_PREFIX . "amazonus_product` WHERE `product_id` = " . (int)$product_id . " AND `version` = 3")->row;
+
+ if ($quick) {
+ return 'error_quick';
+ } else {
+ return 'error_advanced';
+ }
+ } else {
+ return 'error_few';
+ }
+
+ return false;
+ }
+
+ public function getProductErrors($product_id, $version = 2) {
+ if ($version == 3) {
+ $message_row = $this->db->query("
+ SELECT `messages` FROM `" . DB_PREFIX . "amazonus_product`
+ WHERE `product_id` = '" . (int)$product_id . "' AND `version` = 3")->row;
+
+ return json_decode($message_row['messages']);
+ }
+
+ $result = array();
+
+ $insertion_rows = $this->db->query("SELECT `sku`, `insertion_id` FROM `" . DB_PREFIX . "amazonus_product` WHERE `product_id` = '" . (int)$product_id . "' AND `version` = 2")->rows;
+
+ if (!empty($insertion_rows)) {
+ foreach($insertion_rows as $insertion_row) {
+ $error_rows = $this->db->query("SELECT * FROM `" . DB_PREFIX . "amazonus_product_error` WHERE `sku` = '" . $this->db->escape($insertion_row['sku']) . "' AND `insertion_id` = '" . $this->db->escape($insertion_row['insertion_id']) . "'")->rows;
+
+ foreach($error_rows as $error_row) {
+ $result[] = $error_row;
+ }
+ }
+ }
+ return $result;
+ }
+
+ public function getProductsWithErrors() {
+ return $this->db->query("
+ SELECT `product_id`, `sku` FROM `" . DB_PREFIX . "amazonus_product`
+ WHERE `status` = 'error' AND `version` = 2")->rows;
+ }
+
+ public function deleteProduct($product_id) {
+ $this->db->query(
+ "DELETE FROM `" . DB_PREFIX . "amazonus_product`
+ WHERE `product_id` = '" . (int)$product_id . "'");
+ }
+
+ public function linkProduct($amazonus_sku, $product_id, $var = '') {
+ $count = $this->db->query("SELECT COUNT(*) as `count` FROM `" . DB_PREFIX . "amazonus_product_link` WHERE `product_id` = '" . (int)$product_id . "' AND `amazonus_sku` = '" . $this->db->escape($amazonus_sku) . "' AND `var` = '" . $this->db->escape($var) . "' LIMIT 1")->row;
+
+ if ($count['count'] == 0) {
+ $this->db->query("INSERT INTO `" . DB_PREFIX . "amazonus_product_link` SET `product_id` = '" . (int)$product_id . "', `amazonus_sku` = '" . $this->db->escape($amazonus_sku) . "', `var` = '" . $this->db->escape($var) . "'");
+ }
+ }
+
+ public function removeProductLink($amazonus_sku) {
+ $this->db->query(
+ "DELETE FROM `" . DB_PREFIX . "amazonus_product_link`
+ WHERE `amazonus_sku` = '" . $this->db->escape($amazonus_sku) . "'");
+ }
+
+ public function removeAdvancedErrors($product_id) {
+ $product_rows = $this->db->query("
+ SELECT `insertion_id` FROM `" . DB_PREFIX . "amazonus_product`
+ WHERE `product_id` = '" . (int)$product_id . "' AND `version` = 2")->rows;
+
+ foreach ($product_rows as $product) {
+ $this->db->query(
+ "DELETE FROM `" . DB_PREFIX . "amazonus_product_error`
+ WHERE `insertion_id` = '" . $this->db->escape($product['insertion_id']) . "'");
+ }
+
+ $this->db->query(
+ "UPDATE `" . DB_PREFIX . "amazonus_product`
+ SET `status` = 'saved', `insertion_id` = ''
+ WHERE `product_id` = '" . (int)$product_id . "' AND `status` = 'error' AND `version` = 2");
+ }
+
+ public function getProductLinks($product_id = 'all') {
+ $query = "SELECT `apl`.`amazonus_sku`, `apl`.`product_id`, `pd`.`name` as `product_name`, `p`.`model`, `p`.`sku`, `apl`.`var`, '' as `combination`
+ FROM `" . DB_PREFIX . "amazonus_product_link` as `apl`
+ LEFT JOIN `" . DB_PREFIX . "product_description` as `pd`
+ ON `apl`.`product_id` = `pd`.`product_id`
+ LEFT JOIN `" . DB_PREFIX . "product` as `p`
+ ON `apl`.`product_id` = `p`.`product_id`";
+ if ($product_id != 'all') {
+ $query .= " WHERE `apl`.`product_id` = '" . (int)$product_id . "' AND `pd`.`language_id` = '" . (int)$this->config->get('config_language_id') . "'";
+ } else {
+ $query .= "WHERE `pd`.`language_id` = '" . (int)$this->config->get('config_language_id') . "'";
+ }
+
+ $product_links = $this->db->query($query)->rows;
+
+ if ($this->openbay->addonLoad('openstock')) {
+ $this->load->model('extension/module/openstock');
+ $this->load->model('tool/image');
+
+ foreach ($product_links as $key => $product_link) {
+ $variants = $this->model_setting_module_openstock->getVariants($product_link['product_id']);
+
+ if (!empty($variants)) {
+ foreach($variants as $variant) {
+ if ($variant['sku'] == $product_link['var']) {
+ $product_links[$key]['combination'] = $variant['combination'];
+ break;
+ }
+ }
+ }
+ }
+
+ return $product_links;
+ } else {
+ return $product_links;
+ }
+ }
+
+ public function getUnlinkedProducts() {
+ if ($this->openbay->addonLoad('openstock')) {
+ $rows = $this->db->query("
+ SELECT `p`.`product_id`, `p`.`model`, `p`.`sku`, `pd`.`name` as `product_name`, '' as `var`, '' as `combination`, `p`.`has_option`
+ FROM `" . DB_PREFIX . "product` as `p`
+ LEFT JOIN `" . DB_PREFIX . "product_description` as `pd`
+ ON `p`.`product_id` = `pd`.`product_id`
+ AND `pd`.`language_id` = '" . (int)$this->config->get('config_language_id') . "'")->rows;
+
+ $result = array();
+ $this->load->model('extension/module/openstock');
+ $this->load->model('tool/image');
+ foreach($rows as $row) {
+ if ($row['has_option'] == 1) {
+ $stock_opts = $this->model_setting_module_openstock->getVariants($row['product_id']);
+ foreach($stock_opts as $opt) {
+ if ($this->productLinkExists($row['product_id'], $opt['sku'])) {
+ continue;
+ }
+ $row['sku'] = $opt['sku'];
+ $row['combination'] = $opt['combination'];
+ $row['sku'] = $opt['sku'];
+ $result[] = $row;
+ }
+ } else {
+ if (!$this->productLinkExists($row['product_id'], $row['sku'])) {
+ $result[] = $row;
+ }
+ }
+ }
+ } else {
+ $result = $this->db->query("
+ SELECT `p`.`product_id`, `p`.`model`, `p`.`sku`, `pd`.`name` as `product_name`, '' as `var`, '' as `combination`
+ FROM `" . DB_PREFIX . "product` as `p`
+ LEFT JOIN `" . DB_PREFIX . "product_description` as `pd`
+ ON `p`.`product_id` = `pd`.`product_id`
+ LEFT JOIN `" . DB_PREFIX . "amazonus_product_link` as `apl`
+ ON `apl`.`product_id` = `p`.`product_id`
+ WHERE `apl`.`amazonus_sku` IS NULL
+ AND `pd`.`language_id` = '" . (int)$this->config->get('config_language_id') . "'")->rows;
+ }
+
+ return $result;
+ }
+
+ private function productLinkExists($product_id, $var) {
+ $link = $this->db->query("SELECT * FROM `" . DB_PREFIX . "amazonus_product_link` WHERE `product_id` = " . (int)$product_id . " AND var = '" . $this->db->escape($var) . "'")->row;
+
+ if (empty($link)) {
+ return false;
+ } else {
+ return true;
+ }
+ }
+
+ public function getOrderStatusString($order_id) {
+ $row = $this->db->query("
+ SELECT `s`.`key`
+ FROM `" . DB_PREFIX . "order` `o`
+ JOIN `" . DB_PREFIX . "setting` `s` ON `o`.`order_id` = " . (int)$order_id . " AND `s`.`value` = `o`.`order_status_id`
+ WHERE `s`.`key` = 'openbay_amazonus_order_status_shipped' OR `s`.`key` = 'openbay_amazonus_order_status_canceled'
+ LIMIT 1")->row;
+
+ if (!isset($row['key']) || empty($row['key'])) {
+ return null;
+ }
+
+ $key = $row['key'];
+
+ switch ($key) {
+ case 'openbay_amazonus_order_status_shipped':
+ $order_status = 'shipped';
+ break;
+ case 'openbay_amazonus_order_status_canceled':
+ $order_status = 'canceled';
+ break;
+
+ default:
+ $order_status = null;
+ break;
+ }
+
+ return $order_status;
+ }
+
+ public function updateAmazonusOrderTracking($order_id, $courier_id, $courier_from_list, $tracking_no) {
+ $this->db->query("UPDATE `" . DB_PREFIX . "amazonus_order` SET `courier_id` = '" . $this->db->escape($courier_id) . "', `courier_other` = " . (int)!$courier_from_list . ", `tracking_no` = '" . $this->db->escape($tracking_no) . "' WHERE `order_id` = " . (int)$order_id . "");
+ }
+
+ public function getAmazonusOrderId($order_id) {
+ $row = $this->db->query("
+ SELECT `amazonus_order_id`
+ FROM `" . DB_PREFIX . "amazonus_order`
+ WHERE `order_id` = " . (int)$order_id . "
+ LIMIT 1")->row;
+
+ if (isset($row['amazonus_order_id']) && !empty($row['amazonus_order_id'])) {
+ return $row['amazonus_order_id'];
+ }
+
+ return null;
+ }
+
+ public function getAmazonusOrderedProducts($order_id) {
+ return $this->db->query("
+ SELECT `aop`.`amazonus_order_item_id`, `op`.`quantity`
+ FROM `" . DB_PREFIX . "amazonus_order_product` `aop`
+ JOIN `" . DB_PREFIX . "order_product` `op` ON `op`.`order_product_id` = `aop`.`order_product_id`
+ AND `op`.`order_id` = " . (int)$order_id)->rows;
+ }
+
+ public function getProductQuantity($product_id, $var = '') {
+ $result = null;
+
+ if ($var !== '' && $this->openbay->addonLoad('openstock')) {
+ $this->load->model('tool/image');
+ $this->load->model('extension/module/openstock');
+ $option_stocks = $this->model_setting_module_openstock->getVariants($product_id);
+
+ $option = null;
+ foreach ($option_stocks as $option_iterator) {
+ if ($option_iterator['sku'] === $var) {
+ $option = $option_iterator;
+ break;
+ }
+ }
+
+ if ($option != null) {
+ $result = $option['stock'];
+ }
+ } else {
+ $this->load->model('catalog/product');
+ $product_info = $this->model_catalog_product->getProduct($product_id);
+
+ if (isset($product_info['quantity'])) {
+ $result = $product_info['quantity'];
+ }
+ }
+ return $result;
+ }
+
+ public function getProductSearchTotal($data = array()) {
+ $sql = "
+ SELECT COUNT(*) AS product_total
+ FROM " . DB_PREFIX . "product p
+ LEFT JOIN " . DB_PREFIX . "amazonus_product_search aps ON p.product_id = aps.product_id
+ LEFT JOIN " . DB_PREFIX . "amazonus_product_link apl ON p.product_id = apl.product_id
+ LEFT JOIN " . DB_PREFIX . "amazonus_product ap ON p.product_id = ap.product_id
+ WHERE apl.product_id IS NULL AND ap.product_id IS NULL ";
+
+ if (!empty($data['status'])) {
+ $sql .= " AND aps.status = '" . $this->db->escape($data['status']) . "'";
+ }
+
+ return $this->db->query($sql)->row['product_total'];
+ }
+
+ public function getProductSearch($data = array()) {
+ $sql = "
+ SELECT p.product_id, aps.status, aps.data, aps.matches
+ FROM " . DB_PREFIX . "product p
+ LEFT JOIN " . DB_PREFIX . "amazonus_product_search aps ON p.product_id = aps.product_id
+ LEFT JOIN " . DB_PREFIX . "amazonus_product_link apl ON p.product_id = apl.product_id
+ LEFT JOIN " . DB_PREFIX . "amazonus_product ap ON p.product_id = ap.product_id
+ WHERE apl.product_id IS NULL AND ap.product_id IS NULL ";
+
+ if (!empty($data['status'])) {
+ $sql .= " AND aps.status = '" . $this->db->escape($data['status']) . "'";
+ }
+
+ $sql .= " LIMIT " . (int)$data['start'] . ", " . (int)$data['limit'];
+
+ $results = array();
+
+ $rows = $this->db->query($sql)->rows;
+
+ foreach ($rows as $row) {
+ $results[] = array(
+ 'product_id' => $row['product_id'],
+ 'status' => $row['status'],
+ 'matches' => $row['matches'],
+ 'data' => json_decode($row['data'], 1),
+ );
+ }
+
+ return $results;
+ }
+
+ public function updateAmazonSkusQuantities($skus) {
+ $sku_array = array();
+
+ foreach ($skus as $sku) {
+ $sku_array[] = "'" . $this->db->escape($sku) . "'";
+ }
+
+ if ($this->openbay->addonLoad('openstock')) {
+ $rows = $this->db->query("
+ SELECT apl.amazonus_sku, if (por.product_id IS NULL, p.quantity, por.stock) AS 'quantity'
+ FROM " . DB_PREFIX . "amazonus_product_link apl
+ JOIN " . DB_PREFIX . "product p ON apl.product_id = p.product_id
+ LEFT JOIN " . DB_PREFIX . "product_option_variant por ON apl.product_id = por.product_id AND apl.var = por.sku
+ WHERE apl.amazonus_sku IN (" . implode(',', $sku_array) . ")
+ ")->rows;
+ } else {
+ $rows = $this->db->query("
+ SELECT apl.amazonus_sku, p.quantity
+ FROM " . DB_PREFIX . "amazonus_product_link apl
+ JOIN " . DB_PREFIX . "product p ON apl.product_id = p.product_id
+ WHERE apl.amazonus_sku IN (" . implode(',', $sku_array) . ")
+ ")->rows;
+ }
+
+ $return = array();
+
+ foreach ($rows as $row) {
+ $return[$row['amazonus_sku']] = $row['quantity'];
+ }
+
+ $this->openbay->amazonus->updateQuantities($return);
+ }
+
+ public function getTotalUnlinkedItemsFromReport() {
+ if ($this->openbay->addonLoad('openstock')) {
+ $result = $this->db->query("
+ SELECT alr.sku AS 'amazon_sku', alr.quantity AS 'amazon_quantity', alr.asin, alr.price AS 'amazon_price', oc_sku.product_id, pd.name, oc_sku.sku, oc_sku.var, oc_sku.quantity, oc_sku.pov_id
+ FROM " . DB_PREFIX . "amazonus_listing_report alr
+ LEFT JOIN (
+ SELECT p.product_id, if (por.product_id IS NULL, p.sku, por.sku) AS 'sku', if (por.product_id IS NULL, NULL, por.sku) AS 'var', if (por.product_id IS NULL, p.quantity, por.stock) AS 'quantity', por.product_option_variant_id AS pov_id
+ FROM " . DB_PREFIX . "product p
+ LEFT JOIN " . DB_PREFIX . "product_option_variant por USING(product_id)
+ ) AS oc_sku ON alr.sku = oc_sku.sku
+ LEFT JOIN " . DB_PREFIX . "amazonus_product_link apl ON (oc_sku.var IS NULL AND oc_sku.product_id = apl.product_id) OR (oc_sku.var IS NOT NULL AND oc_sku.product_id = apl.product_id AND oc_sku.var = apl.var)
+ LEFT JOIN " . DB_PREFIX . "product_description pd ON oc_sku.product_id = pd.product_id AND pd.language_id = " . (int)$this->config->get('config_language_id') . "
+ WHERE apl.product_id IS NULL
+ ");
+ } else {
+ $result = $this->db->query("
+ SELECT alr.sku AS 'amazon_sku', alr.quantity AS 'amazon_quantity', alr.asin, alr.price AS 'amazon_price', oc_sku.product_id, pd.name, oc_sku.sku, oc_sku.var, oc_sku.quantity, '' AS combination
+ FROM " . DB_PREFIX . "amazonus_listing_report alr
+ LEFT JOIN (
+ SELECT p.product_id, p.sku, NULL AS 'var', p.quantity
+ FROM " . DB_PREFIX . "product p
+ ) AS oc_sku ON alr.sku = oc_sku.sku
+ LEFT JOIN " . DB_PREFIX . "amazonus_product_link apl ON (oc_sku.var IS NULL AND oc_sku.product_id = apl.product_id) OR (oc_sku.var IS NOT NULL AND oc_sku.product_id = apl.product_id AND oc_sku.var = apl.var)
+ LEFT JOIN " . DB_PREFIX . "product_description pd ON oc_sku.product_id = pd.product_id AND pd.language_id = " . (int)$this->config->get('config_language_id') . "
+ WHERE apl.product_id IS NULL
+ ORDER BY alr.sku
+ ");
+ }
+
+ return (int)$result->num_rows;
+ }
+
+ public function getUnlinkedItemsFromReport($limit = 100, $page = 1) {
+ $start = $limit * ($page - 1);
+
+ if ($this->openbay->addonLoad('openstock')) {
+ $this->load->model('extension/module/openstock');
+ $rows = $this->db->query("
+ SELECT alr.sku AS 'amazon_sku', alr.quantity AS 'amazon_quantity', alr.asin, alr.price AS 'amazon_price', oc_sku.product_id, pd.name, oc_sku.sku, oc_sku.var, oc_sku.quantity, oc_sku.pov_id
+ FROM " . DB_PREFIX . "amazonus_listing_report alr
+ LEFT JOIN (
+ SELECT p.product_id, if (por.product_id IS NULL, p.sku, por.sku) AS 'sku', if (por.product_id IS NULL, NULL, por.sku) AS 'var', if (por.product_id IS NULL, p.quantity, por.stock) AS 'quantity', por.product_option_variant_id AS pov_id
+ FROM " . DB_PREFIX . "product p
+ LEFT JOIN " . DB_PREFIX . "product_option_variant por USING(product_id)
+ ) AS oc_sku ON alr.sku = oc_sku.sku
+ LEFT JOIN " . DB_PREFIX . "amazonus_product_link apl ON (oc_sku.var IS NULL AND oc_sku.product_id = apl.product_id) OR (oc_sku.var IS NOT NULL AND oc_sku.product_id = apl.product_id AND oc_sku.var = apl.var)
+ LEFT JOIN " . DB_PREFIX . "product_description pd ON oc_sku.product_id = pd.product_id AND pd.language_id = " . (int)$this->config->get('config_language_id') . "
+ WHERE apl.product_id IS NULL
+ ORDER BY alr.sku
+ LIMIT " . (int)$start . "," . (int)$limit)->rows;
+ } else {
+ $rows = $this->db->query("
+ SELECT alr.sku AS 'amazon_sku', alr.quantity AS 'amazon_quantity', alr.asin, alr.price AS 'amazon_price', oc_sku.product_id, pd.name, oc_sku.sku, oc_sku.var, oc_sku.quantity, '' AS combination
+ FROM " . DB_PREFIX . "amazonus_listing_report alr
+ LEFT JOIN (
+ SELECT p.product_id, p.sku, NULL AS 'var', p.quantity
+ FROM " . DB_PREFIX . "product p
+ ) AS oc_sku ON alr.sku = oc_sku.sku
+ LEFT JOIN " . DB_PREFIX . "amazonus_product_link apl ON (oc_sku.var IS NULL AND oc_sku.product_id = apl.product_id) OR (oc_sku.var IS NOT NULL AND oc_sku.product_id = apl.product_id AND oc_sku.var = apl.var)
+ LEFT JOIN " . DB_PREFIX . "product_description pd ON oc_sku.product_id = pd.product_id AND pd.language_id = " . (int)$this->config->get('config_language_id') . "
+ WHERE apl.product_id IS NULL
+ ORDER BY alr.sku
+ LIMIT " . (int)$start . "," . (int)$limit)->rows;
+ }
+
+ $products = array();
+
+ foreach ($rows as $row) {
+ $combinations = array();
+
+ if (isset($row['pov_id']) && !empty($row['pov_id'])) {
+ $variants = (isset($row['pov_id']) ? $this->model_setting_module_openstock->getVariant($row['pov_id']) : '');
+
+ foreach ($variants as $variant) {
+ $combinations[] = $variant['option_value_name'];
+ }
+ }
+
+ $products[] = array(
+ 'product_id' => $row['product_id'],
+ 'name' => $row['name'],
+ 'sku' => $row['sku'],
+ 'var' => $row['var'],
+ 'quantity' => $row['quantity'],
+ 'amazon_sku' => $row['amazon_sku'],
+ 'amazon_quantity' => $row['amazon_quantity'],
+ 'amazon_price' => number_format($row['amazon_price'], 2, '.', ''),
+ 'asin' => $row['asin'],
+ 'combination' => implode(' > ', $combinations),
+ );
+ }
+
+ return $products;
+ }
+
+ public function deleteListingReports() {
+ $this->db->query("
+ DELETE FROM " . DB_PREFIX . "amazonus_listing_report
+ ");
+ }
+}
diff --git a/public/admin/model/extension/openbay/amazonus_listing.php b/public/admin/model/extension/openbay/amazonus_listing.php
new file mode 100644
index 0000000..beaea33
--- /dev/null
+++ b/public/admin/model/extension/openbay/amazonus_listing.php
@@ -0,0 +1,197 @@
+<?php
+class ModelExtensionOpenBayAmazonusListing extends Model {
+ private $tabs = array();
+
+ public function search($search_string) {
+
+ $search_params = array(
+ 'search_string' => $search_string,
+ );
+
+ $results = json_decode($this->openbay->amazonus->call('productv3/search', $search_params), 1);
+
+ $products = array();
+
+ if (!empty($results)) {
+ foreach ($results['Products'] as $result) {
+ if ($result['price']['amount'] && $result['price']['currency']) {
+ $price = $result['price']['amount'] . ' ' . $result['price']['currency'];
+ } else {
+ $price = '-';
+ }
+
+ $link = 'http://www.amazon.com/gp/product/' . $result['asin'] . '/';
+
+ $products[] = array(
+ 'name' => $result['name'],
+ 'asin' => $result['asin'],
+ 'image' => $result['image'],
+ 'price' => $price,
+ 'link' => $link,
+ );
+ }
+ }
+
+ return $products;
+ }
+
+ public function getProductByAsin($asin) {
+ $data = array(
+ 'asin' => $asin,
+ );
+
+ $results = json_decode($this->openbay->amazonus->call('productv3/getProduct', $data), 1);
+
+ return $results;
+ }
+
+ public function getBestPrice($asin, $condition) {
+ $search_params = array(
+ 'asin' => $asin,
+ 'condition' => $condition,
+ );
+
+ $best_price = '';
+
+ $result = json_decode($this->openbay->amazonus->call('productv3/getPrice', $search_params), 1);
+
+ if (isset($result['Price']['Amount']) && $result['Price']['Currency'] && $this->currency->has($result['Price']['Currency'])) {
+ $best_price['amount'] = number_format($this->currency->convert($result['Price']['Amount'], $result['Price']['Currency'], $this->config->get('config_currency')), 2, '.', '');
+ $best_price['shipping'] = number_format($this->currency->convert($result['Price']['Shipping'], $result['Price']['Currency'], $this->config->get('config_currency')), 2, '.', '');
+ $best_price['currency'] = $result['Price']['Currency'];
+ }
+
+ return $best_price;
+ }
+
+ public function simpleListing($data) {
+ $request = array(
+ 'asin' => $data['asin'],
+ 'sku' => $data['sku'],
+ 'quantity' => $data['quantity'],
+ 'price' => $data['price'],
+ 'sale' => array(
+ 'price' => $data['sale_price'],
+ 'from' => $data['sale_from'],
+ 'to' => $data['sale_to'],
+ ),
+ 'condition' => $data['condition'],
+ 'condition_note' => $data['condition_note'],
+ 'start_selling' => $data['start_selling'],
+ 'restock_date' => $data['restock_date'],
+ 'response_url' => HTTPS_CATALOG . 'index.php?route=extension/openbay/amazonus/listing',
+ 'product_id' => $data['product_id'],
+ );
+
+ $response = $this->openbay->amazonus->call('productv3/simpleListing', $request);
+ $response = json_decode($response);
+ if (empty($response)) {
+ return array(
+ 'status' => 0,
+ 'message' => 'Problem connecting OpenBay: API'
+ );
+ }
+ $response = (array)$response;
+
+ if ($response['status'] === 1) {
+ $this->db->query("
+ REPLACE INTO `" . DB_PREFIX . "amazonus_product`
+ SET `product_id` = " . (int)$data['product_id'] . ",
+ `status` = 'uploaded',
+ `version` = 3,
+ `var` = ''
+ ");
+ }
+
+ return $response;
+ }
+
+ public function getBrowseNodes($request) {
+ return $this->openbay->amazonus->call('productv3/getBrowseNodes', $request);
+ }
+
+ public function deleteSearchResults($product_ids) {
+ $imploded_ids = array();
+
+ foreach ($product_ids as $product_id) {
+ $imploded_ids[] = (int)$product_id;
+ }
+
+ $imploded_ids = implode(',', $imploded_ids);
+
+ $this->db->query("
+ DELETE FROM " . DB_PREFIX . "amazonus_product_search
+ WHERE product_id IN ($imploded_ids)
+ ");
+ }
+
+ public function doBulkListing($data) {
+ $this->load->model('catalog/product');
+ $request = array();
+
+ foreach($data['products'] as $product_id => $asin) {
+ $product = $this->model_catalog_product->getProduct($product_id);
+
+ if ($product) {
+ $price = $product['price'];
+
+ if ($this->config->get('openbay_amazonus_listing_tax_added') && $this->config->get('openbay_amazonus_listing_tax_added') > 0) {
+ $price += $price * ($this->config->get('openbay_amazonus_listing_tax_added') / 100);
+ }
+
+ $request[] = array(
+ 'asin' => $asin,
+ 'sku' => $product['sku'],
+ 'quantity' => $product['quantity'],
+ 'price' => number_format($price, 2, '.', ''),
+ 'sale' => array(),
+ 'condition' => (isset($data['condition']) ? $data['condition'] : ''),
+ 'condition_note' => (isset($data['condition_note']) ? $data['condition_note'] : ''),
+ 'start_selling' => (isset($data['start_selling']) ? $data['start_selling'] : ''),
+ 'restock_date' => '',
+ 'response_url' => HTTPS_CATALOG . 'index.php?route=extension/openbay/amazonus/listing',
+ 'product_id' => $product['product_id'],
+ );
+ }
+ }
+
+ if ($request) {
+ $response = $this->openbay->amazonus->call('productv3/bulkListing', $request);
+
+ $response = json_decode($response, 1);
+
+ if ($response['status'] == 1) {
+ foreach ($request as $product) {
+ $this->db->query("
+ REPLACE INTO `" . DB_PREFIX . "amazonus_product`
+ SET `product_id` = " . (int)$product['product_id'] . ",
+ `status` = 'uploaded',
+ `var` = '',
+ `version` = 3
+ ");
+ }
+
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+ public function doBulkSearch($search_data) {
+ foreach ($search_data as $products) {
+ foreach ($products as $product) {
+ $this->db->query("
+ REPLACE INTO " . DB_PREFIX . "amazonus_product_search (product_id, `status`)
+ VALUES (" . (int)$product['product_id'] . ", 'searching')");
+ }
+ }
+
+ $request_data = array(
+ 'search' => $search_data,
+ 'response_url' => HTTPS_CATALOG . 'index.php?route=extension/openbay/amazonus/search'
+ );
+
+ $response = $this->openbay->amazonus->call('productv3/bulkSearch', $request_data);
+ }
+} \ No newline at end of file
diff --git a/public/admin/model/extension/openbay/ebay.php b/public/admin/model/extension/openbay/ebay.php
new file mode 100644
index 0000000..246f64e
--- /dev/null
+++ b/public/admin/model/extension/openbay/ebay.php
@@ -0,0 +1,832 @@
+<?php
+class ModelExtensionOpenBayEbay extends Model{
+ public function install() {
+ $this->load->model('setting/event');
+
+ $this->model_setting_event->addEvent('openbay_ebay_add_order', 'catalog/model/checkout/order/addOrderHistory/after', 'extension/openbay/ebay/eventAddOrderHistory');
+
+ $settings = array();
+ $settings["ebay_token"] = '';
+ $settings["ebay_secret"] = '';
+ $settings["ebay_encryption_key"] = '';
+ $settings["ebay_encryption_iv"] = '';
+ $settings["ebay_enditems"] = '0';
+ $settings["ebay_logging"] = '1';
+ $settings["ebay_payment_instruction"] = '';
+ $settings["ebay_payment_paypal_address"] = '';
+ $settings["ebay_tax"] = '0';
+ $settings["ebay_status_import_id"] = '1';
+ $settings["ebay_status_shipped_id"] = '3';
+ $settings["ebay_status_paid_id"] = '2';
+ $settings["ebay_status_cancelled_id"] = '7';
+ $settings["ebay_status_refunded_id"] = '11';
+ $settings["ebay_def_currency"] = 'GBP';
+ $settings["ebay_stock_allocate"] = '0';
+ $settings["ebay_update_notify"] = '1';
+ $settings["ebay_confirm_notify"] = '1';
+ $settings["ebay_confirmadmin_notify"] = '1';
+ $settings["ebay_created_hours"] = '48';
+ $settings["ebay_create_date"] = '0';
+ $settings["ebay_itm_link"] = 'http://www.ebay.com/itm/';
+ $settings["ebay_relistitems"] = 0;
+ $settings["ebay_time_offset"] = 0;
+ $settings["ebay_default_addressformat"] = '{firstname} {lastname}
+{company}
+{address_1}
+{address_2}
+{city}
+{zone}
+{postcode}
+{country}';
+
+ $this->model_setting_setting->editSetting('ebay', $settings);
+
+ $this->db->query("
+ CREATE TABLE IF NOT EXISTS `" . DB_PREFIX . "ebay_category` (
+ `ebay_category_id` int(11) NOT NULL AUTO_INCREMENT,
+ `CategoryID` int(11) NOT NULL,
+ `CategoryParentID` int(11) NOT NULL,
+ `CategoryLevel` smallint(6) NOT NULL,
+ `CategoryName` char(100) NOT NULL,
+ `BestOfferEnabled` tinyint(1) NOT NULL,
+ `AutoPayEnabled` tinyint(1) NOT NULL,
+ PRIMARY KEY (`ebay_category_id`)
+ ) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_general_ci;");
+
+ $this->db->query("
+ CREATE TABLE IF NOT EXISTS `" . DB_PREFIX . "ebay_category_history` (
+ `ebay_category_history_id` int(11) NOT NULL AUTO_INCREMENT,
+ `CategoryID` int(11) NOT NULL,
+ `breadcrumb` varchar(255) NOT NULL,
+ `used` int(6) NOT NULL,
+ PRIMARY KEY (`ebay_category_history_id`)
+ ) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_general_ci;");
+
+ $this->db->query("
+ CREATE TABLE IF NOT EXISTS `" . DB_PREFIX . "ebay_listing` (
+ `ebay_listing_id` int(11) NOT NULL AUTO_INCREMENT,
+ `ebay_item_id` char(100) NOT NULL,
+ `product_id` int(11) NOT NULL,
+ `variant` int(11) NOT NULL,
+ `status` SMALLINT(3) NOT NULL DEFAULT '1',
+ PRIMARY KEY (`ebay_listing_id`),
+ KEY `product_id` (`product_id`)
+ ) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_general_ci;");
+ ;
+ $this->db->query("
+ CREATE TABLE IF NOT EXISTS `" . DB_PREFIX . "ebay_listing_pending` (
+ `ebay_listing_pending_id` int(11) NOT NULL AUTO_INCREMENT,
+ `ebay_item_id` char(25) NOT NULL,
+ `product_id` int(11) NOT NULL,
+ `key` char(50) NOT NULL,
+ `variant` int(11) NOT NULL,
+ PRIMARY KEY (`ebay_listing_pending_id`),
+ KEY `product_id` (`product_id`)
+ ) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_general_ci;");
+
+ $this->db->query("
+ CREATE TABLE IF NOT EXISTS `" . DB_PREFIX . "ebay_shipping` (
+ `ebay_shipping_id` int(11) NOT NULL AUTO_INCREMENT,
+ `description` varchar(100) NOT NULL,
+ `InternationalService` tinyint(4) NOT NULL,
+ `ShippingService` varchar(100) NOT NULL,
+ `ShippingServiceID` int(11) NOT NULL,
+ `ServiceType` varchar(100) NOT NULL,
+ `ValidForSellingFlow` tinyint(4) NOT NULL,
+ `ShippingCategory` varchar(100) NOT NULL,
+ `ShippingTimeMin` int(11) NOT NULL,
+ `ShippingTimeMax` int(11) NOT NULL,
+ PRIMARY KEY (`ebay_shipping_id`)
+ ) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_general_ci;");
+
+ $this->db->query("
+ CREATE TABLE IF NOT EXISTS `" . DB_PREFIX . "ebay_shipping_location` (
+ `ebay_shipping_id` int(11) NOT NULL AUTO_INCREMENT,
+ `description` varchar(100) NOT NULL,
+ `detail_version` varchar(100) NOT NULL,
+ `shipping_location` varchar(100) NOT NULL,
+ `update_time` varchar(100) NOT NULL,
+ PRIMARY KEY (`ebay_shipping_id`)
+ ) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_general_ci;");
+
+ $this->db->query("
+ CREATE TABLE IF NOT EXISTS `" . DB_PREFIX . "ebay_payment_method` (
+ `ebay_payment_method_id` int(11) NOT NULL AUTO_INCREMENT,
+ `ebay_name` char(50) NOT NULL,
+ `local_name` char(50) NOT NULL,
+ PRIMARY KEY (`ebay_payment_method_id`)
+ ) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_general_ci AUTO_INCREMENT=5;");
+
+ $this->db->query("
+ CREATE TABLE IF NOT EXISTS `" . DB_PREFIX . "ebay_transaction` (
+ `ebay_transaction_id` int(11) NOT NULL AUTO_INCREMENT,
+ `order_id` int(11) NOT NULL,
+ `product_id` int(11) NOT NULL,
+ `sku` varchar(100) NOT NULL,
+ `txn_id` varchar(100) NOT NULL,
+ `item_id` varchar(100) NOT NULL,
+ `containing_order_id` varchar(100) NOT NULL,
+ `order_line_id` varchar(100) NOT NULL,
+ `qty` int(11) NOT NULL,
+ `smp_id` int(11) NOT NULL,
+ `created` DATETIME NOT NULL,
+ `modified` DATETIME NOT NULL,
+ PRIMARY KEY (`ebay_transaction_id`),
+ KEY `product_id` (`product_id`),
+ KEY `order_id` (`order_id`),
+ KEY `smp_id` (`smp_id`)
+ ) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_general_ci;");
+
+ $this->db->query("
+ CREATE TABLE IF NOT EXISTS `" . DB_PREFIX . "ebay_order` (
+ `ebay_order_id` int(11) NOT NULL AUTO_INCREMENT,
+ `parent_ebay_order_id` int(11) NOT NULL,
+ `order_id` int(11) NOT NULL,
+ `smp_id` int(11) NOT NULL,
+ `tracking_no` varchar(100) NOT NULL,
+ `carrier_id` varchar(100) NOT NULL,
+ PRIMARY KEY (`ebay_order_id`),
+ KEY `order_id` (`order_id`),
+ KEY `smp_id` (`smp_id`),
+ KEY `parent_ebay_order_id` (`parent_ebay_order_id`)
+ ) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_general_ci;");
+
+ $this->db->query("
+ CREATE TABLE IF NOT EXISTS `" . DB_PREFIX . "ebay_profile` (
+ `ebay_profile_id` int(11) NOT NULL AUTO_INCREMENT,
+ `name` varchar(100) NOT NULL,
+ `description` text NOT NULL,
+ `type` int(11) NOT NULL,
+ `default` TINYINT(1) NOT NULL,
+ `data` text NOT NULL,
+ PRIMARY KEY (`ebay_profile_id`)
+ ) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_general_ci;");
+
+ $this->db->query("
+ CREATE TABLE IF NOT EXISTS `" . DB_PREFIX . "ebay_setting_option` (
+ `ebay_setting_option_id` INT(11) NOT NULL AUTO_INCREMENT,
+ `key` VARCHAR(100) NOT NULL,
+ `last_updated` DATETIME NOT NULL,
+ `data` TEXT NOT NULL,
+ PRIMARY KEY (`ebay_setting_option_id`)
+ ) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_general_ci;");
+
+ $this->db->query("
+ CREATE TABLE IF NOT EXISTS `" . DB_PREFIX . "ebay_image_import` (
+ `id` int(11) NOT NULL AUTO_INCREMENT,
+ `image_original` text NOT NULL,
+ `image_new` text NOT NULL,
+ `name` text NOT NULL,
+ `product_id` int(11) NOT NULL,
+ `imgcount` int(11) NOT NULL,
+ PRIMARY KEY (`id`)
+ ) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_general_ci;");
+
+ $this->db->query("
+ CREATE TABLE IF NOT EXISTS `" . DB_PREFIX . "ebay_shipping_location_exclude` (
+ `ebay_shipping_exclude_id` int(11) NOT NULL AUTO_INCREMENT,
+ `description` varchar(100) NOT NULL,
+ `location` varchar(100) NOT NULL,
+ `region` varchar(100) NOT NULL,
+ PRIMARY KEY (`ebay_shipping_exclude_id`)
+ ) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_general_ci;");
+
+ $this->db->query("
+ CREATE TABLE IF NOT EXISTS `" . DB_PREFIX . "ebay_stock_reserve` (
+ `id` int(11) NOT NULL AUTO_INCREMENT,
+ `product_id` int(11) NOT NULL,
+ `variant_id` varchar(100) NOT NULL,
+ `item_id` varchar(100) NOT NULL,
+ `reserve` int(11) NOT NULL,
+ PRIMARY KEY (`id`),
+ KEY `product_id` (`product_id`)
+ ) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_general_ci;");
+
+ $this->db->query("
+ CREATE TABLE IF NOT EXISTS `" . DB_PREFIX . "ebay_order_lock` (
+ `smp_id` int(11) NOT NULL,
+ PRIMARY KEY (`smp_id`)
+ ) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_general_ci;");
+
+ $this->db->query("
+ CREATE TABLE IF NOT EXISTS `" . DB_PREFIX . "ebay_template` (
+ `template_id` INT(11) NOT NULL AUTO_INCREMENT,
+ `name` VARCHAR(100) NOT NULL,
+ `html` MEDIUMTEXT NOT NULL,
+ PRIMARY KEY (`template_id`)
+ ) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_general_ci;");
+ }
+
+ public function uninstall() {
+ $this->db->query("DROP TABLE IF EXISTS `" . DB_PREFIX . "ebay_category`;");
+ $this->db->query("DROP TABLE IF EXISTS `" . DB_PREFIX . "ebay_category_history`;");
+ $this->db->query("DROP TABLE IF EXISTS `" . DB_PREFIX . "ebay_listing`;");
+ $this->db->query("DROP TABLE IF EXISTS `" . DB_PREFIX . "ebay_listing_pending`;");
+ $this->db->query("DROP TABLE IF EXISTS `" . DB_PREFIX . "ebay_shipping`;");
+ $this->db->query("DROP TABLE IF EXISTS `" . DB_PREFIX . "ebay_shipping_location`;");
+ $this->db->query("DROP TABLE IF EXISTS `" . DB_PREFIX . "ebay_payment_method`;");
+ $this->db->query("DROP TABLE IF EXISTS `" . DB_PREFIX . "ebay_transaction`;");
+ $this->db->query("DROP TABLE IF EXISTS `" . DB_PREFIX . "ebay_order`;");
+ $this->db->query("DROP TABLE IF EXISTS `" . DB_PREFIX . "ebay_profile`;");
+
+ $this->load->model('setting/event');
+ $this->model_setting_event->deleteEventByCode('openbay_ebay_add_order');
+ }
+
+ public function patch() {
+ if ($this->config->get('ebay_status') == 1) {
+
+ }
+ }
+
+ public function totalLinked() {
+ $sql = "SELECT COUNT(DISTINCT p.product_id) AS total
+ FROM `" . DB_PREFIX . "ebay_listing` `el`
+ LEFT JOIN `" . DB_PREFIX . "product` `p` ON (`el`.`product_id` = `p`.`product_id`)
+ LEFT JOIN `" . DB_PREFIX . "product_description` `pd` ON (`p`.`product_id` = `pd`.`product_id`)
+ WHERE `el`.`status` = '1'
+ AND `pd`.`language_id` = '" . (int)$this->config->get('config_language_id') . "'";
+
+ $query = $this->db->query($sql);
+
+ return $query->row['total'];
+ }
+
+ public function loadLinked($limit = 100, $page = 1) {
+ $this->load->model('tool/image');
+
+ $start = $limit * ($page - 1);
+
+ $has_option = '';
+ if ($this->openbay->addonLoad('openstock') ) {
+ $this->load->model('extension/module/openstock');
+ $has_option = '`p`.`has_option`, ';
+ }
+
+ $sql = "
+ SELECT
+ " . $has_option . "
+ `el`.`ebay_item_id`,
+ `p`.`product_id`,
+ `p`.`sku`,
+ `p`.`model`,
+ `p`.`quantity`,
+ `pd`.`name`,
+ `esr`.`reserve`
+ FROM `" . DB_PREFIX . "ebay_listing` `el`
+ LEFT JOIN `" . DB_PREFIX . "product` `p` ON (`el`.`product_id` = `p`.`product_id`)
+ LEFT JOIN `" . DB_PREFIX . "product_description` `pd` ON (`p`.`product_id` = `pd`.`product_id`)
+ LEFT JOIN `" . DB_PREFIX . "ebay_stock_reserve` `esr` ON (`esr`.`product_id` = `p`.`product_id`)
+ WHERE `el`.`status` = '1'
+ AND `pd`.`language_id` = '" . (int)$this->config->get('config_language_id') . "'";
+
+ $sql .= " LIMIT " . (int)$start . "," . (int)$limit;
+
+ $qry = $this->db->query($sql);
+
+ $data = array();
+ if ($qry->num_rows) {
+ foreach ($qry->rows as $row) {
+ $data[$row['ebay_item_id']] = array(
+ 'product_id' => $row['product_id'],
+ 'sku' => $row['sku'],
+ 'model' => $row['model'],
+ 'qty' => $row['quantity'],
+ 'name' => $row['name'],
+ 'link_edit' => $this->url->link('catalog/product/edit', 'user_token=' . $this->session->data['user_token'] . '&product_id=' . $row['product_id'], true),
+ 'link_ebay' => $this->config->get('ebay_itm_link') . $row['ebay_item_id'],
+ 'reserve' => (int)$row['reserve'],
+ );
+
+ $data[$row['ebay_item_id']]['options'] = 0;
+
+ if ((isset($row['has_option']) && $row['has_option'] == 1) && $this->openbay->addonLoad('openstock')) {
+ $data[$row['ebay_item_id']]['options'] = $this->model_setting_module_openstock->getVariants((int)$row['product_id']);
+ }
+
+ //get the allocated stock - items that have been bought but not assigned to an order
+ if ($this->config->get('ebay_stock_allocate') == 0) {
+ $data[$row['ebay_item_id']]['allocated'] = $this->openbay->ebay->getAllocatedStock($row['product_id']);
+ } else {
+ $data[$row['ebay_item_id']]['allocated'] = 0;
+ }
+ }
+ }
+
+ return $data;
+ }
+
+ public function loadLinkedStatus($item_ids) {
+ $this->openbay->ebay->log('loadLinkedStatus() - Get item status from ebay for multiple IDs');
+ return $this->openbay->ebay->call('item/getItemsById/', array('item_ids' => $item_ids));
+ }
+
+ public function loadUnlinked($limit = 200, $page = 1, $filter = array()) {
+ $unlinked = array();
+ $current = 1;
+ $stop_flag = 0;
+
+ while(count($unlinked) < 5) {
+ if ($current > 5) {
+ $stop_flag = 1;
+ break;
+ } else {
+ $current++;
+ }
+
+ $this->openbay->ebay->log('Checking unlinked page: ' . $page);
+
+ $response = $this->openbay->ebay->getEbayItemList($limit, $page, $filter);
+
+ if ($this->openbay->ebay->lasterror == true) {
+ break;
+ }
+
+ foreach ($response['items'] as $item_id => $item) {
+ if ($this->openbay->ebay->getProductId($item_id, 1) == false) {
+ $unlinked[$item_id] = $item;
+ }
+ }
+
+ $this->openbay->ebay->log('Unlinked count: ' . count($unlinked));
+
+ if ($response['max_page'] == $page || count($unlinked) >= 5) {
+ break;
+ } else {
+ $page++;
+ }
+ }
+
+ return array(
+ 'items' => $unlinked,
+ 'break' => $stop_flag,
+ 'next_page' => $response['page']+1,
+ 'max_page' => $response['max_page']
+ );
+ }
+
+ public function loadItemLinks() {
+ $local = $this->openbay->ebay->getLiveListingArray();
+ $response = $this->openbay->ebay->getEbayActiveListings();
+
+ $data = array(
+ 'unlinked' => array(),
+ 'linked' => array()
+ );
+
+ if (!empty($response)) {
+ foreach ($response as $key => $value) {
+ if (!in_array($key, $local)) {
+ $data['unlinked'][$key] = $value;
+ } else {
+ $data['linked'][$key] = $value;
+ }
+ }
+ }
+
+ return $data;
+ }
+
+ public function saveItemLink($data) {
+ $this->openbay->ebay->log('Creating item link.');
+ $this->openbay->ebay->createLink($data['pid'], $data['itemId'], $data['variants']);
+
+ if (($data['qty'] != $data['ebayqty']) || $data['variants'] == 1) {
+ $this->load->model('catalog/product');
+ $this->openbay->ebay->log('Updating eBay with new qty');
+ $this->openbay->ebay->productUpdateListen($data['pid'], $this->model_catalog_product->getProduct($data['pid']));
+ } else {
+ $this->openbay->ebay->log('Qty on eBay is the same as our stock, no update needed');
+ return array('msg' => 'ok', 'error' => false);
+ }
+ }
+
+ public function getSellerStoreCategories() {
+ $qry = $this->db->query("SHOW TABLES LIKE '" . DB_PREFIX . "ebay_store_category'");
+
+ if ($qry->num_rows) {
+ $qry = $this->db->query("SELECT * FROM `" . DB_PREFIX . "ebay_store_category` WHERE `parent_id` = '0' ORDER BY `CategoryName` ASC");
+
+ if ($qry->num_rows) {
+ $cats = array();
+
+ foreach ($qry->rows as $row) {
+ $lev1 = $row['CategoryName'];
+ $qry2 = $this->db->query("SELECT * FROM `" . DB_PREFIX . "ebay_store_category` WHERE `parent_id` = '" . $row['ebay_store_category_id'] . "' ORDER BY `CategoryName` ASC");
+
+ if ($qry2->num_rows) {
+ foreach ($qry2->rows as $row2) {
+ $qry3 = $this->db->query("SELECT * FROM `" . DB_PREFIX . "ebay_store_category` WHERE `parent_id` = '" . $row2['ebay_store_category_id'] . "' ORDER BY `CategoryName` ASC");
+
+ if ($qry3->num_rows) {
+ foreach ($qry3->rows as $row3) {
+ $cats[$row3['CategoryID']] = $lev1 . ' > ' . $row2['CategoryName'] . ' > ' . $row3['CategoryName'];
+ }
+ } else {
+ $cats[$row2['CategoryID']] = $lev1 . ' > ' . $row2['CategoryName'];
+ }
+ }
+ } else {
+ $cats[$row['CategoryID']] = $lev1;
+ }
+ }
+
+ return $cats;
+ } else {
+ return false;
+ }
+ } else {
+ return false;
+ }
+ }
+
+ public function getCategory($parent) {
+ $this->load->language('extension/openbay/ebay_new');
+
+ $json = array();
+
+ if (empty($parent)) {
+ $cat_qry = $this->db->query("SELECT * FROM `" . DB_PREFIX . "ebay_category` WHERE `CategoryID` = `CategoryParentID`");
+ } else {
+ $cat_qry = $this->db->query("SELECT * FROM `" . DB_PREFIX . "ebay_category` WHERE `CategoryParentID` = '" . $parent . "'");
+ }
+
+ if ($cat_qry->num_rows) {
+ $json['cats'] = array();
+ foreach ($cat_qry->rows as $row) {
+ $json['cats'][] = $row;
+ }
+ $json['items'] = $cat_qry->num_rows;
+
+ } else {
+ if (empty($parent)) {
+ $json['error'] = $this->language->get('error_category_sync');
+ }
+
+ $json['items'] = null;
+ }
+
+ return $json;
+ }
+
+ public function getSuggestedCategories($qry) {
+ $response = array(
+ 'data' => $this->openbay->ebay->call('listing/getSuggestedCategories/', array('qry' => $qry)),
+ 'error' => $this->openbay->ebay->lasterror,
+ 'msg' => $this->openbay->ebay->lastmsg
+ );
+
+ return $response;
+ }
+
+ public function getShippingService($international, $type) {
+ $json = array();
+ $result = $this->db->query("SELECT * FROM `" . DB_PREFIX . "ebay_shipping` WHERE `InternationalService` = '" . (int)$international . "' AND `ValidForSellingFlow` = '1' AND `ServiceType` LIKE '%" . $this->db->escape($type) . "%'");
+
+ if ($result->num_rows) {
+ $json['service'] = array();
+ foreach ($result->rows as $row) {
+ $json['service'][$row['ShippingService']] = $row;
+ }
+ }
+
+ return $json;
+ }
+
+ public function getShippingLocations() {
+ $qry = $this->db->query("SELECT * FROM `" . DB_PREFIX . "ebay_shipping_location` WHERE `shipping_location` != 'None' AND `shipping_location` != 'Worldwide'");
+
+ if ($qry->num_rows) {
+ $json = array();
+ foreach ($qry->rows as $row) {
+ $json[] = $row;
+ }
+ return $json;
+ } else {
+ return false;
+ }
+ }
+
+ public function getEbayCategorySpecifics($category_id) {
+ $response['data'] = $this->openbay->ebay->call('listing/getEbayCategorySpecifics/', array('id' => $category_id));
+ $response['error'] = $this->openbay->ebay->lasterror;
+ $response['msg'] = $this->openbay->ebay->lastmsg;
+ return $response;
+ }
+
+ public function getCategoryFeatures($category_id) {
+ $response['data'] = $this->openbay->ebay->call('listing/getCategoryFeatures/', array('id' => $category_id));
+ $response['error'] = $this->openbay->ebay->lasterror;
+ $response['msg'] = $this->openbay->ebay->lastmsg;
+ return $response;
+ }
+
+ public function getSellerSummary() {
+ $response['data'] = $this->openbay->ebay->call('account/getSellerSummary/');
+ $response['error'] = $this->openbay->ebay->lasterror;
+ $response['msg'] = $this->openbay->ebay->lastmsg;
+
+ return $response;
+ }
+
+ public function getPaymentTypes() {
+ $cat_payment = $this->db->query("SELECT * FROM `" . DB_PREFIX . "ebay_payment_method`");
+ $payments = array();
+
+ foreach ($cat_payment->rows as $row) {
+ $payments[] = $row;
+ }
+
+ return $payments;
+ }
+
+ public function getPopularCategories() {
+ $res = $this->db->query("SELECT * FROM `" . DB_PREFIX . "ebay_category_history` ORDER BY `used` DESC LIMIT 5");
+ $cats = array();
+
+ foreach ($res->rows as $row) {
+ $cats[] = $row;
+ }
+
+ return $cats;
+ }
+
+ private function getCategoryStructure($id) {
+ $res = $this->db->query("SELECT * FROM `" . DB_PREFIX . "ebay_category` WHERE `CategoryID` = '" . $this->db->escape($id) . "' LIMIT 1");
+ return $res->row;
+ }
+
+ public function ebayVerifyAddItem($data, $options) {
+ if ($options == 'yes') {
+ $response['data'] = $this->openbay->ebay->call('listing/verifyFixedPrice/', $data);
+ } else {
+ $response['data'] = $this->openbay->ebay->call('listing/ebayVerifyAddItem/', $data);
+ }
+
+ $response['error'] = $this->openbay->ebay->lasterror;
+ $response['msg'] = $this->openbay->ebay->lastmsg;
+
+ return $response;
+ }
+
+ public function ebayAddItem($data, $options) {
+ if ($options == 'yes') {
+ $response = $this->openbay->ebay->call('listing/addFixedPrice/', $data);
+ $variant = 1;
+ } else {
+ $response = $this->openbay->ebay->call('listing/ebayAddItem/', $data);
+ $variant = 0;
+ }
+
+ $data2 = array();
+ $data2['data'] = $response;
+ $data2['error'] = $this->openbay->ebay->lasterror;
+ $data2['msg'] = $this->openbay->ebay->lastmsg;
+
+ if (!empty($response['ItemID'])) {
+ $this->openbay->ebay->createLink($data['product_id'], $response['ItemID'], $variant);
+ $this->openbay->ebay->addReserve($data, $response['ItemID'], $variant);
+
+ $item_link = $this->config->get('ebay_itm_link');
+
+ if (!empty($item_link)) {
+ $data2['data']['view_link'] = html_entity_decode($this->config->get('ebay_itm_link') . $response['ItemID']);
+ } else {
+ $data2['data']['view_link'] = '';
+ }
+ } else {
+ $data2['error'] = false;
+ $data2['msg'] = 'ok';
+ $data2['data']['Failed'] = true;
+ }
+
+ return $data2;
+ }
+
+ public function logCategoryUsed($category_id) {
+ $breadcrumb = array();
+ $original_id = $category_id;
+ $stop = false;
+ $i = 0; //fallback to stop infinate loop
+ $err = false;
+
+ while($stop == false && $i < 10) {
+ $cat = $this->getCategoryStructure($category_id);
+
+ if (!empty($cat)) {
+ $breadcrumb[] = $cat['CategoryName'];
+
+ if ($cat['CategoryParentID'] == $category_id) {
+ $stop = true;
+ } else {
+ $category_id = $cat['CategoryParentID'];
+ }
+
+ $i++;
+ } else {
+ $stop = true;
+ $err = true;
+ }
+ }
+
+ if ($err == false) {
+ $res = $this->db->query("SELECT `used` FROM `" . DB_PREFIX . "ebay_category_history` WHERE `CategoryID` = '" . $original_id . "' LIMIT 1");
+
+ if ($res->num_rows) {
+ $new = $res->row['used'] + 1;
+ $this->db->query("UPDATE `" . DB_PREFIX . "ebay_category_history` SET `used` = '" . $new . "' WHERE `CategoryID` = '" . $original_id . "' LIMIT 1");
+ } else {
+ $this->db->query("INSERT INTO `" . DB_PREFIX . "ebay_category_history` SET `CategoryID` = '" . $original_id . "', `breadcrumb` = '" . $this->db->escape(implode(' > ', array_reverse($breadcrumb))) . "', `used` = '1'");
+ }
+ }
+ }
+
+ public function getProductStock($id) {
+ $res = $this->db->query("SELECT * FROM `" . DB_PREFIX . "product` WHERE `product_id` = '" . $this->db->escape($id) . "' LIMIT 1");
+
+ if (isset($res->row['has_option']) && $res->row['has_option'] == 1) {
+ if ($this->openbay->addonLoad('openstock')) {
+ $this->load->model('extension/module/openstock');
+ $this->load->model('tool/image');
+ $variant = $this->model_setting_module_openstock->getVariants((int)$id);
+ } else {
+ $variant = 0;
+ }
+ } else {
+ $variant = 0;
+ }
+
+ return array(
+ 'qty' => $res->row['quantity'],
+ 'subtract' => (int)$res->row['subtract'],
+ 'allocated' => $this->openbay->ebay->getAllocatedStock($id),
+ 'variant' => $variant
+ );
+ }
+
+ public function getUsage() {
+ return $this->openbay->ebay->call('report/accountUse/');
+ }
+
+ public function getPlans() {
+ return $this->openbay->ebay->call('plan/getPlans/');
+ }
+
+ public function getMyPlan() {
+ return $this->openbay->ebay->call('plan/myPlan/');
+ }
+
+ public function getLiveListingArray() {
+ $qry = $this->db->query("SELECT `product_id`, `ebay_item_id` FROM `" . DB_PREFIX . "ebay_listing` WHERE `status` = 1");
+
+ $data = array();
+ if ($qry->num_rows) {
+ foreach ($qry->rows as $row) {
+ $data[$row['product_id']] = $row['ebay_item_id'];
+ }
+ }
+
+ return $data;
+ }
+
+ public function verifyCredentials() {
+ $this->request->post['domain'] = HTTPS_SERVER;
+
+ $data = $this->openbay->ebay->call('account/validate/', $this->request->post, array(), 'json', 1);
+
+ $return = array('error' => $this->openbay->ebay->lasterror, 'msg' => $this->openbay->ebay->lastmsg);
+
+ if ($this->openbay->ebay->lasterror != true) {
+ $return['data'] = $data;
+ }
+
+ return $return;
+ }
+
+ public function editSave($data) {
+ $this->openbay->ebay->log('editSave() - start..');
+
+ //get product id
+ $product_id = $this->openbay->ebay->getProductId($data['itemId']);
+
+ $this->openbay->ebay->log('editSave() - product_id: ' . $product_id);
+
+ if ($data['variant'] == 0) {
+ //save the reserve level
+ $this->openbay->ebay->updateReserve($product_id, $data['itemId'], $data['qty_reserve']);
+
+ //get the stock info
+ $stock = $this->openbay->ebay->getProductStockLevel($product_id);
+
+ //do the stock sync
+ $this->openbay->ebay->putStockUpdate($data['itemId'], $stock['quantity']);
+
+ //finish the revise item call
+ return $this->openbay->ebay->call('listing/reviseItem/', $data);
+ } else {
+ $this->openbay->ebay->log('editSave() - variant item');
+
+ $variant_data = array();
+ $this->load->model('tool/image');
+ $this->load->model('catalog/product');
+ $this->load->model('extension/module/openstock');
+
+ //get the options list for this product
+ $options = $this->model_setting_module_openstock->getVariants($product_id);
+
+ $variant_data['option_list'] = base64_encode(serialize($options[key($options)]['option_values']));
+
+ $variant_data['groups'] = $data['optGroupArray'];
+ $variant_data['related'] = $data['optGroupRelArray'];
+ $variant_data['id'] = $data['itemId'];
+
+ $stock_flag = false;
+
+ foreach ($data['opt'] as $k => $opt) {
+ //update the variant reserve level
+ $this->openbay->ebay->updateReserve($product_id, $data['itemId'], $opt['reserve'], $opt['sku'], 1);
+
+ //get the stock info
+ $stock = $this->openbay->ebay->getProductStockLevel($product_id, $opt['sku']);
+
+ $this->openbay->ebay->log('editSave() - stock: ' . serialize($stock));
+
+ if ($stock['quantity'] > 0 || $stock == true) {
+ $stock_flag = true;
+ }
+
+ // PRODUCT RESERVE LEVELS FOR VARIANT ITEMS (DOES NOT PASS THROUGH NORMAL SYSTEM)
+ $reserve = $this->openbay->ebay->getReserve($product_id, $data['itemId'], $opt['sku']);
+
+ $this->openbay->ebay->log('editSave() - reserve level: ' . $reserve);
+
+ if ($reserve != false) {
+ $this->openbay->ebay->log('editSave() / Variant (' . $opt['sku'] . ') - Reserve stock: ' . $reserve);
+
+ if ($stock['quantity'] > $reserve) {
+ $this->openbay->ebay->log('editSave() - Stock (' . $stock['quantity'] . ') is larger than reserve (' . $reserve . '), setting level to reserve');
+ $stock['quantity'] = $reserve;
+ }
+ }
+
+ $variant_data['opt'][$k]['sku'] = $opt['sku'];
+ $variant_data['opt'][$k]['qty'] = $stock['quantity'];
+ $variant_data['opt'][$k]['price'] = number_format($opt['price'], 2, '.', '');
+
+ // if any of the variants have 0 stock or no SKU set to inactive
+ if ($opt['sku'] == '' || $variant_data['opt'][$k]['qty'] < 1) {
+ $variant_data['opt'][$k]['active'] = 0;
+ } else {
+ $variant_data['opt'][$k]['active'] = $opt['active'];
+ }
+
+
+ $variant_option_values = $this->model_setting_module_openstock->getVariant($opt['product_option_variant_id']);
+
+ foreach ($variant_option_values as $variant_option_value) {
+ $variant_data['opt'][$k]['specifics'][] = array('name' => $variant_option_value['option_name'], 'value' => $variant_option_value['option_value_name']);
+ }
+ }
+
+ $this->openbay->ebay->log('editSave() - Debug - ' . serialize($variant_data));
+
+ //send to the api to process
+ if ($stock_flag == true) {
+ $this->openbay->ebay->log('editSave() - Sending to API');
+ $response = $this->openbay->ebay->call('item/reviseVariants', $variant_data);
+ return $response;
+ } else {
+ $this->openbay->ebay->log('editSave() - Ending item');
+ $this->openbay->ebay->endItem($data['itemId']);
+ }
+ }
+ }
+
+ public function getProductAttributes($product_id) {
+ $product_attribute_group_data = array();
+
+ $product_attribute_group_query = $this->db->query("SELECT ag.attribute_group_id, agd.name FROM " . DB_PREFIX . "product_attribute pa LEFT JOIN " . DB_PREFIX . "attribute a ON (pa.attribute_id = a.attribute_id) LEFT JOIN " . DB_PREFIX . "attribute_group ag ON (a.attribute_group_id = ag.attribute_group_id) LEFT JOIN " . DB_PREFIX . "attribute_group_description agd ON (ag.attribute_group_id = agd.attribute_group_id) WHERE pa.product_id = '" . (int)$product_id . "' AND agd.language_id = '" . (int)$this->config->get('config_language_id') . "' GROUP BY ag.attribute_group_id ORDER BY ag.sort_order, agd.name");
+
+ foreach ($product_attribute_group_query->rows as $product_attribute_group) {
+ $product_attribute_data = array();
+
+ $product_attribute_query = $this->db->query("SELECT a.attribute_id, ad.name, pa.text FROM " . DB_PREFIX . "product_attribute pa LEFT JOIN " . DB_PREFIX . "attribute a ON (pa.attribute_id = a.attribute_id) LEFT JOIN " . DB_PREFIX . "attribute_description ad ON (a.attribute_id = ad.attribute_id) WHERE pa.product_id = '" . (int)$product_id . "' AND a.attribute_group_id = '" . (int)$product_attribute_group['attribute_group_id'] . "' AND ad.language_id = '" . (int)$this->config->get('config_language_id') . "' AND pa.language_id = '" . (int)$this->config->get('config_language_id') . "' ORDER BY a.sort_order, ad.name");
+
+ foreach ($product_attribute_query->rows as $product_attribute) {
+ $product_attribute_data[] = array(
+ 'attribute_id' => $product_attribute['attribute_id'],
+ 'name' => $product_attribute['name'],
+ 'text' => $product_attribute['text']
+ );
+ }
+
+ $product_attribute_group_data[] = array(
+ 'attribute_group_id' => $product_attribute_group['attribute_group_id'],
+ 'name' => $product_attribute_group['name'],
+ 'attribute' => $product_attribute_data
+ );
+ }
+
+ return $product_attribute_group_data;
+ }
+}
diff --git a/public/admin/model/extension/openbay/ebay_product.php b/public/admin/model/extension/openbay/ebay_product.php
new file mode 100644
index 0000000..40c2af9
--- /dev/null
+++ b/public/admin/model/extension/openbay/ebay_product.php
@@ -0,0 +1,101 @@
+<?php
+class ModelExtensionOpenBayEbayProduct extends Model {
+ public function getTaxRate($class_id) {
+ return $this->openbay->getTaxRate($class_id);
+ }
+
+ public function countImportImages() {
+ $qry = $this->db->query("SELECT * FROM `" . DB_PREFIX . "ebay_image_import`");
+
+ return $qry->num_rows;
+ }
+
+ public function getProductOptions($product_id) {
+ $product_option_data = array();
+
+ $product_option_query = $this->db->query("SELECT * FROM " . DB_PREFIX . "product_option po LEFT JOIN `" . DB_PREFIX . "option` o ON (po.option_id = o.option_id) LEFT JOIN " . DB_PREFIX . "option_description od ON (o.option_id = od.option_id) WHERE po.product_id = '" . (int)$product_id . "' AND od.language_id = '" . (int)$this->config->get('config_language_id') . "' ORDER BY o.sort_order");
+
+ foreach ($product_option_query->rows as $product_option) {
+ if ($product_option['type'] == 'select' || $product_option['type'] == 'radio' || $product_option['type'] == 'image') {
+ $product_option_value_data = array();
+
+ $product_option_value_query = $this->db->query("SELECT * FROM " . DB_PREFIX . "product_option_value pov LEFT JOIN " . DB_PREFIX . "option_value ov ON (pov.option_value_id = ov.option_value_id) LEFT JOIN " . DB_PREFIX . "option_value_description ovd ON (ov.option_value_id = ovd.option_value_id) WHERE pov.product_option_id = '" . (int)$product_option['product_option_id'] . "' AND ovd.language_id = '" . (int)$this->config->get('config_language_id') . "' ORDER BY ov.sort_order");
+
+ foreach ($product_option_value_query->rows as $product_option_value) {
+ $product_option_value_data[] = array(
+ 'product_option_value_id' => $product_option_value['product_option_value_id'],
+ 'option_value_id' => $product_option_value['option_value_id'],
+ 'name' => $product_option_value['name'],
+ 'image' => $product_option_value['image'],
+ 'image_thumb' => (!empty($product_option_value['image'])) ? $this->model_tool_image->resize($product_option_value['image'], 100, 100) : '',
+ 'quantity' => $product_option_value['quantity'],
+ 'subtract' => $product_option_value['subtract'],
+ 'price' => $product_option_value['price'],
+ 'price_prefix' => $product_option_value['price_prefix'],
+ 'points' => $product_option_value['points'],
+ 'points_prefix' => $product_option_value['points_prefix'],
+ 'weight' => $product_option_value['weight'],
+ 'weight_prefix' => $product_option_value['weight_prefix']
+ );
+ }
+
+ $product_option_data[] = array(
+ 'product_option_id' => $product_option['product_option_id'],
+ 'option_id' => $product_option['option_id'],
+ 'name' => $product_option['name'],
+ 'type' => $product_option['type'],
+ 'product_option_value' => $product_option_value_data,
+ 'required' => $product_option['required']
+ );
+ }
+ }
+
+ return $product_option_data;
+ }
+
+ public function repairLinks() {
+ //get distinct product id's where they are active
+ $sql = $this->db->query("
+ SELECT DISTINCT `product_id`
+ FROM `" . DB_PREFIX . "ebay_listing`
+ WHERE `status` = '1'");
+
+ //loop over products and if count is more than 1, update all older entries to 0
+ foreach($sql->rows as $row) {
+ $sql2 = $this->db->query("SELECT * FROM `" . DB_PREFIX . "ebay_listing` WHERE `product_id` = '" . (int)$row['product_id'] . "' AND `status` = 1 ORDER BY `ebay_listing_id` DESC");
+
+ if ($sql2->num_rows > 1) {
+ $this->db->query("UPDATE `" . DB_PREFIX . "ebay_listing` SET `status` = 0 WHERE `product_id` = '" . (int)$row['product_id'] . "'");
+ $this->db->query("UPDATE `" . DB_PREFIX . "ebay_listing` SET `status` = 1 WHERE `ebay_listing_id` = '" . (int)$sql2->row['ebay_listing_id'] . "'");
+ }
+ }
+ }
+
+ public function searchEbayCatalog($search, $category_id, $page = 1) {
+ $response = $this->openbay->ebay->call('listing/searchCatalog/', array('page' => (int)$page, 'categoryId' => $category_id, 'search' => $search));
+
+ return $response;
+ }
+
+ public function getPartsCompatibilityOptions($category_id) {
+ $response = $this->openbay->ebay->call('partscompatibility/getOptions/', array('category_id' => $category_id));
+
+ return $response;
+ }
+
+ public function getPartsCompatibilityValues($filters) {
+ $response = $this->openbay->ebay->call('partscompatibility/getValues/', $filters);
+
+ return $response;
+ }
+
+ public function getItemRecommendations($filters) {
+ $response = $this->openbay->ebay->call('listingrecommendation/recommendations/', $filters);
+
+ return array(
+ 'error' => $this->openbay->ebay->lasterror,
+ 'error_message' => $this->openbay->ebay->lastmsg,
+ 'data' => $response
+ );
+ }
+} \ No newline at end of file
diff --git a/public/admin/model/extension/openbay/ebay_profile.php b/public/admin/model/extension/openbay/ebay_profile.php
new file mode 100644
index 0000000..0099039
--- /dev/null
+++ b/public/admin/model/extension/openbay/ebay_profile.php
@@ -0,0 +1,106 @@
+<?php
+class ModelExtensionOpenBayEbayProfile extends Model{
+ public function add($data) {
+ if ($data['default'] == 1) {
+ $this->clearDefault($data['type']);
+ }
+
+ $this->db->query("INSERT INTO `" . DB_PREFIX . "ebay_profile` SET `name` = '" . $this->db->escape($data['name']) . "', `description` = '" . $this->db->escape($data['description']) . "', `type` = '" . (int)$data['type'] . "', `default` = '" . (int)$data['default'] . "', `data` = '" . $this->db->escape(serialize($data['data'])) . "'");
+
+ return $this->db->getLastId();
+ }
+
+ public function edit($id, $data) {
+ if ($data['default'] == 1) {
+ $this->clearDefault($data['type']);
+ }
+
+ $this->db->query("UPDATE `" . DB_PREFIX . "ebay_profile` SET `name` = '" . $this->db->escape($data['name']) . "', `description` = '" . $this->db->escape($data['description']) . "', `data` = '" . $this->db->escape(serialize($data['data'])) . "', `default` = '" . (int)$data['default'] . "' WHERE `ebay_profile_id` = '" . (int)$id . "' LIMIT 1");
+ }
+
+ public function delete($id) {
+ $this->db->query("DELETE FROM `" . DB_PREFIX . "ebay_profile` WHERE `ebay_profile_id` = '" . (int)$id . "' LIMIT 1");
+
+ if ($this->db->countAffected() > 0) {
+ return true;
+ } else {
+ return false;
+ }
+ }
+
+ public function get($id) {
+ $qry = $this->db->query("SELECT * FROM `" . DB_PREFIX . "ebay_profile` WHERE `ebay_profile_id` = '" . (int)$id . "' LIMIT 1");
+
+ if ($qry->num_rows) {
+ $row = $qry->row;
+ $row['link_edit'] = $this->url->link('extension/openbay/ebay_profile/edit', 'user_token=' . $this->session->data['user_token'] . '&ebay_profile_id=' . $row['ebay_profile_id'], true);
+ $row['link_delete'] = $this->url->link('extension/openbay/ebay_profile/delete', 'user_token=' . $this->session->data['user_token'] . '&ebay_profile_id=' . $row['ebay_profile_id'], true);
+ $row['data'] = unserialize($row['data']);
+
+ return $row;
+ } else {
+ return false;
+ }
+ }
+
+ public function getAll($type = '') {
+ $sql = "SELECT * FROM `" . DB_PREFIX . "ebay_profile`";
+
+ if ($type !== '') {
+ $sql .= " WHERE `type` = '" . (int)$type . "'";
+ }
+
+ $qry = $this->db->query($sql);
+
+ if ($qry->num_rows) {
+ $profiles = array();
+ foreach ($qry->rows as $row) {
+ $row['link_edit'] = $this->url->link('extension/openbay/ebay_profile/edit', 'user_token=' . $this->session->data['user_token'] . '&ebay_profile_id=' . $row['ebay_profile_id'], true);
+ $row['link_delete'] = $this->url->link('extension/openbay/ebay_profile/delete', 'user_token=' . $this->session->data['user_token'] . '&ebay_profile_id=' . $row['ebay_profile_id'], true);
+ $row['data'] = !empty($row['data']) ? unserialize($row['data']) : array();
+ $profiles[] = $row;
+ }
+
+ return $profiles;
+ } else {
+ return false;
+ }
+ }
+
+ public function getTypes() {
+ $types = array(
+ 0 => array(
+ 'name' => $this->language->get('text_type_shipping'),
+ 'template' => 'extension/openbay/ebay_profile_form_shipping'
+ ),
+ 1 => array(
+ 'name' => $this->language->get('text_type_returns'),
+ 'template' => 'extension/openbay/ebay_profile_form_returns'
+ ),
+ 2 => array(
+ 'name' => $this->language->get('text_type_template'),
+ 'template' => 'extension/openbay/ebay_profile_form_template'
+ ),
+ 3 => array(
+ 'name' => $this->language->get('text_type_general'),
+ 'template' => 'extension/openbay/ebay_profile_form_generic'
+ )
+ );
+
+ return $types;
+ }
+
+ public function getDefault($type) {
+ $qry = $this->db->query("SELECT `ebay_profile_id` FROM `" . DB_PREFIX . "ebay_profile` WHERE `type` = '" . (int)$type . "' AND `default` = '1'LIMIT 1");
+
+ if ($qry->num_rows) {
+ return (int)$qry->row['ebay_profile_id'];
+ } else {
+ return false;
+ }
+ }
+
+ private function clearDefault($type) {
+ $this->db->query("UPDATE `" . DB_PREFIX . "ebay_profile` SET `default` = '0' WHERE `type` = '" . (int)$type . "'");
+ }
+} \ No newline at end of file
diff --git a/public/admin/model/extension/openbay/ebay_template.php b/public/admin/model/extension/openbay/ebay_template.php
new file mode 100644
index 0000000..b367059
--- /dev/null
+++ b/public/admin/model/extension/openbay/ebay_template.php
@@ -0,0 +1,51 @@
+<?php
+class ModelExtensionOpenBayEbayTemplate extends Model {
+ public function add($data) {
+ $this->db->query("INSERT INTO `" . DB_PREFIX . "ebay_template` SET `name` = '" . $this->db->escape($data['name']) . "', `html` = '" . $this->db->escape($data['html']) . "'");
+ return $this->db->getLastId();
+ }
+
+ public function edit($id, $data) {
+ $this->db->query("UPDATE `" . DB_PREFIX . "ebay_template` SET `name` = '" . $this->db->escape($data['name']) . "', `html` = '" . $this->db->escape($data['html']) . "' WHERE `template_id` = '" . (int)$id . "' LIMIT 1");
+ }
+
+ public function delete($id) {
+ $qry = $this->db->query("DELETE FROM `" . DB_PREFIX . "ebay_template` WHERE `template_id` = '" . (int)$id . "' LIMIT 1");
+
+ if ($qry->countAffected() > 0) {
+ return true;
+ }else{
+ return false;
+ }
+ }
+
+ public function get($id) {
+ $qry = $this->db->query("SELECT * FROM `" . DB_PREFIX . "ebay_template` WHERE `template_id` = '" . (int)$id . "' LIMIT 1");
+
+ if ($qry->num_rows) {
+ $row = $qry->row;
+ $row['link_edit'] = $this->url->link('extension/openbay/ebay_template/edit&user_token=' . $this->session->data['user_token'] . '&template_id=' . $row['template_id'], true);
+ $row['link_delete'] = $this->url->link('extension/openbay/ebay_template/delete&user_token=' . $this->session->data['user_token'] . '&template_id=' . $row['template_id'], true);
+
+ return $row;
+ }else{
+ return false;
+ }
+ }
+
+ public function getAll() {
+ $qry = $this->db->query("SELECT * FROM `" . DB_PREFIX . "ebay_template`");
+
+ $templates = array();
+
+ if($qry->num_rows) {
+ foreach($qry->rows as $row) {
+ $row['link_edit'] = $this->url->link('extension/openbay/ebay_template/edit&user_token=' . $this->session->data['user_token'] . '&template_id=' . $row['template_id'], true);
+ $row['link_delete'] = $this->url->link('extension/openbay/ebay_template/delete&user_token=' . $this->session->data['user_token'] . '&template_id=' . $row['template_id'], true);
+ $templates[] = $row;
+ }
+ }
+
+ return $templates;
+ }
+}
diff --git a/public/admin/model/extension/openbay/etsy.php b/public/admin/model/extension/openbay/etsy.php
new file mode 100644
index 0000000..fec7862
--- /dev/null
+++ b/public/admin/model/extension/openbay/etsy.php
@@ -0,0 +1,73 @@
+<?php
+class ModelExtensionOpenBayEtsy extends Model{
+ public function install() {
+ $this->load->model('setting/event');
+
+ $this->model_setting_event->addEvent('openbay_etsy_add_order', 'catalog/model/checkout/order/addOrderHistory/after', 'extension/openbay/etsy/eventAddOrderHistory');
+
+ $settings = array();
+ $settings["etsy_token"] = '';
+ $settings["etsy_secret"] = '';
+ $settings["etsy_encryption_key"] = '';
+ $settings["etsy_encryption_iv"] = '';
+ $settings["etsy_logging"] = '1';
+
+ $this->model_setting_setting->editSetting('etsy', $settings);
+
+ $this->db->query("
+ CREATE TABLE IF NOT EXISTS `" . DB_PREFIX . "etsy_setting_option` (
+ `etsy_setting_option_id` INT(11) NOT NULL AUTO_INCREMENT,
+ `key` VARCHAR(100) NOT NULL,
+ `last_updated` DATETIME NOT NULL,
+ `data` TEXT NOT NULL,
+ PRIMARY KEY (`etsy_setting_option_id`)
+ ) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_general_ci;");
+
+ $this->db->query("
+ CREATE TABLE IF NOT EXISTS `" . DB_PREFIX . "etsy_listing` (
+ `etsy_listing_id` int(11) NOT NULL AUTO_INCREMENT,
+ `etsy_item_id` char(100) NOT NULL,
+ `product_id` int(11) NOT NULL,
+ `status` SMALLINT(3) NOT NULL DEFAULT '1',
+ `created` DATETIME NOT NULL,
+ PRIMARY KEY (`etsy_listing_id`),
+ KEY `product_id` (`product_id`)
+ ) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_general_ci;");
+
+ $this->db->query("
+ CREATE TABLE IF NOT EXISTS `" . DB_PREFIX . "etsy_order` (
+ `etsy_order_id` int(11) NOT NULL AUTO_INCREMENT,
+ `order_id` int(11) NOT NULL,
+ `receipt_id` int(11) NOT NULL,
+ `paid` int(1) NOT NULL,
+ `shipped` int(1) NOT NULL,
+ PRIMARY KEY (`etsy_order_id`),
+ KEY `order_id` (`order_id`)
+ ) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_general_ci;");
+
+ $this->db->query("
+ CREATE TABLE IF NOT EXISTS `" . DB_PREFIX . "etsy_order_lock` (
+ `order_id` int(11) NOT NULL,
+ PRIMARY KEY (`order_id`)
+ ) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_general_ci;");
+ }
+
+ public function uninstall() {
+ $this->load->model('setting/event');
+ $this->model_setting_event->deleteEventByCode('openbay_etsy_add_order');
+ }
+
+ public function patch() {
+ if ($this->config->get('etsy_status') == 1) {
+
+ }
+ }
+
+ public function verifyAccount() {
+ if ($this->openbay->etsy->validate() == true) {
+ return $this->openbay->etsy->call('v1/etsy/account/info/', 'GET');
+ } else {
+ return false;
+ }
+ }
+}
diff --git a/public/admin/model/extension/openbay/etsy_product.php b/public/admin/model/extension/openbay/etsy_product.php
new file mode 100644
index 0000000..876ef16
--- /dev/null
+++ b/public/admin/model/extension/openbay/etsy_product.php
@@ -0,0 +1,75 @@
+<?php
+class ModelExtensionOpenBayEtsyProduct extends Model{
+ public function getStatus($product_id) {
+ $query = $this->db->query("SELECT * FROM `" . DB_PREFIX . "etsy_listing` WHERE `product_id` = '" . (int)$product_id . "' AND `status` = 1 LIMIT 1");
+
+ if ($query->num_rows == 0) {
+ return 0;
+ } else {
+ return 1;
+ }
+ }
+
+ public function totalLinked() {
+ $sql = "SELECT COUNT(DISTINCT p.product_id) AS total
+ FROM `" . DB_PREFIX . "etsy_listing` `el`
+ LEFT JOIN `" . DB_PREFIX . "product` `p` ON (`el`.`product_id` = `p`.`product_id`)
+ LEFT JOIN `" . DB_PREFIX . "product_description` `pd` ON (`p`.`product_id` = `pd`.`product_id`)
+ WHERE `el`.`status` = '1'
+ AND `pd`.`language_id` = '" . (int)$this->config->get('config_language_id') . "'";
+
+ $query = $this->db->query($sql);
+
+ return (int)$query->row['total'];
+ }
+
+ public function addLink($product_id, $etsy_item_id, $status_id = 0) {
+ $this->db->query("INSERT INTO `" . DB_PREFIX . "etsy_listing` SET `product_id` = '" . (int)$product_id . "', `etsy_item_id` = '" . $this->db->escape($etsy_item_id) . "', `status` = '" . (int)$status_id . "', `created` = now()");
+ }
+
+ public function loadLinked($limit = 100, $page = 1) {
+ $this->load->model('tool/image');
+
+ $start = $limit * ($page - 1);
+
+ $sql = "
+ SELECT
+ `el`.`etsy_listing_id`,
+ `el`.`etsy_item_id`,
+ `el`.`status`,
+ `p`.`product_id`,
+ `p`.`sku`,
+ `p`.`model`,
+ `p`.`quantity`,
+ `pd`.`name`
+ FROM `" . DB_PREFIX . "etsy_listing` `el`
+ LEFT JOIN `" . DB_PREFIX . "product` `p` ON (`el`.`product_id` = `p`.`product_id`)
+ LEFT JOIN `" . DB_PREFIX . "product_description` `pd` ON (`p`.`product_id` = `pd`.`product_id`)
+ WHERE `el`.`status` = '1'
+ AND `pd`.`language_id` = '" . (int)$this->config->get('config_language_id') . "'";
+
+ $sql .= " LIMIT " . (int)$start . "," . (int)$limit;
+
+ $qry = $this->db->query($sql);
+
+ $data = array();
+ if ($qry->num_rows) {
+ foreach($qry->rows as $row) {
+ $data[] = array(
+ 'etsy_listing_id' => $row['etsy_listing_id'],
+ 'product_id' => $row['product_id'],
+ 'sku' => $row['sku'],
+ 'model' => $row['model'],
+ 'quantity' => $row['quantity'],
+ 'name' => $row['name'],
+ 'status' => $row['status'],
+ 'etsy_item_id' => $row['etsy_item_id'],
+ 'link_edit' => $this->url->link('catalog/product/edit', 'user_token=' . $this->session->data['user_token'] . '&product_id=' . $row['product_id'], true),
+ 'link_etsy' => 'http://www.etsy.com/listing/' . $row['etsy_item_id'],
+ );
+ }
+ }
+
+ return $data;
+ }
+} \ No newline at end of file
diff --git a/public/admin/model/extension/openbay/fba.php b/public/admin/model/extension/openbay/fba.php
new file mode 100644
index 0000000..f74641d
--- /dev/null
+++ b/public/admin/model/extension/openbay/fba.php
@@ -0,0 +1,65 @@
+<?php
+class ModelExtensionOpenBayFba extends Model {
+ public function install() {
+ $this->load->model('setting/event');
+
+ $this->model_setting_event->addEvent('openbay_fba_add_order', 'catalog/model/checkout/order/addOrder/after', 'extension/openbay/fba/eventAddOrder');
+ $this->model_setting_event->addEvent('openbay_fba_add_orderhistory', 'catalog/model/checkout/order/addOrderHistory/after', 'extension/openbay/fba/eventAddOrderHistory');
+
+ $this->db->query("
+ CREATE TABLE IF NOT EXISTS `" . DB_PREFIX . "fba_order` (
+ `order_id` INT(11) NOT NULL,
+ `fba_order_fulfillment_id` INT(11) NOT NULL,
+ `fba_order_fulfillment_ref` CHAR(50) NOT NULL,
+ `status` CHAR(10) NOT NULL,
+ `created` DATETIME NOT NULL,
+ KEY `fba_order_id` (`order_id`)
+ ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_general_ci;");
+
+ $this->db->query("
+ CREATE TABLE IF NOT EXISTS `" . DB_PREFIX . "fba_order_fulfillment` (
+ `fba_order_fulfillment_id` INT(11) NOT NULL AUTO_INCREMENT,
+ `order_id` INT(11) NOT NULL,
+ `created` DATETIME NOT NULL,
+ `request_body` TEXT NOT NULL,
+ `response_body` TEXT NOT NULL,
+ `response_header_code` INT(3) NOT NULL,
+ `type` INT(3) NOT NULL,
+ PRIMARY KEY (`fba_order_fulfillment_id`),
+ KEY `order_id` (`order_id`)
+ ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_general_ci;");
+
+ // Default settings
+ $setting = array();
+ $setting["openbay_fba_status"] = 0;
+ $setting["openbay_fba_send_orders"] = 0;
+ $setting["openbay_fba_debug_log"] = 1;
+ $setting["openbay_fba_order_trigger_status"] = 15;
+ $setting["openbay_fba_cancel_order_trigger_status"] = 7;
+ $setting["openbay_fba_fulfill_policy"] = 'FillAllAvailable';
+ $setting["openbay_fba_shipping_speed"] = 'Standard';
+ $setting["openbay_fba_order_prefix"] = 'OC-';
+
+ $this->model_setting_setting->editSetting('openbay_fba', $setting);
+ }
+
+ public function uninstall() {
+ $this->db->query("DELETE FROM `" . DB_PREFIX . "setting` WHERE `code` = 'openbay_fba'");
+
+ $this->load->model('setting/event');
+ $this->model_setting_event->deleteEventByCode('openbay_fba_add_order');
+ $this->model_setting_event->deleteEventByCode('openbay_fba_add_orderhistory');
+ }
+
+ public function patch() {
+ if ($this->config->get('openbay_fba_status') == 1) {
+
+ }
+ }
+
+ public function countFbaOrders() {
+ $query = $this->db->query("SELECT COUNT(*) AS `total` FROM `" . DB_PREFIX . "fba_order`");
+
+ return (int)$query->row['total'];
+ }
+}
diff --git a/public/admin/model/extension/openbay/openbay.php b/public/admin/model/extension/openbay/openbay.php
new file mode 100644
index 0000000..c40c357
--- /dev/null
+++ b/public/admin/model/extension/openbay/openbay.php
@@ -0,0 +1,761 @@
+<?php
+class ModelExtensionOpenBayOpenbay extends Model {
+ private $url = 'https://account.openbaypro.com/';
+ private $error;
+ private $branch_version = 6;
+
+ public function patch() {
+
+ }
+
+ public function updateTest() {
+ $this->error = array();
+
+ $this->openbay->log('Starting update test');
+
+ if (!function_exists("exception_error_handler")) {
+ function exception_error_handler($errno, $errstr, $errfile, $errline ) {
+ throw new ErrorException($errstr, 0, $errno, $errfile, $errline);
+ }
+ }
+
+ set_error_handler('exception_error_handler');
+
+ // create a tmp folder
+ if (!is_dir(DIR_DOWNLOAD . '/tmp')) {
+ try {
+ mkdir(DIR_DOWNLOAD . '/tmp');
+ } catch(ErrorException $ex) {
+ $this->error[] = $ex->getMessage();
+ }
+ }
+
+ // create tmp file
+ try {
+ $tmp_file = fopen(DIR_DOWNLOAD . '/tmp/test_file.php', 'w+');
+ } catch(ErrorException $ex) {
+ $this->error[] = $ex->getMessage();
+ }
+
+ // open and write over tmp file
+ try {
+ $output = '<?php' . "\n";
+ $output .= '$test = \'12345\';' . "\n";
+ $output .= 'echo $test;' . "\n";
+
+ fwrite($tmp_file, $output);
+ fclose($tmp_file);
+ } catch(ErrorException $ex) {
+ $this->error[] = $ex->getMessage();
+ }
+
+ // try and read the file
+
+ // remove tmp file
+ try {
+ unlink(DIR_DOWNLOAD . '/tmp/test_file.php');
+ } catch(ErrorException $ex) {
+ $this->error[] = $ex->getMessage();
+ }
+
+ // delete tmp folder
+ try {
+ rmdir(DIR_DOWNLOAD . '/tmp');
+ } catch(ErrorException $ex) {
+ $this->error[] = $ex->getMessage();
+ }
+
+ // reset to the OC error handler
+ restore_error_handler();
+
+ $this->openbay->log('Finished update test');
+
+ if (!$this->error) {
+ $this->openbay->log('Finished update test - no errors');
+ return array('error' => 0, 'response' => '', 'percent_complete' => 20, 'status_message' => $this->language->get('text_check_new'));
+ } else {
+ $this->openbay->log('Finished update test - errors: ' . print_r($this->error));
+ return array('error' => 1, 'response' => $this->error);
+ }
+ }
+
+ public function updateCheckVersion($beta = 0) {
+ $current_version = $this->config->get('feed_openbaypro_version');
+
+ $this->openbay->log('Start check version, beta: ' . $beta . ', current: ' . $current_version);
+
+ $post = array('version' => $this->branch_version, 'beta' => $beta);
+
+ $data = $this->call('update/version/', $post);
+
+ if ($this->lasterror == true) {
+ $this->openbay->log('Check version error: ' . $this->lastmsg);
+
+ return array('error' => 1, 'response' => $this->lastmsg . ' (' . VERSION . ')');
+ } else {
+ if ($data['version'] > $current_version) {
+ $this->openbay->log('Check version new available: ' . $data['version']);
+ return array('error' => 0, 'response' => $data['version'], 'percent_complete' => 40, 'status_message' => $this->language->get('text_downloading'));
+ } else {
+ $this->openbay->log('Check version - already latest');
+ return array('error' => 1, 'response' => $this->language->get('text_version_ok') . $current_version);
+ }
+ }
+ }
+
+ public function updateDownload($beta = 0) {
+ $this->openbay->log('Downloading');
+
+ $local_file = DIR_DOWNLOAD . '/openbaypro_update.zip';
+ $handle = fopen($local_file, "w+");
+
+ $post = array('version' => $this->branch_version, 'beta' => $beta);
+
+ $defaults = array(
+ CURLOPT_POST => 1,
+ CURLOPT_HEADER => 0,
+ CURLOPT_URL => $this->url . 'update/download/',
+ CURLOPT_USERAGENT => 'OpenBay Pro update script',
+ CURLOPT_FRESH_CONNECT => 1,
+ CURLOPT_RETURNTRANSFER => 1,
+ CURLOPT_FORBID_REUSE => 1,
+ CURLOPT_TIMEOUT => 0,
+ CURLOPT_SSL_VERIFYPEER => 0,
+ CURLOPT_SSL_VERIFYHOST => 0,
+ CURLOPT_POSTFIELDS => http_build_query($post, '', "&"),
+ CURLOPT_FILE => $handle
+ );
+
+ $curl = curl_init();
+ curl_setopt_array($curl, $defaults);
+ curl_exec($curl);
+
+ $curl_error = curl_error ($curl);
+
+ $this->openbay->log('Download errors: ' . $curl_error);
+
+ curl_close($curl);
+
+ return array('error' => 0, 'response' => $curl_error, 'percent_complete' => 60, 'status_message' => $this->language->get('text_extracting'));
+ }
+
+ public function updateExtract() {
+ $this->error = array();
+
+ $web_root = preg_replace('/system\/$/', '', DIR_SYSTEM);
+
+ if (!function_exists("exception_error_handler")) {
+ function exception_error_handler($errno, $errstr, $errfile, $errline ) {
+ throw new ErrorException($errstr, 0, $errno, $errfile, $errline);
+ }
+ }
+
+ set_error_handler('exception_error_handler');
+
+ try {
+ $zip = new ZipArchive();
+
+ if ($zip->open(DIR_DOWNLOAD . 'openbaypro_update.zip')) {
+ $zip->extractTo($web_root);
+ $zip->close();
+ } else {
+ $this->openbay->log('Unable to extract update files');
+
+ $this->error[] = $this->language->get('text_fail_patch');
+ }
+ } catch(ErrorException $ex) {
+ $this->openbay->log('Unable to extract update files');
+ $this->error[] = $ex->getMessage();
+ }
+
+ // reset to the OC error handler
+ restore_error_handler();
+
+ if (!$this->error) {
+ return array('error' => 0, 'response' => '', 'percent_complete' => 80, 'status_message' => $this->language->get('text_remove_files'));
+ } else {
+ return array('error' => 1, 'response' => $this->error);
+ }
+ }
+
+ public function updateRemove($beta = 0) {
+ $this->error = array();
+
+ $web_root = preg_replace('/system\/$/', '', DIR_SYSTEM);
+
+ if (!function_exists("exception_error_handler")) {
+ function exception_error_handler($errno, $errstr, $errfile, $errline ) {
+ throw new ErrorException($errstr, 0, $errno, $errfile, $errline);
+ }
+ }
+
+ $this->openbay->log('Get files to remove, beta: ' . $beta);
+
+ $post = array('beta' => $beta);
+
+ $files = $this->call('update/getRemoveList/', $post);
+
+ $this->openbay->log("Remove Files: " . print_r($files, 1));
+
+ if (!empty($files['asset']) && is_array($files['asset'])) {
+ foreach($files['asset'] as $file) {
+ $filename = $web_root . implode('/', $file['locations']['location']) . '/' . $file['name'];
+
+ if (file_exists($filename)) {
+ try {
+ unlink($filename);
+ } catch(ErrorException $ex) {
+ $this->openbay->log('Unable to remove file: ' . $filename . ', ' . $ex->getMessage());
+ $this->error[] = $filename;
+ }
+ }
+ }
+ }
+
+ // reset to the OC error handler
+ restore_error_handler();
+
+ if (!$this->error) {
+ return array('error' => 0, 'response' => '', 'percent_complete' => 90, 'status_message' => $this->language->get('text_running_patch'));
+ } else {
+ $response_error = '<p>' . $this->language->get('error_file_delete') . '</p>';
+ $response_error .= '<ul>';
+
+ foreach($this->error as $error_file) {
+ $response_error .= '<li>' . $error_file . '</li>';
+ }
+
+ $response_error .= '</ul>';
+
+ return array('error' => 1, 'response' => $response_error, 'percent_complete' => 90, 'status_message' => $this->language->get('text_running_patch'));
+ }
+ }
+
+ public function updateUpdateVersion($beta = 0) {
+ $this->openbay->log('Updating the version in settings');
+
+ $post = array('version' => $this->branch_version, 'beta' => $beta);
+
+ $data = $this->call('update/version/', $post);
+
+ if ($this->lasterror == true) {
+ $this->openbay->log('Update version error: ' . $this->lastmsg);
+
+ return array('error' => 1, 'response' => $this->lastmsg . ' (' . VERSION . ')');
+ } else {
+ $this->load->model('setting/setting');
+
+ $settings = $this->model_setting_setting->getSetting('feed_openbaypro');
+
+ $settings['feed_openbaypro_version'] = $data['version'];
+
+ $this->model_setting_setting->editSetting('feed_openbaypro', $settings);
+
+ return array('error' => 0, 'response' => $data['version'], 'percent_complete' => 100, 'status_message' => $this->language->get('text_updated_ok') . $data['version']);
+ }
+ }
+
+ public function setUrl($url) {
+ $this->url = $url;
+ }
+
+ public function getNotifications() {
+ $data = $this->call('update/getNotifications/');
+ return $data;
+ }
+
+ public function version() {
+ $data = $this->call('update/getStableVersion/');
+
+ if ($this->lasterror == true) {
+ $data = array(
+ 'error' => true,
+ 'msg' => $this->lastmsg . ' (' . VERSION . ')',
+ );
+
+ return $data;
+ } else {
+ return $data;
+ }
+ }
+
+ public function faqGet($route) {
+ if ($this->faqIsDismissed($route) != true) {
+ $data = $this->call('faq/get/', array('route' => $route));
+
+ return $data;
+ } else {
+ return false;
+ }
+ }
+
+ public function faqIsDismissed($route) {
+ $this->faqDbTableCheck();
+
+ $sql = $this->db->query("SELECT * FROM `" . DB_PREFIX . "openbay_faq` WHERE `route` = '" . $this->db->escape($route) . "'");
+
+ if ($sql->num_rows > 0) {
+ return true;
+ } else {
+ return false;
+ }
+ }
+
+ public function faqDismiss($route) {
+ $this->faqDbTableCheck();
+ $this->db->query("INSERT INTO `" . DB_PREFIX . "openbay_faq` SET `route` = '" . $this->db->escape($route) . "'");
+ }
+
+ public function faqClear() {
+ $this->faqDbTableCheck();
+ $this->db->query("TRUNCATE `" . DB_PREFIX . "openbay_faq`");
+ }
+
+ public function faqDbTableCheck() {
+ if (!$this->openbay->testDbTable(DB_PREFIX . "openbay_faq")) {
+ $this->db->query("CREATE TABLE IF NOT EXISTS `" . DB_PREFIX . "openbay_faq` (`id` int(11) NOT NULL AUTO_INCREMENT,`route` text NOT NULL, PRIMARY KEY (`id`)) ENGINE=MyISAM DEFAULT CHARSET=utf8;");
+ }
+ }
+
+ public function requirementTest() {
+ $error = array();
+
+ // check for mkdir enabled
+ if (!function_exists('mkdir')) {
+ $error[] = $this->language->get('error_mkdir');
+ }
+
+ if (!function_exists('openssl_encrypt')) {
+ $error[] = $this->language->get('error_openssl_encrypt');
+ }
+
+ if (!function_exists('openssl_decrypt')) {
+ $error[] = $this->language->get('error_openssl_decrypt');
+ }
+
+ if (!function_exists('fopen')) {
+ $error[] = $this->language->get('error_fopen');
+ }
+
+ if (!function_exists('set_time_limit')) {
+ $error[] = $this->language->get('error_fopen');
+ }
+
+ if (!ini_get('allow_url_fopen')) {
+ $error[] = $this->language->get('error_url_fopen');
+ }
+
+ if (!extension_loaded('curl')) {
+ $error[] = $this->language->get('error_curl');
+ }
+
+ if (!extension_loaded('zip')) {
+ $error[] = $this->language->get('error_zip');
+ }
+
+ if (!function_exists('mb_detect_encoding')) {
+ $error[] = $this->language->get('error_mbstring');
+ }
+
+ return $error;
+ }
+
+ private function call($call, array $post = null, array $options = array(), $content_type = 'json') {
+ $data = array(
+ 'language' => $this->config->get('feed_openbaypro_language'),
+ 'server' => 1,
+ 'domain' => HTTP_CATALOG,
+ 'openbay_version' => (int)$this->config->get('feed_openbaypro_version'),
+ 'data' => $post,
+ 'content_type' => $content_type,
+ 'ocversion' => VERSION
+ );
+
+ $useragent = "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8.1.1) Gecko/20061204 Firefox/2.0.0.1";
+
+ $defaults = array(
+ CURLOPT_POST => 1,
+ CURLOPT_HEADER => 0,
+ CURLOPT_URL => $this->url . $call,
+ CURLOPT_USERAGENT => $useragent,
+ CURLOPT_FRESH_CONNECT => 1,
+ CURLOPT_RETURNTRANSFER => 1,
+ CURLOPT_FORBID_REUSE => 1,
+ CURLOPT_TIMEOUT => 0,
+ CURLOPT_SSL_VERIFYPEER => 0,
+ CURLOPT_SSL_VERIFYHOST => 0,
+ CURLOPT_POSTFIELDS => http_build_query($data, '', "&")
+ );
+
+ $curl = curl_init();
+ curl_setopt_array($curl, ($options + $defaults));
+ $result = curl_exec($curl);
+ curl_close($curl);
+
+ if ($content_type == 'json') {
+ $encoding = mb_detect_encoding($result);
+
+ /* some json data may have BOM due to php not handling types correctly */
+ if ($encoding == 'UTF-8') {
+ $result = preg_replace('/[^(\x20-\x7F)]*/', '', $result);
+ }
+
+ $result = json_decode($result, 1);
+ $this->lasterror = $result['error'];
+ $this->lastmsg = $result['msg'];
+
+ if (!empty($result['data'])) {
+ return $result['data'];
+ } else {
+ return false;
+ }
+ } elseif ($content_type == 'xml') {
+ $result = simplexml_load_string($result);
+ $this->lasterror = $result->error;
+ $this->lastmsg = $result->msg;
+
+ if (!empty($result->data)) {
+ return $result->data;
+ } else {
+ return false;
+ }
+ }
+ }
+
+ public function getTotalProducts($data = array()) {
+ $sql = "SELECT COUNT(DISTINCT p.product_id) AS total FROM " . DB_PREFIX . "product p LEFT JOIN " . DB_PREFIX . "product_description pd ON (p.product_id = pd.product_id)";
+
+ if (!empty($data['filter_category'])) {
+ $sql .= " LEFT JOIN " . DB_PREFIX . "product_to_category p2c ON (p.product_id = p2c.product_id)";
+ }
+
+ if ($data['filter_market_name'] == 'ebay') {
+ $sql .= " LEFT JOIN `" . DB_PREFIX . "ebay_listing` `ebay` ON (`p`.`product_id` = `ebay`.`product_id`)";
+
+ if ($data['filter_market_id'] == 0) {
+ $sql .= " LEFT JOIN (SELECT product_id, IF( SUM( `status` ) = 0, 0, 1 ) AS 'listing_status' FROM " . DB_PREFIX . "ebay_listing GROUP BY product_id ) ebay2 ON (p.product_id = ebay2.product_id)";
+ }
+ }
+
+ if ($data['filter_market_name'] == 'amazon') {
+ if ($data['filter_market_id'] <= 4) {
+ $sql .= " LEFT JOIN " . DB_PREFIX . "amazon_product ap ON p.product_id = ap.product_id";
+ } else {
+ $sql .= " LEFT JOIN " . DB_PREFIX . "amazon_product_link apl ON p.product_id = apl.product_id";
+ }
+
+ $amazon_status = array(
+ 1 => 'saved',
+ 2 => 'uploaded',
+ 3 => 'ok',
+ 4 => 'error',
+ 5 => 'amazon_linked',
+ 6 => 'amazon_not_linked',
+ );
+ }
+
+ $sql .= " WHERE pd.language_id = '" . (int)$this->config->get('config_language_id') . "'";
+
+ if (!empty($data['filter_category'])) {
+ if ($data['filter_category'] == 'none') {
+ $sql .= " AND p2c.category_id IS NULL";
+ } else {
+ $sql .= " AND p2c.category_id = '" . (int)$data['filter_category'] . "'";
+ }
+ }
+
+ if ($data['filter_market_name'] == 'ebay') {
+ if ($data['filter_market_id'] == 0) {
+ $sql .= " AND (ebay.ebay_listing_id IS NULL OR ebay2.listing_status = 0)";
+ } else {
+ $sql .= " AND (ebay.ebay_listing_id IS NOT NULL AND ebay.status = 1)";
+ }
+ }
+
+ if ($data['filter_market_name'] == 'amazon') {
+ if ($data['filter_market_id'] == 0) {
+ $sql .= " AND ap.product_id IS NULL ";
+ } elseif ($data['filter_market_id'] == 5) {
+ $sql .= " AND apl.id IS NOT NULL";
+ } elseif ($data['filter_market_id'] == 6) {
+ $sql .= " AND apl.id IS NULL";
+ } else {
+ $sql .= " AND FIND_IN_SET('" . $this->db->escape($amazon_status[$data['filter_market_id']]) . "', ap.`status`) != 0";
+ }
+ }
+
+ if (isset($data['filter_name']) && !empty($data['filter_name']) && !is_null($data['filter_name'])) {
+ $sql .= " AND pd.name LIKE '" . $this->db->escape($data['filter_name']) . "%'";
+ }
+ if (isset($data['filter_model']) && !empty($data['filter_model']) && !is_null($data['filter_model'])) {
+ $sql .= " AND p.model LIKE '" . $this->db->escape($data['filter_model']) . "%'";
+ }
+ if (isset($data['filter_price']) && !empty($data['filter_price']) && !is_null($data['filter_price'])) {
+ $sql .= " AND p.price >= '" . (double)$data['filter_price'] . "'";
+ }
+ if (isset($data['filter_price_to']) && !empty($data['filter_price_to']) && !is_null($data['filter_price_to'])) {
+ $sql .= " AND p.price <= '" . (double)$data['filter_price_to'] . "'";
+ }
+ if (isset($data['filter_quantity']) && !empty($data['filter_quantity']) && !is_null($data['filter_quantity'])) {
+ $sql .= " AND p.quantity >= " . (int)$data['filter_quantity'];
+ }
+ if (isset($data['filter_quantity_to']) && !empty($data['filter_quantity_to']) && !is_null($data['filter_quantity_to'])) {
+ $sql .= " AND p.quantity <= " . (int)$data['filter_quantity_to'];
+ }
+ if (isset($data['filter_status']) && !empty($data['filter_status']) && !is_null($data['filter_status'])) {
+ $sql .= " AND p.status = " . (int)$data['filter_status'];
+ }
+ if (isset($data['filter_sku']) && !empty($data['filter_sku']) && !is_null($data['filter_sku'])) {
+ $sql .= " AND p.sku != ''";
+ }
+ if (isset($data['filter_desc']) && !empty($data['filter_desc']) && !is_null($data['filter_desc'])) {
+ $sql .= " AND pd.description != ''";
+ }
+ if (isset($data['filter_manufacturer']) && !empty($data['filter_price_to']) && !is_null($data['filter_manufacturer'])) {
+ $sql .= " AND p.manufacturer_id = " . (int)$data['filter_manufacturer'];
+ }
+
+ $query = $this->db->query($sql);
+
+ return $query->row['total'];
+ }
+
+ public function getProducts($data = array()) {
+ $sql = "SELECT p.*, pd.* FROM " . DB_PREFIX . "product p LEFT JOIN " . DB_PREFIX . "product_description pd ON (p.product_id = pd.product_id)";
+
+ if (!empty($data['filter_category'])) {
+ $sql .= " LEFT JOIN " . DB_PREFIX . "product_to_category p2c ON (p.product_id = p2c.product_id)";
+ }
+
+ if ($data['filter_market_name'] == 'ebay') {
+ $sql .= " LEFT JOIN `" . DB_PREFIX . "ebay_listing` `ebay` ON (`p`.`product_id` = `ebay`.`product_id`)";
+
+ if ($data['filter_market_id'] == 0) {
+ $sql .= " LEFT JOIN (SELECT product_id, IF( SUM( `status` ) = 0, 0, 1 ) AS 'listing_status' FROM " . DB_PREFIX . "ebay_listing GROUP BY product_id ) ebay2 ON (p.product_id = ebay2.product_id)";
+ }
+ }
+
+ if ($data['filter_market_name'] == 'amazon') {
+ if ($data['filter_market_id'] <= 4) {
+ $sql .= " LEFT JOIN " . DB_PREFIX . "amazon_product ap ON p.product_id = ap.product_id";
+ } elseif ($data['filter_market_id'] <= 6) {
+ $sql .= " LEFT JOIN " . DB_PREFIX . "amazon_product_link apl ON p.product_id = apl.product_id";
+ }
+
+ $amazon_status = array(
+ 1 => 'saved',
+ 2 => 'uploaded',
+ 3 => 'ok',
+ 4 => 'error',
+ );
+ }
+
+ if ($data['filter_market_name'] == 'amazonus') {
+ if ($data['filter_market_id'] <= 4) {
+ $sql .= " LEFT JOIN " . DB_PREFIX . "amazonus_product ap ON p.product_id = ap.product_id";
+ } elseif ($data['filter_market_id'] <= 6) {
+ $sql .= " LEFT JOIN " . DB_PREFIX . "amazonus_product_link apl ON p.product_id = apl.product_id";
+ }
+
+ $amazonus_status = array(
+ 1 => 'saved',
+ 2 => 'uploaded',
+ 3 => 'ok',
+ 4 => 'error',
+ );
+ }
+
+ $sql .= " WHERE pd.language_id = '" . (int)$this->config->get('config_language_id') . "'";
+
+ if (!empty($data['filter_category'])) {
+ if ($data['filter_category'] == 'none') {
+ $sql .= " AND p2c.category_id IS NULL";
+ } else {
+ $sql .= " AND p2c.category_id = '" . (int)$data['filter_category'] . "'";
+ }
+ }
+
+ if ($data['filter_market_name'] == 'ebay') {
+ if ($data['filter_market_id'] == 0) {
+ $sql .= " AND (ebay.ebay_listing_id IS NULL OR ebay2.listing_status = 0)";
+ } else {
+ $sql .= " AND (ebay.ebay_listing_id IS NOT NULL AND ebay.status = 1)";
+ }
+ }
+
+ if ($data['filter_market_name'] == 'amazon') {
+ if ($data['filter_market_id'] == 0) {
+ $sql .= " AND ap.product_id IS NULL ";
+ } elseif ($data['filter_market_id'] == 5) {
+ $sql .= " AND apl.id IS NOT NULL";
+ } elseif ($data['filter_market_id'] == 6) {
+ $sql .= " AND apl.id IS NULL";
+ } else {
+ $sql .= " AND FIND_IN_SET('" . $this->db->escape($amazon_status[$data['filter_market_id']]) . "', ap.`status`) != 0";
+ }
+ }
+
+ if ($data['filter_market_name'] == 'amazonus') {
+ if ($data['filter_market_id'] == 0) {
+ $sql .= " AND ap.product_id IS NULL ";
+ } elseif ($data['filter_market_id'] == 5) {
+ $sql .= " AND apl.id IS NOT NULL";
+ } elseif ($data['filter_market_id'] == 6) {
+ $sql .= " AND apl.id IS NULL";
+ } else {
+ $sql .= " AND FIND_IN_SET('" . $this->db->escape($amazonus_status[$data['filter_market_id']]) . "', ap.`status`) != 0";
+ }
+ }
+
+ if (isset($data['filter_name']) && !empty($data['filter_name']) && !is_null($data['filter_name'])) {
+ $sql .= " AND pd.name LIKE '" . $this->db->escape($data['filter_name']) . "%'";
+ }
+ if (isset($data['filter_model']) && !empty($data['filter_model']) && !is_null($data['filter_model'])) {
+ $sql .= " AND p.model LIKE '" . $this->db->escape($data['filter_model']) . "%'";
+ }
+ if (isset($data['filter_price']) && !empty($data['filter_price']) && !is_null($data['filter_price'])) {
+ $sql .= " AND p.price >= '" . (double)$data['filter_price'] . "'";
+ }
+ if (isset($data['filter_price_to']) && !empty($data['filter_price_to']) && !is_null($data['filter_price_to'])) {
+ $sql .= " AND p.price <= '" . (double)$data['filter_price_to'] . "'";
+ }
+ if (isset($data['filter_quantity']) && !empty($data['filter_quantity']) && !is_null($data['filter_quantity'])) {
+ $sql .= " AND p.quantity >= " . (int)$data['filter_quantity'];
+ }
+ if (isset($data['filter_quantity_to']) && !empty($data['filter_quantity_to']) && !is_null($data['filter_quantity_to'])) {
+ $sql .= " AND p.quantity <= " . (int)$data['filter_quantity_to'];
+ }
+ if (isset($data['filter_status']) && !empty($data['filter_status']) && !is_null($data['filter_status'])) {
+ $sql .= " AND p.status = " . (int)$data['filter_status'];
+ }
+ if (isset($data['filter_sku']) && !empty($data['filter_sku']) && !is_null($data['filter_sku'])) {
+ $sql .= " AND p.sku != ''";
+ }
+ if (isset($data['filter_desc']) && !empty($data['filter_desc']) && !is_null($data['filter_desc'])) {
+ $sql .= " AND pd.description != ''";
+ }
+ if (isset($data['filter_manufacturer']) && !empty($data['filter_price_to']) && !is_null($data['filter_manufacturer'])) {
+ $sql .= " AND p.manufacturer_id = " . (int)$data['filter_manufacturer'];
+ }
+
+ $sql .= " GROUP BY p.product_id";
+
+ $sort_data = array(
+ 'pd.name',
+ 'p.model',
+ 'p.price',
+ 'p.quantity',
+ 'p.status',
+ 'p.sort_order'
+ );
+
+ if (isset($data['sort']) && in_array($data['sort'], $sort_data)) {
+ $sql .= " ORDER BY " . $data['sort'];
+ } else {
+ $sql .= " ORDER BY pd.name";
+ }
+
+ if (isset($data['order']) && ($data['order'] == 'DESC')) {
+ $sql .= " DESC";
+ } else {
+ $sql .= " ASC";
+ }
+
+ if (isset($data['start']) || isset($data['limit'])) {
+ if ($data['start'] < 0) {
+ $data['start'] = 0;
+ }
+
+ if ($data['limit'] < 1) {
+ $data['limit'] = 20;
+ }
+
+ $sql .= " LIMIT " . (int)$data['start'] . "," . (int)$data['limit'];
+ }
+
+ $query = $this->db->query($sql);
+
+ return $query->rows;
+ }
+
+ public function addOrderHistory($order_id, $post_data, $api_token) {
+ $defaults = array(
+ CURLOPT_POST => true,
+ CURLOPT_HEADER => false,
+ CURLOPT_USERAGENT => $this->request->server['HTTP_USER_AGENT'],
+ CURLOPT_URL => HTTPS_CATALOG . 'index.php?route=api/order/history&api_token=' . $api_token . '&store_id=0&order_id=' . (int)$order_id,
+ CURLOPT_SSL_VERIFYPEER => 0,
+ CURLOPT_SSL_VERIFYHOST => 0,
+ CURLOPT_FORBID_REUSE => true,
+ CURLOPT_RETURNTRANSFER => true,
+ CURLOPT_POSTFIELDS => http_build_query($post_data, '', "&"),
+ CURLOPT_TIMEOUT => 60,
+ );
+
+ $curl = curl_init();
+ curl_setopt_array($curl, $defaults);
+ $result = curl_exec($curl);
+ curl_close($curl);
+
+ $result = json_decode($result, 1);
+
+ return $result;
+ }
+
+ public function storeImage($filename, $width, $height, $sub_directory = '') {
+ /**
+ * This method should be used to save images for the marketplaces where the image will be used in a listing template.
+ * It will save to a dedicated folder in the /images location and not the /cache folder.
+ * This is due to people clearing the cache folder - only to realise all remotely references images are now gone.
+ */
+
+ if (!is_file(DIR_IMAGE . $filename) || substr(str_replace('\\', '/', realpath(DIR_IMAGE . $filename)), 0, strlen(DIR_IMAGE)) != DIR_IMAGE) {
+ return;
+ }
+
+ $extension = pathinfo($filename, PATHINFO_EXTENSION);
+
+ $image_old = $filename;
+
+ $new_path = 'openbay_template_images/';
+ if ($sub_directory != '') {
+ $new_path = $new_path . '/' .$sub_directory . '/';
+ }
+
+ $image_new = $new_path . utf8_substr($filename, 0, utf8_strrpos($filename, '.')) . '-' . $width . 'x' . $height . '.' . $extension;
+
+ if (!is_file(DIR_IMAGE . $image_new) || (filemtime(DIR_IMAGE . $image_old) > filemtime(DIR_IMAGE . $image_new))) {
+ list($width_orig, $height_orig, $image_type) = getimagesize(DIR_IMAGE . $image_old);
+
+ if (!in_array($image_type, array(IMAGETYPE_PNG, IMAGETYPE_JPEG, IMAGETYPE_GIF))) {
+ return DIR_IMAGE . $image_old;
+ }
+
+ $path = '';
+
+ $directories = explode('/', dirname($image_new));
+
+ foreach ($directories as $directory) {
+ $path = $path . '/' . $directory;
+
+ if (!is_dir(DIR_IMAGE . $path)) {
+ @mkdir(DIR_IMAGE . $path, 0777);
+ }
+ }
+
+ if ($width_orig != $width || $height_orig != $height) {
+ $image = new Image(DIR_IMAGE . $image_old);
+ $image->resize($width, $height);
+ $image->save(DIR_IMAGE . $image_new);
+ } else {
+ copy(DIR_IMAGE . $image_old, DIR_IMAGE . $image_new);
+ }
+ }
+
+ if ($this->request->server['HTTPS']) {
+ return HTTPS_CATALOG . 'image/' . $image_new;
+ } else {
+ return HTTP_CATALOG . 'image/' . $image_new;
+ }
+ }
+}
diff --git a/public/admin/model/extension/openbay/order.php b/public/admin/model/extension/openbay/order.php
new file mode 100644
index 0000000..d6aa936
--- /dev/null
+++ b/public/admin/model/extension/openbay/order.php
@@ -0,0 +1,228 @@
+<?php
+class ModelExtensionOpenBayOrder extends Model {
+ public function getTotalOrders($data = array()) {
+ $sql = "SELECT COUNT(*) AS `total` FROM `" . DB_PREFIX . "order` AS o";
+
+ if ($this->config->get('ebay_status')) {
+ $sql .= " LEFT JOIN " . DB_PREFIX . "ebay_order eo ON o.order_id = eo.order_id ";
+ } else {
+ $sql .= " JOIN (SELECT NULL AS order_id) eo ";
+ }
+
+ if ($this->config->get('openbay_amazon_status')) {
+ $sql .= " LEFT JOIN " . DB_PREFIX . "amazon_order ao ON o.order_id = ao.order_id ";
+ } else {
+ $sql .= " JOIN (SELECT NULL AS order_id) ao ";
+ }
+
+ if ($this->config->get('openbay_amazonus_status')) {
+ $sql .= " LEFT JOIN " . DB_PREFIX . "amazonus_order auso ON o.order_id = auso.order_id ";
+ } else {
+ $sql .= " JOIN (SELECT NULL AS order_id) auso ";
+ }
+
+ if ($this->config->get('etsy_status')) {
+ $sql .= " LEFT JOIN " . DB_PREFIX . "etsy_order eto ON o.order_id = eto.order_id ";
+ } else {
+ $sql .= " JOIN (SELECT NULL AS order_id) eto ";
+ }
+
+ if (isset($data['filter_order_status_id']) && !empty($data['filter_order_status_id']) && !is_null($data['filter_order_status_id'])) {
+ $sql .= " WHERE `o`.`order_status_id` = '" . (int)$data['filter_order_status_id'] . "'";
+ } else {
+ $sql .= " WHERE `o`.`order_status_id` > '0'";
+ }
+
+ if (!empty($data['filter_order_id'])) {
+ $sql .= " AND o.`order_id` = '" . (int)$data['filter_order_id'] . "'";
+ }
+
+ if (!empty($data['filter_customer'])) {
+ $sql .= " AND CONCAT(`firstname`, ' ', `lastname`) LIKE '%" . $this->db->escape($data['filter_customer']) . "%'";
+ }
+
+ if (!empty($data['filter_date_added'])) {
+ $sql .= " AND DATE(`date_added`) = DATE('" . $this->db->escape($data['filter_date_added']) . "')";
+ }
+
+ if (!empty($data['filter_channel'])) {
+ $sql .= " AND IF(eto.order_id IS NULL, IF(ao.order_id IS NULL, IF(auso.order_id IS NULL, IF(eo.order_id IS NULL, 'web', 'ebay'), 'amazonus'), 'amazon'), 'etsy') = '" . $this->db->escape($data['filter_channel']) . "'";
+ }
+
+ $query = $this->db->query($sql);
+
+ return $query->row['total'];
+ }
+
+ public function getOrders($data = array()) {
+ $sql = "SELECT o.order_id, o.customer_id, CONCAT(o.firstname, ' ', o.lastname) AS customer,";
+
+ if ($this->config->get('ebay_status')) {
+ $sql .= " `eo`.`smp_id` AS `ebay_order_ref`,";
+ } else {
+ $sql .= " NULL AS `ebay_order_ref`,";
+ }
+
+ if ($this->config->get('openbay_amazon_status')) {
+ $sql .= " `ao`.`amazon_order_id` AS `amazon_order_ref`,";
+ } else {
+ $sql .= " NULL AS `amazon_order_ref`,";
+ }
+
+ if ($this->config->get('openbay_amazonus_status')) {
+ $sql .= " `auso`.`amazonus_order_id` AS `amazonus_order_ref`,";
+ } else {
+ $sql .= " NULL AS `amazonus_order_ref`,";
+ }
+
+ if ($this->config->get('etsy_status')) {
+ $sql .= " `eto`.`receipt_id` AS `etsy_order_ref`,";
+ } else {
+ $sql .= " NULL AS `etsy_order_ref`,";
+ }
+
+ $sql .= " (SELECT os.name FROM " . DB_PREFIX . "order_status os WHERE os.order_status_id = o.order_status_id AND os.language_id = '" . (int)$this->config->get('config_language_id') . "') AS `status`, o.currency_code, o.currency_value, o.date_added, IF(eto.order_id IS NULL, IF(ao.order_id IS NULL, IF(auso.order_id IS NULL, IF(eo.order_id IS NULL, 'web', 'ebay'), 'amazonus'), 'amazon'), 'etsy') AS channel FROM `" . DB_PREFIX . "order` o";
+
+ if ($this->config->get('ebay_status')) {
+ $sql .= " LEFT JOIN " . DB_PREFIX . "ebay_order eo ON eo.order_id = o.order_id";
+ } else {
+ $sql .= " JOIN (SELECT NULL AS order_id) eo ";
+ }
+
+ if ($this->config->get('openbay_amazon_status')) {
+ $sql .= " LEFT JOIN " . DB_PREFIX . "amazon_order ao ON ao.order_id = o.order_id ";
+ } else {
+ $sql .= " JOIN (SELECT NULL AS order_id) ao ";
+ }
+
+ if ($this->config->get('openbay_amazonus_status')) {
+ $sql .= " LEFT JOIN " . DB_PREFIX . "amazonus_order auso ON auso.order_id = o.order_id ";
+ } else {
+ $sql .= " JOIN (SELECT NULL AS order_id) auso ";
+ }
+
+ if ($this->config->get('etsy_status')) {
+ $sql .= " LEFT JOIN " . DB_PREFIX . "etsy_order eto ON eto.order_id = o.order_id ";
+ } else {
+ $sql .= " JOIN (SELECT NULL AS order_id) eto ";
+ }
+
+ if (isset($data['filter_order_status_id']) && !empty($data['filter_order_status_id']) && !is_null($data['filter_order_status_id'])) {
+ $sql .= " WHERE o.order_status_id = '" . (int)$data['filter_order_status_id'] . "'";
+ } else {
+ $sql .= " WHERE o.order_status_id > '0'";
+ }
+
+ if (!empty($data['filter_order_id'])) {
+ $sql .= " AND o.order_id = '" . (int)$data['filter_order_id'] . "'";
+ }
+
+ if (!empty($data['filter_customer'])) {
+ $sql .= " AND LCASE(CONCAT(o.firstname, ' ', o.lastname)) LIKE '" . $this->db->escape(utf8_strtolower($data['filter_customer'])) . "%'";
+ }
+
+ if (!empty($data['filter_date_added'])) {
+ $sql .= " AND DATE(o.date_added) = DATE('" . $this->db->escape($data['filter_date_added']) . "')";
+ }
+
+ if (!empty($data['filter_channel'])) {
+ $sql .= " HAVING channel = '" . $this->db->escape($data['filter_channel']) . "'";
+ }
+
+ $sort_data = array(
+ 'o.order_id',
+ 'customer',
+ 'status',
+ 'o.date_added',
+ 'channel',
+ );
+
+ if (isset($data['sort']) && in_array($data['sort'], $sort_data)) {
+ $sql .= " ORDER BY " . $data['sort'];
+ } else {
+ $sql .= " ORDER BY o.order_id";
+ }
+
+ if (isset($data['order']) && ($data['order'] == 'DESC')) {
+ $sql .= " DESC";
+ } else {
+ $sql .= " ASC";
+ }
+
+ if (isset($data['start']) || isset($data['limit'])) {
+ if ($data['start'] < 0) {
+ $data['start'] = 0;
+ }
+
+ if ($data['limit'] < 1) {
+ $data['limit'] = 20;
+ }
+
+ $sql .= " LIMIT " . (int)$data['start'] . "," . (int)$data['limit'];
+ }
+
+ $query = $this->db->query($sql);
+
+ return $query->rows;
+ }
+
+ public function getOrder($order_id) {
+ $sql = "SELECT o.order_id, o.order_status_id, o.shipping_method, CONCAT(o.firstname, ' ', o.lastname) AS customer,";
+
+ if ($this->config->get('ebay_status')) {
+ $sql .= " `eo`.`smp_id` AS `ebay_order_ref`,";
+ } else {
+ $sql .= " NULL AS `ebay_order_ref`,";
+ }
+
+ if ($this->config->get('openbay_amazon_status')) {
+ $sql .= " `ao`.`amazon_order_id` AS `amazon_order_ref`,";
+ } else {
+ $sql .= " NULL AS `amazon_order_ref`,";
+ }
+
+ if ($this->config->get('openbay_amazonus_status')) {
+ $sql .= " `auso`.`amazonus_order_id` AS `amazonus_order_ref`,";
+ } else {
+ $sql .= " NULL AS `amazonus_order_ref`,";
+ }
+
+ if ($this->config->get('etsy_status')) {
+ $sql .= " `eto`.`receipt_id` AS `etsy_order_ref`,";
+ } else {
+ $sql .= " NULL AS `etsy_order_ref`,";
+ }
+
+ $sql .= " (SELECT os.name FROM " . DB_PREFIX . "order_status os WHERE os.order_status_id = o.order_status_id AND os.language_id = '" . (int)$this->config->get('config_language_id') . "') AS status, o.currency_code, o.currency_value, o.date_added, IF(eto.order_id IS NULL, IF(ao.order_id IS NULL, IF(auso.order_id IS NULL, IF(eo.order_id IS NULL, 'web', 'ebay'), 'amazonus'), 'amazon'), 'etsy') AS channel FROM `" . DB_PREFIX . "order` o";
+
+ if ($this->config->get('ebay_status')) {
+ $sql .= " LEFT JOIN " . DB_PREFIX . "ebay_order eo ON eo.order_id = o.order_id ";
+ } else {
+ $sql .= " JOIN (SELECT NULL AS order_id) eo ";
+ }
+
+ if ($this->config->get('openbay_amazon_status')) {
+ $sql .= " LEFT JOIN " . DB_PREFIX . "amazon_order ao ON ao.order_id = o.order_id ";
+ } else {
+ $sql .= " JOIN (SELECT NULL AS order_id) ao ";
+ }
+
+ if ($this->config->get('openbay_amazonus_status')) {
+ $sql .= " LEFT JOIN " . DB_PREFIX . "amazonus_order auso ON auso.order_id = o.order_id ";
+ } else {
+ $sql .= " JOIN (SELECT NULL AS order_id) auso ";
+ }
+
+ if ($this->config->get('etsy_status')) {
+ $sql .= " LEFT JOIN " . DB_PREFIX . "etsy_order eto ON eto.order_id = o.order_id ";
+ } else {
+ $sql .= " JOIN (SELECT NULL AS order_id) eto ";
+ }
+
+ $sql .= " WHERE `o`.`order_id` = '" . (int)$order_id . "'";
+
+ $sql = $this->db->query($sql);
+
+ return $sql->row;
+ }
+} \ No newline at end of file
diff --git a/public/admin/model/extension/openbay/version.php b/public/admin/model/extension/openbay/version.php
new file mode 100644
index 0000000..eaa07a8
--- /dev/null
+++ b/public/admin/model/extension/openbay/version.php
@@ -0,0 +1,7 @@
+<?php
+class ModelExtensionOpenBayVersion extends Model {
+ public function version() {
+ return (int)3250;
+
+ }
+}
diff --git a/public/admin/model/extension/payment/amazon_login_pay.php b/public/admin/model/extension/payment/amazon_login_pay.php
new file mode 100644
index 0000000..a89037c
--- /dev/null
+++ b/public/admin/model/extension/payment/amazon_login_pay.php
@@ -0,0 +1,452 @@
+<?php
+class ModelExtensionPaymentAmazonLoginPay extends Model {
+
+ public function install() {
+ $this->db->query("
+ CREATE TABLE IF NOT EXISTS `" . DB_PREFIX . "amazon_login_pay_order` (
+ `amazon_login_pay_order_id` INT(11) NOT NULL AUTO_INCREMENT,
+ `order_id` int(11) NOT NULL,
+ `amazon_order_reference_id` varchar(255) NOT NULL,
+ `amazon_authorization_id` varchar(255) NOT NULL,
+ `free_shipping` tinyint NOT NULL DEFAULT 0,
+ `date_added` DATETIME NOT NULL,
+ `modified` DATETIME NOT NULL,
+ `capture_status` INT(1) DEFAULT NULL,
+ `cancel_status` INT(1) DEFAULT NULL,
+ `refund_status` INT(1) DEFAULT NULL,
+ `currency_code` CHAR(3) NOT NULL,
+ `total` DECIMAL( 10, 2 ) NOT NULL,
+ KEY `amazon_order_reference_id` (`amazon_order_reference_id`),
+ PRIMARY KEY `amazon_login_pay_order_id` (`amazon_login_pay_order_id`)
+ ) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_general_ci;
+ ");
+
+ $this->db->query("
+ CREATE TABLE IF NOT EXISTS `" . DB_PREFIX . "amazon_login_pay_order_transaction` (
+ `amazon_login_pay_order_transaction_id` INT(11) NOT NULL AUTO_INCREMENT,
+ `amazon_login_pay_order_id` INT(11) NOT NULL,
+ `amazon_authorization_id` varchar(255),
+ `amazon_capture_id` varchar(255),
+ `amazon_refund_id` varchar(255),
+ `date_added` DATETIME NOT NULL,
+ `type` ENUM('authorization', 'capture', 'refund', 'cancel') DEFAULT NULL,
+ `status` ENUM('Open', 'Pending', 'Completed', 'Suspended', 'Declined', 'Closed', 'Canceled') DEFAULT NULL,
+ `amount` DECIMAL( 10, 2 ) NOT NULL,
+ PRIMARY KEY (`amazon_login_pay_order_transaction_id`)
+ ) ENGINE=MyISAM DEFAULT COLLATE=utf8_general_ci;
+ ");
+ }
+
+ public function uninstall() {
+ $this->db->query("DROP TABLE IF EXISTS `" . DB_PREFIX . "amazon_login_pay_order`;");
+ $this->db->query("DROP TABLE IF EXISTS `" . DB_PREFIX . "amazon_login_pay_order_total_tax`;");
+ $this->db->query("DROP TABLE IF EXISTS `" . DB_PREFIX . "amazon_login_pay_order_transaction`;");
+ }
+
+ public function deleteEvents() {
+ $this->load->model('setting/event');
+ $this->model_setting_event->deleteEventByCode('amazon_edit_capture');
+ $this->model_setting_event->deleteEventByCode('amazon_history_capture');
+ }
+
+ public function addEvents() {
+ $this->load->model('setting/event');
+ $this->model_setting_event->addEvent('amazon_edit_capture', 'catalog/model/checkout/order/editOrder/after', 'extension/payment/amazon_login_pay/capture');
+ $this->model_setting_event->addEvent('amazon_history_capture', 'catalog/model/checkout/order/addOrderHistory/after', 'extension/payment/amazon_login_pay/capture');
+ }
+
+ public function getOrder($order_id) {
+
+ $qry = $this->db->query("SELECT * FROM `" . DB_PREFIX . "amazon_login_pay_order` WHERE `order_id` = '" . (int)$order_id . "' LIMIT 1");
+
+ if ($qry->num_rows) {
+ $order = $qry->row;
+ $order['transactions'] = $this->getTransactions($order['amazon_login_pay_order_id'], $qry->row['currency_code']);
+ return $order;
+ } else {
+ return false;
+ }
+ }
+
+ public function cancel($amazon_login_pay_order) {
+ $total_captured = $this->getTotalCaptured($amazon_login_pay_order['amazon_login_pay_order_id']);
+
+ if (!empty($amazon_login_pay_order) && $total_captured == 0) {
+
+ $cancel_response = array();
+ $cancel_paramter_data = array();
+
+ $cancel_paramter_data['AmazonOrderReferenceId'] = $amazon_login_pay_order['amazon_order_reference_id'];
+ $cancel_details = $this->offAmazon('CancelOrderReference', $cancel_paramter_data);
+ $cancel_details_xml = simplexml_load_string($cancel_details['ResponseBody']);
+ $this->logger($cancel_details_xml);
+ if (isset($cancel_details_xml->Error)) {
+ $cancel_response['status'] = 'Error';
+ $cancel_response['status_detail'] = (string)$cancel_details_xml->Error->Code . ': ' . (string)$cancel_details_xml->Error->Message;
+ } else {
+ $cancel_response['status'] = 'Completed';
+ }
+ return $cancel_response;
+ } else {
+ return false;
+ }
+ }
+
+ public function updateCancelStatus($amazon_login_pay_order_id, $status) {
+ $this->db->query("UPDATE `" . DB_PREFIX . "amazon_login_pay_order` SET `cancel_status` = '" . (int)$status . "' WHERE `amazon_login_pay_order_id` = '" . (int)$amazon_login_pay_order_id . "'");
+ }
+
+ public function hasOpenAuthorization($transactions) {
+ foreach ($transactions as $transaction) {
+ if ($transaction['type'] == 'authorization' && $transaction['status'] == 'Open') {
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+ public function capture($amazon_login_pay_order, $amount) {
+ $total_captured = $this->getTotalCaptured($amazon_login_pay_order['amazon_login_pay_order_id']);
+
+ if (!empty($amazon_login_pay_order) && $amazon_login_pay_order['capture_status'] == 0 && ($total_captured + $amount <= $amazon_login_pay_order['total'])) {
+ if (!$this->hasOpenAuthorization($amazon_login_pay_order['transactions'])) {
+ $amazon_authorization = $this->authorize($amazon_login_pay_order, $amount);
+ if (isset($amazon_authorization['AmazonAuthorizationId'])) {
+ $amazon_authorization_id = $amazon_authorization['AmazonAuthorizationId'];
+ } else {
+ return $amazon_authorization;
+ }
+ } else {
+ $amazon_authorization_id = $amazon_login_pay_order['amazon_authorization_id'];
+ }
+
+ $capture_paramter_data = array();
+ $capture_paramter_data['AmazonOrderReferenceId'] = $amazon_login_pay_order['amazon_order_reference_id'];
+ $capture_paramter_data['AmazonAuthorizationId'] = $amazon_authorization_id;
+ $capture_paramter_data['CaptureAmount.Amount'] = $amount;
+ $capture_paramter_data['CaptureAmount.CurrencyCode'] = $amazon_login_pay_order['currency_code'];
+ $capture_paramter_data['CaptureReferenceId'] = 'capture_' . mt_rand();
+ $capture_paramter_data['TransactionTimeout'] = 0;
+ $capture_details = $this->offAmazon('Capture', $capture_paramter_data);
+
+ $capture_response = $this->validateResponse('Capture', $capture_details);
+ $capture_response['AmazonAuthorizationId'] = $amazon_authorization_id;
+ return $capture_response;
+ } else {
+ return false;
+ }
+ }
+
+ private function authorize($amazon_login_pay_order, $amount) {
+ $authorize_paramter_data = array();
+ $authorize_paramter_data['AmazonOrderReferenceId'] = $amazon_login_pay_order['amazon_order_reference_id'];
+ $authorize_paramter_data['AuthorizationAmount.Amount'] = $amount;
+ $authorize_paramter_data['AuthorizationAmount.CurrencyCode'] = $amazon_login_pay_order['currency_code'];
+ $authorize_paramter_data['AuthorizationReferenceId'] = 'auth_' . mt_rand();
+ $authorize_paramter_data['TransactionTimeout'] = 0;
+ $authorize_details = $this->offAmazon('Authorize', $authorize_paramter_data);
+
+ return $this->validateResponse('Authorize', $authorize_details);
+ }
+
+ public function closeOrderRef($amazon_order_reference_id) {
+ $close_paramter_data = array();
+ $close_paramter_data['AmazonOrderReferenceId'] = $amazon_order_reference_id;
+ $this->offAmazon('CloseOrderReference', $close_paramter_data);
+ $close_details = $this->offAmazon('CloseOrderReference', $close_paramter_data);
+ $this->logger($close_details);
+ }
+
+ public function updateCaptureStatus($amazon_login_pay_order_id, $status) {
+ $this->db->query("UPDATE `" . DB_PREFIX . "amazon_login_pay_order` SET `capture_status` = '" . (int)$status . "' WHERE `amazon_login_pay_order_id` = '" . (int)$amazon_login_pay_order_id . "'");
+ }
+
+ public function refund($amazon_login_pay_order, $amount) {
+ if (!empty($amazon_login_pay_order) && $amazon_login_pay_order['refund_status'] != 1) {
+ $amazon_captures_remaining = $this->getUnCaptured($amazon_login_pay_order['amazon_login_pay_order_id']);
+
+ $refund_response = array();
+ $i = 0;
+ $count = count($amazon_captures_remaining);
+ for ($amount; $amount > 0 && $count > $i; $amount -= $amazon_captures_remaining[$i++]['capture_remaining']) {
+ $refund_amount = $amount;
+ if ($amazon_captures_remaining[$i]['capture_remaining'] <= $amount) {
+ $refund_amount = $amazon_captures_remaining[$i]['capture_remaining'];
+ }
+
+ $refund_paramter_data = array();
+ $refund_paramter_data['AmazonOrderReferenceId'] = $amazon_login_pay_order['amazon_order_reference_id'];
+ $refund_paramter_data['AmazonCaptureId'] = $amazon_captures_remaining[$i]['amazon_capture_id'];
+ $refund_paramter_data['RefundAmount.Amount'] = $refund_amount;
+ $refund_paramter_data['RefundAmount.CurrencyCode'] = $amazon_login_pay_order['currency_code'];
+ $refund_paramter_data['RefundReferenceId'] = 'refund_' . mt_rand();
+ $refund_paramter_data['TransactionTimeout'] = 0;
+ $refund_details = $this->offAmazon('Refund', $refund_paramter_data);
+ $refund_response[$i] = $this->validateResponse('Refund', $refund_details);
+ $refund_response[$i]['amazon_authorization_id'] = $amazon_captures_remaining[$i]['amazon_authorization_id'];
+ $refund_response[$i]['amazon_capture_id'] = $amazon_captures_remaining[$i]['amazon_capture_id'];
+ $refund_response[$i]['amount'] = $refund_amount;
+ }
+
+ return $refund_response;
+ } else {
+ return false;
+ }
+ }
+
+ public function getUnCaptured($amazon_login_pay_order_id) {
+ $qry = $this->db->query("SELECT * FROM `" . DB_PREFIX . "amazon_login_pay_order_transaction` WHERE (`type` = 'refund' OR `type` = 'capture') AND `amazon_login_pay_order_id` = '" . (int)$amazon_login_pay_order_id . "' ORDER BY `date_added`");
+ $uncaptured = array();
+ foreach ($qry->rows as $row) {
+ $uncaptured[$row['amazon_capture_id']]['amazon_authorization_id'] = $row['amazon_authorization_id'];
+ $uncaptured[$row['amazon_capture_id']]['amazon_capture_id'] = $row['amazon_capture_id'];
+ if (isset($uncaptured[$row['amazon_capture_id']]['capture_remaining'])) {
+ $uncaptured[$row['amazon_capture_id']]['capture_remaining'] += $row['amount'];
+ } else {
+ $uncaptured[$row['amazon_capture_id']]['capture_remaining'] = $row['amount'];
+ }
+
+ if ($uncaptured[$row['amazon_capture_id']]['capture_remaining'] == 0) {
+ unset($uncaptured[$row['amazon_capture_id']]);
+ }
+ }
+ return array_values($uncaptured);
+ }
+
+ public function updateRefundStatus($amazon_login_pay_order_id, $status) {
+ $this->db->query("UPDATE `" . DB_PREFIX . "amazon_login_pay_order` SET `refund_status` = '" . (int)$status . "' WHERE `amazon_login_pay_order_id` = '" . (int)$amazon_login_pay_order_id . "'");
+ }
+
+ public function getCapturesRemaining($amazon_login_pay_order_id) {
+ $query = $this->db->query("SELECT * FROM `" . DB_PREFIX . "amazon_login_pay_order_transaction` WHERE `amazon_login_pay_order_id` = '" . (int)$amazon_login_pay_order_id . "' AND capture_remaining != '0' ORDER BY `date_added`");
+ if ($query->num_rows) {
+ return $query->rows;
+ } else {
+ return false;
+ }
+ }
+
+ private function getTransactions($amazon_login_pay_order_id, $currency_code) {
+ $query = $this->db->query("SELECT * FROM `" . DB_PREFIX . "amazon_login_pay_order_transaction` WHERE `amazon_login_pay_order_id` = '" . (int)$amazon_login_pay_order_id . "' ORDER BY `date_added` DESC");
+
+ $transactions = array();
+ if ($query->num_rows) {
+ foreach ($query->rows as $row) {
+ $row['amount'] = $this->currency->format($row['amount'], $currency_code, true, true);
+ $transactions[] = $row;
+ }
+ return $transactions;
+ } else {
+ return false;
+ }
+ }
+
+ public function addTransaction($amazon_login_pay_order_id, $type, $status, $total, $amazon_authorization_id = null, $amazon_capture_id = null, $amazon_refund_id = null) {
+ $this->db->query("INSERT INTO `" . DB_PREFIX . "amazon_login_pay_order_transaction` SET `amazon_login_pay_order_id` = '" . (int)$amazon_login_pay_order_id . "',`amazon_authorization_id` = '" . $this->db->escape($amazon_authorization_id) . "',`amazon_capture_id` = '" . $this->db->escape($amazon_capture_id) . "',`amazon_refund_id` = '" . $this->db->escape($amazon_refund_id) . "', `date_added` = now(), `type` = '" . $this->db->escape($type) . "', `amount` = '" . (double)$total . "', `status` = '" . $this->db->escape($status) . "'");
+ }
+
+ public function updateAuthorizationStatus($amazon_authorization_id, $status) {
+ $this->db->query("UPDATE `" . DB_PREFIX . "amazon_login_pay_order_transaction` SET `status` = '" . $this->db->escape($status) . "' WHERE `amazon_authorization_id`='" . $this->db->escape($amazon_authorization_id) . "' AND `type`='authorization'");
+ }
+
+ public function isOrderInState($order_reference_id, $states = array()) {
+ return in_array((string)$this->fetchOrder($order_reference_id)->OrderReferenceStatus->State, $states);
+ }
+
+ public function fetchOrder($order_reference_id) {
+ $order = $this->offAmazon("GetOrderReferenceDetails", array(
+ 'AmazonOrderReferenceId' => $order_reference_id
+ ));
+
+ $responseBody = $order['ResponseBody'];
+
+ $details_xml = simplexml_load_string($responseBody);
+
+ return $details_xml
+ ->GetOrderReferenceDetailsResult
+ ->OrderReferenceDetails;
+ }
+
+ public function getTotalCaptured($amazon_login_pay_order_id) {
+ $query = $this->db->query("SELECT SUM(`amount`) AS `total` FROM `" . DB_PREFIX . "amazon_login_pay_order_transaction` WHERE `amazon_login_pay_order_id` = '" . (int)$amazon_login_pay_order_id . "' AND (`type` = 'capture' OR `type` = 'refund') AND (`status` = 'Completed' OR `status` = 'Closed')");
+
+ return (double)$query->row['total'];
+ }
+
+ public function getTotalRefunded($amazon_login_pay_order_id) {
+ $query = $this->db->query("SELECT SUM(`amount`) AS `total` FROM `" . DB_PREFIX . "amazon_login_pay_order_transaction` WHERE `amazon_login_pay_order_id` = '" . (int)$amazon_login_pay_order_id . "' AND 'refund'");
+
+ return (double)$query->row['total'];
+ }
+
+ public function validateDetails($data) {
+ $validate_paramter_data = array();
+ $validate_paramter_data['AWSAccessKeyId'] = $data['payment_amazon_login_pay_access_key'];
+ $validate_paramter_data['SellerId'] = $data['payment_amazon_login_pay_merchant_id'];
+ $validate_paramter_data['AmazonOrderReferenceId'] = 'validate details';
+ $validate_details = $this->offAmazon('GetOrderReferenceDetails', $validate_paramter_data);
+ $validate_response = $this->validateResponse('GetOrderReferenceDetails', $validate_details, true);
+ if($validate_response['error_code'] && $validate_response['error_code'] != 'InvalidOrderReferenceId'){
+ return $validate_response;
+ }
+ }
+
+ public function offAmazon($Action, $parameter_data, $post_data = array()) {
+ if(!empty($post_data)){
+ $merchant_id = $post_data['payment_amazon_login_pay_merchant_id'];
+ $access_key = $post_data['payment_amazon_login_pay_access_key'];
+ $access_secret = $post_data['payment_amazon_login_pay_access_secret'];
+ $test = $post_data['payment_amazon_login_pay_test'];
+ $payment_region = $post_data['payment_amazon_login_pay_payment_region'];
+ } else {
+ $merchant_id = $this->config->get('payment_amazon_login_pay_merchant_id');
+ $access_key = $this->config->get('payment_amazon_login_pay_access_key');
+ $access_secret = $this->config->get('payment_amazon_login_pay_access_secret');
+ $test = $this->config->get('payment_amazon_login_pay_test');
+ $payment_region = $this->config->get('payment_amazon_login_pay_payment_region');
+
+ }
+
+ if ($test == 'sandbox') {
+ if ($payment_region == 'USD') {
+ $url = 'https://mws.amazonservices.com/OffAmazonPayments_Sandbox/2013-01-01/';
+ } else {
+ $url = 'https://mws-eu.amazonservices.com/OffAmazonPayments_Sandbox/2013-01-01/';
+ }
+ } else {
+ if ($payment_region == 'USD') {
+ $url = 'https://mws.amazonservices.com/OffAmazonPayments/2013-01-01/';
+ } else {
+ $url = 'https://mws-eu.amazonservices.com/OffAmazonPayments/2013-01-01/';
+ }
+ }
+
+ $parameters = array();
+ $parameters['AWSAccessKeyId'] = $access_key;
+ $parameters['Action'] = $Action;
+ $parameters['SellerId'] = $merchant_id;
+ $parameters['SignatureMethod'] = 'HmacSHA256';
+ $parameters['SignatureVersion'] = 2;
+ $parameters['Timestamp'] = date('c', time());
+ $parameters['Version'] = '2013-01-01';
+ foreach ($parameter_data as $k => $v) {
+ $parameters[$k] = $v;
+ }
+
+ $query = $this->calculateStringToSignV2($parameters, $url);
+
+ $parameters['Signature'] = base64_encode(hash_hmac('sha256', $query, $access_secret, true));
+
+ return $this->sendCurl($url, $parameters);
+ }
+
+ private function validateResponse($action, $details, $skip_logger = false) {
+ $details_xml = simplexml_load_string($details['ResponseBody']);
+ if (!$skip_logger) {
+ $this->logger($details_xml);
+ }
+ switch ($action) {
+ case 'Authorize':
+ $result = 'AuthorizeResult';
+ $details = 'AuthorizationDetails';
+ $status = 'AuthorizationStatus';
+ $amazon_id = 'AmazonAuthorizationId';
+ break;
+ case 'Capture':
+ $result = 'CaptureResult';
+ $details = 'CaptureDetails';
+ $status = 'CaptureStatus';
+ $amazon_id = 'AmazonCaptureId';
+ break;
+ case 'Refund':
+ $result = 'RefundResult';
+ $details = 'RefundDetails';
+ $status = 'RefundStatus';
+ $amazon_id = 'AmazonRefundId';
+ }
+
+ $details_xml->registerXPathNamespace('m', 'http://mws.amazonservices.com/schema/OffAmazonPayments/2013-01-01');
+ $error_set = $details_xml->xpath('//m:ReasonCode');
+
+ if (isset($details_xml->Error)) {
+ $response['status'] = 'Error';
+ $response['error_code'] = (string)$details_xml->Error->Code;
+ $response['status_detail'] = (string)$details_xml->Error->Code . ': ' . (string)$details_xml->Error->Message;
+ } elseif (!empty($error_set)) {
+ $response['status'] = (string)$details_xml->$result->$details->$status->State;
+ $response['status_detail'] = (string)$details_xml->$result->$details->$status->ReasonCode;
+ } else {
+ $response['status'] = (string)$details_xml->$result->$details->$status->State;
+ $response[$amazon_id] = (string)$details_xml->$result->$details->$amazon_id;
+ }
+
+ return $response;
+ }
+
+ public function sendCurl($url, $parameters) {
+ $query = $this->getParametersAsString($parameters);
+
+ $curl = curl_init($url);
+
+ curl_setopt($curl, CURLOPT_URL, $url);
+ curl_setopt($curl, CURLOPT_PORT, 443);
+ curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, true);
+ curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, 2);
+ curl_setopt($curl, CURLOPT_USERAGENT, $this->request->server['HTTP_USER_AGENT']);
+ curl_setopt($curl, CURLOPT_POST, true);
+ curl_setopt($curl, CURLOPT_POSTFIELDS, $query);
+ curl_setopt($curl, CURLOPT_HEADER, true);
+ curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
+
+ $response = curl_exec($curl);
+ curl_close($curl);
+
+ list($other, $responseBody) = explode("\r\n\r\n", $response, 2);
+ $other = preg_split("/\r\n|\n|\r/", $other);
+
+ list($protocol, $code, $text) = explode(' ', trim(array_shift($other)), 3);
+ return array('status' => (int)$code, 'ResponseBody' => $responseBody);
+ }
+
+ private function getParametersAsString(array $parameters) {
+ $queryParameters = array();
+ foreach ($parameters as $key => $value) {
+ $queryParameters[] = $key . '=' . $this->urlencode($value);
+ }
+ return implode('&', $queryParameters);
+ }
+
+ private function calculateStringToSignV2(array $parameters, $url) {
+ $data = 'POST';
+ $data .= "\n";
+ $endpoint = parse_url($url);
+ $data .= $endpoint['host'];
+ $data .= "\n";
+ $uri = array_key_exists('path', $endpoint) ? $endpoint['path'] : null;
+ if (!isset($uri)) {
+ $uri = "/";
+ }
+ $uriencoded = implode("/", array_map(array($this, "urlencode"), explode("/", $uri)));
+ $data .= $uriencoded;
+ $data .= "\n";
+ uksort($parameters, 'strcmp');
+ $data .= $this->getParametersAsString($parameters);
+ return $data;
+ }
+
+ private function urlencode($value) {
+ return str_replace('%7E', '~', rawurlencode($value));
+ }
+
+ public function logger($message) {
+ if ($this->config->get('payment_amazon_login_pay_debug') == 1) {
+ $log = new Log('amazon_login_pay_admin.log');
+ $backtrace = debug_backtrace();
+ $class = isset($backtrace[6]['class']) ? $backtrace[6]['class'] . '::' : '';
+ $log->write('Origin: ' . $class . $backtrace[6]['function']);
+ $log->write(!is_string($message) ? print_r($message, true) : $message);
+ unset($log);
+ }
+ }
+} \ No newline at end of file
diff --git a/public/admin/model/extension/payment/bluepay_hosted.php b/public/admin/model/extension/payment/bluepay_hosted.php
new file mode 100644
index 0000000..d1a85ac
--- /dev/null
+++ b/public/admin/model/extension/payment/bluepay_hosted.php
@@ -0,0 +1,235 @@
+<?php
+class ModelExtensionPaymentBluePayHosted extends Model {
+ public function install() {
+ $this->db->query("
+ CREATE TABLE IF NOT EXISTS `" . DB_PREFIX . "bluepay_hosted_order` (
+ `bluepay_hosted_order_id` INT(11) NOT NULL AUTO_INCREMENT,
+ `order_id` INT(11) NOT NULL,
+ `transaction_id` VARCHAR(50),
+ `date_added` DATETIME NOT NULL,
+ `date_modified` DATETIME NOT NULL,
+ `release_status` INT(1) DEFAULT 0,
+ `void_status` INT(1) DEFAULT 0,
+ `rebate_status` INT(1) DEFAULT 0,
+ `currency_code` CHAR(3) NOT NULL,
+ `total` DECIMAL( 10, 2 ) NOT NULL,
+ PRIMARY KEY (`bluepay_hosted_order_id`)
+ ) ENGINE=MyISAM DEFAULT COLLATE=utf8_general_ci;");
+
+ $this->db->query("
+ CREATE TABLE IF NOT EXISTS `" . DB_PREFIX . "bluepay_hosted_order_transaction` (
+ `bluepay_hosted_order_transaction_id` INT(11) NOT NULL AUTO_INCREMENT,
+ `bluepay_hosted_order_id` INT(11) NOT NULL,
+ `date_added` DATETIME NOT NULL,
+ `type` ENUM('auth', 'payment', 'rebate', 'void') DEFAULT NULL,
+ `amount` DECIMAL( 10, 2 ) NOT NULL,
+ PRIMARY KEY (`bluepay_hosted_order_transaction_id`)
+ ) ENGINE=MyISAM DEFAULT COLLATE=utf8_general_ci;");
+
+ $this->db->query("
+ CREATE TABLE IF NOT EXISTS `" . DB_PREFIX . "bluepay_hosted_card` (
+ `card_id` INT(11) NOT NULL AUTO_INCREMENT,
+ `customer_id` INT(11) NOT NULL,
+ `token` VARCHAR(50) NOT NULL,
+ `digits` VARCHAR(4) NOT NULL,
+ `expiry` VARCHAR(5) NOT NULL,
+ `type` VARCHAR(50) NOT NULL,
+ PRIMARY KEY (`card_id`)
+ ) ENGINE=MyISAM DEFAULT COLLATE=utf8_general_ci;");
+ }
+
+ public function uninstall() {
+ $this->db->query("DROP TABLE IF EXISTS `" . DB_PREFIX . "bluepay_hosted_order`;");
+ $this->db->query("DROP TABLE IF EXISTS `" . DB_PREFIX . "bluepay_hosted_order_transaction`;");
+ $this->db->query("DROP TABLE IF EXISTS `" . DB_PREFIX . "bluepay_hosted_card`;");
+ }
+
+ public function void($order_id) {
+ $bluepay_hosted_order = $this->getOrder($order_id);
+
+ if (!empty($bluepay_hosted_order) && $bluepay_hosted_order['release_status'] == 1) {
+
+ $void_data = array();
+
+ $void_data['MERCHANT'] = $this->config->get('payment_bluepay_hosted_account_id');
+ $void_data["TRANSACTION_TYPE"] = 'VOID';
+ $void_data["MODE"] = strtoupper($this->config->get('payment_bluepay_hosted_test'));
+ $void_data["RRNO"] = $bluepay_hosted_order['transaction_id'];
+
+ $void_data['APPROVED_URL'] = HTTP_CATALOG . 'index.php?route=extension/payment/bluepay_hosted/adminCallback';
+ $void_data['DECLINED_URL'] = HTTP_CATALOG . 'index.php?route=extension/payment/bluepay_hosted/adminCallback';
+ $void_data['MISSING_URL'] = HTTP_CATALOG . 'index.php?route=extension/payment/bluepay_hosted/adminCallback';
+
+ if (isset($this->request->server["REMOTE_ADDR"])) {
+ $void_data["REMOTE_IP"] = $this->request->server["REMOTE_ADDR"];
+ }
+
+ $tamper_proof_data = $this->config->get('payment_bluepay_hosted_secret_key') . $void_data['MERCHANT'] . $void_data["TRANSACTION_TYPE"] . $void_data["RRNO"] . $void_data["MODE"];
+
+ $void_data["TAMPER_PROOF_SEAL"] = md5($tamper_proof_data);
+
+ $this->logger('$void_data:\r\n' . print_r($void_data, 1));
+
+ $response_data = $this->sendCurl('https://secure.bluepay.com/interfaces/bp10emu', $void_data);
+
+ return $response_data;
+ } else {
+ return false;
+ }
+ }
+
+ public function updateVoidStatus($bluepay_hosted_order_id, $status) {
+ $this->logger('$bluepay_hosted_order_id:\r\n' . print_r($bluepay_hosted_order_id, 1));
+ $this->logger('$status:\r\n' . print_r($status, 1));
+ $this->db->query("UPDATE `" . DB_PREFIX . "bluepay_hosted_order` SET `void_status` = '" . (int)$status . "' WHERE `bluepay_hosted_order_id` = '" . (int)$bluepay_hosted_order_id . "'");
+ }
+
+ public function release($order_id, $amount) {
+ $bluepay_hosted_order = $this->getOrder($order_id);
+ $total_released = $this->getTotalReleased($bluepay_hosted_order['bluepay_hosted_order_id']);
+
+ if (!empty($bluepay_hosted_order) && $bluepay_hosted_order['release_status'] == 0 && ($total_released + $amount <= $bluepay_hosted_order['total'])) {
+ $release_data = array();
+
+ $release_data['MERCHANT'] = $this->config->get('payment_bluepay_hosted_account_id');
+ $release_data["TRANSACTION_TYPE"] = 'CAPTURE';
+ $release_data["MODE"] = strtoupper($this->config->get('payment_bluepay_hosted_test'));
+ $release_data["RRNO"] = $bluepay_hosted_order['transaction_id'];
+
+ $release_data['APPROVED_URL'] = HTTP_CATALOG . 'index.php?route=extension/payment/bluepay_hosted/adminCallback';
+ $release_data['DECLINED_URL'] = HTTP_CATALOG . 'index.php?route=extension/payment/bluepay_hosted/adminCallback';
+ $release_data['MISSING_URL'] = HTTP_CATALOG . 'index.php?route=extension/payment/bluepay_hosted/adminCallback';
+
+ if (isset($this->request->server["REMOTE_ADDR"])) {
+ $release_data["REMOTE_IP"] = $this->request->server["REMOTE_ADDR"];
+ }
+
+ $tamper_proof_data = $this->config->get('payment_bluepay_hosted_secret_key') . $release_data['MERCHANT'] . $release_data["TRANSACTION_TYPE"] . $release_data["RRNO"] . $release_data["MODE"];
+
+ $release_data["TAMPER_PROOF_SEAL"] = md5($tamper_proof_data);
+
+ $response_data = $this->sendCurl('https://secure.bluepay.com/interfaces/bp10emu', $release_data);
+
+ return $response_data;
+ } else {
+ return false;
+ }
+ }
+
+ public function updateReleaseStatus($bluepay_hosted_order_id, $status) {
+ $this->db->query("UPDATE `" . DB_PREFIX . "bluepay_hosted_order` SET `release_status` = '" . (int)$status . "' WHERE `bluepay_hosted_order_id` = '" . (int)$bluepay_hosted_order_id . "'");
+ }
+
+ public function rebate($order_id, $amount) {
+ $bluepay_hosted_order = $this->getOrder($order_id);
+
+ if (!empty($bluepay_hosted_order) && $bluepay_hosted_order['rebate_status'] != 1) {
+ $rebate_data = array();
+
+ $rebate_data['MERCHANT'] = $this->config->get('payment_bluepay_hosted_account_id');
+ $rebate_data["TRANSACTION_TYPE"] = 'REFUND';
+ $rebate_data["MODE"] = strtoupper($this->config->get('payment_bluepay_hosted_test'));
+ $rebate_data["RRNO"] = $bluepay_hosted_order['transaction_id'];
+ $rebate_data["AMOUNT"] = $amount;
+ $rebate_data['APPROVED_URL'] = HTTP_CATALOG . 'index.php?route=extension/payment/bluepay_hosted/adminCallback';
+ $rebate_data['DECLINED_URL'] = HTTP_CATALOG . 'index.php?route=extension/payment/bluepay_hosted/adminCallback';
+ $rebate_data['MISSING_URL'] = HTTP_CATALOG . 'index.php?route=extension/payment/bluepay_hosted/adminCallback';
+
+ if (isset($this->request->server["REMOTE_ADDR"])) {
+ $rebate_data["REMOTE_IP"] = $this->request->server["REMOTE_ADDR"];
+ }
+
+ $tamper_proof_data = $this->config->get('payment_bluepay_hosted_secret_key') . $rebate_data['MERCHANT'] . $rebate_data["TRANSACTION_TYPE"] . $rebate_data['AMOUNT'] . $rebate_data["RRNO"] . $rebate_data["MODE"];
+
+ $rebate_data["TAMPER_PROOF_SEAL"] = md5($tamper_proof_data);
+
+ $response_data = $this->sendCurl('https://secure.bluepay.com/interfaces/bp10emu', $rebate_data);
+
+ return $response_data;
+ } else {
+ return false;
+ }
+ }
+
+ public function updateRebateStatus($bluepay_hosted_order_id, $status) {
+ $this->db->query("UPDATE `" . DB_PREFIX . "bluepay_hosted_order` SET `rebate_status` = '" . (int)$status . "' WHERE `bluepay_hosted_order_id` = '" . (int)$bluepay_hosted_order_id . "'");
+ }
+
+ public function updateTransactionId($bluepay_hosted_order_id, $transaction_id) {
+ $this->db->query("UPDATE `" . DB_PREFIX . "bluepay_hosted_order` SET `transaction_id` = '" . (int)$transaction_id . "' WHERE `bluepay_hosted_order_id` = '" . (int)$bluepay_hosted_order_id . "'");
+ }
+
+ public function getOrder($order_id) {
+
+ $qry = $this->db->query("SELECT * FROM `" . DB_PREFIX . "bluepay_hosted_order` WHERE `order_id` = '" . (int)$order_id . "' LIMIT 1");
+
+ if ($qry->num_rows) {
+ $order = $qry->row;
+ $order['transactions'] = $this->getTransactions($order['bluepay_hosted_order_id']);
+
+ return $order;
+ } else {
+ return false;
+ }
+ }
+
+ private function getTransactions($bluepay_hosted_order_id) {
+ $qry = $this->db->query("SELECT * FROM `" . DB_PREFIX . "bluepay_hosted_order_transaction` WHERE `bluepay_hosted_order_id` = '" . (int)$bluepay_hosted_order_id . "'");
+
+ if ($qry->num_rows) {
+ return $qry->rows;
+ } else {
+ return false;
+ }
+ }
+
+ public function addTransaction($bluepay_hosted_order_id, $type, $total) {
+ $this->logger('$type:\r\n' . print_r($type, 1));
+ $this->logger('$total:\r\n' . print_r($total, 1));
+ $this->db->query("INSERT INTO `" . DB_PREFIX . "bluepay_hosted_order_transaction` SET `bluepay_hosted_order_id` = '" . (int)$bluepay_hosted_order_id . "', `date_added` = now(), `type` = '" . $this->db->escape($type) . "', `amount` = '" . (float)$total . "'");
+ }
+
+ public function getTotalReleased($bluepay_hosted_order_id) {
+ $query = $this->db->query("SELECT SUM(`amount`) AS `total` FROM `" . DB_PREFIX . "bluepay_hosted_order_transaction` WHERE `bluepay_hosted_order_id` = '" . (int)$bluepay_hosted_order_id . "' AND (`type` = 'payment' OR `type` = 'rebate')");
+
+ return (float)$query->row['total'];
+ }
+
+ public function getTotalRebated($bluepay_hosted_order_id) {
+ $query = $this->db->query("SELECT SUM(`amount`) AS `total` FROM `" . DB_PREFIX . "bluepay_hosted_order_transaction` WHERE `bluepay_hosted_order_id` = '" . (int)$bluepay_hosted_order_id . "' AND 'rebate'");
+
+ return (float)$query->row['total'];
+ }
+
+ public function sendCurl($url, $post_data) {
+ $curl = curl_init($url);
+
+ curl_setopt($curl, CURLOPT_PORT, 443);
+ curl_setopt($curl, CURLOPT_HEADER, 0);
+ curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, 0);
+ curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
+ curl_setopt($curl, CURLOPT_FOLLOWLOCATION, true);
+ curl_setopt($curl, CURLOPT_FORBID_REUSE, 1);
+ curl_setopt($curl, CURLOPT_FRESH_CONNECT, 1);
+ curl_setopt($curl, CURLOPT_POST, 1);
+ curl_setopt($curl, CURLOPT_POSTFIELDS, http_build_query($post_data));
+
+ $response_data = curl_exec($curl);
+
+ curl_close($curl);
+
+ return json_decode($response_data, true);
+ }
+
+ public function adminCallback() {
+ $this->response->addHeader('Content-Type: application/json');
+ $this->response->setOutput(json_encode($this->request->get));
+ }
+
+ public function logger($message) {
+ if ($this->config->get('payment_bluepay_hosted_debug') == 1) {
+ $log = new Log('bluepay_hosted.log');
+ $log->write($message);
+ }
+ }
+} \ No newline at end of file
diff --git a/public/admin/model/extension/payment/bluepay_redirect.php b/public/admin/model/extension/payment/bluepay_redirect.php
new file mode 100644
index 0000000..e6df201
--- /dev/null
+++ b/public/admin/model/extension/payment/bluepay_redirect.php
@@ -0,0 +1,228 @@
+<?php
+class ModelExtensionPaymentBluepayredirect extends Model {
+ public function install() {
+ $this->db->query("
+ CREATE TABLE IF NOT EXISTS `" . DB_PREFIX . "bluepay_redirect_order` (
+ `bluepay_redirect_order_id` INT(11) NOT NULL AUTO_INCREMENT,
+ `order_id` INT(11) NOT NULL,
+ `transaction_id` VARCHAR(50),
+ `date_added` DATETIME NOT NULL,
+ `date_modified` DATETIME NOT NULL,
+ `release_status` INT(1) DEFAULT 0,
+ `void_status` INT(1) DEFAULT 0,
+ `rebate_status` INT(1) DEFAULT 0,
+ `currency_code` CHAR(3) NOT NULL,
+ `total` DECIMAL( 10, 2 ) NOT NULL,
+ PRIMARY KEY (`bluepay_redirect_order_id`)
+ ) ENGINE=MyISAM DEFAULT COLLATE=utf8_general_ci;");
+
+ $this->db->query("
+ CREATE TABLE IF NOT EXISTS `" . DB_PREFIX . "bluepay_redirect_order_transaction` (
+ `bluepay_redirect_order_transaction_id` INT(11) NOT NULL AUTO_INCREMENT,
+ `bluepay_redirect_order_id` INT(11) NOT NULL,
+ `date_added` DATETIME NOT NULL,
+ `type` ENUM('auth', 'payment', 'rebate', 'void') DEFAULT NULL,
+ `amount` DECIMAL( 10, 2 ) NOT NULL,
+ PRIMARY KEY (`bluepay_redirect_order_transaction_id`)
+ ) ENGINE=MyISAM DEFAULT COLLATE=utf8_general_ci;");
+
+ $this->db->query("
+ CREATE TABLE IF NOT EXISTS `" . DB_PREFIX . "bluepay_redirect_card` (
+ `card_id` INT(11) NOT NULL AUTO_INCREMENT,
+ `customer_id` INT(11) NOT NULL,
+ `token` VARCHAR(50) NOT NULL,
+ `digits` VARCHAR(4) NOT NULL,
+ `expiry` VARCHAR(5) NOT NULL,
+ `type` VARCHAR(50) NOT NULL,
+ PRIMARY KEY (`card_id`)
+ ) ENGINE=MyISAM DEFAULT COLLATE=utf8_general_ci;");
+ }
+
+ public function uninstall() {
+ $this->db->query("DROP TABLE IF EXISTS `" . DB_PREFIX . "bluepay_redirect_order`;");
+ $this->db->query("DROP TABLE IF EXISTS `" . DB_PREFIX . "bluepay_redirect_order_transaction`;");
+ $this->db->query("DROP TABLE IF EXISTS `" . DB_PREFIX . "bluepay_redirect_card`;");
+ }
+
+ public function void($order_id) {
+ $bluepay_redirect_order = $this->getOrder($order_id);
+
+ if (!empty($bluepay_redirect_order) && $bluepay_redirect_order['release_status'] == 1) {
+
+ $void_data = array();
+
+ $void_data['MERCHANT'] = $this->config->get('payment_bluepay_redirect_account_id');
+ $void_data["TRANSACTION_TYPE"] = 'VOID';
+ $void_data["MODE"] = strtoupper($this->config->get('payment_bluepay_redirect_test'));
+ $void_data["RRNO"] = $bluepay_redirect_order['transaction_id'];
+
+ $void_data['APPROVED_URL'] = HTTP_CATALOG . 'index.php?route=extension/payment/bluepay_redirect/callback';
+ $void_data['DECLINED_URL'] = HTTP_CATALOG . 'index.php?route=extension/payment/bluepay_redirect/callback';
+ $void_data['MISSING_URL'] = HTTP_CATALOG . 'index.php?route=extension/payment/bluepay_redirect/callback';
+
+ if (isset($this->request->server["REMOTE_ADDR"])) {
+ $void_data["REMOTE_IP"] = $this->request->server["REMOTE_ADDR"];
+ }
+
+ $tamper_proof_data = $this->config->get('payment_bluepay_redirect_secret_key') . $void_data['MERCHANT'] . $void_data["TRANSACTION_TYPE"] . $void_data["RRNO"] . $void_data["MODE"];
+
+ $void_data["TAMPER_PROOF_SEAL"] = md5($tamper_proof_data);
+
+ $response_data = $this->sendCurl('https://secure.bluepay.com/interfaces/bp10emu', $void_data);
+
+ return $response_data;
+ } else {
+ return false;
+ }
+ }
+
+ public function updateVoidStatus($bluepay_redirect_order_id, $status) {
+ $this->db->query("UPDATE `" . DB_PREFIX . "bluepay_redirect_order` SET `void_status` = '" . (int)$status . "' WHERE `bluepay_redirect_order_id` = '" . (int)$bluepay_redirect_order_id . "'");
+ }
+
+ public function release($order_id, $amount) {
+ $bluepay_redirect_order = $this->getOrder($order_id);
+ $total_released = $this->getTotalReleased($bluepay_redirect_order['bluepay_redirect_order_id']);
+
+ if (!empty($bluepay_redirect_order) && $bluepay_redirect_order['release_status'] == 0 && ($total_released + $amount <= $bluepay_redirect_order['total'])) {
+ $release_data = array();
+
+ $release_data['MERCHANT'] = $this->config->get('payment_bluepay_redirect_account_id');
+ $release_data["TRANSACTION_TYPE"] = 'CAPTURE';
+ $release_data["MODE"] = strtoupper($this->config->get('payment_bluepay_redirect_test'));
+ $release_data["RRNO"] = $bluepay_redirect_order['transaction_id'];
+ $release_data["AMOUNT"] = $amount;
+ $release_data['APPROVED_URL'] = HTTP_CATALOG . 'index.php?route=extension/payment/bluepay_redirect/callback';
+ $release_data['DECLINED_URL'] = HTTP_CATALOG . 'index.php?route=extension/payment/bluepay_redirect/callback';
+ $release_data['MISSING_URL'] = HTTP_CATALOG . 'index.php?route=extension/payment/bluepay_redirect/callback';
+
+ if (isset($this->request->server["REMOTE_ADDR"])) {
+ $release_data["REMOTE_IP"] = $this->request->server["REMOTE_ADDR"];
+ }
+
+ $tamper_proof_data = $this->config->get('payment_bluepay_redirect_secret_key') . $release_data['MERCHANT'] . $release_data["TRANSACTION_TYPE"] . $release_data["AMOUNT"] . $release_data["RRNO"] . $release_data["MODE"];
+
+ $release_data["TAMPER_PROOF_SEAL"] = md5($tamper_proof_data);
+
+ $response_data = $this->sendCurl('https://secure.bluepay.com/interfaces/bp10emu', $release_data);
+
+ return $response_data;
+ } else {
+ return false;
+ }
+ }
+
+ public function updateReleaseStatus($bluepay_redirect_order_id, $status) {
+ $this->db->query("UPDATE `" . DB_PREFIX . "bluepay_redirect_order` SET `release_status` = '" . (int)$status . "' WHERE `bluepay_redirect_order_id` = '" . (int)$bluepay_redirect_order_id . "'");
+ }
+
+ public function rebate($order_id, $amount) {
+ $bluepay_redirect_order = $this->getOrder($order_id);
+
+ if (!empty($bluepay_redirect_order) && $bluepay_redirect_order['rebate_status'] != 1) {
+ $rebate_data = array();
+
+ $rebate_data['MERCHANT'] = $this->config->get('payment_bluepay_redirect_account_id');
+ $rebate_data["TRANSACTION_TYPE"] = 'REFUND';
+ $rebate_data["MODE"] = strtoupper($this->config->get('payment_bluepay_redirect_test'));
+ $rebate_data["RRNO"] = $bluepay_redirect_order['transaction_id'];
+ $rebate_data["AMOUNT"] = $amount;
+ $rebate_data['APPROVED_URL'] = HTTP_CATALOG . 'index.php?route=extension/payment/bluepay_redirect/callback';
+ $rebate_data['DECLINED_URL'] = HTTP_CATALOG . 'index.php?route=extension/payment/bluepay_redirect/callback';
+ $rebate_data['MISSING_URL'] = HTTP_CATALOG . 'index.php?route=extension/payment/bluepay_redirect/callback';
+
+ if (isset($this->request->server["REMOTE_ADDR"])) {
+ $rebate_data["REMOTE_IP"] = $this->request->server["REMOTE_ADDR"];
+ }
+
+ $tamper_proof_data = $this->config->get('payment_bluepay_redirect_secret_key') . $rebate_data['MERCHANT'] . $rebate_data["TRANSACTION_TYPE"] . $rebate_data['AMOUNT'] . $rebate_data["RRNO"] . $rebate_data["MODE"];
+
+ $rebate_data["TAMPER_PROOF_SEAL"] = md5($tamper_proof_data);
+
+ $response_data = $this->sendCurl('https://secure.bluepay.com/interfaces/bp10emu', $rebate_data);
+
+ return $response_data;
+ } else {
+ return false;
+ }
+ }
+
+ public function updateRebateStatus($bluepay_redirect_order_id, $status) {
+ $this->db->query("UPDATE `" . DB_PREFIX . "bluepay_redirect_order` SET `rebate_status` = '" . (int)$status . "' WHERE `bluepay_redirect_order_id` = '" . (int)$bluepay_redirect_order_id . "'");
+ }
+
+ public function updateTransactionId($bluepay_redirect_order_id, $transaction_id) {
+ $this->db->query("UPDATE `" . DB_PREFIX . "bluepay_redirect_order` SET `transaction_id` = '" . (int)$transaction_id . "' WHERE `bluepay_redirect_order_id` = '" . (int)$bluepay_redirect_order_id . "'");
+ }
+
+ public function getOrder($order_id) {
+
+ $qry = $this->db->query("SELECT * FROM `" . DB_PREFIX . "bluepay_redirect_order` WHERE `order_id` = '" . (int)$order_id . "' LIMIT 1");
+
+ if ($qry->num_rows) {
+ $order = $qry->row;
+ $order['transactions'] = $this->getTransactions($order['bluepay_redirect_order_id']);
+
+ return $order;
+ } else {
+ return false;
+ }
+ }
+
+ private function getTransactions($bluepay_redirect_order_id) {
+ $qry = $this->db->query("SELECT * FROM `" . DB_PREFIX . "bluepay_redirect_order_transaction` WHERE `bluepay_redirect_order_id` = '" . (int)$bluepay_redirect_order_id . "'");
+
+ if ($qry->num_rows) {
+ return $qry->rows;
+ } else {
+ return false;
+ }
+ }
+
+ public function addTransaction($bluepay_redirect_order_id, $type, $total) {
+ $this->db->query("INSERT INTO `" . DB_PREFIX . "bluepay_redirect_order_transaction` SET `bluepay_redirect_order_id` = '" . (int)$bluepay_redirect_order_id . "', `date_added` = now(), `type` = '" . $this->db->escape($type) . "', `amount` = '" . (float)$total . "'");
+ }
+
+ public function getTotalReleased($bluepay_redirect_order_id) {
+ $query = $this->db->query("SELECT SUM(`amount`) AS `total` FROM `" . DB_PREFIX . "bluepay_redirect_order_transaction` WHERE `bluepay_redirect_order_id` = '" . (int)$bluepay_redirect_order_id . "' AND (`type` = 'payment' OR `type` = 'rebate')");
+
+ return (float)$query->row['total'];
+ }
+
+ public function getTotalRebated($bluepay_redirect_order_id) {
+ $query = $this->db->query("SELECT SUM(`amount`) AS `total` FROM `" . DB_PREFIX . "bluepay_redirect_order_transaction` WHERE `bluepay_redirect_order_id` = '" . (int)$bluepay_redirect_order_id . "' AND 'rebate'");
+
+ return (float)$query->row['total'];
+ }
+
+ public function sendCurl($url, $post_data) {
+ $curl = curl_init($url);
+
+ curl_setopt($curl, CURLOPT_PORT, 443);
+ curl_setopt($curl, CURLOPT_HEADER, 0);
+ curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, 0);
+ curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
+ curl_setopt($curl, CURLOPT_FOLLOWLOCATION, true);
+ curl_setopt($curl, CURLOPT_FORBID_REUSE, 1);
+ curl_setopt($curl, CURLOPT_FRESH_CONNECT, 1);
+ curl_setopt($curl, CURLOPT_POST, 1);
+ curl_setopt($curl, CURLOPT_POSTFIELDS, http_build_query($post_data));
+
+ $response_data = curl_exec($curl);
+ curl_close($curl);
+
+ return json_decode($response_data, true);
+ }
+
+ public function callback() {
+ $this->response->addHeader('Content-Type: application/json');
+ $this->response->setOutput(json_encode($this->request->get));
+ }
+
+ public function logger($message) {
+ if ($this->config->get('payment_bluepay_redirect_debug') == 1) {
+ $log = new Log('bluepay_redirect.log');
+ $log->write($message);
+ }
+ }
+}
diff --git a/public/admin/model/extension/payment/cardconnect.php b/public/admin/model/extension/payment/cardconnect.php
new file mode 100644
index 0000000..4cb4b60
--- /dev/null
+++ b/public/admin/model/extension/payment/cardconnect.php
@@ -0,0 +1,328 @@
+<?php
+class ModelExtensionPaymentCardConnect extends Model {
+ public function install() {
+ $this->db->query("
+ CREATE TABLE IF NOT EXISTS `" . DB_PREFIX . "cardconnect_card` (
+ `cardconnect_card_id` INT(11) NOT NULL AUTO_INCREMENT,
+ `cardconnect_order_id` INT(11) NOT NULL DEFAULT '0',
+ `customer_id` INT(11) NOT NULL DEFAULT '0',
+ `profileid` VARCHAR(16) NOT NULL DEFAULT '',
+ `token` VARCHAR(19) NOT NULL DEFAULT '',
+ `type` VARCHAR(50) NOT NULL DEFAULT '',
+ `account` VARCHAR(4) NOT NULL DEFAULT '',
+ `expiry` VARCHAR(4) NOT NULL DEFAULT '',
+ `date_added` DATETIME NOT NULL DEFAULT '0000-00-00 00:00:00',
+ PRIMARY KEY (`cardconnect_card_id`)
+ ) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_general_ci");
+
+ $this->db->query("
+ CREATE TABLE IF NOT EXISTS `" . DB_PREFIX . "cardconnect_order` (
+ `cardconnect_order_id` INT(11) NOT NULL AUTO_INCREMENT,
+ `order_id` INT(11) NOT NULL DEFAULT '0',
+ `customer_id` INT(11) NOT NULL DEFAULT '0',
+ `payment_method` VARCHAR(255) NOT NULL DEFAULT '',
+ `retref` VARCHAR(12) NOT NULL DEFAULT '',
+ `authcode` VARCHAR(6) NOT NULL DEFAULT '',
+ `currency_code` VARCHAR(3) NOT NULL DEFAULT '',
+ `total` DECIMAL(10, 2) NOT NULL DEFAULT '0.00',
+ `date_added` DATETIME NOT NULL DEFAULT '0000-00-00 00:00:00',
+ PRIMARY KEY (`cardconnect_order_id`)
+ ) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_general_ci");
+
+ $this->db->query("
+ CREATE TABLE IF NOT EXISTS `" . DB_PREFIX . "cardconnect_order_transaction` (
+ `cardconnect_order_transaction_id` INT(11) NOT NULL AUTO_INCREMENT,
+ `cardconnect_order_id` INT(11) NOT NULL DEFAULT '0',
+ `type` VARCHAR(50) NOT NULL DEFAULT '',
+ `retref` VARCHAR(12) NOT NULL DEFAULT '',
+ `amount` DECIMAL(10, 2) NOT NULL DEFAULT '0.00',
+ `status` VARCHAR(255) NOT NULL DEFAULT '',
+ `date_modified` DATETIME NOT NULL DEFAULT '0000-00-00 00:00:00',
+ `date_added` DATETIME NOT NULL DEFAULT '0000-00-00 00:00:00',
+ PRIMARY KEY (`cardconnect_order_transaction_id`)
+ ) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_general_ci");
+ }
+
+ public function uninstall() {
+ $this->db->query("DROP TABLE IF EXISTS `" . DB_PREFIX . "cardconnect_card`");
+ $this->db->query("DROP TABLE IF EXISTS `" . DB_PREFIX . "cardconnect_order`");
+ $this->db->query("DROP TABLE IF EXISTS `" . DB_PREFIX . "cardconnect_order_transaction`");
+
+ $this->log('Module uninstalled');
+ }
+
+ public function getOrder($order_id) {
+ $query = $this->db->query("SELECT * FROM `" . DB_PREFIX . "cardconnect_order` WHERE `order_id` = '" . (int)$order_id . "' LIMIT 1");
+
+ if ($query->num_rows) {
+ $order = $query->row;
+
+ $order['transactions'] = $this->getTransactions($order['cardconnect_order_id']);
+
+ return $order;
+ } else {
+ return false;
+ }
+ }
+
+ private function getTransactions($cardconnect_order_id) {
+ $query = $this->db->query("SELECT * FROM `" . DB_PREFIX . "cardconnect_order_transaction` WHERE `cardconnect_order_id` = '" . (int)$cardconnect_order_id . "'");
+
+ if ($query->num_rows) {
+ return $query->rows;
+ } else {
+ return array();
+ }
+ }
+
+ public function getTotalCaptured($cardconnect_order_id) {
+ $query = $this->db->query("SELECT SUM(`amount`) AS `total` FROM `" . DB_PREFIX . "cardconnect_order_transaction` WHERE `cardconnect_order_id` = '" . (int)$cardconnect_order_id . "' AND (`type` = 'payment' OR `type` = 'refund')");
+
+ return (float)$query->row['total'];
+ }
+
+ public function inquire($order_info, $retref) {
+ $this->log('Posting inquire to CardConnect');
+
+ $this->log('Order ID: ' . $order_info['order_id']);
+
+ $url = 'https://' . $this->config->get('cardconnect_site') . '.cardconnect.com:' . (($this->config->get('cardconnect_environment') == 'live') ? 8443 : 6443) . '/cardconnect/rest/inquire/' . $retref . '/' . $this->config->get('payment_cardconnect_merchant_id');
+
+ $header = array();
+
+ $header[] = 'Content-type: application/json';
+ $header[] = 'Authorization: Basic ' . base64_encode($this->config->get('cardconnect_api_username') . ':' . $this->config->get('cardconnect_api_password'));
+
+ $this->model_extension_payment_cardconnect->log('Header: ' . print_r($header, true));
+
+ $this->model_extension_payment_cardconnect->log('URL: ' . $url);
+
+ $ch = curl_init();
+ curl_setopt($ch, CURLOPT_URL, $url);
+ curl_setopt($ch, CURLOPT_HTTPHEADER, $header);
+ curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'GET');
+ curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
+ curl_setopt($ch, CURLOPT_TIMEOUT, 30);
+ curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
+ $response_data = curl_exec($ch);
+ if (curl_errno($ch)) {
+ $this->model_extension_payment_cardconnect->log('cURL error: ' . curl_errno($ch));
+ }
+ curl_close($ch);
+
+ $response_data = json_decode($response_data, true);
+
+ $this->log('Response: ' . print_r($response_data, true));
+
+ return $response_data;
+ }
+
+ public function capture($order_info, $amount) {
+ $this->load->model('sale/order');
+
+ $this->log('Posting capture to CardConnect');
+
+ $this->log('Order ID: ' . $order_info['order_id']);
+
+ $order = $this->model_sale_order->getOrder($order_info['order_id']);
+
+ $totals = $this->model_sale_order->getOrderTotals($order_info['order_id']);
+
+ $shipping_cost = '';
+
+ foreach($totals as $total) {
+ if ($total['code'] == 'shipping') {
+ $shipping_cost = $total['value'];
+ }
+ }
+
+ $products = $this->model_sale_order->getOrderProducts($order_info['order_id']);
+
+ $items = array();
+
+ $i = 1;
+
+ foreach ($products as $product) {
+ $items[] = array(
+ 'lineno' => $i,
+ 'material' => '',
+ 'description' => $product['name'],
+ 'upc' => '',
+ 'quantity' => $product['quantity'],
+ 'uom' => '',
+ 'unitcost' => $product['price'],
+ 'netamnt' => $product['total'],
+ 'taxamnt' => $product['tax'],
+ 'discamnt' => ''
+ );
+
+ $i++;
+ }
+
+ $data = array(
+ 'merchid' => $this->config->get('payment_cardconnect_merchant_id'),
+ 'retref' => $order_info['retref'],
+ 'authcode' => $order_info['authcode'],
+ 'ponumber' => $order_info['order_id'],
+ 'amount' => round(floatval($amount), 2, PHP_ROUND_HALF_DOWN),
+ 'currency' => $order_info['currency_code'],
+ 'frtamnt' => $shipping_cost,
+ 'dutyamnt' => '',
+ 'orderdate' => '',
+ 'shiptozip' => $order['shipping_postcode'],
+ 'shipfromzip' => '',
+ 'shiptocountry' => $order['shipping_iso_code_2'],
+ 'Items' => $items
+ );
+
+ $data_json = json_encode($data);
+
+ $url = 'https://' . $this->config->get('cardconnect_site') . '.cardconnect.com:' . (($this->config->get('cardconnect_environment') == 'live') ? 8443 : 6443) . '/cardconnect/rest/capture';
+
+ $header = array();
+
+ $header[] = 'Content-type: application/json';
+ $header[] = 'Content-length: ' . strlen($data_json);
+ $header[] = 'Authorization: Basic ' . base64_encode($this->config->get('cardconnect_api_username') . ':' . $this->config->get('cardconnect_api_password'));
+
+ $this->model_extension_payment_cardconnect->log('Header: ' . print_r($header, true));
+
+ $this->model_extension_payment_cardconnect->log('Post Data: ' . print_r($data, true));
+
+ $this->model_extension_payment_cardconnect->log('URL: ' . $url);
+
+ $ch = curl_init();
+ curl_setopt($ch, CURLOPT_URL, $url);
+ curl_setopt($ch, CURLOPT_HTTPHEADER, $header);
+ curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'PUT');
+ curl_setopt($ch, CURLOPT_POSTFIELDS, $data_json);
+ curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
+ curl_setopt($ch, CURLOPT_TIMEOUT, 30);
+ curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
+ $response_data = curl_exec($ch);
+ if (curl_errno($ch)) {
+ $this->model_extension_payment_cardconnect->log('cURL error: ' . curl_errno($ch));
+ }
+ curl_close($ch);
+
+ $response_data = json_decode($response_data, true);
+
+ $this->log('Response: ' . print_r($response_data, true));
+
+ return $response_data;
+ }
+
+ public function refund($order_info, $amount) {
+ $this->log('Posting refund to CardConnect');
+
+ $this->log('Order ID: ' . $order_info['order_id']);
+
+ $data = array(
+ 'merchid' => $this->config->get('payment_cardconnect_merchant_id'),
+ 'amount' => round(floatval($amount), 2, PHP_ROUND_HALF_DOWN),
+ 'currency' => $order_info['currency_code'],
+ 'retref' => $order_info['retref']
+ );
+
+ $data_json = json_encode($data);
+
+ $url = 'https://' . $this->config->get('cardconnect_site') . '.cardconnect.com:' . (($this->config->get('cardconnect_environment') == 'live') ? 8443 : 6443) . '/cardconnect/rest/refund';
+
+ $header = array();
+
+ $header[] = 'Content-type: application/json';
+ $header[] = 'Content-length: ' . strlen($data_json);
+ $header[] = 'Authorization: Basic ' . base64_encode($this->config->get('cardconnect_api_username') . ':' . $this->config->get('cardconnect_api_password'));
+
+ $this->model_extension_payment_cardconnect->log('Header: ' . print_r($header, true));
+
+ $this->model_extension_payment_cardconnect->log('Post Data: ' . print_r($data, true));
+
+ $this->model_extension_payment_cardconnect->log('URL: ' . $url);
+
+ $ch = curl_init();
+ curl_setopt($ch, CURLOPT_URL, $url);
+ curl_setopt($ch, CURLOPT_HTTPHEADER, $header);
+ curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'PUT');
+ curl_setopt($ch, CURLOPT_POSTFIELDS, $data_json);
+ curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
+ curl_setopt($ch, CURLOPT_TIMEOUT, 30);
+ curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
+ $response_data = curl_exec($ch);
+ if (curl_errno($ch)) {
+ $this->model_extension_payment_cardconnect->log('cURL error: ' . curl_errno($ch));
+ }
+ curl_close($ch);
+
+ $response_data = json_decode($response_data, true);
+
+ $this->log('Response: ' . print_r($response_data, true));
+
+ return $response_data;
+ }
+
+ public function void($order_info, $retref) {
+ $this->log('Posting void to CardConnect');
+
+ $this->log('Order ID: ' . $order_info['order_id']);
+
+ $data = array(
+ 'merchid' => $this->config->get('payment_cardconnect_merchant_id'),
+ 'amount' => 0,
+ 'currency' => $order_info['currency_code'],
+ 'retref' => $retref
+ );
+
+ $data_json = json_encode($data);
+
+ $url = 'https://' . $this->config->get('cardconnect_site') . '.cardconnect.com:' . (($this->config->get('cardconnect_environment') == 'live') ? 8443 : 6443) . '/cardconnect/rest/void';
+
+ $header = array();
+
+ $header[] = 'Content-type: application/json';
+ $header[] = 'Content-length: ' . strlen($data_json);
+ $header[] = 'Authorization: Basic ' . base64_encode($this->config->get('cardconnect_api_username') . ':' . $this->config->get('cardconnect_api_password'));
+
+ $this->model_extension_payment_cardconnect->log('Header: ' . print_r($header, true));
+
+ $this->model_extension_payment_cardconnect->log('Post Data: ' . print_r($data, true));
+
+ $this->model_extension_payment_cardconnect->log('URL: ' . $url);
+
+ $ch = curl_init();
+ curl_setopt($ch, CURLOPT_URL, $url);
+ curl_setopt($ch, CURLOPT_HTTPHEADER, $header);
+ curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'PUT');
+ curl_setopt($ch, CURLOPT_POSTFIELDS, $data_json);
+ curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
+ curl_setopt($ch, CURLOPT_TIMEOUT, 30);
+ curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
+ $response_data = curl_exec($ch);
+ if (curl_errno($ch)) {
+ $this->model_extension_payment_cardconnect->log('cURL error: ' . curl_errno($ch));
+ }
+ curl_close($ch);
+
+ $response_data = json_decode($response_data, true);
+
+ $this->log('Response: ' . print_r($response_data, true));
+
+ return $response_data;
+ }
+
+ public function updateTransactionStatusByRetref($retref, $status) {
+ $this->db->query("UPDATE `" . DB_PREFIX . "cardconnect_order_transaction` SET `status` = '" . $this->db->escape($status) . "', `date_modified` = NOW() WHERE `retref` = '" . $this->db->escape($retref) . "'");
+ }
+
+ public function addTransaction($cardconnect_order_id, $type, $retref, $amount, $status) {
+ $this->db->query("INSERT INTO `" . DB_PREFIX . "cardconnect_order_transaction` SET `cardconnect_order_id` = '" . (int)$cardconnect_order_id . "', `type` = '" . $this->db->escape($type) . "', `retref` = '" . $this->db->escape($retref) . "', `amount` = '" . (float)$amount . "', `status` = '" . $this->db->escape($status) . "', `date_modified` = NOW(), `date_added` = NOW()");
+ }
+
+ public function log($data) {
+ if ($this->config->get('cardconnect_logging')) {
+ $log = new Log('cardconnect.log');
+
+ $log->write($data);
+ }
+ }
+} \ No newline at end of file
diff --git a/public/admin/model/extension/payment/cardinity.php b/public/admin/model/extension/payment/cardinity.php
new file mode 100644
index 0000000..81ee76a
--- /dev/null
+++ b/public/admin/model/extension/payment/cardinity.php
@@ -0,0 +1,98 @@
+<?php
+use Cardinity\Client;
+use Cardinity\Method\Payment;
+use Cardinity\Method\Refund;
+
+class ModelExtensionPaymentCardinity extends Model {
+ public function getOrder($order_id) {
+ $query = $this->db->query("SELECT * FROM `" . DB_PREFIX . "cardinity_order` WHERE `order_id` = '" . (int)$order_id . "' LIMIT 1");
+
+ return $query->row;
+ }
+
+ public function createClient($credentials) {
+ return Client::create(array(
+ 'consumerKey' => $credentials['key'],
+ 'consumerSecret' => $credentials['secret'],
+ ));
+ }
+
+ public function verifyCredentials($client) {
+ $method = new Payment\GetAll(10);
+
+ try {
+ $client->call($method);
+
+ return true;
+ } catch (Exception $e) {
+ $this->log($e->getMessage());
+
+ return false;
+ }
+ }
+
+ public function getPayment($client, $payment_id) {
+ $method = new Payment\Get($payment_id);
+
+ try {
+ $payment = $client->call($method);
+
+ return $payment;
+ } catch (Exception $e) {
+ $this->log($e->getMessage());
+
+ return false;
+ }
+ }
+
+ public function getRefunds($client, $payment_id) {
+ $method = new Refund\GetAll($payment_id);
+
+ try {
+ $refunds = $client->call($method);
+
+ return $refunds;
+ } catch (Exception $e) {
+ $this->log($e->getMessage());
+
+ return false;
+ }
+ }
+
+ public function refundPayment($client, $payment_id, $amount, $description) {
+ $method = new Refund\Create($payment_id, $amount, $description);
+
+ try {
+ $refund = $client->call($method);
+
+ return $refund;
+ } catch (Exception $e) {
+ $this->log($e->getMessage());
+
+ return false;
+ }
+ }
+
+ public function log($data) {
+ if ($this->config->get('payment_cardinity_debug')) {
+ $backtrace = debug_backtrace();
+ $log = new Log('cardinity.log');
+ $log->write('(' . $backtrace[1]['class'] . '::' . $backtrace[1]['function'] . ') - ' . print_r($data, true));
+ }
+ }
+
+ public function install() {
+ $this->db->query("
+ CREATE TABLE IF NOT EXISTS `" . DB_PREFIX . "cardinity_order` (
+ `cardinity_order_id` INT(11) NOT NULL AUTO_INCREMENT,
+ `order_id` INT(11) NOT NULL,
+ `payment_id` VARCHAR(255),
+ PRIMARY KEY (`cardinity_order_id`)
+ ) ENGINE=MyISAM DEFAULT COLLATE=utf8_general_ci;
+ ");
+ }
+
+ public function uninstall() {
+ $this->db->query("DROP TABLE IF EXISTS `" . DB_PREFIX . "cardinity_order`;");
+ }
+} \ No newline at end of file
diff --git a/public/admin/model/extension/payment/divido.php b/public/admin/model/extension/payment/divido.php
new file mode 100644
index 0000000..b8c6116
--- /dev/null
+++ b/public/admin/model/extension/payment/divido.php
@@ -0,0 +1,81 @@
+<?php
+class ModelExtensionPaymentDivido extends Model {
+ const CACHE_KEY_PLANS = 'divido_plans';
+
+ public function getAllPlans() {
+ if ($plans = $this->cache->get(self::CACHE_KEY_PLANS)) {
+ // OpenCart 2.1 decodes json objects to associative arrays so we
+ // need to make sure we're getting a list of simple objects back.
+ $plans = array_map(function ($plan) {
+ return (object)$plan;
+ }, $plans);
+
+ return $plans;
+ }
+
+ $api_key = $this->config->get('payment_divido_api_key');
+ if (!$api_key) {
+ throw new Exception("No Divido api-key defined");
+ }
+
+ Divido::setMerchant($api_key);
+
+ $response = Divido_Finances::all();
+ if ($response->status != 'ok') {
+ throw new Exception("Can't get list of finance plans from Divido!");
+ }
+
+ $plans = $response->finances;
+
+ // OpenCart 2.1 switched to json for their file storage cache, so
+ // we need to convert to a simple object.
+ $plans_plain = array();
+ foreach ($plans as $plan) {
+ $plan_copy = new stdClass();
+ $plan_copy->id = $plan->id;
+ $plan_copy->text = $plan->text;
+ $plan_copy->country = $plan->country;
+ $plan_copy->min_amount = $plan->min_amount;
+ $plan_copy->min_deposit = $plan->min_deposit;
+ $plan_copy->max_deposit = $plan->max_deposit;
+ $plan_copy->interest_rate = $plan->interest_rate;
+ $plan_copy->deferral_period = $plan->deferral_period;
+ $plan_copy->agreement_duration = $plan->agreement_duration;
+
+ $plans_plain[] = $plan_copy;
+ }
+
+ $this->cache->set(self::CACHE_KEY_PLANS, $plans_plain);
+
+ return $plans_plain;
+ }
+
+ public function getLookupByOrderId($order_id) {
+ return $this->db->query("SELECT * FROM `" . DB_PREFIX . "divido_lookup` WHERE `order_id` = " . (int)$order_id);
+ }
+
+ public function install() {
+ $this->db->query("
+ CREATE TABLE IF NOT EXISTS `" . DB_PREFIX . "divido_product` (
+ `product_id` INT(11) NOT NULL,
+ `display` CHAR(7) NOT NULL,
+ `plans` text,
+ PRIMARY KEY (`product_id`)
+ ) ENGINE=MyISAM DEFAULT COLLATE=utf8_general_ci;");
+
+ $this->db->query("
+ CREATE TABLE IF NOT EXISTS `" . DB_PREFIX . "divido_lookup` (
+ `order_id` INT(11) NOT NULL,
+ `salt` CHAR(64) NOT NULL,
+ `proposal_id` CHAR(40),
+ `application_id` CHAR(40),
+ `deposit_amount` NUMERIC(6,2),
+ PRIMARY KEY (`order_id`)
+ ) ENGINE=MyISAM DEFAULT COLLATE=utf8_general_ci;");
+ }
+
+ public function uninstall() {
+ $this->db->query("DROP TABLE IF EXISTS `" . DB_PREFIX . "divido_product`;");
+ $this->db->query("DROP TABLE IF EXISTS `" . DB_PREFIX . "divido_lookup`;");
+ }
+}
diff --git a/public/admin/model/extension/payment/eway.php b/public/admin/model/extension/payment/eway.php
new file mode 100644
index 0000000..070a8d5
--- /dev/null
+++ b/public/admin/model/extension/payment/eway.php
@@ -0,0 +1,227 @@
+<?php
+
+class ModelExtensionPaymentEway extends Model {
+
+ public function install() {
+ $this->db->query("
+ CREATE TABLE IF NOT EXISTS `" . DB_PREFIX . "eway_order` (
+ `eway_order_id` int(11) NOT NULL AUTO_INCREMENT,
+ `order_id` int(11) NOT NULL,
+ `created` DATETIME NOT NULL,
+ `modified` DATETIME NOT NULL,
+ `amount` DECIMAL( 10, 2 ) NOT NULL,
+ `currency_code` CHAR(3) NOT NULL,
+ `transaction_id` VARCHAR(24) NOT NULL,
+ `debug_data` TEXT,
+ `capture_status` INT(1) DEFAULT NULL,
+ `void_status` INT(1) DEFAULT NULL,
+ `refund_status` INT(1) DEFAULT NULL,
+ PRIMARY KEY (`eway_order_id`)
+ ) ENGINE=MyISAM DEFAULT COLLATE=utf8_general_ci;");
+
+ $this->db->query("
+ CREATE TABLE IF NOT EXISTS `" . DB_PREFIX . "eway_transactions` (
+ `eway_order_transaction_id` int(11) NOT NULL AUTO_INCREMENT,
+ `eway_order_id` int(11) NOT NULL,
+ `transaction_id` VARCHAR(24) NOT NULL,
+ `created` DATETIME NOT NULL,
+ `type` ENUM('auth', 'payment', 'refund', 'void') DEFAULT NULL,
+ `amount` DECIMAL( 10, 2 ) NOT NULL,
+ PRIMARY KEY (`eway_order_transaction_id`)
+ ) ENGINE=MyISAM DEFAULT COLLATE=utf8_general_ci;");
+
+ $this->db->query("
+ CREATE TABLE IF NOT EXISTS `" . DB_PREFIX . "eway_card` (
+ `card_id` INT(11) NOT NULL AUTO_INCREMENT,
+ `customer_id` INT(11) NOT NULL,
+ `order_id` INT(11) NOT NULL,
+ `token` VARCHAR(50) NOT NULL,
+ `digits` VARCHAR(4) NOT NULL,
+ `expiry` VARCHAR(5) NOT NULL,
+ `type` VARCHAR(50) NOT NULL,
+ PRIMARY KEY (`card_id`)
+ ) ENGINE=MyISAM DEFAULT COLLATE=utf8_general_ci;");
+ }
+
+ public function uninstall() {
+ //$this->model_setting_setting->deleteSetting($this->request->get['extension']);
+ $this->db->query("DROP TABLE IF EXISTS `" . DB_PREFIX . "eway_order`;");
+ $this->db->query("DROP TABLE IF EXISTS `" . DB_PREFIX . "eway_transactions`;");
+ $this->db->query("DROP TABLE IF EXISTS `" . DB_PREFIX . "eway_card`;");
+ }
+
+ public function getOrder($order_id) {
+ $qry = $this->db->query("SELECT * FROM `" . DB_PREFIX . "eway_order` WHERE `order_id` = '" . (int)$order_id . "' LIMIT 1");
+
+ if ($qry->num_rows) {
+ $order = $qry->row;
+ $order['transactions'] = $this->getTransactions($order['eway_order_id']);
+ return $order;
+ } else {
+ return false;
+ }
+ }
+
+ public function addRefundRecord($order, $result) {
+ $transaction_id = $result->TransactionID;
+ $total_amount = $result->Refund->TotalAmount / 100;
+ $refund_amount = $order['refund_amount'] + $total_amount;
+
+ if (isset($order['refund_transaction_id']) && !empty($order['refund_transaction_id'])) {
+ $order['refund_transaction_id'] .= ',';
+ }
+ $order['refund_transaction_id'] .= $transaction_id;
+
+ $this->db->query("UPDATE `" . DB_PREFIX . "eway_order` SET `modified` = NOW(), refund_amount = '" . (double)$refund_amount . "', `refund_transaction_id` = '" . $this->db->escape($order['refund_transaction_id']) . "' WHERE eway_order_id = '" . $order['eway_order_id'] . "'");
+ }
+
+ public function capture($order_id, $capture_amount, $currency) {
+ $eway_order = $this->getOrder($order_id);
+
+ if ($eway_order && $capture_amount > 0 ) {
+
+ $capture_data = new stdClass();
+ $capture_data->Payment = new stdClass();
+ $capture_data->Payment->TotalAmount = (int)(number_format($capture_amount, 2, '.', '') * 100);
+ $capture_data->Payment->CurrencyCode = $currency;
+ $capture_data->TransactionID = $eway_order['transaction_id'];
+
+ if ($this->config->get('payment_eway_test')) {
+ $url = 'https://api.sandbox.ewaypayments.com/CapturePayment';
+ } else {
+ $url = 'https://api.ewaypayments.com/CapturePayment';
+ }
+
+ $response = $this->sendCurl($url, $capture_data);
+
+ return json_decode($response);
+
+ } else {
+ return false;
+ }
+ }
+
+ public function updateCaptureStatus($eway_order_id, $status) {
+ $this->db->query("UPDATE `" . DB_PREFIX . "eway_order` SET `capture_status` = '" . (int)$status . "' WHERE `eway_order_id` = '" . (int)$eway_order_id . "'");
+ }
+
+ public function updateTransactionId($eway_order_id, $transaction_id) {
+ $this->db->query("UPDATE `" . DB_PREFIX . "eway_order` SET `transaction_id` = '" . $transaction_id . "' WHERE `eway_order_id` = '" . (int)$eway_order_id . "'");
+ }
+
+ public function void($order_id) {
+ $eway_order = $this->getOrder($order_id);
+ if ($eway_order) {
+
+ $data = new stdClass();
+ $data->TransactionID = $eway_order['transaction_id'];
+
+ if ($this->config->get('payment_eway_test')) {
+ $url = 'https://api.sandbox.ewaypayments.com/CancelAuthorisation';
+ } else {
+ $url = 'https://api.ewaypayments.com/CancelAuthorisation';
+ }
+
+ $response = $this->sendCurl($url, $data);
+
+ return json_decode($response);
+
+ } else {
+ return false;
+ }
+ }
+
+ public function updateVoidStatus($eway_order_id, $status) {
+ $this->db->query("UPDATE `" . DB_PREFIX . "eway_order` SET `void_status` = '" . (int)$status . "' WHERE `eway_order_id` = '" . (int)$eway_order_id . "'");
+ }
+
+ public function refund($order_id, $refund_amount) {
+ $eway_order = $this->getOrder($order_id);
+
+ if ($eway_order && $refund_amount > 0) {
+
+ $refund_data = new stdClass();
+ $refund_data->Refund = new stdClass();
+ $refund_data->Refund->TotalAmount = (int)(number_format($refund_amount, 2, '.', '') * 100);
+ $refund_data->Refund->TransactionID = $eway_order['transaction_id'];
+ $refund_data->Refund->CurrencyCode = $eway_order['currency_code'];
+
+ if ($this->config->get('payment_eway_test')) {
+ $url = 'https://api.sandbox.ewaypayments.com/Transaction/' . $eway_order['transaction_id'] . '/Refund';
+ } else {
+ $url = 'https://api.ewaypayments.com/Transaction/' . $eway_order['transaction_id'] . '/Refund';
+ }
+
+ $response = $this->sendCurl($url, $refund_data);
+
+ return json_decode($response);
+ } else {
+ return false;
+ }
+ }
+
+ public function updateRefundStatus($eway_order_id, $status) {
+ $this->db->query("UPDATE `" . DB_PREFIX . "eway_order` SET `refund_status` = '" . (int)$status . "' WHERE `eway_order_id` = '" . (int)$eway_order_id . "'");
+ }
+
+ public function sendCurl($url, $data) {
+ $ch = curl_init($url);
+
+ $eway_username = html_entity_decode($this->config->get('payment_eway_username'), ENT_QUOTES, 'UTF-8');
+ $eway_password = html_entity_decode($this->config->get('payment_eway_password'), ENT_QUOTES, 'UTF-8');
+
+ curl_setopt($ch, CURLOPT_HTTPHEADER, array("Content-Type: application/json"));
+ curl_setopt($ch, CURLOPT_USERPWD, $eway_username . ":" . $eway_password);
+ curl_setopt($ch, CURLOPT_POST, 1);
+ curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($data));
+ curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
+ curl_setopt($ch, CURLOPT_TIMEOUT, 60);
+ curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 1);
+
+ $response = curl_exec($ch);
+
+ if (curl_errno($ch) != CURLE_OK) {
+ $response = new stdClass();
+ $response->Errors = "POST Error: " . curl_error($ch) . " URL: $url";
+ $response = json_encode($response);
+ } else {
+ $info = curl_getinfo($ch);
+ if ($info['http_code'] == 401 || $info['http_code'] == 404) {
+ $response = new stdClass();
+ $response->Errors = "Please check the API Key and Password";
+ $response = json_encode($response);
+ }
+ }
+
+ curl_close($ch);
+
+ return $response;
+ }
+
+ private function getTransactions($eway_order_id) {
+ $qry = $this->db->query("SELECT * FROM `" . DB_PREFIX . "eway_transactions` WHERE `eway_order_id` = '" . (int)$eway_order_id . "'");
+
+ if ($qry->num_rows) {
+ return $qry->rows;
+ } else {
+ return false;
+ }
+ }
+
+ public function addTransaction($eway_order_id, $transactionid, $type, $total, $currency) {
+ $this->db->query("INSERT INTO `" . DB_PREFIX . "eway_transactions` SET `eway_order_id` = '" . (int)$eway_order_id . "', `created` = NOW(), `transaction_id` = '" . $this->db->escape($transactionid) . "', `type` = '" . $this->db->escape($type) . "', `amount` = '" . $this->currency->format($total, $currency, false, false) . "'");
+ }
+
+ public function getTotalCaptured($eway_order_id) {
+ $query = $this->db->query("SELECT SUM(`amount`) AS `total` FROM `" . DB_PREFIX . "eway_transactions` WHERE `eway_order_id` = '" . (int)$eway_order_id . "' AND `type` = 'payment' ");
+
+ return (double)$query->row['total'];
+ }
+
+ public function getTotalRefunded($eway_order_id) {
+ $query = $this->db->query("SELECT SUM(`amount`) AS `total` FROM `" . DB_PREFIX . "eway_transactions` WHERE `eway_order_id` = '" . (int)$eway_order_id . "' AND `type` = 'refund'");
+
+ return (double)$query->row['total'];
+ }
+
+} \ No newline at end of file
diff --git a/public/admin/model/extension/payment/firstdata.php b/public/admin/model/extension/payment/firstdata.php
new file mode 100644
index 0000000..bac5b8e
--- /dev/null
+++ b/public/admin/model/extension/payment/firstdata.php
@@ -0,0 +1,222 @@
+<?php
+class ModelExtensionPaymentFirstdata extends Model {
+ public function install() {
+ $this->db->query("
+ CREATE TABLE IF NOT EXISTS `" . DB_PREFIX . "firstdata_order` (
+ `firstdata_order_id` INT(11) NOT NULL AUTO_INCREMENT,
+ `order_id` INT(11) NOT NULL,
+ `order_ref` CHAR(50) NOT NULL,
+ `order_ref_previous` CHAR(50) NOT NULL,
+ `pasref` VARCHAR(50) NOT NULL,
+ `pasref_previous` VARCHAR(50) NOT NULL,
+ `tdate` DATETIME NOT NULL,
+ `date_added` DATETIME NOT NULL,
+ `date_modified` DATETIME NOT NULL,
+ `capture_status` INT(1) DEFAULT NULL,
+ `void_status` INT(1) DEFAULT NULL,
+ `currency_code` CHAR(3) NOT NULL,
+ `authcode` VARCHAR(30) NOT NULL,
+ `account` VARCHAR(30) NOT NULL,
+ `total` DECIMAL( 10, 2 ) NOT NULL,
+ PRIMARY KEY (`firstdata_order_id`)
+ ) ENGINE=MyISAM DEFAULT COLLATE=utf8_general_ci;");
+
+ $this->db->query("
+ CREATE TABLE IF NOT EXISTS `" . DB_PREFIX . "firstdata_order_transaction` (
+ `firstdata_order_transaction_id` INT(11) NOT NULL AUTO_INCREMENT,
+ `firstdata_order_id` INT(11) NOT NULL,
+ `date_added` DATETIME NOT NULL,
+ `type` ENUM('auth', 'payment', 'void') DEFAULT NULL,
+ `amount` DECIMAL( 10, 2 ) NOT NULL,
+ PRIMARY KEY (`firstdata_order_transaction_id`)
+ ) ENGINE=MyISAM DEFAULT COLLATE=utf8_general_ci;");
+
+ $this->db->query("
+ CREATE TABLE IF NOT EXISTS `" . DB_PREFIX . "firstdata_card` (
+ `firstdata_card_id` INT(11) NOT NULL AUTO_INCREMENT,
+ `customer_id` INT(11) NOT NULL,
+ `date_added` DATETIME NOT NULL,
+ `digits` CHAR(25) NOT NULL,
+ `expire_month` INT(2) NOT NULL,
+ `expire_year` INT(2) NOT NULL,
+ `token` CHAR(64) NOT NULL,
+ PRIMARY KEY (`firstdata_card_id`)
+ ) ENGINE=MyISAM DEFAULT COLLATE=utf8_general_ci;");
+ }
+
+ public function uninstall() {
+ $this->db->query("DROP TABLE IF EXISTS `" . DB_PREFIX . "firstdata_order`;");
+ $this->db->query("DROP TABLE IF EXISTS `" . DB_PREFIX . "firstdata_order_transaction`;");
+ $this->db->query("DROP TABLE IF EXISTS `" . DB_PREFIX . "firstdata_card`;");
+ }
+
+ public function void($order_id) {
+ $firstdata_order = $this->getOrder($order_id);
+
+ if (!empty($firstdata_order)) {
+ $timestamp = strftime("%Y%m%d%H%M%S");
+ $merchant_id = $this->config->get('payment_firstdata_merchant_id');
+ $secret = $this->config->get('payment_firstdata_secret');
+
+ $this->logger('Void hash construct: ' . $timestamp . ' . ' . $merchant_id . ' . ' . $firstdata_order['order_ref'] . ' . . . ');
+
+ $tmp = $timestamp . ' . ' . $merchant_id . ' . ' . $firstdata_order['order_ref'] . ' . . . ';
+ $hash = sha1($tmp);
+ $tmp = $hash . ' . ' . $secret;
+ $hash = sha1($tmp);
+
+ $xml = '';
+ $xml .= '<request type="void" timestamp="' . $timestamp . '">';
+ $xml .= '<merchantid>' . $merchant_id . '</merchantid>';
+ $xml .= '<account>' . $firstdata_order['account'] . '</account>';
+ $xml .= '<orderid>' . $firstdata_order['order_ref'] . '</orderid>';
+ $xml .= '<pasref>' . $firstdata_order['pasref'] . '</pasref>';
+ $xml .= '<authcode>' . $firstdata_order['authcode'] . '</authcode>';
+ $xml .= '<sha1hash>' . $hash . '</sha1hash>';
+ $xml .= '</request>';
+
+ $this->logger('Void XML request:\r\n' . print_r(simplexml_load_string($xml), 1));
+
+ $ch = curl_init();
+ curl_setopt($ch, CURLOPT_URL, "https://epage.payandshop.com/epage-remote.cgi");
+ curl_setopt($ch, CURLOPT_POST, 1);
+ curl_setopt($ch, CURLOPT_USERAGENT, "OpenCart " . VERSION);
+ curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
+ curl_setopt($ch, CURLOPT_POSTFIELDS, $xml);
+ curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
+ $response = curl_exec ($ch);
+ curl_close ($ch);
+
+ return simplexml_load_string($response);
+ } else {
+ return false;
+ }
+ }
+
+ public function updateVoidStatus($firstdata_order_id, $status) {
+ $this->db->query("UPDATE `" . DB_PREFIX . "firstdata_order` SET `void_status` = '" . (int)$status . "' WHERE `firstdata_order_id` = '" . (int)$firstdata_order_id . "'");
+ }
+
+ public function capture($order_id, $amount) {
+ $firstdata_order = $this->getOrder($order_id);
+
+ if (!empty($firstdata_order) && $firstdata_order['capture_status'] == 0) {
+ $timestamp = strftime("%Y%m%d%H%M%S");
+ $merchant_id = $this->config->get('payment_firstdata_merchant_id');
+ $secret = $this->config->get('payment_firstdata_secret');
+
+ if ($firstdata_order['settle_type'] == 2) {
+ $this->logger('Capture hash construct: ' . $timestamp . ' . ' . $merchant_id . ' . ' . $firstdata_order['order_ref'] . ' . ' . (int)round($amount*100) . ' . ' . (string)$firstdata_order['currency_code'] . ' . ');
+
+ $tmp = $timestamp . ' . ' . $merchant_id . ' . ' . $firstdata_order['order_ref'] . ' . ' . (int)round($amount*100) . ' . ' . (string)$firstdata_order['currency_code'] . ' . ';
+ $hash = sha1($tmp);
+ $tmp = $hash . ' . ' . $secret;
+ $hash = sha1($tmp);
+
+ $settle_type = 'multisettle';
+ $xml_amount = '<amount currency="' . (string)$firstdata_order['currency_code'] . '">' . (int)round($amount*100) . '</amount>';
+ } else {
+ //$this->logger('Capture hash construct: ' . $timestamp . ' . ' . $merchant_id . ' . ' . $firstdata_order['order_ref'] . ' . . . ');
+ $this->logger('Capture hash construct: ' . $timestamp . ' . ' . $merchant_id . ' . ' . $firstdata_order['order_ref'] . ' . ' . (int)round($amount*100) . ' . ' . (string)$firstdata_order['currency_code'] . ' . ');
+
+ $tmp = $timestamp . ' . ' . $merchant_id . ' . ' . $firstdata_order['order_ref'] . ' . ' . (int)round($amount*100) . ' . ' . (string)$firstdata_order['currency_code'] . ' . ';
+ $hash = sha1($tmp);
+ $tmp = $hash . ' . ' . $secret;
+ $hash = sha1($tmp);
+
+ $settle_type = 'settle';
+ $xml_amount = '<amount currency="' . (string)$firstdata_order['currency_code'] . '">' . (int)round($amount*100) . '</amount>';
+ }
+
+ $xml = '';
+ $xml .= '<request type="' . $settle_type . '" timestamp="' . $timestamp . '">';
+ $xml .= '<merchantid>' . $merchant_id . '</merchantid>';
+ $xml .= '<account>' . $firstdata_order['account'] . '</account>';
+ $xml .= '<orderid>' . $firstdata_order['order_ref'] . '</orderid>';
+ $xml .= $xml_amount;
+ $xml .= '<pasref>' . $firstdata_order['pasref'] . '</pasref>';
+ $xml .= '<autosettle flag="1" />';
+ $xml .= '<authcode>' . $firstdata_order['authcode'] . '</authcode>';
+ $xml .= '<sha1hash>' . $hash . '</sha1hash>';
+ $xml .= '</request>';
+
+ $this->logger('Settle XML request:\r\n' . print_r(simplexml_load_string($xml), 1));
+
+ $ch = curl_init();
+ curl_setopt($ch, CURLOPT_URL, "https://epage.payandshop.com/epage-remote.cgi");
+ curl_setopt($ch, CURLOPT_POST, 1);
+ curl_setopt($ch, CURLOPT_USERAGENT, "OpenCart " . VERSION);
+ curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
+ curl_setopt($ch, CURLOPT_POSTFIELDS, $xml);
+ curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
+ $response = curl_exec ($ch);
+ curl_close ($ch);
+
+ return simplexml_load_string($response);
+ } else {
+ return false;
+ }
+ }
+
+ public function updateCaptureStatus($firstdata_order_id, $status) {
+ $this->db->query("UPDATE `" . DB_PREFIX . "firstdata_order` SET `capture_status` = '" . (int)$status . "' WHERE `firstdata_order_id` = '" . (int)$firstdata_order_id . "'");
+ }
+
+ public function getOrder($order_id) {
+ $this->logger('getOrder - ' . $order_id);
+
+ $qry = $this->db->query("SELECT * FROM `" . DB_PREFIX . "firstdata_order` WHERE `order_id` = '" . (int)$order_id . "' LIMIT 1");
+
+ if ($qry->num_rows) {
+ $order = $qry->row;
+ $order['transactions'] = $this->getTransactions($order['firstdata_order_id']);
+
+ $this->logger(print_r($order, 1));
+
+ return $order;
+ } else {
+ return false;
+ }
+ }
+
+ private function getTransactions($firstdata_order_id) {
+ $qry = $this->db->query("SELECT * FROM `" . DB_PREFIX . "firstdata_order_transaction` WHERE `firstdata_order_id` = '" . (int)$firstdata_order_id . "'");
+
+ if ($qry->num_rows) {
+ return $qry->rows;
+ } else {
+ return false;
+ }
+ }
+
+ public function addTransaction($firstdata_order_id, $type, $total) {
+ $this->db->query("INSERT INTO `" . DB_PREFIX . "firstdata_order_transaction` SET `firstdata_order_id` = '" . (int)$firstdata_order_id . "', `date_added` = now(), `type` = '" . $this->db->escape($type) . "', `amount` = '" . (float)$total . "'");
+ }
+
+ public function logger($message) {
+ if ($this->config->get('payment_firstdata_debug') == 1) {
+ $log = new Log('firstdata.log');
+ $log->write($message);
+ }
+ }
+
+ public function getTotalCaptured($firstdata_order_id) {
+ $query = $this->db->query("SELECT SUM(`amount`) AS `total` FROM `" . DB_PREFIX . "firstdata_order_transaction` WHERE `firstdata_order_id` = '" . (int)$firstdata_order_id . "' AND (`type` = 'payment' OR `type` = 'refund')");
+
+ return (float)$query->row['total'];
+ }
+
+ public function mapCurrency($code) {
+ $currency = array(
+ 'GBP' => 826,
+ 'USD' => 840,
+ 'EUR' => 978,
+ );
+
+ if (array_key_exists($code, $currency)) {
+ return $currency[$code];
+ } else {
+ return false;
+ }
+ }
+} \ No newline at end of file
diff --git a/public/admin/model/extension/payment/firstdata_remote.php b/public/admin/model/extension/payment/firstdata_remote.php
new file mode 100644
index 0000000..9cbd1bc
--- /dev/null
+++ b/public/admin/model/extension/payment/firstdata_remote.php
@@ -0,0 +1,278 @@
+<?php
+class ModelExtensionPaymentFirstdataRemote extends Model {
+ public function install() {
+ $this->db->query("
+ CREATE TABLE IF NOT EXISTS `" . DB_PREFIX . "firstdata_remote_order` (
+ `firstdata_remote_order_id` INT(11) NOT NULL AUTO_INCREMENT,
+ `order_id` INT(11) NOT NULL,
+ `order_ref` CHAR(50) NOT NULL,
+ `date_added` DATETIME NOT NULL,
+ `date_modified` DATETIME NOT NULL,
+ `tdate` VARCHAR(30) NOT NULL,
+ `capture_status` INT(1) DEFAULT NULL,
+ `void_status` INT(1) DEFAULT NULL,
+ `refund_status` INT(1) DEFAULT NULL,
+ `currency_code` CHAR(3) NOT NULL,
+ `authcode` VARCHAR(30) NOT NULL,
+ `total` DECIMAL( 10, 2 ) NOT NULL,
+ PRIMARY KEY (`firstdata_remote_order_id`)
+ ) ENGINE=MyISAM DEFAULT COLLATE=utf8_general_ci;");
+
+ $this->db->query("
+ CREATE TABLE IF NOT EXISTS `" . DB_PREFIX . "firstdata_remote_order_transaction` (
+ `firstdata_remote_order_transaction_id` INT(11) NOT NULL AUTO_INCREMENT,
+ `firstdata_remote_order_id` INT(11) NOT NULL,
+ `date_added` DATETIME NOT NULL,
+ `type` ENUM('auth', 'payment', 'refund', 'void') DEFAULT NULL,
+ `amount` DECIMAL( 10, 2 ) NOT NULL,
+ PRIMARY KEY (`firstdata_remote_order_transaction_id`)
+ ) ENGINE=MyISAM DEFAULT COLLATE=utf8_general_ci;");
+
+ $this->db->query("
+ CREATE TABLE IF NOT EXISTS `" . DB_PREFIX . "firstdata_remote_card` (
+ `firstdata_remote_card_id` INT(11) NOT NULL AUTO_INCREMENT,
+ `customer_id` INT(11) NOT NULL,
+ `date_added` DATETIME NOT NULL,
+ `digits` CHAR(4) NOT NULL,
+ `expire_month` INT(2) NOT NULL,
+ `expire_year` INT(2) NOT NULL,
+ `card_type` CHAR(15) NOT NULL,
+ `token` CHAR(64) NOT NULL,
+ PRIMARY KEY (`firstdata_remote_card_id`)
+ ) ENGINE=MyISAM DEFAULT COLLATE=utf8_general_ci;");
+ }
+
+ public function uninstall() {
+ $this->db->query("DROP TABLE IF EXISTS `" . DB_PREFIX . "firstdata_remote_order`;");
+ $this->db->query("DROP TABLE IF EXISTS `" . DB_PREFIX . "firstdata_remote_order_transaction`;");
+ $this->db->query("DROP TABLE IF EXISTS `" . DB_PREFIX . "firstdata_remote_card`;");
+ }
+
+ public function call($xml) {
+ $ch = curl_init();
+ curl_setopt($ch, CURLOPT_URL, "https://test.ipg-online.com/ipgapi/services");
+ curl_setopt($ch, CURLOPT_POST, 1);
+ curl_setopt($ch, CURLOPT_HTTPHEADER, array("Content-Type: text/xml"));
+ curl_setopt($ch, CURLOPT_HTTPAUTH, 'CURLAUTH_BASIC');
+ curl_setopt($ch, CURLOPT_USERPWD, $this->config->get('firstdata_remote_user_id') . ':' . $this->config->get('firstdata_remote_password'));
+ curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 1);
+ curl_setopt($ch, CURLOPT_CAINFO, $this->config->get('firstdata_remote_ca'));
+ curl_setopt($ch, CURLOPT_SSLCERT, $this->config->get('firstdata_remote_certificate'));
+ curl_setopt($ch, CURLOPT_SSLKEY, $this->config->get('firstdata_remote_key'));
+ curl_setopt($ch, CURLOPT_SSLKEYPASSWD, $this->config->get('firstdata_remote_key_pw'));
+ curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
+ curl_setopt($ch, CURLOPT_POSTFIELDS, $xml);
+ //curl_setopt($ch, CURLOPT_STDERR, fopen(DIR_LOGS . "/headers.txt", "w+"));
+ curl_setopt($ch, CURLOPT_VERBOSE, true);
+ $response = curl_exec ($ch);
+
+ $this->logger('Post data: ' . print_r($this->request->post, 1));
+ $this->logger('Request: ' . $xml);
+ $this->logger('Curl error #: ' . curl_errno($ch));
+ $this->logger('Curl error text: ' . curl_error($ch));
+ $this->logger('Curl response info: ' . print_r(curl_getinfo($ch), 1));
+ $this->logger('Curl response: ' . $response);
+
+ curl_close ($ch);
+
+ return $response;
+ }
+
+ public function void($order_ref, $tdate) {
+ $xml = '<?xml version="1.0" encoding="UTF-8"?>';
+ $xml .= '<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/">';
+ $xml .= '<SOAP-ENV:Header />';
+ $xml .= '<SOAP-ENV:Body>';
+ $xml .= '<ipgapi:IPGApiOrderRequest xmlns:v1="http://ipg-online.com/ipgapi/schemas/v1" xmlns:ipgapi="http://ipg-online.com/ipgapi/schemas/ipgapi">';
+ $xml .= '<v1:Transaction>';
+ $xml .= '<v1:CreditCardTxType>';
+ $xml .= '<v1:Type>void</v1:Type>';
+ $xml .= '</v1:CreditCardTxType>';
+ $xml .= '<v1:TransactionDetails>';
+ $xml .= '<v1:OrderId>' . $order_ref . '</v1:OrderId>';
+ $xml .= '<v1:TDate>' . $tdate . '</v1:TDate>';
+ $xml .= '</v1:TransactionDetails>';
+ $xml .= '</v1:Transaction>';
+ $xml .= '</ipgapi:IPGApiOrderRequest>';
+ $xml .= '</SOAP-ENV:Body>';
+ $xml .= '</SOAP-ENV:Envelope>';
+
+ $xml = simplexml_load_string($this->call($xml));
+
+ $xml->registerXPathNamespace('ipgapi', 'http://ipg-online.com/ipgapi/schemas/ipgapi');
+ $xml->registerXPathNamespace('soap', 'http://schemas.xmlsoap.org/soap/envelope/');
+
+ $fault = $xml->xpath('//soap:Fault');
+
+ $response['fault'] = '';
+ if (!empty($fault[0]) && isset($fault[0]->detail)) {
+ $response['fault'] = (string)$fault[0]->detail;
+ }
+
+ $string = $xml->xpath('//ipgapi:ErrorMessage');
+ $response['error'] = isset($string[0]) ? (string)$string[0] : '';
+
+ $string = $xml->xpath('//ipgapi:TransactionResult');
+ $response['transaction_result'] = isset($string[0]) ? (string)$string[0] : '';
+
+ return $response;
+ }
+
+ public function updateVoidStatus($firstdata_remote_order_id, $status) {
+ $this->db->query("UPDATE `" . DB_PREFIX . "firstdata_remote_order` SET `void_status` = '" . (int)$status . "' WHERE `firstdata_remote_order_id` = '" . (int)$firstdata_remote_order_id . "'");
+ }
+
+ public function capture($order_ref, $total, $currency_code) {
+ $xml = '<?xml version="1.0" encoding="UTF-8"?>';
+ $xml .= '<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/">';
+ $xml .= '<SOAP-ENV:Header />';
+ $xml .= '<SOAP-ENV:Body>';
+ $xml .= '<ipgapi:IPGApiOrderRequest xmlns:v1="http://ipg-online.com/ipgapi/schemas/v1" xmlns:ipgapi="http://ipg-online.com/ipgapi/schemas/ipgapi">';
+ $xml .= '<v1:Transaction>';
+ $xml .= '<v1:CreditCardTxType>';
+ $xml .= '<v1:Type>postAuth</v1:Type>';
+ $xml .= '</v1:CreditCardTxType>';
+ $xml .= '<v1:Payment>';
+ $xml .= '<v1:ChargeTotal>' . $total . '</v1:ChargeTotal>';
+ $xml .= '<v1:Currency>' . $this->mapCurrency($currency_code) . '</v1:Currency>';
+ $xml .= '</v1:Payment>';
+ $xml .= '<v1:TransactionDetails>';
+ $xml .= '<v1:OrderId>' . $order_ref . '</v1:OrderId>';
+ $xml .= '</v1:TransactionDetails>';
+ $xml .= '</v1:Transaction>';
+ $xml .= '</ipgapi:IPGApiOrderRequest>';
+ $xml .= '</SOAP-ENV:Body>';
+ $xml .= '</SOAP-ENV:Envelope>';
+
+ $xml = simplexml_load_string($this->call($xml));
+
+ $xml->registerXPathNamespace('ipgapi', 'http://ipg-online.com/ipgapi/schemas/ipgapi');
+ $xml->registerXPathNamespace('soap', 'http://schemas.xmlsoap.org/soap/envelope/');
+
+ $fault = $xml->xpath('//soap:Fault');
+
+ $response['fault'] = '';
+ if (!empty($fault[0]) && isset($fault[0]->detail)) {
+ $response['fault'] = (string)$fault[0]->detail;
+ }
+
+ $string = $xml->xpath('//ipgapi:ErrorMessage');
+ $response['error'] = isset($string[0]) ? (string)$string[0] : '';
+
+ $string = $xml->xpath('//ipgapi:TransactionResult');
+ $response['transaction_result'] = isset($string[0]) ? (string)$string[0] : '';
+
+ return $response;
+ }
+
+ public function updateCaptureStatus($firstdata_remote_order_id, $status) {
+ $this->db->query("UPDATE `" . DB_PREFIX . "firstdata_remote_order` SET `capture_status` = '" . (int)$status . "' WHERE `firstdata_remote_order_id` = '" . (int)$firstdata_remote_order_id . "'");
+ }
+
+ public function refund($order_ref, $total, $currency_code) {
+ $xml = '<?xml version="1.0" encoding="UTF-8"?>';
+ $xml .= '<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/">';
+ $xml .= '<SOAP-ENV:Header />';
+ $xml .= '<SOAP-ENV:Body>';
+ $xml .= '<ipgapi:IPGApiOrderRequest xmlns:v1="http://ipg-online.com/ipgapi/schemas/v1" xmlns:ipgapi="http://ipg-online.com/ipgapi/schemas/ipgapi">';
+ $xml .= '<v1:Transaction>';
+ $xml .= '<v1:CreditCardTxType>';
+ $xml .= '<v1:Type>return</v1:Type>';
+ $xml .= '</v1:CreditCardTxType>';
+ $xml .= '<v1:Payment>';
+ $xml .= '<v1:ChargeTotal>' . $total . '</v1:ChargeTotal>';
+ $xml .= '<v1:Currency>' . $this->mapCurrency($currency_code) . '</v1:Currency>';
+ $xml .= '</v1:Payment>';
+ $xml .= '<v1:TransactionDetails>';
+ $xml .= '<v1:OrderId>' . $order_ref . '</v1:OrderId>';
+ $xml .= '</v1:TransactionDetails>';
+ $xml .= '</v1:Transaction>';
+ $xml .= '</ipgapi:IPGApiOrderRequest>';
+ $xml .= '</SOAP-ENV:Body>';
+ $xml .= '</SOAP-ENV:Envelope>';
+
+ $xml = simplexml_load_string($this->call($xml));
+
+ $xml->registerXPathNamespace('ipgapi', 'http://ipg-online.com/ipgapi/schemas/ipgapi');
+ $xml->registerXPathNamespace('soap', 'http://schemas.xmlsoap.org/soap/envelope/');
+
+ $fault = $xml->xpath('//soap:Fault');
+
+ $response['fault'] = '';
+ if (!empty($fault[0]) && isset($fault[0]->detail)) {
+ $response['fault'] = (string)$fault[0]->detail;
+ }
+
+ $string = $xml->xpath('//ipgapi:ErrorMessage');
+ $response['error'] = isset($string[0]) ? (string)$string[0] : '';
+
+ $string = $xml->xpath('//ipgapi:TransactionResult');
+ $response['transaction_result'] = isset($string[0]) ? (string)$string[0] : '';
+
+ return $response;
+ }
+
+ public function updateRefundStatus($firstdata_remote_order_id, $status) {
+ $this->db->query("UPDATE `" . DB_PREFIX . "firstdata_remote_order` SET `refund_status` = '" . (int)$status . "' WHERE `firstdata_remote_order_id` = '" . (int)$firstdata_remote_order_id . "'");
+ }
+
+ public function getOrder($order_id) {
+ $qry = $this->db->query("SELECT * FROM `" . DB_PREFIX . "firstdata_remote_order` WHERE `order_id` = '" . (int)$order_id . "' LIMIT 1");
+
+ if ($qry->num_rows) {
+ $order = $qry->row;
+ $order['transactions'] = $this->getTransactions($order['firstdata_remote_order_id']);
+
+ return $order;
+ } else {
+ return false;
+ }
+ }
+
+ private function getTransactions($firstdata_remote_order_id) {
+ $qry = $this->db->query("SELECT * FROM `" . DB_PREFIX . "firstdata_remote_order_transaction` WHERE `firstdata_remote_order_id` = '" . (int)$firstdata_remote_order_id . "'");
+
+ if ($qry->num_rows) {
+ return $qry->rows;
+ } else {
+ return false;
+ }
+ }
+
+ public function addTransaction($firstdata_remote_order_id, $type, $total) {
+ $this->db->query("INSERT INTO `" . DB_PREFIX . "firstdata_remote_order_transaction` SET `firstdata_remote_order_id` = '" . (int)$firstdata_remote_order_id . "', `date_added` = now(), `type` = '" . $this->db->escape($type) . "', `amount` = '" . (float)$total . "'");
+ }
+
+ public function logger($message) {
+ if ($this->config->get('firstdata_remote_debug') == 1) {
+ $log = new Log('firstdata_remote.log');
+ $log->write($message);
+ }
+ }
+
+ public function getTotalCaptured($firstdata_order_id) {
+ $query = $this->db->query("SELECT SUM(`amount`) AS `total` FROM `" . DB_PREFIX . "firstdata_remote_order_transaction` WHERE `firstdata_remote_order_id` = '" . (int)$firstdata_order_id . "' AND (`type` = 'payment' OR `type` = 'refund')");
+
+ return (float)$query->row['total'];
+ }
+
+ public function getTotalRefunded($firstdata_order_id) {
+ $query = $this->db->query("SELECT SUM(`amount`) AS `total` FROM `" . DB_PREFIX . "firstdata_remote_order_transaction` WHERE `firstdata_remote_order_id` = '" . (int)$firstdata_order_id . "' AND 'refund'");
+
+ return (float)$query->row['total'];
+ }
+
+ public function mapCurrency($code) {
+ $currency = array(
+ 'GBP' => 826,
+ 'USD' => 840,
+ 'EUR' => 978,
+ );
+
+ if (array_key_exists($code, $currency)) {
+ return $currency[$code];
+ } else {
+ return false;
+ }
+ }
+} \ No newline at end of file
diff --git a/public/admin/model/extension/payment/g2apay.php b/public/admin/model/extension/payment/g2apay.php
new file mode 100644
index 0000000..83ea7b8
--- /dev/null
+++ b/public/admin/model/extension/payment/g2apay.php
@@ -0,0 +1,145 @@
+<?php
+
+class ModelExtensionPaymentG2aPay extends Model {
+
+ public function install() {
+ $this->db->query("
+ CREATE TABLE `" . DB_PREFIX . "g2apay_order` (
+ `g2apay_order_id` INT(11) NOT NULL AUTO_INCREMENT,
+ `order_id` int(11) NOT NULL,
+ `g2apay_transaction_id` varchar(255) NOT NULL,
+ `date_added` DATETIME NOT NULL,
+ `modified` DATETIME NOT NULL,
+ `refund_status` INT(1) DEFAULT NULL,
+ `currency_code` CHAR(3) NOT NULL,
+ `total` DECIMAL( 10, 2 ) NOT NULL,
+ KEY `g2apay_transaction_id` (`g2apay_transaction_id`),
+ PRIMARY KEY `g2apay_order_id` (`g2apay_order_id`)
+ ) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_general_ci;
+ ");
+
+ $this->db->query("
+ CREATE TABLE IF NOT EXISTS `" . DB_PREFIX . "g2apay_order_transaction` (
+ `g2apay_order_transaction_id` INT(11) NOT NULL AUTO_INCREMENT,
+ `g2apay_order_id` INT(11) NOT NULL,
+ `date_added` DATETIME NOT NULL,
+ `type` ENUM('payment', 'refund') DEFAULT NULL,
+ `amount` DECIMAL( 10, 2 ) NOT NULL,
+ PRIMARY KEY (`g2apay_order_transaction_id`)
+ ) ENGINE=MyISAM DEFAULT COLLATE=utf8_general_ci;
+ ");
+ }
+
+ public function uninstall() {
+ $this->db->query("DROP TABLE IF EXISTS `" . DB_PREFIX . "g2apay_order`;");
+ $this->db->query("DROP TABLE IF EXISTS `" . DB_PREFIX . "g2apay_order_transaction`;");
+ }
+
+ public function getOrder($order_id) {
+
+ $qry = $this->db->query("SELECT * FROM `" . DB_PREFIX . "g2apay_order` WHERE `order_id` = '" . (int)$order_id . "' LIMIT 1");
+
+ if ($qry->num_rows) {
+ $order = $qry->row;
+ $order['transactions'] = $this->getTransactions($order['g2apay_order_id'], $qry->row['currency_code']);
+ return $order;
+ } else {
+ return false;
+ }
+ }
+
+ public function getTotalReleased($g2apay_order_id) {
+ $query = $this->db->query("SELECT SUM(`amount`) AS `total` FROM `" . DB_PREFIX . "g2apay_order_transaction` WHERE `g2apay_order_id` = '" . (int)$g2apay_order_id . "' AND (`type` = 'payment' OR `type` = 'refund')");
+
+ return (double)$query->row['total'];
+ }
+
+ public function refund($g2apay_order, $amount) {
+ if (!empty($g2apay_order) && $g2apay_order['refund_status'] != 1) {
+ if ($this->config->get('payment_g2apay_environment') == 1) {
+ $url = 'https://pay.g2a.com/rest/transactions/' . $g2apay_order['g2apay_transaction_id'];
+ } else {
+ $url = 'https://www.test.pay.g2a.com/rest/transactions/' . $g2apay_order['g2apay_transaction_id'];
+ }
+
+ $refunded_amount = round($amount, 2);
+
+ $string = $g2apay_order['g2apay_transaction_id'] . $g2apay_order['order_id'] . round($g2apay_order['total'], 2) . $refunded_amount . html_entity_decode($this->config->get('payment_g2apay_secret'));
+ $hash = hash('sha256', $string);
+
+ $fields = array(
+ 'action' => 'refund',
+ 'amount' => $refunded_amount,
+ 'hash' => $hash,
+ );
+
+ return $this->sendCurl($url, $fields);
+ } else {
+ return false;
+ }
+ }
+
+ public function updateRefundStatus($g2apay_order_id, $status) {
+ $this->db->query("UPDATE `" . DB_PREFIX . "g2apay_order` SET `refund_status` = '" . (int)$status . "' WHERE `g2apay_order_id` = '" . (int)$g2apay_order_id . "'");
+ }
+
+ private function getTransactions($g2apay_order_id, $currency_code) {
+ $query = $this->db->query("SELECT * FROM `" . DB_PREFIX . "g2apay_order_transaction` WHERE `g2apay_order_id` = '" . (int)$g2apay_order_id . "'");
+
+ $transactions = array();
+ if ($query->num_rows) {
+ foreach ($query->rows as $row) {
+ $row['amount'] = $this->currency->format($row['amount'], $currency_code, true, true);
+ $transactions[] = $row;
+ }
+ return $transactions;
+ } else {
+ return false;
+ }
+ }
+
+ public function addTransaction($g2apay_order_id, $type, $total) {
+ $this->db->query("INSERT INTO `" . DB_PREFIX . "g2apay_order_transaction` SET `g2apay_order_id` = '" . (int)$g2apay_order_id . "',`date_added` = now(), `type` = '" . $this->db->escape($type) . "', `amount` = '" . (double)$total . "'");
+ }
+
+ public function getTotalRefunded($g2apay_order_id) {
+ $query = $this->db->query("SELECT SUM(`amount`) AS `total` FROM `" . DB_PREFIX . "g2apay_order_transaction` WHERE `g2apay_order_id` = '" . (int)$g2apay_order_id . "' AND 'refund'");
+
+ return (double)$query->row['total'];
+ }
+
+ public function sendCurl($url, $fields) {
+ $curl = curl_init($url);
+ curl_setopt($curl, CURLOPT_URL, $url);
+ curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
+ curl_setopt($curl, CURLOPT_CUSTOMREQUEST, "PUT");
+ curl_setopt($curl, CURLOPT_POSTFIELDS, http_build_query($fields));
+
+ $auth_hash = hash('sha256', $this->config->get('payment_g2apay_api_hash') . $this->config->get('payment_g2apay_username') . html_entity_decode($this->config->get('payment_g2apay_secret')));
+ $authorization = $this->config->get('payment_g2apay_api_hash') . ";" . $auth_hash;
+ curl_setopt(
+ $curl, CURLOPT_HTTPHEADER, array(
+ "Authorization: " . $authorization
+ )
+ );
+
+ $response = json_decode(curl_exec($curl));
+
+ curl_close($curl);
+ if (is_object($response)) {
+ return (string)$response->status;
+ } else {
+ return str_replace('"', "", $response);
+ }
+ }
+
+ public function logger($message) {
+ if ($this->config->get('payment_g2apay_debug') == 1) {
+ $log = new Log('g2apay.log');
+ $backtrace = debug_backtrace();
+ $log->write('Origin: ' . $backtrace[6]['class'] . '::' . $backtrace[6]['function']);
+ $log->write(print_r($message, 1));
+ }
+ }
+
+}
diff --git a/public/admin/model/extension/payment/globalpay.php b/public/admin/model/extension/payment/globalpay.php
new file mode 100644
index 0000000..a28dbb2
--- /dev/null
+++ b/public/admin/model/extension/payment/globalpay.php
@@ -0,0 +1,265 @@
+<?php
+class ModelExtensionPaymentGlobalpay extends Model {
+ public function install() {
+ $this->db->query("
+ CREATE TABLE IF NOT EXISTS `" . DB_PREFIX . "globalpay_order` (
+ `globalpay_order_id` INT(11) NOT NULL AUTO_INCREMENT,
+ `order_id` INT(11) NOT NULL,
+ `order_ref` CHAR(50) NOT NULL,
+ `order_ref_previous` CHAR(50) NOT NULL,
+ `pasref` VARCHAR(50) NOT NULL,
+ `pasref_previous` VARCHAR(50) NOT NULL,
+ `date_added` DATETIME NOT NULL,
+ `date_modified` DATETIME NOT NULL,
+ `capture_status` INT(1) DEFAULT NULL,
+ `void_status` INT(1) DEFAULT NULL,
+ `settle_type` INT(1) DEFAULT NULL,
+ `rebate_status` INT(1) DEFAULT NULL,
+ `currency_code` CHAR(3) NOT NULL,
+ `authcode` VARCHAR(30) NOT NULL,
+ `account` VARCHAR(30) NOT NULL,
+ `total` DECIMAL( 10, 2 ) NOT NULL,
+ PRIMARY KEY (`globalpay_order_id`)
+ ) ENGINE=MyISAM DEFAULT COLLATE=utf8_general_ci;");
+
+ $this->db->query("
+ CREATE TABLE IF NOT EXISTS `" . DB_PREFIX . "globalpay_order_transaction` (
+ `globalpay_order_transaction_id` INT(11) NOT NULL AUTO_INCREMENT,
+ `globalpay_order_id` INT(11) NOT NULL,
+ `date_added` DATETIME NOT NULL,
+ `type` ENUM('auth', 'payment', 'rebate', 'void') DEFAULT NULL,
+ `amount` DECIMAL( 10, 2 ) NOT NULL,
+ PRIMARY KEY (`globalpay_order_transaction_id`)
+ ) ENGINE=MyISAM DEFAULT COLLATE=utf8_general_ci;");
+ }
+
+ public function void($order_id) {
+ $globalpay_order = $this->getOrder($order_id);
+
+ if (!empty($globalpay_order)) {
+ $timestamp = strftime("%Y%m%d%H%M%S");
+ $merchant_id = $this->config->get('payment_globalpay_merchant_id');
+ $secret = $this->config->get('payment_globalpay_secret');
+
+ $this->logger('Void hash construct: ' . $timestamp . '.' . $merchant_id . '.' . $globalpay_order['order_ref'] . '...');
+
+ $tmp = $timestamp . '.' . $merchant_id . '.' . $globalpay_order['order_ref'] . '...';
+ $hash = sha1($tmp);
+ $tmp = $hash . '.' . $secret;
+ $hash = sha1($tmp);
+
+ $xml = '';
+ $xml .= '<request type="void" timestamp="' . $timestamp . '">';
+ $xml .= '<merchantid>' . $merchant_id . '</merchantid>';
+ $xml .= '<account>' . $globalpay_order['account'] . '</account>';
+ $xml .= '<orderid>' . $globalpay_order['order_ref'] . '</orderid>';
+ $xml .= '<pasref>' . $globalpay_order['pasref'] . '</pasref>';
+ $xml .= '<authcode>' . $globalpay_order['authcode'] . '</authcode>';
+ $xml .= '<sha1hash>' . $hash . '</sha1hash>';
+ $xml .= '</request>';
+
+ $this->logger('Void XML request:\r\n' . print_r(simplexml_load_string($xml), 1));
+
+ $ch = curl_init();
+ curl_setopt($ch, CURLOPT_URL, "https://epage.payandshop.com/epage-remote.cgi");
+ curl_setopt($ch, CURLOPT_POST, 1);
+ curl_setopt($ch, CURLOPT_USERAGENT, "OpenCart " . VERSION);
+ curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
+ curl_setopt($ch, CURLOPT_POSTFIELDS, $xml);
+ curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
+ $response = curl_exec ($ch);
+ curl_close ($ch);
+
+ return simplexml_load_string($response);
+ } else {
+ return false;
+ }
+ }
+
+ public function updateVoidStatus($globalpay_order_id, $status) {
+ $this->db->query("UPDATE `" . DB_PREFIX . "globalpay_order` SET `void_status` = '" . (int)$status . "' WHERE `globalpay_order_id` = '" . (int)$globalpay_order_id . "'");
+ }
+
+ public function capture($order_id, $amount) {
+ $globalpay_order = $this->getOrder($order_id);
+
+ if (!empty($globalpay_order) && $globalpay_order['capture_status'] == 0) {
+ $timestamp = strftime("%Y%m%d%H%M%S");
+ $merchant_id = $this->config->get('payment_globalpay_merchant_id');
+ $secret = $this->config->get('payment_globalpay_secret');
+
+ if ($globalpay_order['settle_type'] == 2) {
+ $this->logger('Capture hash construct: ' . $timestamp . '.' . $merchant_id . '.' . $globalpay_order['order_ref'] . '.' . (int)round($amount*100) . '.' . (string)$globalpay_order['currency_code'] . '.');
+
+ $tmp = $timestamp . '.' . $merchant_id . '.' . $globalpay_order['order_ref'] . '.' . (int)round($amount*100) . '.' . (string)$globalpay_order['currency_code'] . '.';
+ $hash = sha1($tmp);
+ $tmp = $hash . '.' . $secret;
+ $hash = sha1($tmp);
+
+ $settle_type = 'multisettle';
+ $xml_amount = '<amount currency="' . (string)$globalpay_order['currency_code'] . '">' . (int)round($amount*100) . '</amount>';
+ } else {
+ //$this->logger('Capture hash construct: ' . $timestamp . '.' . $merchant_id . '.' . $globalpay_order['order_ref'] . '...');
+ $this->logger('Capture hash construct: ' . $timestamp . '.' . $merchant_id . '.' . $globalpay_order['order_ref'] . '.' . (int)round($amount*100) . '.' . (string)$globalpay_order['currency_code'] . '.');
+
+ $tmp = $timestamp . '.' . $merchant_id . '.' . $globalpay_order['order_ref'] . '.' . (int)round($amount*100) . '.' . (string)$globalpay_order['currency_code'] . '.';
+ $hash = sha1($tmp);
+ $tmp = $hash . '.' . $secret;
+ $hash = sha1($tmp);
+
+ $settle_type = 'settle';
+ $xml_amount = '<amount currency="' . (string)$globalpay_order['currency_code'] . '">' . (int)round($amount*100) . '</amount>';
+ }
+
+ $xml = '';
+ $xml .= '<request type="' . $settle_type . '" timestamp="' . $timestamp . '">';
+ $xml .= '<merchantid>' . $merchant_id . '</merchantid>';
+ $xml .= '<account>' . $globalpay_order['account'] . '</account>';
+ $xml .= '<orderid>' . $globalpay_order['order_ref'] . '</orderid>';
+ $xml .= $xml_amount;
+ $xml .= '<pasref>' . $globalpay_order['pasref'] . '</pasref>';
+ $xml .= '<autosettle flag="1" />';
+ $xml .= '<authcode>' . $globalpay_order['authcode'] . '</authcode>';
+ $xml .= '<sha1hash>' . $hash . '</sha1hash>';
+ $xml .= '</request>';
+
+ $this->logger('Settle XML request:\r\n' . print_r(simplexml_load_string($xml), 1));
+
+ $ch = curl_init();
+ curl_setopt($ch, CURLOPT_URL, "https://epage.payandshop.com/epage-remote.cgi");
+ curl_setopt($ch, CURLOPT_POST, 1);
+ curl_setopt($ch, CURLOPT_USERAGENT, "OpenCart " . VERSION);
+ curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
+ curl_setopt($ch, CURLOPT_POSTFIELDS, $xml);
+ curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
+ $response = curl_exec ($ch);
+ curl_close ($ch);
+
+ return simplexml_load_string($response);
+ } else {
+ return false;
+ }
+ }
+
+ public function updateCaptureStatus($globalpay_order_id, $status) {
+ $this->db->query("UPDATE `" . DB_PREFIX . "globalpay_order` SET `capture_status` = '" . (int)$status . "' WHERE `globalpay_order_id` = '" . (int)$globalpay_order_id . "'");
+ }
+
+ public function updateForRebate($globalpay_order_id, $pas_ref, $order_ref) {
+ $this->db->query("UPDATE `" . DB_PREFIX . "globalpay_order` SET `order_ref_previous` = '_multisettle_" . $this->db->escape($order_ref) . "', `pasref_previous` = '" . $this->db->escape($pas_ref) . "' WHERE `globalpay_order_id` = '" . (int)$globalpay_order_id . "' LIMIT 1");
+ }
+
+ public function rebate($order_id, $amount) {
+ $globalpay_order = $this->getOrder($order_id);
+
+ if (!empty($globalpay_order) && $globalpay_order['rebate_status'] != 1) {
+ $timestamp = strftime("%Y%m%d%H%M%S");
+ $merchant_id = $this->config->get('payment_globalpay_merchant_id');
+ $secret = $this->config->get('payment_globalpay_secret');
+
+ if ($globalpay_order['settle_type'] == 2) {
+ $order_ref = '_multisettle_' . $globalpay_order['order_ref'];
+
+ if (empty($globalpay_order['pasref_previous'])) {
+ $pas_ref = $globalpay_order['pasref'];
+ } else {
+ $pas_ref = $globalpay_order['pasref_previous'];
+ }
+ } else {
+ $order_ref = $globalpay_order['order_ref'];
+ $pas_ref = $globalpay_order['pasref'];
+ }
+
+ $this->logger('Rebate hash construct: ' . $timestamp . '.' . $merchant_id . '.' . $order_ref . '.' . (int)round($amount*100) . '.' . $globalpay_order['currency_code'] . '.');
+
+ $tmp = $timestamp . '.' . $merchant_id . '.' . $order_ref . '.' . (int)round($amount*100) . '.' . $globalpay_order['currency_code'] . '.';
+ $hash = sha1($tmp);
+ $tmp = $hash . '.' . $secret;
+ $hash = sha1($tmp);
+
+ $rebate_hash = sha1($this->config->get('payment_globalpay_rebate_password'));
+
+ $xml = '';
+ $xml .= '<request type="rebate" timestamp="' . $timestamp . '">';
+ $xml .= '<merchantid>' . $merchant_id . '</merchantid>';
+ $xml .= '<account>' . $globalpay_order['account'] . '</account>';
+ $xml .= '<orderid>' . $order_ref . '</orderid>';
+ $xml .= '<pasref>' . $pas_ref . '</pasref>';
+ $xml .= '<authcode>' . $globalpay_order['authcode'] . '</authcode>';
+ $xml .= '<amount currency="' . (string)$globalpay_order['currency_code'] . '">' . (int)round($amount*100) . '</amount>';
+ $xml .= '<refundhash>' . $rebate_hash . '</refundhash>';
+ $xml .= '<sha1hash>' . $hash . '</sha1hash>';
+ $xml .= '</request>';
+
+ $this->logger('Rebate XML request:\r\n' . print_r(simplexml_load_string($xml), 1));
+
+ $ch = curl_init();
+ curl_setopt($ch, CURLOPT_URL, "https://epage.payandshop.com/epage-remote.cgi");
+ curl_setopt($ch, CURLOPT_POST, 1);
+ curl_setopt($ch, CURLOPT_USERAGENT, "OpenCart " . VERSION);
+ curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
+ curl_setopt($ch, CURLOPT_POSTFIELDS, $xml);
+ curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
+ $response = curl_exec ($ch);
+ curl_close ($ch);
+
+ return simplexml_load_string($response);
+ } else {
+ return false;
+ }
+ }
+
+ public function updateRebateStatus($globalpay_order_id, $status) {
+ $this->db->query("UPDATE `" . DB_PREFIX . "globalpay_order` SET `rebate_status` = '" . (int)$status . "' WHERE `globalpay_order_id` = '" . (int)$globalpay_order_id . "'");
+ }
+
+ public function getOrder($order_id) {
+ $this->logger('getOrder - ' . $order_id);
+
+ $qry = $this->db->query("SELECT * FROM `" . DB_PREFIX . "globalpay_order` WHERE `order_id` = '" . (int)$order_id . "' LIMIT 1");
+
+ if ($qry->num_rows) {
+ $order = $qry->row;
+ $order['transactions'] = $this->getTransactions($order['globalpay_order_id']);
+
+ $this->logger(print_r($order, 1));
+
+ return $order;
+ } else {
+ return false;
+ }
+ }
+
+ private function getTransactions($globalpay_order_id) {
+ $qry = $this->db->query("SELECT * FROM `" . DB_PREFIX . "globalpay_order_transaction` WHERE `globalpay_order_id` = '" . (int)$globalpay_order_id . "'");
+
+ if ($qry->num_rows) {
+ return $qry->rows;
+ } else {
+ return false;
+ }
+ }
+
+ public function addTransaction($globalpay_order_id, $type, $total) {
+ $this->db->query("INSERT INTO `" . DB_PREFIX . "globalpay_order_transaction` SET `globalpay_order_id` = '" . (int)$globalpay_order_id . "', `date_added` = now(), `type` = '" . $this->db->escape($type) . "', `amount` = '" . (float)$total . "'");
+ }
+
+ public function logger($message) {
+ if ($this->config->get('payment_globalpay_debug') == 1) {
+ $log = new Log('globalpay.log');
+ $log->write($message);
+ }
+ }
+
+ public function getTotalCaptured($globalpay_order_id) {
+ $query = $this->db->query("SELECT SUM(`amount`) AS `total` FROM `" . DB_PREFIX . "globalpay_order_transaction` WHERE `globalpay_order_id` = '" . (int)$globalpay_order_id . "' AND (`type` = 'payment' OR `type` = 'rebate')");
+
+ return (float)$query->row['total'];
+ }
+
+ public function getTotalRebated($globalpay_order_id) {
+ $query = $this->db->query("SELECT SUM(`amount`) AS `total` FROM `" . DB_PREFIX . "globalpay_order_transaction` WHERE `globalpay_order_id` = '" . (int)$globalpay_order_id . "' AND 'rebate'");
+
+ return (float)$query->row['total'];
+ }
+} \ No newline at end of file
diff --git a/public/admin/model/extension/payment/globalpay_remote.php b/public/admin/model/extension/payment/globalpay_remote.php
new file mode 100644
index 0000000..788e70b
--- /dev/null
+++ b/public/admin/model/extension/payment/globalpay_remote.php
@@ -0,0 +1,260 @@
+<?php
+class ModelExtensionPaymentGlobalpayRemote extends Model {
+ public function install() {
+ $this->db->query("
+ CREATE TABLE IF NOT EXISTS `" . DB_PREFIX . "globalpay_remote_order` (
+ `globalpay_remote_order_id` INT(11) NOT NULL AUTO_INCREMENT,
+ `order_id` INT(11) NOT NULL,
+ `order_ref` CHAR(50) NOT NULL,
+ `order_ref_previous` CHAR(50) NOT NULL,
+ `pasref` VARCHAR(50) NOT NULL,
+ `pasref_previous` VARCHAR(50) NOT NULL,
+ `date_added` DATETIME NOT NULL,
+ `date_modified` DATETIME NOT NULL,
+ `capture_status` INT(1) DEFAULT NULL,
+ `void_status` INT(1) DEFAULT NULL,
+ `settle_type` INT(1) DEFAULT NULL,
+ `rebate_status` INT(1) DEFAULT NULL,
+ `currency_code` CHAR(3) NOT NULL,
+ `authcode` VARCHAR(30) NOT NULL,
+ `account` VARCHAR(30) NOT NULL,
+ `total` DECIMAL( 10, 2 ) NOT NULL,
+ PRIMARY KEY (`globalpay_remote_order_id`)
+ ) ENGINE=MyISAM DEFAULT COLLATE=utf8_general_ci;");
+
+ $this->db->query("
+ CREATE TABLE IF NOT EXISTS `" . DB_PREFIX . "globalpay_remote_order_transaction` (
+ `globalpay_remote_order_transaction_id` INT(11) NOT NULL AUTO_INCREMENT,
+ `globalpay_remote_order_id` INT(11) NOT NULL,
+ `date_added` DATETIME NOT NULL,
+ `type` ENUM('auth', 'payment', 'rebate', 'void') DEFAULT NULL,
+ `amount` DECIMAL( 10, 2 ) NOT NULL,
+ PRIMARY KEY (`globalpay_remote_order_transaction_id`)
+ ) ENGINE=MyISAM DEFAULT COLLATE=utf8_general_ci;");
+ }
+
+ public function void($order_id) {
+ $globalpay_order = $this->getOrder($order_id);
+
+ if (!empty($globalpay_order)) {
+ $timestamp = strftime("%Y%m%d%H%M%S");
+ $merchant_id = $this->config->get('payment_globalpay_remote_merchant_id');
+ $secret = $this->config->get('payment_globalpay_remote_secret');
+
+ $this->logger('Void hash construct: ' . $timestamp . '.' . $merchant_id . '.' . $globalpay_order['order_ref'] . '...');
+
+ $tmp = $timestamp . '.' . $merchant_id . '.' . $globalpay_order['order_ref'] . '...';
+ $hash = sha1($tmp);
+ $tmp = $hash . '.' . $secret;
+ $hash = sha1($tmp);
+
+ $xml = '';
+ $xml .= '<request type="void" timestamp="' . $timestamp . '">';
+ $xml .= '<merchantid>' . $merchant_id . '</merchantid>';
+ $xml .= '<account>' . $globalpay_order['account'] . '</account>';
+ $xml .= '<orderid>' . $globalpay_order['order_ref'] . '</orderid>';
+ $xml .= '<pasref>' . $globalpay_order['pasref'] . '</pasref>';
+ $xml .= '<authcode>' . $globalpay_order['authcode'] . '</authcode>';
+ $xml .= '<sha1hash>' . $hash . '</sha1hash>';
+ $xml .= '</request>';
+
+ $this->logger('Void XML request:\r\n' . print_r(simplexml_load_string($xml), 1));
+
+ $ch = curl_init();
+ curl_setopt($ch, CURLOPT_URL, "https://epage.payandshop.com/epage-remote.cgi");
+ curl_setopt($ch, CURLOPT_POST, 1);
+ curl_setopt($ch, CURLOPT_USERAGENT, "OpenCart " . VERSION);
+ curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
+ curl_setopt($ch, CURLOPT_POSTFIELDS, $xml);
+ curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
+ $response = curl_exec ($ch);
+ curl_close ($ch);
+
+ return simplexml_load_string($response);
+ } else {
+ return false;
+ }
+ }
+
+ public function updateVoidStatus($globalpay_remote_order_id, $status) {
+ $this->db->query("UPDATE `" . DB_PREFIX . "globalpay_remote_order` SET `void_status` = '" . (int)$status . "' WHERE `globalpay_remote_order_id` = '" . (int)$globalpay_remote_order_id . "'");
+ }
+
+ public function capture($order_id, $amount) {
+ $globalpay_order = $this->getOrder($order_id);
+
+ if (!empty($globalpay_order) && $globalpay_order['capture_status'] == 0) {
+ $timestamp = strftime("%Y%m%d%H%M%S");
+ $merchant_id = $this->config->get('payment_globalpay_remote_merchant_id');
+ $secret = $this->config->get('payment_globalpay_remote_secret');
+
+ if ($globalpay_order['settle_type'] == 2) {
+ $this->logger('Capture hash construct: ' . $timestamp . '.' . $merchant_id . '.' . $globalpay_order['order_ref'] . '.' . (int)round($amount*100) . '.' . (string)$globalpay_order['currency_code'] . '.');
+
+ $tmp = $timestamp . '.' . $merchant_id . '.' . $globalpay_order['order_ref'] . '.' . (int)round($amount*100) . '.' . (string)$globalpay_order['currency_code'] . '.';
+ $hash = sha1($tmp);
+ $tmp = $hash . '.' . $secret;
+ $hash = sha1($tmp);
+
+ $settle_type = 'multisettle';
+ $xml_amount = '<amount currency="' . (string)$globalpay_order['currency_code'] . '">' . (int)round($amount*100) . '</amount>';
+ } else {
+ //$this->logger('Capture hash construct: ' . $timestamp . '.' . $merchant_id . '.' . $globalpay_order['order_ref'] . '...');
+ $this->logger('Capture hash construct: ' . $timestamp . '.' . $merchant_id . '.' . $globalpay_order['order_ref'] . '.' . (int)round($amount*100) . '.' . (string)$globalpay_order['currency_code'] . '.');
+
+ $tmp = $timestamp . '.' . $merchant_id . '.' . $globalpay_order['order_ref'] . '.' . (int)round($amount*100) . '.' . (string)$globalpay_order['currency_code'] . '.';
+ $hash = sha1($tmp);
+ $tmp = $hash . '.' . $secret;
+ $hash = sha1($tmp);
+
+ $settle_type = 'settle';
+ $xml_amount = '<amount currency="' . (string)$globalpay_order['currency_code'] . '">' . (int)round($amount*100) . '</amount>';
+ }
+
+ $xml = '';
+ $xml .= '<request type="' . $settle_type . '" timestamp="' . $timestamp . '">';
+ $xml .= '<merchantid>' . $merchant_id . '</merchantid>';
+ $xml .= '<account>' . $globalpay_order['account'] . '</account>';
+ $xml .= '<orderid>' . $globalpay_order['order_ref'] . '</orderid>';
+ $xml .= $xml_amount;
+ $xml .= '<pasref>' . $globalpay_order['pasref'] . '</pasref>';
+ $xml .= '<authcode>' . $globalpay_order['authcode'] . '</authcode>';
+ $xml .= '<sha1hash>' . $hash . '</sha1hash>';
+ $xml .= '</request>';
+
+ $this->logger('Settle XML request:\r\n' . print_r(simplexml_load_string($xml), 1));
+
+ $ch = curl_init();
+ curl_setopt($ch, CURLOPT_URL, "https://epage.payandshop.com/epage-remote.cgi");
+ curl_setopt($ch, CURLOPT_POST, 1);
+ curl_setopt($ch, CURLOPT_USERAGENT, "OpenCart " . VERSION);
+ curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
+ curl_setopt($ch, CURLOPT_POSTFIELDS, $xml);
+ curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
+ $response = curl_exec ($ch);
+ curl_close ($ch);
+
+ return simplexml_load_string($response);
+ } else {
+ return false;
+ }
+ }
+
+ public function updateCaptureStatus($globalpay_remote_order_id, $status) {
+ $this->db->query("UPDATE `" . DB_PREFIX . "globalpay_remote_order` SET `capture_status` = '" . (int)$status . "' WHERE `globalpay_remote_order_id` = '" . (int)$globalpay_remote_order_id . "'");
+ }
+
+ public function updateForRebate($globalpay_remote_order_id, $pas_ref, $order_ref) {
+ $this->db->query("UPDATE `" . DB_PREFIX . "globalpay_remote_order` SET `order_ref_previous` = '_multisettle_" . $this->db->escape($order_ref) . "', `pasref_previous` = '" . $this->db->escape($pas_ref) . "' WHERE `globalpay_remote_order_id` = '" . (int)$globalpay_remote_order_id . "' LIMIT 1");
+ }
+
+ public function rebate($order_id, $amount) {
+ $globalpay_order = $this->getOrder($order_id);
+
+ if (!empty($globalpay_order) && $globalpay_order['rebate_status'] != 1) {
+ $timestamp = strftime("%Y%m%d%H%M%S");
+ $merchant_id = $this->config->get('payment_globalpay_remote_merchant_id');
+ $secret = $this->config->get('payment_globalpay_remote_secret');
+
+ if ($globalpay_order['settle_type'] == 2) {
+ $order_ref = '_multisettle_' . $globalpay_order['order_ref'];
+
+ if (empty($globalpay_order['pasref_previous'])) {
+ $pas_ref = $globalpay_order['pasref'];
+ } else {
+ $pas_ref = $globalpay_order['pasref_previous'];
+ }
+ } else {
+ $order_ref = $globalpay_order['order_ref'];
+ $pas_ref = $globalpay_order['pasref'];
+ }
+
+ $this->logger('Rebate hash construct: ' . $timestamp . '.' . $merchant_id . '.' . $order_ref . '.' . (int)round($amount*100) . '.' . $globalpay_order['currency_code'] . '.');
+
+ $tmp = $timestamp . '.' . $merchant_id . '.' . $order_ref . '.' . (int)round($amount*100) . '.' . $globalpay_order['currency_code'] . '.';
+ $hash = sha1($tmp);
+ $tmp = $hash . '.' . $secret;
+ $hash = sha1($tmp);
+
+ $rebatehash = sha1($this->config->get('payment_globalpay_remote_rebate_password'));
+
+ $xml = '';
+ $xml .= '<request type="rebate" timestamp="' . $timestamp . '">';
+ $xml .= '<merchantid>' . $merchant_id . '</merchantid>';
+ $xml .= '<account>' . $globalpay_order['account'] . '</account>';
+ $xml .= '<orderid>' . $order_ref . '</orderid>';
+ $xml .= '<pasref>' . $pas_ref . '</pasref>';
+ $xml .= '<authcode>' . $globalpay_order['authcode'] . '</authcode>';
+ $xml .= '<amount currency="' . (string)$globalpay_order['currency_code'] . '">' . (int)round($amount*100) . '</amount>';
+ $xml .= '<refundhash>' . $rebatehash . '</refundhash>';
+ $xml .= '<sha1hash>' . $hash . '</sha1hash>';
+ $xml .= '</request>';
+
+ $this->logger('Rebate XML request:\r\n' . print_r(simplexml_load_string($xml), 1));
+
+ $ch = curl_init();
+ curl_setopt($ch, CURLOPT_URL, "https://epage.payandshop.com/epage-remote.cgi");
+ curl_setopt($ch, CURLOPT_POST, 1);
+ curl_setopt($ch, CURLOPT_USERAGENT, "OpenCart " . VERSION);
+ curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
+ curl_setopt($ch, CURLOPT_POSTFIELDS, $xml);
+ curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
+ $response = curl_exec ($ch);
+ curl_close ($ch);
+
+ return simplexml_load_string($response);
+ } else {
+ return false;
+ }
+ }
+
+ public function updateRebateStatus($globalpay_remote_order_id, $status) {
+ $this->db->query("UPDATE `" . DB_PREFIX . "globalpay_remote_order` SET `rebate_status` = '" . (int)$status . "' WHERE `globalpay_remote_order_id` = '" . (int)$globalpay_remote_order_id . "'");
+ }
+
+ public function getOrder($order_id) {
+ $qry = $this->db->query("SELECT * FROM `" . DB_PREFIX . "globalpay_remote_order` WHERE `order_id` = '" . (int)$order_id . "' LIMIT 1");
+
+ if ($qry->num_rows) {
+ $order = $qry->row;
+ $order['transactions'] = $this->getTransactions($order['globalpay_remote_order_id']);
+
+ return $order;
+ } else {
+ return false;
+ }
+ }
+
+ private function getTransactions($globalpay_remote_order_id) {
+ $qry = $this->db->query("SELECT * FROM `" . DB_PREFIX . "globalpay_remote_order_transaction` WHERE `globalpay_remote_order_id` = '" . (int)$globalpay_remote_order_id . "'");
+
+ if ($qry->num_rows) {
+ return $qry->rows;
+ } else {
+ return false;
+ }
+ }
+
+ public function addTransaction($globalpay_remote_order_id, $type, $total) {
+ $this->db->query("INSERT INTO `" . DB_PREFIX . "globalpay_remote_order_transaction` SET `globalpay_remote_order_id` = '" . (int)$globalpay_remote_order_id . "', `date_added` = now(), `type` = '" . $this->db->escape($type) . "', `amount` = '" . (float)$total . "'");
+ }
+
+ public function logger($message) {
+ if ($this->config->get('payment_globalpay_remote_debug') == 1) {
+ $log = new Log('globalpay_remote.log');
+ $log->write($message);
+ }
+ }
+
+ public function getTotalCaptured($globalpay_order_id) {
+ $query = $this->db->query("SELECT SUM(`amount`) AS `total` FROM `" . DB_PREFIX . "globalpay_remote_order_transaction` WHERE `globalpay_remote_order_id` = '" . (int)$globalpay_order_id . "' AND (`type` = 'payment' OR `type` = 'rebate')");
+
+ return (float)$query->row['total'];
+ }
+
+ public function getTotalRebated($globalpay_order_id) {
+ $query = $this->db->query("SELECT SUM(`amount`) AS `total` FROM `" . DB_PREFIX . "globalpay_remote_order_transaction` WHERE `globalpay_remote_order_id` = '" . (int)$globalpay_order_id . "' AND 'rebate'");
+
+ return (double)$query->row['total'];
+ }
+} \ No newline at end of file
diff --git a/public/admin/model/extension/payment/klarna_checkout.php b/public/admin/model/extension/payment/klarna_checkout.php
new file mode 100644
index 0000000..d9e9cbc
--- /dev/null
+++ b/public/admin/model/extension/payment/klarna_checkout.php
@@ -0,0 +1,226 @@
+<?php
+use Klarna\Rest\Transport\Connector as KCConnector;
+use Klarna\Rest\Transport\ConnectorInterface as KCConnectorInterface;
+use Klarna\Rest\OrderManagement\Order as KCOrder;
+
+class ModelExtensionPaymentKlarnaCheckout extends Model {
+ public function connector($merchant_id, $secret, $url) {
+ try {
+ $connector = KCConnector::create(
+ $merchant_id,
+ $secret,
+ $url
+ );
+
+ return $connector;
+ } catch (\Exception $e) {
+ $this->log($e->getMessage());
+
+ return false;
+ }
+ }
+
+ public function omRetrieve(KCConnector $connector, $order_id) {
+ try {
+ $order = new KCOrder($connector, $order_id);
+
+ return $order->fetch();
+ } catch (\Exception $e) {
+ $this->log($e->getMessage());
+
+ return false;
+ }
+ }
+
+ public function omCancel(KCConnector $connector, $order_id) {
+ try {
+ $order = new KCOrder($connector, $order_id);
+
+ return $order->cancel();
+ } catch (\Exception $e) {
+ $this->log($e->getMessage());
+
+ return false;
+ }
+ }
+
+ public function omCapture(KCConnector $connector, $order_id, $data) {
+ try {
+ $order = new KCOrder($connector, $order_id);
+
+ return $order->createCapture($data);
+ } catch (\Exception $e) {
+ $this->log($e->getMessage());
+
+ return false;
+ }
+ }
+
+ public function omRefund(KCConnector $connector, $order_id, $data) {
+ try {
+ $order = new KCOrder($connector, $order_id);
+
+ return $order->refund($data);
+ } catch (\Exception $e) {
+ $this->log($e->getMessage());
+
+ return false;
+ }
+ }
+
+ public function omExtendAuthorizationTime(KCConnector $connector, $order_id) {
+ try {
+ $order = new KCOrder($connector, $order_id);
+
+ return $order->extendAuthorizationTime();
+ } catch (\Exception $e) {
+ $this->log($e->getMessage());
+
+ return false;
+ }
+ }
+
+ public function omUpdateMerchantReference(KCConnector $connector, $order_id, $data) {
+ try {
+ $order = new KCOrder($connector, $order_id);
+
+ return $order->updateMerchantReferences($data);
+ } catch (\Exception $e) {
+ $this->log($e->getMessage());
+
+ return false;
+ }
+ }
+
+ public function omUpdateAddress(KCConnector $connector, $order_id, $data) {
+ try {
+ $order = new KCOrder($connector, $order_id);
+
+ return $order->updateCustomerDetails($data);
+ } catch (\Exception $e) {
+ $this->log($e->getMessage());
+
+ return false;
+ }
+ }
+
+ public function omReleaseAuthorization(KCConnector $connector, $order_id) {
+ try {
+ $order = new KCOrder($connector, $order_id);
+
+ return $order->releaseRemainingAuthorization();
+ } catch (\Exception $e) {
+ $this->log($e->getMessage());
+
+ return false;
+ }
+ }
+
+ public function omShippingInfo(KCConnector $connector, $order_id, $capture_id, $data) {
+ try {
+ $order = new KCOrder($connector, $order_id);
+
+ $capture = $order->fetchCapture($capture_id);
+ return $capture->addShippingInfo($data);
+ } catch (\Exception $e) {
+ $this->log($e->getMessage());
+
+ return false;
+ }
+ }
+
+ public function omCustomerDetails(KCConnector $connector, $order_id, $capture_id, $data) {
+ try {
+ $order = new KCOrder($connector, $order_id);
+
+ $capture = $order->fetchCapture($capture_id);
+ return $capture->updateCustomerDetails($data);
+ } catch (\Exception $e) {
+ $this->log($e->getMessage());
+
+ return false;
+ }
+ }
+
+ public function omTriggerSendOut(KCConnector $connector, $order_id, $capture_id) {
+ try {
+ $order = new KCOrder($connector, $order_id);
+
+ $capture = $order->fetchCapture($capture_id);
+ return $capture->triggerSendout();
+ } catch (\Exception $e) {
+ $this->log($e->getMessage());
+
+ return false;
+ }
+ }
+
+ public function getConnector($accounts, $currency) {
+ $klarna_account = false;
+ $connector = false;
+
+ if ($accounts && $currency) {
+ foreach ($accounts as $account) {
+ if ($account['currency'] == $currency) {
+ if ($account['environment'] == 'test') {
+ if ($account['api'] == 'NA') {
+ $base_url = KCConnectorInterface::NA_TEST_BASE_URL;
+ } elseif ($account['api'] == 'EU') {
+ $base_url = KCConnectorInterface::EU_TEST_BASE_URL;
+ }
+ } elseif ($account['environment'] == 'live') {
+ if ($account['api'] == 'NA') {
+ $base_url = KCConnectorInterface::NA_BASE_URL;
+ } elseif ($account['api'] == 'EU') {
+ $base_url = KCConnectorInterface::EU_BASE_URL;
+ }
+ }
+
+ $klarna_account = $account;
+ $connector = $this->connector(
+ $account['merchant_id'],
+ $account['secret'],
+ $base_url
+ );
+
+ break;
+ }
+ }
+ }
+
+ return array($klarna_account, $connector);
+ }
+
+ public function getOrder($order_id) {
+ return $this->db->query("SELECT * FROM `" . DB_PREFIX . "klarna_checkout_order` WHERE `order_id` = '" . (int)$order_id . "' LIMIT 1")->row;
+ }
+
+ public function checkForPaymentTaxes() {
+ $query = $this->db->query("SELECT COUNT(*) AS `total` FROM " . DB_PREFIX . "product p LEFT JOIN " . DB_PREFIX . "tax_rule tr ON (`tr`.`tax_class_id` = `p`.`tax_class_id`) WHERE `tr`.`based` = 'payment'");
+
+ return $query->row['total'];
+ }
+
+ public function install() {
+ $this->db->query("
+ CREATE TABLE IF NOT EXISTS `" . DB_PREFIX . "klarna_checkout_order` (
+ `klarna_checkout_order_id` INT(11) NOT NULL AUTO_INCREMENT,
+ `order_id` INT(11) NOT NULL,
+ `order_ref` VARCHAR(255) NOT NULL,
+ `data` text NOT NULL,
+ PRIMARY KEY (`klarna_checkout_order_id`)
+ ) ENGINE=MyISAM DEFAULT COLLATE=utf8_general_ci;");
+ }
+
+ public function uninstall() {
+ $this->db->query("DROP TABLE IF EXISTS `" . DB_PREFIX . "klarna_checkout_order`;");
+ }
+
+ public function log($data) {
+ if ($this->config->get('klarna_checkout_debug')) {
+ $backtrace = debug_backtrace();
+ $log = new Log('klarna_checkout.log');
+ $log->write('(' . $backtrace[1]['class'] . '::' . $backtrace[1]['function'] . ') - ' . print_r($data, true));
+ }
+ }
+} \ No newline at end of file
diff --git a/public/admin/model/extension/payment/laybuy.php b/public/admin/model/extension/payment/laybuy.php
new file mode 100644
index 0000000..f9689fd
--- /dev/null
+++ b/public/admin/model/extension/payment/laybuy.php
@@ -0,0 +1,362 @@
+<?php
+class ModelExtensionPaymentLaybuy extends Model {
+ public function addRevisedTransaction($data = array()) {
+ $query = $this->db->query("INSERT INTO `" . DB_PREFIX . "laybuy_revise_request` SET `laybuy_transaction_id` = '" . (int)$data['transaction_id'] . "', `type` = '" . $this->db->escape($data['type']) . "', `order_id` = '" . (int)$data['order_id'] . "', `firstname` = '" . $this->db->escape($data['firstname']) . "', `lastname` = '" . $this->db->escape($data['lastname']) . "', `address` = '" . $this->db->escape($data['address']) . "', `suburb` = '" . $this->db->escape($data['suburb']) . "', `state` = '" . $this->db->escape($data['state']) . "', `country` = '" . $this->db->escape($data['country']) . "', `postcode` = '" . $this->db->escape($data['postcode']) . "', `email` = '" . $this->db->escape($data['email']) . "', `amount` = '" . (float)$data['amount'] . "', `currency` = '" . $this->db->escape($data['currency']) . "', `downpayment` = '" . $this->db->escape($data['downpayment']) . "', `months` = '" . (int)$data['months'] . "', `downpayment_amount` = '" . (float)$data['downpayment_amount'] . "', `payment_amounts` = '" . (float)$data['payment_amounts'] . "', `first_payment_due` = '" . $this->db->escape($data['first_payment_due']) . "', `last_payment_due` = '" . $this->db->escape($data['last_payment_due']) . "', `store_id` = '" . (int)$data['store_id'] . "', `status` = '" . (int)$data['status'] . "', `report` = '" . $this->db->escape($data['report']) . "', `transaction` = '" . (int)$data['transaction'] . "', `paypal_profile_id` = '" . $this->db->escape($data['paypal_profile_id']) . "', `laybuy_ref_no` = '" . (int)$data['laybuy_ref_no'] . "', `payment_type` = '" . (int)$data['payment_type'] . "', `date_added` = NOW()");
+
+ return $this->db->getLastId();
+ }
+
+ public function getCustomerIdByOrderId($order_id) {
+ $query = $this->db->query("SELECT `customer_id` FROM `" . DB_PREFIX . "order` WHERE `order_id` = '" . (int)$order_id . "'");
+
+ if ($query->num_rows) {
+ return $query->row['customer_id'];
+ } else {
+ return 0;
+ }
+ }
+
+ public function getInitialPayments() {
+ $minimum = $this->config->get('payment_laybuy_min_deposit') ? $this->config->get('payment_laybuy_min_deposit') : 20;
+
+ $maximum = $this->config->get('payment_laybuy_max_deposit') ? $this->config->get('payment_laybuy_max_deposit') : 50;
+
+ $initial_payments = array();
+
+ for ($i = $minimum; $i <= $maximum; $i += 10) {
+ $initial_payments[] = $i;
+ }
+
+ return $initial_payments;
+ }
+
+ public function getMonths() {
+ $this->load->language('extension/payment/laybuy');
+
+ $max_months = $this->config->get('payment_laybuy_max_months');
+
+ if (!$max_months) {
+ $max_months = 3;
+ }
+
+ if ($max_months < 1) {
+ $max_months = 1;
+ }
+
+ $months = array();
+
+ for ($i = 1; $i <= $max_months; $i++) {
+ $months[] = array(
+ 'value' => $i,
+ 'label' => $i . ' ' . (($i > 1) ? $this->language->get('text_months') : $this->language->get('text_month'))
+ );
+ }
+
+ return $months;
+ }
+
+ public function getPayPalProfileIds() {
+ $query = $this->db->query("SELECT `paypal_profile_id` FROM `" . DB_PREFIX . "laybuy_transaction` WHERE `status` = '1'");
+
+ return $query->rows;
+ }
+
+ public function getRevisedTransaction($id) {
+ $query = $this->db->query("SELECT * FROM `" . DB_PREFIX . "laybuy_revise_request` WHERE `laybuy_revise_request_id` = '" . (int)$id . "'");
+
+ return $query->row;
+ }
+
+ public function getRemainingAmount($amount, $downpayment_amount, $payment_amounts, $transaction = 2) {
+ return $amount - ($downpayment_amount + (((int)$transaction - 2) * $payment_amounts));
+ }
+
+ public function getRevisedTransactions($id) {
+ $query = $this->db->query("SELECT * FROM `" . DB_PREFIX . "laybuy_revise_request` WHERE `laybuy_revise_request_id` = '" . (int)$id . "'");
+
+ return $query->rows;
+ }
+
+ public function getStatusLabel($id) {
+ $statuses = $this->getTransactionStatuses();
+
+ foreach ($statuses as $status) {
+ if ($status['status_id'] == $id && $status['status_name'] != '') {
+ return $status['status_name'];
+
+ break;
+ }
+ }
+
+ return $id;
+ }
+
+ public function getTransaction($id) {
+ $query = $this->db->query("SELECT * FROM `" . DB_PREFIX . "laybuy_transaction` WHERE `laybuy_transaction_id` = '" . (int)$id . "'");
+
+ return $query->row;
+ }
+
+ public function getTransactions($data = array()) {
+ $sql = "SELECT *, CONCAT(firstname, ' ', lastname) AS `customer` FROM `" . DB_PREFIX . "laybuy_transaction` `lt` WHERE 1 = 1";
+
+ $implode = array();
+
+ if (!empty($data['filter_order_id'])) {
+ $implode[] = "`lt`.`order_id` = '" . (int)$data['filter_order_id'] . "'";
+ }
+
+ if (!empty($data['filter_customer'])) {
+ $implode[] = "CONCAT(firstname, ' ', lastname) LIKE '%" . $this->db->escape($data['filter_customer']) . "%'";
+ }
+
+ if (!empty($data['filter_dp_percent'])) {
+ $implode[] = "`lt`.`downpayment` = '" . (int)$data['filter_dp_percent'] . "'";
+ }
+
+ if (!empty($data['filter_months'])) {
+ $implode[] = "`lt`.`months` = '" . (int)$data['filter_months'] . "'";
+ }
+
+ if (!empty($data['filter_status'])) {
+ $implode[] = "`lt`.`status` = '" . (int)$data['filter_status'] . "'";
+ }
+
+ if (!empty($data['filter_date_added'])) {
+ $implode[] = "DATE(`lt`.`date_added`) = DATE('" . $this->db->escape($data['filter_date_added']) . "')";
+ }
+
+ if ($implode) {
+ $sql .= " AND " . implode(" AND ", $implode);
+ }
+
+ $sort_data = array(
+ 'lt.order_id',
+ 'customer',
+ 'lt.amount',
+ 'lt.downpayment',
+ 'lt.months',
+ 'lt.downpayment_amount',
+ 'lt.first_payment_due',
+ 'lt.last_payment_due',
+ 'lt.status',
+ 'lt.date_added'
+ );
+
+ if (isset($data['sort']) && in_array($data['sort'], $sort_data)) {
+ $sql .= " ORDER BY " . $data['sort'];
+ } else {
+ $sql .= " ORDER BY order_id";
+ }
+
+ if (isset($data['order']) && ($data['order'] == 'DESC')) {
+ $sql .= " DESC";
+ } else {
+ $sql .= " ASC";
+ }
+
+ if (isset($data['sort']) && $data['sort'] != 'lt.date_added') {
+ $sql .= ", lt.date_added DESC";
+ }
+
+ if (isset($data['start']) || isset($data['limit'])) {
+ if ($data['start'] < 0) {
+ $data['start'] = 0;
+ }
+
+ if ($data['limit'] < 1) {
+ $data['limit'] = 20;
+ }
+
+ $sql .= " LIMIT " . (int)$data['start'] . "," . (int)$data['limit'];
+ }
+
+ $query = $this->db->query($sql);
+
+ return $query->rows;
+ }
+
+ public function getTotalTransactions($data = array()) {
+ $sql = "SELECT COUNT(*) AS `total` FROM `" . DB_PREFIX . "laybuy_transaction` `lt` WHERE 1 = 1";
+
+ $implode = array();
+
+ if (!empty($data['filter_order_id'])) {
+ $implode[] = "`lt`.`order_id` = '" . (int)$data['filter_order_id'] . "'";
+ }
+
+ if (!empty($data['filter_customer'])) {
+ $implode[] = "CONCAT(firstname, ' ', lastname) LIKE '%" . $this->db->escape($data['filter_customer']) . "%'";
+ }
+
+ if (!empty($data['filter_dp_percent'])) {
+ $implode[] = "`lt`.`downpayment` = '" . (int)$data['filter_dp_percent'] . "'";
+ }
+
+ if (!empty($data['filter_months'])) {
+ $implode[] = "`lt`.`months` = '" . (int)$data['filter_months'] . "'";
+ }
+
+ if (!empty($data['filter_status'])) {
+ $implode[] = "`lt`.`status` = '" . (int)$data['filter_status'] . "'";
+ }
+
+ if (!empty($data['filter_date_added'])) {
+ $implode[] = "DATE(`lt`.`date_added`) = DATE('" . $this->db->escape($data['filter_date_added']) . "')";
+ }
+
+ if ($implode) {
+ $sql .= " AND " . implode(" AND ", $implode);
+ }
+
+ $query = $this->db->query($sql);
+
+ return $query->row['total'];
+ }
+
+ public function getTransactionByLayBuyRefId($laybuy_ref_id) {
+ $query = $this->db->query("SELECT * FROM `" . DB_PREFIX . "laybuy_transaction` WHERE `laybuy_ref_no` = '" . (int)$laybuy_ref_id . "'");
+
+ return $query->row;
+ }
+
+ public function getTransactionByOrderId($order_id) {
+ $query = $this->db->query("SELECT * FROM `" . DB_PREFIX . "laybuy_transaction` WHERE `order_id` = '" . (int)$order_id . "' ORDER BY `laybuy_ref_no` DESC LIMIT 1");
+
+ return $query->row;
+ }
+
+ public function getTransactionStatuses() {
+ $this->load->language('extension/payment/laybuy');
+
+ $transaction_statuses = array(
+ array(
+ 'status_id' => 1,
+ 'status_name' => $this->language->get('text_status_1')
+ ),
+ array(
+ 'status_id' => 5,
+ 'status_name' => $this->language->get('text_status_5')
+ ),
+ array(
+ 'status_id' => 7,
+ 'status_name' => $this->language->get('text_status_7')
+ ),
+ array(
+ 'status_id' => 50,
+ 'status_name' => $this->language->get('text_status_50')
+ ),
+ array(
+ 'status_id' => 51,
+ 'status_name' => $this->language->get('text_status_51')
+ )
+ );
+
+ return $transaction_statuses;
+ }
+
+ public function install() {
+ $this->db->query("CREATE TABLE IF NOT EXISTS `" . DB_PREFIX . "laybuy_transaction` (
+ `laybuy_transaction_id` int(11) NOT NULL AUTO_INCREMENT,
+ `order_id` int(11) NOT NULL DEFAULT '0',
+ `firstname` varchar(32) NOT NULL DEFAULT '',
+ `lastname` varchar(32) NOT NULL DEFAULT '',
+ `address` text,
+ `suburb` varchar(128) NOT NULL DEFAULT '',
+ `state` varchar(128) NOT NULL DEFAULT '',
+ `country` varchar(32) NOT NULL DEFAULT '',
+ `postcode` varchar(10) NOT NULL DEFAULT '',
+ `email` varchar(96) NOT NULL DEFAULT '',
+ `amount` double NOT NULL,
+ `currency` varchar(5) NOT NULL,
+ `downpayment` double NOT NULL,
+ `months` int(11) NOT NULL,
+ `downpayment_amount` double NOT NULL,
+ `payment_amounts` double NOT NULL,
+ `first_payment_due` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
+ `last_payment_due` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
+ `store_id` int(11) NOT NULL DEFAULT '0',
+ `status` int(11) NOT NULL DEFAULT '1',
+ `report` text,
+ `transaction` int(11) NOT NULL DEFAULT '2',
+ `paypal_profile_id` varchar(250) NOT NULL DEFAULT '',
+ `laybuy_ref_no` int(11) NOT NULL DEFAULT '0',
+ `date_added` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
+ PRIMARY KEY (`laybuy_transaction_id`)
+ ) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_general_ci");
+
+ $this->db->query("CREATE TABLE IF NOT EXISTS `" . DB_PREFIX . "laybuy_revise_request` (
+ `laybuy_revise_request_id` int(11) NOT NULL AUTO_INCREMENT,
+ `laybuy_transaction_id` int(11) DEFAULT '0',
+ `type` varchar(250) NOT NULL DEFAULT '',
+ `order_id` int(11) NOT NULL DEFAULT '0',
+ `firstname` varchar(32) NOT NULL DEFAULT '',
+ `lastname` varchar(32) NOT NULL DEFAULT '',
+ `address` text,
+ `suburb` varchar(128) NOT NULL DEFAULT '',
+ `state` varchar(128) NOT NULL DEFAULT '',
+ `country` varchar(32) NOT NULL DEFAULT '',
+ `postcode` varchar(10) NOT NULL DEFAULT '',
+ `email` varchar(96) NOT NULL DEFAULT '',
+ `amount` double NOT NULL,
+ `currency` varchar(5) NOT NULL,
+ `downpayment` double NOT NULL,
+ `months` int(11) NOT NULL,
+ `downpayment_amount` double NOT NULL,
+ `payment_amounts` double NOT NULL,
+ `first_payment_due` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
+ `last_payment_due` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
+ `store_id` int(11) NOT NULL DEFAULT '0',
+ `status` int(11) NOT NULL DEFAULT '1',
+ `report` text,
+ `transaction` int(11) NOT NULL DEFAULT '2',
+ `paypal_profile_id` varchar(250) NOT NULL DEFAULT '',
+ `laybuy_ref_no` int(11) NOT NULL DEFAULT '0',
+ `payment_type` tinyint(1) NOT NULL DEFAULT '1',
+ `date_added` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
+ PRIMARY KEY (`laybuy_revise_request_id`)
+ ) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_general_ci");
+
+ $this->load->model('setting/event');
+
+ $this->model_setting_event->addEvent('laybuy', 'catalog/model/checkout/order/deleteOrder/after', 'extension/payment/laybuy/deleteOrder');
+ }
+
+ public function log($data, $step = 6) {
+ if ($this->config->get('payment_laybuy_logging')) {
+ $backtrace = debug_backtrace();
+
+ $log = new Log('laybuy.log');
+
+ $log->write('(' . $backtrace[$step]['class'] . '::' . $backtrace[$step]['function'] . ') - ' . $data);
+ }
+ }
+
+ public function uninstall() {
+ $this->db->query("DROP TABLE IF EXISTS `" . DB_PREFIX . "laybuy_transaction`");
+
+ $this->db->query("DROP TABLE IF EXISTS `" . DB_PREFIX . "laybuy_revise_request`");
+
+ $this->load->model('setting/event');
+
+ $this->model_setting_event->deleteEventByCode('laybuy');
+ }
+
+ public function updateOrderStatus($order_id, $order_status_id, $comment) {
+ $this->db->query("UPDATE `" . DB_PREFIX . "order` SET `order_status_id` = '" . (int)$order_status_id . "', `date_modified` = NOW() WHERE `order_id` = '" . (int)$order_id . "'");
+
+ $this->db->query("INSERT INTO `" . DB_PREFIX . "order_history` SET `order_id` = '" . (int)$order_id . "', `order_status_id` = '" . (int)$order_status_id . "', `notify` = '0', `comment` = '" . $this->db->escape($comment) . "', `date_added` = NOW()");
+ }
+
+ public function updateRevisedTransaction($id, $data = array()) {
+ $this->db->query("UPDATE `" . DB_PREFIX . "laybuy_revise_request` SET `laybuy_transaction_id` = '" . (int)$data['transaction_id'] . "', `type` = '" . $this->db->escape($data['type']) . "', `order_id` = '" . (int)$data['order_id'] . "', `firstname` = '" . $this->db->escape($data['firstname']) . "', `lastname` = '" . $this->db->escape($data['lastname']) . "', `address` = '" . $this->db->escape($data['address']) . "', `suburb` = '" . $this->db->escape($data['suburb']) . "', `state` = '" . $this->db->escape($data['state']) . "', `country` = '" . $this->db->escape($data['country']) . "', `postcode` = '" . $this->db->escape($data['postcode']) . "', `email` = '" . $this->db->escape($data['email']) . "', `amount` = '" . (float)$data['amount'] . "', `currency` = '" . $this->db->escape($data['currency']) . "', `downpayment` = '" . $this->db->escape($data['downpayment']) . "', `months` = '" . (int)$data['months'] . "', `downpayment_amount` = '" . (float)$data['downpayment_amount'] . "', `payment_amounts` = '" . (float)$data['payment_amounts'] . "', `first_payment_due` = '" . $this->db->escape($data['first_payment_due']) . "', `last_payment_due` = '" . $this->db->escape($data['last_payment_due']) . "', `store_id` = '" . (int)$data['store_id'] . "', `status` = '" . (int)$data['status'] . "', `report` = '" . $this->db->escape($data['report']) . "', `transaction` = '" . (int)$data['transaction'] . "', `paypal_profile_id` = '" . $this->db->escape($data['paypal_profile_id']) . "', `laybuy_ref_no` = '" . (int)$data['laybuy_ref_no'] . "', `payment_type` = '" . (int)$data['payment_type'] . "', `date_added` = NOW() WHERE `laybuy_revise_request_id` = '" . (int)$id . "'");
+ }
+
+ public function updateTransaction($id, $status, $report, $transaction) {
+ $this->db->query("UPDATE `" . DB_PREFIX . "laybuy_transaction` SET `status` = '" . (int)$status . "', `report` = '" . $this->db->escape($report) . "', `transaction` = '" . (int)$transaction . "' WHERE `laybuy_transaction_id` = '" . (int)$id . "'");
+ }
+
+ public function updateTransactionStatus($id, $status) {
+ $this->db->query("UPDATE `" . DB_PREFIX . "laybuy_transaction` SET `status` = '" . (int)$status . "' WHERE `laybuy_transaction_id` = '" . (int)$id . "'");
+ }
+} \ No newline at end of file
diff --git a/public/admin/model/extension/payment/pilibaba.php b/public/admin/model/extension/payment/pilibaba.php
new file mode 100644
index 0000000..718680d
--- /dev/null
+++ b/public/admin/model/extension/payment/pilibaba.php
@@ -0,0 +1,165 @@
+<?php
+class ModelExtensionPaymentPilibaba extends Model {
+ public function install() {
+ $this->db->query("CREATE TABLE IF NOT EXISTS `" . DB_PREFIX . "pilibaba_order` (
+ `pilibaba_order_id` int(11) NOT NULL AUTO_INCREMENT,
+ `order_id` int(11) NOT NULL DEFAULT '0',
+ `amount` double NOT NULL,
+ `fee` double NOT NULL,
+ `tracking` VARCHAR(50) NOT NULL DEFAULT '',
+ `date_added` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
+ PRIMARY KEY (`pilibaba_order_id`)
+ ) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_general_ci");
+ }
+
+ public function uninstall() {
+ $this->db->query("DROP TABLE IF EXISTS `" . DB_PREFIX . "pilibaba_order`");
+
+ $this->disablePiliExpress();
+
+ $this->log('Module uninstalled');
+ }
+
+ public function getCurrencies() {
+ $ch = curl_init();
+ curl_setopt($ch, CURLOPT_URL, 'http://www.pilibaba.com/pilipay/getCurrency');
+ curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'GET');
+ curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
+ curl_setopt($ch, CURLOPT_HEADER, false);
+ curl_setopt($ch, CURLOPT_TIMEOUT, 30);
+ curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
+ $response = curl_exec($ch);
+ curl_close($ch);
+
+ return json_decode($response, true);
+ }
+
+ public function getWarehouses() {
+ $ch = curl_init();
+ curl_setopt($ch, CURLOPT_URL, 'http://www.pilibaba.com/pilipay/getAddressList');
+ curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'GET');
+ curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
+ curl_setopt($ch, CURLOPT_HEADER, false);
+ curl_setopt($ch, CURLOPT_TIMEOUT, 30);
+ curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
+ $response = curl_exec($ch);
+ curl_close($ch);
+
+ return json_decode($response, true);
+ }
+
+ public function getOrder($order_id) {
+ $query = $this->db->query("SELECT * FROM `" . DB_PREFIX . "pilibaba_order` WHERE `order_id` = '" . (int)$order_id . "' LIMIT 1");
+
+ if ($query->num_rows) {
+ return $query->row;
+ } else {
+ return false;
+ }
+ }
+
+ public function register($email, $password, $currency, $warehouse, $country, $environment) {
+ $this->log('Posting register');
+
+ if ($warehouse == 'other') {
+ $warehouse = '';
+ }
+
+ if ($warehouse) {
+ $country = '';
+ }
+
+ if ($environment == 'live') {
+ $url = 'http://en.pilibaba.com/autoRegist';
+ } else {
+ $url = 'http://preen.pilibaba.com/autoRegist';
+ }
+
+ $this->log('URL: ' . $url);
+
+ $app_secret = strtoupper(md5((($warehouse) ? $warehouse : $country) . '0210000574' . '0b8l3ww5' . $currency . $email . md5($password)));
+
+ $data = array(
+ 'platformNo' => '0210000574',
+ 'appSecret' => $app_secret,
+ 'email' => $email,
+ 'password' => md5($password),
+ 'currency' => $currency,
+ 'logistics' => $warehouse,
+ 'countryCode' => $country
+ );
+
+ $this->log('Data: ' . print_r($data, true));
+
+ $headers = array('Accept: application/json','Content-Type: application/json');
+
+ $ch = curl_init();
+ curl_setopt($ch, CURLOPT_URL, $url);
+ curl_setopt($ch, CURLOPT_POST, true);
+ curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($data));
+ curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
+ curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
+ curl_setopt($ch, CURLOPT_TIMEOUT, 30);
+ curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
+ $response = curl_exec($ch);
+ if (curl_errno($ch)) {
+ $this->log('cURL error: ' . curl_errno($ch));
+ }
+ curl_close($ch);
+
+ $this->log('Response: ' . print_r($response, true));
+
+ return json_decode($response, true);
+ }
+
+ public function updateTrackingNumber($order_id, $tracking_number, $merchant_number) {
+ $this->log('Posting tracking');
+
+ $sign_msg = strtoupper(md5($order_id . $tracking_number . $merchant_number . $this->config->get('payment_pilibaba_secret_key')));
+
+ if ($this->config->get('payment_pilibaba_environment') == 'live') {
+ $url = 'https://www.pilibaba.com/pilipay/updateTrackNo';
+ } else {
+ $url = 'http://pre.pilibaba.com/pilipay/updateTrackNo';
+ }
+
+ $url .= '?orderNo=' . $order_id . '&logisticsNo=' . $tracking_number . '&merchantNo=' . $merchant_number . '&signMsg=' . $sign_msg;
+
+ $this->log('URL: ' . $url);
+
+ $ch = curl_init();
+ curl_setopt($ch, CURLOPT_URL, $url);
+ curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'GET');
+ curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
+ curl_setopt($ch, CURLOPT_HEADER, false);
+ curl_setopt($ch, CURLOPT_TIMEOUT, 30);
+ curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
+ $response = curl_exec($ch);
+ if (curl_errno($ch)) {
+ $this->log('cURL error: ' . curl_errno($ch));
+ }
+ curl_close($ch);
+
+ $this->db->query("UPDATE `" . DB_PREFIX . "pilibaba_order` SET `tracking` = '" . $this->db->escape($tracking_number) . "' WHERE `order_id` = '" . (int)$order_id . "'");
+ }
+
+ public function enablePiliExpress() {
+ $query = $this->db->query("SELECT * FROM `" . DB_PREFIX . "extension` WHERE `type` = 'shipping' AND `code` = 'pilibaba'");
+
+ if (!$query->num_rows) {
+ $this->db->query("INSERT INTO `" . DB_PREFIX . "extension` SET `type` = 'shipping', `code` = 'pilibaba'");
+ }
+ }
+
+ public function disablePiliExpress() {
+ $this->db->query("DELETE FROM `" . DB_PREFIX . "extension` WHERE `type` = 'shipping' AND `code` = 'pilibaba'");
+ }
+
+ public function log($data) {
+ if ($this->config->has('payment_pilibaba_logging') && $this->config->get('payment_pilibaba_logging')) {
+ $log = new Log('pilibaba.log');
+
+ $log->write($data);
+ }
+ }
+} \ No newline at end of file
diff --git a/public/admin/model/extension/payment/pp_braintree.php b/public/admin/model/extension/payment/pp_braintree.php
new file mode 100644
index 0000000..af0e604
--- /dev/null
+++ b/public/admin/model/extension/payment/pp_braintree.php
@@ -0,0 +1,168 @@
+<?php
+class ModelExtensionPaymentPPBraintree extends Model {
+ public function generateToken($gateway, $data = array()) {
+ try {
+ if ($gateway != null) {
+ $client_token = $gateway->clientToken()->generate($data);
+ } else {
+ $client_token = Braintree_ClientToken::generate($data);
+ }
+
+ return $client_token;
+ } catch (Exception $e) {
+ $this->log($e->getMessage());
+
+ return false;
+ }
+ }
+
+ public function getTransaction($gateway, $transaction_id) {
+ try {
+ if ($gateway != null) {
+ $transaction = $gateway->transaction()->find($transaction_id);
+ } else {
+ $transaction = Braintree_Transaction::find($transaction_id);
+ }
+
+ if ($transaction) {
+ return $transaction;
+ } else {
+ return false;
+ }
+ } catch (Exception $e) {
+ $this->log($e->getMessage());
+
+ return false;
+ }
+ }
+
+ public function getTransactions($gateway, $data = array()) {
+ try {
+ if ($gateway != null) {
+ $transactions = $gateway->transaction()->search($data);
+ } else {
+ $transactions = Braintree_Transaction::search($data);
+ }
+
+ if ($transactions) {
+ return $transactions;
+ } else {
+ return false;
+ }
+ } catch (Exception $e) {
+ $this->log($e->getMessage());
+
+ return false;
+ }
+ }
+
+ public function voidTransaction($gateway, $transaction_id) {
+ try {
+ if ($gateway != null) {
+ $transaction = $gateway->transaction()->void($transaction_id);
+ } else {
+ $transaction = Braintree_Transaction::void($transaction_id);
+ }
+
+ if ($transaction) {
+ return $transaction;
+ } else {
+ return false;
+ }
+ } catch (Exception $e) {
+ $this->log($e->getMessage());
+
+ return false;
+ }
+ }
+
+ public function settleTransaction($gateway, $transaction_id, $amount) {
+ try {
+ if ($gateway != null) {
+ $transaction = $gateway->transaction()->submitForSettlement($transaction_id, $amount);
+ } else {
+ $transaction = Braintree_Transaction::submitForSettlement($transaction_id, $amount);
+ }
+
+ if ($transaction) {
+ return $transaction;
+ } else {
+ return false;
+ }
+ } catch (Exception $e) {
+ $this->log($e->getMessage());
+
+ return false;
+ }
+ }
+
+ public function refundTransaction($gateway, $transaction_id, $amount) {
+ try {
+ if ($gateway != null) {
+ $transaction = $gateway->transaction()->refund($transaction_id, $amount);
+ } else {
+ $transaction = Braintree_Transaction::refund($transaction_id, $amount);
+ }
+
+ if ($transaction) {
+ return $transaction;
+ } else {
+ return false;
+ }
+ } catch (Exception $e) {
+ $this->log($e->getMessage());
+
+ return false;
+ }
+ }
+
+ public function verifyCredentials($gateway) {
+ try {
+ //Try API call, if no exception is thrown, the credentials are correct
+ if ($gateway != null) {
+ $client_token = $gateway->clientToken()->generate();
+ } else {
+ $client_token = Braintree_ClientToken::generate();
+ }
+
+ return $client_token;
+ } catch (Exception $e) {
+ $this->log($e->getMessage());
+
+ return false;
+ }
+ }
+
+ public function verifyMerchantAccount($gateway, $merchant_account_id) {
+ try {
+ //Try API call, if no exception is thrown, the above credentials are correct
+ if ($gateway != null) {
+ $merchant_account = $gateway->merchantAccount()->find($merchant_account_id);
+ } else {
+ $merchant_account = Braintree_MerchantAccount::find($merchant_account_id);
+ }
+
+ if ($merchant_account && $merchant_account->status == 'active') {
+ return $merchant_account;
+ } else {
+ return false;
+ }
+ } catch (Exception $e) {
+ $this->log($e->getMessage());
+
+ return false;
+ }
+ }
+
+ public function setGateway($access_token) {
+ return new Braintree_Gateway(array('accessToken' => $access_token));
+ }
+
+ public function log($data) {
+ if ($this->config->get('payment_pp_braintree_debug')) {
+ $backtrace = debug_backtrace();
+ $log = new Log('braintree.log');
+ $log->write('(' . $backtrace[1]['class'] . '::' . $backtrace[1]['function'] . ') - ' . print_r($data, true));
+ }
+ }
+}
diff --git a/public/admin/model/extension/payment/pp_express.php b/public/admin/model/extension/payment/pp_express.php
new file mode 100644
index 0000000..5c82d30
--- /dev/null
+++ b/public/admin/model/extension/payment/pp_express.php
@@ -0,0 +1,376 @@
+<?php
+class ModelExtensionPaymentPPExpress extends Model {
+ public function install() {
+ $this->db->query("
+ CREATE TABLE IF NOT EXISTS `" . DB_PREFIX . "paypal_order` (
+ `paypal_order_id` int(11) NOT NULL AUTO_INCREMENT,
+ `order_id` int(11) NOT NULL,
+ `date_added` DATETIME NOT NULL,
+ `date_modified` DATETIME NOT NULL,
+ `capture_status` ENUM('Complete','NotComplete') DEFAULT NULL,
+ `currency_code` CHAR(3) NOT NULL,
+ `authorization_id` VARCHAR(30) NOT NULL,
+ `total` DECIMAL( 10, 2 ) NOT NULL,
+ PRIMARY KEY (`paypal_order_id`)
+ ) ENGINE=MyISAM DEFAULT COLLATE=utf8_general_ci
+ ");
+
+ $this->db->query("
+ CREATE TABLE IF NOT EXISTS `" . DB_PREFIX . "paypal_order_transaction` (
+ `paypal_order_transaction_id` int(11) NOT NULL AUTO_INCREMENT,
+ `paypal_order_id` int(11) NOT NULL,
+ `transaction_id` CHAR(20) NOT NULL,
+ `parent_id` CHAR(20) NOT NULL,
+ `date_added` DATETIME NOT NULL,
+ `note` VARCHAR(255) NOT NULL,
+ `msgsubid` CHAR(38) NOT NULL,
+ `receipt_id` CHAR(20) NOT NULL,
+ `payment_type` ENUM('none','echeck','instant', 'refund', 'void') DEFAULT NULL,
+ `payment_status` CHAR(20) NOT NULL,
+ `pending_reason` CHAR(50) NOT NULL,
+ `transaction_entity` CHAR(50) NOT NULL,
+ `amount` DECIMAL( 10, 2 ) NOT NULL,
+ `debug_data` TEXT NOT NULL,
+ `call_data` TEXT NOT NULL,
+ PRIMARY KEY (`paypal_order_transaction_id`)
+ ) ENGINE=MyISAM DEFAULT COLLATE=utf8_general_ci
+ ");
+
+ $this->load->model('setting/setting');
+
+ $defaults = array();
+
+ // Order Status defaults
+ $defaults['payment_pp_express_canceled_reversal_status_id'] = 9;
+ $defaults['payment_pp_express_completed_status_id'] = 5;
+ $defaults['payment_pp_express_denied_status_id'] = 8;
+ $defaults['payment_pp_express_expired_status_id'] = 14;
+ $defaults['payment_pp_express_failed_status_id'] = 10;
+ $defaults['payment_pp_express_pending_status_id'] = 1;
+ $defaults['payment_pp_express_processed_status_id'] = 15;
+ $defaults['payment_pp_express_refunded_status_id'] = 11;
+ $defaults['payment_pp_express_reversed_status_id'] = 12;
+ $defaults['payment_pp_express_voided_status_id'] = 16;
+
+ $defaults['payment_pp_express_status'] = 0;
+ $defaults['payment_pp_express_currency'] = "USD";
+
+ $this->model_setting_setting->editSetting('payment_pp_express', $defaults);
+
+ $this->load->model('setting/event');
+ $this->model_setting_event->addEvent('extension_pp_express_checkout_js', 'catalog/controller/checkout/checkout/before', 'extension/payment/pp_express/eventLoadCheckoutJs');
+ }
+
+ public function uninstall() {
+ $this->db->query("DROP TABLE IF EXISTS `" . DB_PREFIX . "paypal_order_transaction`");
+ $this->db->query("DROP TABLE IF EXISTS `" . DB_PREFIX . "paypal_order`");
+
+ $this->load->model('setting/event');
+ $this->model_setting_event->deleteEventByCode('extension_pp_express_checkout_js');
+ }
+
+ public function getPayPalOrder($order_id) {
+ $query = $this->db->query("SELECT * FROM `" . DB_PREFIX . "paypal_order` WHERE `order_id` = '" . (int)$order_id . "'");
+
+ return $query->row;
+ }
+
+ public function editPayPalOrderStatus($order_id, $capture_status) {
+ $this->db->query("UPDATE `" . DB_PREFIX . "paypal_order` SET `capture_status` = '" . $this->db->escape($capture_status) . "', `date_modified` = NOW() WHERE `order_id` = '" . (int)$order_id . "'");
+ }
+
+ public function addTransaction($transaction_data, $request_data = array()) {
+ if ($request_data) {
+ $serialized_data = json_encode($request_data);
+
+ $this->db->query("UPDATE " . DB_PREFIX . "paypal_order_transaction SET call_data = '" . $this->db->escape($serialized_data) . "' WHERE paypal_order_transaction_id = " . (int)$paypal_order_transaction_id . " LIMIT 1");
+ }
+
+
+
+ $this->db->query("INSERT INTO `" . DB_PREFIX . "paypal_order_transaction` SET `paypal_order_id` = '" . (int)$transaction_data['paypal_order_id'] . "', `transaction_id` = '" . $this->db->escape($transaction_data['transaction_id']) . "', `parent_id` = '" . $this->db->escape($transaction_data['parent_id']) . "', `date_added` = NOW(), `note` = '" . $this->db->escape($transaction_data['note']) . "', `msgsubid` = '" . $this->db->escape($transaction_data['msgsubid']) . "', `receipt_id` = '" . $this->db->escape($transaction_data['receipt_id']) . "', `payment_type` = '" . $this->db->escape($transaction_data['payment_type']) . "', `payment_status` = '" . $this->db->escape($transaction_data['payment_status']) . "', `pending_reason` = '" . $this->db->escape($transaction_data['pending_reason']) . "', `transaction_entity` = '" . $this->db->escape($transaction_data['transaction_entity']) . "', `amount` = '" . (float)$transaction_data['amount'] . "', `debug_data` = '" . $this->db->escape($transaction_data['debug_data']) . "'");
+
+ return $this->db->getLastId();
+ }
+
+ public function updateTransaction($transaction) {
+ $this->db->query("UPDATE " . DB_PREFIX . "paypal_order_transaction SET paypal_order_id = " . (int)$transaction['paypal_order_id'] . ", transaction_id = '" . $this->db->escape($transaction['transaction_id']) . "', parent_id = '" . $this->db->escape($transaction['parent_id']) . "', date_added = '" . $this->db->escape($transaction['date_added']) . "', note = '" . $this->db->escape($transaction['note']) . "', msgsubid = '" . $this->db->escape($transaction['msgsubid']) . "', receipt_id = '" . $this->db->escape($transaction['receipt_id']) . "', payment_type = '" . $this->db->escape($transaction['payment_type']) . "', payment_status = '" . $this->db->escape($transaction['payment_status']) . "', pending_reason = '" . $this->db->escape($transaction['pending_reason']) . "', transaction_entity = '" . $this->db->escape($transaction['transaction_entity']) . "', amount = '" . $this->db->escape($transaction['amount']) . "', debug_data = '" . $this->db->escape($transaction['debug_data']) . "', call_data = '" . $this->db->escape($transaction['call_data']) . "' WHERE paypal_order_transaction_id = '" . (int)$transaction['paypal_order_transaction_id'] . "'");
+ }
+
+ public function getPaypalOrderByTransactionId($transaction_id) {
+ $query = $this->db->query("SELECT * FROM " . DB_PREFIX . "paypal_order_transaction WHERE transaction_id = '" . $this->db->escape($transaction_id) . "'");
+
+ return $query->rows;
+ }
+
+ public function getFailedTransaction($paypal_order_transaction_id) {
+ $query = $this->db->query("SELECT * FROM " . DB_PREFIX . "paypal_order_transaction WHERE paypal_order_transaction_id = '" . (int)$paypal_order_transaction_id . "'");
+
+ return $query->row;
+ }
+
+ public function getLocalTransaction($transaction_id) {
+ $result = $this->db->query("SELECT * FROM " . DB_PREFIX . "paypal_order_transaction WHERE transaction_id = '" . $this->db->escape($transaction_id) . "'")->row;
+
+ if ($result) {
+ return $result;
+ } else {
+ return false;
+ }
+ }
+
+ public function getTransaction($transaction_id) {
+ $call_data = array(
+ 'METHOD' => 'GetTransactionDetails',
+ 'TRANSACTIONID' => $transaction_id,
+ );
+
+ return $this->call($call_data);
+ }
+
+ public function getCurrencies() {
+ return array(
+ 'AUD',
+ 'BRL',
+ 'CAD',
+ 'CZK',
+ 'DKK',
+ 'EUR',
+ 'HKD',
+ 'HUF',
+ 'ILS',
+ 'JPY',
+ 'MYR',
+ 'MXN',
+ 'NOK',
+ 'NZD',
+ 'PHP',
+ 'PLN',
+ 'GBP',
+ 'SGD',
+ 'SEK',
+ 'CHF',
+ 'TWD',
+ 'THB',
+ 'TRY',
+ 'USD',
+ );
+ }
+
+ public function getOrderId($transaction_id) {
+ $query = $this->db->query("SELECT `o`.`order_id` FROM `" . DB_PREFIX . "paypal_order_transaction` `ot` LEFT JOIN `" . DB_PREFIX . "paypal_order` `o` ON `o`.`paypal_order_id` = `ot`.`paypal_order_id` WHERE `ot`.`transaction_id` = '" . $this->db->escape($transaction_id) . "' LIMIT 1");
+
+ return $query->row['order_id'];
+ }
+
+ public function getCapturedTotal($paypal_order_id) {
+ $query = $this->db->query("SELECT SUM(`amount`) AS `amount` FROM `" . DB_PREFIX . "paypal_order_transaction` WHERE `paypal_order_id` = '" . (int)$paypal_order_id . "' AND `pending_reason` != 'authorization' AND (`payment_status` = 'Partially-Refunded' OR `payment_status` = 'Completed' OR `payment_status` = 'Pending') AND `transaction_entity` = 'payment'");
+
+ return $query->row['amount'];
+ }
+
+ public function getRefundedTotal($paypal_order_id) {
+ $query = $this->db->query("SELECT SUM(`amount`) AS `amount` FROM `" . DB_PREFIX . "paypal_order_transaction` WHERE `paypal_order_id` = '" . (int)$paypal_order_id . "' AND `payment_status` = 'Refunded' AND `parent_id` != ''");
+
+ return $query->row['amount'];
+ }
+
+ public function getRefundedTotalByParentId($transaction_id) {
+ $query = $this->db->query("SELECT SUM(`amount`) AS `amount` FROM `" . DB_PREFIX . "paypal_order_transaction` WHERE `parent_id` = '" . $this->db->escape($transaction_id) . "' AND `payment_type` = 'refund'");
+
+ return $query->row['amount'];
+ }
+
+ public function cleanReturn($data) {
+ $data = explode('&', $data);
+
+ $arr = array();
+
+ foreach ($data as $k => $v) {
+ $tmp = explode('=', $v);
+ $arr[$tmp[0]] = urldecode($tmp[1]);
+ }
+
+ return $arr;
+ }
+
+ public function log($data, $title = null) {
+ if ($this->config->get('payment_pp_express_debug')) {
+ $this->log->write('PayPal Express debug (' . $title . '): ' . json_encode($data));
+ }
+ }
+
+ public function getOrder($order_id) {
+ $qry = $this->db->query("SELECT * FROM `" . DB_PREFIX . "paypal_order` WHERE `order_id` = '" . (int)$order_id . "' LIMIT 1");
+
+ if ($qry->num_rows) {
+ $order = $qry->row;
+ $order['transactions'] = $this->getTransactions($order['paypal_order_id']);
+ $order['captured'] = $this->totalCaptured($order['paypal_order_id']);
+ return $order;
+ } else {
+ return false;
+ }
+ }
+
+ public function totalCaptured($paypal_order_id) {
+ $qry = $this->db->query("SELECT SUM(`amount`) AS `amount` FROM `" . DB_PREFIX . "paypal_order_transaction` WHERE `paypal_order_id` = '" . (int)$paypal_order_id . "' AND `pending_reason` != 'authorization' AND (`payment_status` = 'Partially-Refunded' OR `payment_status` = 'Completed' OR `payment_status` = 'Pending') AND `transaction_entity` = 'payment'");
+
+ return $qry->row['amount'];
+ }
+
+ public function getTransactions($paypal_order_id) {
+ $query = $this->db->query("SELECT `ot`.*, (SELECT COUNT(`ot2`.`paypal_order_id`) FROM `" . DB_PREFIX . "paypal_order_transaction` `ot2` WHERE `ot2`.`parent_id` = `ot`.`transaction_id`) AS `children` FROM `" . DB_PREFIX . "paypal_order_transaction` `ot` WHERE `paypal_order_id` = '" . (int)$paypal_order_id . "' ORDER BY `date_added` ASC");
+
+ return $query->rows;
+ }
+
+ public function getTokens($test) {
+ if ($test == 'sandbox') {
+ $endpoint = 'https://api.sandbox.paypal.com/v1/oauth2/token';
+ $client_id = 'Ad3QTBAHwhuNI_blejO4_RqvES74yWRUC61c5QVNDbxkq9csbLpDZogWp_0n';
+ $client_secret = 'EGqgGxCqjs1GIa5l1Ex_Flq0Mb2oMT3rJu2kwz6FuF9QKyxCg6qNqyddxCCW';
+ } else {
+ $endpoint = 'https://api.paypal.com/v1/oauth2/token';
+ $client_id = 'AWyAiBCUYsE156N8YpiiISQpSpep2HPoXXPrf33VBeYleE0SQJg40pgEqZvq';
+ $client_secret = 'EEkc6xB30fDkgUO_YldWWHxKDquY7LBRId6FJ-parAR1CsVpK35zB6U0SIh4';
+ }
+
+ $request = '';
+ $request .= 'client_id=' . $client_id;
+ $request .= '&client_secret=' . $client_secret;
+ $request .= '&grant_type=client_credentials';
+
+ $additional_opts = array(
+ CURLOPT_USERPWD => $client_id . ':' . $client_secret,
+ CURLOPT_POST => true,
+ CURLOPT_POSTFIELDS => $request
+ );
+
+ $curl = $this->curl($endpoint, $additional_opts);
+
+ $this->log('cURL Response 1: ' . print_r($curl, 1));
+
+ return $curl;
+ }
+
+ public function getUserInfo($merchant_id, $test, $access_token) {
+ if ($test == 'sandbox') {
+ $endpoint = 'https://api.sandbox.paypal.com/v1/customer/partners/T4E8WSXT43QPJ/merchant-integrations';
+ } else {
+ $endpoint = 'https://api.paypal.com/v1/customer/partners/9PDNYE4RZBVFJ/merchant-integrations';
+ }
+
+ $endpoint1 = $endpoint . '?tracking_id=' . $merchant_id;
+
+ $header = array();
+ $header[] = 'Content-Type: application/json';
+ $header[] = 'Authorization: Bearer ' . $access_token;
+ $header[] = 'PAYPAL_SERVICE_VERSION:1.2.0';
+
+ $additional_opts = array(
+ CURLOPT_HTTPHEADER => $header,
+ );
+
+ $curl = $this->curl($endpoint1, $additional_opts);
+
+ $this->log('cURL Response 2: ' . print_r($curl, 1));
+
+ if (isset($curl->merchant_id)) {
+ $endpoint2 = $endpoint . '/' . $curl->merchant_id;
+ $curl2 = $this->curl($endpoint2, $additional_opts);
+
+ $this->log('cURL Response 3: ' . print_r($curl2, 1));
+
+ if (isset($curl2->api_credentials->signature)) {
+ return $curl2->api_credentials->signature;
+ } else {
+ return;
+ }
+ } else {
+ return;
+ }
+ }
+
+ public function call($data) {
+ if ($this->config->get('payment_pp_express_test') == 1) {
+ $api_endpoint = 'https://api-3t.sandbox.paypal.com/nvp';
+ $user = $this->config->get('payment_pp_express_sandbox_username');
+ $password = $this->config->get('payment_pp_express_sandbox_password');
+ $signature = $this->config->get('payment_pp_express_sandbox_signature');
+ } else {
+ $api_endpoint = 'https://api-3t.paypal.com/nvp';
+ $user = $this->config->get('payment_pp_express_username');
+ $password = $this->config->get('payment_pp_express_password');
+ $signature = $this->config->get('payment_pp_express_signature');
+ }
+
+ $settings = array(
+ 'USER' => $user,
+ 'PWD' => $password,
+ 'SIGNATURE' => $signature,
+ 'VERSION' => '84',
+ 'BUTTONSOURCE' => 'OpenCart_Cart_EC',
+ );
+
+ $this->log($data, 'Call data');
+
+ $defaults = array(
+ CURLOPT_POST => 1,
+ CURLOPT_HEADER => 0,
+ CURLOPT_URL => $api_endpoint,
+ CURLOPT_USERAGENT => "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8.1.1) Gecko/20061204 Firefox/2.0.0.1",
+ CURLOPT_FRESH_CONNECT => 1,
+ CURLOPT_RETURNTRANSFER => 1,
+ CURLOPT_FORBID_REUSE => 1,
+ CURLOPT_TIMEOUT => 0,
+ CURLOPT_SSL_VERIFYPEER => 0,
+ CURLOPT_SSL_VERIFYHOST => 0,
+ CURLOPT_POSTFIELDS => http_build_query(array_merge($data, $settings), '', "&")
+ );
+
+ $ch = curl_init();
+
+ curl_setopt_array($ch, $defaults);
+
+ if (!$result = curl_exec($ch)) {
+ $log_data = array(
+ 'curl_error' => curl_error($ch),
+ 'curl_errno' => curl_errno($ch)
+ );
+
+ $this->log($log_data, 'CURL failed');
+ return false;
+ }
+
+ $this->log($result, 'Result');
+
+ curl_close($ch);
+
+ return $this->cleanReturn($result);
+ }
+
+ private function curl($endpoint, $additional_opts = array()) {
+ $default_opts = array(
+ CURLOPT_PORT => 443,
+ CURLOPT_HEADER => 0,
+ CURLOPT_SSL_VERIFYPEER => 0,
+ CURLOPT_RETURNTRANSFER => 1,
+ CURLOPT_FORBID_REUSE => 1,
+ CURLOPT_FRESH_CONNECT => 1,
+ CURLOPT_URL => $endpoint,
+ );
+
+ $ch = curl_init($endpoint);
+
+ $opts = $default_opts + $additional_opts;
+
+ curl_setopt_array($ch, $opts);
+
+ $response = json_decode(curl_exec($ch));
+
+ curl_close($ch);
+
+ return $response;
+ }
+}
diff --git a/public/admin/model/extension/payment/pp_payflow_iframe.php b/public/admin/model/extension/payment/pp_payflow_iframe.php
new file mode 100644
index 0000000..34c2251
--- /dev/null
+++ b/public/admin/model/extension/payment/pp_payflow_iframe.php
@@ -0,0 +1,136 @@
+<?php
+class ModelExtensionPaymentPPPayflowIFrame extends Model {
+ public function install() {
+ $this->db->query("
+ CREATE TABLE `" . DB_PREFIX . "paypal_payflow_iframe_order` (
+ `order_id` int(11) DEFAULT NULL,
+ `secure_token_id` varchar(255) NOT NULL,
+ `transaction_reference` varchar(255) DEFAULT NULL,
+ `transaction_type` varchar(1) DEFAULT NULL,
+ `complete` tinyint(4) NOT NULL DEFAULT '0',
+ PRIMARY KEY(`order_id`),
+ KEY `secure_token_id` (`secure_token_id`)
+ ) ENGINE=MyISAM DEFAULT COLLATE=utf8_general_ci");
+
+ $this->db->query("
+ CREATE TABLE `" . DB_PREFIX . "paypal_payflow_iframe_order_transaction` (
+ `order_id` int(11) NOT NULL,
+ `transaction_reference` varchar(255) NOT NULL,
+ `transaction_type` char(1) NOT NULL,
+ `time` datetime NOT NULL,
+ `amount` decimal(10,4) DEFAULT NULL,
+ PRIMARY KEY (`transaction_reference`),
+ KEY `order_id` (`order_id`)
+ ) ENGINE=MyISAM DEFAULT CHARSET=utf8;");
+ }
+
+ public function uninstall() {
+ $this->db->query("DROP TABLE IF EXISTS `" . DB_PREFIX . "paypal_payflow_iframe_order`;");
+ $this->db->query("DROP TABLE IF EXISTS `" . DB_PREFIX . "paypal_payflow_iframe_order_transaction`;");
+ }
+
+ public function log($message) {
+ if ($this->config->get('payment_pp_payflow_iframe_debug')) {
+ $log = new Log('payflow-iframe.log');
+ $log->write($message);
+ }
+ }
+
+ public function getOrder($order_id) {
+ $result = $this->db->query("SELECT * FROM " . DB_PREFIX . "paypal_payflow_iframe_order WHERE order_id = " . (int)$order_id);
+
+ if ($result->num_rows) {
+ $order = $result->row;
+ } else {
+ $order = false;
+ }
+
+ return $order;
+ }
+
+ public function updateOrderStatus($order_id, $status) {
+ $this->db->query("
+ UPDATE " . DB_PREFIX . "paypal_payflow_iframe_order
+ SET `complete` = " . (int)$status . "
+ WHERE order_id = '" . (int)$order_id . "'
+ ");
+ }
+
+ public function addTransaction($data) {
+ $this->db->query("
+ INSERT INTO " . DB_PREFIX . "paypal_payflow_iframe_order_transaction
+ SET order_id = " . (int)$data['order_id'] . ",
+ transaction_reference = '" . $this->db->escape($data['transaction_reference']) . "',
+ transaction_type = '" . $this->db->escape($data['type']) . "',
+ `time` = NOW(),
+ `amount` = '" . $this->db->escape($data['amount']) . "'
+ ");
+ }
+
+ public function getTransactions($order_id) {
+ return $this->db->query("
+ SELECT *
+ FROM " . DB_PREFIX . "paypal_payflow_iframe_order_transaction
+ WHERE order_id = " . (int)$order_id . "
+ ORDER BY `time` ASC")->rows;
+ }
+
+ public function getTransaction($transaction_reference) {
+ $result = $this->db->query("
+ SELECT *
+ FROM " . DB_PREFIX . "paypal_payflow_iframe_order_transaction
+ WHERE transaction_reference = '" . $this->db->escape($transaction_reference) . "'")->row;
+
+ if ($result) {
+ $transaction = $result;
+ } else {
+ $transaction = false;
+ }
+
+ return $transaction;
+ }
+
+ public function call($data) {
+ $default_parameters = array(
+ 'USER' => $this->config->get('payment_pp_payflow_iframe_user'),
+ 'VENDOR' => $this->config->get('payment_pp_payflow_iframe_vendor'),
+ 'PWD' => $this->config->get('payment_pp_payflow_iframe_password'),
+ 'PARTNER' => $this->config->get('payment_pp_payflow_iframe_partner'),
+ 'BUTTONSOURCE' => 'OpenCart_Cart_PFP',
+ );
+
+ $call_parameters = array_merge($data, $default_parameters);
+
+ if ($this->config->get('payment_pp_payflow_iframe_test')) {
+ $url = 'https://pilot-payflowpro.paypal.com';
+ } else {
+ $url = 'https://payflowpro.paypal.com';
+ }
+
+ $query_params = array();
+
+ foreach ($call_parameters as $key => $value) {
+ $query_params[] = $key . '=' . utf8_decode($value);
+ }
+
+ $this->log('Call data: ' . implode('&', $query_params));
+
+ $curl = curl_init($url);
+
+ curl_setopt($curl, CURLOPT_POST, true);
+ curl_setopt($curl, CURLOPT_POSTFIELDS, implode('&', $query_params));
+ curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
+ curl_setopt($curl, CURLOPT_HEADER, false);
+ curl_setopt($curl, CURLOPT_TIMEOUT, 30);
+ curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false);
+
+ $response = curl_exec($curl);
+
+ $this->log('Response data: ' . $response);
+
+ $response_params = array();
+ parse_str($response, $response_params);
+
+ return $response_params;
+ }
+} \ No newline at end of file
diff --git a/public/admin/model/extension/payment/pp_pro_iframe.php b/public/admin/model/extension/payment/pp_pro_iframe.php
new file mode 100644
index 0000000..f1df3b5
--- /dev/null
+++ b/public/admin/model/extension/payment/pp_pro_iframe.php
@@ -0,0 +1,261 @@
+<?php
+class ModelExtensionPaymentPPProIframe extends Model {
+ public function install() {
+ $this->db->query("
+ CREATE TABLE IF NOT EXISTS `" . DB_PREFIX . "paypal_iframe_order` (
+ `paypal_iframe_order_id` int(11) NOT NULL AUTO_INCREMENT,
+ `order_id` int(11) NOT NULL,
+ `date_added` DATETIME NOT NULL,
+ `date_modified` DATETIME NOT NULL,
+ `capture_status` ENUM('Complete','NotComplete') DEFAULT NULL,
+ `currency_code` CHAR(3) NOT NULL,
+ `authorization_id` VARCHAR(30) NOT NULL,
+ `total` DECIMAL( 10, 2 ) NOT NULL,
+ PRIMARY KEY (`paypal_iframe_order_id`)
+ ) ENGINE=MyISAM DEFAULT COLLATE=utf8_general_ci;");
+
+ $this->db->query("
+ CREATE TABLE IF NOT EXISTS `" . DB_PREFIX . "paypal_iframe_order_transaction` (
+ `paypal_iframe_order_transaction_id` int(11) NOT NULL AUTO_INCREMENT,
+ `paypal_iframe_order_id` int(11) NOT NULL,
+ `transaction_id` CHAR(20) NOT NULL,
+ `parent_id` CHAR(20) NOT NULL,
+ `date_added` DATETIME NOT NULL,
+ `note` VARCHAR(255) NOT NULL,
+ `msgsubid` CHAR(38) NOT NULL,
+ `receipt_id` CHAR(20) NOT NULL,
+ `payment_type` ENUM('none','echeck','instant', 'refund', 'void') DEFAULT NULL,
+ `payment_status` CHAR(20) NOT NULL,
+ `pending_reason` CHAR(50) NOT NULL,
+ `transaction_entity` CHAR(50) NOT NULL,
+ `amount` DECIMAL( 10, 2 ) NOT NULL,
+ `debug_data` TEXT NOT NULL,
+ `call_data` TEXT NOT NULL,
+ PRIMARY KEY (`paypal_iframe_order_transaction_id`)
+ ) ENGINE=MyISAM DEFAULT COLLATE=utf8_general_ci;");
+ }
+
+ public function uninstall() {
+ $this->db->query("DROP TABLE IF EXISTS `" . DB_PREFIX . "paypal_iframe_order_transaction`;");
+ $this->db->query("DROP TABLE IF EXISTS `" . DB_PREFIX . "paypal_iframe_order`;");
+ }
+
+ private function getTransactions($paypal_iframe_order_id) {
+ $qry = $this->db->query("SELECT `ot`.*, ( SELECT count(`ot2`.`paypal_iframe_order_id`) FROM `" . DB_PREFIX . "paypal_iframe_order_transaction` `ot2` WHERE `ot2`.`parent_id` = `ot`.`transaction_id` ) AS `children` FROM `" . DB_PREFIX . "paypal_iframe_order_transaction` `ot` WHERE `paypal_iframe_order_id` = '" . (int)$paypal_iframe_order_id . "'");
+
+ if ($qry->num_rows) {
+ return $qry->rows;
+ } else {
+ return false;
+ }
+ }
+
+ public function getTotalCaptured($paypal_iframe_order_id) {
+ $qry = $this->db->query("SELECT SUM(`amount`) AS `amount` FROM `" . DB_PREFIX . "paypal_iframe_order_transaction` WHERE `paypal_iframe_order_id` = '" . (int)$paypal_iframe_order_id . "' AND `pending_reason` != 'authorization' AND (`payment_status` = 'Partially-Refunded' OR `payment_status` = 'Completed' OR `payment_status` = 'Pending') AND `transaction_entity` = 'payment'");
+
+ return $qry->row['amount'];
+ }
+
+ public function getTotalRefunded($paypal_iframe_order_id) {
+ $qry = $this->db->query("SELECT SUM(`amount`) AS `amount` FROM `" . DB_PREFIX . "paypal_iframe_order_transaction` WHERE `paypal_iframe_order_id` = '" . (int)$paypal_iframe_order_id . "' AND `payment_status` = 'Refunded'");
+
+ return $qry->row['amount'];
+ }
+
+ public function getTotalRefundedTransaction($transaction_id) {
+ $qry = $this->db->query("SELECT SUM(`amount`) AS `amount` FROM `" . DB_PREFIX . "paypal_iframe_order_transaction` WHERE `parent_id` = '" . $this->db->escape($transaction_id) . "' AND `payment_type` = 'refund'");
+
+ return $qry->row['amount'];
+ }
+
+ public function getOrder($order_id) {
+ $qry = $this->db->query("SELECT * FROM `" . DB_PREFIX . "paypal_iframe_order` WHERE `order_id` = '" . (int)$order_id . "' LIMIT 1");
+
+ if ($qry->num_rows) {
+ $order = $qry->row;
+ $order['transactions'] = $this->getTransactions($order['paypal_iframe_order_id']);
+ $order['captured'] = $this->getTotalCaptured($order['paypal_iframe_order_id']);
+ return $order;
+ } else {
+ return false;
+ }
+ }
+
+ public function call($data) {
+
+ if ($this->config->get('payment_pp_pro_iframe_test') == 1) {
+ $api_endpoint = 'https://api-3t.sandbox.paypal.com/nvp';
+ } else {
+ $api_endpoint = 'https://api-3t.paypal.com/nvp';
+ }
+
+ $settings = array(
+ 'USER' => $this->config->get('payment_pp_pro_iframe_user'),
+ 'PWD' => $this->config->get('payment_pp_pro_iframe_password'),
+ 'SIGNATURE' => $this->config->get('payment_pp_pro_iframe_sig'),
+ 'VERSION' => '84',
+ 'BUTTONSOURCE' => 'WM_PRO_OPENCART_UK_' . VERSION,
+ );
+
+ $this->log($data, 'Call data');
+
+ $defaults = array(
+ CURLOPT_POST => 1,
+ CURLOPT_HEADER => 0,
+ CURLOPT_URL => $api_endpoint,
+ CURLOPT_USERAGENT => "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8.1.1) Gecko/20061204 Firefox/2.0.0.1",
+ CURLOPT_FRESH_CONNECT => 1,
+ CURLOPT_RETURNTRANSFER => 1,
+ CURLOPT_FORBID_REUSE => 1,
+ CURLOPT_TIMEOUT => 0,
+ CURLOPT_SSL_VERIFYPEER => 0,
+ CURLOPT_SSL_VERIFYHOST => 0,
+ CURLOPT_POSTFIELDS => http_build_query(array_merge($data, $settings), '', "&")
+ );
+
+ $ch = curl_init();
+
+ curl_setopt_array($ch, $defaults);
+
+ if (!$result = curl_exec($ch)) {
+
+ $log_data = array(
+ 'curl_error' => curl_error($ch),
+ 'curl_errno' => curl_errno($ch)
+ );
+
+ $this->log($log_data, 'CURL failed');
+
+ return false;
+ }
+
+ $this->log($result, 'Result');
+
+ curl_close($ch);
+
+ return $this->cleanReturn($result);
+ }
+
+ public function updateOrder($capture_status, $order_id) {
+ $this->db->query("UPDATE `" . DB_PREFIX . "paypal_iframe_order` SET `date_modified` = now(), `capture_status` = '" . $this->db->escape($capture_status) . "' WHERE `order_id` = '" . (int)$order_id . "'");
+ }
+
+ public function updateTransaction($transaction) {
+ $this->db->query("
+ UPDATE " . DB_PREFIX . "paypal_iframe_order_transaction
+ SET paypal_iframe_order_id = " . (int)$transaction['paypal_iframe_order_id'] . ",
+ transaction_id = '" . $this->db->escape($transaction['transaction_id']) . "',
+ parent_id = '" . $this->db->escape($transaction['parent_id']) . "',
+ date_added = '" . $this->db->escape($transaction['date_added']) . "',
+ note = '" . $this->db->escape($transaction['note']) . "',
+ msgsubid = '" . $this->db->escape($transaction['msgsubid']) . "',
+ receipt_id = '" . $this->db->escape($transaction['receipt_id']) . "',
+ payment_type = '" . $this->db->escape($transaction['payment_type']) . "',
+ payment_status = '" . $this->db->escape($transaction['payment_status']) . "',
+ pending_reason = '" . $this->db->escape($transaction['pending_reason']) . "',
+ transaction_entity = '" . $this->db->escape($transaction['transaction_entity']) . "',
+ amount = '" . $this->db->escape($transaction['amount']) . "',
+ debug_data = '" . $this->db->escape($transaction['debug_data']) . "',
+ call_data = '" . $this->db->escape($transaction['call_data']) . "'
+ WHERE paypal_iframe_order_transaction_id = " . (int)$transaction['paypal_iframe_order_transaction_id'] . "
+ ");
+ }
+
+ public function addTransaction($transaction_data, $request_data = array()) {
+ $this->db->query("INSERT INTO `" . DB_PREFIX . "paypal_iframe_order_transaction` SET `paypal_iframe_order_id` = '" . (int)$transaction_data['paypal_iframe_order_id'] . "', `transaction_id` = '" . $this->db->escape($transaction_data['transaction_id']) . "', `parent_id` = '" . $this->db->escape($transaction_data['parent_id']) . "', `date_added` = NOW(), `note` = '" . $this->db->escape($transaction_data['note']) . "', `msgsubid` = '" . $this->db->escape($transaction_data['msgsubid']) . "', `receipt_id` = '" . $this->db->escape($transaction_data['receipt_id']) . "', `payment_type` = '" . $this->db->escape($transaction_data['payment_type']) . "', `payment_status` = '" . $this->db->escape($transaction_data['payment_status']) . "', `pending_reason` = '" . $this->db->escape($transaction_data['pending_reason']) . "', `transaction_entity` = '" . $this->db->escape($transaction_data['transaction_entity']) . "', `amount` = '" . (float)$transaction_data['amount'] . "', `debug_data` = '" . $this->db->escape($transaction_data['debug_data']) . "'");
+
+ $paypal_iframe_order_transaction_id = $this->db->getLastId();
+
+ if ($request_data) {
+ $serialized_data = json_encode($request_data);
+
+ $this->db->query("
+ UPDATE " . DB_PREFIX . "paypal_iframe_order_transaction
+ SET call_data = '" . $this->db->escape($serialized_data) . "'
+ WHERE paypal_iframe_order_transaction_id = " . (int)$paypal_iframe_order_transaction_id . "
+ LIMIT 1
+ ");
+ }
+
+ return $paypal_iframe_order_transaction_id;
+ }
+
+ public function log($data, $title = null) {
+ if ($this->config->get('payment_pp_pro_iframe_debug')) {
+ $log = new Log('pp_pro_iframe.log');
+ $log->write($title . ': ' . json_encode($data));
+ }
+ }
+
+ public function getTransaction($transaction_id) {
+ $call_data = array(
+ 'METHOD' => 'GetTransactionDetails',
+ 'TRANSACTIONID' => $transaction_id,
+ );
+
+ return $this->call($call_data);
+ }
+
+ public function getOrderId($transaction_id) {
+ $qry = $this->db->query("SELECT `o`.`order_id` FROM `" . DB_PREFIX . "paypal_iframe_order_transaction` `ot` LEFT JOIN `" . DB_PREFIX . "paypal_iframe_order` `o` ON `o`.`paypal_iframe_order_id` = `ot`.`paypal_iframe_order_id` WHERE `ot`.`transaction_id` = '" . $this->db->escape($transaction_id) . "' LIMIT 1");
+
+ if ($qry->num_rows) {
+ return $qry->row['order_id'];
+ } else {
+ return false;
+ }
+ }
+
+ public function updateAuthorizationId($paypal_iframe_order_id, $authorization_id) {
+ $this->db->query("
+ UPDATE `" . DB_PREFIX . "paypal_iframe_order`
+ SET `authorization_id` = '" . $this->db->escape($authorization_id) . "'
+ WHERE `paypal_iframe_order_id` = '" . $this->db->escape($paypal_iframe_order_id) . "'
+ ");
+ }
+
+ public function updateRefundTransaction($transaction_id, $transaction_type) {
+ $this->db->query("UPDATE `" . DB_PREFIX . "paypal_iframe_order_transaction` SET `payment_status` = '" . $this->db->escape($transaction_type) . "' WHERE `transaction_id` = '" . $this->db->escape($transaction_id) . "' LIMIT 1");
+ }
+
+ public function getFailedTransaction($paypl_iframe_order_transaction_id) {
+ $result = $this->db->query("
+ SELECT *
+ FROM " . DB_PREFIX . "paypal_iframe_order_transaction
+ WHERE paypal_iframe_order_transaction_id = " . (int)$paypl_iframe_order_transaction_id . "
+ ")->row;
+
+ if ($result) {
+ return $result;
+ } else {
+ return false;
+ }
+ }
+
+ public function getLocalTransaction($transaction_id) {
+ $result = $this->db->query("
+ SELECT *
+ FROM " . DB_PREFIX . "paypal_iframe_order_transaction
+ WHERE transaction_id = '" . $this->db->escape($transaction_id) . "'
+ ")->row;
+
+ if ($result) {
+ return $result;
+ } else {
+ return false;
+ }
+ }
+
+ protected function cleanReturn($data) {
+ $data = explode('&', $data);
+
+ $arr = array();
+
+ foreach ($data as $k => $v) {
+ $tmp = explode('=', $v);
+ $arr[$tmp[0]] = urldecode($tmp[1]);
+ }
+
+ return $arr;
+ }
+} \ No newline at end of file
diff --git a/public/admin/model/extension/payment/realex.php b/public/admin/model/extension/payment/realex.php
new file mode 100644
index 0000000..d2b7a7a
--- /dev/null
+++ b/public/admin/model/extension/payment/realex.php
@@ -0,0 +1,265 @@
+<?php
+class ModelExtensionPaymentRealex extends Model {
+ public function install() {
+ $this->db->query("
+ CREATE TABLE IF NOT EXISTS `" . DB_PREFIX . "realex_order` (
+ `realex_order_id` INT(11) NOT NULL AUTO_INCREMENT,
+ `order_id` INT(11) NOT NULL,
+ `order_ref` CHAR(50) NOT NULL,
+ `order_ref_previous` CHAR(50) NOT NULL,
+ `pasref` VARCHAR(50) NOT NULL,
+ `pasref_previous` VARCHAR(50) NOT NULL,
+ `date_added` DATETIME NOT NULL,
+ `date_modified` DATETIME NOT NULL,
+ `capture_status` INT(1) DEFAULT NULL,
+ `void_status` INT(1) DEFAULT NULL,
+ `settle_type` INT(1) DEFAULT NULL,
+ `rebate_status` INT(1) DEFAULT NULL,
+ `currency_code` CHAR(3) NOT NULL,
+ `authcode` VARCHAR(30) NOT NULL,
+ `account` VARCHAR(30) NOT NULL,
+ `total` DECIMAL( 10, 2 ) NOT NULL,
+ PRIMARY KEY (`realex_order_id`)
+ ) ENGINE=MyISAM DEFAULT COLLATE=utf8_general_ci;");
+
+ $this->db->query("
+ CREATE TABLE IF NOT EXISTS `" . DB_PREFIX . "realex_order_transaction` (
+ `realex_order_transaction_id` INT(11) NOT NULL AUTO_INCREMENT,
+ `realex_order_id` INT(11) NOT NULL,
+ `date_added` DATETIME NOT NULL,
+ `type` ENUM('auth', 'payment', 'rebate', 'void') DEFAULT NULL,
+ `amount` DECIMAL( 10, 2 ) NOT NULL,
+ PRIMARY KEY (`realex_order_transaction_id`)
+ ) ENGINE=MyISAM DEFAULT COLLATE=utf8_general_ci;");
+ }
+
+ public function void($order_id) {
+ $realex_order = $this->getOrder($order_id);
+
+ if (!empty($realex_order)) {
+ $timestamp = strftime("%Y%m%d%H%M%S");
+ $merchant_id = $this->config->get('payment_realex_merchant_id');
+ $secret = $this->config->get('payment_realex_secret');
+
+ $this->logger('Void hash construct: ' . $timestamp . '.' . $merchant_id . '.' . $realex_order['order_ref'] . '...');
+
+ $tmp = $timestamp . '.' . $merchant_id . '.' . $realex_order['order_ref'] . '...';
+ $hash = sha1($tmp);
+ $tmp = $hash . '.' . $secret;
+ $hash = sha1($tmp);
+
+ $xml = '';
+ $xml .= '<request type="void" timestamp="' . $timestamp . '">';
+ $xml .= '<merchantid>' . $merchant_id . '</merchantid>';
+ $xml .= '<account>' . $realex_order['account'] . '</account>';
+ $xml .= '<orderid>' . $realex_order['order_ref'] . '</orderid>';
+ $xml .= '<pasref>' . $realex_order['pasref'] . '</pasref>';
+ $xml .= '<authcode>' . $realex_order['authcode'] . '</authcode>';
+ $xml .= '<sha1hash>' . $hash . '</sha1hash>';
+ $xml .= '</request>';
+
+ $this->logger('Void XML request:\r\n' . print_r(simplexml_load_string($xml), 1));
+
+ $ch = curl_init();
+ curl_setopt($ch, CURLOPT_URL, "https://epage.payandshop.com/epage-remote.cgi");
+ curl_setopt($ch, CURLOPT_POST, 1);
+ curl_setopt($ch, CURLOPT_USERAGENT, "OpenCart " . VERSION);
+ curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
+ curl_setopt($ch, CURLOPT_POSTFIELDS, $xml);
+ curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
+ $response = curl_exec ($ch);
+ curl_close ($ch);
+
+ return simplexml_load_string($response);
+ } else {
+ return false;
+ }
+ }
+
+ public function updateVoidStatus($realex_order_id, $status) {
+ $this->db->query("UPDATE `" . DB_PREFIX . "realex_order` SET `void_status` = '" . (int)$status . "' WHERE `realex_order_id` = '" . (int)$realex_order_id . "'");
+ }
+
+ public function capture($order_id, $amount) {
+ $realex_order = $this->getOrder($order_id);
+
+ if (!empty($realex_order) && $realex_order['capture_status'] == 0) {
+ $timestamp = strftime("%Y%m%d%H%M%S");
+ $merchant_id = $this->config->get('payment_realex_merchant_id');
+ $secret = $this->config->get('payment_realex_secret');
+
+ if ($realex_order['settle_type'] == 2) {
+ $this->logger('Capture hash construct: ' . $timestamp . '.' . $merchant_id . '.' . $realex_order['order_ref'] . '.' . (int)round($amount*100) . '.' . (string)$realex_order['currency_code'] . '.');
+
+ $tmp = $timestamp . '.' . $merchant_id . '.' . $realex_order['order_ref'] . '.' . (int)round($amount*100) . '.' . (string)$realex_order['currency_code'] . '.';
+ $hash = sha1($tmp);
+ $tmp = $hash . '.' . $secret;
+ $hash = sha1($tmp);
+
+ $settle_type = 'multisettle';
+ $xml_amount = '<amount currency="' . (string)$realex_order['currency_code'] . '">' . (int)round($amount*100) . '</amount>';
+ } else {
+ //$this->logger('Capture hash construct: ' . $timestamp . '.' . $merchant_id . '.' . $realex_order['order_ref'] . '...');
+ $this->logger('Capture hash construct: ' . $timestamp . '.' . $merchant_id . '.' . $realex_order['order_ref'] . '.' . (int)round($amount*100) . '.' . (string)$realex_order['currency_code'] . '.');
+
+ $tmp = $timestamp . '.' . $merchant_id . '.' . $realex_order['order_ref'] . '.' . (int)round($amount*100) . '.' . (string)$realex_order['currency_code'] . '.';
+ $hash = sha1($tmp);
+ $tmp = $hash . '.' . $secret;
+ $hash = sha1($tmp);
+
+ $settle_type = 'settle';
+ $xml_amount = '<amount currency="' . (string)$realex_order['currency_code'] . '">' . (int)round($amount*100) . '</amount>';
+ }
+
+ $xml = '';
+ $xml .= '<request type="' . $settle_type . '" timestamp="' . $timestamp . '">';
+ $xml .= '<merchantid>' . $merchant_id . '</merchantid>';
+ $xml .= '<account>' . $realex_order['account'] . '</account>';
+ $xml .= '<orderid>' . $realex_order['order_ref'] . '</orderid>';
+ $xml .= $xml_amount;
+ $xml .= '<pasref>' . $realex_order['pasref'] . '</pasref>';
+ $xml .= '<autosettle flag="1" />';
+ $xml .= '<authcode>' . $realex_order['authcode'] . '</authcode>';
+ $xml .= '<sha1hash>' . $hash . '</sha1hash>';
+ $xml .= '</request>';
+
+ $this->logger('Settle XML request:\r\n' . print_r(simplexml_load_string($xml), 1));
+
+ $ch = curl_init();
+ curl_setopt($ch, CURLOPT_URL, "https://epage.payandshop.com/epage-remote.cgi");
+ curl_setopt($ch, CURLOPT_POST, 1);
+ curl_setopt($ch, CURLOPT_USERAGENT, "OpenCart " . VERSION);
+ curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
+ curl_setopt($ch, CURLOPT_POSTFIELDS, $xml);
+ curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
+ $response = curl_exec ($ch);
+ curl_close ($ch);
+
+ return simplexml_load_string($response);
+ } else {
+ return false;
+ }
+ }
+
+ public function updateCaptureStatus($realex_order_id, $status) {
+ $this->db->query("UPDATE `" . DB_PREFIX . "realex_order` SET `capture_status` = '" . (int)$status . "' WHERE `realex_order_id` = '" . (int)$realex_order_id . "'");
+ }
+
+ public function updateForRebate($realex_order_id, $pas_ref, $order_ref) {
+ $this->db->query("UPDATE `" . DB_PREFIX . "realex_order` SET `order_ref_previous` = '_multisettle_" . $this->db->escape($order_ref) . "', `pasref_previous` = '" . $this->db->escape($pas_ref) . "' WHERE `realex_order_id` = '" . (int)$realex_order_id . "' LIMIT 1");
+ }
+
+ public function rebate($order_id, $amount) {
+ $realex_order = $this->getOrder($order_id);
+
+ if (!empty($realex_order) && $realex_order['rebate_status'] != 1) {
+ $timestamp = strftime("%Y%m%d%H%M%S");
+ $merchant_id = $this->config->get('payment_realex_merchant_id');
+ $secret = $this->config->get('payment_realex_secret');
+
+ if ($realex_order['settle_type'] == 2) {
+ $order_ref = '_multisettle_' . $realex_order['order_ref'];
+
+ if (empty($realex_order['pasref_previous'])) {
+ $pas_ref = $realex_order['pasref'];
+ } else {
+ $pas_ref = $realex_order['pasref_previous'];
+ }
+ } else {
+ $order_ref = $realex_order['order_ref'];
+ $pas_ref = $realex_order['pasref'];
+ }
+
+ $this->logger('Rebate hash construct: ' . $timestamp . '.' . $merchant_id . '.' . $order_ref . '.' . (int)round($amount*100) . '.' . $realex_order['currency_code'] . '.');
+
+ $tmp = $timestamp . '.' . $merchant_id . '.' . $order_ref . '.' . (int)round($amount*100) . '.' . $realex_order['currency_code'] . '.';
+ $hash = sha1($tmp);
+ $tmp = $hash . '.' . $secret;
+ $hash = sha1($tmp);
+
+ $rebate_hash = sha1($this->config->get('payment_realex_rebate_password'));
+
+ $xml = '';
+ $xml .= '<request type="rebate" timestamp="' . $timestamp . '">';
+ $xml .= '<merchantid>' . $merchant_id . '</merchantid>';
+ $xml .= '<account>' . $realex_order['account'] . '</account>';
+ $xml .= '<orderid>' . $order_ref . '</orderid>';
+ $xml .= '<pasref>' . $pas_ref . '</pasref>';
+ $xml .= '<authcode>' . $realex_order['authcode'] . '</authcode>';
+ $xml .= '<amount currency="' . (string)$realex_order['currency_code'] . '">' . (int)round($amount*100) . '</amount>';
+ $xml .= '<refundhash>' . $rebate_hash . '</refundhash>';
+ $xml .= '<sha1hash>' . $hash . '</sha1hash>';
+ $xml .= '</request>';
+
+ $this->logger('Rebate XML request:\r\n' . print_r(simplexml_load_string($xml), 1));
+
+ $ch = curl_init();
+ curl_setopt($ch, CURLOPT_URL, "https://epage.payandshop.com/epage-remote.cgi");
+ curl_setopt($ch, CURLOPT_POST, 1);
+ curl_setopt($ch, CURLOPT_USERAGENT, "OpenCart " . VERSION);
+ curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
+ curl_setopt($ch, CURLOPT_POSTFIELDS, $xml);
+ curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
+ $response = curl_exec ($ch);
+ curl_close ($ch);
+
+ return simplexml_load_string($response);
+ } else {
+ return false;
+ }
+ }
+
+ public function updateRebateStatus($realex_order_id, $status) {
+ $this->db->query("UPDATE `" . DB_PREFIX . "realex_order` SET `rebate_status` = '" . (int)$status . "' WHERE `realex_order_id` = '" . (int)$realex_order_id . "'");
+ }
+
+ public function getOrder($order_id) {
+ $this->logger('getOrder - ' . $order_id);
+
+ $qry = $this->db->query("SELECT * FROM `" . DB_PREFIX . "realex_order` WHERE `order_id` = '" . (int)$order_id . "' LIMIT 1");
+
+ if ($qry->num_rows) {
+ $order = $qry->row;
+ $order['transactions'] = $this->getTransactions($order['realex_order_id']);
+
+ $this->logger(print_r($order, 1));
+
+ return $order;
+ } else {
+ return false;
+ }
+ }
+
+ private function getTransactions($realex_order_id) {
+ $qry = $this->db->query("SELECT * FROM `" . DB_PREFIX . "realex_order_transaction` WHERE `realex_order_id` = '" . (int)$realex_order_id . "'");
+
+ if ($qry->num_rows) {
+ return $qry->rows;
+ } else {
+ return false;
+ }
+ }
+
+ public function addTransaction($realex_order_id, $type, $total) {
+ $this->db->query("INSERT INTO `" . DB_PREFIX . "realex_order_transaction` SET `realex_order_id` = '" . (int)$realex_order_id . "', `date_added` = now(), `type` = '" . $this->db->escape($type) . "', `amount` = '" . (float)$total . "'");
+ }
+
+ public function logger($message) {
+ if ($this->config->get('payment_realex_debug') == 1) {
+ $log = new Log('realex.log');
+ $log->write($message);
+ }
+ }
+
+ public function getTotalCaptured($realex_order_id) {
+ $query = $this->db->query("SELECT SUM(`amount`) AS `total` FROM `" . DB_PREFIX . "realex_order_transaction` WHERE `realex_order_id` = '" . (int)$realex_order_id . "' AND (`type` = 'payment' OR `type` = 'rebate')");
+
+ return (float)$query->row['total'];
+ }
+
+ public function getTotalRebated($realex_order_id) {
+ $query = $this->db->query("SELECT SUM(`amount`) AS `total` FROM `" . DB_PREFIX . "realex_order_transaction` WHERE `realex_order_id` = '" . (int)$realex_order_id . "' AND 'rebate'");
+
+ return (float)$query->row['total'];
+ }
+} \ No newline at end of file
diff --git a/public/admin/model/extension/payment/realex_remote.php b/public/admin/model/extension/payment/realex_remote.php
new file mode 100644
index 0000000..be40791
--- /dev/null
+++ b/public/admin/model/extension/payment/realex_remote.php
@@ -0,0 +1,260 @@
+<?php
+class ModelExtensionPaymentRealexRemote extends Model {
+ public function install() {
+ $this->db->query("
+ CREATE TABLE IF NOT EXISTS `" . DB_PREFIX . "realex_remote_order` (
+ `realex_remote_order_id` INT(11) NOT NULL AUTO_INCREMENT,
+ `order_id` INT(11) NOT NULL,
+ `order_ref` CHAR(50) NOT NULL,
+ `order_ref_previous` CHAR(50) NOT NULL,
+ `pasref` VARCHAR(50) NOT NULL,
+ `pasref_previous` VARCHAR(50) NOT NULL,
+ `date_added` DATETIME NOT NULL,
+ `date_modified` DATETIME NOT NULL,
+ `capture_status` INT(1) DEFAULT NULL,
+ `void_status` INT(1) DEFAULT NULL,
+ `settle_type` INT(1) DEFAULT NULL,
+ `rebate_status` INT(1) DEFAULT NULL,
+ `currency_code` CHAR(3) NOT NULL,
+ `authcode` VARCHAR(30) NOT NULL,
+ `account` VARCHAR(30) NOT NULL,
+ `total` DECIMAL( 10, 2 ) NOT NULL,
+ PRIMARY KEY (`realex_remote_order_id`)
+ ) ENGINE=MyISAM DEFAULT COLLATE=utf8_general_ci;");
+
+ $this->db->query("
+ CREATE TABLE IF NOT EXISTS `" . DB_PREFIX . "realex_remote_order_transaction` (
+ `realex_remote_order_transaction_id` INT(11) NOT NULL AUTO_INCREMENT,
+ `realex_remote_order_id` INT(11) NOT NULL,
+ `date_added` DATETIME NOT NULL,
+ `type` ENUM('auth', 'payment', 'rebate', 'void') DEFAULT NULL,
+ `amount` DECIMAL( 10, 2 ) NOT NULL,
+ PRIMARY KEY (`realex_remote_order_transaction_id`)
+ ) ENGINE=MyISAM DEFAULT COLLATE=utf8_general_ci;");
+ }
+
+ public function void($order_id) {
+ $realex_order = $this->getOrder($order_id);
+
+ if (!empty($realex_order)) {
+ $timestamp = strftime("%Y%m%d%H%M%S");
+ $merchant_id = $this->config->get('payment_realex_remote_merchant_id');
+ $secret = $this->config->get('payment_realex_remote_secret');
+
+ $this->logger('Void hash construct: ' . $timestamp . '.' . $merchant_id . '.' . $realex_order['order_ref'] . '...');
+
+ $tmp = $timestamp . '.' . $merchant_id . '.' . $realex_order['order_ref'] . '...';
+ $hash = sha1($tmp);
+ $tmp = $hash . '.' . $secret;
+ $hash = sha1($tmp);
+
+ $xml = '';
+ $xml .= '<request type="void" timestamp="' . $timestamp . '">';
+ $xml .= '<merchantid>' . $merchant_id . '</merchantid>';
+ $xml .= '<account>' . $realex_order['account'] . '</account>';
+ $xml .= '<orderid>' . $realex_order['order_ref'] . '</orderid>';
+ $xml .= '<pasref>' . $realex_order['pasref'] . '</pasref>';
+ $xml .= '<authcode>' . $realex_order['authcode'] . '</authcode>';
+ $xml .= '<sha1hash>' . $hash . '</sha1hash>';
+ $xml .= '</request>';
+
+ $this->logger('Void XML request:\r\n' . print_r(simplexml_load_string($xml), 1));
+
+ $ch = curl_init();
+ curl_setopt($ch, CURLOPT_URL, "https://epage.payandshop.com/epage-remote.cgi");
+ curl_setopt($ch, CURLOPT_POST, 1);
+ curl_setopt($ch, CURLOPT_USERAGENT, "OpenCart " . VERSION);
+ curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
+ curl_setopt($ch, CURLOPT_POSTFIELDS, $xml);
+ curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
+ $response = curl_exec ($ch);
+ curl_close ($ch);
+
+ return simplexml_load_string($response);
+ } else {
+ return false;
+ }
+ }
+
+ public function updateVoidStatus($realex_remote_order_id, $status) {
+ $this->db->query("UPDATE `" . DB_PREFIX . "realex_remote_order` SET `void_status` = '" . (int)$status . "' WHERE `realex_remote_order_id` = '" . (int)$realex_remote_order_id . "'");
+ }
+
+ public function capture($order_id, $amount) {
+ $realex_order = $this->getOrder($order_id);
+
+ if (!empty($realex_order) && $realex_order['capture_status'] == 0) {
+ $timestamp = strftime("%Y%m%d%H%M%S");
+ $merchant_id = $this->config->get('payment_realex_remote_merchant_id');
+ $secret = $this->config->get('payment_realex_remote_secret');
+
+ if ($realex_order['settle_type'] == 2) {
+ $this->logger('Capture hash construct: ' . $timestamp . '.' . $merchant_id . '.' . $realex_order['order_ref'] . '.' . (int)round($amount*100) . '.' . (string)$realex_order['currency_code'] . '.');
+
+ $tmp = $timestamp . '.' . $merchant_id . '.' . $realex_order['order_ref'] . '.' . (int)round($amount*100) . '.' . (string)$realex_order['currency_code'] . '.';
+ $hash = sha1($tmp);
+ $tmp = $hash . '.' . $secret;
+ $hash = sha1($tmp);
+
+ $settle_type = 'multisettle';
+ $xml_amount = '<amount currency="' . (string)$realex_order['currency_code'] . '">' . (int)round($amount*100) . '</amount>';
+ } else {
+ //$this->logger('Capture hash construct: ' . $timestamp . '.' . $merchant_id . '.' . $realex_order['order_ref'] . '...');
+ $this->logger('Capture hash construct: ' . $timestamp . '.' . $merchant_id . '.' . $realex_order['order_ref'] . '.' . (int)round($amount*100) . '.' . (string)$realex_order['currency_code'] . '.');
+
+ $tmp = $timestamp . '.' . $merchant_id . '.' . $realex_order['order_ref'] . '.' . (int)round($amount*100) . '.' . (string)$realex_order['currency_code'] . '.';
+ $hash = sha1($tmp);
+ $tmp = $hash . '.' . $secret;
+ $hash = sha1($tmp);
+
+ $settle_type = 'settle';
+ $xml_amount = '<amount currency="' . (string)$realex_order['currency_code'] . '">' . (int)round($amount*100) . '</amount>';
+ }
+
+ $xml = '';
+ $xml .= '<request type="' . $settle_type . '" timestamp="' . $timestamp . '">';
+ $xml .= '<merchantid>' . $merchant_id . '</merchantid>';
+ $xml .= '<account>' . $realex_order['account'] . '</account>';
+ $xml .= '<orderid>' . $realex_order['order_ref'] . '</orderid>';
+ $xml .= $xml_amount;
+ $xml .= '<pasref>' . $realex_order['pasref'] . '</pasref>';
+ $xml .= '<authcode>' . $realex_order['authcode'] . '</authcode>';
+ $xml .= '<sha1hash>' . $hash . '</sha1hash>';
+ $xml .= '</request>';
+
+ $this->logger('Settle XML request:\r\n' . print_r(simplexml_load_string($xml), 1));
+
+ $ch = curl_init();
+ curl_setopt($ch, CURLOPT_URL, "https://epage.payandshop.com/epage-remote.cgi");
+ curl_setopt($ch, CURLOPT_POST, 1);
+ curl_setopt($ch, CURLOPT_USERAGENT, "OpenCart " . VERSION);
+ curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
+ curl_setopt($ch, CURLOPT_POSTFIELDS, $xml);
+ curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
+ $response = curl_exec ($ch);
+ curl_close ($ch);
+
+ return simplexml_load_string($response);
+ } else {
+ return false;
+ }
+ }
+
+ public function updateCaptureStatus($realex_remote_order_id, $status) {
+ $this->db->query("UPDATE `" . DB_PREFIX . "realex_remote_order` SET `capture_status` = '" . (int)$status . "' WHERE `realex_remote_order_id` = '" . (int)$realex_remote_order_id . "'");
+ }
+
+ public function updateForRebate($realex_remote_order_id, $pas_ref, $order_ref) {
+ $this->db->query("UPDATE `" . DB_PREFIX . "realex_remote_order` SET `order_ref_previous` = '_multisettle_" . $this->db->escape($order_ref) . "', `pasref_previous` = '" . $this->db->escape($pas_ref) . "' WHERE `realex_remote_order_id` = '" . (int)$realex_remote_order_id . "' LIMIT 1");
+ }
+
+ public function rebate($order_id, $amount) {
+ $realex_order = $this->getOrder($order_id);
+
+ if (!empty($realex_order) && $realex_order['rebate_status'] != 1) {
+ $timestamp = strftime("%Y%m%d%H%M%S");
+ $merchant_id = $this->config->get('payment_realex_remote_merchant_id');
+ $secret = $this->config->get('payment_realex_remote_secret');
+
+ if ($realex_order['settle_type'] == 2) {
+ $order_ref = '_multisettle_' . $realex_order['order_ref'];
+
+ if (empty($realex_order['pasref_previous'])) {
+ $pas_ref = $realex_order['pasref'];
+ } else {
+ $pas_ref = $realex_order['pasref_previous'];
+ }
+ } else {
+ $order_ref = $realex_order['order_ref'];
+ $pas_ref = $realex_order['pasref'];
+ }
+
+ $this->logger('Rebate hash construct: ' . $timestamp . '.' . $merchant_id . '.' . $order_ref . '.' . (int)round($amount*100) . '.' . $realex_order['currency_code'] . '.');
+
+ $tmp = $timestamp . '.' . $merchant_id . '.' . $order_ref . '.' . (int)round($amount*100) . '.' . $realex_order['currency_code'] . '.';
+ $hash = sha1($tmp);
+ $tmp = $hash . '.' . $secret;
+ $hash = sha1($tmp);
+
+ $rebatehash = sha1($this->config->get('payment_realex_remote_rebate_password'));
+
+ $xml = '';
+ $xml .= '<request type="rebate" timestamp="' . $timestamp . '">';
+ $xml .= '<merchantid>' . $merchant_id . '</merchantid>';
+ $xml .= '<account>' . $realex_order['account'] . '</account>';
+ $xml .= '<orderid>' . $order_ref . '</orderid>';
+ $xml .= '<pasref>' . $pas_ref . '</pasref>';
+ $xml .= '<authcode>' . $realex_order['authcode'] . '</authcode>';
+ $xml .= '<amount currency="' . (string)$realex_order['currency_code'] . '">' . (int)round($amount*100) . '</amount>';
+ $xml .= '<refundhash>' . $rebatehash . '</refundhash>';
+ $xml .= '<sha1hash>' . $hash . '</sha1hash>';
+ $xml .= '</request>';
+
+ $this->logger('Rebate XML request:\r\n' . print_r(simplexml_load_string($xml), 1));
+
+ $ch = curl_init();
+ curl_setopt($ch, CURLOPT_URL, "https://epage.payandshop.com/epage-remote.cgi");
+ curl_setopt($ch, CURLOPT_POST, 1);
+ curl_setopt($ch, CURLOPT_USERAGENT, "OpenCart " . VERSION);
+ curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
+ curl_setopt($ch, CURLOPT_POSTFIELDS, $xml);
+ curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
+ $response = curl_exec ($ch);
+ curl_close ($ch);
+
+ return simplexml_load_string($response);
+ } else {
+ return false;
+ }
+ }
+
+ public function updateRebateStatus($realex_remote_order_id, $status) {
+ $this->db->query("UPDATE `" . DB_PREFIX . "realex_remote_order` SET `rebate_status` = '" . (int)$status . "' WHERE `realex_remote_order_id` = '" . (int)$realex_remote_order_id . "'");
+ }
+
+ public function getOrder($order_id) {
+ $qry = $this->db->query("SELECT * FROM `" . DB_PREFIX . "realex_remote_order` WHERE `order_id` = '" . (int)$order_id . "' LIMIT 1");
+
+ if ($qry->num_rows) {
+ $order = $qry->row;
+ $order['transactions'] = $this->getTransactions($order['realex_remote_order_id']);
+
+ return $order;
+ } else {
+ return false;
+ }
+ }
+
+ private function getTransactions($realex_remote_order_id) {
+ $qry = $this->db->query("SELECT * FROM `" . DB_PREFIX . "realex_remote_order_transaction` WHERE `realex_remote_order_id` = '" . (int)$realex_remote_order_id . "'");
+
+ if ($qry->num_rows) {
+ return $qry->rows;
+ } else {
+ return false;
+ }
+ }
+
+ public function addTransaction($realex_remote_order_id, $type, $total) {
+ $this->db->query("INSERT INTO `" . DB_PREFIX . "realex_remote_order_transaction` SET `realex_remote_order_id` = '" . (int)$realex_remote_order_id . "', `date_added` = now(), `type` = '" . $this->db->escape($type) . "', `amount` = '" . (float)$total . "'");
+ }
+
+ public function logger($message) {
+ if ($this->config->get('payment_realex_remote_debug') == 1) {
+ $log = new Log('realex_remote.log');
+ $log->write($message);
+ }
+ }
+
+ public function getTotalCaptured($realex_order_id) {
+ $query = $this->db->query("SELECT SUM(`amount`) AS `total` FROM `" . DB_PREFIX . "realex_remote_order_transaction` WHERE `realex_remote_order_id` = '" . (int)$realex_order_id . "' AND (`type` = 'payment' OR `type` = 'rebate')");
+
+ return (float)$query->row['total'];
+ }
+
+ public function getTotalRebated($realex_order_id) {
+ $query = $this->db->query("SELECT SUM(`amount`) AS `total` FROM `" . DB_PREFIX . "realex_remote_order_transaction` WHERE `realex_remote_order_id` = '" . (int)$realex_order_id . "' AND 'rebate'");
+
+ return (double)$query->row['total'];
+ }
+} \ No newline at end of file
diff --git a/public/admin/model/extension/payment/sagepay_direct.php b/public/admin/model/extension/payment/sagepay_direct.php
new file mode 100644
index 0000000..370e4f0
--- /dev/null
+++ b/public/admin/model/extension/payment/sagepay_direct.php
@@ -0,0 +1,265 @@
+<?php
+class ModelExtensionPaymentSagepayDirect extends Model {
+ public function install() {
+ $this->db->query("
+ CREATE TABLE IF NOT EXISTS `" . DB_PREFIX . "sagepay_direct_order` (
+ `sagepay_direct_order_id` INT(11) NOT NULL AUTO_INCREMENT,
+ `order_id` INT(11) NOT NULL,
+ `VPSTxId` VARCHAR(50),
+ `VendorTxCode` VARCHAR(50) NOT NULL,
+ `SecurityKey` CHAR(50) NOT NULL,
+ `TxAuthNo` INT(50),
+ `date_added` DATETIME NOT NULL,
+ `date_modified` DATETIME NOT NULL,
+ `release_status` INT(1) DEFAULT NULL,
+ `void_status` INT(1) DEFAULT NULL,
+ `settle_type` INT(1) DEFAULT NULL,
+ `rebate_status` INT(1) DEFAULT NULL,
+ `currency_code` CHAR(3) NOT NULL,
+ `total` DECIMAL( 10, 2 ) NOT NULL,
+ `card_id` INT(11),
+ PRIMARY KEY (`sagepay_direct_order_id`)
+ ) ENGINE=MyISAM DEFAULT COLLATE=utf8_general_ci;");
+
+ $this->db->query("
+ CREATE TABLE IF NOT EXISTS `" . DB_PREFIX . "sagepay_direct_order_transaction` (
+ `sagepay_direct_order_transaction_id` INT(11) NOT NULL AUTO_INCREMENT,
+ `sagepay_direct_order_id` INT(11) NOT NULL,
+ `date_added` DATETIME NOT NULL,
+ `type` ENUM('auth', 'payment', 'rebate', 'void') DEFAULT NULL,
+ `amount` DECIMAL( 10, 2 ) NOT NULL,
+ PRIMARY KEY (`sagepay_direct_order_transaction_id`)
+ ) ENGINE=MyISAM DEFAULT COLLATE=utf8_general_ci;");
+
+ $this->db->query("
+ CREATE TABLE IF NOT EXISTS `" . DB_PREFIX . "sagepay_direct_order_recurring` (
+ `sagepay_direct_order_recurring_id` INT(11) NOT NULL AUTO_INCREMENT,
+ `order_id` INT(11) NOT NULL,
+ `order_recurring_id` INT(11) NOT NULL,
+ `VPSTxId` VARCHAR(50),
+ `VendorTxCode` VARCHAR(50) NOT NULL,
+ `SecurityKey` CHAR(50) NOT NULL,
+ `TxAuthNo` INT(50),
+ `date_added` DATETIME NOT NULL,
+ `date_modified` DATETIME NOT NULL,
+ `next_payment` DATETIME NOT NULL,
+ `trial_end` datetime DEFAULT NULL,
+ `subscription_end` datetime DEFAULT NULL,
+ `currency_code` CHAR(3) NOT NULL,
+ `total` DECIMAL( 10, 2 ) NOT NULL,
+ PRIMARY KEY (`sagepay_direct_order_recurring_id`)
+ ) ENGINE=MyISAM DEFAULT COLLATE=utf8_general_ci;");
+
+ $this->db->query("
+ CREATE TABLE IF NOT EXISTS `" . DB_PREFIX . "sagepay_direct_card` (
+ `card_id` INT(11) NOT NULL AUTO_INCREMENT,
+ `customer_id` INT(11) NOT NULL,
+ `token` VARCHAR(50) NOT NULL,
+ `digits` VARCHAR(4) NOT NULL,
+ `expiry` VARCHAR(5) NOT NULL,
+ `type` VARCHAR(50) NOT NULL,
+ PRIMARY KEY (`card_id`)
+ ) ENGINE=MyISAM DEFAULT COLLATE=utf8_general_ci;");
+ }
+
+ public function uninstall() {
+ $this->db->query("DROP TABLE IF EXISTS `" . DB_PREFIX . "sagepay_direct_order`;");
+ $this->db->query("DROP TABLE IF EXISTS `" . DB_PREFIX . "sagepay_direct_order_transaction`;");
+ $this->db->query("DROP TABLE IF EXISTS `" . DB_PREFIX . "sagepay_direct_order_recurring`;");
+ $this->db->query("DROP TABLE IF EXISTS `" . DB_PREFIX . "sagepay_direct_card`;");
+ }
+
+ public function void($order_id) {
+ $sagepay_direct_order = $this->getOrder($order_id);
+
+ if (!empty($sagepay_direct_order) && $sagepay_direct_order['release_status'] == 0) {
+
+ $void_data = array();
+
+ if ($this->config->get('payment_sagepay_direct_test') == 'live') {
+ $url = 'https://live.sagepay.com/gateway/service/void.vsp';
+ $void_data['VPSProtocol'] = '3.00';
+ } elseif ($this->config->get('payment_sagepay_direct_test') == 'test') {
+ $url = 'https://test.sagepay.com/gateway/service/void.vsp';
+ $void_data['VPSProtocol'] = '3.00';
+ } elseif ($this->config->get('payment_sagepay_direct_test') == 'sim') {
+ $url = 'https://test.sagepay.com/Simulator/VSPServerGateway.asp?Service=VendorVoidTx';
+ $void_data['VPSProtocol'] = '2.23';
+ }
+
+ $void_data['TxType'] = 'VOID';
+ $void_data['Vendor'] = $this->config->get('payment_sagepay_direct_vendor');
+ $void_data['VendorTxCode'] = $sagepay_direct_order['VendorTxCode'];
+ $void_data['VPSTxId'] = $sagepay_direct_order['VPSTxId'];
+ $void_data['SecurityKey'] = $sagepay_direct_order['SecurityKey'];
+ $void_data['TxAuthNo'] = $sagepay_direct_order['TxAuthNo'];
+
+ $response_data = $this->sendCurl($url, $void_data);
+
+ return $response_data;
+ } else {
+ return false;
+ }
+ }
+
+ public function updateVoidStatus($sagepay_direct_order_id, $status) {
+ $this->db->query("UPDATE `" . DB_PREFIX . "sagepay_direct_order` SET `void_status` = '" . (int)$status . "' WHERE `sagepay_direct_order_id` = '" . (int)$sagepay_direct_order_id . "'");
+ }
+
+ public function release($order_id, $amount) {
+ $sagepay_direct_order = $this->getOrder($order_id);
+ $total_released = $this->getTotalReleased($sagepay_direct_order['sagepay_direct_order_id']);
+
+ if (!empty($sagepay_direct_order) && $sagepay_direct_order['release_status'] == 0 && ($total_released + $amount <= $sagepay_direct_order['total'])) {
+ $release_data = array();
+
+ if ($this->config->get('payment_sagepay_direct_test') == 'live') {
+ $url = 'https://live.sagepay.com/gateway/service/release.vsp';
+ $release_data['VPSProtocol'] = '3.00';
+ } elseif ($this->config->get('payment_sagepay_direct_test') == 'test') {
+ $url = 'https://test.sagepay.com/gateway/service/release.vsp';
+ $release_data['VPSProtocol'] = '3.00';
+ } elseif ($this->config->get('payment_sagepay_direct_test') == 'sim') {
+ $url = 'https://test.sagepay.com/Simulator/VSPServerGateway.asp?Service=VendorReleaseTx';
+ $release_data['VPSProtocol'] = '2.23';
+ }
+
+ $release_data['TxType'] = 'RELEASE';
+ $release_data['Vendor'] = $this->config->get('payment_sagepay_direct_vendor');
+ $release_data['VendorTxCode'] = $sagepay_direct_order['VendorTxCode'];
+ $release_data['VPSTxId'] = $sagepay_direct_order['VPSTxId'];
+ $release_data['SecurityKey'] = $sagepay_direct_order['SecurityKey'];
+ $release_data['TxAuthNo'] = $sagepay_direct_order['TxAuthNo'];
+ $release_data['Amount'] = $amount;
+
+ $response_data = $this->sendCurl($url, $release_data);
+
+ return $response_data;
+ } else {
+ return false;
+ }
+ }
+
+ public function updateReleaseStatus($sagepay_direct_order_id, $status) {
+ $this->db->query("UPDATE `" . DB_PREFIX . "sagepay_direct_order` SET `release_status` = '" . (int)$status . "' WHERE `sagepay_direct_order_id` = '" . (int)$sagepay_direct_order_id . "'");
+ }
+
+ public function rebate($order_id, $amount) {
+ $sagepay_direct_order = $this->getOrder($order_id);
+
+ if (!empty($sagepay_direct_order) && $sagepay_direct_order['rebate_status'] != 1) {
+
+ $refund_data = array();
+
+ if ($this->config->get('payment_sagepay_direct_test') == 'live') {
+ $url = 'https://live.sagepay.com/gateway/service/refund.vsp';
+ $refund_data['VPSProtocol'] = '3.00';
+ } elseif ($this->config->get('payment_sagepay_direct_test') == 'test') {
+ $url = 'https://test.sagepay.com/gateway/service/refund.vsp';
+ $refund_data['VPSProtocol'] = '3.00';
+ } elseif ($this->config->get('payment_sagepay_direct_test') == 'sim') {
+ $url = 'https://test.sagepay.com/Simulator/VSPServerGateway.asp?Service=VendorRefundTx';
+ $refund_data['VPSProtocol'] = '2.23';
+ }
+
+ $refund_data['TxType'] = 'REFUND';
+ $refund_data['Vendor'] = $this->config->get('payment_sagepay_direct_vendor');
+ $refund_data['VendorTxCode'] = $sagepay_direct_order['sagepay_direct_order_id'] . rand();
+ $refund_data['Amount'] = $amount;
+ $refund_data['Currency'] = $sagepay_direct_order['currency_code'];
+ $refund_data['Description'] = substr($this->config->get('config_name'), 0, 100);
+ $refund_data['RelatedVPSTxId'] = $sagepay_direct_order['VPSTxId'];
+ $refund_data['RelatedVendorTxCode'] = $sagepay_direct_order['VendorTxCode'];
+ $refund_data['RelatedSecurityKey'] = $sagepay_direct_order['SecurityKey'];
+ $refund_data['RelatedTxAuthNo'] = $sagepay_direct_order['TxAuthNo'];
+
+ $response_data = $this->sendCurl($url, $refund_data);
+
+ return $response_data;
+ } else {
+ return false;
+ }
+ }
+
+ public function updateRebateStatus($sagepay_direct_order_id, $status) {
+ $this->db->query("UPDATE `" . DB_PREFIX . "sagepay_direct_order` SET `rebate_status` = '" . (int)$status . "' WHERE `sagepay_direct_order_id` = '" . (int)$sagepay_direct_order_id . "'");
+ }
+
+ public function getOrder($order_id) {
+
+ $qry = $this->db->query("SELECT * FROM `" . DB_PREFIX . "sagepay_direct_order` WHERE `order_id` = '" . (int)$order_id . "' LIMIT 1");
+
+ if ($qry->num_rows) {
+ $order = $qry->row;
+ $order['transactions'] = $this->getTransactions($order['sagepay_direct_order_id']);
+
+ return $order;
+ } else {
+ return false;
+ }
+ }
+
+ private function getTransactions($sagepay_direct_order_id) {
+ $qry = $this->db->query("SELECT * FROM `" . DB_PREFIX . "sagepay_direct_order_transaction` WHERE `sagepay_direct_order_id` = '" . (int)$sagepay_direct_order_id . "'");
+
+ if ($qry->num_rows) {
+ return $qry->rows;
+ } else {
+ return false;
+ }
+ }
+
+ public function addTransaction($sagepay_direct_order_id, $type, $total) {
+ $this->db->query("INSERT INTO `" . DB_PREFIX . "sagepay_direct_order_transaction` SET `sagepay_direct_order_id` = '" . (int)$sagepay_direct_order_id . "', `date_added` = now(), `type` = '" . $this->db->escape($type) . "', `amount` = '" . (float)$total . "'");
+ }
+
+ public function getTotalReleased($sagepay_direct_order_id) {
+ $query = $this->db->query("SELECT SUM(`amount`) AS `total` FROM `" . DB_PREFIX . "sagepay_direct_order_transaction` WHERE `sagepay_direct_order_id` = '" . (int)$sagepay_direct_order_id . "' AND (`type` = 'payment' OR `type` = 'rebate')");
+
+ return (float)$query->row['total'];
+ }
+
+ public function getTotalRebated($sagepay_direct_order_id) {
+ $query = $this->db->query("SELECT SUM(`amount`) AS `total` FROM `" . DB_PREFIX . "sagepay_direct_order_transaction` WHERE `sagepay_direct_order_id` = '" . (int)$sagepay_direct_order_id . "' AND 'rebate'");
+
+ return (float)$query->row['total'];
+ }
+
+ public function sendCurl($url, $payment_data) {
+ $curl = curl_init($url);
+
+ curl_setopt($curl, CURLOPT_PORT, 443);
+ curl_setopt($curl, CURLOPT_HEADER, 0);
+ curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, 0);
+ curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
+ curl_setopt($curl, CURLOPT_FOLLOWLOCATION, false);
+ curl_setopt($curl, CURLOPT_FORBID_REUSE, 1);
+ curl_setopt($curl, CURLOPT_FRESH_CONNECT, 1);
+ curl_setopt($curl, CURLOPT_POST, 1);
+ curl_setopt($curl, CURLOPT_POSTFIELDS, http_build_query($payment_data));
+
+ $response = curl_exec($curl);
+
+ curl_close($curl);
+
+ $response_info = explode(chr(10), $response);
+
+ foreach ($response_info as $string) {
+ if (strpos($string, '=') && isset($i)) {
+ $parts = explode('=', $string, 2);
+ $data['RepeatResponseData_' . $i][trim($parts[0])] = trim($parts[1]);
+ } elseif (strpos($string, '=')) {
+ $parts = explode('=', $string, 2);
+ $data[trim($parts[0])] = trim($parts[1]);
+ }
+ }
+ return $data;
+ }
+
+ public function logger($title, $data) {
+ if ($this->config->get('payment_sagepay_direct_debug')) {
+ $log = new Log('sagepay_direct.log');
+ $log->write($title . ': ' . print_r($data, 1));
+ }
+ }
+}
diff --git a/public/admin/model/extension/payment/sagepay_server.php b/public/admin/model/extension/payment/sagepay_server.php
new file mode 100644
index 0000000..8dacbd9
--- /dev/null
+++ b/public/admin/model/extension/payment/sagepay_server.php
@@ -0,0 +1,266 @@
+<?php
+class ModelExtensionPaymentSagepayServer extends Model {
+ public function install() {
+ $this->db->query("
+ CREATE TABLE IF NOT EXISTS `" . DB_PREFIX . "sagepay_server_order` (
+ `sagepay_server_order_id` INT(11) NOT NULL AUTO_INCREMENT,
+ `order_id` INT(11) NOT NULL,
+ `customer_id` INT(11) NOT NULL,
+ `VPSTxId` VARCHAR(50),
+ `VendorTxCode` VARCHAR(50) NOT NULL,
+ `SecurityKey` CHAR(50) NOT NULL,
+ `TxAuthNo` INT(50),
+ `date_added` DATETIME NOT NULL,
+ `date_modified` DATETIME NOT NULL,
+ `release_status` INT(1) DEFAULT NULL,
+ `void_status` INT(1) DEFAULT NULL,
+ `settle_type` INT(1) DEFAULT NULL,
+ `rebate_status` INT(1) DEFAULT NULL,
+ `currency_code` CHAR(3) NOT NULL,
+ `total` DECIMAL( 10, 2 ) NOT NULL,
+ PRIMARY KEY (`sagepay_server_order_id`)
+ ) ENGINE=MyISAM DEFAULT COLLATE=utf8_general_ci;");
+
+ $this->db->query("
+ CREATE TABLE IF NOT EXISTS `" . DB_PREFIX . "sagepay_server_order_transaction` (
+ `sagepay_server_order_transaction_id` INT(11) NOT NULL AUTO_INCREMENT,
+ `sagepay_server_order_id` INT(11) NOT NULL,
+ `date_added` DATETIME NOT NULL,
+ `type` ENUM('auth', 'payment', 'rebate', 'void') DEFAULT NULL,
+ `amount` DECIMAL( 10, 2 ) NOT NULL,
+ PRIMARY KEY (`sagepay_server_order_transaction_id`)
+ ) ENGINE=MyISAM DEFAULT COLLATE=utf8_general_ci;");
+
+ $this->db->query("
+ CREATE TABLE IF NOT EXISTS `" . DB_PREFIX . "sagepay_server_order_recurring` (
+ `sagepay_server_order_recurring_id` INT(11) NOT NULL AUTO_INCREMENT,
+ `order_id` INT(11) NOT NULL,
+ `order_recurring_id` INT(11) NOT NULL,
+ `VPSTxId` VARCHAR(50),
+ `VendorTxCode` VARCHAR(50) NOT NULL,
+ `SecurityKey` CHAR(50) NOT NULL,
+ `TxAuthNo` INT(50),
+ `date_added` DATETIME NOT NULL,
+ `date_modified` DATETIME NOT NULL,
+ `next_payment` DATETIME NOT NULL,
+ `trial_end` datetime DEFAULT NULL,
+ `subscription_end` datetime DEFAULT NULL,
+ `currency_code` CHAR(3) NOT NULL,
+ `total` DECIMAL( 10, 2 ) NOT NULL,
+ PRIMARY KEY (`sagepay_server_order_recurring_id`)
+ ) ENGINE=MyISAM DEFAULT COLLATE=utf8_general_ci;");
+
+ $this->db->query("
+ CREATE TABLE IF NOT EXISTS `" . DB_PREFIX . "sagepay_server_card` (
+ `card_id` INT(11) NOT NULL AUTO_INCREMENT,
+ `customer_id` INT(11) NOT NULL,
+ `order_id` INT(11) NOT NULL,
+ `token` VARCHAR(50) NOT NULL,
+ `digits` VARCHAR(4) NOT NULL,
+ `expiry` VARCHAR(5) NOT NULL,
+ `type` VARCHAR(50) NOT NULL,
+ PRIMARY KEY (`card_id`)
+ ) ENGINE=MyISAM DEFAULT COLLATE=utf8_general_ci;");
+ }
+
+ public function uninstall() {
+ $this->db->query("DROP TABLE IF EXISTS `" . DB_PREFIX . "sagepay_server_order`;");
+ $this->db->query("DROP TABLE IF EXISTS `" . DB_PREFIX . "sagepay_server_order_transaction`;");
+ $this->db->query("DROP TABLE IF EXISTS `" . DB_PREFIX . "sagepay_server_order_recurring`;");
+ $this->db->query("DROP TABLE IF EXISTS `" . DB_PREFIX . "sagepay_server_card`;");
+ }
+
+ public function void($order_id) {
+ $sagepay_server_order = $this->getOrder($order_id);
+
+ if (!empty($sagepay_server_order) && $sagepay_server_order['release_status'] == 0) {
+
+ $void_data = array();
+
+ if ($this->config->get('payment_sagepay_server_test') == 'live') {
+ $url = 'https://live.sagepay.com/gateway/service/void.vsp';
+ $void_data['VPSProtocol'] = '3.00';
+ } elseif ($this->config->get('payment_sagepay_server_test') == 'test') {
+ $url = 'https://test.sagepay.com/gateway/service/void.vsp';
+ $void_data['VPSProtocol'] = '3.00';
+ } elseif ($this->config->get('payment_sagepay_server_test') == 'sim') {
+ $url = 'https://test.sagepay.com/Simulator/VSPServerGateway.asp?Service=VendorVoidTx';
+ $void_data['VPSProtocol'] = '2.23';
+ }
+
+ $void_data['TxType'] = 'VOID';
+ $void_data['Vendor'] = $this->config->get('payment_sagepay_server_vendor');
+ $void_data['VendorTxCode'] = $sagepay_server_order['VendorTxCode'];
+ $void_data['VPSTxId'] = $sagepay_server_order['VPSTxId'];
+ $void_data['SecurityKey'] = $sagepay_server_order['SecurityKey'];
+ $void_data['TxAuthNo'] = $sagepay_server_order['TxAuthNo'];
+
+ $response_data = $this->sendCurl($url, $void_data);
+
+ return $response_data;
+ } else {
+ return false;
+ }
+ }
+
+ public function updateVoidStatus($sagepay_server_order_id, $status) {
+ $this->db->query("UPDATE `" . DB_PREFIX . "sagepay_server_order` SET `void_status` = '" . (int)$status . "' WHERE `sagepay_server_order_id` = '" . (int)$sagepay_server_order_id . "'");
+ }
+
+ public function release($order_id, $amount) {
+ $sagepay_server_order = $this->getOrder($order_id);
+ $total_released = $this->getTotalReleased($sagepay_server_order['sagepay_server_order_id']);
+
+ if (!empty($sagepay_server_order) && $sagepay_server_order['release_status'] == 0 && ($total_released + $amount <= $sagepay_server_order['total'])) {
+ $release_data = array();
+
+ if ($this->config->get('payment_sagepay_server_test') == 'live') {
+ $url = 'https://live.sagepay.com/gateway/service/release.vsp';
+ $release_data['VPSProtocol'] = '3.00';
+ } elseif ($this->config->get('payment_sagepay_server_test') == 'test') {
+ $url = 'https://test.sagepay.com/gateway/service/release.vsp';
+ $release_data['VPSProtocol'] = '3.00';
+ } elseif ($this->config->get('payment_sagepay_server_test') == 'sim') {
+ $url = 'https://test.sagepay.com/Simulator/VSPServerGateway.asp?Service=VendorReleaseTx';
+ $release_data['VPSProtocol'] = '2.23';
+ }
+
+ $release_data['TxType'] = 'RELEASE';
+ $release_data['Vendor'] = $this->config->get('payment_sagepay_server_vendor');
+ $release_data['VendorTxCode'] = $sagepay_server_order['VendorTxCode'];
+ $release_data['VPSTxId'] = $sagepay_server_order['VPSTxId'];
+ $release_data['SecurityKey'] = $sagepay_server_order['SecurityKey'];
+ $release_data['TxAuthNo'] = $sagepay_server_order['TxAuthNo'];
+ $release_data['Amount'] = $amount;
+
+ $response_data = $this->sendCurl($url, $release_data);
+
+ return $response_data;
+ } else {
+ return false;
+ }
+ }
+
+ public function updateReleaseStatus($sagepay_server_order_id, $status) {
+ $this->db->query("UPDATE `" . DB_PREFIX . "sagepay_server_order` SET `release_status` = '" . (int)$status . "' WHERE `sagepay_server_order_id` = '" . (int)$sagepay_server_order_id . "'");
+ }
+
+ public function updateForRebate($sagepay_server_order_id, $order_ref) {
+ $this->db->query("UPDATE `" . DB_PREFIX . "sagepay_server_order` SET `order_ref_previous` = '_multisettle_" . $this->db->escape($order_ref) . "' WHERE `sagepay_server_order_id` = '" . (int)$sagepay_server_order_id . "' LIMIT 1");
+ }
+
+ public function rebate($order_id, $amount) {
+ $sagepay_server_order = $this->getOrder($order_id);
+
+ if (!empty($sagepay_server_order) && $sagepay_server_order['rebate_status'] != 1) {
+
+ $refund_data = array();
+
+ if ($this->config->get('payment_sagepay_server_test') == 'live') {
+ $url = 'https://live.sagepay.com/gateway/service/refund.vsp';
+ $refund_data['VPSProtocol'] = '3.00';
+ } elseif ($this->config->get('payment_sagepay_server_test') == 'test') {
+ $url = 'https://test.sagepay.com/gateway/service/refund.vsp';
+ $refund_data['VPSProtocol'] = '3.00';
+ } elseif ($this->config->get('payment_sagepay_server_test') == 'sim') {
+ $url = 'https://test.sagepay.com/Simulator/VSPServerGateway.asp?Service=VendorRefundTx';
+ $refund_data['VPSProtocol'] = '2.23';
+ }
+
+ $refund_data['TxType'] = 'REFUND';
+ $refund_data['Vendor'] = $this->config->get('payment_sagepay_server_vendor');
+ $refund_data['VendorTxCode'] = $sagepay_server_order['sagepay_server_order_id'] . rand();
+ $refund_data['Amount'] = $amount;
+ $refund_data['Currency'] = $sagepay_server_order['currency_code'];
+ $refund_data['Description'] = substr($this->config->get('config_name'), 0, 100);
+ $refund_data['RelatedVPSTxId'] = $sagepay_server_order['VPSTxId'];
+ $refund_data['RelatedVendorTxCode'] = $sagepay_server_order['VendorTxCode'];
+ $refund_data['RelatedSecurityKey'] = $sagepay_server_order['SecurityKey'];
+ $refund_data['RelatedTxAuthNo'] = $sagepay_server_order['TxAuthNo'];
+
+ $response_data = $this->sendCurl($url, $refund_data);
+
+ return $response_data;
+ } else {
+ return false;
+ }
+ }
+
+ public function getOrder($order_id) {
+
+ $qry = $this->db->query("SELECT * FROM `" . DB_PREFIX . "sagepay_server_order` WHERE `order_id` = '" . (int)$order_id . "' LIMIT 1");
+
+ if ($qry->num_rows) {
+ $order = $qry->row;
+ $order['transactions'] = $this->getTransactions($order['sagepay_server_order_id']);
+
+ return $order;
+ } else {
+ return false;
+ }
+ }
+
+ private function getTransactions($sagepay_server_order_id) {
+ $qry = $this->db->query("SELECT * FROM `" . DB_PREFIX . "sagepay_server_order_transaction` WHERE `sagepay_server_order_id` = '" . (int)$sagepay_server_order_id . "'");
+
+ if ($qry->num_rows) {
+ return $qry->rows;
+ } else {
+ return false;
+ }
+ }
+
+ public function addTransaction($sagepay_server_order_id, $type, $total) {
+ $this->db->query("INSERT INTO `" . DB_PREFIX . "sagepay_server_order_transaction` SET `sagepay_server_order_id` = '" . (int)$sagepay_server_order_id . "', `date_added` = now(), `type` = '" . $this->db->escape($type) . "', `amount` = '" . (float)$total . "'");
+ }
+
+ public function getTotalReleased($sagepay_server_order_id) {
+ $query = $this->db->query("SELECT SUM(`amount`) AS `total` FROM `" . DB_PREFIX . "sagepay_server_order_transaction` WHERE `sagepay_server_order_id` = '" . (int)$sagepay_server_order_id . "' AND (`type` = 'payment' OR `type` = 'rebate')");
+
+ return (float)$query->row['total'];
+ }
+
+ public function getTotalRebated($sagepay_server_order_id) {
+ $query = $this->db->query("SELECT SUM(`amount`) AS `total` FROM `" . DB_PREFIX . "sagepay_server_order_transaction` WHERE `sagepay_server_order_id` = '" . (int)$sagepay_server_order_id . "' AND 'rebate'");
+
+ return (float)$query->row['total'];
+ }
+
+ public function sendCurl($url, $payment_data) {
+ $curl = curl_init($url);
+
+ curl_setopt($curl, CURLOPT_PORT, 443);
+ curl_setopt($curl, CURLOPT_HEADER, 0);
+ curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, 0);
+ curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
+ curl_setopt($curl, CURLOPT_FOLLOWLOCATION, false);
+ curl_setopt($curl, CURLOPT_FORBID_REUSE, 1);
+ curl_setopt($curl, CURLOPT_FRESH_CONNECT, 1);
+ curl_setopt($curl, CURLOPT_POST, 1);
+ curl_setopt($curl, CURLOPT_POSTFIELDS, http_build_query($payment_data));
+
+ $response = curl_exec($curl);
+
+ curl_close($curl);
+
+ $response_info = explode(chr(10), $response);
+
+ foreach ($response_info as $string) {
+ if (strpos($string, '=') && isset($i)) {
+ $parts = explode('=', $string, 2);
+ $data['RepeatResponseData_' . $i][trim($parts[0])] = trim($parts[1]);
+ } elseif (strpos($string, '=')) {
+ $parts = explode('=', $string, 2);
+ $data[trim($parts[0])] = trim($parts[1]);
+ }
+ }
+ return $data;
+ }
+
+ public function logger($title, $data) {
+ if ($this->config->get('payment_sagepay_server_debug')) {
+ $log = new Log('sagepay_server.log');
+ $log->write($title . ': ' . print_r($data, 1));
+ }
+ }
+} \ No newline at end of file
diff --git a/public/admin/model/extension/payment/securetrading_pp.php b/public/admin/model/extension/payment/securetrading_pp.php
new file mode 100644
index 0000000..2e21b3a
--- /dev/null
+++ b/public/admin/model/extension/payment/securetrading_pp.php
@@ -0,0 +1,208 @@
+<?php
+class ModelExtensionPaymentSecureTradingPp extends Model {
+ public function install() {
+ $this->db->query("
+ CREATE TABLE IF NOT EXISTS `" . DB_PREFIX . "securetrading_pp_order` (
+ `securetrading_pp_order_id` INT(11) NOT NULL AUTO_INCREMENT,
+ `order_id` INT(11) NOT NULL,
+ `transaction_reference` varchar(127) DEFAULT NULL,
+ `created` DATETIME NOT NULL,
+ `modified` DATETIME NOT NULL,
+ `release_status` INT(1) DEFAULT NULL,
+ `void_status` INT(1) DEFAULT NULL,
+ `settle_type` INT(1) DEFAULT NULL,
+ `rebate_status` INT(1) DEFAULT NULL,
+ `currency_code` CHAR(3) NOT NULL,
+ `total` DECIMAL( 10, 2 ) NOT NULL,
+ PRIMARY KEY (`securetrading_pp_order_id`)
+ ) ENGINE=MyISAM DEFAULT COLLATE=utf8_general_ci;");
+
+ $this->db->query("
+ CREATE TABLE IF NOT EXISTS `" . DB_PREFIX . "securetrading_pp_order_transaction` (
+ `securetrading_pp_order_transaction_id` INT(11) NOT NULL AUTO_INCREMENT,
+ `securetrading_pp_order_id` INT(11) NOT NULL,
+ `created` DATETIME NOT NULL,
+ `type` ENUM('auth', 'payment', 'rebate', 'reversed') DEFAULT NULL,
+ `amount` DECIMAL( 10, 2 ) NOT NULL,
+ PRIMARY KEY (`securetrading_pp_order_transaction_id`)
+ ) ENGINE=MyISAM DEFAULT COLLATE=utf8_general_ci;");
+ }
+
+ public function uninstall() {
+ $this->db->query("DROP TABLE IF EXISTS " . DB_PREFIX . "securetrading_pp_order");
+ $this->db->query("DROP TABLE IF EXISTS `" . DB_PREFIX . "securetrading_pp_order_transaction`;");
+ }
+
+ public function void($order_id) {
+ $securetrading_pp_order = $this->getOrder($order_id);
+
+ if (!empty($securetrading_pp_order) && $securetrading_pp_order['release_status'] == 0) {
+
+ $requestblock_xml = new SimpleXMLElement('<requestblock></requestblock>');
+ $requestblock_xml->addAttribute('version', '3.67');
+ $requestblock_xml->addChild('alias', $this->config->get('payment_securetrading_pp_webservice_username'));
+
+ $request_node = $requestblock_xml->addChild('request');
+ $request_node->addAttribute('type', 'TRANSACTIONUPDATE');
+
+ $filter_node = $request_node->addChild('filter');
+ $filter_node->addChild('sitereference', $this->config->get('payment_securetrading_pp_site_reference'));
+ $filter_node->addChild('transactionreference', $securetrading_pp_order['transaction_reference']);
+
+ $request_node->addChild('updates')->addChild('settlement')->addChild('settlestatus', 3);
+
+ return $this->call($requestblock_xml->asXML());
+ } else {
+ return false;
+ }
+ }
+
+ public function updateVoidStatus($securetrading_pp_order_id, $status) {
+ $this->db->query("UPDATE `" . DB_PREFIX . "securetrading_pp_order` SET `void_status` = '" . (int)$status . "' WHERE `securetrading_pp_order_id` = '" . (int)$securetrading_pp_order_id . "'");
+ }
+
+ public function release($order_id, $amount) {
+ $securetrading_pp_order = $this->getOrder($order_id);
+ $total_released = $this->getTotalReleased($securetrading_pp_order['securetrading_pp_order_id']);
+
+ if (!empty($securetrading_pp_order) && $securetrading_pp_order['release_status'] == 0 && $total_released <= $amount) {
+
+ $requestblock_xml = new SimpleXMLElement('<requestblock></requestblock>');
+ $requestblock_xml->addAttribute('version', '3.67');
+ $requestblock_xml->addChild('alias', $this->config->get('payment_securetrading_pp_webservice_username'));
+
+ $request_node = $requestblock_xml->addChild('request');
+ $request_node->addAttribute('type', 'TRANSACTIONUPDATE');
+
+ $filter_node = $request_node->addChild('filter');
+ $filter_node->addChild('sitereference', $this->config->get('payment_securetrading_pp_site_reference'));
+ $filter_node->addChild('transactionreference', $securetrading_pp_order['transaction_reference']);
+
+ $settlement_node = $request_node->addChild('updates')->addChild('settlement');
+ $settlement_node->addChild('settlestatus', 0);
+ $settlement_node->addChild('settlemainamount', $amount)->addAttribute('currencycode', $securetrading_pp_order['currency_code']);
+
+ return $this->call($requestblock_xml->asXML());
+ } else {
+ return false;
+ }
+ }
+
+ public function updateReleaseStatus($securetrading_pp_order_id, $status) {
+ $this->db->query("UPDATE `" . DB_PREFIX . "securetrading_pp_order` SET `release_status` = '" . (int)$status . "' WHERE `securetrading_pp_order_id` = '" . (int)$securetrading_pp_order_id . "'");
+ }
+
+ public function updateForRebate($securetrading_pp_order_id, $order_ref) {
+ $this->db->query("UPDATE `" . DB_PREFIX . "securetrading_pp_order` SET `order_ref_previous` = '_multisettle_" . $this->db->escape($order_ref) . "' WHERE `securetrading_pp_order_id` = '" . (int)$securetrading_pp_order_id . "' LIMIT 1");
+ }
+
+ public function rebate($order_id, $refunded_amount) {
+ $securetrading_pp_order = $this->getOrder($order_id);
+
+ if (!empty($securetrading_pp_order) && $securetrading_pp_order['rebate_status'] != 1) {
+
+ $requestblock_xml = new SimpleXMLElement('<requestblock></requestblock>');
+ $requestblock_xml->addAttribute('version', '3.67');
+ $requestblock_xml->addChild('alias', $this->config->get('payment_securetrading_pp_webservice_username'));
+
+ $request_node = $requestblock_xml->addChild('request');
+ $request_node->addAttribute('type', 'REFUND');
+
+ $request_node->addChild('merchant')->addChild('orderreference', $order_id);
+
+ $operation_node = $request_node->addChild('operation');
+ $operation_node->addChild('accounttypedescription', 'ECOM');
+ $operation_node->addChild('parenttransactionreference', $securetrading_pp_order['transaction_reference']);
+ $operation_node->addChild('sitereference', $this->config->get('payment_securetrading_pp_site_reference'));
+
+ $billing_node = $request_node->addChild('billing');
+ $billing_node->addAttribute('currencycode', $securetrading_pp_order['currency_code']);
+ $billing_node->addChild('amount', str_replace('.', '', $refunded_amount));
+
+ return $this->call($requestblock_xml->asXML());
+ } else {
+ return false;
+ }
+ }
+
+ public function getOrder($order_id) {
+ $qry = $this->db->query("SELECT * FROM `" . DB_PREFIX . "securetrading_pp_order` WHERE `order_id` = '" . (int)$order_id . "' LIMIT 1");
+
+ if ($qry->num_rows) {
+ $order = $qry->row;
+ $order['transactions'] = $this->getTransactions($order['securetrading_pp_order_id']);
+
+ return $order;
+ } else {
+ return false;
+ }
+ }
+
+ private function getTransactions($securetrading_pp_order_id) {
+ $qry = $this->db->query("SELECT * FROM `" . DB_PREFIX . "securetrading_pp_order_transaction` WHERE `securetrading_pp_order_id` = '" . (int)$securetrading_pp_order_id . "'");
+
+ if ($qry->num_rows) {
+ return $qry->rows;
+ } else {
+ return false;
+ }
+ }
+
+ public function addTransaction($securetrading_pp_order_id, $type, $total) {
+ $this->db->query("INSERT INTO `" . DB_PREFIX . "securetrading_pp_order_transaction` SET `securetrading_pp_order_id` = '" . (int)$securetrading_pp_order_id . "', `created` = now(), `type` = '" . $this->db->escape($type) . "', `amount` = '" . (double)$total . "'");
+ }
+
+ public function getTotalReleased($securetrading_pp_order_id) {
+ $query = $this->db->query("SELECT SUM(`amount`) AS `total` FROM `" . DB_PREFIX . "securetrading_pp_order_transaction` WHERE `securetrading_pp_order_id` = '" . (int)$securetrading_pp_order_id . "' AND (`type` = 'payment' OR `type` = 'rebate')");
+
+ return (double)$query->row['total'];
+ }
+
+ public function getTotalRebated($securetrading_pp_order_id) {
+ $query = $this->db->query("SELECT SUM(`amount`) AS `total` FROM `" . DB_PREFIX . "securetrading_pp_order_transaction` WHERE `securetrading_pp_order_id` = '" . (int)$securetrading_pp_order_id . "' AND 'rebate'");
+
+ return (double)$query->row['total'];
+ }
+
+ public function increaseRefundedAmount($order_id, $amount) {
+ $this->db->query("UPDATE " . DB_PREFIX . "securetrading_pp_order SET refunded = refunded + " . (double)$amount . " WHERE order_id = " . (int)$order_id);
+ }
+
+ public function call($data) {
+ $ch = curl_init();
+
+ $defaults = array(
+ CURLOPT_POST => 1,
+ CURLOPT_HEADER => 0,
+ CURLOPT_SSL_VERIFYPEER => 0,
+ CURLOPT_URL => 'https://webservices.securetrading.net/xml/',
+ CURLOPT_FRESH_CONNECT => 1,
+ CURLOPT_RETURNTRANSFER => 1,
+ CURLOPT_FORBID_REUSE => 1,
+ CURLOPT_TIMEOUT => 15,
+ CURLOPT_HTTPHEADER => array(
+ 'User-Agent: OpenCart - Secure Trading PP',
+ 'Content-Length: ' . strlen($data),
+ 'Authorization: Basic ' . base64_encode($this->config->get('payment_securetrading_pp_webservice_username') . ':' . $this->config->get('payment_securetrading_pp_webservice_password')),
+ ),
+ CURLOPT_POSTFIELDS => $data,
+ );
+
+ curl_setopt_array($ch, $defaults);
+
+ $response = curl_exec($ch);
+
+ if ($response === false) {
+ $this->log->write('Secure Trading PP CURL Error: (' . curl_errno($ch) . ') ' . curl_error($ch));
+ }
+
+ curl_close($ch);
+
+ return $response;
+ }
+
+ public function logger($message) {
+ $log = new Log('securetrading_pp.log');
+ $log->write($message);
+ }
+} \ No newline at end of file
diff --git a/public/admin/model/extension/payment/securetrading_ws.php b/public/admin/model/extension/payment/securetrading_ws.php
new file mode 100644
index 0000000..5b2b567
--- /dev/null
+++ b/public/admin/model/extension/payment/securetrading_ws.php
@@ -0,0 +1,351 @@
+<?php
+class ModelExtensionPaymentSecureTradingWs extends Model {
+ public function install() {
+ $this->db->query("
+ CREATE TABLE IF NOT EXISTS `" . DB_PREFIX . "securetrading_ws_order` (
+ `securetrading_ws_order_id` INT(11) NOT NULL AUTO_INCREMENT,
+ `order_id` INT(11) NOT NULL,
+ `md` varchar(1024) DEFAULT NULL,
+ `transaction_reference` varchar(127) DEFAULT NULL,
+ `created` DATETIME NOT NULL,
+ `modified` DATETIME NOT NULL,
+ `release_status` INT(1) DEFAULT NULL,
+ `void_status` INT(1) DEFAULT NULL,
+ `settle_type` INT(1) DEFAULT NULL,
+ `rebate_status` INT(1) DEFAULT NULL,
+ `currency_code` CHAR(3) NOT NULL,
+ `total` DECIMAL( 10, 2 ) NOT NULL,
+ PRIMARY KEY (`securetrading_ws_order_id`)
+ ) ENGINE=MyISAM DEFAULT COLLATE=utf8_general_ci;");
+
+ $this->db->query("
+ CREATE TABLE IF NOT EXISTS `" . DB_PREFIX . "securetrading_ws_order_transaction` (
+ `securetrading_ws_order_transaction_id` INT(11) NOT NULL AUTO_INCREMENT,
+ `securetrading_ws_order_id` INT(11) NOT NULL,
+ `created` DATETIME NOT NULL,
+ `type` ENUM('auth', 'payment', 'rebate', 'reversed') DEFAULT NULL,
+ `amount` DECIMAL( 10, 2 ) NOT NULL,
+ PRIMARY KEY (`securetrading_ws_order_transaction_id`)
+ ) ENGINE=MyISAM DEFAULT COLLATE=utf8_general_ci;");
+ }
+
+ public function uninstall() {
+ $this->db->query("DROP TABLE IF EXISTS " . DB_PREFIX . "securetrading_ws_order");
+ $this->db->query("DROP TABLE IF EXISTS `" . DB_PREFIX . "securetrading_ws_order_transaction`;");
+ }
+
+ public function void($order_id) {
+ $securetrading_ws_order = $this->getOrder($order_id);
+
+ if (!empty($securetrading_ws_order) && $securetrading_ws_order['release_status'] == 0) {
+
+ $requestblock_xml = new SimpleXMLElement('<requestblock></requestblock>');
+ $requestblock_xml->addAttribute('version', '3.67');
+ $requestblock_xml->addChild('alias', $this->config->get('payment_securetrading_ws_username'));
+
+ $request_node = $requestblock_xml->addChild('request');
+ $request_node->addAttribute('type', 'TRANSACTIONUPDATE');
+
+ $filter_node = $request_node->addChild('filter');
+ $filter_node->addChild('sitereference', $this->config->get('payment_securetrading_ws_site_reference'));
+ $filter_node->addChild('transactionreference', $securetrading_ws_order['transaction_reference']);
+
+ $request_node->addChild('updates')->addChild('settlement')->addChild('settlestatus', 3);
+
+ return $this->call($requestblock_xml->asXML());
+ } else {
+ return false;
+ }
+ }
+
+ public function updateVoidStatus($securetrading_ws_order_id, $status) {
+ $this->db->query("UPDATE `" . DB_PREFIX . "securetrading_ws_order` SET `void_status` = '" . (int)$status . "' WHERE `securetrading_ws_order_id` = '" . (int)$securetrading_ws_order_id . "'");
+ }
+
+ public function release($order_id, $amount) {
+ $securetrading_ws_order = $this->getOrder($order_id);
+ $total_released = $this->getTotalReleased($securetrading_ws_order['securetrading_ws_order_id']);
+
+ if (!empty($securetrading_ws_order) && $securetrading_ws_order['release_status'] == 0 && $total_released <= $amount) {
+
+ $requestblock_xml = new SimpleXMLElement('<requestblock></requestblock>');
+ $requestblock_xml->addAttribute('version', '3.67');
+ $requestblock_xml->addChild('alias', $this->config->get('payment_securetrading_ws_username'));
+
+ $request_node = $requestblock_xml->addChild('request');
+ $request_node->addAttribute('type', 'TRANSACTIONUPDATE');
+
+ $filter_node = $request_node->addChild('filter');
+ $filter_node->addChild('sitereference', $this->config->get('payment_securetrading_ws_site_reference'));
+ $filter_node->addChild('transactionreference', $securetrading_ws_order['transaction_reference']);
+
+ $settlement_node = $request_node->addChild('updates')->addChild('settlement');
+ $settlement_node->addChild('settlestatus', 0);
+ $settlement_node->addChild('settlemainamount', $amount)->addAttribute('currencycode', $securetrading_ws_order['currency_code']);
+
+ return $this->call($requestblock_xml->asXML());
+ } else {
+ return false;
+ }
+ }
+
+ public function updateReleaseStatus($securetrading_ws_order_id, $status) {
+ $this->db->query("UPDATE `" . DB_PREFIX . "securetrading_ws_order` SET `release_status` = '" . (int)$status . "' WHERE `securetrading_ws_order_id` = '" . (int)$securetrading_ws_order_id . "'");
+ }
+
+ public function updateForRebate($securetrading_ws_order_id, $order_ref) {
+ $this->db->query("UPDATE `" . DB_PREFIX . "securetrading_ws_order` SET `order_ref_previous` = '_multisettle_" . $this->db->escape($order_ref) . "' WHERE `securetrading_ws_order_id` = '" . (int)$securetrading_ws_order_id . "' LIMIT 1");
+ }
+
+ public function rebate($order_id, $refunded_amount) {
+ $securetrading_ws_order = $this->getOrder($order_id);
+
+ if (!empty($securetrading_ws_order) && $securetrading_ws_order['rebate_status'] != 1) {
+
+ $requestblock_xml = new SimpleXMLElement('<requestblock></requestblock>');
+ $requestblock_xml->addAttribute('version', '3.67');
+ $requestblock_xml->addChild('alias', $this->config->get('payment_securetrading_ws_username'));
+
+ $request_node = $requestblock_xml->addChild('request');
+ $request_node->addAttribute('type', 'REFUND');
+
+ $request_node->addChild('merchant')->addChild('orderreference', $order_id);
+
+ $operation_node = $request_node->addChild('operation');
+ $operation_node->addChild('accounttypedescription', 'ECOM');
+ $operation_node->addChild('parenttransactionreference', $securetrading_ws_order['transaction_reference']);
+ $operation_node->addChild('sitereference', $this->config->get('payment_securetrading_ws_site_reference'));
+
+ $billing_node = $request_node->addChild('billing');
+ $billing_node->addAttribute('currencycode', $securetrading_ws_order['currency_code']);
+ $billing_node->addChild('amount', str_replace('.', '', $refunded_amount));
+
+ return $this->call($requestblock_xml->asXML());
+ } else {
+ return false;
+ }
+ }
+
+ public function getOrder($order_id) {
+ $qry = $this->db->query("SELECT * FROM `" . DB_PREFIX . "securetrading_ws_order` WHERE `order_id` = '" . (int)$order_id . "' LIMIT 1");
+
+ if ($qry->num_rows) {
+ $order = $qry->row;
+ $order['transactions'] = $this->getTransactions($order['securetrading_ws_order_id']);
+
+ return $order;
+ } else {
+ return false;
+ }
+ }
+
+ private function getTransactions($securetrading_ws_order_id) {
+ $qry = $this->db->query("SELECT * FROM `" . DB_PREFIX . "securetrading_ws_order_transaction` WHERE `securetrading_ws_order_id` = '" . (int)$securetrading_ws_order_id . "'");
+
+ if ($qry->num_rows) {
+ return $qry->rows;
+ } else {
+ return false;
+ }
+ }
+
+ public function addTransaction($securetrading_ws_order_id, $type, $total) {
+ $this->db->query("INSERT INTO `" . DB_PREFIX . "securetrading_ws_order_transaction` SET `securetrading_ws_order_id` = '" . (int)$securetrading_ws_order_id . "', `created` = now(), `type` = '" . $this->db->escape($type) . "', `amount` = '" . (double)$total . "'");
+ }
+
+ public function getTotalReleased($securetrading_ws_order_id) {
+ $query = $this->db->query("SELECT SUM(`amount`) AS `total` FROM `" . DB_PREFIX . "securetrading_ws_order_transaction` WHERE `securetrading_ws_order_id` = '" . (int)$securetrading_ws_order_id . "' AND (`type` = 'payment' OR `type` = 'rebate')");
+
+ return (double)$query->row['total'];
+ }
+
+ public function getTotalRebated($securetrading_ws_order_id) {
+ $query = $this->db->query("SELECT SUM(`amount`) AS `total` FROM `" . DB_PREFIX . "securetrading_ws_order_transaction` WHERE `securetrading_ws_order_id` = '" . (int)$securetrading_ws_order_id . "' AND 'rebate'");
+
+ return (double)$query->row['total'];
+ }
+
+ public function increaseRefundedAmount($order_id, $amount) {
+ $this->db->query("UPDATE " . DB_PREFIX . "securetrading_ws_order SET refunded = refunded + " . (double)$amount . " WHERE order_id = " . (int)$order_id);
+ }
+
+ public function getCsv($data) {
+ $ch = curl_init();
+
+ $post_data = array();
+ $post_data['sitereferences'] = $this->config->get('payment_securetrading_ws_site_reference');
+ $post_data['startdate'] = $data['date_from'];
+ $post_data['enddate'] = $data['date_to'];
+ $post_data['accounttypedescriptions'] = 'ECOM';
+
+ if ($data['detail']) {
+ $post_data['optionalfields'] = array(
+ 'parenttransactionreference',
+ 'accounttypedescription',
+ 'requesttypedescription',
+ 'mainamount',
+ 'currencyiso3a',
+ 'errorcode',
+ 'authcode',
+ 'customerip',
+ 'fraudrating',
+ 'orderreference',
+ 'paymenttypedescription',
+ 'maskedpan',
+ 'expirydate',
+ 'settlestatus',
+ 'settlemainamount',
+ 'settleduedate',
+ 'securityresponsesecuritycode',
+ 'securityresponseaddress',
+ 'securityresponsepostcode',
+ 'billingprefixname',
+ 'billingfirstname',
+ 'billingmiddlename',
+ 'billinglastname',
+ 'billingpremise',
+ 'billingstreet',
+ 'billingtown',
+ 'billingcounty',
+ 'billingemail',
+ 'billingcountryiso2a',
+ 'billingpostcode',
+ 'billingtelephones',
+ 'customerprefixname',
+ 'customerfirstname',
+ 'customermiddlename',
+ 'customerlastname',
+ 'customerpremise',
+ 'customerstreet',
+ 'customertown',
+ 'customercounty',
+ 'customeremail',
+ 'customercountryiso2a',
+ 'customerpostcode',
+ 'customertelephones',
+ );
+ } else {
+ $post_data['optionalfields'] = array(
+ 'orderreference',
+ 'currencyiso3a',
+ 'errorcode',
+ 'paymenttypedescription',
+ 'settlestatus',
+ 'requesttypedescription',
+ 'mainamount',
+ 'billingfirstname',
+ 'billinglastname',
+ );
+ }
+
+ if (isset($data['currency']) && !empty($data['currency'])) {
+ $post_data['currencyiso3as'] = $data['currency'];
+ }
+
+ if (isset($data['status']) && !empty($data['status'])) {
+ $post_data['errorcodes'] = $data['status'];
+ }
+
+ if (isset($data['payment_type']) && !empty($data['payment_type'])) {
+ $post_data['paymenttypedescriptions'] = $data['payment_type'];
+ }
+
+ if (isset($data['request']) && !empty($data['request'])) {
+ $post_data['requesttypedescriptions'] = $data['request'];
+ }
+
+ if (isset($data['settle_status']) && !empty($data['settle_status'])) {
+ $post_data['settlestatuss'] = $data['settle_status'];
+ }
+
+ $defaults = array(
+ CURLOPT_POST => 1,
+ CURLOPT_HEADER => 0,
+ CURLOPT_SSL_VERIFYPEER => 0,
+ CURLOPT_URL => 'https://myst.securetrading.net/auto/transactions/transactionsearch',
+ CURLOPT_FRESH_CONNECT => 1,
+ CURLOPT_RETURNTRANSFER => 1,
+ CURLOPT_FORBID_REUSE => 1,
+ CURLOPT_TIMEOUT => 15,
+ CURLOPT_HTTPHEADER => array(
+ 'User-Agent: OpenCart - Secure Trading WS',
+ 'Authorization: Basic ' . base64_encode($this->config->get('payment_securetrading_ws_csv_username') . ':' . $this->config->get('payment_securetrading_ws_csv_password')),
+ ),
+ CURLOPT_POSTFIELDS => $this->encodePost($post_data),
+ );
+
+ curl_setopt_array($ch, $defaults);
+
+ $response = curl_exec($ch);
+
+ if ($response === false) {
+ $this->log->write('Secure Trading WS CURL Error: (' . curl_errno($ch) . ') ' . curl_error($ch));
+ }
+
+ curl_close($ch);
+
+ if (empty($response) || $response === 'No records found for search') {
+ return false;
+ }
+
+ if (preg_match('/401 Authorization Required/', $response)) {
+ return false;
+ }
+
+ return $response;
+ }
+
+ private function encodePost($data) {
+ $params = array();
+
+ foreach ($data as $key => $value) {
+ if (is_array($value)) {
+ foreach ($value as $v) {
+ $params[] = $key . '=' . rawurlencode($v);
+ }
+ } else {
+ $params[] = $key . '=' . rawurlencode($value);
+ }
+ }
+
+ return implode('&', $params);
+ }
+
+ public function call($data) {
+ $ch = curl_init();
+
+ $defaults = array(
+ CURLOPT_POST => 1,
+ CURLOPT_HEADER => 0,
+ CURLOPT_SSL_VERIFYPEER => 0,
+ CURLOPT_URL => 'https://webservices.securetrading.net/xml/',
+ CURLOPT_FRESH_CONNECT => 1,
+ CURLOPT_RETURNTRANSFER => 1,
+ CURLOPT_FORBID_REUSE => 1,
+ CURLOPT_TIMEOUT => 15,
+ CURLOPT_HTTPHEADER => array(
+ 'User-Agent: OpenCart - Secure Trading WS',
+ 'Content-Length: ' . strlen($data),
+ 'Authorization: Basic ' . base64_encode($this->config->get('payment_securetrading_ws_username') . ':' . $this->config->get('payment_securetrading_ws_password')),
+ ),
+ CURLOPT_POSTFIELDS => $data,
+ );
+
+ curl_setopt_array($ch, $defaults);
+
+ $response = curl_exec($ch);
+
+ if ($response === false) {
+ $this->log->write('Secure Trading WS CURL Error: (' . curl_errno($ch) . ') ' . curl_error($ch));
+ }
+
+ curl_close($ch);
+
+ return $response;
+ }
+
+ public function logger($message) {
+ $log = new Log('securetrading_ws.log');
+ $log->write($message);
+ }
+} \ No newline at end of file
diff --git a/public/admin/model/extension/payment/squareup.php b/public/admin/model/extension/payment/squareup.php
new file mode 100644
index 0000000..d5c428c
--- /dev/null
+++ b/public/admin/model/extension/payment/squareup.php
@@ -0,0 +1,117 @@
+<?php
+
+class ModelExtensionPaymentSquareup extends Model {
+ const RECURRING_ACTIVE = 1;
+ const RECURRING_INACTIVE = 2;
+ const RECURRING_CANCELLED = 3;
+ const RECURRING_SUSPENDED = 4;
+ const RECURRING_EXPIRED = 5;
+ const RECURRING_PENDING = 6;
+
+ public function getTransaction($squareup_transaction_id) {
+ return $this->db->query("SELECT * FROM `" . DB_PREFIX . "squareup_transaction` WHERE squareup_transaction_id='" . (int)$squareup_transaction_id . "'")->row;
+ }
+
+ public function getTransactions($data) {
+ $sql = "SELECT * FROM `" . DB_PREFIX . "squareup_transaction`";
+
+ if (isset($data['order_id'])) {
+ $sql .= " WHERE order_id='" . (int)$data['order_id'] . "'";
+ }
+
+ $sql .= " ORDER BY created_at DESC";
+
+ if (isset($data['start']) && isset($data['limit'])) {
+ $sql .= " LIMIT " . $data['start'] . ', ' . $data['limit'];
+ }
+
+ return $this->db->query($sql)->rows;
+ }
+
+ public function getTotalTransactions($data) {
+ $sql = "SELECT COUNT(*) as total FROM `" . DB_PREFIX . "squareup_transaction`";
+
+ if (isset($data['order_id'])) {
+ $sql .= " WHERE order_id='" . (int)$data['order_id'] . "'";
+ }
+
+ return $this->db->query($sql)->row['total'];
+ }
+
+ public function updateTransaction($squareup_transaction_id, $type, $refunds = array()) {
+ $this->db->query("UPDATE `" . DB_PREFIX . "squareup_transaction` SET transaction_type='" . $this->db->escape($type) . "', is_refunded='" . (int)!empty($refunds) . "', refunds='" . $this->db->escape(json_encode($refunds)) . "' WHERE squareup_transaction_id='" . (int)$squareup_transaction_id . "'");
+ }
+
+ public function getOrderStatusId($order_id, $transaction_status = null) {
+ if ($transaction_status) {
+ return $this->config->get('payment_squareup_status_' . strtolower($transaction_status));
+ } else {
+ $this->load->model('sale/order');
+
+ $order_info = $this->model_sale_order->getOrder($order_id);
+
+ return $order_info['order_status_id'];
+ }
+ }
+
+ public function editOrderRecurringStatus($order_recurring_id, $status) {
+ $this->db->query("UPDATE `" . DB_PREFIX . "order_recurring` SET `status` = '" . (int)$status . "' WHERE `order_recurring_id` = '" . (int)$order_recurring_id . "'");
+ }
+
+ public function createTables() {
+ $this->db->query("CREATE TABLE IF NOT EXISTS `" . DB_PREFIX . "squareup_transaction` (
+ `squareup_transaction_id` int(11) UNSIGNED NOT NULL AUTO_INCREMENT,
+ `transaction_id` char(40) NOT NULL,
+ `merchant_id` char(32) NOT NULL,
+ `location_id` varchar(32) NOT NULL,
+ `order_id` int(11) NOT NULL,
+ `transaction_type` char(20) NOT NULL,
+ `transaction_amount` decimal(15,2) NOT NULL,
+ `transaction_currency` char(3) NOT NULL,
+ `billing_address_city` char(100) NOT NULL,
+ `billing_address_company` char(100) NOT NULL,
+ `billing_address_country` char(3) NOT NULL,
+ `billing_address_postcode` char(10) NOT NULL,
+ `billing_address_province` char(20) NOT NULL,
+ `billing_address_street_1` char(100) NOT NULL,
+ `billing_address_street_2` char(100) NOT NULL,
+ `device_browser` char(255) NOT NULL,
+ `device_ip` char(15) NOT NULL,
+ `created_at` char(29) NOT NULL,
+ `is_refunded` tinyint(1) NOT NULL,
+ `refunded_at` varchar(29) NOT NULL,
+ `tenders` text NOT NULL,
+ `refunds` text NOT NULL,
+ PRIMARY KEY (`squareup_transaction_id`),
+ KEY `order_id` (`order_id`),
+ KEY `transaction_id` (`transaction_id`)
+ ) ENGINE=InnoDB DEFAULT CHARSET=utf8;");
+
+ $this->db->query("CREATE TABLE IF NOT EXISTS `" . DB_PREFIX . "squareup_token` (
+ `squareup_token_id` int(11) unsigned NOT NULL AUTO_INCREMENT,
+ `customer_id` int(11) NOT NULL,
+ `sandbox` tinyint(1) NOT NULL,
+ `token` char(40) NOT NULL,
+ `date_added` datetime NOT NULL,
+ `brand` VARCHAR(32) NOT NULL,
+ `ends_in` VARCHAR(4) NOT NULL,
+ PRIMARY KEY (`squareup_token_id`),
+ KEY `getCards` (`customer_id`, `sandbox`),
+ KEY `verifyCardCustomer` (`squareup_token_id`, `customer_id`),
+ KEY `cardExists` (`customer_id`, `brand`, `ends_in`)
+ ) ENGINE=InnoDB DEFAULT CHARSET=utf8");
+
+ $this->db->query("CREATE TABLE IF NOT EXISTS `" . DB_PREFIX . "squareup_customer` (
+ `customer_id` int(11) NOT NULL,
+ `sandbox` tinyint(1) NOT NULL,
+ `square_customer_id` varchar(32) NOT NULL,
+ PRIMARY KEY (`customer_id`, `sandbox`)
+ ) ENGINE=InnoDB DEFAULT CHARSET=utf8");
+ }
+
+ public function dropTables() {
+ $this->db->query("DROP TABLE IF EXISTS `" . DB_PREFIX . "squareup_transaction`");
+ $this->db->query("DROP TABLE IF EXISTS `" . DB_PREFIX . "squareup_token`");
+ $this->db->query("DROP TABLE IF EXISTS `" . DB_PREFIX . "squareup_customer`");
+ }
+} \ No newline at end of file
diff --git a/public/admin/model/extension/payment/worldpay.php b/public/admin/model/extension/payment/worldpay.php
new file mode 100644
index 0000000..ae2d9ce
--- /dev/null
+++ b/public/admin/model/extension/payment/worldpay.php
@@ -0,0 +1,175 @@
+<?php
+
+class ModelExtensionPaymentWorldpay extends Model {
+
+ public function install() {
+ $this->db->query("
+ CREATE TABLE IF NOT EXISTS `" . DB_PREFIX . "worldpay_order` (
+ `worldpay_order_id` INT(11) NOT NULL AUTO_INCREMENT,
+ `order_id` INT(11) NOT NULL,
+ `order_code` VARCHAR(50),
+ `date_added` DATETIME NOT NULL,
+ `date_modified` DATETIME NOT NULL,
+ `refund_status` INT(1) DEFAULT NULL,
+ `currency_code` CHAR(3) NOT NULL,
+ `total` DECIMAL( 10, 2 ) NOT NULL,
+ PRIMARY KEY (`worldpay_order_id`)
+ ) ENGINE=MyISAM DEFAULT COLLATE=utf8_general_ci;");
+
+ $this->db->query("
+ CREATE TABLE IF NOT EXISTS `" . DB_PREFIX . "worldpay_order_transaction` (
+ `worldpay_order_transaction_id` INT(11) NOT NULL AUTO_INCREMENT,
+ `worldpay_order_id` INT(11) NOT NULL,
+ `date_added` DATETIME NOT NULL,
+ `type` ENUM('payment', 'refund') DEFAULT NULL,
+ `amount` DECIMAL( 10, 2 ) NOT NULL,
+ PRIMARY KEY (`worldpay_order_transaction_id`)
+ ) ENGINE=MyISAM DEFAULT COLLATE=utf8_general_ci;");
+
+ $this->db->query("
+ CREATE TABLE IF NOT EXISTS `" . DB_PREFIX . "worldpay_order_recurring` (
+ `worldpay_order_recurring_id` INT(11) NOT NULL AUTO_INCREMENT,
+ `order_id` INT(11) NOT NULL,
+ `order_recurring_id` INT(11) NOT NULL,
+ `order_code` VARCHAR(50),
+ `token` VARCHAR(50),
+ `date_added` DATETIME NOT NULL,
+ `date_modified` DATETIME NOT NULL,
+ `next_payment` DATETIME NOT NULL,
+ `trial_end` datetime DEFAULT NULL,
+ `subscription_end` datetime DEFAULT NULL,
+ `currency_code` CHAR(3) NOT NULL,
+ `total` DECIMAL( 10, 2 ) NOT NULL,
+ PRIMARY KEY (`worldpay_order_recurring_id`)
+ ) ENGINE=MyISAM DEFAULT COLLATE=utf8_general_ci;");
+
+ $this->db->query("
+ CREATE TABLE IF NOT EXISTS `" . DB_PREFIX . "worldpay_card` (
+ `card_id` INT(11) NOT NULL AUTO_INCREMENT,
+ `customer_id` INT(11) NOT NULL,
+ `order_id` INT(11) NOT NULL,
+ `token` VARCHAR(50) NOT NULL,
+ `digits` VARCHAR(22) NOT NULL,
+ `expiry` VARCHAR(5) NOT NULL,
+ `type` VARCHAR(50) NOT NULL,
+ PRIMARY KEY (`card_id`)
+ ) ENGINE=MyISAM DEFAULT COLLATE=utf8_general_ci;");
+ }
+
+ public function uninstall() {
+ $this->db->query("DROP TABLE IF EXISTS `" . DB_PREFIX . "worldpay_order`;");
+ $this->db->query("DROP TABLE IF EXISTS `" . DB_PREFIX . "worldpay_order_transaction`;");
+ $this->db->query("DROP TABLE IF EXISTS `" . DB_PREFIX . "worldpay_order_recurring`;");
+ $this->db->query("DROP TABLE IF EXISTS `" . DB_PREFIX . "worldpay_card`;");
+ }
+
+ public function refund($order_id, $amount) {
+ $worldpay_order = $this->getOrder($order_id);
+
+ if (!empty($worldpay_order) && $worldpay_order['refund_status'] != 1) {
+ $order['refundAmount'] = (int)($amount * 100);
+
+ $url = $worldpay_order['order_code'] . '/refund';
+
+ $response_data = $this->sendCurl($url, $order);
+
+ return $response_data;
+ } else {
+ return false;
+ }
+ }
+
+ public function updateRefundStatus($worldpay_order_id, $status) {
+ $this->db->query("UPDATE `" . DB_PREFIX . "worldpay_order` SET `refund_status` = '" . (int)$status . "' WHERE `worldpay_order_id` = '" . (int)$worldpay_order_id . "'");
+ }
+
+ public function getOrder($order_id) {
+
+ $qry = $this->db->query("SELECT * FROM `" . DB_PREFIX . "worldpay_order` WHERE `order_id` = '" . (int)$order_id . "' LIMIT 1");
+
+ if ($qry->num_rows) {
+ $order = $qry->row;
+ $order['transactions'] = $this->getTransactions($order['worldpay_order_id'], $qry->row['currency_code']);
+
+ return $order;
+ } else {
+ return false;
+ }
+ }
+
+ private function getTransactions($worldpay_order_id, $currency_code) {
+ $query = $this->db->query("SELECT * FROM `" . DB_PREFIX . "worldpay_order_transaction` WHERE `worldpay_order_id` = '" . (int)$worldpay_order_id . "'");
+
+ $transactions = array();
+ if ($query->num_rows) {
+ foreach ($query->rows as $row) {
+ $row['amount'] = $this->currency->format($row['amount'], $currency_code, false);
+ $transactions[] = $row;
+ }
+ return $transactions;
+ } else {
+ return false;
+ }
+ }
+
+ public function addTransaction($worldpay_order_id, $type, $total) {
+ $this->db->query("INSERT INTO `" . DB_PREFIX . "worldpay_order_transaction` SET `worldpay_order_id` = '" . (int)$worldpay_order_id . "', `date_added` = now(), `type` = '" . $this->db->escape($type) . "', `amount` = '" . (double)$total . "'");
+ }
+
+ public function getTotalReleased($worldpay_order_id) {
+ $query = $this->db->query("SELECT SUM(`amount`) AS `total` FROM `" . DB_PREFIX . "worldpay_order_transaction` WHERE `worldpay_order_id` = '" . (int)$worldpay_order_id . "' AND (`type` = 'payment' OR `type` = 'refund')");
+
+ return (double)$query->row['total'];
+ }
+
+ public function getTotalRefunded($worldpay_order_id) {
+ $query = $this->db->query("SELECT SUM(`amount`) AS `total` FROM `" . DB_PREFIX . "worldpay_order_transaction` WHERE `worldpay_order_id` = '" . (int)$worldpay_order_id . "' AND 'refund'");
+
+ return (double)$query->row['total'];
+ }
+
+ public function sendCurl($url, $order) {
+
+ $json = json_encode($order);
+
+ $curl = curl_init();
+
+ curl_setopt($curl, CURLOPT_URL, 'https://api.worldpay.com/v1/orders/' . $url);
+ curl_setopt($curl, CURLOPT_CUSTOMREQUEST, 'POST');
+ curl_setopt($curl, CURLOPT_POSTFIELDS, $json);
+ curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
+ curl_setopt($curl, CURLOPT_CONNECTTIMEOUT, 0);
+ curl_setopt($curl, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_0);
+ curl_setopt($curl, CURLOPT_TIMEOUT, 10);
+ curl_setopt(
+ $curl, CURLOPT_HTTPHEADER, array(
+ "Authorization: " . $this->config->get('payment_worldpay_service_key'),
+ "Content-Type: application/json",
+ "Content-Length: " . strlen($json)
+ )
+ );
+
+ $result = json_decode(curl_exec($curl));
+ curl_close($curl);
+
+ $response = array();
+
+ if (isset($result)) {
+ $response['status'] = $result->httpStatusCode;
+ $response['message'] = $result->message;
+ $response['full_details'] = $result;
+ } else {
+ $response['status'] = 'success';
+ }
+
+ return $response;
+ }
+
+ public function logger($message) {
+ if ($this->config->get('payment_worldpay_debug') == 1) {
+ $log = new Log('worldpay.log');
+ $log->write($message);
+ }
+ }
+
+}
diff --git a/public/admin/model/extension/report/activity.php b/public/admin/model/extension/report/activity.php
new file mode 100644
index 0000000..94612f7
--- /dev/null
+++ b/public/admin/model/extension/report/activity.php
@@ -0,0 +1,8 @@
+<?php
+class ModelExtensionReportActivity extends Model {
+ public function getActivities() {
+ $query = $this->db->query("SELECT a.key, a.data, a.date_added FROM ((SELECT CONCAT('customer_', ca.key) AS `key`, ca.data, ca.date_added FROM `" . DB_PREFIX . "customer_activity` ca) UNION (SELECT CONCAT('affiliate_', aa.key) AS `key`, aa.data, aa.date_added FROM `" . DB_PREFIX . "affiliate_activity` aa)) a ORDER BY a.date_added DESC LIMIT 0,5");
+
+ return $query->rows;
+ }
+} \ No newline at end of file
diff --git a/public/admin/model/extension/report/coupon.php b/public/admin/model/extension/report/coupon.php
new file mode 100644
index 0000000..86038c7
--- /dev/null
+++ b/public/admin/model/extension/report/coupon.php
@@ -0,0 +1,60 @@
+<?php
+class ModelExtensionReportCoupon extends Model {
+ public function getCoupons($data = array()) {
+ $sql = "SELECT ch.coupon_id, c.name, c.code, COUNT(DISTINCT ch.order_id) AS `orders`, SUM(ch.amount) AS total FROM `" . DB_PREFIX . "coupon_history` ch LEFT JOIN `" . DB_PREFIX . "coupon` c ON (ch.coupon_id = c.coupon_id)";
+
+ $implode = array();
+
+ if (!empty($data['filter_date_start'])) {
+ $implode[] = "DATE(ch.date_added) >= '" . $this->db->escape($data['filter_date_start']) . "'";
+ }
+
+ if (!empty($data['filter_date_end'])) {
+ $implode[] = "DATE(ch.date_added) <= '" . $this->db->escape($data['filter_date_end']) . "'";
+ }
+
+ if ($implode) {
+ $sql .= " WHERE " . implode(" AND ", $implode);
+ }
+
+ $sql .= " GROUP BY ch.coupon_id ORDER BY total DESC";
+
+ if (isset($data['start']) || isset($data['limit'])) {
+ if ($data['start'] < 0) {
+ $data['start'] = 0;
+ }
+
+ if ($data['limit'] < 1) {
+ $data['limit'] = 20;
+ }
+
+ $sql .= " LIMIT " . (int)$data['start'] . "," . (int)$data['limit'];
+ }
+
+ $query = $this->db->query($sql);
+
+ return $query->rows;
+ }
+
+ public function getTotalCoupons($data = array()) {
+ $sql = "SELECT COUNT(DISTINCT coupon_id) AS total FROM `" . DB_PREFIX . "coupon_history`";
+
+ $implode = array();
+
+ if (!empty($data['filter_date_start'])) {
+ $implode[] = "DATE(date_added) >= '" . $this->db->escape($data['filter_date_start']) . "'";
+ }
+
+ if (!empty($data['filter_date_end'])) {
+ $implode[] = "DATE(date_added) <= '" . $this->db->escape($data['filter_date_end']) . "'";
+ }
+
+ if ($implode) {
+ $sql .= " WHERE " . implode(" AND ", $implode);
+ }
+
+ $query = $this->db->query($sql);
+
+ return $query->row['total'];
+ }
+} \ No newline at end of file
diff --git a/public/admin/model/extension/report/customer.php b/public/admin/model/extension/report/customer.php
new file mode 100644
index 0000000..93e9c33
--- /dev/null
+++ b/public/admin/model/extension/report/customer.php
@@ -0,0 +1,380 @@
+<?php
+class ModelExtensionReportCustomer extends Model {
+ public function getTotalCustomersByDay() {
+ $customer_data = array();
+
+ for ($i = 0; $i < 24; $i++) {
+ $customer_data[$i] = array(
+ 'hour' => $i,
+ 'total' => 0
+ );
+ }
+
+ $query = $this->db->query("SELECT COUNT(*) AS total, HOUR(date_added) AS hour FROM `" . DB_PREFIX . "customer` WHERE DATE(date_added) = DATE(NOW()) GROUP BY HOUR(date_added) ORDER BY date_added ASC");
+
+ foreach ($query->rows as $result) {
+ $customer_data[$result['hour']] = array(
+ 'hour' => $result['hour'],
+ 'total' => $result['total']
+ );
+ }
+
+ return $customer_data;
+ }
+
+ public function getTotalCustomersByWeek() {
+ $customer_data = array();
+
+ $date_start = strtotime('-' . date('w') . ' days');
+
+ for ($i = 0; $i < 7; $i++) {
+ $date = date('Y-m-d', $date_start + ($i * 86400));
+
+ $customer_data[date('w', strtotime($date))] = array(
+ 'day' => date('D', strtotime($date)),
+ 'total' => 0
+ );
+ }
+
+ $query = $this->db->query("SELECT COUNT(*) AS total, date_added FROM `" . DB_PREFIX . "customer` WHERE DATE(date_added) >= DATE('" . $this->db->escape(date('Y-m-d', $date_start)) . "') GROUP BY DAYNAME(date_added)");
+
+ foreach ($query->rows as $result) {
+ $customer_data[date('w', strtotime($result['date_added']))] = array(
+ 'day' => date('D', strtotime($result['date_added'])),
+ 'total' => $result['total']
+ );
+ }
+
+ return $customer_data;
+ }
+
+ public function getTotalCustomersByMonth() {
+ $customer_data = array();
+
+ for ($i = 1; $i <= date('t'); $i++) {
+ $date = date('Y') . '-' . date('m') . '-' . $i;
+
+ $customer_data[date('j', strtotime($date))] = array(
+ 'day' => date('d', strtotime($date)),
+ 'total' => 0
+ );
+ }
+
+ $query = $this->db->query("SELECT COUNT(*) AS total, date_added FROM `" . DB_PREFIX . "customer` WHERE DATE(date_added) >= '" . $this->db->escape(date('Y') . '-' . date('m') . '-1') . "' GROUP BY DATE(date_added)");
+
+ foreach ($query->rows as $result) {
+ $customer_data[date('j', strtotime($result['date_added']))] = array(
+ 'day' => date('d', strtotime($result['date_added'])),
+ 'total' => $result['total']
+ );
+ }
+
+ return $customer_data;
+ }
+
+ public function getTotalCustomersByYear() {
+ $customer_data = array();
+
+ for ($i = 1; $i <= 12; $i++) {
+ $customer_data[$i] = array(
+ 'month' => date('M', mktime(0, 0, 0, $i)),
+ 'total' => 0
+ );
+ }
+
+ $query = $this->db->query("SELECT COUNT(*) AS total, date_added FROM `" . DB_PREFIX . "customer` WHERE YEAR(date_added) = YEAR(NOW()) GROUP BY MONTH(date_added)");
+
+ foreach ($query->rows as $result) {
+ $customer_data[date('n', strtotime($result['date_added']))] = array(
+ 'month' => date('M', strtotime($result['date_added'])),
+ 'total' => $result['total']
+ );
+ }
+
+ return $customer_data;
+ }
+
+ public function getOrders($data = array()) {
+ $sql = "SELECT c.customer_id, CONCAT(c.firstname, ' ', c.lastname) AS customer, c.email, cgd.name AS customer_group, c.status, o.order_id, SUM(op.quantity) as products, o.total AS total FROM `" . DB_PREFIX . "order` o LEFT JOIN `" . DB_PREFIX . "order_product` op ON (o.order_id = op.order_id) LEFT JOIN `" . DB_PREFIX . "customer` c ON (o.customer_id = c.customer_id) LEFT JOIN `" . DB_PREFIX . "customer_group_description` cgd ON (c.customer_group_id = cgd.customer_group_id) WHERE o.customer_id > 0 AND cgd.language_id = '" . (int)$this->config->get('config_language_id') . "'";
+
+ if (!empty($data['filter_date_start'])) {
+ $sql .= " AND DATE(o.date_added) >= '" . $this->db->escape($data['filter_date_start']) . "'";
+ }
+
+ if (!empty($data['filter_date_end'])) {
+ $sql .= " AND DATE(o.date_added) <= '" . $this->db->escape($data['filter_date_end']) . "'";
+ }
+
+ if (!empty($data['filter_customer'])) {
+ $sql .= " AND CONCAT(c.firstname, ' ', c.lastname) LIKE '" . $this->db->escape($data['filter_customer']) . "'";
+ }
+
+ if (!empty($data['filter_order_status_id'])) {
+ $sql .= " AND o.order_status_id = '" . (int)$data['filter_order_status_id'] . "'";
+ } else {
+ $sql .= " AND o.order_status_id > '0'";
+ }
+
+ $sql .= " GROUP BY o.order_id";
+
+ $sql = "SELECT t.customer_id, t.customer, t.email, t.customer_group, t.status, COUNT(DISTINCT t.order_id) AS orders, SUM(t.products) AS products, SUM(t.total) AS total FROM (" . $sql . ") AS t GROUP BY t.customer_id ORDER BY total DESC";
+
+ if (isset($data['start']) || isset($data['limit'])) {
+ if ($data['start'] < 0) {
+ $data['start'] = 0;
+ }
+
+ if ($data['limit'] < 1) {
+ $data['limit'] = 20;
+ }
+
+ $sql .= " LIMIT " . (int)$data['start'] . "," . (int)$data['limit'];
+ }
+
+ $query = $this->db->query($sql);
+
+ return $query->rows;
+ }
+
+ public function getTotalOrders($data = array()) {
+ $sql = "SELECT COUNT(DISTINCT o.customer_id) AS total FROM `" . DB_PREFIX . "order` o LEFT JOIN `" . DB_PREFIX . "customer` c ON (o.customer_id = c.customer_id) WHERE o.customer_id > '0'";
+
+ if (!empty($data['filter_date_start'])) {
+ $sql .= " AND DATE(o.date_added) >= '" . $this->db->escape($data['filter_date_start']) . "'";
+ }
+
+ if (!empty($data['filter_date_end'])) {
+ $sql .= " AND DATE(o.date_added) <= '" . $this->db->escape($data['filter_date_end']) . "'";
+ }
+
+ if (!empty($data['filter_customer'])) {
+ $sql .= " AND CONCAT(c.firstname, ' ', c.lastname) LIKE '" . $this->db->escape($data['filter_customer']) . "'";
+ }
+
+ if (!empty($data['filter_order_status_id'])) {
+ $sql .= " AND o.order_status_id = '" . (int)$data['filter_order_status_id'] . "'";
+ } else {
+ $sql .= " AND o.order_status_id > '0'";
+ }
+
+ $query = $this->db->query($sql);
+
+ return $query->row['total'];
+ }
+
+ public function getRewardPoints($data = array()) {
+ $sql = "SELECT cr.customer_id, CONCAT(c.firstname, ' ', c.lastname) AS customer, c.email, cgd.name AS customer_group, c.status, SUM(cr.points) AS points, COUNT(o.order_id) AS orders, SUM(o.total) AS total FROM " . DB_PREFIX . "customer_reward cr LEFT JOIN `" . DB_PREFIX . "customer` c ON (cr.customer_id = c.customer_id) LEFT JOIN " . DB_PREFIX . "customer_group_description cgd ON (c.customer_group_id = cgd.customer_group_id) LEFT JOIN `" . DB_PREFIX . "order` o ON (cr.order_id = o.order_id) WHERE cgd.language_id = '" . (int)$this->config->get('config_language_id') . "'";
+
+ if (!empty($data['filter_date_start'])) {
+ $sql .= " AND DATE(cr.date_added) >= '" . $this->db->escape($data['filter_date_start']) . "'";
+ }
+
+ if (!empty($data['filter_date_end'])) {
+ $sql .= " AND DATE(cr.date_added) <= '" . $this->db->escape($data['filter_date_end']) . "'";
+ }
+
+ if (!empty($data['filter_customer'])) {
+ $sql .= " AND CONCAT(c.firstname, ' ', c.lastname) LIKE '" . $this->db->escape($data['filter_customer']) . "'";
+ }
+
+ $sql .= " GROUP BY cr.customer_id ORDER BY points DESC";
+
+ if (isset($data['start']) || isset($data['limit'])) {
+ if ($data['start'] < 0) {
+ $data['start'] = 0;
+ }
+
+ if ($data['limit'] < 1) {
+ $data['limit'] = 20;
+ }
+
+ $sql .= " LIMIT " . (int)$data['start'] . "," . (int)$data['limit'];
+ }
+
+ $query = $this->db->query($sql);
+
+ return $query->rows;
+ }
+
+ public function getTotalRewardPoints($data = array()) {
+ $sql = "SELECT COUNT(DISTINCT cr.customer_id) AS total FROM `" . DB_PREFIX . "customer_reward` cr LEFT JOIN `" . DB_PREFIX . "customer` c ON (cr.customer_id = c.customer_id)";
+
+ $implode = array();
+
+ if (!empty($data['filter_date_start'])) {
+ $implode[] = "DATE(cr.date_added) >= '" . $this->db->escape($data['filter_date_start']) . "'";
+ }
+
+ if (!empty($data['filter_date_end'])) {
+ $implode[] = "DATE(cr.date_added) <= '" . $this->db->escape($data['filter_date_end']) . "'";
+ }
+
+ if (!empty($data['filter_customer'])) {
+ $implode[] = "CONCAT(c.firstname, ' ', c.lastname) LIKE '" . $this->db->escape($data['filter_customer']) . "'";
+ }
+
+ if ($implode) {
+ $sql .= " WHERE " . implode(" AND ", $implode);
+ }
+
+ $query = $this->db->query($sql);
+
+ return $query->row['total'];
+ }
+
+ public function getCustomerActivities($data = array()) {
+ $sql = "SELECT ca.customer_activity_id, ca.customer_id, ca.key, ca.data, ca.ip, ca.date_added FROM " . DB_PREFIX . "customer_activity ca LEFT JOIN " . DB_PREFIX . "customer c ON (ca.customer_id = c.customer_id)";
+
+ $implode = array();
+
+ if (!empty($data['filter_date_start'])) {
+ $implode[] = "DATE(ca.date_added) >= '" . $this->db->escape($data['filter_date_start']) . "'";
+ }
+
+ if (!empty($data['filter_date_end'])) {
+ $implode[] = "DATE(ca.date_added) <= '" . $this->db->escape($data['filter_date_end']) . "'";
+ }
+
+ if (!empty($data['filter_customer'])) {
+ $implode[] = "CONCAT(c.firstname, ' ', c.lastname) LIKE '" . $this->db->escape($data['filter_customer']) . "'";
+ }
+
+ if (!empty($data['filter_ip'])) {
+ $implode[] = "ca.ip LIKE '" . $this->db->escape($data['filter_ip']) . "'";
+ }
+
+ if ($implode) {
+ $sql .= " WHERE " . implode(" AND ", $implode);
+ }
+
+ $sql .= " ORDER BY ca.date_added DESC";
+
+ if (isset($data['start']) || isset($data['limit'])) {
+ if ($data['start'] < 0) {
+ $data['start'] = 0;
+ }
+
+ if ($data['limit'] < 1) {
+ $data['limit'] = 20;
+ }
+
+ $sql .= " LIMIT " . (int)$data['start'] . "," . (int)$data['limit'];
+ }
+
+ $query = $this->db->query($sql);
+
+ return $query->rows;
+ }
+
+ public function getTotalCustomerActivities($data = array()) {
+ $sql = "SELECT COUNT(*) AS total FROM `" . DB_PREFIX . "customer_activity` ca LEFT JOIN " . DB_PREFIX . "customer c ON (ca.customer_id = c.customer_id)";
+
+ $implode = array();
+
+ if (!empty($data['filter_date_start'])) {
+ $implode[] = "DATE(ca.date_added) >= '" . $this->db->escape($data['filter_date_start']) . "'";
+ }
+
+ if (!empty($data['filter_date_end'])) {
+ $implode[] = "DATE(ca.date_added) <= '" . $this->db->escape($data['filter_date_end']) . "'";
+ }
+
+ if (!empty($data['filter_customer'])) {
+ $implode[] = "CONCAT(c.firstname, ' ', c.lastname) LIKE '" . $this->db->escape($data['filter_customer']) . "'";
+ }
+
+ if (!empty($data['filter_ip'])) {
+ $implode[] = "ca.ip LIKE '" . $this->db->escape($data['filter_ip']) . "'";
+ }
+
+ if ($implode) {
+ $sql .= " WHERE " . implode(" AND ", $implode);
+ }
+
+ $query = $this->db->query($sql);
+
+ return $query->row['total'];
+ }
+
+ public function getCustomerSearches($data = array()) {
+ $sql = "SELECT cs.customer_id, cs.keyword, cs.category_id, cs.products, cs.ip, cs.date_added, CONCAT(c.firstname, ' ', c.lastname) AS customer FROM " . DB_PREFIX . "customer_search cs LEFT JOIN " . DB_PREFIX . "customer c ON (cs.customer_id = c.customer_id)";
+
+ $implode = array();
+
+ if (!empty($data['filter_date_start'])) {
+ $implode[] = "DATE(cs.date_added) >= '" . $this->db->escape($data['filter_date_start']) . "'";
+ }
+
+ if (!empty($data['filter_date_end'])) {
+ $implode[] = "DATE(cs.date_added) <= '" . $this->db->escape($data['filter_date_end']) . "'";
+ }
+
+ if (!empty($data['filter_keyword'])) {
+ $implode[] = "cs.keyword LIKE '" . $this->db->escape($data['filter_keyword']) . "%'";
+ }
+
+ if (!empty($data['filter_customer'])) {
+ $implode[] = "CONCAT(c.firstname, ' ', c.lastname) LIKE '" . $this->db->escape($data['filter_customer']) . "'";
+ }
+
+ if (!empty($data['filter_ip'])) {
+ $implode[] = "cs.ip LIKE '" . $this->db->escape($data['filter_ip']) . "'";
+ }
+
+ if ($implode) {
+ $sql .= " WHERE " . implode(" AND ", $implode);
+ }
+
+ $sql .= " ORDER BY cs.date_added DESC";
+
+ if (isset($data['start']) || isset($data['limit'])) {
+ if ($data['start'] < 0) {
+ $data['start'] = 0;
+ }
+
+ if ($data['limit'] < 1) {
+ $data['limit'] = 20;
+ }
+
+ $sql .= " LIMIT " . (int)$data['start'] . "," . (int)$data['limit'];
+ }
+
+ $query = $this->db->query($sql);
+
+ return $query->rows;
+ }
+
+ public function getTotalCustomerSearches($data = array()) {
+ $sql = "SELECT COUNT(*) AS total FROM `" . DB_PREFIX . "customer_search` cs LEFT JOIN " . DB_PREFIX . "customer c ON (cs.customer_id = c.customer_id)";
+
+ $implode = array();
+
+ if (!empty($data['filter_date_start'])) {
+ $implode[] = "DATE(cs.date_added) >= '" . $this->db->escape($data['filter_date_start']) . "'";
+ }
+
+ if (!empty($data['filter_date_end'])) {
+ $implode[] = "DATE(cs.date_added) <= '" . $this->db->escape($data['filter_date_end']) . "'";
+ }
+
+ if (!empty($data['filter_keyword'])) {
+ $implode[] = "cs.keyword LIKE '" . $this->db->escape($data['filter_keyword']) . "%'";
+ }
+
+ if (!empty($data['filter_customer'])) {
+ $implode[] = "CONCAT(c.firstname, ' ', c.lastname) LIKE '" . $this->db->escape($data['filter_customer']) . "'";
+ }
+
+ if (!empty($data['filter_ip'])) {
+ $implode[] = "cs.ip LIKE '" . $this->db->escape($data['filter_ip']) . "'";
+ }
+
+ if ($implode) {
+ $sql .= " WHERE " . implode(" AND ", $implode);
+ }
+
+ $query = $this->db->query($sql);
+
+ return $query->row['total'];
+ }
+}
diff --git a/public/admin/model/extension/report/customer_transaction.php b/public/admin/model/extension/report/customer_transaction.php
new file mode 100644
index 0000000..02ca94e
--- /dev/null
+++ b/public/admin/model/extension/report/customer_transaction.php
@@ -0,0 +1,62 @@
+<?php
+class ModelExtensionReportCustomerTransaction extends Model {
+ public function getTransactions($data = array()) {
+ $sql = "SELECT ct.customer_id, CONCAT(c.firstname, ' ', c.lastname) AS customer, c.email, cgd.name AS customer_group, c.status, SUM(ct.amount) AS total FROM `" . DB_PREFIX . "customer_transaction` ct LEFT JOIN `" . DB_PREFIX . "customer` c ON (ct.customer_id = c.customer_id) LEFT JOIN `" . DB_PREFIX . "customer_group_description` cgd ON (c.customer_group_id = cgd.customer_group_id) WHERE cgd.language_id = '" . (int)$this->config->get('config_language_id') . "'";
+
+ if (!empty($data['filter_date_start'])) {
+ $sql .= " AND DATE(ct.date_added) >= '" . $this->db->escape($data['filter_date_start']) . "'";
+ }
+
+ if (!empty($data['filter_date_end'])) {
+ $sql .= " AND DATE(ct.date_added) <= '" . $this->db->escape($data['filter_date_end']) . "'";
+ }
+
+ if (!empty($data['filter_customer'])) {
+ $sql .= " AND CONCAT(c.firstname, ' ', c.lastname) LIKE '" . $this->db->escape($data['filter_customer']) . "'";
+ }
+
+ $sql .= " GROUP BY ct.customer_id ORDER BY total DESC";
+
+ if (isset($data['start']) || isset($data['limit'])) {
+ if ($data['start'] < 0) {
+ $data['start'] = 0;
+ }
+
+ if ($data['limit'] < 1) {
+ $data['limit'] = 20;
+ }
+
+ $sql .= " LIMIT " . (int)$data['start'] . "," . (int)$data['limit'];
+ }
+
+ $query = $this->db->query($sql);
+
+ return $query->rows;
+ }
+
+ public function getTotalTransactions($data = array()) {
+ $sql = "SELECT COUNT(DISTINCT ct.customer_id) AS total FROM `" . DB_PREFIX . "customer_transaction` ct LEFT JOIN `" . DB_PREFIX . "customer` c ON (ct.customer_id = c.customer_id)";
+
+ $implode = array();
+
+ if (!empty($data['filter_date_start'])) {
+ $implode[] = "DATE(ct.date_added) >= '" . $this->db->escape($data['filter_date_start']) . "'";
+ }
+
+ if (!empty($data['filter_date_end'])) {
+ $implode[] = "DATE(ct.date_added) <= '" . $this->db->escape($data['filter_date_end']) . "'";
+ }
+
+ if (!empty($data['filter_customer'])) {
+ $implode[] = "CONCAT(c.firstname, ' ', c.lastname) LIKE '" . $this->db->escape($data['filter_customer']) . "'";
+ }
+
+ if ($implode) {
+ $sql .= " WHERE " . implode(" AND ", $implode);
+ }
+
+ $query = $this->db->query($sql);
+
+ return $query->row['total'];
+ }
+} \ No newline at end of file
diff --git a/public/admin/model/extension/report/marketing.php b/public/admin/model/extension/report/marketing.php
new file mode 100644
index 0000000..0eba986
--- /dev/null
+++ b/public/admin/model/extension/report/marketing.php
@@ -0,0 +1,60 @@
+<?php
+class ModelExtensionReportMarketing extends Model {
+ public function getMarketing($data = array()) {
+ $sql = "SELECT m.marketing_id, m.name AS campaign, m.code, m.clicks AS clicks, (SELECT COUNT(DISTINCT order_id) FROM `" . DB_PREFIX . "order` o1 WHERE o1.marketing_id = m.marketing_id";
+
+ if (!empty($data['filter_order_status_id'])) {
+ $sql .= " AND o1.order_status_id = '" . (int)$data['filter_order_status_id'] . "'";
+ } else {
+ $sql .= " AND o1.order_status_id > '0'";
+ }
+
+ if (!empty($data['filter_date_start'])) {
+ $sql .= " AND DATE(o1.date_added) >= '" . $this->db->escape($data['filter_date_start']) . "'";
+ }
+
+ if (!empty($data['filter_date_end'])) {
+ $sql .= " AND DATE(o1.date_added) <= '" . $this->db->escape($data['filter_date_end']) . "'";
+ }
+
+ $sql .= ") AS `orders`, (SELECT SUM(total) FROM `" . DB_PREFIX . "order` o2 WHERE o2.marketing_id = m.marketing_id";
+
+ if (!empty($data['filter_order_status_id'])) {
+ $sql .= " AND o2.order_status_id = '" . (int)$data['filter_order_status_id'] . "'";
+ } else {
+ $sql .= " AND o2.order_status_id > '0'";
+ }
+
+ if (!empty($data['filter_date_start'])) {
+ $sql .= " AND DATE(o2.date_added) >= '" . $this->db->escape($data['filter_date_start']) . "'";
+ }
+
+ if (!empty($data['filter_date_end'])) {
+ $sql .= " AND DATE(o2.date_added) <= '" . $this->db->escape($data['filter_date_end']) . "'";
+ }
+
+ $sql .= " GROUP BY o2.marketing_id) AS `total` FROM `" . DB_PREFIX . "marketing` m ORDER BY m.date_added ASC";
+
+ if (isset($data['start']) || isset($data['limit'])) {
+ if ($data['start'] < 0) {
+ $data['start'] = 0;
+ }
+
+ if ($data['limit'] < 1) {
+ $data['limit'] = 20;
+ }
+
+ $sql .= " LIMIT " . (int)$data['start'] . "," . (int)$data['limit'];
+ }
+
+ $query = $this->db->query($sql);
+
+ return $query->rows;
+ }
+
+ public function getTotalMarketing($data = array()) {
+ $query = $this->db->query("SELECT COUNT(*) AS total FROM `" . DB_PREFIX . "marketing`");
+
+ return $query->row['total'];
+ }
+} \ No newline at end of file
diff --git a/public/admin/model/extension/report/product.php b/public/admin/model/extension/report/product.php
new file mode 100644
index 0000000..78a0ae0
--- /dev/null
+++ b/public/admin/model/extension/report/product.php
@@ -0,0 +1,96 @@
+<?php
+class ModelExtensionReportProduct extends Model {
+ public function getProductsViewed($data = array()) {
+ $sql = "SELECT pd.name, p.model, p.viewed FROM " . DB_PREFIX . "product p LEFT JOIN " . DB_PREFIX . "product_description pd ON (p.product_id = pd.product_id) WHERE pd.language_id = '" . (int)$this->config->get('config_language_id') . "' AND p.viewed > 0 ORDER BY p.viewed DESC";
+
+ if (isset($data['start']) || isset($data['limit'])) {
+ if ($data['start'] < 0) {
+ $data['start'] = 0;
+ }
+
+ if ($data['limit'] < 1) {
+ $data['limit'] = 20;
+ }
+
+ $sql .= " LIMIT " . (int)$data['start'] . "," . (int)$data['limit'];
+ }
+
+ $query = $this->db->query($sql);
+
+ return $query->rows;
+ }
+
+ public function getTotalProductViews() {
+ $query = $this->db->query("SELECT SUM(viewed) AS total FROM " . DB_PREFIX . "product");
+
+ return $query->row['total'];
+ }
+
+ public function getTotalProductsViewed() {
+ $query = $this->db->query("SELECT COUNT(*) AS total FROM " . DB_PREFIX . "product WHERE viewed > 0");
+
+ return $query->row['total'];
+ }
+
+ public function reset() {
+ $this->db->query("UPDATE " . DB_PREFIX . "product SET viewed = '0'");
+ }
+
+ public function getPurchased($data = array()) {
+ $sql = "SELECT op.name, op.model, SUM(op.quantity) AS quantity, SUM((op.price + op.tax) * op.quantity) AS total FROM " . DB_PREFIX . "order_product op LEFT JOIN `" . DB_PREFIX . "order` o ON (op.order_id = o.order_id)";
+
+ if (!empty($data['filter_order_status_id'])) {
+ $sql .= " WHERE o.order_status_id = '" . (int)$data['filter_order_status_id'] . "'";
+ } else {
+ $sql .= " WHERE o.order_status_id > '0'";
+ }
+
+ if (!empty($data['filter_date_start'])) {
+ $sql .= " AND DATE(o.date_added) >= '" . $this->db->escape($data['filter_date_start']) . "'";
+ }
+
+ if (!empty($data['filter_date_end'])) {
+ $sql .= " AND DATE(o.date_added) <= '" . $this->db->escape($data['filter_date_end']) . "'";
+ }
+
+ $sql .= " GROUP BY op.product_id ORDER BY total DESC";
+
+ if (isset($data['start']) || isset($data['limit'])) {
+ if ($data['start'] < 0) {
+ $data['start'] = 0;
+ }
+
+ if ($data['limit'] < 1) {
+ $data['limit'] = 20;
+ }
+
+ $sql .= " LIMIT " . (int)$data['start'] . "," . (int)$data['limit'];
+ }
+
+ $query = $this->db->query($sql);
+
+ return $query->rows;
+ }
+
+ public function getTotalPurchased($data) {
+ $sql = "SELECT COUNT(DISTINCT op.product_id) AS total FROM `" . DB_PREFIX . "order_product` op LEFT JOIN `" . DB_PREFIX . "order` o ON (op.order_id = o.order_id)";
+
+ if (!empty($data['filter_order_status_id'])) {
+ $sql .= " WHERE o.order_status_id = '" . (int)$data['filter_order_status_id'] . "'";
+ } else {
+ $sql .= " WHERE o.order_status_id > '0'";
+ }
+
+ if (!empty($data['filter_date_start'])) {
+ $sql .= " AND DATE(o.date_added) >= '" . $this->db->escape($data['filter_date_start']) . "'";
+ }
+
+ if (!empty($data['filter_date_end'])) {
+ $sql .= " AND DATE(o.date_added) <= '" . $this->db->escape($data['filter_date_end']) . "'";
+ }
+
+ $query = $this->db->query($sql);
+
+ return $query->row['total'];
+ }
+}
diff --git a/public/admin/model/extension/report/return.php b/public/admin/model/extension/report/return.php
new file mode 100644
index 0000000..1afff7b
--- /dev/null
+++ b/public/admin/model/extension/report/return.php
@@ -0,0 +1,100 @@
+<?php
+class ModelExtensionReportReturn extends Model {
+ public function getReturns($data = array()) {
+ $sql = "SELECT MIN(r.date_added) AS date_start, MAX(r.date_added) AS date_end, COUNT(r.return_id) AS `returns` FROM `" . DB_PREFIX . "return` r";
+
+ if (!empty($data['filter_return_status_id'])) {
+ $sql .= " WHERE r.return_status_id = '" . (int)$data['filter_return_status_id'] . "'";
+ } else {
+ $sql .= " WHERE r.return_status_id > '0'";
+ }
+
+ if (!empty($data['filter_date_start'])) {
+ $sql .= " AND DATE(r.date_added) >= '" . $this->db->escape($data['filter_date_start']) . "'";
+ }
+
+ if (!empty($data['filter_date_end'])) {
+ $sql .= " AND DATE(r.date_added) <= '" . $this->db->escape($data['filter_date_end']) . "'";
+ }
+
+ if (isset($data['filter_group'])) {
+ $group = $data['filter_group'];
+ } else {
+ $group = 'week';
+ }
+
+ switch($group) {
+ case 'day';
+ $sql .= " GROUP BY YEAR(r.date_added), MONTH(r.date_added), DAY(r.date_added)";
+ break;
+ default:
+ case 'week':
+ $sql .= " GROUP BY YEAR(r.date_added), WEEK(r.date_added)";
+ break;
+ case 'month':
+ $sql .= " GROUP BY YEAR(r.date_added), MONTH(r.date_added)";
+ break;
+ case 'year':
+ $sql .= " GROUP BY YEAR(r.date_added)";
+ break;
+ }
+
+ if (isset($data['start']) || isset($data['limit'])) {
+ if ($data['start'] < 0) {
+ $data['start'] = 0;
+ }
+
+ if ($data['limit'] < 1) {
+ $data['limit'] = 20;
+ }
+
+ $sql .= " LIMIT " . (int)$data['start'] . "," . (int)$data['limit'];
+ }
+
+ $query = $this->db->query($sql);
+
+ return $query->rows;
+ }
+
+ public function getTotalReturns($data = array()) {
+ if (!empty($data['filter_group'])) {
+ $group = $data['filter_group'];
+ } else {
+ $group = 'week';
+ }
+
+ switch($group) {
+ case 'day';
+ $sql = "SELECT COUNT(DISTINCT YEAR(date_added), MONTH(date_added), DAY(date_added)) AS total FROM `" . DB_PREFIX . "return`";
+ break;
+ default:
+ case 'week':
+ $sql = "SELECT COUNT(DISTINCT YEAR(date_added), WEEK(date_added)) AS total FROM `" . DB_PREFIX . "return`";
+ break;
+ case 'month':
+ $sql = "SELECT COUNT(DISTINCT YEAR(date_added), MONTH(date_added)) AS total FROM `" . DB_PREFIX . "return`";
+ break;
+ case 'year':
+ $sql = "SELECT COUNT(DISTINCT YEAR(date_added)) AS total FROM `" . DB_PREFIX . "return`";
+ break;
+ }
+
+ if (!empty($data['filter_return_status_id'])) {
+ $sql .= " WHERE return_status_id = '" . (int)$data['filter_return_status_id'] . "'";
+ } else {
+ $sql .= " WHERE return_status_id > '0'";
+ }
+
+ if (!empty($data['filter_date_start'])) {
+ $sql .= " AND DATE(date_added) >= '" . $this->db->escape($data['filter_date_start']) . "'";
+ }
+
+ if (!empty($data['filter_date_end'])) {
+ $sql .= " AND DATE(date_added) <= '" . $this->db->escape($data['filter_date_end']) . "'";
+ }
+
+ $query = $this->db->query($sql);
+
+ return $query->row['total'];
+ }
+} \ No newline at end of file
diff --git a/public/admin/model/extension/report/sale.php b/public/admin/model/extension/report/sale.php
new file mode 100644
index 0000000..21073f5
--- /dev/null
+++ b/public/admin/model/extension/report/sale.php
@@ -0,0 +1,438 @@
+<?php
+class ModelExtensionReportSale extends Model {
+ public function getTotalSales($data = array()) {
+ $sql = "SELECT SUM(total) AS total FROM `" . DB_PREFIX . "order` WHERE order_status_id > '0'";
+
+ if (!empty($data['filter_date_added'])) {
+ $sql .= " AND DATE(date_added) = DATE('" . $this->db->escape($data['filter_date_added']) . "')";
+ }
+
+ $query = $this->db->query($sql);
+
+ return $query->row['total'];
+ }
+
+ public function getTotalOrdersByCountry() {
+ $query = $this->db->query("SELECT COUNT(*) AS total, SUM(o.total) AS amount, c.iso_code_2 FROM `" . DB_PREFIX . "order` o LEFT JOIN `" . DB_PREFIX . "country` c ON (o.payment_country_id = c.country_id) WHERE o.order_status_id > '0' GROUP BY o.payment_country_id");
+
+ return $query->rows;
+ }
+
+ public function getTotalOrdersByDay() {
+ $implode = array();
+
+ foreach ($this->config->get('config_complete_status') as $order_status_id) {
+ $implode[] = "'" . (int)$order_status_id . "'";
+ }
+
+ $order_data = array();
+
+ for ($i = 0; $i < 24; $i++) {
+ $order_data[$i] = array(
+ 'hour' => $i,
+ 'total' => 0
+ );
+ }
+
+ $query = $this->db->query("SELECT COUNT(*) AS total, HOUR(date_added) AS hour FROM `" . DB_PREFIX . "order` WHERE order_status_id IN(" . implode(",", $implode) . ") AND DATE(date_added) = DATE(NOW()) GROUP BY HOUR(date_added) ORDER BY date_added ASC");
+
+ foreach ($query->rows as $result) {
+ $order_data[$result['hour']] = array(
+ 'hour' => $result['hour'],
+ 'total' => $result['total']
+ );
+ }
+
+ return $order_data;
+ }
+
+ public function getTotalOrdersByWeek() {
+ $implode = array();
+
+ foreach ($this->config->get('config_complete_status') as $order_status_id) {
+ $implode[] = "'" . (int)$order_status_id . "'";
+ }
+
+ $order_data = array();
+
+ $date_start = strtotime('-' . date('w') . ' days');
+
+ for ($i = 0; $i < 7; $i++) {
+ $date = date('Y-m-d', $date_start + ($i * 86400));
+
+ $order_data[date('w', strtotime($date))] = array(
+ 'day' => date('D', strtotime($date)),
+ 'total' => 0
+ );
+ }
+
+ $query = $this->db->query("SELECT COUNT(*) AS total, date_added FROM `" . DB_PREFIX . "order` WHERE order_status_id IN(" . implode(",", $implode) . ") AND DATE(date_added) >= DATE('" . $this->db->escape(date('Y-m-d', $date_start)) . "') GROUP BY DAYNAME(date_added)");
+
+ foreach ($query->rows as $result) {
+ $order_data[date('w', strtotime($result['date_added']))] = array(
+ 'day' => date('D', strtotime($result['date_added'])),
+ 'total' => $result['total']
+ );
+ }
+
+ return $order_data;
+ }
+
+ public function getTotalOrdersByMonth() {
+ $implode = array();
+
+ foreach ($this->config->get('config_complete_status') as $order_status_id) {
+ $implode[] = "'" . (int)$order_status_id . "'";
+ }
+
+ $order_data = array();
+
+ for ($i = 1; $i <= date('t'); $i++) {
+ $date = date('Y') . '-' . date('m') . '-' . $i;
+
+ $order_data[date('j', strtotime($date))] = array(
+ 'day' => date('d', strtotime($date)),
+ 'total' => 0
+ );
+ }
+
+ $query = $this->db->query("SELECT COUNT(*) AS total, date_added FROM `" . DB_PREFIX . "order` WHERE order_status_id IN(" . implode(",", $implode) . ") AND DATE(date_added) >= '" . $this->db->escape(date('Y') . '-' . date('m') . '-1') . "' GROUP BY DATE(date_added)");
+
+ foreach ($query->rows as $result) {
+ $order_data[date('j', strtotime($result['date_added']))] = array(
+ 'day' => date('d', strtotime($result['date_added'])),
+ 'total' => $result['total']
+ );
+ }
+
+ return $order_data;
+ }
+
+ public function getTotalOrdersByYear() {
+ $implode = array();
+
+ foreach ($this->config->get('config_complete_status') as $order_status_id) {
+ $implode[] = "'" . (int)$order_status_id . "'";
+ }
+
+ $order_data = array();
+
+ for ($i = 1; $i <= 12; $i++) {
+ $order_data[$i] = array(
+ 'month' => date('M', mktime(0, 0, 0, $i)),
+ 'total' => 0
+ );
+ }
+
+ $query = $this->db->query("SELECT COUNT(*) AS total, date_added FROM `" . DB_PREFIX . "order` WHERE order_status_id IN(" . implode(",", $implode) . ") AND YEAR(date_added) = YEAR(NOW()) GROUP BY MONTH(date_added)");
+
+ foreach ($query->rows as $result) {
+ $order_data[date('n', strtotime($result['date_added']))] = array(
+ 'month' => date('M', strtotime($result['date_added'])),
+ 'total' => $result['total']
+ );
+ }
+
+ return $order_data;
+ }
+
+ public function getOrders($data = array()) {
+ $sql = "SELECT MIN(o.date_added) AS date_start, MAX(o.date_added) AS date_end, COUNT(*) AS `orders`, SUM((SELECT SUM(op.quantity) FROM `" . DB_PREFIX . "order_product` op WHERE op.order_id = o.order_id GROUP BY op.order_id)) AS products, SUM((SELECT SUM(ot.value) FROM `" . DB_PREFIX . "order_total` ot WHERE ot.order_id = o.order_id AND ot.code = 'tax' GROUP BY ot.order_id)) AS tax, SUM(o.total) AS `total` FROM `" . DB_PREFIX . "order` o";
+
+ if (!empty($data['filter_order_status_id'])) {
+ $sql .= " WHERE o.order_status_id = '" . (int)$data['filter_order_status_id'] . "'";
+ } else {
+ $sql .= " WHERE o.order_status_id > '0'";
+ }
+
+ if (!empty($data['filter_date_start'])) {
+ $sql .= " AND DATE(o.date_added) >= '" . $this->db->escape($data['filter_date_start']) . "'";
+ }
+
+ if (!empty($data['filter_date_end'])) {
+ $sql .= " AND DATE(o.date_added) <= '" . $this->db->escape($data['filter_date_end']) . "'";
+ }
+
+ if (!empty($data['filter_group'])) {
+ $group = $data['filter_group'];
+ } else {
+ $group = 'week';
+ }
+
+ switch($group) {
+ case 'day';
+ $sql .= " GROUP BY YEAR(o.date_added), MONTH(o.date_added), DAY(o.date_added)";
+ break;
+ default:
+ case 'week':
+ $sql .= " GROUP BY YEAR(o.date_added), WEEK(o.date_added)";
+ break;
+ case 'month':
+ $sql .= " GROUP BY YEAR(o.date_added), MONTH(o.date_added)";
+ break;
+ case 'year':
+ $sql .= " GROUP BY YEAR(o.date_added)";
+ break;
+ }
+
+ $sql .= " ORDER BY o.date_added DESC";
+
+ if (isset($data['start']) || isset($data['limit'])) {
+ if ($data['start'] < 0) {
+ $data['start'] = 0;
+ }
+
+ if ($data['limit'] < 1) {
+ $data['limit'] = 20;
+ }
+
+ $sql .= " LIMIT " . (int)$data['start'] . "," . (int)$data['limit'];
+ }
+
+ $query = $this->db->query($sql);
+
+ return $query->rows;
+ }
+
+ public function getTotalOrders($data = array()) {
+ if (!empty($data['filter_group'])) {
+ $group = $data['filter_group'];
+ } else {
+ $group = 'week';
+ }
+
+ switch($group) {
+ case 'day';
+ $sql = "SELECT COUNT(DISTINCT YEAR(date_added), MONTH(date_added), DAY(date_added)) AS total FROM `" . DB_PREFIX . "order`";
+ break;
+ default:
+ case 'week':
+ $sql = "SELECT COUNT(DISTINCT YEAR(date_added), WEEK(date_added)) AS total FROM `" . DB_PREFIX . "order`";
+ break;
+ case 'month':
+ $sql = "SELECT COUNT(DISTINCT YEAR(date_added), MONTH(date_added)) AS total FROM `" . DB_PREFIX . "order`";
+ break;
+ case 'year':
+ $sql = "SELECT COUNT(DISTINCT YEAR(date_added)) AS total FROM `" . DB_PREFIX . "order`";
+ break;
+ }
+
+ if (!empty($data['filter_order_status_id'])) {
+ $sql .= " WHERE order_status_id = '" . (int)$data['filter_order_status_id'] . "'";
+ } else {
+ $sql .= " WHERE order_status_id > '0'";
+ }
+
+ if (!empty($data['filter_date_start'])) {
+ $sql .= " AND DATE(date_added) >= '" . $this->db->escape($data['filter_date_start']) . "'";
+ }
+
+ if (!empty($data['filter_date_end'])) {
+ $sql .= " AND DATE(date_added) <= '" . $this->db->escape($data['filter_date_end']) . "'";
+ }
+
+ $query = $this->db->query($sql);
+
+ return $query->row['total'];
+ }
+
+ public function getTaxes($data = array()) {
+ $sql = "SELECT MIN(o.date_added) AS date_start, MAX(o.date_added) AS date_end, ot.title, SUM(ot.value) AS total, COUNT(o.order_id) AS `orders` FROM `" . DB_PREFIX . "order` o LEFT JOIN `" . DB_PREFIX . "order_total` ot ON (ot.order_id = o.order_id) WHERE ot.code = 'tax'";
+
+ if (!empty($data['filter_order_status_id'])) {
+ $sql .= " AND o.order_status_id = '" . (int)$data['filter_order_status_id'] . "'";
+ } else {
+ $sql .= " AND o.order_status_id > '0'";
+ }
+
+ if (!empty($data['filter_date_start'])) {
+ $sql .= " AND DATE(o.date_added) >= '" . $this->db->escape($data['filter_date_start']) . "'";
+ }
+
+ if (!empty($data['filter_date_end'])) {
+ $sql .= " AND DATE(o.date_added) <= '" . $this->db->escape($data['filter_date_end']) . "'";
+ }
+
+ if (!empty($data['filter_group'])) {
+ $group = $data['filter_group'];
+ } else {
+ $group = 'week';
+ }
+
+ switch($group) {
+ case 'day';
+ $sql .= " GROUP BY YEAR(o.date_added), MONTH(o.date_added), DAY(o.date_added), ot.title";
+ break;
+ default:
+ case 'week':
+ $sql .= " GROUP BY YEAR(o.date_added), WEEK(o.date_added), ot.title";
+ break;
+ case 'month':
+ $sql .= " GROUP BY YEAR(o.date_added), MONTH(o.date_added), ot.title";
+ break;
+ case 'year':
+ $sql .= " GROUP BY YEAR(o.date_added), ot.title";
+ break;
+ }
+
+ if (isset($data['start']) || isset($data['limit'])) {
+ if ($data['start'] < 0) {
+ $data['start'] = 0;
+ }
+
+ if ($data['limit'] < 1) {
+ $data['limit'] = 20;
+ }
+
+ $sql .= " LIMIT " . (int)$data['start'] . "," . (int)$data['limit'];
+ }
+
+ $query = $this->db->query($sql);
+
+ return $query->rows;
+ }
+
+ public function getTotalTaxes($data = array()) {
+ if (!empty($data['filter_group'])) {
+ $group = $data['filter_group'];
+ } else {
+ $group = 'week';
+ }
+
+ switch($group) {
+ case 'day';
+ $sql = "SELECT COUNT(DISTINCT YEAR(o.date_added), MONTH(o.date_added), DAY(o.date_added), ot.title) AS total FROM `" . DB_PREFIX . "order` o";
+ break;
+ default:
+ case 'week':
+ $sql = "SELECT COUNT(DISTINCT YEAR(o.date_added), WEEK(o.date_added), ot.title) AS total FROM `" . DB_PREFIX . "order` o";
+ break;
+ case 'month':
+ $sql = "SELECT COUNT(DISTINCT YEAR(o.date_added), MONTH(o.date_added), ot.title) AS total FROM `" . DB_PREFIX . "order` o";
+ break;
+ case 'year':
+ $sql = "SELECT COUNT(DISTINCT YEAR(o.date_added), ot.title) AS total FROM `" . DB_PREFIX . "order` o";
+ break;
+ }
+
+ $sql .= " LEFT JOIN `" . DB_PREFIX . "order_total` ot ON (o.order_id = ot.order_id) WHERE ot.code = 'tax'";
+
+ if (!empty($data['filter_order_status_id'])) {
+ $sql .= " AND o.order_status_id = '" . (int)$data['filter_order_status_id'] . "'";
+ } else {
+ $sql .= " AND o.order_status_id > '0'";
+ }
+
+ if (!empty($data['filter_date_start'])) {
+ $sql .= " AND DATE(o.date_added) >= '" . $this->db->escape($data['filter_date_start']) . "'";
+ }
+
+ if (!empty($data['filter_date_end'])) {
+ $sql .= " AND DATE(o.date_added) <= '" . $this->db->escape($data['filter_date_end']) . "'";
+ }
+
+ $query = $this->db->query($sql);
+
+ return $query->row['total'];
+ }
+
+ public function getShipping($data = array()) {
+ $sql = "SELECT MIN(o.date_added) AS date_start, MAX(o.date_added) AS date_end, ot.title, SUM(ot.value) AS total, COUNT(o.order_id) AS `orders` FROM `" . DB_PREFIX . "order` o LEFT JOIN `" . DB_PREFIX . "order_total` ot ON (o.order_id = ot.order_id) WHERE ot.code = 'shipping'";
+
+ if (!empty($data['filter_order_status_id'])) {
+ $sql .= " AND o.order_status_id = '" . (int)$data['filter_order_status_id'] . "'";
+ } else {
+ $sql .= " AND o.order_status_id > '0'";
+ }
+
+ if (!empty($data['filter_date_start'])) {
+ $sql .= " AND DATE(o.date_added) >= '" . $this->db->escape($data['filter_date_start']) . "'";
+ }
+
+ if (!empty($data['filter_date_end'])) {
+ $sql .= " AND DATE(o.date_added) <= '" . $this->db->escape($data['filter_date_end']) . "'";
+ }
+
+ if (!empty($data['filter_group'])) {
+ $group = $data['filter_group'];
+ } else {
+ $group = 'week';
+ }
+
+ switch($group) {
+ case 'day';
+ $sql .= " GROUP BY YEAR(o.date_added), MONTH(o.date_added), DAY(o.date_added), ot.title";
+ break;
+ default:
+ case 'week':
+ $sql .= " GROUP BY YEAR(o.date_added), WEEK(o.date_added), ot.title";
+ break;
+ case 'month':
+ $sql .= " GROUP BY YEAR(o.date_added), MONTH(o.date_added), ot.title";
+ break;
+ case 'year':
+ $sql .= " GROUP BY YEAR(o.date_added), ot.title";
+ break;
+ }
+
+ if (isset($data['start']) || isset($data['limit'])) {
+ if ($data['start'] < 0) {
+ $data['start'] = 0;
+ }
+
+ if ($data['limit'] < 1) {
+ $data['limit'] = 20;
+ }
+
+ $sql .= " LIMIT " . (int)$data['start'] . "," . (int)$data['limit'];
+ }
+
+ $query = $this->db->query($sql);
+
+ return $query->rows;
+ }
+
+ public function getTotalShipping($data = array()) {
+ if (!empty($data['filter_group'])) {
+ $group = $data['filter_group'];
+ } else {
+ $group = 'week';
+ }
+
+ switch($group) {
+ case 'day';
+ $sql = "SELECT COUNT(DISTINCT YEAR(o.date_added), MONTH(o.date_added), DAY(o.date_added), ot.title) AS total FROM `" . DB_PREFIX . "order` o";
+ break;
+ default:
+ case 'week':
+ $sql = "SELECT COUNT(DISTINCT YEAR(o.date_added), WEEK(o.date_added), ot.title) AS total FROM `" . DB_PREFIX . "order` o";
+ break;
+ case 'month':
+ $sql = "SELECT COUNT(DISTINCT YEAR(o.date_added), MONTH(o.date_added), ot.title) AS total FROM `" . DB_PREFIX . "order` o";
+ break;
+ case 'year':
+ $sql = "SELECT COUNT(DISTINCT YEAR(o.date_added), ot.title) AS total FROM `" . DB_PREFIX . "order` o";
+ break;
+ }
+
+ $sql .= " LEFT JOIN `" . DB_PREFIX . "order_total` ot ON (o.order_id = ot.order_id) WHERE ot.code = 'shipping'";
+
+ if (!empty($data['filter_order_status_id'])) {
+ $sql .= " AND order_status_id = '" . (int)$data['filter_order_status_id'] . "'";
+ } else {
+ $sql .= " AND order_status_id > '0'";
+ }
+
+ if (!empty($data['filter_date_start'])) {
+ $sql .= " AND DATE(o.date_added) >= '" . $this->db->escape($data['filter_date_start']) . "'";
+ }
+
+ if (!empty($data['filter_date_end'])) {
+ $sql .= " AND DATE(o.date_added) <= '" . $this->db->escape($data['filter_date_end']) . "'";
+ }
+
+ $query = $this->db->query($sql);
+
+ return $query->row['total'];
+ }
+} \ No newline at end of file