Cost+Docs

Java / Kotlin

Oficjalny SDK Kotlin/Java dla bramki płatności Cost+

Oficjalny SDK Kotlin dla bramki płatności Cost+, w pełni interoperacyjny z Javą. Upraszcza przepływ przekierowań HPP (hostowanej strony płatności), podpisywanie HMAC i weryfikację webhooków.

Funkcje

  • Kotlin-first, przyjazny dla Javy — klasy danych, coroutines, null safety; w pełni używalny z Javy
  • kotlinx.serialization — bez zależności od Gson/Jackson; automatyczne mapowanie snake_case/camelCase
  • Generowanie podpisów HMAC-SHA256 i weryfikacja w stałym czasie
  • Parsowanie webhooków + weryfikacja zamówienia przez API
  • Funkcje suspend dla nieblokującego IO przez coroutines Kotlin
  • Wstrzykiwalny HttpClient do łatwego testowania z mockowymi transportami
  • Wymaga Java 17+

Wymagania

Instalacja

Gradle (Kotlin DSL)

dependencies {
    implementation("io.nopayn:nopayn-sdk:1.0.0")
}

Gradle (Groovy)

dependencies {
    implementation 'io.nopayn:nopayn-sdk:1.0.0'
}

Maven

<dependency>
    <groupId>io.nopayn</groupId>
    <artifactId>nopayn-sdk</artifactId>
    <version>1.0.0</version>
</dependency>

Szybki start (Kotlin)

1. Zainicjalizuj klienta

import io.nopayn.*
import kotlinx.coroutines.runBlocking

fun main() = runBlocking {
    val nopayn = NoPaynClient(
        NoPaynConfig(
            apiKey = "your-api-key",
            merchantId = "your-project",
        )
    )
}

2. Utwórz płatność i przekieruj na HPP

val result = nopayn.generatePaymentUrl(
    CreateOrderParams(
        amount = 1295,            // 12,95 EUR w centach
        currency = "EUR",
        merchantOrderId = "ORDER-001",
        description = "Premium Widget",
        returnUrl = "https://shop.example.com/success",
        failureUrl = "https://shop.example.com/failure",
        webhookUrl = "https://shop.example.com/webhook",
        locale = "en-GB",
        expirationPeriod = "PT30M",
    )
)

println(result.orderUrl)    // URL HPP
println(result.paymentUrl)  // Bezpośredni URL metody płatności
println(result.signature)   // Podpis HMAC-SHA256

3. Obsłuż webhook

// W obsłudze HTTP (Ktor, Spring, itp.)
val rawBody: String = request.body()
val verified = nopayn.verifyWebhook(rawBody)

println(verified.order.status)  // "completed", "cancelled", itp.
println(verified.isFinal)       // true gdy zamówienie się nie zmieni

if (verified.order.status == "completed") {
    // Zrealizuj zamówienie
}

Szybki start (Java)

import io.nopayn.*;
import kotlinx.coroutines.BuildersKt;
import kotlinx.coroutines.Dispatchers;

public class Example {
    public static void main(String[] args) throws Exception {
        NoPaynClient client = new NoPaynClient(
            new NoPaynConfig("your-api-key", "your-project", "https://api.nopayn.co.uk")
        );

        Order order = BuildersKt.runBlocking(
            Dispatchers.getIO(),
            (scope, continuation) -> client.createOrder(
                new CreateOrderParams(
                    1295, "EUR", "ORDER-001", "Premium Widget",
                    "https://shop.example.com/success",
                    "https://shop.example.com/failure",
                    "https://shop.example.com/webhook",
                    "en-GB", null, "PT30M"
                ),
                continuation
            )
        );

        System.out.println("Order ID: " + order.getId());
        System.out.println("Order URL: " + order.getOrderUrl());

        // Narzędzia podpisów działają synchronicznie
        String sig = client.generateSignature(1295, "EUR", order.getId());
        boolean valid = client.verifySignature(1295, "EUR", order.getId(), sig);
    }
}

Dokumentacja API

NoPaynClient(config, httpClient?)

ParametrTypWymaganyDomyślnie
config.apiKeyStringTak
config.merchantIdStringTak
config.baseUrlStringNiehttps://api.nopayn.co.uk
httpClientjava.net.http.HttpClientNieDomyślny klient

client.createOrder(params): Order (suspend)

Tworzy zamówienie przez POST /v1/orders/.

