WSTĘP

Biblioteka mobilna dla systemu Android umożliwia wykonanie płatności wewnątrz aplikacji mobilnej sklepu bez konieczności przełączania użytkownika między aplikacją a przeglądarką lub inną aplikacją. 

W bibliotece dostępne są następujące metody płatności

  1. Przelewy bankowe 
  2. Karty płatnicze
  3. Google Pay
  4. BLIK

KONFIGURACJA 

1. Pobierz gotową bibliotekę dla systemu Android.
2. Następnie w pliku konfiguracyjnym dokonaj konfiguracji danych z konta Tpay. 

TpayModule.configure(  
    Merchant(
        merchantId = "YOUR_MERCHANT_ID",
        authorization = Merchant.Authorization(  
            clientId = "YOUR_CLIENT_ID",  
            clientSecret = "YOUR_CLIENT_SECRET"  
        )
    )  
)

Co oznaczają poszczególne pola?

  • YOUR_MERCHANT_ID numer ID twojego konta 
  • YOUR_CLIENT_ID tutaj umieść wartość z pola Client_ID*
  • YOUR_CLIENT_SECRET tutaj umieść wartość z pola Secret*

 

* dane znajdziesz w Panelu Akceptanta w zakładce Integracje -> API w sekcji Klucze do nowego OpenAPI

3. Ustaw środowisko pracy 

 

TpayModule.configure(Environment.PRODUCTION)

Co oznaczają poszczególne pola?

 

Podczas konfiguracji upewnij się, że dane konfiguracyjne należą do odpowiedniego środowiska.

4. Ustaw język, który będzie wyświetlany w interfejsie użytkownika.

TpayModule.configure(  
    preferredLanguage = Language.PL,  
    supportedLanguages = listOf(Language.PL, Language.EN)  
)

5. Możesz konfigurować metody płatności, jakie będą dostępne w Twojej aplikacji. Należy wskazać te, które są dostępne na twoim koncie Sprzedawcy. 

TpayModule.configure(  
    paymentMethods = listOf(  
        PaymentMethod.Card,  
        PaymentMethod.Blik,  
        PaymentMethod.Pbl,  
        PaymentMethod.DigitalWallets(  
            wallets = listOf(DigitalWallet.GOOGLE_PAY)  
        )  
    )  
)

* używając  paymentMethods.allMethods wyświetlisz wszystkie metody płatności.

 

Jeśli jakieś metody płatności nie są dostępne na Twoim koncie, skontaktuj się z Biurem Obsługi Klienta Tpay.

6. Umieść odpowiednią nazwę Sprzedawcy oraz regulamin Sprzedawcy dla odpowiedniej wersji językowej. 

TpayModule.configure(object : MerchantDetailsProvider {  
    override fun merchantDisplayName(language: Language): String {  
        return when (language) { 
       Language.PL -> "polish name"  
            Language.EN -> "english name"  
        }  
    }

    override fun merchantCity(language: Language): String {
        return when (language) {
            Language.PL -> "Warszawa"
            Language.EN -> "Warsaw"
        }
    }

    override fun regulationsLink(language: Language): String {  
        return when (language) {  
            Language.PL -> "polish regulation url"  
            Language.EN -> "english regulation url"  
        }  
    }  
})

Co oznaczają poszczególne pola?

  • polish name – polska nazwa sprzedawcy 
  • english name – angielska nazwa sprzedawcy 
  • polish regulation url– adres URL do regulaminu w języku polskim
  • english regulation url– adres URL do regulaminu w języku angielskim

7. Jeśli Twój sklep będzie obsługiwał płatności kartowe, umieść klucz publiczny RSA z Panelu Akceptanta.

TpayModule.configure(object : SSLCertificatesProvider {  
    override var apiConfiguration: CertificatePinningConfiguration =  
        CertificatePinningConfiguration(publicKeyHash = "PUBLIC_KEY")  
})

Co oznacza to pole?

  • PUBLIC_KEY klucz publiczny RSA*

 

* dane znajdziesz w Panelu Akceptanta w zakładce Płatności kartami -> API. Aby klucz był widoczny, zaznacz opcję securesale jako tak.

8. Interfejs Tpay musi obsługiwać przycisk powrotu.

override fun onBackPressed() {  
        sheet.onBackPressed()  
}

9. Skonfiguruj obsługę rezultatu dla płatności przez Google Pay.

 

