1: <?php
2: namespace Opencart\Catalog\Controller\Api\Sale;
3: /**
4: * Class Order
5: *
6: * @package Opencart\Catalog\Controller\Api\Sale
7: */
8: class Order extends \Opencart\System\Engine\Controller {
9: // Loads order info
10: /**
11: * Load
12: *
13: * @return void
14: */
15: public function load(): void {
16: $this->load->language('api/sale/order');
17:
18: $json = [];
19:
20: if (isset($this->request->get['order_id'])) {
21: $order_id = (int)$this->request->get['order_id'];
22: } else {
23: $order_id = 0;
24: }
25:
26: $this->load->model('checkout/order');
27:
28: $order_info = $this->model_checkout_order->getOrder($order_id);
29:
30: if (!$order_info) {
31: $json['error'] = $this->language->get('error_order');
32: }
33:
34: if (!$json) {
35: $this->session->data['order_id'] = $order_id;
36:
37: // Customer Details
38: $this->session->data['customer'] = [
39: 'customer_id' => $order_info['customer_id'],
40: 'customer_group_id' => $order_info['customer_group_id'],
41: 'firstname' => $order_info['firstname'],
42: 'lastname' => $order_info['lastname'],
43: 'email' => $order_info['email'],
44: 'telephone' => $order_info['telephone'],
45: 'custom_field' => $order_info['custom_field']
46: ];
47:
48: // Payment Details
49: if ($this->config->get('config_checkout_payment_address')) {
50: $this->session->data['payment_address'] = [
51: 'address_id' => $order_info['payment_address_id'],
52: 'firstname' => $order_info['payment_firstname'],
53: 'lastname' => $order_info['payment_lastname'],
54: 'company' => $order_info['payment_company'],
55: 'address_1' => $order_info['payment_address_1'],
56: 'address_2' => $order_info['payment_address_2'],
57: 'postcode' => $order_info['payment_postcode'],
58: 'city' => $order_info['payment_city'],
59: 'zone_id' => $order_info['payment_zone_id'],
60: 'zone' => $order_info['payment_zone'],
61: 'zone_code' => $order_info['payment_zone_code'],
62: 'country_id' => $order_info['payment_country_id'],
63: 'country' => $order_info['payment_country'],
64: 'iso_code_2' => $order_info['payment_iso_code_2'],
65: 'iso_code_3' => $order_info['payment_iso_code_3'],
66: 'address_format' => $order_info['payment_address_format'],
67: 'custom_field' => $order_info['payment_custom_field']
68: ];
69: } else {
70: unset($this->session->data['payment_address']);
71: }
72:
73: $this->session->data['payment_method'] = $order_info['payment_method'];
74:
75: if ($order_info['shipping_method']) {
76: $this->session->data['shipping_address'] = [
77: 'address_id' => $order_info['shipping_address_id'],
78: 'firstname' => $order_info['shipping_firstname'],
79: 'lastname' => $order_info['shipping_lastname'],
80: 'company' => $order_info['shipping_company'],
81: 'address_1' => $order_info['shipping_address_1'],
82: 'address_2' => $order_info['shipping_address_2'],
83: 'postcode' => $order_info['shipping_postcode'],
84: 'city' => $order_info['shipping_city'],
85: 'zone_id' => $order_info['shipping_zone_id'],
86: 'zone' => $order_info['shipping_zone'],
87: 'zone_code' => $order_info['shipping_zone_code'],
88: 'country_id' => $order_info['shipping_country_id'],
89: 'country' => $order_info['shipping_country'],
90: 'iso_code_2' => $order_info['shipping_iso_code_2'],
91: 'iso_code_3' => $order_info['shipping_iso_code_3'],
92: 'address_format' => $order_info['shipping_address_format'],
93: 'custom_field' => $order_info['shipping_custom_field']
94: ];
95:
96: $this->session->data['shipping_method'] = $order_info['shipping_method'];
97: }
98:
99: if ($order_info['comment']) {
100: $this->session->data['comment'] = $order_info['comment'];
101: }
102:
103: if ($order_info['currency_code']) {
104: $this->session->data['currency'] = $order_info['currency_code'];
105: }
106:
107: $products = $this->model_checkout_order->getProducts($order_id);
108:
109: foreach ($products as $product) {
110: $option_data = [];
111:
112: $options = $this->model_checkout_order->getOptions($order_id, $product['order_product_id']);
113:
114: foreach ($options as $option) {
115: if ($option['type'] == 'text' || $option['type'] == 'textarea' || $option['type'] == 'file' || $option['type'] == 'date' || $option['type'] == 'datetime' || $option['type'] == 'time') {
116: $option_data[$option['product_option_id']] = $option['value'];
117: } elseif ($option['type'] == 'select' || $option['type'] == 'radio') {
118: $option_data[$option['product_option_id']] = $option['product_option_value_id'];
119: } elseif ($option['type'] == 'checkbox') {
120: $option_data[$option['product_option_id']][] = $option['product_option_value_id'];
121: }
122: }
123:
124: $subscription_info = $this->model_checkout_order->getSubscription($order_id, $product['order_product_id']);
125:
126: if ($subscription_info) {
127: $subscription_plan_id = $subscription_info['subscription_plan_id'];
128: } else {
129: $subscription_plan_id = 0;
130: }
131:
132: $this->cart->add($product['product_id'], $product['quantity'], $option_data, $subscription_plan_id, true, $product['price']);
133: }
134:
135: $this->session->data['vouchers'] = [];
136:
137: $this->load->model('checkout/voucher');
138:
139: $vouchers = $this->model_checkout_order->getVouchers($order_id);
140:
141: foreach ($vouchers as $voucher) {
142: $this->session->data['vouchers'][] = [
143: 'code' => $voucher['code'],
144: 'description' => sprintf($this->language->get('text_for'), $this->currency->format($voucher['amount'], $this->session->data['currency'], 1.0), $voucher['to_name']),
145: 'to_name' => $voucher['to_name'],
146: 'to_email' => $voucher['to_email'],
147: 'from_name' => $voucher['from_name'],
148: 'from_email' => $voucher['from_email'],
149: 'voucher_theme_id' => $voucher['voucher_theme_id'],
150: 'message' => $voucher['message'],
151: 'amount' => $this->currency->convert($voucher['amount'], $this->session->data['currency'], $this->config->get('config_currency'))
152: ];
153: }
154:
155: if ($order_info['affiliate_id']) {
156: $this->session->data['affiliate_id'] = $order_info['affiliate_id'];
157: }
158:
159: // Coupon, Voucher, Reward
160: $order_totals = $this->model_checkout_order->getTotals($order_id);
161:
162: foreach ($order_totals as $order_total) {
163: // If coupon, voucher or reward points
164: $start = strpos($order_total['title'], '(');
165: $end = strrpos($order_total['title'], ')');
166:
167: if ($start !== false && $end !== false) {
168: $this->session->data[$order_total['code']] = substr($order_total['title'], $start + 1, $end - ($start + 1));
169: }
170: }
171:
172: $json['success'] = $this->language->get('text_success');
173: }
174:
175: $this->response->addHeader('Content-Type: application/json');
176: $this->response->setOutput(json_encode($json));
177: }
178:
179: /**
180: * Save
181: *
182: * @return void
183: */
184: public function save(): void {
185: $this->load->language('api/sale/order');
186:
187: $json = [];
188:
189: if (!isset($this->request->post['order_id'])) {
190: $json['error'] = $this->language->get('error_order');
191: }
192:
193: if (!$json) {
194: $this->load->model('checkout/order');
195:
196: $this->model_checkout_order->editOrder($this->request->post['order_id'], $this->request->post);
197:
198: $json['success'] = $this->language->get('text_success');
199: }
200:
201: $this->response->addHeader('Content-Type: application/json');
202: $this->response->setOutput(json_encode($json));
203: }
204:
205: /**
206: * Comment
207: *
208: * @return void
209: */
210: public function comment(): void {
211: $this->load->language('api/sale/order');
212:
213: $json = [];
214:
215: if (!isset($this->request->post['comment'])) {
216: $json['error'] = $this->language->get('error_comment');
217: }
218:
219: if (!$json) {
220: $this->session->data['comment'] = $this->request->post['comment'];
221:
222: $json['success'] = $this->language->get('text_success');
223: }
224:
225: $this->response->addHeader('Content-Type: application/json');
226: $this->response->setOutput(json_encode($json));
227: }
228:
229: /**
230: * Confirm
231: *
232: * @return void
233: */
234: public function confirm(): void {
235: $this->load->language('api/sale/order');
236:
237: $json = [];
238:
239: // Validate cart has products and has stock.
240: if (($this->cart->hasProducts() || !empty($this->session->data['vouchers']))) {
241: if (!$this->cart->hasStock() && !$this->config->get('config_stock_checkout')) {
242: $json['error']['stock'] = $this->language->get('error_stock');
243: }
244: } else {
245: $json['error']['product'] = $this->language->get('error_product');
246: }
247:
248: // Validate minimum quantity requirements.
249: $products = $this->cart->getProducts();
250:
251: foreach ($products as $product) {
252: if (!$product['minimum']) {
253: $json['error']['minimum'] = sprintf($this->language->get('error_minimum'), $product['name'], $product['minimum']);
254:
255: break;
256: }
257: }
258:
259: // Customer
260: if (!isset($this->session->data['customer'])) {
261: $json['error']['customer'] = $this->language->get('error_customer');
262: }
263:
264: // Payment Address
265: if ($this->config->get('config_checkout_payment_address') && !isset($this->session->data['payment_address'])) {
266: $json['error']['payment_address'] = $this->language->get('error_payment_address');
267: }
268:
269: // Shipping
270: if ($this->cart->hasShipping()) {
271: // Shipping Address
272: if (!isset($this->session->data['shipping_address'])) {
273: $json['error']['shipping_address'] = $this->language->get('error_shipping_address');
274: }
275:
276: // Validate shipping method
277: if (!isset($this->session->data['shipping_method'])) {
278: $json['error']['shipping_method'] = $this->language->get('error_shipping_method');
279: }
280: } else {
281: unset($this->session->data['shipping_address']);
282: unset($this->session->data['shipping_method']);
283: unset($this->session->data['shipping_methods']);
284: }
285:
286: // Payment Method
287: if (empty($this->session->data['payment_method'])) {
288: $json['error']['payment_method'] = $this->language->get('error_payment_method');
289: }
290:
291: if (!$json) {
292: $order_data = [];
293:
294: // Store Details
295: $order_data['invoice_prefix'] = $this->config->get('config_invoice_prefix');
296:
297: $order_data['store_id'] = $this->config->get('config_store_id');
298: $order_data['store_name'] = $this->config->get('config_name');
299: $order_data['store_url'] = $this->config->get('config_url');
300:
301: // Customer Details
302: $order_data['customer_id'] = $this->session->data['customer']['customer_id'];
303: $order_data['customer_group_id'] = $this->session->data['customer']['customer_group_id'];
304: $order_data['firstname'] = $this->session->data['customer']['firstname'];
305: $order_data['lastname'] = $this->session->data['customer']['lastname'];
306: $order_data['email'] = $this->session->data['customer']['email'];
307: $order_data['telephone'] = $this->session->data['customer']['telephone'];
308: $order_data['custom_field'] = $this->session->data['customer']['custom_field'];
309:
310: // Payment Details
311: if ($this->config->get('config_checkout_payment_address')) {
312: $order_data['payment_address_id'] = $this->session->data['payment_address']['address_id'];
313: $order_data['payment_lastname'] = $this->session->data['payment_address']['lastname'];
314: $order_data['payment_company'] = $this->session->data['payment_address']['company'];
315: $order_data['payment_address_1'] = $this->session->data['payment_address']['address_1'];
316: $order_data['payment_address_2'] = $this->session->data['payment_address']['address_2'];
317: $order_data['payment_city'] = $this->session->data['payment_address']['city'];
318: $order_data['payment_postcode'] = $this->session->data['payment_address']['postcode'];
319: $order_data['payment_zone'] = $this->session->data['payment_address']['zone'];
320: $order_data['payment_zone_id'] = $this->session->data['payment_address']['zone_id'];
321: $order_data['payment_country'] = $this->session->data['payment_address']['country'];
322: $order_data['payment_country_id'] = $this->session->data['payment_address']['country_id'];
323: $order_data['payment_address_format'] = $this->session->data['payment_address']['address_format'];
324: $order_data['payment_custom_field'] = $this->session->data['payment_address']['custom_field'] ?? [];
325: } else {
326: $order_data['payment_address_id'] = 0;
327: $order_data['payment_firstname'] = '';
328: $order_data['payment_lastname'] = '';
329: $order_data['payment_company'] = '';
330: $order_data['payment_address_1'] = '';
331: $order_data['payment_address_2'] = '';
332: $order_data['payment_city'] = '';
333: $order_data['payment_postcode'] = '';
334: $order_data['payment_zone'] = '';
335: $order_data['payment_zone_id'] = 0;
336: $order_data['payment_country'] = '';
337: $order_data['payment_country_id'] = 0;
338: $order_data['payment_address_format'] = '';
339: $order_data['payment_custom_field'] = [];
340: }
341:
342: $order_data['payment_method'] = $this->session->data['payment_method'];
343:
344: // Shipping Details
345: if ($this->cart->hasShipping()) {
346: $order_data['shipping_address_id'] = $this->session->data['shipping_address']['address_id'];
347: $order_data['shipping_firstname'] = $this->session->data['shipping_address']['firstname'];
348: $order_data['shipping_lastname'] = $this->session->data['shipping_address']['lastname'];
349: $order_data['shipping_company'] = $this->session->data['shipping_address']['company'];
350: $order_data['shipping_address_1'] = $this->session->data['shipping_address']['address_1'];
351: $order_data['shipping_address_2'] = $this->session->data['shipping_address']['address_2'];
352: $order_data['shipping_city'] = $this->session->data['shipping_address']['city'];
353: $order_data['shipping_postcode'] = $this->session->data['shipping_address']['postcode'];
354: $order_data['shipping_zone'] = $this->session->data['shipping_address']['zone'];
355: $order_data['shipping_zone_id'] = $this->session->data['shipping_address']['zone_id'];
356: $order_data['shipping_country'] = $this->session->data['shipping_address']['country'];
357: $order_data['shipping_country_id'] = $this->session->data['shipping_address']['country_id'];
358: $order_data['shipping_address_format'] = $this->session->data['shipping_address']['address_format'];
359: $order_data['shipping_custom_field'] = $this->session->data['shipping_address']['custom_field'] ?? [];
360:
361: $order_data['shipping_method'] = $this->session->data['shipping_method'];
362: } else {
363: $order_data['shipping_address_id'] = 0;
364: $order_data['shipping_firstname'] = '';
365: $order_data['shipping_lastname'] = '';
366: $order_data['shipping_company'] = '';
367: $order_data['shipping_address_1'] = '';
368: $order_data['shipping_address_2'] = '';
369: $order_data['shipping_city'] = '';
370: $order_data['shipping_postcode'] = '';
371: $order_data['shipping_zone'] = '';
372: $order_data['shipping_zone_id'] = 0;
373: $order_data['shipping_country'] = '';
374: $order_data['shipping_country_id'] = 0;
375: $order_data['shipping_address_format'] = '';
376: $order_data['shipping_custom_field'] = [];
377:
378: $order_data['shipping_method'] = [];
379: }
380:
381: $points = 0;
382:
383: // Products
384: $order_data['products'] = [];
385:
386: foreach ($this->cart->getProducts() as $product) {
387: $option_data = [];
388:
389: foreach ($product['option'] as $option) {
390: $option_data[] = [
391: 'product_option_id' => $option['product_option_id'],
392: 'product_option_value_id' => $option['product_option_value_id'],
393: 'option_id' => $option['option_id'],
394: 'option_value_id' => $option['option_value_id'],
395: 'name' => $option['name'],
396: 'value' => $option['value'],
397: 'type' => $option['type']
398: ];
399: }
400:
401: $subscription_data = [];
402:
403: if ($product['subscription']) {
404: $subscription_data = [
405: 'subscription_plan_id' => $product['subscription']['subscription_plan_id'],
406: 'name' => $product['subscription']['name'],
407: 'trial_frequency' => $product['subscription']['trial_frequency'],
408: 'trial_cycle' => $product['subscription']['trial_cycle'],
409: 'trial_duration' => $product['subscription']['trial_duration'],
410: 'trial_remaining' => $product['subscription']['trial_remaining'],
411: 'trial_status' => $product['subscription']['trial_status'],
412: 'frequency' => $product['subscription']['frequency'],
413: 'cycle' => $product['subscription']['cycle'],
414: 'duration' => $product['subscription']['duration']
415: ];
416: }
417:
418: $order_data['products'][] = [
419: 'product_id' => $product['product_id'],
420: 'master_id' => $product['master_id'],
421: 'name' => $product['name'],
422: 'model' => $product['model'],
423: 'option' => $option_data,
424: 'subscription' => $subscription_data,
425: 'download' => $product['download'],
426: 'quantity' => $product['quantity'],
427: 'subtract' => $product['subtract'],
428: 'price' => $product['price'],
429: 'total' => $product['total'],
430: 'tax' => $this->tax->getTax($product['price'], $product['tax_class_id']),
431: 'reward' => $product['reward']
432: ];
433:
434: $points += $product['reward'];
435: }
436:
437: // Gift Voucher
438: $order_data['vouchers'] = [];
439:
440: if (!empty($this->session->data['vouchers'])) {
441: foreach ($this->session->data['vouchers'] as $voucher) {
442: $order_data['vouchers'][] = [
443: 'description' => $voucher['description'],
444: 'code' => oc_token(10),
445: 'to_name' => $voucher['to_name'],
446: 'to_email' => $voucher['to_email'],
447: 'from_name' => $voucher['from_name'],
448: 'from_email' => $voucher['from_email'],
449: 'voucher_theme_id' => $voucher['voucher_theme_id'],
450: 'message' => $voucher['message'],
451: 'amount' => $voucher['amount']
452: ];
453: }
454: }
455:
456: if (isset($this->session->data['comment'])) {
457: $order_data['comment'] = $this->session->data['comment'];
458: } else {
459: $order_data['comment'] = '';
460: }
461:
462: // Order Totals
463: $totals = [];
464: $taxes = $this->cart->getTaxes();
465: $total = 0;
466:
467: $this->load->model('checkout/cart');
468:
469: ($this->model_checkout_cart->getTotals)($totals, $taxes, $total);
470:
471: $total_data = [
472: 'totals' => $totals,
473: 'taxes' => $taxes,
474: 'total' => $total
475: ];
476:
477: $order_data = array_merge($order_data, $total_data);
478:
479: $order_data['affiliate_id'] = 0;
480: $order_data['commission'] = 0;
481: $order_data['marketing_id'] = 0;
482: $order_data['tracking'] = '';
483:
484: if (isset($this->session->data['affiliate_id'])) {
485: $subtotal = $this->cart->getSubTotal();
486:
487: // Affiliate
488: $this->load->model('account/affiliate');
489:
490: $affiliate_info = $this->model_account_affiliate->getAffiliate($this->session->data['affiliate_id']);
491:
492: if ($affiliate_info) {
493: $order_data['affiliate_id'] = $affiliate_info['customer_id'];
494: $order_data['commission'] = ($subtotal / 100) * $affiliate_info['commission'];
495: $order_data['tracking'] = $affiliate_info['tracking'];
496: }
497: }
498:
499: // We use session to store language code for API access
500: $order_data['language_id'] = $this->config->get('config_language_id');
501: $order_data['language_code'] = $this->config->get('config_language');
502:
503: $order_data['currency_id'] = $this->currency->getId($this->session->data['currency']);
504: $order_data['currency_code'] = $this->session->data['currency'];
505: $order_data['currency_value'] = $this->currency->getValue($this->session->data['currency']);
506:
507: $order_data['ip'] = $this->request->server['REMOTE_ADDR'];
508:
509: if (!empty($this->request->server['HTTP_X_FORWARDED_FOR'])) {
510: $order_data['forwarded_ip'] = $this->request->server['HTTP_X_FORWARDED_FOR'];
511: } elseif (!empty($this->request->server['HTTP_CLIENT_IP'])) {
512: $order_data['forwarded_ip'] = $this->request->server['HTTP_CLIENT_IP'];
513: } else {
514: $order_data['forwarded_ip'] = '';
515: }
516:
517: if (isset($this->request->server['HTTP_USER_AGENT'])) {
518: $order_data['user_agent'] = $this->request->server['HTTP_USER_AGENT'];
519: } else {
520: $order_data['user_agent'] = '';
521: }
522:
523: if (isset($this->request->server['HTTP_ACCEPT_LANGUAGE'])) {
524: $order_data['accept_language'] = $this->request->server['HTTP_ACCEPT_LANGUAGE'];
525: } else {
526: $order_data['accept_language'] = '';
527: }
528:
529: $this->load->model('checkout/order');
530:
531: if (!isset($this->session->data['order_id'])) {
532: $this->session->data['order_id'] = $this->model_checkout_order->addOrder($order_data);
533: } else {
534: $order_info = $this->model_checkout_order->getOrder($this->session->data['order_id']);
535:
536: if ($order_info) {
537: $this->model_checkout_order->editOrder($this->session->data['order_id'], $order_data);
538: }
539: }
540:
541: $json['order_id'] = $this->session->data['order_id'];
542:
543: // Set the order history
544: if (isset($this->request->post['order_status_id'])) {
545: $order_status_id = (int)$this->request->post['order_status_id'];
546: } else {
547: $order_status_id = $this->config->get('config_order_status_id');
548: }
549:
550: $this->model_checkout_order->addHistory($json['order_id'], $order_status_id);
551:
552: $json['success'] = $this->language->get('text_success');
553:
554: $json['points'] = $points;
555:
556: if (isset($order_data['affiliate_id'])) {
557: $json['commission'] = $this->currency->format($order_data['commission'], $this->config->get('config_currency'));
558: }
559: }
560:
561: $this->response->addHeader('Content-Type: application/json');
562: $this->response->setOutput(json_encode($json));
563: }
564:
565: /**
566: * Delete
567: *
568: * @return void
569: */
570: public function delete(): void {
571: $this->load->language('api/sale/order');
572:
573: $json = [];
574:
575: $selected = [];
576:
577: if (isset($this->request->post['selected'])) {
578: $selected = $this->request->post['selected'];
579: }
580:
581: if (isset($this->request->get['order_id'])) {
582: $selected[] = (int)$this->request->get['order_id'];
583: }
584:
585: foreach ($selected as $order_id) {
586: $this->load->model('checkout/order');
587:
588: $order_info = $this->model_checkout_order->getOrder($order_id);
589:
590: if ($order_info) {
591: $this->model_checkout_order->deleteOrder($order_id);
592: }
593: }
594:
595: $json['success'] = $this->language->get('text_success');
596:
597: $this->response->addHeader('Content-Type: application/json');
598: $this->response->setOutput(json_encode($json));
599: }
600:
601: /**
602: * Add History
603: *
604: * @return void
605: */
606: public function addHistory(): void {
607: $this->load->language('api/sale/order');
608:
609: $json = [];
610:
611: // Add keys for missing post vars
612: $keys = [
613: 'order_id',
614: 'order_status_id',
615: 'comment',
616: 'notify',
617: 'override'
618: ];
619:
620: foreach ($keys as $key) {
621: if (!isset($this->request->post[$key])) {
622: $this->request->post[$key] = '';
623: }
624: }
625:
626: $this->load->model('checkout/order');
627:
628: $order_info = $this->model_checkout_order->getOrder((int)$this->request->post['order_id']);
629:
630: if (!$order_info) {
631: $json['error'] = $this->language->get('error_order');
632: }
633:
634: if (!$json) {
635: $this->model_checkout_order->addHistory((int)$this->request->post['order_id'], (int)$this->request->post['order_status_id'], (string)$this->request->post['comment'], (bool)$this->request->post['notify'], (bool)$this->request->post['override']);
636:
637: $json['success'] = $this->language->get('text_success');
638: }
639:
640: $this->response->addHeader('Content-Type: application/json');
641: $this->response->setOutput(json_encode($json));
642: }
643: }
644: