pluspay_a2a

POS+ (Pluspay) Android uygulaması ile App-to-App (A2A) iletişim kurmak için geliştirilmiş Flutter eklentisi. Bu paket, Flutter uygulamanızdan POS+ uygulamasını başlatarak ödeme, iptal, EFT işlemleri, sipariş ödemeleri, gün sonu raporları ve parametre güncellemeleri yapmanızı sağlar.

Not: Bu paket yalnızca Android platformunu desteklemektedir. iOS desteği bulunmamaktadır.

Kurulum

Aşağıdaki komutu çalıştırın:

flutter pub add pluspay_a2a

Veya pubspec.yaml dosyanıza elle ekleyip flutter pub get çalıştırın:

dependencies:
  pluspay_a2a: ^0.8.0

Not: Mevcut versiyonları pub.dev/packages/pluspay_a2a sayfasından görebilirsiniz.

Hızlı Başlangıç

import 'package:pluspay_a2a/pluspay_a2a.dart';

// 1. İstemciyi oluşturun ve başlatın
final pluspay = PPA2AClient();
await pluspay.initialize();

// 2. Ödeme başlatın
try {
  final result = await pluspay.startPayment(
    PPStartPaymentRequestModel.toRequest(
      orderCode: 'ORD-001',
      totalAmount: 150.0,
      paymentType: PPPaymentType.POS,
      paymentMethod: PPPaymentMethod.CC,
    ),
  );
  print('Ödeme başarılı: ${result.id}');
} on PPA2AException catch (e) {
  print('Ödeme başarısız: ${e.errorCode} - ${e.message}');
}

// 3. İşiniz bittiğinde kaynakları temizleyin
await pluspay.dispose();

Dil (Locale)

POS+, isteğin header'ındaki locale alanına göre arayüzünü işlem süresince o dile çevirir ve cevap döndükten sonra cihazın önceki diline geri döner.

// Tüm istekler için varsayılan dil
await pluspay.initialize(locale: 'en');
// veya daha sonra
pluspay.locale = 'de';

// Tek bir istek için override
PPStartPaymentRequestModel.toRequest(
  orderCode: 'ORD-001',
  totalAmount: 150.0,
  paymentType: PPPaymentType.POS,
  paymentMethod: PPPaymentMethod.CC,
  locale: 'ar',
);
  • Desteklenen diller ppSupportedLocales sabitinde listelenir: tr, en, ar, de, fr, it, es, ru, zh.
  • en, en_US ve en-US biçimlerinin hepsi kabul edilir.
  • Alan gönderilmezse ya da desteklenmeyen bir dil gönderilirse POS+ mevcut dilinde açılır; hata dönmez.
  • Kiosk cihazlarında bu alan yok sayılır.
  • İsteğe ait locale, istemcinin locale değerinden önceliklidir.
  • error_message metinleri seçilen dilden bağımsız olarak her zaman Türkçedir (bkz. Hata Yönetimi).

İstemci Metodları

Tüm metodlar PPA2AClient sınıfı üzerindedir. Her metod başarılı durumda tipli bir response modeli döner, hata durumunda PPA2AException fırlatır.

Metod İstek Modeli Yanıt Modeli Açıklama
startPayment PPStartPaymentRequestModel PPStartPaymentResponseModel Ödeme başlat
cancelPayment PPCancelPaymentRequestModel PPStartPaymentResponseModel Ödeme iptal et
startEftPayment PPEftPaymentRequestModel PPStartPaymentResponseModel EFT POS ödemesi başlat
cancelEftPayment PPEftCancelRequestModel PPStartPaymentResponseModel EFT POS ödemesini iptal et
startOrderPayment PPOrderPaymentRequestModel PPOrderPaymentResponseModel Sipariş ödemesi başlat
startMultiPayment PPMultiPaymentRequest PPMultiPaymentResponseModel Çoklu ödeme başlat
createOrder PPOrderCreateRequest PPOrderCreateResponseModel Ödeme başlatmadan sipariş oluştur
triggerEod PPEodRequestModel PPEodResponseModel Gün sonu tetikle
triggerParameters PPParameterRequestModel PPParametersResponseModel Parametre güncellemesi tetikle
getAvailablePaymentMethods PPAvailablePaymentMethodsRequestModel PPAvailablePaymentMethodsResponseModel Aktif/kullanılabilir ödeme yöntemlerini sorgula
getTransactionResult PPTransactionResultRequestModel PPStartPaymentResponseModel Tek bir işlemin sonucunu sorgula
getOrderResult PPOrderResultRequestModel PPOrderPaymentResponseModel Siparişi ve tüm işlemlerini sorgula
technicalCancel PPTechnicalCancelRequestModel PPTechnicalCancelResponseModel İşlemi teknik olarak iptal et

Aynı anda tek istek: POS+ aynı anda yalnızca bir isteği işler. Bir isteğin cevabı beklenirken yeni bir istek gönderilirse, istemci intent atmadan hemen PP_A2A_015 (PPA2AErrorCodes.requestInProgress) fırlatır; bekleyen istek etkilenmez. 20 dakikadan uzun süredir cevapsız kalan bir istek kaybolmuş sayılır ve yeni isteği engellemez.

İstek Modelleri

Her istek modeli, düz ve kullanışlı bir API sunan toRequest factory constructor'ına sahiptir. İlgili alanları doğrudan geçirirsiniz; model dahili header + data yapısını sizin için oluşturur.

Ödeme Başlat

PPStartPaymentRequestModel.toRequest(
  orderCode: 'ORD-001',
  totalAmount: 100.0,
  paymentType: PPPaymentType.POS,
  paymentMethod: PPPaymentMethod.CC,
  installment: 3,               // opsiyonel
  isPartial: false,              // opsiyonel, varsayılan: false
  partialType: null,             // opsiyonel
  products: [],                  // opsiyonel
  billingInformation: null,      // opsiyonel
);

Ödeme İptal

PPCancelPaymentRequestModel.toRequest(
  orderCode: 'ORD-001',
  transactionId: 'TX-123',
  note: 'Müşteri iptali talep etti', // opsiyonel
);

EFT Ödeme

PPEftPaymentRequestModel.toRequest(
  totalAmount: 250.0,
  paymentType: PPPaymentType.POS,
  paymentMethod: PPPaymentMethod.CC,
  transactionId: 'EFT-001',
  taxRate: 18,
  installment: null, // opsiyonel
);

EFT İptal

PPEftCancelRequestModel.toRequest(
  transactionId: 'EFT-001',
  totalAmount: 250.0,
);

Sipariş Ödemesi

PPOrderPaymentRequestModel.toRequest(
  orderCode: 'ORD-001',
);

Gün Sonu (EOD)

PPEodRequestModel.toRequest(
  isAll: false,
  types: [PPEodType.POS, PPEodType.MULTINET],
);

Parametre Yükleme

PPParameterRequestModel.toRequest(
  isAll: true,
  types: null,
);

Mevcut Ödeme Yöntemleri

POS+ üzerinde o an aktif/kullanılabilir ödeme tiplerini ve yöntemlerini sorgular. Ekstra parametre gerektirmez.

PPAvailablePaymentMethodsRequestModel.toRequest();

Sipariş Oluşturma (Order Create)

Ödeme başlatmadan yalnızca sipariş oluşturur. Oluşturulan sipariş daha sonra aynı orderCode ile startOrderPayment üzerinden tahsil edilebilir. orderCode POS+ üzerinde zaten kayıtlıysa sipariş güncellenir.