override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
    super.onActivityResult(requestCode, resultCode, data)
    // Where paymentSheet is a object of Payment.Sheet class
    paymentSheet.onActivityResult(requestCode, resultCode, data)
}

10. W celu rozpoczęcia płatności zainicjalizuj Payment.Sheet i wyświetl go w sposób pokazany poniżej.

// Create payment
val paymentSheet = Payment.Sheet(  
    object : Transaction {  
        override val amount: Double = 29.99  
        override val description: String = "transaction description"  
        override val payerContext: PayerContext = PayerContext(  
            payer = Payer(  
                name = "Jan Kowalski",  
                email = "[email protected]",  
                phone = null,  
                address = null  
            ),
            automaticPaymentMethods = AutomaticPaymentMethods(
                blikAlias = BlikAlias.Registered(value = "alias value", label = "alias label"),
                tokenizedCards = listOf(
                    TokenizedCard(token = "card token 1", cardTail = "1234", brand = CreditCardBrand.VISA),
                    TokenizedCard(token = "card token 2", cardTail = "1234", brand = CreditCardBrand.MASTERCARD)
                )
            )
        )  
  override val notifications: Notifications = Notifications(  
            notificationEmail = "[email protected]",  
            notificationUrl = "https://yourstore.com"  
        )  
    }  
)

// Add payment observer
paymentSheet.addObserver(object : PaymentDelegate {  
    override fun onPaymentCreated(transactionId: String?) { }  
    override fun onPaymentCompleted(transactionId: String?) { }  
    override fun onPaymentCancelled(transactionId: String?) { }
    override fun onModuleClosed() { }  
})

// Open UI module
val result = paymentSheet.present(activity, activity.supportFragmentManager)
if (result is SheetOpenResult.Success) {
    // Module opened successfully
}

Co oznaczają poszczególne pola?

  • amount – kwota transakcji 
  • description opis transakcji (będzie on również widoczny dla kupującego) (maksymalna długość) 
  • payerContext dane kupującego (wymagane name oraz e-mail)
  • blikAlias alias płatności BLIK do uruchomienia funkcjonalności BLIK one click
  • TokenizedCard token karty płatniczej wymagany do płatności cyklicznych
  • notificationEmail adres mailowy dla powiadomień dla sprzedawcy
  • notificationUrl adres URL dla serwera sprzedawcy, do poinformowania o zmianie statusu transakcji.

    Ważne: Weź pod uwagę, czy dwa pola notificationEmail oraz  notificationUrl są opcjonalne czy wymagane?

 

 Przykład utworzenia płatności kartowych przy użyciu tokenu karty 

// Create payment
val tokenPaymentSheet = CardTokenPayment.Sheet(  
    CardTokenTransaction(
        amount = 29.99,
        description = "transaction description",
        payer = Payer(
            name = "Jan Kowalski",
            email = "[email protected]",
            phone = null,
            address = null
        ),
        cardToken = "card token",
        notifications = "https://yourstore.com"
    )  
)

// Add payment observer
tokenPaymentSheet.addObserver(object : PaymentDelegate {  
    override fun onPaymentCreated(transactionId: String?) { }
    override fun onPaymentCompleted(transactionId: String?) { }
    override fun onPaymentCancelled(transactionId: String?) { }
    override fun onModuleClosed() { }
})

// Open UI module
val result = tokenPaymentSheet.present(activity, activity.supportFragmentManager)
if (result is SheetOpenResult.Success) { 
    // Module opened successfully
}

Co oznaczają poszczególne pola?

  • amount kwota transakcji (double)
  • description opis transakcji (będzie on widoczny również dla kupującego)
  • payer dane kupującego (wymagane name oraz e-mail)
  • cardToken token karty płatniczej
  • notification adres URL dla serwera sprzedawcy, do poinformowania o zmianie statusu transakcji

 

Bliblioteka Tpay SDK umożliwia tokenizację kart kredytowych w celu zachowania ich na potrzeby przyszłych płatności np. do pobierania płatności cyklicznych. 

Przykładowy kod realizujący tokenizację:

// Create tokenization
val tokenizationSheet = AddCard.Sheet(  
    tokenization = Tokenization(  
        payer = Payer(  
            name = "Jan Kowalski",  
            email = "[email protected]",  
            phone = null,  
            address = null  
        ),  
        notificationUrl = "https://yourstore.com"  
    )  
)

