Интеграция онлайн-кассы Комтет с сайтом

Author Автор: Роман Чернышов    Опубликовано: 3 декабря 2021

Комтет касса Доброго времени друзья, сегодня я хочу рассказать об опыте работы с API онлайн-кассы от компании Комтет, об интеграции её с сайтом совместных покупок(интернет-магазином) в рамках 54-ФЗ, где продажа подразумевает прием предоплаты от пользователей, с последующей полной оплатой заказа спустя пару недель, где также ряд товаров идет с маркировкой(487-ФЗ), в итоге как первое так и второе должно отобразиться в «пробиваемых» электронных чеках. И конечно же я расскажу о настройке таких параметров как — система налогообложения, наличие НДС и способ оплаты. Далее обо всем подробнее.

Алгоритм работы

В нашем случае, алгоритм работы и пробитие чеков подразумевает пробитие предварительных чеков о предоплате, с последующим пробитием второго чека о полном расчете или о возврате предоплаты, т.к. бизнес модель подразумевает выкуп товара у поставщика по заказу клиента, а товара может и не оказаться. Также мы работаем с клиентом(т.е. не продаем товар, а оказываем услугу) по агентскому договору, что также должно отобраться в чеках, чтобы последующее начисление налогов было корректным(только с суммы агентского вознаграждения).

По этому алгоритм работы у нас такой:

  1. Принимаем заказ и выставляем счет на сумму предоплаты в процентах от стоимости заказа, в некоторых случаях сумма предоплаты может равняться 100%. Во всех случаях это должно отразиться в чеках.
  2. Клиент производит оплату на сумму предоплаты, на что наш сайт отправляет по API Комтет запрос на печать чека предоплаты с такими параметрами: без НДС , УСН доход — расход 15%, оплата картой, сумма предоплаты, название услуги и заказанного товара, стоимость товара, количество, общая сумма, данные о кассире, данные о маркировке товара(если есть).
  3. Спустя некоторое время, когда пользователь получает свой заказ(заказанный товар), мы пробиваем основной закрывающий чек, указывая в нем те данные что и при предоплате, но сам чек уже имеет статус «полная оплата».
  4. В случае если пользователь по какой-то причине отказался от заказа или мы не можем его выполнить, то мы оформляем возврат и пробиваем соответствующий чек возврата.
  5. Также функционал должен предусматривать внесение корректировок, например если стоимость заказа изменилась или изменился список товаров.

Настройка кассы в личном кабинете Комтет

1. Регистрируемся на сайте Комтет и переходим в личный кабинет(ЛК).

Создание Кассы
2. Для тестирования вам будут выданы тестовые данные, для этого в ЛК в разделе Фискализация->Магазины нужно создать первый тестовый магазин, указав параметры: домен сайта, URL возврата в случае успеха и URL возврата в случае неудачи.

Параметры Кассы
3. Затем переходим в раздел Фискализация->Кассы, создаем Очередь и Кассу, указывая ФИО и ИНН кассира, связываем их. Касса последовательно разбирает задачи из очереди на фискализацию. К одной очереди можно добавить несколько касс, чтобы увеличить скорость обработки чеков.
Список очередей и касс

4. Для тестирования Кассы, вам потребуется скачать программу под Windows, далее установить её и настроить, указав при этом значения из полей ID кассы и секретный ключ кассы (их можно посмотреть в настройках кассы). Программа под Windows будет имитировать работу кассы на вашей тестовой среде. Как это выглядит вы можете посмотреть на скриншотах ниже.

Программа Комтет Касса для Windows Настройки Программы Комтет касса

5. После проделанной процедуры вы можете перейти к тестированию, а именно отправлять на печать чеки с помощью API Комтет, указав в его параметрах работы данные тестовой кассы. Все чеки будут печататься в тестовом режиме, на указанные вами Email адреса будут приходить чеки в электронном виде, где вы сможете посмотреть все их параметры и при необходимости внести настройки в свой скрипт работы с API.

6. После завершения тестирования вы сможете переключить работу API в боевой режим, указав параметры реальной онлайн кассы, вместо тестовой. Также по окончанию тестирования необходимо уведомить тех. поддержку Комтет, они со свой стороны, перед переключением в боевой режим,  проверят корректность работы вашей интеграции.