ParametrTypWymaganyOpis
amountIntTakKwota w najmniejszej jednostce waluty (centy)
currencyStringTakKod ISO 4217 (EUR, GBP, USD, NOK, SEK)
merchantOrderIdString?NieTwoja wewnętrzna referencja zamówienia
descriptionString?NieOpis zamówienia
returnUrlString?NiePrzekierowanie po pomyślnej płatności
failureUrlString?NiePrzekierowanie przy anulowaniu/wygaśnięciu/błędzie
webhookUrlString?NieAsynchroniczne powiadomienia o zmianie statusu
localeString?NieJęzyk HPP (en-GB, de-DE, nl-NL, itp.)
paymentMethodsList<String>?NieFiltruj metody HPP
expirationPeriodString?NieCzas trwania ISO 8601 (PT30M)

Dostępne metody płatności: credit-card, apple-pay, google-pay, vipps-mobilepay

client.getOrder(orderId): Order (suspend)

Pobiera szczegóły zamówienia przez GET /v1/orders/{id}/.

client.createRefund(orderId, amount, description?): Refund (suspend)

Dokonuje pełnego lub częściowego zwrotu przez POST /v1/orders/{id}/refunds/.

client.generatePaymentUrl(params): PaymentUrlResult (suspend)

Metoda pomocnicza, która tworzy zamówienie i zwraca:

PaymentUrlResult(
    orderId: String,     // UUID zamówienia NoPayn
    orderUrl: String,    // URL HPP
    paymentUrl: String?, // Bezpośredni URL płatności (pierwsza transakcja)
    signature: String,   // HMAC-SHA256 z amount:currency:orderId
    order: Order,        // Pełny obiekt zamówienia
)

client.generateSignature(amount, currency, orderId): String

Generuje podpis HMAC-SHA256 w formacie hex. Kanoniczny komunikat to $amount:$currency:$orderId, podpisany kluczem API.

client.verifySignature(amount, currency, orderId, signature): Boolean

Weryfikacja HMAC-SHA256 w stałym czasie.

client.verifyWebhook(rawBody): VerifiedWebhook (suspend)

Parsuje treść webhooka, następnie wywołuje GET /v1/orders/{id}/, aby zweryfikować rzeczywisty status.

Samodzielne narzędzia HMAC

import io.nopayn.NoPaynSignature

val sig = NoPaynSignature.generate("your-api-key", 1295, "EUR", "order-uuid")
val ok  = NoPaynSignature.verify("your-api-key", 1295, "EUR", "order-uuid", sig)

Z Javy:

String sig = NoPaynSignature.generate("your-api-key", 1295, "EUR", "order-uuid");
boolean ok = NoPaynSignature.verify("your-api-key", 1295, "EUR", "order-uuid", sig);

Obsługa błędów

import io.nopayn.*

try {
    nopayn.createOrder(CreateOrderParams(amount = 100, currency = "EUR"))
} catch (e: ApiException) {
    println(e.statusCode)  // 401, 400, itp.
    println(e.errorBody)   // Surowa odpowiedź błędu API
} catch (e: NoPaynException) {
    println(e.message)     // Błąd sieci lub parsowania
}

Statusy zamówień

StatusKońcowy?Opis
newNieZamówienie utworzone
processingNiePłatność w toku
completedTakPłatność zakończona sukcesem — wydaj towar
cancelledTakPłatność anulowana przez klienta
expiredTakLink płatności wygasł
errorTakBłąd techniczny

Najlepsze praktyki dotyczące webhooków

  1. Zawsze weryfikuj przez API — treść webhooka zawiera tylko identyfikator zamówienia, nigdy status. verifyWebhook() SDK robi to automatycznie.
  2. Zwracaj HTTP 200, aby potwierdzić odbiór. Każdy inny kod powoduje do 10 ponowień (co 2 minuty).
  3. Zaimplementuj zapasowe odpytywanie — dla zamówień starszych niż 10 minut, które nie osiągnęły końcowego statusu, odpytuj getOrder() jako zabezpieczenie.
  4. Bądź idempotentny — możesz otrzymać ten sam webhook wielokrotnie.

Karty testowe

Użyj tych kart w trybie testowym Cost+ (strona testowa):

KartaNumerUwagi
Visa (sukces)4111 1111 1111 1111Dowolny CVV
Mastercard (sukces)5544 3300 0003 7Dowolny CVV
Visa (odrzucona)4111 1111 1111 1105Do Not Honor
Visa (brak środków)4111 1111 1111 1151Insufficient Funds

Użyj dowolnej przyszłej daty ważności i dowolnego 3-cyfrowego CVC.

Aplikacja demonstracyjna

Aplikacja demonstracyjna oparta na Dockerze (Ktor) jest dołączona w repozytorium GitHub do testowania pełnego przepływu płatności.

Wsparcie

Potrzebujesz pomocy? Skontaktuj się z naszym zespołem wsparcia pod adresem support@costplus.io.

On this page