// Add tokenization observer
tokenizationSheet.addObserver(object : AddCardDelegate {  
    override fun onAddCardSuccess(tokenizationId: String?) { }
    override fun onAddCardFailure() { }
    override fun onModuleClosed() { }  
})

// Open UI module
val result = tokenizationSheet.present(activity, activity.supportFragmentManager)
if (result is SheetOpenResult.Success) { 
    // Module opened successfully
}

Co oznaczają poszczególne pola?

  • payer dane kupującego
  • notification adres URL dla serwera sprzedawcy, do poinformowania o zmianie statusu transakcji.

 

Biblioteka pozwala również na dokonywanie płatności bez widocznego interfejsu Tpay na ekranie urządzenia. Dzięki temu klient może opłacić zamówienie już podczas tworzenia płatności.

 

Klasa GetPaymentMethods umożliwia pobranie metody płatności, które możesz wykorzystać do swojej aplikacji. 

Jest to część wspólna dla metod płatności dostępnych na koncie Sprzedawcy w systemie Tpay oraz metod płatności skonfigurowanych za pomocą TpayModule. Wynikiem działania jest result

GetPaymentMethods().execute { result ->  
    if (result is GetPaymentMethodsResult.Success) {  
        if (result.isCreditCardPaymentAvailable) {  
            // show credit card  
        }  
        if (result.isBLIKPaymentAvailable) {  
            // show BLIK  
        }  
        if (result.availableTransferMethods.isNotEmpty()) {
            // show transfers
            // each transfer object contains         
            // groupId, name and image url
        }
        if (result.availableDigitalWallets.isNotEmpty()) {  
            // show digital wallets  
        }  
    }  
}

Wszystkie płatności bez widocznego interfejsu Tpay wymagają podania danych dotyczących transakcji oraz danych o płatniku. Dodatkowo  możesz także przekazywać przekierowania i powiadomienia.

val payer = Payer(  
    name = "Jan Kowalski",  
    email = "[email protected]",  
    phone = null,  
    address = null  
)

val paymentDetails = PaymentDetails(  
    amount = 29.99,  
    description = "transaction description",  
    hiddenDescription = "hidden description",  
    language = Language.PL  
)

val redirects = Redirects(  
    successUrl = "https://yourstore.com/success",  
   errorUrl = "https://yourstore.com/error"  
)  

val notifications = Notifications(  
    notificationEmail = "[email protected]",  
    notificationUrl = "https://yourstore.com"  
)

o oznaczają poszczególne pola?

  • payer – dane płatnika
  • paymentDetails – dane płatności
  • redirects – przekierowania po zakończonej transakcji
  • notifications – powiadomienia informujące o statusie transakcji

 

Klasa CreditCardPayment umożliwia tworzenie płatności za pomocą danych karty kredytowej, tokenu karty kredytowej (mechanizm zapisywania danych karty) lub poprzez płatności rekurencyjne.

val calendar = Calendar.getInstance()  
calendar.set(2024, 6, 1)  

CreditCardPayment.Builder()  
    .setRecursive(  
        Recursive(  
            frequency = Frequency.MONTHLY,  
            quantity = Quantity.Specified(3),  
            expirationDate = calendar.time  
        )  
    )  
    .setCallbacks(redirects, notifications)  
    .setPayer(payer)  
    .setCreditCard(  
        CreditCard("1111111111111111", "02/29", "123"),  
        domain = "https://yourstore.com"  
    )  
    .setCreditCardToken("card token")
    .setPaymentDetails(paymentDetails)  
    .build()
    .execute { result ->
        // handle payment create result
    }

Co oznaczają poszczególne pola?

  • setRecursive – mechanizm odpowiadający za wywoływanie płatności cyklicznych 
  • setCreditCard – dane karty płatniczej

 

Klasa BLIKPayment tworzy transakcje metodą BLIK, gdzie kod z Aplikacji Bankowej oraz dodania aliasu do płatności jest przesyłany od razu. Dodanie aliasu pozwala na dokonywanie kolejnych płatności bez podawania kodu. 

 

BLIKPayment.Builder()  
    .setBLIKCode(code = "123456")
    .setBLIKCodeAndRegisterAlias(
        code = "123456", 
        blikAlias = BlikAlias.NotRegistered(value = "value", label = "label")
    )
    .setBLIKAlias(BlikAlias.Registered(value = "value", label = "label"))
    .setPayer(payer)  
    .setPaymentDetails(paymentDetails)
    .setCallbacks(redirects, notifications)
    .build()  
    .execute { result ->  
        // handle payment create result
    }

