Для передачи информации, необходимой для формирования фискальных документов в ККТ продавца маркетплейс использует сервис https://kassa.payanyway.ru, который поддерживает сбор и передачу информации о платеже в ККТ и сервисы продавца следующих типов: https://kassa.payanyway.ru/instruction.
Для интеграции с сервисом https://kassa.payanyway.ru маркетплейсу необходимо запросить у продавца настройки доступа к ККТ (логин, пароль доступа, идентификатор ККТ) и передать их в сервис через API (в настоящей момент метод не реализован, данные заносятся вручную в личном кабинете).
Если маркетплейс использует транзитный счет, то фискальный документ необходимо формировать при поступлении платежа на транзитный счет
Настройка кассы
Для транзитного счета маркетплейса и для счета продавца, создаются учетные записи в kassa.payanyway.ru
В настройках kassa.payanyway.ru для транзитного счёта выбираем тип кассы: "МодульКасса", в поле "Ссылка на API МодульКассы" вводим значение
"-" (минус), логин, пароль, UUID киоска - поля должны быть пустые.
Касса должна быть включена (параметр "Касса включена").
Настраиваем PayURL, в случае использования транзитный PayURL, задаём другие необходимые параметры.
3. Настраиваем учетные записи в kassa.payanyway.ru для клиентов маркетплейса (продавцов), используя логин и пароль от "аккаунта 2" и номер расширенного счёта магазина. В экспертных настройках этих учетных записей указываем номер расширенного счёта (параметр "Родительский AccountId") транзитного счёта.
PayURL в этих учетных записях не используются, его настраивать не нужно.
Печать чеков
3.1. Передача номенклатуры через PayURL.
В случае передачи номенклатуры через PayURL в каждый элемент, описывающий товарную позицию, добавляется новый параметр "account". Этот параметр содержит номер расширенного счета клиента маркетпейса, в котором чек на этот товар нужно пробить.
3.2. Передача номенклатуры в платёжном запросе Moneta.Assistant.
В случае передачи номенклатуры в платёжном запросе Moneta.Assistant, аналогично п.3.1, добавляется параметр "a".
Пример параметра формы платежного запроса:
В случае передачи номенклатуры в платёжном запросе Moneta.Assistant, аналогично п.3.1, добавляется параметр "a". Пример параметра формы платежного запроса:
Данные для формирования чека можно передать в сервис kassa.payanyway.ru, при этом нет необходимости направлять url-уведомление об успешном платеже транзитом через сервис kassa.
Для передачи чека через API сервиса, используйте следующий код php:
<?php
// варианты налогообложения:
const paw_kassa_VAT0 = '1104'; // НДС 0%
const paw_kassa_VAT10 = '1103'; // НДС 10%
const paw_kassa_VAT18 = '1102'; // НДС 18% (c 01.01.2019 ставка 20%)
const paw_kassa_VATNOVAT = '1105'; // НДС не облагается
const paw_kassa_VATWR10 = '1107'; // НДС с рассч. ставкой 10%
const paw_kassa_VATWR18 = '1106'; // НДС с рассч. ставкой 18% (c 01.01.2019 ставка 20%)
//
// paw_kassa_sale - функция "печати" чека в кассе kassa.payanyway.ru, вызывать её нужно
// в обработчике PayURL в случае положительного ответа (SUCCESS)
//
// Параметры:
//
// $mnt_id - номер расширенного счёта (бизнес-счёта)
// $mnt_transaction_id - id (номер) заказа, однозначно определяющий заказ в системе магазина.
// В случае, если отправляется запрос на фискализацию чека возврата, необходимо добавить к
// MNT_TRANSACTION_ID префикс или постфикс.
// $mnt_operation_id - номер операции в системе MONETA.RU.
// $mnt_amount - сумма заказа (в формате Moneta.ru, пример: 100.00)
// $mnt_data_integrity_code - код проверки целостности данных
// $inventoryPositions = array(
// array(
// 'name' => 'tovar 1', 'price' => 1, 'quantity' => 2, 'vatTag' => paw_kassa_VATNOVAT,
// 'pm' => 'full_payment', 'po' => 'commodity', 'markCode' => array
(
'gs1m' => 'MDEwNDYzMDAzNDA3MDAxMjIxQ01LNDVCcmhOMFdMZg=='
)
// ),
// array(
// 'name' => 'tovar 2', 'price' => 3, 'quantity' => 1, 'vatTag' => paw_kassa_VATNOVAT,
// 'pm' => 'full_payment', 'po' => 'commodity', 'idInternal' => '1122334455')
// - позиции заказа,
//
// где:
// name - название товара
// price - цена за единицу товара
// quantity - количество единиц товара
// vatTag - вариант налогообложения
// markCode - код маркировки товара
Здесь:
gs1m - код товара, считанный с маркированного товара, в формате GS1 Data Matrix
(например: 010463003407001221CMK45BrhN0WLf). В связи с тем, что в коде маркировки могут быть
непечатные символы, необходимо перед отправкой кодировать строку с кодом маркировки в
Base64.
base64_encode(010463003407001221CMK45BrhN0WLf) = MDEwNDYzMDAzNDA3MDAxMjIxQ01LNDVCcmhOMFdMZg==
hex - код товара в шестнадцатеричном формате
// idInternal - внутренний код товара из учётной системы магазина. Если в личном кабинете
//kassa.payanyway.ru, была добавлена номенклатура с данным кодом товара, то данные номенклатуры
будут //добавлены в чек.
//
// для 'name' в $inventoryPositions надо делать преобразование cleanProductName
//
// $client['email'] - email покупателя
// $client['phone'] - номер телефона покупателя.
// Только цифры и символ “+” (без пробелов, др. символов)
// $client['name'] - наименование покупателя (клиента). Наименование организации или фамилия, имя,
// отчество (при наличии), серия и номер паспорта покупателя (клиента)
// $client['inn'] - ИНН организации или покупателя (клиента)
function cleanProductName($value)
{
$result = preg_replace('/[^0-9a-zA-Zа-яА-Я-,. ]/ui', '', htmlspecialchars_decode($value));
//$result = trim(mb_substr($result, 0, 20));
return $result;
}
function paw_kassa_sale($mnt_id, $mnt_transaction_id, $mnt_operation_id, $mnt_amount,
$mnt_data_integrity_code, $client, $inventoryPositions)
{
$productsTototal = 0;
foreach ($inventoryPositions AS $item)
{
$productsTototal = $productsTototal + floatval($item['price'])*floatval($item['quantity']);
}
if (floatval($productsTototal) != floatval($mnt_amount))
{
$discountRate = floatval($mnt_amount) / floatval($productsTototal);
$newInvenrory = array();
foreach ($inventoryPositions AS $item)
{
$item['price'] = round(floatval($item['price']) * $discountRate, 5);
$newInvenrory[] = $item;
}
$inventoryPositions = $newInvenrory;
}
$data = array(
'operationId' => $mnt_operation_id,
'checkoutDateTime' => date(DATE_ATOM),
'docNum' => $mnt_transaction_id,
'docType' => 'SALE',
'inventPositions' => $inventoryPositions,
'moneyPositions' => array(array('paymentType' => 'CARD', 'sum' => $mnt_amount)),
'client' => array(
'email' => $client['email'],
'phone' => $client['phone'],
'name' => cleanProductName($client['name']),
'inn' => cleanProductName($client['inn']),
),
);
$data['signature'] = md5($data['docNum'].$data['checkoutDateTime'].$mnt_data_integrity_code);
if (isset($_SERVER['HTTP_HOST']))
$domainName = $_SERVER['HTTP_HOST'];
else
$domainName = $_SERVER['SERVER_NAME'];
$data['telemetry'] = array('domain' => $domainName);
$jsonData = preg_replace_callback('/\\\\u(\w{4})/', function ($matches) {
return html_entity_decode('&#x' . $matches[1] . ';', ENT_COMPAT, 'UTF-8');
}, json_encode($data));
$operationUrl = 'https://kassa.payanyway.ru/api/api.php?accountid='.$mnt_id.'&group=receipt';
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $operationUrl);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, $jsonData);
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "POST");
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, array(
'Content-Type: application/json',
'Content-Length: '.strlen($jsonData)
));
$result = curl_exec($ch);
curl_close($ch);
return $result;
}
Чтобы фискализировать чек на возврат, нужно передать значение SALE_RETURN в параметре docType:
При передаче чека на зачёт предоплаты (чек, фискализируемый при отгрузке товара), тип оплаты paymentType должен быть передан как PREPAID.
Также в строки номенклатуры можно добавить параметр account для распределения чеков по магазинам торговой площадки при испоьзовании площадкой мультикорзины.