Описание API

Для работы с API, отправки данных для печати чеков, средствами PHP, предусмотрена специальная библиотека komtet-kassa-php-sdk, которая содержит в себе все необходимы классы и методы. Документация далеко не исчерпывающая и для понимания того, как работать например с чеками предоплаты было не понятно, для этого потребовалось заглянуть в сами скрипты, а по некоторым вопросом связаться с поддержкой. Ниже я приведу несколько примеров взаимодействия с API, которых нет в документации к SDK(хоть он их, разумеется, и поддерживает).

Разумеется можно реализовать и свои классы и методы работы с API, документация по ссылке.

Первым делом необходимо создать менеджер очередей(из документации к SDK):

<?php
 
use Komtet\KassaSdk\Client;
use Komtet\KassaSdk\QueueManager;
 
$key = 'идентификатор магазина';
$secret = 'секретный ключ';
// PSR-совместимый логгер (опциональный параметр)
$logger = null;
$client = new Client($key, $secret, $logger);
$manager = new QueueManager($client);

После чего зарегистрировать очереди:

<?php
$manager->registerQueue('queue-name-1', 'queue-id-1');
$manager->registerQueue('queue-name-2', 'queue-id-2');
// 'queue-name-1' и 'queue-name-2' - произвольные псевдомимы для обращения к очередям.
// 'queue-id-1' и 'queue-id-2' - идентификаторы очередей, созданных в личном кабинете.

Отправка чека на печать:

<?php
use Komtet\KassaSdk\Agent;
use Komtet\KassaSdk\Buyer;
use Komtet\KassaSdk\Check;
use Komtet\KassaSdk\Cashier;
use Komtet\KassaSdk\Payment;
use Komtet\KassaSdk\Position;
use Komtet\KassaSdk\TaxSystem;
use Komtet\KassaSdk\Vat;
use Komtet\KassaSdk\Exception\SdkException;
 
// уникальный ID, предоставляемый магазином
$checkID = 'id';
// E-Mail клиента, на который будет отправлен E-Mail с чеком.
$clientEmail = 'user@host';
 
$check = Check::createSell($checkID, $clientEmail, TaxSystem::COMMON); // или Check::createSellReturn для оформления возврата
// Говорим, что чек нужно распечатать
$check->setShouldPrint(true);
 
$vat = new Vat(Vat::RATE_20);
 
// Позиция в чеке: имя, цена, кол-во, общая стоимость, налог
$position = new Position('name', 100, 1, 100, $vat);
 
// Опционально можно установить:
// Идентификатор позиции
// $position->setId('123');
 
// Единицу измерения
// $position->setMeasureName('Кг.');
 
// Cпособ расчета
// $position->setCalculationMethod(CalculationMethod::FULL_PAYMENT);
 
// Признак расчета
// $position->setCalculationSubject(CalculationSubject::PRODUCT);
 
// Агента по предмету расчета
// $agent = new Agent(Agent::COMMISSIONAIRE, "+77777777777", "ООО 'Лютик'", "12345678901");
// $position->setAgent($agent);
 
//Код маркировки товара (487-ФЗ)
// $position->setNomenclature('123'); 
 
$check->addPosition($position);
 
// Итоговая сумма расчёта
$payment = new Payment(Payment::TYPE_CARD, 100);
$check->addPayment($payment);
 
// Добавление данных покупателя (опционально)
$buyer = new Buyer('Пупкин П.П.', '123412341234');
$check->addBuyer($buyer);
 
// Добавление кассира (опционально)
$cashier = new Cashier('Иваров И.П.', '1234567890123');
$check->addCashier($cashier);
 
// Добавляем чек в очередь.
try {
    $manager->putCheck($check, 'queue-name-1');
} catch (SdkException $e) {
    echo $e->getMessage();
}

Отправка чека коррекции:

<?php
use Komtet\KassaSdk\Correction;
use Komtet\KassaSdk\CorrectionCheck;
use Komtet\KassaSdk\AuthorisedPerson;
 