Klasa TransferPaymentpozwala na wybór metody płatności bezpośrednio w aplikacji mobilnej (bez uruchamiania interfejsu Tpay).

TransferPayment.Builder()  
    .setGroupId(102)  
    .setPayer(payer)  
    .setPaymentDetails(paymentDetails)  
    .setCallbacks(redirects, notifications)  
    .build()  
    .execute { result -> 
        // handle payment create result
    }

Co oznacza to pole?

  • setGroupId tutaj umieść grupę metody płatności. Tę klasę dodaliśmy z zamiarem użycia jej dla standardowych płatności online, dlatego zalecamy pobieranie dostępnych grup płatności z metody GetPaymentMethods z pola result.availableTransferMethods

 

Klasa GooglePayPayment zezwala na płatność kartą powiązaną z płatnościami Google Pay. 

GooglePayPayment.Builder()
    .setGooglePayToken("GOOGLE_PAY_TOKEN")
    .setPayer(payer)
    .setPaymentDetails(paymentDetails)
    .setCallbacks(redirects, notifications)
    .build()
    .execute { result ->
        // handle payment create result
    }

Dla ułatwienia możesz użyć gotowej klasy GooglePayUnit

val googlePayUtil = GooglePayUtil(
    activity = requireActivity(),
    googlePayRequest = GooglePayRequest(
        price = 19.99, // Final price
        merchantName = "Your Store",
        clientId = "YOUR_MERCHANT_ID" // Tpay client id
    ),
    googlePayEnvironment = GooglePayEnvironment.PRODUCTION
)

// Check if Google Pay is available to use on the device
googlePayUtil.checkIfGooglePayIsAvailable { isAvailable ->
    if (isAvailable) {
        // show Google Pay button
    }
}

// Opens the Google Pay module with data specified in GooglePayRequest
googlePayUtil.openGooglePay()

// Google Pay requires your app to override onActivityResult method in Activity
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
    super.onActivityResult(requestCode, resultCode, data)
googlePayUtil.handleActivityResult(requestCode, resultCode, data) { result ->
        when (result) {
            is OpenGooglePayResult.Success -> {
                // Payer selected credit card
                // use result.token with GooglePayPayment.Builder
                // to create payment
            }
            is OpenGooglePayResult.Cancelled -> {
                // Google Pay request was cancelled
            }
            is OpenGooglePayResult.UnknownError -> {
                // Unknown error occurred
            }
        }
    }
}

Płatności wykonywane bez interfejsu Tpay muszą wyświetlić użytkownikowi adres URL informujący o przebiegu danej transakcji. 

 

Płatności BLIKIEM nie przekierowują na płatności pod adresem URL, ponieważ użytkownik musi zaakceptować płatność w aplikacji bankowej. W przypadku tych płatności zaleca się użycie mechanizmu długiego odpytywania.

 

Przekaż obiekt LongPollingConfig jako pierwszy parametr funkcji wykonania, jak pokazano na BLIKPayment. Mechanizm długiego odpytywania uruchomi się tylko wtedy, gdy będzie on konieczny:

 

  • CreditCardPayment: kiedy jest tworzona płatność i musi nastąpić przekierowanie na  adres URL płatności.
  • BLIKPayment: kiedy tworzona jest płatność i płatnik musi zaakceptować ją  w aplikacji bankowej.
  • TransferPayment:  kiedy jest tworzona płatność i musi nastąpić przekierowanie na  adres URL płatności.
  • GooglePayPayment:  kiedy jest tworzona płatność i musi nastąpić przekierowanie na  adres URL płatności.
val config = LongPollingConfig(  
    delayMillis = 4000, // delay between requests
    maxRequestCount = 10, 
stopOnFirstRequestError = false, 
    onTransactionState = { 
        // this function is called on each response 
        // with new transaction state 
        // long polling keeps running if transaction 
        // state is PENDING
    },  
    onRequestError = { 
        // read error  
    },  
    onMaxRequestCount = { 
        // maximum request count was reached 
        // long polling stops and you can show timeout to user 
        // this means that we don't know if payment was successful
    }  
)

BLIKPayment.Builder()  
    .setBLIKCode("123456")
    .setBLIKAlias(alias = "value", label = "label")
    .setPayer(payer)  
    .setPaymentDetails(paymentDetails)
    .setCallbacks(redirects, notifications)
    .build()  
    .execute(config) { result ->  
        // handle payment create result
    }