Bitrix-D7 23.9
 
Загрузка...
Поиск...
Не найдено
cashboxatolfarmv4.php
1<?php
2
3namespace Bitrix\Sale\Cashbox;
4
8
9Localization\Loc::loadMessages(__FILE__);
10
16{
17 const SERVICE_URL = 'https://online.atol.ru/possystem/v4';
18 const SERVICE_TEST_URL = 'https://testonline.atol.ru/possystem/v4';
19
20 const HANDLER_MODE_ACTIVE = 'ACTIVE';
21 const HANDLER_MODE_TEST = 'TEST';
22
23 const CODE_CALC_VAT_10 = 'vat110';
24 const CODE_CALC_VAT_20 = 'vat120';
25
30 public function buildCheckQuery(Check $check)
31 {
32 $data = $check->getDataForCheck();
33
35 $dateTime = $data['date_create'];
36
37 $serviceEmail = $this->getValueFromSettings('SERVICE', 'EMAIL');
38 if (!$serviceEmail)
39 {
40 $serviceEmail = static::getDefaultServiceEmail();
41 }
42
43 $result = [
44 'timestamp' => $dateTime->format('d.m.Y H:i:s'),
45 'external_id' => static::buildUuid(static::UUID_TYPE_CHECK, $data['unique_id']),
46 'service' => [
47 'callback_url' => $this->getCallbackUrl(),
48 ],
49 'receipt' => [
50 'client' => [],
51 'company' => [
52 'email' => $serviceEmail,
53 'sno' => $this->getValueFromSettings('TAX', 'SNO'),
54 'inn' => $this->getValueFromSettings('SERVICE', 'INN'),
55 'payment_address' => $this->getValueFromSettings('SERVICE', 'P_ADDRESS'),
56 ],
57 'payments' => [],
58 'items' => [],
59 'total' => (float)$data['total_sum']
60 ]
61 ];
62
63 $email = $data['client_email'] ?? '';
64
65 $phone = \NormalizePhone($data['client_phone']);
66 if (is_string($phone))
67 {
68 if ($phone[0] !== '7')
69 {
70 $phone = '7'.$phone;
71 }
72
73 $phone = '+'.$phone;
74 }
75 else
76 {
77 $phone = '';
78 }
79
80 $clientInfo = $this->getValueFromSettings('CLIENT', 'INFO');
81 if ($clientInfo === 'PHONE')
82 {
83 $result['receipt']['client'] = ['phone' => $phone];
84 }
85 elseif ($clientInfo === 'EMAIL')
86 {
87 $result['receipt']['client'] = ['email' => $email];
88 }
89 else
90 {
91 $result['receipt']['client'] = [];
92
93 if ($email)
94 {
95 $result['receipt']['client']['email'] = $email;
96 }
97
98 if ($phone)
99 {
100 $result['receipt']['client']['phone'] = $phone;
101 }
102 }
103
104 if (isset($data['payments']))
105 {
106 $paymentTypeMap = $this->getPaymentTypeMap();
107 foreach ($data['payments'] as $payment)
108 {
109 $result['receipt']['payments'][] = [
110 'type' => $paymentTypeMap[$payment['type']],
111 'sum' => (float)$payment['sum']
112 ];
113 }
114 }
115
116 foreach ($data['items'] as $item)
117 {
118 $result['receipt']['items'][] = $this->buildPosition($data, $item);
119 }
120
121 return $result;
122 }
123
129 protected function buildPosition(array $checkData, array $item): array
130 {
131 $result = [
132 'name' => $this->buildPositionName($item),
133 'price' => $this->buildPositionPrice($item),
134 'sum' => $this->buildPositionSum($item),
135 'quantity' => $this->buildPositionQuantity($item),
136 'payment_method' => $this->buildPositionPaymentMethod($checkData),
137 'payment_object' => $this->buildPositionPaymentObject($item),
138 'vat' => [
139 'type' => $this->buildPositionVatType($checkData, $item)
140 ],
141 ];
142
143 if (isset($item['nomenclature_code']))
144 {
145 $result['nomenclature_code'] = $this->buildPositionNomenclatureCode($item['nomenclature_code']);
146 }
147
148 return $result;
149 }
150
155 protected function buildPositionName(array $item)
156 {
157 return mb_substr($item['name'], 0, static::MAX_NAME_LENGTH);
158 }
159
164 protected function buildPositionPrice(array $item)
165 {
166 return (float)$item['price'];
167 }
168
173 protected function buildPositionSum(array $item)
174 {
175 return (float)$item['sum'];
176 }
177
182 protected function buildPositionQuantity(array $item)
183 {
184 return $item['quantity'];
185 }
186
191 protected function buildPositionPaymentMethod(array $checkData)
192 {
193 $checkTypeMap = $this->getCheckTypeMap();
194
195 return $checkTypeMap[$checkData['type']];
196 }
197
202 protected function buildPositionPaymentObject(array $item)
203 {
204 $paymentObjectMap = $this->getPaymentObjectMap();
205
206 return $paymentObjectMap[$item['payment_object']];
207 }
208
214 protected function buildPositionVatType(array $checkData, array $item)
215 {
216 $vat = $this->getValueFromSettings('VAT', $item['vat']);
217 if ($vat === null)
218 {
219 $vat = $this->getValueFromSettings('VAT', 'NOT_VAT');
220 }
221
222 return $this->mapVatValue($checkData['type'], $vat);
223 }
224
229 protected function buildPositionNomenclatureCode($code)
230 {
231 $hexCode = bin2hex($code);
232 $hexCodeArray = str_split($hexCode, 2);
233 $hexCodeArray = array_map('ToUpper', $hexCodeArray);
234
235 return join(' ', $hexCodeArray);
236 }
237
244 {
245 $checkQuery = $this->buildCorrectionCheckQuery($check);
246
247 $operation = 'sell_correction';
248 if ($check::getCalculatedSign() === Check::CALCULATED_SIGN_CONSUMPTION)
249 {
250 $operation = 'sell_refund';
251 }
252
253 return $this->registerCheck($operation, $checkQuery);
254 }
255
260 public function buildCorrectionCheckQuery(CorrectionCheck $check)
261 {
262 $data = $check->getDataForCheck();
263
265 $dateTime = $data['date_create'];
266
267 $documentDate = $data['correction_info']['document_date'];
268 if (!$documentDate instanceof Main\Type\Date)
269 {
270 $documentDate = new Main\Type\Date($documentDate);
271 }
272
273 $result = [
274 'timestamp' => $dateTime->format('d.m.Y H:i:s'),
275 'external_id' => static::buildUuid(static::UUID_TYPE_CHECK, $data['unique_id']),
276 'service' => [
277 'callback_url' => $this->getCallbackUrl(),
278 ],
279 'correction' => [
280 'company' => [
281 'sno' => $this->getValueFromSettings('TAX', 'SNO'),
282 'inn' => $this->getValueFromSettings('SERVICE', 'INN'),
283 'payment_address' => $this->getValueFromSettings('SERVICE', 'P_ADDRESS'),
284 ],
285 'correction_info' => [
286 'type' => $data['correction_info']['type'],
287 'base_date' => $documentDate->format('d.m.Y H:i:s'),
288 'base_number' => $data['correction_info']['document_number'],
289 'base_name' => mb_substr(
290 $data['correction_info']['description'],
291 0,
292 255
293 ),
294 ],
295 'payments' => [],
296 'vats' => []
297 ]
298 ];
299
300 if (isset($data['payments']))
301 {
302 $paymentTypeMap = $this->getPaymentTypeMap();
303 foreach ($data['payments'] as $payment)
304 {
305 $result['correction']['payments'][] = [
306 'type' => $paymentTypeMap[$payment['type']],
307 'sum' => (float)$payment['sum']
308 ];
309 }
310 }
311
312 if (isset($data['vats']))
313 {
314 foreach ($data['vats'] as $item)
315 {
316 $vat = $this->getValueFromSettings('VAT', $item['type']);
317 if (is_null($vat) || $vat === '')
318 {
319 $vat = $this->getValueFromSettings('VAT', 'NOT_VAT');
320 }
321
322 $result['correction']['vats'][] = [
323 'type' => $vat,
324 'sum' => (float)$item['sum']
325 ];
326 }
327 }
328
329 return $result;
330 }
331
332 public function checkCorrection(CorrectionCheck $check)
333 {
334 return $this->checkByUuid(
335 $check->getField('EXTERNAL_UUID')
336 );
337 }
338
344 private function mapVatValue($checkType, $vat)
345 {
346 $map = [
347 self::CODE_VAT_10 => [
354 ],
355 self::CODE_VAT_20 => [
362 ],
363 ];
364
365 return $map[$vat][$checkType] ?? $vat;
366 }
367
371 protected function getPaymentObjectMap()
372 {
373 return [
374 Check::PAYMENT_OBJECT_COMMODITY => 'commodity',
379 Check::PAYMENT_OBJECT_GAMBLING_BET => 'gambling_bet',
380 Check::PAYMENT_OBJECT_GAMBLING_PRIZE => 'gambling_prize',
382 Check::PAYMENT_OBJECT_LOTTERY_PRIZE => 'lottery_prize',
383 Check::PAYMENT_OBJECT_INTELLECTUAL_ACTIVITY => 'intellectual_activity',
384 Check::PAYMENT_OBJECT_AGENT_COMMISSION => 'agent_commission',
385 Check::PAYMENT_OBJECT_COMPOSITE => 'composite',
387 Check::PAYMENT_OBJECT_PROPERTY_RIGHT => 'property_right',
388 Check::PAYMENT_OBJECT_NON_OPERATING_GAIN => 'non-operating_gain',
389 Check::PAYMENT_OBJECT_SALES_TAX => 'sales_tax',
390 Check::PAYMENT_OBJECT_RESORT_FEE => 'resort_fee',
393 Check::PAYMENT_OBJECT_PENSION_INSURANCE_IP => 'pension_insurance_ip',
394 Check::PAYMENT_OBJECT_PENSION_INSURANCE => 'pension_insurance',
395 Check::PAYMENT_OBJECT_MEDICAL_INSURANCE_IP => 'medical_insurance_ip',
396 Check::PAYMENT_OBJECT_MEDICAL_INSURANCE => 'medical_insurance',
397 Check::PAYMENT_OBJECT_SOCIAL_INSURANCE => 'social_insurance',
398 Check::PAYMENT_OBJECT_CASINO_PAYMENT => 'casino_payment',
403 ];
404 }
405
409 private function getPaymentTypeMap()
410 {
411 return array(
416 );
417 }
418
422 private static function getDefaultServiceEmail()
423 {
424 return Main\Config\Option::get('main', 'email_from');
425 }
426
430 public static function getName()
431 {
432 return Localization\Loc::getMessage('SALE_CASHBOX_ATOL_FARM_V4_TITLE');
433 }
434
438 protected function getCheckTypeMap()
439 {
440 return array(
441 SellCheck::getType() => 'full_payment',
442 SellReturnCashCheck::getType() => 'full_payment',
443 SellReturnCheck::getType() => 'full_payment',
444 AdvancePaymentCheck::getType() => 'advance',
445 AdvanceReturnCashCheck::getType() => 'advance',
446 AdvanceReturnCheck::getType() => 'advance',
447 PrepaymentCheck::getType() => 'prepayment',
448 PrepaymentReturnCheck::getType() => 'prepayment',
449 PrepaymentReturnCashCheck::getType() => 'prepayment',
450 FullPrepaymentCheck::getType() => 'full_prepayment',
451 FullPrepaymentReturnCheck::getType() => 'full_prepayment',
452 FullPrepaymentReturnCashCheck::getType() => 'full_prepayment',
453 CreditCheck::getType() => 'credit',
454 CreditReturnCheck::getType() => 'credit',
455 CreditPaymentCheck::getType() => 'credit_payment',
456 CreditPaymentReturnCashCheck::getType() => 'credit_payment',
457 CreditPaymentReturnCheck::getType() => 'credit_payment',
458 );
459 }
460
468 protected function getRequestUrl($operation, $token, array $queryData = array())
469 {
470 $serviceUrl = static::SERVICE_URL;
471
472 if ($this->getValueFromSettings('INTERACTION', 'MODE_HANDLER') === static::HANDLER_MODE_TEST)
473 {
474 $serviceUrl = static::SERVICE_TEST_URL;
475 }
476
477 $groupCode = $this->getField('NUMBER_KKM');
478
479 if ($operation === static::OPERATION_CHECK_REGISTRY)
480 {
481 return $serviceUrl.'/'.$groupCode.'/'.$queryData['CHECK_TYPE'].'?token='.$token;
482 }
483 elseif ($operation === static::OPERATION_CHECK_CHECK)
484 {
485 return $serviceUrl.'/'.$groupCode.'/report/'.$queryData['EXTERNAL_UUID'].'?token='.$token;
486 }
487 elseif ($operation === static::OPERATION_GET_TOKEN)
488 {
489 return $serviceUrl.'/getToken';
490 }
491
492 throw new Main\SystemException();
493 }
494
499 public static function getSettings($modelId = 0)
500 {
501 $settings = parent::getSettings($modelId);
502 unset($settings['PAYMENT_TYPE']);
503
504 $settings['SERVICE']['ITEMS']['EMAIL'] = [
505 'TYPE' => 'STRING',
506 'LABEL' => Localization\Loc::getMessage('SALE_CASHBOX_ATOL_FARM_SETTINGS_SERVICE_EMAIL_LABEL'),
507 'VALUE' => static::getDefaultServiceEmail()
508 ];
509
510 $settings['INTERACTION'] = [
511 'LABEL' => Localization\Loc::getMessage('SALE_CASHBOX_ATOL_FARM_SETTINGS_INTERACTION'),
512 'ITEMS' => [
513 'MODE_HANDLER' => [
514 'TYPE' => 'ENUM',
515 'LABEL' => Localization\Loc::getMessage('SALE_CASHBOX_ATOL_FARM_SETTINGS_MODE_HANDLER_LABEL'),
516 'OPTIONS' => [
517 static::HANDLER_MODE_ACTIVE => Localization\Loc::getMessage('SALE_CASHBOX_ATOL_FARM_MODE_ACTIVE'),
518 static::HANDLER_MODE_TEST => Localization\Loc::getMessage('SALE_CASHBOX_ATOL_FARM_MODE_TEST'),
519 ]
520 ]
521 ]
522 ];
523
524 return $settings;
525 }
526
531 protected function validateCheckQuery(array $checkData)
532 {
533 $result = new Result();
534
535 if (empty($checkData['receipt']['client']['email']) && empty($checkData['receipt']['client']['phone']))
536 {
537 $result->addError(new Main\Error(Localization\Loc::getMessage('SALE_CASHBOX_ATOL_ERR_EMPTY_PHONE_EMAIL')));
538 }
539
540 foreach ($checkData['receipt']['items'] as $item)
541 {
542 if ($item['vat'] === null)
543 {
544 $result->addError(new Main\Error(Localization\Loc::getMessage('SALE_CASHBOX_ATOL_ERR_EMPTY_TAX')));
545 break;
546 }
547 }
548
549 return $result;
550 }
551
555 public static function getFfdVersion(): ?float
556 {
557 return 1.05;
558 }
559}
static getMessage($code, $replace=null, $language=null)
Definition loc.php:29
registerCheck($operation, array $check)
printCorrectionImmediately(CorrectionCheck $check)
buildPositionVatType(array $checkData, array $item)
buildPosition(array $checkData, array $item)
getRequestUrl($operation, $token, array $queryData=array())
buildCheckQuery(Check $check)
getValueFromSettings($name, $code)
Definition cashbox.php:201
const PAYMENT_OBJECT_SOCIAL_INSURANCE
Definition check.php:47
const PAYMENT_OBJECT_LOTTERY_PRIZE
Definition check.php:32
const PAYMENT_OBJECT_MEDICAL_INSURANCE_IP
Definition check.php:45
const PAYMENT_OBJECT_COMMODITY_MARKING_EXCISE
Definition check.php:50
const PAYMENT_OBJECT_NON_OPERATING_GAIN
Definition check.php:38
const PAYMENT_OBJECT_COMMODITY_MARKING_NO_MARKING_EXCISE
Definition check.php:49
const PAYMENT_OBJECT_RESORT_FEE
Definition check.php:40
const PAYMENT_OBJECT_PENSION_INSURANCE_IP
Definition check.php:43
const PAYMENT_OBJECT_PROPERTY_RIGHT
Definition check.php:37
const PAYMENT_OBJECT_GAMBLING_PRIZE
Definition check.php:30
const PAYMENT_OBJECT_COMMODITY_MARKING
Definition check.php:52
const PAYMENT_OBJECT_AGENT_COMMISSION
Definition check.php:34
const PAYMENT_OBJECT_MEDICAL_INSURANCE
Definition check.php:46
const PAYMENT_OBJECT_INTELLECTUAL_ACTIVITY
Definition check.php:33
const PAYMENT_OBJECT_GAMBLING_BET
Definition check.php:29
const PAYMENT_OBJECT_CASINO_PAYMENT
Definition check.php:48
const PAYMENT_OBJECT_PENSION_INSURANCE
Definition check.php:44
const PAYMENT_OBJECT_COMMODITY_MARKING_NO_MARKING
Definition check.php:51
buildCorrectionCheckQuery(CorrectionCheck $check)