SimPay Checkout Android SDK wyświetla arkusz płatności w aplikacji. Pobiera kanały, tworzy transakcję, obsługuje BLIK Level 0 i kanały z przekierowaniem w Custom Tab, a następnie sprawdza status przez API. To biblioteka interfejsu Android, nie Java SDK do integracji backendowej.
Kod i aplikacja demonstracyjna są w repozytorium simpay-android. Ten SDK nie udostępnia obsługi OneClick, płatności cyklicznych BLIK, zwrotów, SMS ani DirectBilling.
- W panelu akceptanta otwórz ustawienia usługi i włącz obsługę w zakładce "Mobilne SDK".
- Zapisz krótki, 8-znakowy identyfikator usługi, np.
a1b2c3d4. To pierwszy segment UUID usługi, nie cały UUID. Backend i aplikacja muszą używać tej samej wartości. - Zarejestruj schemat powrotu, np.
pl.example.shop. Musi być identyczny w panelu, manifeście Androida iTransactionReturns. - Przygotuj backend do wydawania sesji i weryfikacji IPN. Klucz API akceptanta pozostaje wyłącznie na backendzie. Nie umieszczaj go w APK, zasobach ani
BuildConfig.
SDK wymaga minSdk 21, compileSdk co najmniej 34 i zgodności kodu Java 11. Wersja JDK uruchamiająca Gradle zależy od używanego Android Gradle Plugin, nie od ustawienia zgodności Java 11. Hostem arkusza musi być FragmentActivity lub jej podklasa, np. AppCompatActivity.
W settings.gradle.kts aplikacji:
dependencyResolutionManagement {
repositories {
google()
mavenCentral()
}
}W build.gradle.kts modułu aplikacji:
android {
compileSdk = 34
defaultConfig { minSdk = 21 }
compileOptions {
sourceCompatibility = JavaVersion.VERSION_11
targetCompatibility = JavaVersion.VERSION_11
}
}
dependencies {
implementation("pl.simpay:checkout-android:1.0.0")
}Wersja 1.0.0 jest dostępna w Maven Central. Pakiet zawiera AAR, źródła i dokumentację Javadoc. Nie wymaga dodatkowego repozytorium Maven poza mavenCentral().
Aplikacja prosi Twój uwierzytelniony backend o sesję. Backend wywołuje POST https://api.simpay.pl/payment/{serviceId}/mobile-sdk/session z kluczem akceptanta w Authorization: Bearer <klucz API>. Zwraca aplikacji krótko ważny token, zwykle około 15 minut, jego termin ważności, jeśli dostępny, oraz publiczny IP płatnika zaobserwowany przy żądaniu. Za proxy korzystaj wyłącznie z zaufanej konfiguracji przekazywania IP, nie z dowolnego nagłówka od klienta.
MyBackendClient i BackendSessionResponse poniżej to abstrakcje dostarczane przez integratora, nie klasy SDK. Zaimplementuj klienta HTTP swojego backendu. Nie wywołuj endpointu sesji z kluczem akceptanta z aplikacji.
import pl.simpay.android.checkout.mobile.MobileSdkSession
import pl.simpay.android.checkout.mobile.MobileSessionProvider
data class BackendSessionResponse(
val token: String,
val expiresAt: String?,
val payerIp: String
)
interface MyBackendClient {
suspend fun createPaymentSession(): BackendSessionResponse
}
class BackendSessionProvider(private val client: MyBackendClient) : MobileSessionProvider {
override suspend fun provideSession(): MobileSdkSession {
val response = client.createPaymentSession()
return MobileSdkSession(
token = response.token,
expiresAt = response.expiresAt,
payerIp = response.payerIp
)
}
}Przekaż cały token z prefiksem mobsdk_. SDK dodaje Bearer i używa stałego hosta https://api.simpay.pl. Provider powinien zwracać aktualną sesję, także przy ponownym wywołaniu. Nie loguj tokenów. payerIp to publiczny adres płatnika, nie adres serwera backendu ani lokalnego interfejsu telefonu. payerIpOverride w zamówieniu jest tylko wartością zapasową, gdy sesja nie zawiera IP, i podlega tym samym zasadom.
Poniższa funkcja przyjmuje klienta Twojego backendu. Wywołaj ją z aktywnej FragmentActivity, np. po naciśnięciu przycisku płatności. onResult aktualizuje interfejs aplikacji, nie realizuje zamówienia.
import androidx.fragment.app.FragmentActivity
import java.math.BigDecimal
import pl.simpay.android.checkout.mobile.CheckoutResult
import pl.simpay.android.checkout.mobile.SimPayMobileCheckout
import pl.simpay.android.checkout.mobile.SimPayMobileConfiguration
import pl.simpay.android.checkout.mobile.TransactionOrder
import pl.simpay.android.checkout.mobile.TransactionReturns
fun pay(
activity: FragmentActivity,
client: MyBackendClient,
onResult: (CheckoutResult) -> Unit
) {
val checkout = SimPayMobileCheckout(
configuration = SimPayMobileConfiguration(
serviceId = "a1b2c3d4",
merchantDisplayName = "Example Shop"
),
sessionProvider = BackendSessionProvider(client)
)
val order = TransactionOrder(
amount = BigDecimal("49.99"),
currency = "PLN",
description = "Order 2451",
control = "order-2451",
customerEmail = "buyer@example.com",
customerCountryCode = "PL",
returns = TransactionReturns(
success = "pl.example.shop://payment-return?result=success",
failure = "pl.example.shop://payment-return?result=failure"
)
)
checkout.present(activity, order, onResult)
}Kwota musi wynosić co najmniej 1. Używaj BigDecimal z tekstu, nie z Double. Opis ma limit 64 znaków, control 255. control powinno wskazywać zamówienie zapisane w Twoim backendzie. E-mail jest wymagany. Kraj to dwie wielkie litery ISO 3166-1 alpha-2 zgodne z walutą. SDK może ustalić kraj z waluty, ale dla niejednoznacznej waluty, np. EUR, podaj go jawnie.
Dodaj do <application> w AndroidManifest.xml. Zastąp nazwy klas i schemat wartościami swojej aplikacji. CheckoutActivity musi dziedziczyć po FragmentActivity.
<activity
android:name=".CheckoutActivity"
android:exported="false"
android:launchMode="singleTop" />
<activity
android:name=".PaymentReturnActivity"
android:exported="true"
android:theme="@android:style/Theme.Translucent.NoTitleBar">
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="pl.example.shop" android:host="payment-return" />
</intent-filter>
</activity>import android.app.Activity
import android.content.Intent
import android.os.Bundle
class PaymentReturnActivity : Activity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
startActivity(
Intent(this, CheckoutActivity::class.java)
.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP or Intent.FLAG_ACTIVITY_SINGLE_TOP)
)
finish()
}
}Nie traktuj parametru result=success jako potwierdzenia płatności. Schematy niestandardowe nie gwarantują wyłączności aplikacji. Powrót ma jedynie przywrócić ekran, a SDK ponownie sprawdza status transakcji. Nie zakładaj odtworzenia callbacku i całego checkoutu po zabiciu procesu. Po ponownym uruchomieniu pobierz stan zamówienia z backendu zamiast automatycznie tworzyć nową płatność.
CheckoutResult | Działanie aplikacji |
|---|---|
Succeeded | SDK odczytał transaction_paid. Pokaż wynik i pobierz stan zamówienia z backendu. |
Pending | Wynik pozostaje otwarty, np. trwa weryfikacja lub skończył się czas odpytywania. Nie oznaczaj jako opłacone ani definitywnie odrzucone. transactionId może być null. |
Failed | Obsłuż error; message zawiera szczegóły techniczne. transactionId i rawStatus mogą być null. Sprawdź stan zamówienia przed ponowieniem. |
Cancelled | Użytkownik zamknął arkusz. Nie jest to dowód anulowania zamówienia na backendzie. |
Żaden wynik SDK nie uprawnia do wydania towaru. Zmodyfikowana aplikacja może zmienić kwotę, walutę i control, a token sesji nie wiąże tych wartości z zamówieniem.
Backend musi zweryfikować sygnaturę IPN i obsłużyć zmianę statusu transakcji. Przed realizacją porównaj status opłacenia, identyfikator usługi, control i powiązanie transakcji z zamówieniem, kwotę oraz walutę z własnym rekordem zamówienia. Obsłuż powtórzone IPN idempotentnie. Przeglądarka i aplikacja nie są źródłem potwierdzenia. Zobacz wprowadzenie do IPN.
| Objaw | Co sprawdzić |
|---|---|
Gradle nie znajduje 1.0.0 | Sprawdź współrzędne pl.simpay:checkout-android:1.0.0 i obecność mavenCentral() w repozytoriach. |
| Błąd metadanych AAR | compileSdk musi wynosić co najmniej 34. |
present nie przyjmuje Activity | Wymagana jest FragmentActivity, nie sama ComponentActivity. |
SessionFailed lub Unauthorized | Włączenie Mobilnego SDK, krótki service ID, zgodność usługi i klucza na backendzie, ważność tokenu i pełny prefiks mobsdk_. |
MissingPayerIp | Backend musi zwrócić publiczny IP płatnika w sesji. |
MissingCountryCode | Podaj customerCountryCode, zwłaszcza dla EUR. |
| Płatnik zostaje w przeglądarce | Porównaj schemat w panelu, manifeście i obu adresach TransactionReturns, a także host filtra. |
RateLimited | Odczekaj przed ponowieniem, nie pobieraj sesji w pętli. |
BrowserUnavailable | Na urządzeniu musi być przeglądarka obsługująca przekierowanie. |
Indeterminate, timeout lub Pending | Sprawdź stan na backendzie. Nie ponawiaj automatycznie operacji, która mogła już utworzyć transakcję. |
Do diagnostyki używaj CheckoutResult.Failed.error i message, bez tokenów i danych płatnika w logach. Demo z fałszywym API sprawdza interfejs, nie rzeczywistą płatność. Przed wdrożeniem sprawdź na przygotowanej usłudze BLIK, przekierowanie i powrót, przerwanie płatności, opóźnione IPN i zgodność danych zamówienia na backendzie.