Bitrix-D7 23.9
 
Загрузка...
Поиск...
Не найдено
financialtransactionsru.php
1<?php
2
4
9
18{
19 public const FORMAT_IDENTIFIER = 'ST';
20 public const FORMAT_VERSION = '0001';
21 public const CHARSET_WIN1251 = 1;
22 public const CHARSET_UTF8 = 2;
23 public const CHARSET_KOI8R = 3;
24
25 // region mandatory fields
26 public const FIELD_NAME = 'Name';
27 public const FIELD_PERSONAL_ACCOUNT = 'PersonalAcc';
28 public const FIELD_BANK_NAME = 'BankName';
29 public const FIELD_BIC = 'BIC';
30 public const FIELD_CORRESPONDENT_ACCOUNT = 'CorrespAcc';
31 // endregion
32 //region common fields
33 public const FIELD_SUM = 'Sum';
34 public const FIELD_PURPOSE = 'Purpose';
35 public const FIELD_PAYEE_INN = 'PayeeINN';
36 public const FIELD_PAYER_INN = 'PayerINN';
37 public const FIELD_DRAWER_STATUS_CODE = 'DrawerStatus';
38 public const FIELD_KPP = 'KPP';
39 public const FIELD_CBC = 'CBC';
40 public const FIELD_OKTMO = 'OKTMO';
41 public const FIELD_PAYMENT_REASON_CODE = 'PaytReason';
42 public const FIELD_TAX_PERIOD = 'axPeriod';
43 public const FIELD_DOCUMENT_NUMBER = 'DocNo';
44 public const FIELD_DOCUMENT_DATE = 'DocDate';
45 public const FIELD_TAX_PAYMENT_KIND_CODE = 'TaxPaytKind';
46 //endregion
47 //region additional fields
48 public const FIELD_LAST_NAME = 'LastName';
49 public const FIELD_FIRST_NAME = 'FirstName';
50 public const FIELD_MIDDLE_NAME = 'MiddleName';
51 public const FIELD_PAYER_ADDRESS = 'PayerAddress';
52 public const FIELD_BUDGET_PERSONAL_ACCOUNT = 'PersonalAccount';
53 public const FIELD_DOCUMENT_INDEX = 'DocIdx';
54 public const FIELD_PENSION_ACCOUNT = 'PensAcc';
55 public const FIELD_CONTRACT = 'Contract';
56 public const FIELD_PAYER_PERSONAL_ACCOUNT = 'PersAcc';
57 public const FIELD_FLAT = 'Flat';
58 public const FIELD_PHONE = 'Phone';
59 public const FIELD_PAYER_ID_TYPE = 'PayerIdType';
60 public const FIELD_PAYER_ID_NUMBER = 'PayerIdNum';
61 public const FIELD_CHILD_FULL_NAME = 'ChildFio';
62 public const FIELD_BIRTH_DATE = 'BirthDate';
63 public const FIELD_PAYMENT_TERM = 'PaymTerm';
64 public const FIELD_PAYMENT_PERIOD = 'PaymPeriod';
65 public const FIELD_PAYMENT_CATEGORY = 'Category';
66 public const FIELD_SERVICE_NAME = 'ServiceName';
67 public const FIELD_COUNTER_ID = 'CounterId';
68 public const FIELD_COUNTER_VALUE = 'CounterVal';
69 public const FIELD_NOTICE_NUMBER = 'QuittId';
70 public const FIELD_NOTICE_DATE = 'QuittDate';
71 public const FIELD_INSTITUTE_NUMBER = 'InstNum';
72 public const FIELD_CLASS_NUMBER = 'ClassNum';
73 public const FIELD_SPECIALIST_FULL_NAME = 'SpecFio';
74 public const FIELD_SURCHANGE = 'AddAmount';
75 public const FIELD_RULING_NUMBER = 'RuleId';
76 public const FIELD_PROCEEDING_NUMBER = 'ExecId';
77 public const FIELD_REGISTRATION_PAYMENT_TYPE = 'RegType';
78 public const FIELD_UIN = 'UIN';
79 public const FIELD_CODE = 'TechCode';
80 //endregion
81
82 public const ERROR_CODE_MANDATORY_FIELD_IS_NOT_FILLED = 'ERROR_MANDATORY_FIELD_IS_NOT_FILLED';
83 public const ERROR_CODE_VALUE_IS_TOO_LONG = 'ERROR_VALUE_IS_TOO_LONG';
84 public const ERROR_CODE_VALUE_INCORRECT_TYPE = 'ERROR_VALUE_INCORRECT_TYPE';
85
86 protected const VALUE_DELIMITER = '=';
87
88 protected $charsetCode;
89 protected $fields = [];
90
91 public function __construct()
92 {
93 $this->charsetCode = self::CHARSET_UTF8;
94
95 $this->fields = [];
96 }
97
98 public function setCharsetCode(int $charsetCode): self
99 {
100 if (
101 $charsetCode !== static::CHARSET_WIN1251
102 && $charsetCode !== static::CHARSET_UTF8
103 && $charsetCode !== static::CHARSET_KOI8R
104 )
105 {
106 throw new ArgumentOutOfRangeException('charsetCode', static::CHARSET_WIN1251, static::CHARSET_KOI8R);
107 }
108
109 $this->charsetCode = $charsetCode;
110
111 return $this;
112 }
113
114 public function setFields(array $fields): self
115 {
116 $this->fields = $fields;
117
118 return $this;
119 }
120
121 public function setField(string $fieldName, string $value): self
122 {
123 $this->fields[$fieldName] = $value;
124
125 return $this;
126 }
127
128 public function addFields(array $fields): self
129 {
130 $this->fields = array_merge($this->fields, $fields);
131
132 return $this;
133 }
134
135 public function setName(string $name): self
136 {
137 $this->fields[static::FIELD_NAME] = $name;
138
139 return $this;
140 }
141
142 public function setPersonalAccount(string $personalAccount): self
143 {
144 $this->fields[static::FIELD_PERSONAL_ACCOUNT] = $personalAccount;
145
146 return $this;
147 }
148
149 public function setBankName(string $bankName): self
150 {
151 $this->fields[static::FIELD_BANK_NAME] = $bankName;
152
153 return $this;
154 }
155
156 public function setBIC(string $bic): self
157 {
158 $this->fields[static::FIELD_BIC] = $bic;
159
160 return $this;
161 }
162
163 public function setCorrespondentAccount(string $correspondentAccount): self
164 {
165 $this->fields[static::FIELD_CORRESPONDENT_ACCOUNT] = $correspondentAccount;
166
167 return $this;
168 }
169
170 public function validate(): Result
171 {
172 $result = new Result();
173
174 $mandatoryFieldNames = $this->getMandatoryFieldNames();
175 foreach ($mandatoryFieldNames as $mandatoryFieldName)
176 {
177 if (empty($this->fields[$mandatoryFieldName]))
178 {
179 $result->addError(
180 new Error(
181 'Mandatory field ' . $mandatoryFieldName . ' is not filled',
182 static::ERROR_CODE_MANDATORY_FIELD_IS_NOT_FILLED,
183 )
184 );
185 }
186 }
187 foreach ($this->fields as $fieldName => $value)
188 {
189 if (!$this->isValueTypeValid($value))
190 {
191 $result->addError(
192 new Error(
193 'Incorrect value type ' . $fieldName,
194 static::ERROR_CODE_VALUE_INCORRECT_TYPE,
195 )
196 );
197 continue;
198 }
199 $value = (string)$value;
200
201 $maxFieldLength = $this->getFieldValueMaximumLength($fieldName);
202 if ($maxFieldLength > 0 && mb_strlen($value) > $maxFieldLength)
203 {
204 $result->addError(
205 new Error(
206 'The value of ' . $fieldName . ' is too long',
207 static::ERROR_CODE_VALUE_IS_TOO_LONG,
208 )
209 );
210 }
211 }
212
213 return $result;
214 }
215
216 protected function isValueTypeValid($value): bool
217 {
218 return (is_null($value) || is_string($value) || is_int($value) || is_float($value));
219 }
220
221 protected function getMandatoryFieldNames(): array
222 {
223 return [
224 static::FIELD_NAME,
225 static::FIELD_PERSONAL_ACCOUNT,
226 static::FIELD_BANK_NAME,
227 static::FIELD_BIC,
228 static::FIELD_CORRESPONDENT_ACCOUNT,
229 ];
230 }
231
232 public function getFieldValueMaximumLength(string $fieldName): ?int
233 {
234 static $maximumFieldLengths = [
235 self::FIELD_NAME => 160,
236 self::FIELD_PERSONAL_ACCOUNT => 20,
237 self::FIELD_BANK_NAME => 120,
238 self::FIELD_BIC => 9,
239 self::FIELD_CORRESPONDENT_ACCOUNT => 20,
240 ];
241
242 return $maximumFieldLengths[$fieldName] ?? null;
243 }
244
245 public function getData(): string
246 {
247 $delimiter = $this->pickupDelimiter();
248 $decodedFields = $this->decodeFields();
249
250 $decodedFields = array_filter($decodedFields, static function($value) {
251 return (!empty($value) && !is_array($value) && !is_object($value));
252 });
253
254 $data =
255 static::FORMAT_IDENTIFIER
256 . static::FORMAT_VERSION
258 ;
259
260 foreach ($this->getMandatoryFieldNames() as $fieldName)
261 {
262 $data .= $delimiter . $fieldName . static::VALUE_DELIMITER . ($decodedFields[$fieldName] ?? '');
263 unset ($decodedFields[$fieldName]);
264 }
265
266 foreach ($decodedFields as $fieldName => $value)
267 {
268 $data .= $delimiter . $fieldName . static::VALUE_DELIMITER . $value;
269 }
270
271 return $data;
272 }
273
274 protected function pickupDelimiter(): ?string
275 {
276 $possibleDelimiters = ['|', '~', '_', '#', '$' , '^', '&', '*', '/', '`', '@', '%'];
277
278 $allValues = implode(' ', $this->fields);
279 foreach ($possibleDelimiters as $delimiter)
280 {
281 if (mb_strpos($allValues, $delimiter) === false)
282 {
283 return $delimiter;
284 }
285 }
286
287 return '|';
288 }
289
290 protected function pickupCharsetCode(): string
291 {
292 if ($this->charsetCode === static::CHARSET_WIN1251)
293 {
294 return 'Windows-1251';
295 }
296 if ($this->charsetCode === static::CHARSET_KOI8R)
297 {
298 return 'KOI8-R';
299 }
300
301 $this->charsetCode = static::CHARSET_UTF8;
302
303 return 'UTF-8';
304 }
305
306 protected function decodeFields(): array
307 {
308 $charsetTo = $this->pickupCharsetCode();
309
310 return Encoding::convertEncoding($this->fields, SITE_CHARSET, $charsetTo);
311 }
312}