PPOrderCreateRequest.toRequest(
  orderCode: 'ORD-001',
  orderDate: DateTime.now(),
  products: [
    ProductModel(
      id: 1,
      sku: 'SKU-001',
      title: 'Ürün 1',
      price: 100.0,
      quantity: 1,
      taxRate: 10,
      unit: PPQtyEnums.ADET,
      vatInclude: true,
      productType: PPProductTypeEnum.PHYSICALLY,
      discountValue: 0,
    ),
  ],
  currency: PPCurrencyType.TRY,                // opsiyonel, varsayılan: TRY
  deliveryType: PPDeliveryTypeEnum.CASH_ORDER, // opsiyonel, varsayılan: CASH_ORDER
  discountAmount: 0,                           // opsiyonel, varsayılan: 0
  billingInformation: null,                    // opsiyonel
  installment: null,                           // opsiyonel
  groupCode: null,                             // opsiyonel
  note: null,                                  // opsiyonel
);

Yanıt PPOrderCreateResponseModel (PPMultiPaymentResponseModel ile aynı sipariş detayı yapısı) döner.

Çoklu Ödeme (Multi Payment)

PPMultiPaymentRequest.toRequest(
  orderCode: 'ORD-001',
  orderDate: DateTime.now(),
  changePaymentStatus: true,
  products: [
    ProductModel(
      id: 1,
      sku: 'SKU-001',
      title: 'Ürün 1',
      price: 100.0,
      quantity: 1,
      taxRate: 10,
      unit: PPQtyEnums.ADET,
      vatInclude: true,
      productType: PPProductTypeEnum.PHYSICALLY,
      discountValue: 0,
      otvOrani: 0,             // opsiyonel, varsayılan: 0
      konaklamaOrani: 0,       // opsiyonel, varsayılan: 0
    ),
  ],
  transactions: [
    TransactionModel(
      paymentType: PPPaymentType.POS,
      totalAmount: 100.0,
      paymentMethod: PPPaymentMethod.CC,
    ),
  ],
  currency: PPCurrencyType.TRY,           // opsiyonel, varsayılan: TRY
  deliveryType: PPDeliveryTypeEnum.CASH_ORDER, // opsiyonel, varsayılan: CASH_ORDER
  discountAmount: 0,                       // opsiyonel, varsayılan: 0
  billingInformation: null,                // opsiyonel
  installment: null,                       // opsiyonel
  groupCode: null,                         // opsiyonel
  note: null,                              // opsiyonel
  canTryAgain: true,                       // opsiyonel, varsayılan: true
);

İşlem Sonucu Sorgulama (Transaction Result)

Tek bir işlemin güncel durumunu sorgular; ödeme başlatmaz. Zaman aşımı (PP_A2A_014) veya beklenmeyen hata (PP_A2A_007) sonrası işlemin gerçekten tamamlanıp tamamlanmadığını öğrenmek için kullanın. İşlem siparişte bulunamazsa PP_A2A_016 döner.

final tx = await pluspay.getTransactionResult(
  PPTransactionResultRequestModel.toRequest(
    orderCode: 'ORD-001',
    transactionId: 'TX-001',
  ),
);
print(tx.status); // örn. "SUCCESS"

Sipariş Sonucu Sorgulama (Order Result)

Siparişi ve üzerindeki tüm işlemleri (web, link vb. kanallardan yapılanlar dahil) döner; ödeme başlatmaz. Her results[] öğesinde completed, işlem başarılıysa true olur.

final order = await pluspay.getOrderResult(
  PPOrderResultRequestModel.toRequest(orderCode: 'ORD-001'),
);
print('${order.status} — kalan: ${order.amountDue}');

Teknik İptal (Technical Cancel)

Sonucu belirsiz kalan veya tutarsız bir işlemi teknik olarak iptal eder. Başarısız olursa PP_A2A_012 döner.

Cihaz desteği: Teknik iptal yalnızca PAX ve Kozen cihazlarda desteklenir. Diğer cihazlarda (Sunmi, SoftPOS, Kiosk vb.) istek PP_A2A_012 ile döner.

