1
|
|
|
<?php |
2
|
|
|
/** |
3
|
|
|
* Расчёт стоимости доставки СДЭК |
4
|
|
|
* Модуль для интернет-магазинов (ИМ) |
5
|
|
|
* |
6
|
|
|
* @version 1.0 |
7
|
|
|
* @since 21.06.2012 |
8
|
|
|
* @link http://www.edostavka.ru/integrator/ |
9
|
|
|
* @see 3197 |
10
|
|
|
* @author Tatyana Shurmeleva |
11
|
|
|
*/ |
12
|
|
|
|
13
|
|
|
namespace Ecommerce\Vendor; |
14
|
|
|
class CalculatePriceDeliveryCdek { |
15
|
|
|
|
16
|
|
|
//версия модуля |
17
|
|
|
private $version = "1.0"; |
18
|
|
|
//url для получения данных по отправке |
19
|
|
|
private $jsonUrl = 'http://api.cdek.ru/calculator/calculate_price_by_json.php'; |
20
|
|
|
|
21
|
|
|
//авторизация ИМ |
22
|
|
|
private $authLogin; |
23
|
|
|
private $authPassword; |
24
|
|
|
|
25
|
|
|
//id города-отправителя |
26
|
|
|
private $senderCityId; |
27
|
|
|
//id города-получателя |
28
|
|
|
private $receiverCityId; |
29
|
|
|
//id тарифа |
30
|
|
|
private $tariffId; |
31
|
|
|
//id способа доставки (склад-склад, склад-дверь) |
32
|
|
|
private $modeId; |
33
|
|
|
//массив мест отправления |
34
|
|
|
public $goodsList; |
35
|
|
|
//массив id тарифов |
36
|
|
|
public $tariffList; |
37
|
|
|
//результат расчёта стоимости отправления ИМ |
38
|
|
|
private $result; |
39
|
|
|
//результат в случае ошибочного расчёта |
40
|
|
|
private $error; |
41
|
|
|
//планируемая дата заказа |
42
|
|
|
public $dateExecute; |
43
|
|
|
|
44
|
|
|
/** |
45
|
|
|
* конструктор |
46
|
|
|
*/ |
47
|
|
|
public function __construct() { |
48
|
|
|
$this->dateExecute = date('Y-m-d'); |
49
|
|
|
} |
50
|
|
|
|
51
|
|
|
/** |
52
|
|
|
* Установка планируемой даты отправки |
53
|
|
|
* |
54
|
|
|
* @param string $date дата планируемой отправки, например '2012-06-25' |
55
|
|
|
*/ |
56
|
|
|
public function setDateExecute($date) { |
57
|
|
|
$this->dateExecute = date($date); |
58
|
|
|
} |
59
|
|
|
|
60
|
|
|
/** |
61
|
|
|
* Авторизация ИМ |
62
|
|
|
* |
63
|
|
|
* @param string $authLogin логин |
64
|
|
|
* @param string $authPassword пароль |
65
|
|
|
*/ |
66
|
|
|
public function setAuth($authLogin, $authPassword) { |
67
|
|
|
$this->authLogin = $authLogin; |
68
|
|
|
$this->authPassword = $authPassword; |
69
|
|
|
} |
70
|
|
|
|
71
|
|
|
/** |
72
|
|
|
* Защифрованный пароль для передачи на сервер |
73
|
|
|
* |
74
|
|
|
* @return string |
75
|
|
|
*/ |
76
|
|
|
private function _getSecureAuthPassword() { |
77
|
|
|
return md5($this->dateExecute . '&' . $this->authPassword); |
78
|
|
|
} |
79
|
|
|
|
80
|
|
|
/** |
81
|
|
|
* Город-отправитель |
82
|
|
|
* |
83
|
|
|
* @param int $id города |
84
|
|
|
*/ |
85
|
|
|
public function setSenderCityId($id) { |
86
|
|
|
$id = (int)$id; |
87
|
|
|
if ($id == 0) { |
88
|
|
|
throw new \Exception("Неправильно задан город-отправитель."); |
89
|
|
|
} |
90
|
|
|
$this->senderCityId = $id; |
91
|
|
|
} |
92
|
|
|
|
93
|
|
|
/** |
94
|
|
|
* Город-получатель |
95
|
|
|
* |
96
|
|
|
* @param int $id города |
97
|
|
|
*/ |
98
|
|
|
public function setReceiverCityId($id) { |
99
|
|
|
$id = (int)$id; |
100
|
|
|
if ($id == 0) { |
101
|
|
|
throw new \Exception("Неправильно задан город-получатель."); |
102
|
|
|
} |
103
|
|
|
$this->receiverCityId = $id; |
104
|
|
|
} |
105
|
|
|
|
106
|
|
|
/** |
107
|
|
|
* Устанавливаем тариф |
108
|
|
|
* |
109
|
|
|
* @param int $id тарифа |
110
|
|
|
*/ |
111
|
|
|
public function setTariffId($id) { |
112
|
|
|
$id = (int)$id; |
113
|
|
|
if ($id == 0) { |
114
|
|
|
throw new \Exception("Неправильно задан тариф."); |
115
|
|
|
} |
116
|
|
|
$this->tariffId = $id; |
117
|
|
|
} |
118
|
|
|
|
119
|
|
|
/** |
120
|
|
|
* Устанавливаем режим доставки (дверь-дверь=1, дверь-склад=2, склад-дверь=3, склад-склад=4) |
121
|
|
|
* |
122
|
|
|
* @param int $id режим доставки |
123
|
|
|
*/ |
124
|
|
|
public function setModeDeliveryId($id) { |
125
|
|
|
$id = (int)$id; |
126
|
|
|
if (!in_array($id, array(1, 2, 3, 4))) { |
127
|
|
|
throw new \Exception("Неправильно задан режим доставки."); |
128
|
|
|
} |
129
|
|
|
$this->modeId = $id; |
130
|
|
|
} |
131
|
|
|
|
132
|
|
|
/** |
133
|
|
|
* Добавление места в отправлении |
134
|
|
|
* |
135
|
|
|
* @param int $weight вес, килограммы |
136
|
|
|
* @param int $length длина, сантиметры |
137
|
|
|
* @param int $width ширина, сантиметры |
138
|
|
|
* @param int $height высота, сантиметры |
139
|
|
|
*/ |
140
|
|
|
public function addGoodsItemBySize($weight, $length, $width, $height) { |
141
|
|
|
//проверка веса |
142
|
|
|
$weight = (float)$weight; |
143
|
|
|
if ($weight == 0.00) { |
144
|
|
|
throw new \Exception("Неправильно задан вес места № " . (count($this->getGoodslist()) + 1) . "."); |
145
|
|
|
} |
146
|
|
|
//проверка остальных величин |
147
|
|
|
$paramsItem = array("длина" => $length, |
148
|
|
|
"ширина" => $width, |
149
|
|
|
"высота" => $height); |
150
|
|
View Code Duplication |
foreach ($paramsItem as $k => $param) { |
|
|
|
|
151
|
|
|
$param = (int)$param; |
152
|
|
|
if ($param == 0) { |
153
|
|
|
throw new \Exception("Неправильно задан параметр '" . $k . "' места № " . (count($this->getGoodslist()) + 1) . "."); |
154
|
|
|
} |
155
|
|
|
} |
156
|
|
|
$this->goodsList[] = array('weight' => $weight, |
157
|
|
|
'length' => $length, |
158
|
|
|
'width' => $width, |
159
|
|
|
'height' => $height); |
160
|
|
|
} |
161
|
|
|
|
162
|
|
|
/** |
163
|
|
|
* Добавление места в отправлении по объёму (куб.метры) |
164
|
|
|
* |
165
|
|
|
* @param int $weight вес, килограммы |
166
|
|
|
* @param int $volume объёмный вес, метры кубические (А * В * С) |
167
|
|
|
*/ |
168
|
|
|
public function addGoodsItemByVolume($weight, $volume) { |
169
|
|
|
$paramsItem = array("вес" => $weight, |
170
|
|
|
"объёмный вес" => $volume); |
171
|
|
View Code Duplication |
foreach ($paramsItem as $k => $param) { |
|
|
|
|
172
|
|
|
$param = (float)$param; |
173
|
|
|
if ($param == 0.00) { |
174
|
|
|
throw new \ption("Неправильно задан параметр '" . $k . "' места № " . (count($this->getGoodslist()) + 1) . "."); |
175
|
|
|
} |
176
|
|
|
} |
177
|
|
|
$this->goodsList[] = array('weight' => $weight, |
178
|
|
|
'volume' => $volume); |
179
|
|
|
} |
180
|
|
|
|
181
|
|
|
/** |
182
|
|
|
* Получение массива мест отправления |
183
|
|
|
* |
184
|
|
|
* @return array |
185
|
|
|
*/ |
186
|
|
|
public function getGoodslist() { |
187
|
|
|
if (!isset($this->goodsList)) { |
188
|
|
|
return NULL; |
189
|
|
|
} |
190
|
|
|
return $this->goodsList; |
191
|
|
|
} |
192
|
|
|
|
193
|
|
|
/** |
194
|
|
|
* добавление тарифа в список тарифов с приоритетами |
195
|
|
|
* |
196
|
|
|
* @param int $id тариф |
197
|
|
|
* @param int $priority default false приоритет |
198
|
|
|
*/ |
199
|
|
|
public function addTariffPriority($id, $priority = 0) { |
200
|
|
|
$id = (int)$id; |
201
|
|
|
if ($id == 0) { |
202
|
|
|
throw new \Exception("Неправильно задан id тарифа."); |
203
|
|
|
} |
204
|
|
|
$priority = ($priority > 0) ? $priority : count($this->tariffList) + 1; |
205
|
|
|
$this->tariffList[] = array('priority' => $priority, |
206
|
|
|
'id' => $id); |
207
|
|
|
} |
208
|
|
|
|
209
|
|
|
/** |
210
|
|
|
* Получение массива заданных тарифов |
211
|
|
|
* |
212
|
|
|
* @return array |
213
|
|
|
*/ |
214
|
|
|
private function _getTariffList() { |
|
|
|
|
215
|
|
|
if (!isset($this->tariffList)) { |
216
|
|
|
return NULL; |
217
|
|
|
} |
218
|
|
|
return $this->tariffList; |
219
|
|
|
} |
220
|
|
|
|
221
|
|
|
/** |
222
|
|
|
* Выполнение POST-запроса на сервер для получения данных |
223
|
|
|
* по запрашиваемым параметрам. |
224
|
|
|
* |
225
|
|
|
* |
226
|
|
|
*/ |
227
|
|
|
private function _getRemoteData($data) { |
228
|
|
|
$data_string = json_encode($data); |
229
|
|
|
|
230
|
|
|
$ch = curl_init(); |
231
|
|
|
curl_setopt($ch, CURLOPT_URL, $this->jsonUrl); |
232
|
|
|
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); |
233
|
|
|
curl_setopt($ch, CURLOPT_HTTPHEADER, array( |
234
|
|
|
'Content-Type: application/json') |
235
|
|
|
); |
236
|
|
|
curl_setopt($ch, CURLOPT_POST, 1); |
237
|
|
|
curl_setopt($ch, CURLOPT_POSTFIELDS, $data_string); |
238
|
|
|
|
239
|
|
|
$result = curl_exec($ch); |
240
|
|
|
curl_close($ch); |
241
|
|
|
|
242
|
|
|
return json_decode($result, true); |
243
|
|
|
} |
244
|
|
|
|
245
|
|
|
/** |
246
|
|
|
* Расчет стоимости доставки |
247
|
|
|
* |
248
|
|
|
* @return bool |
249
|
|
|
*/ |
250
|
|
|
public function calculate() { |
251
|
|
|
//формируем массив для отправки curl-post-запроса |
252
|
|
|
//передаём только явно заданные параметры, установленные ИМ |
253
|
|
|
//всю проверку и обработку будем делать на стороне сервера |
254
|
|
|
$data = array(); |
255
|
|
|
//получение всех свойств текущего объекта не работает, т.к. у нас свойства private |
256
|
|
|
//поэтому определим массив $data явно |
257
|
|
|
//проверяем на установленную переменную и не-NULL-значение |
258
|
|
|
|
259
|
|
|
//версия модуля |
260
|
|
|
isset($this->version) ? $data['version'] = $this->version : ''; |
261
|
|
|
//дата планируемой доставки, если не установлено, берётся сегодняшний день |
262
|
|
|
$data['dateExecute'] = $this->dateExecute; |
263
|
|
|
//авторизация: логин |
264
|
|
|
isset($this->authLogin) ? $data['authLogin'] = $this->authLogin : ''; |
265
|
|
|
//авторизация: пароль |
266
|
|
|
isset($this->authPassword) ? $data['secure'] = $this->_getSecureAuthPassword() : ''; |
267
|
|
|
//город-отправитель |
268
|
|
|
isset($this->senderCityId) ? $data['senderCityId'] = $this->senderCityId : ''; |
269
|
|
|
//город-получатель |
270
|
|
|
isset($this->receiverCityId) ? $data['receiverCityId'] = $this->receiverCityId : ''; |
271
|
|
|
//выбранный тариф |
272
|
|
|
isset($this->tariffId) ? $data['tariffId'] = $this->tariffId : ''; |
273
|
|
|
//список тарифов с приоритетами |
274
|
|
|
(isset($this->tariffList)) ? $data['tariffList'] = $this->tariffList : ''; |
275
|
|
|
//режим доставки |
276
|
|
|
isset($this->modeId) ? $data['modeId'] = $this->modeId : ''; |
277
|
|
|
|
278
|
|
|
//список мест |
279
|
|
|
if (isset($this->goodsList)) { |
280
|
|
|
foreach ($this->goodsList as $idGoods => $goods) { |
281
|
|
|
$data['goods'][$idGoods] = array(); |
282
|
|
|
//вес |
283
|
|
|
(isset($goods['weight']) && $goods['weight'] <> '' && $goods['weight'] > 0.00) ? $data['goods'][$idGoods]['weight'] = $goods['weight'] : ''; |
284
|
|
|
//длина |
285
|
|
|
(isset($goods['length']) && $goods['length'] <> '' && $goods['length'] > 0) ? $data['goods'][$idGoods]['length'] = $goods['length'] : ''; |
286
|
|
|
//ширина |
287
|
|
|
(isset($goods['width']) && $goods['width'] <> '' && $goods['width'] > 0) ? $data['goods'][$idGoods]['width'] = $goods['width'] : ''; |
288
|
|
|
//высота |
289
|
|
|
(isset($goods['height']) && $goods['height'] <> '' && $goods['height'] > 0) ? $data['goods'][$idGoods]['height'] = $goods['height'] : ''; |
290
|
|
|
//объемный вес (куб.м) |
291
|
|
|
(isset($goods['volume']) && $goods['volume'] <> '' && $goods['volume'] > 0.00) ? $data['goods'][$idGoods]['volume'] = $goods['volume'] : ''; |
292
|
|
|
|
293
|
|
|
} |
294
|
|
|
} |
295
|
|
|
//проверка на подключние библиотеки curl |
296
|
|
|
if (!extension_loaded('curl')) { |
297
|
|
|
throw new \Exception("Не подключена библиотека CURL"); |
298
|
|
|
} |
299
|
|
|
$response = $this->_getRemoteData($data); |
300
|
|
|
|
301
|
|
|
if (isset($response['result']) && !empty($response['result'])) { |
302
|
|
|
$this->result = $response; |
303
|
|
|
return true; |
304
|
|
|
} else { |
305
|
|
|
$this->error = $response; |
306
|
|
|
return false; |
307
|
|
|
} |
308
|
|
|
|
309
|
|
|
//return (isset($response['result']) && (!empty($response['result']))) ? true : false; |
|
|
|
|
310
|
|
|
//результат |
311
|
|
|
//$result = ($this->getResponse()); |
|
|
|
|
312
|
|
|
//return $result; |
313
|
|
|
} |
314
|
|
|
|
315
|
|
|
/** |
316
|
|
|
* Получить результаты подсчета |
317
|
|
|
* |
318
|
|
|
* @return array |
319
|
|
|
*/ |
320
|
|
|
public function getResult() { |
321
|
|
|
return $this->result; |
322
|
|
|
} |
323
|
|
|
|
324
|
|
|
/** |
325
|
|
|
* получить код и текст ошибки |
326
|
|
|
* |
327
|
|
|
* @return object |
328
|
|
|
*/ |
329
|
|
|
public function getError() { |
330
|
|
|
return $this->error; |
331
|
|
|
} |
332
|
|
|
|
333
|
|
|
} |
334
|
|
|
|
335
|
|
|
?> |
|
|
|
|
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.
You can also find more detailed suggestions in the “Code” section of your repository.