// Данные коррекции
// createSelf для самостоятельной коррекции
// createForced для коррекции по предписанию
$correction = Correction::createSelf(
    '2012-12-21', // Дата документа коррекции в формате yyyy-mm-dd
    '4815162342', // Номер документа коррекции
    'description' // Описание коррекции
);
 
// createSell для коррекции прихода
// createSellReturn для коррекции расхода
$check = CorrectionCheck::createSell(
    '4815162342', // Номер операции в вашей системе
    '4815162342', // Серийный номер принтера
    TaxSystem::COMMON, // Система налогообложения
    $correction // Данные коррекции
);
 
$check->setPayment(
    new Payment(Payment::TYPE_CARD, 4815), // Общая сумма по чеку
    new Vat('120') // Ставка налога
);
 
$authorised_person = new AuthorisedPerson(
  'Иваров И.И.', // ФИО
  '123456789012' // ИНН
);
$check->setAuthorisedPerson($authorised_person);
 
// Добавляем чек в очередь.
try {
    $manager->putCheck($check, 'queue-name-1');
} catch (SdkException $e) {
    echo $e->getMessage();
}

Отправка чека на предоплату сумма равная 100%:

<?php
use Komtet\KassaSdk\Agent;
use Komtet\KassaSdk\Buyer;
use Komtet\KassaSdk\Check;
use Komtet\KassaSdk\Cashier;
use Komtet\KassaSdk\Payment;
use Komtet\KassaSdk\Position;
use Komtet\KassaSdk\TaxSystem;
use Komtet\KassaSdk\Vat;
use Komtet\KassaSdk\Exception\SdkException;
 
use Komtet\KassaSdk\Client;
use Komtet\KassaSdk\QueueManager;
 
// уникальный ID, предоставляемый магазином
$checkID = 'id';
// E-Mail клиента, на который будет отправлен E-Mail с чеком.
$clientEmail = 'user@host';
 
$check = Check::createSellReturn($checkID, $clientEmail, TaxSystem::COMMON); // или Check::createSellReturn для оформления возврата
// Говорим, что чек нужно распечатать
$check->setShouldPrint(true);
 
$vat = new Vat(Vat::RATE_20);
 
// Позиция в чеке: имя, цена, кол-во, общая стоимость, налог
$position = new Position('name', 100, 1, 100, $vat);
 
// Cпособ расчета предварительный расчет 100%
$position->setCalculationMethod(CalculationMethod::PRE_PAYMENT_FULL);
 
$check->addPosition($position);
 
// Итоговая сумма расчёта
$payment = new Payment(Payment::TYPE_CARD, 100);
$check->addPayment($payment);
 
// Добавление данных покупателя (опционально)
$buyer = new Buyer('Пупкин П.П.', '123412341234');
$check->addBuyer($buyer);
 
// Добавление кассира (опционально)
$cashier = new Cashier('Иваров И.П.', '1234567890123');
$check->addCashier($cashier);
 
// Добавляем чек в очередь.
try {
    $manager->putCheck($check, 'queue-name-1');
} catch (SdkException $e) {
    echo $e->getMessage();
}

Отправка чека на предоплату сумма НЕ равная 100%, например 30%:

<?php
use Komtet\KassaSdk\Agent;
use Komtet\KassaSdk\Buyer;
use Komtet\KassaSdk\Check;
use Komtet\KassaSdk\Cashier;
use Komtet\KassaSdk\Payment;
use Komtet\KassaSdk\Position;
use Komtet\KassaSdk\TaxSystem;
use Komtet\KassaSdk\Vat;
use Komtet\KassaSdk\Exception\SdkException;
 
use Komtet\KassaSdk\Client;
use Komtet\KassaSdk\QueueManager;
 
// уникальный ID, предоставляемый магазином
$checkID = 'id';
// E-Mail клиента, на который будет отправлен E-Mail с чеком.
$clientEmail = 'user@host';
 
$check = Check::createSellReturn($checkID, $clientEmail, TaxSystem::COMMON); // или Check::createSellReturn для оформления возврата
// Говорим, что чек нужно распечатать
$check->setShouldPrint(true);
 
