0.1.4-prod
added skip shtrih-searsh - [] in connect.json fixed license reader added clearing date-folder after read and before write
This commit is contained in:
@@ -37,22 +37,22 @@ type Config struct {
|
||||
|
||||
// FiscalInfo содержит агрегированную информацию о фискальном регистраторе.
|
||||
type FiscalInfo struct {
|
||||
ModelName string `json:"modelName"` // Наименование модели ККТ
|
||||
SerialNumber string `json:"serialNumber"` // Заводской номер ККТ
|
||||
RNM string `json:"RNM"` // Регистрационный номер машины (РНМ)
|
||||
OrganizationName string `json:"organizationName"` // Наименование организации пользователя
|
||||
Inn string `json:"INN"` // ИНН пользователя
|
||||
FnSerial string `json:"fn_serial"` // Серийный номер фискального накопителя
|
||||
RegistrationDate string `json:"datetime_reg"` // Дата и время регистрации ККТ
|
||||
FnEndDate string `json:"dateTime_end"` // Дата окончания срока действия ФН
|
||||
OfdName string `json:"ofdName"` // Наименование ОФД
|
||||
SoftwareDate string `json:"bootVersion"` // Версия (дата) прошивки ККТ
|
||||
FfdVersion string `json:"ffdVersion"` // Версия ФФД
|
||||
FnExecution string `json:"fnExecution"` // Исполнение ФН
|
||||
InstalledDriver string `json:"installed_driver"` // Версия установленного COM-драйвера
|
||||
AttributeExcise bool `json:"attribute_excise"` // Признак торговли подакцизными товарами
|
||||
AttributeMarked bool `json:"attribute_marked"` // Признак торговли маркированными товарами
|
||||
LicensesRawHex string `json:"licenses,omitempty"` // Строка с лицензиями в HEX-формате
|
||||
ModelName string `json:"modelName"` // Наименование модели ККТ
|
||||
SerialNumber string `json:"serialNumber"` // Заводской номер ККТ
|
||||
RNM string `json:"RNM"` // Регистрационный номер машины (РНМ)
|
||||
OrganizationName string `json:"organizationName"` // Наименование организации пользователя
|
||||
Inn string `json:"INN"` // ИНН пользователя
|
||||
FnSerial string `json:"fn_serial"` // Серийный номер фискального накопителя
|
||||
RegistrationDate string `json:"datetime_reg"` // Дата и время регистрации ККТ
|
||||
FnEndDate string `json:"dateTime_end"` // Дата окончания срока действия ФН
|
||||
OfdName string `json:"ofdName"` // Наименование ОФД
|
||||
SoftwareDate string `json:"bootVersion"` // Версия (дата) прошивки ККТ
|
||||
FfdVersion string `json:"ffdVersion"` // Версия ФФД
|
||||
FnExecution string `json:"fnExecution"` // Исполнение ФН
|
||||
InstalledDriver string `json:"installed_driver"` // Версия установленного COM-драйвера
|
||||
AttributeExcise bool `json:"attribute_excise"` // Признак торговли подакцизными товарами
|
||||
AttributeMarked bool `json:"attribute_marked"` // Признак торговли маркированными товарами
|
||||
SubscriptionInfo string `json:"licenses,omitempty"` // Строка с лицензиями в расшифрованном виде
|
||||
}
|
||||
|
||||
// Driver определяет основной интерфейс для работы с ККТ.
|
||||
@@ -114,10 +114,11 @@ func (d *comDriver) Connect() error {
|
||||
// Установка свойств подключения в зависимости от типа.
|
||||
oleutil.PutProperty(d.dispatch, "ConnectionType", d.config.ConnectionType)
|
||||
oleutil.PutProperty(d.dispatch, "Password", d.config.Password)
|
||||
if d.config.ConnectionType == 0 { // COM-порт
|
||||
switch d.config.ConnectionType {
|
||||
case 0: // COM-порт
|
||||
oleutil.PutProperty(d.dispatch, "ComNumber", d.config.ComNumber)
|
||||
oleutil.PutProperty(d.dispatch, "BaudRate", d.config.BaudRate)
|
||||
} else if d.config.ConnectionType == 6 { // TCP/IP
|
||||
case 6: // TCP/IP
|
||||
oleutil.PutProperty(d.dispatch, "IPAddress", d.config.IPAddress)
|
||||
oleutil.PutProperty(d.dispatch, "TCPPort", d.config.TCPPort)
|
||||
oleutil.PutProperty(d.dispatch, "UseIPAddress", true)
|
||||
@@ -203,10 +204,19 @@ func (d *comDriver) getBaseDeviceInfo(info *FiscalInfo) error {
|
||||
}
|
||||
}
|
||||
|
||||
// Получаем и расшифровываем информацию о лицензии
|
||||
if _, err := oleutil.CallMethod(d.dispatch, "ReadFeatureLicenses"); err == nil {
|
||||
if errCheck := d.checkError(); errCheck == nil {
|
||||
info.LicensesRawHex, _ = d.getPropertyString("License")
|
||||
hexLicense, _ := d.getPropertyString("License")
|
||||
info.SubscriptionInfo = decodeLicense(hexLicense)
|
||||
if info.SubscriptionInfo != "" {
|
||||
log.Printf("Информация о лицензии успешно расшифрована: %s", info.SubscriptionInfo)
|
||||
} else if hexLicense != "" {
|
||||
log.Printf("Не удалось распознать формат полученной лицензии: %s", hexLicense)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
log.Printf("Предупреждение: команда ReadFeatureLicenses не выполнена, информация о лицензиях недоступна.")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
@@ -238,7 +248,7 @@ func (d *comDriver) getFiscalizationInfo(info *FiscalInfo) error {
|
||||
|
||||
workMode, _ := d.getPropertyInt32("WorkMode")
|
||||
workModeEx, _ := d.getPropertyInt32("WorkModeEx")
|
||||
info.AttributeMarked = (workMode & 0x10) != 0 // Бит 4 - признак торговли маркированными товарами
|
||||
info.AttributeMarked = (workMode & 0x10) != 0 // Бит 4 - признак торговли маркированными товарами
|
||||
info.AttributeExcise = (workModeEx & 0x01) != 0 // Бит 0 - признак торговли подакцизными товарами
|
||||
return nil
|
||||
}
|
||||
@@ -564,4 +574,4 @@ func checkIP(ip string, port int32, timeout time.Duration, foundChan chan<- Conf
|
||||
foundChan <- config
|
||||
driver.Disconnect()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
95
pkg/shtrih/license.go
Normal file
95
pkg/shtrih/license.go
Normal file
@@ -0,0 +1,95 @@
|
||||
// Файл: pkg/shtrih/license.go
|
||||
package shtrih
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"sort"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// licenseInfo хранит информацию о квартале и годе для конкретного суффикса лицензии.
|
||||
type licenseInfo struct {
|
||||
quarter string
|
||||
year int
|
||||
}
|
||||
|
||||
// licenseMap сопоставляет суффиксы HEX-лицензий с датой окончания подписки.
|
||||
// Ключи должны быть в верхнем регистре.
|
||||
var licenseMap = map[string]licenseInfo{
|
||||
// 2027
|
||||
"FFFFFFFF": {"4", 2027},
|
||||
"FFFFFF7F": {"3", 2027},
|
||||
"FFFFFF3F": {"2", 2027},
|
||||
"FFFFFF1F": {"1", 2027},
|
||||
// 2026
|
||||
"FFFFFF0F": {"4", 2026},
|
||||
"FFFFFF07": {"3", 2026},
|
||||
"FFFFFF03": {"2", 2026},
|
||||
"FFFFFF01": {"1", 2026},
|
||||
// 2025
|
||||
"FFFFFF00": {"4", 2025},
|
||||
"FFFF7F00": {"3", 2025},
|
||||
"FFFF3F00": {"2", 2025},
|
||||
"FFFF1F00": {"1", 2025},
|
||||
// 2024
|
||||
"FFFF0F00": {"4", 2024},
|
||||
"FFFF0700": {"3", 2024},
|
||||
"FFFF0300": {"2", 2024},
|
||||
"FFFF0100": {"1", 2024},
|
||||
// 2023
|
||||
"FFFF": {"4", 2023},
|
||||
"FF7F": {"3", 2023},
|
||||
"FF3F": {"2", 2023},
|
||||
"FF1F": {"1", 2023},
|
||||
// 2022
|
||||
"FF0F": {"4", 2022},
|
||||
"FF07": {"3", 2022},
|
||||
"FF03": {"2", 2022},
|
||||
"FF01": {"1", 2022},
|
||||
// 2021
|
||||
"FF00": {"4", 2021},
|
||||
"7F00": {"3", 2021},
|
||||
"3F00": {"2", 2021},
|
||||
"1F00": {"1", 2021},
|
||||
// 2020
|
||||
"0F00": {"4", 2020},
|
||||
"0700": {"3", 2020},
|
||||
"0300": {"2", 2020},
|
||||
"0100": {"1", 2020},
|
||||
}
|
||||
|
||||
// sortedLicenseKeys хранит ключи из licenseMap, отсортированные по убыванию длины.
|
||||
// Это необходимо, чтобы длинные суффиксы ("FFFFFFFF") проверялись раньше коротких ("FFFF").
|
||||
var sortedLicenseKeys []string
|
||||
|
||||
func init() {
|
||||
keys := make([]string, 0, len(licenseMap))
|
||||
for k := range licenseMap {
|
||||
keys = append(keys, k)
|
||||
}
|
||||
sort.Slice(keys, func(i, j int) bool {
|
||||
return len(keys[i]) > len(keys[j])
|
||||
})
|
||||
sortedLicenseKeys = keys
|
||||
}
|
||||
|
||||
// decodeLicense расшифровывает HEX-строку лицензии в человекочитаемый формат.
|
||||
// Она ищет наиболее длинное известное вхождение кода лицензии внутри всей строки.
|
||||
// Если лицензия не распознана, возвращает пустую строку.
|
||||
func decodeLicense(hex string) string {
|
||||
if hex == "" {
|
||||
return ""
|
||||
}
|
||||
upperHex := strings.ToUpper(hex)
|
||||
|
||||
// Итерируемся по ключам, отсортированным от самого длинного к самому короткому.
|
||||
for _, licenseCode := range sortedLicenseKeys {
|
||||
// Проверяем, содержится ли код лицензии ГДЕ-ЛИБО в большой HEX-строке.
|
||||
if strings.Contains(upperHex, licenseCode) {
|
||||
info := licenseMap[licenseCode]
|
||||
return fmt.Sprintf("Подписка до %s квартала %d года", info.quarter, info.year)
|
||||
}
|
||||
}
|
||||
|
||||
return ""
|
||||
}
|
||||
Reference in New Issue
Block a user