await pluspay.technicalCancel(
  PPTechnicalCancelRequestModel.toRequest(
    orderCode: 'ORD-001',
    transactionId: 'TX-001',
  ),
);

Yanıt Modelleri

Bilinmeyen enum değerleri: POS+ bu paket sürümünün tanımadığı bir enum değeri döndürürse yanıt hata vermez; ilgili alan UNKNOWN olur (PPParameterTypes için unknown). Zorunlu enum alanları hiç gelmezse de UNKNOWN olur; nullable alanlarda null, alanın gönderilmediği anlamına gelir. Liste alanlarında (örn. methods) bilinmeyen değerler atlanır. UNKNOWN yalnızca yanıtlarda görülür, isteklerde kullanmayın.

PPStartPaymentResponseModel

startPayment, cancelPayment, startEftPayment, cancelEftPayment ve getTransactionResult metodları tarafından döndürülür.

Alan Tip Açıklama
id String İşlem ID
orderCode String Sipariş kodu
paymentType PPPaymentType? Kullanılan ödeme tipi
paymentMethod PPPaymentMethod? Kullanılan ödeme yöntemi
totalAmount double Toplam tutar
totalPaid double? Ödenen tutar
amountDue double? Kalan tutar
isPartial bool Parçalı ödeme olup olmadığı
partialType PPPartialPaymentType? Parçalı ödeme tipi
source String? Kaynak bilgisi
status String? Durum metni
actionStatus bool? İşlem başarı durumu
invoice PPInvoiceModel? Fatura detayları
payment PPPaymentModel? Ödeme detayları (RRN, maskelenmiş kart, slip)
delivery PPDeliveryModel? Teslimat detayları

PPOrderPaymentResponseModel

startOrderPayment ve getOrderResult metodları tarafından döndürülür.

Alan Tip Açıklama
grandTotal double Genel toplam
status PPOrderStatusEnum? Sipariş durumu
orderCode String Sipariş kodu
totalAmount double Toplam tutar
totalPaid double Ödenen tutar
amountDue double Kalan tutar
results List<PPOrderTransactionResult> İşlem sonuçları

PPEodResponseModel

triggerEod metodu tarafından döndürülür.

Alan Tip Açıklama
results List<PPEodResponseItem> Tip bazında gün sonu sonuçları

Her PPEodResponseItem; eodType (PPEodType?), success (bool) ve opsiyonel errorMessage alanlarını içerir.

PPParametersResponseModel

triggerParameters metodu tarafından döndürülür.

Alan Tip Açıklama
results List<PPParameterResultModel> Parametre güncelleme sonuçları

Her PPParameterResultModel; type (PPParameterTypes?), completed (bool) ve opsiyonel errorMessage alanlarını içerir.

PPAvailablePaymentMethodsResponseModel

getAvailablePaymentMethods metodu tarafından döndürülür. Liste, oturumun profil/cihaz filtrelerinden geçmiş hâliyle döner — yani "şu an gerçekten yapılabilecek" ödeme yöntemleridir.

Alan Tip Açıklama
paymentTypes List<PPPaymentTypeMethodsModel> Aktif ödeme tipleri

Her PPPaymentTypeMethodsModel:

Alan Tip Açıklama
code PPPaymentType? Ödeme tipi
methods List<PPPaymentMethod> O tip için kullanılabilir yöntemler
title String? Görünen ad (opsiyonel)
final res = await pluspay.getAvailablePaymentMethods(
  PPAvailablePaymentMethodsRequestModel.toRequest(),
);
for (final type in res.paymentTypes) {
  print('${type.code} -> ${type.methods}');
}

PPMultiPaymentResponseModel

startMultiPayment metodu tarafından döndürülür.

