Разделение чека на несколько платежей

Редактировать

Когда пользователь при продаже или возврате товара выбирает тип оплаты Банковская карта, смарт-терминал рассылает событие PaymentSelectedEvent. Обрабатывая это событие приложения могут разделить оплату соответствующего чека на несколько платежей, например, в счёт разных юридических лиц.

При этом, если на смарт-терминале установлено несколько приложений, которые могут обработать событие PaymentSelectedEvent, пользователь каждый раз вручную выбирает необходимое приложение.

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

Схема разделения чека на несколько платежей и печатных групп выглядит следующим образом:

Схема разделения чека

Получение события

Создайте службу, которая будет обрабатывать событие, например, SplitPaymentService.

В манифесте приложения, в intent-фильтре службы, укажите событие выбора оплаты чека:

<service
    android:name=".SplitPaymentService"
    android:enabled="true"
    android:exported="true">
    <intent-filter>
        <!-- выбрана оплата чека продажи -->
        <action android:name="evo.v2.receipt.sell.payment.SELECTED" />
        <!-- выбрана оплата чека возврата -->
        <action android:name="evo.v2.receipt.payback.payment.SELECTED" />
    </intent-filter>
</service>

Обработка события

Для обработки события необходимо использовать метод call(@NonNull String action, @NonNull PaymentSelectedEvent event, @NonNull Callback callback) обработчика PaymentSelectedEventProcessor. Методы функции callback, которая передаётся в качестве параметра метода call(), позволяют сохранять результат обработки события (callback.onResult()), запускать операции (callback.startActivity()), а также пропускать обработку события (callback.skip()) и обрабатывать ошибки (методы callback.onError()).

В результате обработки события PaymentSelectedEventResult, который передаётся в качестве параметра метода callback.onResult(), требуется указать список необходимых платежей (объекты PaymentPurpose).

Вы также можете передать в результат обработки объект SetExtra, который позволяет сохранять в чеках дополнительные данные.

Чтобы обработать событие выбора оплаты:

  1. Унаследуйте службу SplitPaymentService от класса IntegrationService.
  2. Переопределите метод createProcessors().

    Метод возвращает в смарт терминал коллекцию пар “Событие”:”Обработчик события” (Map<String, ActionProcessor>).

  3. Создайте обработчик события PaymentSelectedEvent с помощью класса PaymentSelectedEventProcessor.
  4. Используйте методы функции обратного вызова callback, чтобы сохранить данные о результате обработки события (PaymentSelectedEventResult).
  5. Сохраните событие и его обработчик в коллекции и верните её в смарт-терминал.

После этого смарт-терминал начнёт процесс создания чека, перед которым разошлёт событие PrintGroupRequiredEvent. Обработайте это событие, чтобы разделить чек на несколько печатных групп.

Пример разделения платежей в чеке

public class SplitPaymentService extends IntegrationService {
    @Nullable
    @Override
    protected Map<String, ActionProcessor> createProcessors() {
        /*
        Указываем установленное на смарт-терминале приложение или его компонент, которое исполнит платежи.
        Исполнителя платежа также можно указать внутри метода call следущим образом: event.getPaymentPurpose().getPaymentPerformer();
         */
        PaymentPerformer paymentPerformerApplicationOrComponent = new PaymentPerformer(
                //Объект с описанием платёжной системы, которое использует приложение, исполняющее платёж.
                new PaymentSystem(PaymentType.CASH, "Some description", "Payment system ID"),
                //Пакет, в котором расположен компонент, исполняющий платёж.
                "ru.evotor.paymentapp",
                //Название компонента, исполняющего платёж.
                "ComponentName",
                //Идентификатор уникальный идентификатор приложения, исполняющего платёж.
                "App identifier",
                //Название приложения, исполняющего платёж
                "App name");

        //Создаём платежи для нескольких юридических лиц и добавляем их в список.
        PaymentPurpose firstLegalEntityPayment = new PaymentPurpose(
                //Идентификатор платежа.
                "First payment identifier",
                //Идентификатор платёжной системы. Устаревший параметр.
                "Deprecated PaymentSystemId or Null",
                //Установленное на смарт-терминале приложение или его компонент, выполняющее платёж.
                paymentPerformerApplicationOrComponent,
                //Сумма платежа.
                new BigDecimal(200.00),
                "Payment account identifier",
                //Сообщение для пользователя.
                "Your payment has proceeded successfully.");
        PaymentPurpose secondLegalEntityPayment = new PaymentPurpose("Second payment identifier",null,paymentPerformerApplicationOrComponent,new BigDecimal(12.12),"Some ID","Congratulations!");
        PaymentPurpose thirdLegalEntityPayment = new PaymentPurpose("Third payment identifier",null,paymentPerformerApplicationOrComponent,new BigDecimal(23.45),"Another ID","Go get some rest!");

        final List<PaymentPurpose> listOfAllPayments = Arrays.asList(firstLegalEntityPayment, secondLegalEntityPayment, thirdLegalEntityPayment);

        //Создаём обработчик события выбора оплаты.
        PaymentSelectedEventProcessor yourEventProcessor = new PaymentSelectedEventProcessor() {
            @Override
            public void call(@NonNull String action, @NonNull PaymentSelectedEvent event, @NonNull Callback callback) {
                /*
                Все методы функции обратного вызова могут вернуть исключение RemoteException, которое необходимо правильно обработать.
                Например, с помощью конструкции try {} catch () {}.
                 */
                try {
                    /*
                    Вы также можете воспользоваться другими методами функции обратного вызова.
                    Например, запустить операцию с помощью startActivity(Intent intent) или отреагировть на ошибку с помощью одного из методов onError().
                     */
                    callback.onResult(new PaymentSelectedEventResult(
                            //Добавляем дополнительные данные в чек.
                            new SetExtra(null),
                            listOfAllPayments));
                } catch (RemoteException exception) {
                    exception.printStackTrace();
                }
            }
        };

        //Создаём и возвращаем в смарт-терминал результат обработки события в виде коллекиции пар "Событие":"Обработчик события".
        Map<String, ActionProcessor> eventProcessingResult = new HashMap<>();
        eventProcessingResult.put(PaymentSelectedEvent.NAME_SELL_RECEIPT, yourEventProcessor);

        return eventProcessingResult;
    }
}

См. также