$vat = new Vat(Vat::RATE_20);
 
// Позиция в чеке: имя, цена, кол-во, общая стоимость 30%, налог
$position = new Position('name', 30, 1, 30, $vat);
 
// Cпособ расчета предварительный расчет 30%
$position->setCalculationMethod(CalculationMethod::PRE_PAYMENT_PART);
$check->addPosition($position);
 
// Итоговая сумма расчёта
$payment = new Payment(Payment::TYPE_CARD, 100);
$check->addPayment($payment);
 
// Добавление данных покупателя (опционально)
$buyer = new Buyer('Пупкин П.П.', '123412341234');
$check->addBuyer($buyer);
 
// Добавление кассира (опционально)
$cashier = new Cashier('Иваров И.П.', '1234567890123');
$check->addCashier($cashier);
 
// Добавляем чек в очередь.
try {
    $manager->putCheck($check, 'queue-name-1');
} catch (SdkException $e) {
    echo $e->getMessage();
}

Чек для оформления возврата:

<?php
use Komtet\KassaSdk\Agent;
use Komtet\KassaSdk\Buyer;
use Komtet\KassaSdk\Check;
use Komtet\KassaSdk\Cashier;
use Komtet\KassaSdk\Payment;
use Komtet\KassaSdk\Position;
use Komtet\KassaSdk\TaxSystem;
use Komtet\KassaSdk\Vat;
use Komtet\KassaSdk\Exception\SdkException;
 
// уникальный ID, предоставляемый магазином
$checkID = 'id';
// E-Mail клиента, на который будет отправлен E-Mail с чеком.
$clientEmail = 'user@host';
 
$check = Check::createSellReturn($checkID, $clientEmail, TaxSystem::COMMON); // или Check::createSellReturn для оформления возврата
// Говорим, что чек нужно распечатать
$check->setShouldPrint(true);
 
$vat = new Vat(Vat::RATE_20);
 
// Позиция в чеке: имя, цена, кол-во, общая стоимость, налог
$position = new Position('name', 100, 1, 100, $vat);
 
$check->addPosition($position);
 
// Итоговая сумма расчёта
$payment = new Payment(Payment::TYPE_CARD, 100);
$check->addPayment($payment);
 
// Добавление данных покупателя (опционально)
$buyer = new Buyer('Пупкин П.П.', '123412341234');
$check->addBuyer($buyer);
 
// Добавление кассира (опционально)
$cashier = new Cashier('Иваров И.П.', '1234567890123');
$check->addCashier($cashier);
 
// Добавляем чек в очередь.
try {
    $manager->putCheck($check, 'queue-name-1');
} catch (SdkException $e) {
    echo $e->getMessage();
}

Список констант для НДС

Vat::RATE_NOБез НДС
Vat::RATE_0НДС 0%
Vat::RATE_10НДС 10%
Vat::RATE_20НДС 20%
Vat::RATE_110Расчетная ставка 10/110
Vat::RATE_120Расчетная ставка 20/120

Список констант методов оплаты

CalculationMethod::PRE_PAYMENT_FULLПолная предварительная оплата до момента передачи предмета расчета «ПРЕДОПЛАТА 100 %»
CalculationMethod::PRE_PAYMENT_PARTЧастичная предварительная оплата до момента передачи предмета расчета — «ПРЕДОПЛАТА»
CalculationMethod::FULL_PAYMENTПолная оплата, в том числе с учетом аванса (предварительной оплаты) в момент передачи предмета расчета «ПОЛНЫЙ РАСЧЕТ»
CalculationMethod::ADVANCEАванс
CalculationMethod::CREDIT_PART Частичная оплата предмета расчета в момент его передачи с последующей оплатой в кредит «ЧАСТИЧНЫЙ РАСЧЕТ И КРЕДИТ»
CalculationMethod::CREDIT_PAY Оплата предмета расчета после его передачи с оплатой в кредит (оплата кредита) «ОПЛАТА КРЕДИТА»

CalculationMethod::CREDIT

Передача предмета расчета без его оплаты в момент его передачи с последующей оплатой в кредит — «ПЕРЕДАЧА В КРЕДИТ»