Alan Tip Açıklama
id String İşlem ID
orderCode String Sipariş kodu
products List<PPMultiPaymentProduct> Ürün detayları
transactions List<PPMultiPaymentTransaction> İşlem detayları
paymentType PPPaymentType? Ödeme tipi
paymentMethod PPPaymentMethod? Ödeme yöntemi
status PPOrderStatusEnum? Sipariş durumu
totalAmount double Toplam tutar
discountAmount double İndirim tutarı
subTotal double Ara toplam
taxAmount double Vergi tutarı
grandTotal double Genel toplam
totalPaid double Ödenen tutar
amountDue double Kalan tutar
preTotal PPMultiPaymentPreTotal Ön toplam bilgileri
deliveryType PPDeliveryTypeEnum? Teslimat tipi
customer PPMultiPaymentCustomer? Müşteri bilgileri

PPTechnicalCancelResponseModel

technicalCancel metodu tarafından döndürülür.

Alan Tip Açıklama
orderCode String Sipariş kodu
transactionId String İptal edilen işlem ID
status String Başarılı durumda "SUCCESS"

Enum'lar

PPPaymentType

POS+ tarafından desteklenen ödeme tipleri.

POS, PAYCELL, HEPSIPAY, ISTANBULCARD, CASH, ONLINE, BANK_TRANSFER, GASTROPAY, CIO_CARD, IWALLET, PAYE, MULTINET, METROPOL, FASTPAY, TICKET, EDENRED, SETCARD, SODEXO, GETIRPAY, TOKENFLEX, YEMEKMATIK, ON_CREDIT, VIRTUAL_POS, CUZDANPLUS, INSTALLMENT

PPPaymentMethod

POS+ tarafından desteklenen ödeme yöntemleri.

CC, CASH, QR, QR_R, NFC, QUICKCODE, MOBILE, SWIPE, NONE, ONLINE, TRENDYOL, GETIR, YEMEKSEPETI, MIGROSYEMEK, CHIP, LINK, NFC_R, PAYCELL_LINK, PAYCELL_MERCHANT_PAGE

PPEodType

Gün sonu rapor tipleri.

POS, CASH, BANK_TRANSFER, ONLINE, OTHER, MULTINET, SODEXO, SETCARD, TICKET, METROPOL, PAYE, TOKENFLEX, EDENRED, CUZDANPLUS, IWALLET

PPParameterTypes

Parametre güncelleme tipleri.

bank, multinet, metropol, paye, iwallet

PPPartialPaymentType

AMOUNT, PRODUCT

PPOrderStatusEnum

CANCEL, NOT_RESPONSE, WAITING, SUCCESS

PPDeliveryStatusEnum

WAITING, PREPREING, READY, ONWAY, COMPLETE, CANCEL

PPDeliveryTypeEnum

CASH_ORDER, PACKAGE_ORDER, TABLE_ORDER, TAKE_AWAY, TAKE_CLOSE

PPCurrencyType

TRY, USD, EUR, GBP

PPProductTypeEnum

PHYSICALLY, VIRTUAL, INFO, MD, DSN, QP, KFO, COMMISSION, HGS

PPQtyEnums

Miktar birimleri.

ADET, KG, GR, LT, MT, KOLI, PAKET, PORSIYON

PPDiscountTypeEnum

PERCENTAGE, FIXED_AMOUNT

PPDocumentTypeEnum

EFATURA, EARSIV, BILGIFISI

PPDocumentStatusEnum

SUCCESS, CANCEL, FAIL, WAITING, NONE

PPTransactionStatusEnum

SUCCESS, CANCEL, FAIL, NONE, WAITING, NOT_RESPONSE

PPTransactionTypeEnum

START, SATIS, CANCEL, REFUND, IADE

PPOrderSourceEnum

POS, WEB, TSM, KIOSK

Hata Yönetimi

POS+ bir hata yanıtı döndürdüğünde (örn. kullanıcı iptali, reddedilen ödeme), istemci PPA2AException fırlatır. Hata kodlarını PPA2AErrorCodes sabitleriyle karşılaştırın:

