├── README.md ├── admin ├── controller │ └── feed │ │ └── web_api.php ├── language │ ├── english │ │ └── feed │ │ │ └── web_api.php │ └── russian │ │ └── feed │ │ └── web_api.php └── view │ └── template │ └── feed │ └── web_api.tpl └── catalog └── controller └── feed └── web_api.php /README.md: -------------------------------------------------------------------------------- 1 | Opencart WEB API 2 | ================ 3 | 4 | This is a small module that adds the ability to remotely work with the OpenCart 1.5.3+ via the REST API. 5 | 6 | * Homepage: http://zenwalker.ru/lab/opencart-webapi/ 7 | * Sources: https://github.com/ethernet1/opencart-webapi 8 | * Ddocumentation in Russian: http://zenwalker.ru/lab/opencart-webapi/documentation.html 9 | 10 | Features: 11 | 12 | * [Get categories list](#get-categories) 13 | * [Get category info](#get-category-info) 14 | * [Get products from category](#get-products) 15 | * [Get full info from product](#get-product) 16 | 17 | 18 | Examples 19 | -------- 20 | 21 | ### Get categories 22 | 23 | Request: 24 | 25 | http://example.com/?route=feed/web_api/categories&parent=0&level=2 26 | 27 | 28 | Params: 29 | 30 | * $_GET['parent']: parent category id 31 | * $_GET['level']: depth level 32 | 33 | 34 | Answer: 35 | 36 | { 37 | "success": true, 38 | 39 | categories: 40 | [ 41 | { 42 | "category_id": "1", 43 | "name": "First category", 44 | "parent_id": "0", 45 | "href": "http://example.com/index.php?route=product/category&category_id=1" 46 | "categories": null, 47 | }, 48 | { 49 | "category_id": "2", 50 | "name": "Second category", 51 | "parent_id": "0", 52 | "href": "http://example.com/index.php?route=product/category&category_id=2" 53 | "categories": [ 54 | { 55 | "category_id": "3", 56 | "name": "Inner category", 57 | "parent_id": "2", 58 | "href": "http://example.com/index.php?route=product/category&category_id=3" 59 | "categories": null 60 | }, 61 | { 62 | "category_id": "3", 63 | "name": "Inner category", 64 | "parent_id": "2", 65 | "href": "http://example.com/index.php?route=product/category&category_id=4" 66 | "categories": null 67 | } 68 | ] 69 | } 70 | ] 71 | } 72 | 73 | 74 | ### Get category info 75 | 76 | Request: 77 | 78 | http://example.com/?route=feed/web_api/category&id=1 79 | 80 | 81 | Params: 82 | 83 | * $_GET['id']: category id 84 | 85 | 86 | Answer: 87 | 88 | { 89 | "success":true, 90 | 91 | "category":{ 92 | "id": "1", 93 | "name": "Category name", 94 | "description": "", 95 | "href": "http://example.com/index.php?route=product/category&category_id=1" 96 | } 97 | } 98 | 99 | 100 | 101 | ### Get products 102 | 103 | Request: 104 | 105 | http://example.com/?route=feed/web_api/products&category=1 106 | 107 | 108 | Params: 109 | 110 | * $_GET['category']: parent category id 111 | 112 | 113 | Answer: 114 | 115 | { 116 | "success": true, 117 | 118 | products: [ 119 | { 120 | "id": "6", 121 | "name": "Product name", 122 | "description": "", 123 | "pirce": "$455.00", 124 | "href": "http://example.com/index.php?route=product/product&product_id=6", 125 | "thumb": false, 126 | "special": false, 127 | "rating": 0 128 | }, 129 | { 130 | "id": "7", 131 | "name": "Product name", 132 | "description": "", 133 | "pirce": "$25.00", 134 | "href": "http://example.com/index.php?route=product/product&product_id=7", 135 | "thumb": false, 136 | "special": false, 137 | "rating": 0 138 | } 139 | ] 140 | } 141 | 142 | 143 | 144 | ### Get product 145 | 146 | Request: 147 | 148 | http://example.com/?route=feed/web_api/product&id=1 149 | 150 | Params: 151 | 152 | * $_GET['id']: product id 153 | 154 | Answer: 155 | 156 | { 157 | "success":true, 158 | 159 | "product":{ 160 | "id": "2", 161 | "seo_h1": "", 162 | "name": "Product name", 163 | "manufacturer":null, 164 | "model": "A1", 165 | "reward":null, 166 | "points": "0", 167 | "image": "", 168 | "images":[], 169 | "price": "$10.00", 170 | "special":false, 171 | "discounts":[], 172 | "options":[ 173 | { 174 | "product_option_id": "2", 175 | "option_id": "5", 176 | "name": "Select", 177 | "type": "select", 178 | "option_value":[ 179 | 180 | ], 181 | "required": "1" 182 | }, 183 | { 184 | "product_option_id": "1", 185 | "option_id": "2", 186 | "name": "Checkbox", 187 | "type": "checkbox", 188 | "option_value":[ 189 | { 190 | "product_option_value_id": "1", 191 | "option_value_id": "24", 192 | "name": "Checkbox 2", 193 | "image":null, 194 | "price": "$20.00", 195 | "price_prefix": "+" 196 | } 197 | ], 198 | "required": "1" 199 | } 200 | ], 201 | "minimum": "1", 202 | "rating": 0, 203 | "description": "HTML Description", 204 | "attribute_groups":[ 205 | { 206 | "attribute_group_id": "1", 207 | "name": "Attribute group 1", 208 | "attribute":[ 209 | { 210 | "attribute_id": "10", 211 | "name": "Attribute 1", 212 | "text": "20" 213 | }, 214 | { 215 | "attribute_id": "70", 216 | "name": "Attrubute 2", 217 | "text": "Value" 218 | } 219 | ] 220 | } 221 | ] 222 | } 223 | } 224 | 225 | 226 | 227 | ### Error handling 228 | 229 | Answer: 230 | 231 | { 232 | "success": false, 233 | "code": 20, 234 | "message": "Invalid secret key" 235 | } 236 | 237 | Error codes: 238 | 239 | * 10 - Module disabled 240 | * 20 - Invalid secret key 241 | 242 | 243 | License 244 | ------- 245 | 246 | This software is distributed under the [GNU GPL V3](http://www.gnu.org/licenses/gpl.html) License. -------------------------------------------------------------------------------- /admin/controller/feed/web_api.php: -------------------------------------------------------------------------------- 1 | load->language('feed/web_api'); 7 | $this->load->model('setting/setting'); 8 | 9 | $this->document->setTitle($this->language->get('heading_title')); 10 | 11 | 12 | $this->data = array( 13 | 'version' => '1.0', 14 | 'heading_title' => $this->language->get('heading_title'), 15 | 16 | 'text_enabled' => $this->language->get('text_enabled'), 17 | 'text_disabled' => $this->language->get('text_disabled'), 18 | 'text_homepage' => $this->language->get('text_homepage'), 19 | 'tab_general' => $this->language->get('tab_general'), 20 | 21 | 'entry_status' => $this->language->get('entry_status'), 22 | 'entry_key' => $this->language->get('entry_key'), 23 | 24 | 'button_save' => $this->language->get('button_save'), 25 | 'button_cancel' => $this->language->get('button_cancel'), 26 | 27 | 'action' => $this->url->link('feed/web_api', 'token=' . $this->session->data['token'], 'SSL'), 28 | 'cancel' => $this->url->link('extension/feed', 'token=' . $this->session->data['token'], 'SSL') 29 | ); 30 | 31 | if (($this->request->server['REQUEST_METHOD'] == 'POST')) { 32 | $this->model_setting_setting->editSetting('web_api', $this->request->post); 33 | $this->session->data['success'] = $this->language->get('text_success'); 34 | $this->redirect($this->url->link('extension/feed', 'token=' . $this->session->data['token'], 'SSL')); 35 | } 36 | 37 | $this->data['breadcrumbs'] = array(); 38 | 39 | $this->data['breadcrumbs'][] = array( 40 | 'text' => $this->language->get('text_home'), 41 | 'href' => $this->url->link('common/home', 'token=' . $this->session->data['token'], 'SSL'), 42 | 'separator' => false 43 | ); 44 | 45 | $this->data['breadcrumbs'][] = array( 46 | 'text' => $this->language->get('text_feed'), 47 | 'href' => $this->url->link('extension/feed', 'token=' . $this->session->data['token'], 'SSL'), 48 | 'separator' => ' :: ' 49 | ); 50 | 51 | $this->data['breadcrumbs'][] = array( 52 | 'text' => $this->language->get('heading_title'), 53 | 'href' => $this->url->link('feed/web_api', 'token=' . $this->session->data['token'], 'SSL'), 54 | 'separator' => ' :: ' 55 | ); 56 | 57 | if (isset($this->request->post['web_api_status'])) { 58 | $this->data['web_api_status'] = $this->request->post['web_api_status']; 59 | } else { 60 | $this->data['web_api_status'] = $this->config->get('web_api_status'); 61 | } 62 | 63 | if (isset($this->request->post['web_api_key'])) { 64 | $this->data['web_api_key'] = $this->request->post['web_api_key']; 65 | } else { 66 | $this->data['web_api_key'] = $this->config->get('web_api_key'); 67 | } 68 | 69 | 70 | $this->template = 'feed/web_api.tpl'; 71 | 72 | $this->children = array( 73 | 'common/header', 74 | 'common/footer' 75 | ); 76 | 77 | $this->response->setOutput($this->render()); 78 | } 79 | 80 | } -------------------------------------------------------------------------------- /admin/language/english/feed/web_api.php: -------------------------------------------------------------------------------- 1 | 2 |
51 | 52 | 55 | 56 | -------------------------------------------------------------------------------- /catalog/controller/feed/web_api.php: -------------------------------------------------------------------------------- 1 | init(); 10 | $this->load->model('catalog/category'); 11 | $json = array('success' => true); 12 | 13 | # -- $_GET params ------------------------------ 14 | 15 | if (isset($this->request->get['parent'])) { 16 | $parent = $this->request->get['parent']; 17 | } else { 18 | $parent = 0; 19 | } 20 | 21 | if (isset($this->request->get['level'])) { 22 | $level = $this->request->get['level']; 23 | } else { 24 | $level = 1; 25 | } 26 | 27 | # -- End $_GET params -------------------------- 28 | 29 | 30 | $json['categories'] = $this->getCategoriesTree($parent, $level); 31 | 32 | if ($this->debug) { 33 | echo ' 8 |'; 34 | print_r($json); 35 | } else { 36 | $this->response->setOutput(json_encode($json)); 37 | } 38 | } 39 | 40 | public function category() { 41 | $this->init(); 42 | $this->load->model('catalog/category'); 43 | $this->load->model('tool/image'); 44 | 45 | $json = array('success' => true); 46 | 47 | # -- $_GET params ------------------------------ 48 | 49 | if (isset($this->request->get['id'])) { 50 | $category_id = $this->request->get['id']; 51 | } else { 52 | $category_id = 0; 53 | } 54 | 55 | # -- End $_GET params -------------------------- 56 | 57 | $category = $this->model_catalog_category->getCategory($category_id); 58 | 59 | $json['category'] = array( 60 | 'id' => $category['category_id'], 61 | 'name' => $category['name'], 62 | 'description' => $category['description'], 63 | 'href' => $this->url->link('product/category', 'category_id=' . $category['category_id']) 64 | ); 65 | 66 | if ($this->debug) { 67 | echo ''; 68 | print_r($json); 69 | } else { 70 | $this->response->setOutput(json_encode($json)); 71 | } 72 | } 73 | 74 | 75 | public function products() { 76 | $this->init(); 77 | $this->load->model('catalog/product'); 78 | $this->load->model('tool/image'); 79 | $json = array('success' => true, 'products' => array()); 80 | 81 | 82 | # -- $_GET params ------------------------------ 83 | 84 | if (isset($this->request->get['category'])) { 85 | $category_id = $this->request->get['category']; 86 | } else { 87 | $category_id = 0; 88 | } 89 | 90 | # -- End $_GET params -------------------------- 91 | 92 | $products = $this->model_catalog_product->getProducts(array( 93 | 'filter_category_id' => $category_id 94 | )); 95 | 96 | foreach ($products as $product) { 97 | 98 | if ($product['image']) { 99 | $image = $this->model_tool_image->resize($product['image'], $this->config->get('config_image_product_width'), $this->config->get('config_image_product_height')); 100 | } else { 101 | $image = false; 102 | } 103 | 104 | if ((float)$product['special']) { 105 | $special = $this->currency->format($this->tax->calculate($product['special'], $product['tax_class_id'], $this->config->get('config_tax'))); 106 | } else { 107 | $special = false; 108 | } 109 | 110 | $json['products'][] = array( 111 | 'id' => $product['product_id'], 112 | 'name' => $product['name'], 113 | 'description' => $product['description'], 114 | 'pirce' => $this->currency->format($this->tax->calculate($product['price'], $product['tax_class_id'], $this->config->get('config_tax'))), 115 | 'href' => $this->url->link('product/product', 'product_id=' . $product['product_id']), 116 | 'thumb' => $image, 117 | 'special' => $special, 118 | 'rating' => $product['rating'] 119 | ); 120 | } 121 | 122 | if ($this->debug) { 123 | echo ''; 124 | print_r($json); 125 | } else { 126 | $this->response->setOutput(json_encode($json)); 127 | } 128 | } 129 | 130 | public function product() { 131 | $this->init(); 132 | $this->load->model('catalog/product'); 133 | $this->load->model('tool/image'); 134 | $json = array('success' => true); 135 | 136 | # -- $_GET params ------------------------------ 137 | 138 | if (isset($this->request->get['id'])) { 139 | $product_id = $this->request->get['id']; 140 | } else { 141 | $product_id = 0; 142 | } 143 | 144 | # -- End $_GET params -------------------------- 145 | 146 | $product = $this->model_catalog_product->getProduct($product_id); 147 | 148 | # product image 149 | if ($product['image']) { 150 | $image = $this->model_tool_image->resize($product['image'], $this->config->get('config_image_popup_width'), $this->config->get('config_image_popup_height')); 151 | } else { 152 | $image = ''; 153 | } 154 | 155 | #additional images 156 | $additional_images = $this->model_catalog_product->getProductImages($product['product_id']); 157 | $images = array(); 158 | 159 | foreach ($additional_images as $additional_image) { 160 | $images[] = $this->model_tool_image->resize($additional_image, $this->config->get('config_image_additional_width'), $this->config->get('config_image_additional_height')); 161 | } 162 | 163 | #specal 164 | if ((float)$product['special']) { 165 | $special = $this->currency->format($this->tax->calculate($product['special'], $product['tax_class_id'], $this->config->get('config_tax'))); 166 | } else { 167 | $special = false; 168 | } 169 | 170 | #discounts 171 | $discounts = array(); 172 | $data_discounts = $this->model_catalog_product->getProductDiscounts($product['product_id']); 173 | 174 | foreach ($data_discounts as $discount) { 175 | $discounts[] = array( 176 | 'quantity' => $discount['quantity'], 177 | 'price' => $this->currency->format($this->tax->calculate($discount['price'], $product['tax_class_id'], $this->config->get('config_tax'))) 178 | ); 179 | } 180 | 181 | #options 182 | $options = array(); 183 | 184 | foreach ($this->model_catalog_product->getProductOptions($product['product_id']) as $option) { 185 | if ($option['type'] == 'select' || $option['type'] == 'radio' || $option['type'] == 'checkbox' || $option['type'] == 'image') { 186 | $option_value_data = array(); 187 | 188 | foreach ($option['option_value'] as $option_value) { 189 | if (!$option_value['subtract'] || ($option_value['quantity'] > 0)) { 190 | if ((($this->config->get('config_customer_price') && $this->customer->isLogged()) || !$this->config->get('config_customer_price')) && (float)$option_value['price']) { 191 | $price = $this->currency->format($this->tax->calculate($option_value['price'], $product['tax_class_id'], $this->config->get('config_tax'))); 192 | } else { 193 | $price = false; 194 | } 195 | 196 | $option_value_data[] = array( 197 | 'product_option_value_id' => $option_value['product_option_value_id'], 198 | 'option_value_id' => $option_value['option_value_id'], 199 | 'name' => $option_value['name'], 200 | 'image' => $this->model_tool_image->resize($option_value['image'], 50, 50), 201 | 'price' => $price, 202 | 'price_prefix' => $option_value['price_prefix'] 203 | ); 204 | } 205 | } 206 | 207 | $options[] = array( 208 | 'product_option_id' => $option['product_option_id'], 209 | 'option_id' => $option['option_id'], 210 | 'name' => $option['name'], 211 | 'type' => $option['type'], 212 | 'option_value' => $option_value_data, 213 | 'required' => $option['required'] 214 | ); 215 | } elseif ($option['type'] == 'text' || $option['type'] == 'textarea' || $option['type'] == 'file' || $option['type'] == 'date' || $option['type'] == 'datetime' || $option['type'] == 'time') { 216 | $options[] = array( 217 | 'product_option_id' => $option['product_option_id'], 218 | 'option_id' => $option['option_id'], 219 | 'name' => $option['name'], 220 | 'type' => $option['type'], 221 | 'option_value' => $option['option_value'], 222 | 'required' => $option['required'] 223 | ); 224 | } 225 | } 226 | 227 | #minimum 228 | if ($product['minimum']) { 229 | $minimum = $product['minimum']; 230 | } else { 231 | $minimum = 1; 232 | } 233 | 234 | $json['product'] = array( 235 | 'id' => $product['product_id'], 236 | 'seo_h1' => $product['seo_h1'], 237 | 'name' => $product['name'], 238 | 'manufacturer' => $product['manufacturer'], 239 | 'model' => $product['model'], 240 | 'reward' => $product['reward'], 241 | 'points' => $product['points'], 242 | 'image' => $image, 243 | 'images' => $images, 244 | 'price' => $this->currency->format($this->tax->calculate($product['price'], $product['tax_class_id'], $this->config->get('config_tax'))), 245 | 'special' => $special, 246 | 'discounts' => $discounts, 247 | 'options' => $options, 248 | 'minimum' => $minimum, 249 | 'rating' => (int)$product['rating'], 250 | 'description' => html_entity_decode($product['description'], ENT_QUOTES, 'UTF-8'), 251 | 'attribute_groups' => $this->model_catalog_product->getProductAttributes($product['product_id']) 252 | ); 253 | 254 | 255 | if ($this->debug) { 256 | echo ''; 257 | print_r($json); 258 | } else { 259 | $this->response->setOutput(json_encode($json)); 260 | } 261 | } 262 | 263 | 264 | /** 265 | * Generation of category tree 266 | * 267 | * @param int $parent Prarent category id 268 | * @param int $level Depth level 269 | * @return array Tree 270 | */ 271 | private function getCategoriesTree($parent = 0, $level = 1) { 272 | $this->load->model('catalog/category'); 273 | $this->load->model('tool/image'); 274 | 275 | $result = array(); 276 | 277 | $categories = $this->model_catalog_category->getCategories($parent); 278 | 279 | if ($categories && $level > 0) { 280 | $level--; 281 | 282 | foreach ($categories as $category) { 283 | 284 | if ($category['image']) { 285 | $image = $this->model_tool_image->resize($category['image'], $this->config->get('config_image_category_width'), $this->config->get('config_image_category_height')); 286 | } else { 287 | $image = false; 288 | } 289 | 290 | $result[] = array( 291 | 'category_id' => $category['category_id'], 292 | 'parent_id' => $category['parent_id'], 293 | 'name' => $category['name'], 294 | 'image' => $image, 295 | 'href' => $this->url->link('product/category', 'category_id=' . $category['category_id']), 296 | 'categories' => $this->getCategoriesTree($category['category_id'], $level) 297 | ); 298 | } 299 | 300 | return $result; 301 | } 302 | } 303 | 304 | /** 305 | * 306 | */ 307 | private function init() { 308 | 309 | $this->response->addHeader('Content-Type: application/json'); 310 | 311 | if (!$this->config->get('web_api_status')) { 312 | $this->error(10, 'API is disabled'); 313 | } 314 | 315 | if ($this->config->get('web_api_key') && (!isset($this->request->get['key']) || $this->request->get['key'] != $this->config->get('web_api_key'))) { 316 | $this->error(20, 'Invalid secret key'); 317 | } 318 | } 319 | 320 | /** 321 | * Error message responser 322 | * 323 | * @param string $message Error message 324 | */ 325 | private function error($code = 0, $message = '') { 326 | 327 | # setOutput() is not called, set headers manually 328 | header('Content-Type: application/json'); 329 | 330 | $json = array( 331 | 'success' => false, 332 | 'code' => $code, 333 | 'message' => $message 334 | ); 335 | 336 | if ($this->debug) { 337 | echo ''; 338 | print_r($json); 339 | } else { 340 | echo json_encode($json); 341 | } 342 | 343 | exit(); 344 | } 345 | 346 | } 347 | --------------------------------------------------------------------------------