Использование различных способов оплаты

Пользователи Эвотор могут установить на смарт-терминал приложения для работы с различными платёжными системами. После установки приложения платёжной системы, на экране оплаты/возврата товара, помимо кнопок Наличные и Банковская карта, добавляется кнопка платёжной системы.

Служба для взаимодействия со сторонними платёжными системами

Чтобы добавить поддержку сторонней платёжной системы:

  1. В манифесте приложения, добавьте разрешение:

    <uses-permission android:name="ru.evotor.permission.PAYMENT_SYSTEM" />
    
  2. Создайте службу и назовите её, например .PaymentService.

    Служба будет обрабатывать событие evo.v2.receipt.paymentSystem.

    Событие содержит поле OperationType, которое указывает тип операции:

    • OperationType.SELL – продажа;
    • OperationType.SELL_CANCEL – отмена продажи;
    • OperationType.PAYBACK – возврат;
    • OperationType.PAYBACK_CANCEL – отмена возврата.

    Каждому типу операции соответствует событие и метод, который его обрабатывает. Методы представлены в классе PaymentSystemProcessor.kt:

    abstract class PaymentSystemProcessor : ActionProcessor() {
        override fun process(action: String, bundle: Bundle?, callback: ActionProcessor.Callback) {
            val event = PaymentSystemEvent.create(bundle) ?: return
    
            when (event.operationType) {
                PaymentSystemEvent.OperationType.SELL -> sell(action, event as PaymentSystemSellEvent, callback)
                PaymentSystemEvent.OperationType.SELL_CANCEL -> sellCancel(action, event as PaymentSystemSellCancelEvent, callback)
                PaymentSystemEvent.OperationType.PAYBACK -> payback(action, event as PaymentSystemPaybackEvent, callback)
                PaymentSystemEvent.OperationType.PAYBACK_CANCEL -> paybackCancel(action, event as PaymentSystemPaybackCancelEvent, callback)
                else -> null
            }
        }
    

    Ваша служба должна реализовывать все методы, описанные в классе.

  3. Измените секцию службы .PaymentService в манифесте приложения:

    <service
        android:name=".PaymentService"
        android:exported="true"
        android:icon="@android:drawable/ic_dialog_map"
        android:label="Текст на кнопке">
        <meta-data
            android:name="ru.evotor.sales_screen.BACKGROUND_COLOR"
            android:value="@android:color/holo_green_light" />
        <meta-data
            android:name="ru.evotor.paymentSystem.PAYMENT_SYSTEM_ID"
            android:value="ru.test.testapplication.paymentSystem.packageName" />
    
        <intent-filter>
            <action android:name="evo.v2.receipt.paymentSystem" />
        </intent-filter>
    </service>
    

    Где:

    • Элемент ru.evotor.sales_screen.BACKGROUND_COLOR задаёт цвет кнопки платёжной системы.
    • Элемент ru.evotor.paymentSystem.PAYMENT_SYSTEM_ID задаёт уникальный идентификатор приложения. Уникальность идентификатора необходима, чтобы смарт-терминал всегда мог определить с какой платёжной системой он взаимодействует. Идентификатор остаётся неизменным даже, если название службы изменилось при обновлении приложения.
    • В intent-filter подпишите службу на получение события evo.v2.receipt.paymentSystem.
  4. После обработки события evo.v2.receipt.paymentSystem, служба .PaymentService должна возвращать соответствующий результат.

    В случае удачной обработки события служба возвращает результат PaymentSystemPaymentOkResult.

    В случае неудачной обработки события служба возвращает результат PaymentSystemPaymentErrorResult.

События

В зависимости от операции на смарт-терминале в службу могут поступать четыре типа событий.

Продажа

При продаже товара приходит событие PaymentSystemSellEvent.kt:

class PaymentSystemSellEvent(
        val receiptUuid: String,
        val accountId: String?,
        val sum: BigDecimal,
        val description: String?
)

Где:

Отмена продажи

При отмене продажи приходит событие PaymentSystemSellCancelEvent.kt:

class PaymentSystemSellCancelEvent(
        val receiptUuid: String,
        val accountId: String?,
        val sum: BigDecimal,
        val rrn: String?,
        val description: String?
)

Где:

Возврат

При возврате товара приходит событие PaymentSystemPaybackEvent.kt:

class PaymentSystemPaybackEvent(
        val receiptUuid: String,
        val accountId: String?,
        val sum: BigDecimal,
        val rrn: String?,
        val description: String?
)

Где:

Отмена возврата

При отмене возврата приходит событие PaymentSystemPaybackCancelEvent.kt:

class PaymentSystemPaybackCancelEvent(
        val receiptUuid: String,
        val accountId: String?,
        val sum: BigDecimal,
        val rrn: String?,
        val description: String?
)

Где:

Результаты

Успешная обработка события

В случае успешной обработки события служба должна возвращать результат PaymentSystemPaymentOkResult:

class PaymentSystemPaymentOkResult(
        val rrn: String,
        val slip: List<String>,
        val paymentInfo: String?,
        val paymentType: PaymentType = PaymentType.ELECTRON
)

Где:

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

В случае ошибки служба должна возвращать результат PaymentSystemPaymentErrorResult.kt:

class PaymentSystemPaymentErrorResult(
        val errorDescription: String?
)

Где:

Пример службы PaymentService

Пример работы с PaymentSystem API в демонстрационном приложении.

Пример службы PaymentService, которая поддерживает все методы класса PaymentSystemProcessor.kt:

public class PaymentService extends IntegrationService {

    public static final String TAG = "PaymentService";

    @Nullable
    @Override
    protected Map<String, ActionProcessor> createProcessors() {
        Map<String, ActionProcessor> processorMap = new HashMap<>();

        processorMap.put(
                PaymentSystemEvent.NAME_ACTION,
                new PaymentSystemProcessor() {

                    @Override
                    public void sell(String s, PaymentSystemSellEvent paymentSystemSellEvent, Callback callback) {
                        Log.e(TAG, "sell " + paymentSystemSellEvent);
                        Intent intent = new Intent(PaymentService.this, PaymentActivity.class);
                        intent.putExtra(EXTRA_NAME_OPERATION, "sell");
                        try {
                            callback.startActivity(intent);
                        } catch (RemoteException exc) {
                            exc.printStackTrace();
                        }
                    }

                    @Override
                    public void sellCancel(String s, PaymentSystemSellCancelEvent paymentSystemSellCancelEvent, Callback callback) {
                        Log.e(TAG, "sellCancel " + paymentSystemSellCancelEvent);
                        Intent intent = new Intent(PaymentService.this, PaymentActivity.class);
                        intent.putExtra(EXTRA_NAME_OPERATION, "sellCancel");
                        try {
                            callback.startActivity(intent);
                        } catch (RemoteException exc) {
                            exc.printStackTrace();
                        }
                    }

                    @Override
                    public void payback(String s, PaymentSystemPaybackEvent paymentSystemPaybackEvent, Callback callback) {
                        Log.e(TAG, "payback " + paymentSystemPaybackEvent);
                        Intent intent = new Intent(PaymentService.this, PaymentActivity.class);
                        intent.putExtra(EXTRA_NAME_OPERATION, "payback");
                        try {
                            callback.startActivity(intent);
                        } catch (RemoteException exc) {
                            exc.printStackTrace();
                        }
                    }

                    @Override
                    public void paybackCancel(String s, PaymentSystemPaybackCancelEvent paymentSystemPaybackCancelEvent, Callback callback) {
                        Log.e(TAG, "paybackCancel " + paymentSystemPaybackCancelEvent);
                        Intent intent = new Intent(PaymentService.this, PaymentActivity.class);
                        intent.putExtra(EXTRA_NAME_OPERATION, "paybackCancel");
                        try {
                            callback.startActivity(intent);
                        } catch (RemoteException exc) {
                            exc.printStackTrace();
                        }
                    }
                }
            }
        );
}

Пример операции PaymentActivity

package ru.apptest.test.testapplication;

import android.os.Bundle;
import android.view.View;
import android.widget.TextView;

import java.util.ArrayList;
import java.util.List;
import java.util.Random;

import ru.evotor.framework.core.IntegrationActivity;
import ru.evotor.framework.core.action.event.receipt.payment.system.result.PaymentSystemPaymentErrorResult;
import ru.evotor.framework.core.action.event.receipt.payment.system.result.PaymentSystemPaymentOkResult;
import ru.evotor.framework.payment.PaymentType;

public class PaymentActivity extends IntegrationActivity {

    public static final String EXTRA_NAME_OPERATION = "EXTRA_NAME_OPERATION";

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_payment);

        findViewById(R.id.button_ok).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                String rrn = "";
                Random random = new Random();
                for (int i = 0; i < 10; i++) {
                    rrn += random.nextInt(10);
                }
                List<String> slip = new ArrayList<String>();
                slip.add("SLIP START");
                slip.add("RRN:");
                slip.add(rrn);
                slip.add("SLIP EMD");
                setIntegrationResult(new PaymentSystemPaymentOkResult(rrn, slip, "123qwe", PaymentType.ELECTRON));
                finish();
            }
        });

        findViewById(R.id.button_error).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                setIntegrationResult(new PaymentSystemPaymentErrorResult("beda was happened"));
                finish();
            }
        });

        if (getIntent().hasExtra(EXTRA_NAME_OPERATION)) {
            ((TextView) findViewById(R.id.textView_operation)).setText(getIntent().getStringExtra(EXTRA_NAME_OPERATION));
        }

    }

    @Override
    public void onBackPressed() {
        setIntegrationResult(new PaymentSystemPaymentErrorResult("onBackPressed was happened"));
        finish();
    }
}