try {
  final result = await pluspay.startPayment(request);
} on PPA2AException catch (e) {
  switch (e.errorCode) {
    case PPA2AErrorCodes.requestInProgress:
      // önceki isteğin cevabını bekleyin
      break;
    case PPA2AErrorCodes.timeout:
    case PPA2AErrorCodes.unexpectedException:
      // işlemin durumunu getTransactionResult / getOrderResult ile sorgulayın
      break;
    default:
      showError(myTextFor(e.errorCode));
  }
}

message her zaman Türkçedir. POS+'ın döndürdüğü error_message, header'da gönderilen locale'den bağımsızdır. Kullanıcıya göstereceğiniz metni errorCode üzerinden kendiniz üretin.

Hata Kodu Sabit Açıklama
PP_A2A_001 requestCannotBeNull İstek boş
PP_A2A_002 dataCannotBeNull İşlem data gerektiriyor ama gönderilmedi
PP_A2A_003 invalidClientToken Client token geçersiz
PP_A2A_004 invalidEodRequest Geçersiz gün sonu isteği (is_all false iken types boş)
PP_A2A_005 invalidParameterRequest Geçersiz parametre isteği (is_all false iken types boş)
PP_A2A_006 invalidRequestParameter data içindeki bir alan eksik/geçersiz
PP_A2A_007 unexpectedException POS+'ta beklenmeyen hata; işlemin durumunu sorgulayın
PP_A2A_008 invalidRequestHeader header eksik/geçersiz
PP_A2A_009 invalidTransactionType Bilinmeyen transaction_type
PP_A2A_010 invalidFieldHeader İşlemin gerektirdiği header alanı (order_code, transaction_id) eksik/geçersiz
PP_A2A_011 needsToLoginAtLeastOnce POS+ bu cihazda hiç giriş yapmamış
PP_A2A_012 errorOnProcess İşlem POS+'ta başarısız oldu (detay mesajda)
PP_A2A_013 autoLoginFailed POS+ otomatik giriş yapamadı
PP_A2A_014 timeout Zaman aşımı (bkz. Zaman Aşımı)
PP_A2A_015 requestInProgress Önceki bir istek hâlâ işleniyor
PP_A2A_016 transactionNotFound TRANSACTION_RESULT: işlem siparişte bulunamadı
LAUNCH_INTENT_ERROR launchIntentError İstemci: POS+ uygulaması başlatılamadı
PP-A2A-PARSE parseError İstemci: yanıt JSON'ı ayrıştırılamadı

Zaman Aşımı

  • POS+ kapalıyken gelen bir istekte, uygulamanın açılıp isteği karşılayacak hâle gelmesi için 3 dakika beklenir.
  • İşlemin kendisi için üst sınır 15 dakikadır.
  • İki durumda da POS+ PP_A2A_014 döner.
  • İstemci tarafında kendi zaman aşımınızı uyguluyorsanız bu süre 15 dakikadan uzun olmalıdır; aksi hâlde POS+'ta tamamlanmış bir ödeme sizin tarafınızda başarısız görünebilir.
  • PP_A2A_014 veya PP_A2A_007 aldığınızda işlemin gerçek sonucunu getTransactionResult (TRANSACTION_RESULT) ya da getOrderResult (ORDER_RESULT) ile sorgulayın.

Yaşam Döngüsü

class _MyPageState extends State<MyPage> {
  final _pluspay = PPA2AClient();

  @override
  void initState() {
    super.initState();
    _pluspay.initialize();
  }

  @override
  void dispose() {
    _pluspay.dispose();
    super.dispose();
  }
}

initialize() diğer tüm metodlardan önce çağrılmalıdır. Uygulamanın paket bilgilerini alır ve POS+ sonuçları için bir broadcast receiver kaydeder. İstemciye artık ihtiyaç kalmadığında receiver'ı temizlemek için dispose() çağrılmalıdır.

Gereksinimler

  • Yalnızca Android
  • Cihazda POS+ uygulaması yüklü olmalıdır
  • Minimum SDK: 24

Libraries

pluspay_a2a