Список констант признаков расчета

CalculationSubject::PRODUCTТовар, за исключением подакцизного товара
CalculationSubject::PRODUCT_PRACTICALПодакцизный товар
CalculationSubject::WORKРабота
CalculationSubject::SERVICEУслуга
CalculationSubject::GAMBLING_BETПрием ставок при осуществлении деятельности по проведению азартных игр
CalculationSubject::GAMBLING_WINВыплата денежных средств в виде выигрыша при осуществлении деятельности по проведению азартных игр
CalculationSubject::LOTTERY_BETПрием денежных средств при реализации лотерейных билетов, электронных лотерейных билетов, приеме лотерейных ставок при осуществлении деятельности по проведению лотерей
CalculationSubject::LOTTERY_WINВыплата денежных средств в виде выигрыша при осуществлении деятельности по проведению лотерей
CalculationSubject::RIDПредоставление прав на использование результатов интеллектуальной деятельности или средств индивидуализации «ПРЕДОСТАВЛЕНИЕ РИД» или «РИД»
CalculationSubject::PAYMENTОб авансе, задатке, предоплате, кредите, взносе в счет оплаты, пени, штрафе, вознаграждении, бонусе и ином аналогичном предмете расчета
CalculationSubject::COMMISSIONВознаграждении пользователя, являющегося платежным агентом (субагентом), банковским платежным агентом (субагентом), комиссионером, поверенным или иным агентом
CalculationSubject::COMPOSITEО предмете расчета, состоящем из предметов, каждому из которых может быть присвоено значение от «0» до «11» (0-11 — это вышеперечисленные)
CalculationSubject::PAYВзнос в счет оплаты пени, штрафа, вознаграждения, бонуса или иного аналогичного предмета расчета
CalculationSubject::OTHERО предмете расчета, не относящемуся к предметам расчета, которым может быть присвоено значение от «0» до «12» (0-12 — это вышеперечисленные)
CalculationSubject::PROPERTY_RIGHTПередача имущественного права
CalculationSubject::NON_OPERATINGВнереализационный доход
CalculationSubject::INSURANCEСтраховые взносы
CalculationSubject::SALES_TAXТорговый сбор
CalculationSubject::RESORT_FEEКурортный сбор

Список констант типа оплаты

Payment::TYPE_CARDЭлектронными
Payment::TYPE_CASHНаличными
Payment::TYPE_PREPAYMENTCумма предоплатой (зачет аванса и/или предыдущих платежей)
Payment::TYPE_CREDITCумма постоплатой (кредит)
Payment::TYPE_COUNTER_PROVISIONINGCумма встречным предлжением

Список констант типа системы налогообложения

TaxSystem::COMMONЕдиный налог
TaxSystem::SIMPLIFIED_INДоход
TaxSystem::SIMPLIFIED_IN_OUTДоход/Расход
TaxSystem::UTOIIЕдиный налог на вмененный доход
TaxSystem::USTЕдиный социальный налог
TaxSystem::PATENTПатент

Заключение

При интеграции, на сайте был реализован функционал с учетом множества различных ситуаций, отмена или изменение параметров сделки, внесение корректировок и т.д., все эти действия сопряжены с автоматической печатью чеков, что существенно снижает нагрузку на кассира или бухгалтерию(что чаще всего), в тех случаях когда приходится вносить корректировки вручную.

Если вам нужна помощь в интеграции онлайн кассы, обращайтесь, буду раз сотрудничеству!

Оставить комментарий

Автор блога
Роман Чернышов
Веб-разработчик,
Full Stack
Senior, Architect
PHP, JavaScript, Node.JS, Python, HTML 5, CSS 3, MySQL, Bash, Linux Admin
Заказать работу
предложить оффер

Моя книга
Книга. Веб-разработчик. Легкий вход в профессию
Печатная книга
Веб-разработчик.
Легкий вход в профессию
Оформить предзаказ
Последние вопросы
Список вопросов
Последние комментарии
Меню

Archive

Мои проекты
Insurance CMS Love Crm CMS Совместные покупки Мой PHP Framework Хостинг для моих клиентов Лицензии на мой софт и поддержка