Cost+Docs

Java / Kotlin

Oficiální Kotlin/Java SDK pro platební bránu Cost+

Oficiální Kotlin SDK pro platební bránu Cost+, plně interoperabilní s Javou. Zjednodušuje tok přesměrování HPP (Hosted Payment Page), HMAC podepisování payloadu a ověřování webhooků.

Funkce

  • Kotlin-first, přátelský k Javě — data classes, coroutines, null safety; plně použitelné z Javy
  • kotlinx.serialization — žádná závislost na Gson/Jackson; automatické mapování snake_case/camelCase
  • Generování podpisů HMAC-SHA256 a ověřování s konstantním časem
  • Parsování webhooků + ověřování objednávek přes API
  • Suspend funkce pro neblokující IO přes Kotlin coroutines
  • Injektovatelný HttpClient pro snadné testování s mock transports
  • Cílí na Java 17+

Požadavky

Instalace

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>

Rychlý start (Kotlin)

1. Inicializace klienta

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

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

2. Vytvoření platby a přesměrování na HPP

val result = nopayn.generatePaymentUrl(
    CreateOrderParams(
        amount = 1295,            // €12.95 in cents
        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)    // HPP URL
println(result.paymentUrl)  // Direct payment method URL
println(result.signature)   // HMAC-SHA256 signature

3. Zpracování webhooku

// In your HTTP handler (Ktor, Spring, etc.)
val rawBody: String = request.body()
val verified = nopayn.verifyWebhook(rawBody)

println(verified.order.status)  // "completed", "cancelled", etc.
println(verified.isFinal)       // true when the order won't change

if (verified.order.status == "completed") {
    // Fulfil the order
}

Rychlý 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());

        // Signature utilities work synchronously
        String sig = client.generateSignature(1295, "EUR", order.getId());
        boolean valid = client.verifySignature(1295, "EUR", order.getId(), sig);
    }
}

API reference

NoPaynClient(config, httpClient?)

ParametrTypPovinnéVýchozí
config.apiKeyStringAno
config.merchantIdStringAno
config.baseUrlStringNehttps://api.nopayn.co.uk
httpClientjava.net.http.HttpClientNeVýchozí klient

client.createOrder(params): Order (suspend)

Vytvoří objednávku přes POST /v1/orders/.

ParametrTypPovinnéPopis
amountIntAnoČástka v nejmenší měnové jednotce (centy)
currencyStringAnoISO 4217 kód (EUR, GBP, USD, NOK, SEK)
merchantOrderIdString?NeVaše interní reference objednávky
descriptionString?NePopis objednávky
returnUrlString?NePřesměrování po úspěšné platbě
failureUrlString?NePřesměrování při zrušení/vypršení/chybě
webhookUrlString?NeAsynchronní notifikace o změně stavu
localeString?NeJazyk HPP (en-GB, de-DE, nl-NL atd.)
paymentMethodsList<String>?NeFiltr metod HPP
expirationPeriodString?NeISO 8601 doba trvání (PT30M)

Dostupné platební metody: credit-card, apple-pay, google-pay, vipps-mobilepay

client.getOrder(orderId): Order (suspend)

Načte detaily objednávky přes GET /v1/orders/{id}/.

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

Provede úplnou nebo částečnou refundaci přes POST /v1/orders/{id}/refunds/.

client.generatePaymentUrl(params): PaymentUrlResult (suspend)

Pohodlná metoda, která vytvoří objednávku a vrátí:

PaymentUrlResult(
    orderId: String,     // NoPayn order UUID
    orderUrl: String,    // HPP URL
    paymentUrl: String?, // Direct payment URL (first transaction)
    signature: String,   // HMAC-SHA256 of amount:currency:orderId
    order: Order,        // Full order object
)

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

Generuje HMAC-SHA256 hex podpis. Kanonická zpráva je $amount:$currency:$orderId, podepsaná API klíčem.

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

Ověření HMAC-SHA256 podpisu s konstantním časem.

client.verifyWebhook(rawBody): VerifiedWebhook (suspend)

Parsuje tělo webhooku a poté zavolá GET /v1/orders/{id}/ pro ověření skutečného stavu.

Samostatné HMAC utility

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);

Zpracování chyb

import io.nopayn.*

try {
    nopayn.createOrder(CreateOrderParams(amount = 100, currency = "EUR"))
} catch (e: ApiException) {
    println(e.statusCode)  // 401, 400, etc.
    println(e.errorBody)   // Raw API error response
} catch (e: NoPaynException) {
    println(e.message)     // Network or parsing error
}

Stavy objednávek

StavKonečný?Popis
newNeObjednávka vytvořena
processingNePlatba probíhá
completedAnoPlatba úspěšná — doručte zboží
cancelledAnoPlatba zrušena zákazníkem
expiredAnoPlatební odkaz vypršel
errorAnoTechnická chyba

Osvědčené postupy pro webhooky

  1. Vždy ověřte přes API — webhookový payload obsahuje pouze ID objednávky, nikdy stav. Metoda verifyWebhook() SDK to dělá automaticky.
  2. Vraťte HTTP 200 jako potvrzení přijetí. Jakýkoli jiný kód spustí až 10 opakování (po 2 minutách).
  3. Implementujte záložní polling — pro objednávky starší než 10 minut, které nedosáhly konečného stavu, dotazujte getOrder() jako záchrannou síť.
  4. Buďte idempotentní — stejný webhook můžete obdržet vícekrát.

Testovací karty

Tyto karty použijte v testovacím režimu Cost+ (sandbox web):

KartaČísloPoznámky
Visa (úspěch)4111 1111 1111 1111Libovolné CVV
Mastercard (úspěch)5544 3300 0003 7Libovolné CVV
Visa (zamítnuto)4111 1111 1111 1105Do Not Honor
Visa (nedostatek prostředků)4111 1111 1111 1151Insufficient Funds

Použijte libovolné budoucí datum platnosti a libovolný 3místný CVC.

Demo aplikace

Demo aplikace založená na Dockeru (Ktor) je součástí GitHub repozitáře pro testování celého platebního toku.

Podpora

Potřebujete pomoc? Obraťte se na náš tým podpory na support@costplus.io.

On this page