Cost+Docs

Java / Kotlin

SDK oficial Kotlin/Java pentru gateway-ul de plăți Cost+

SDK oficial Kotlin pentru gateway-ul de plăți Cost+, complet interoperabil cu Java. Simplifică fluxul de redirecționare HPP (pagina de plată găzduită), semnarea HMAC a payload-ului și verificarea webhook-urilor.

Funcționalități

  • Kotlin-first, compatibil Java — data classes, coroutines, null safety; complet utilizabil din Java
  • kotlinx.serialization — fără dependență Gson/Jackson; mapare automată snake_case/camelCase
  • Generare semnătură HMAC-SHA256 și verificare cu timp constant
  • Parsare webhook + verificare comenzi bazată pe API
  • Funcții suspend pentru IO non-blocant prin Kotlin coroutines
  • HttpClient injectabil pentru testare ușoară cu transport-uri mock
  • Țintește Java 17+

Cerințe

Instalare

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>

Pornire rapidă (Kotlin)

1. Inițializați clientul

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

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

2. Creați o plată și redirecționați către 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. Gestionați webhook-ul

// 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
}

Pornire rapidă (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);
    }
}

Referință API

NoPaynClient(config, httpClient?)

ParametruTipObligatoriuImplicit
config.apiKeyStringDa
config.merchantIdStringDa
config.baseUrlStringNuhttps://api.nopayn.co.uk
httpClientjava.net.http.HttpClientNuClient implicit

client.createOrder(params): Order (suspend)

Creează o comandă prin POST /v1/orders/.

ParametruTipObligatoriuDescriere
amountIntDaSuma în cea mai mică unitate monetară (cenți)
currencyStringDaCod ISO 4217 (EUR, GBP, USD, NOK, SEK)
merchantOrderIdString?NuReferința dvs. internă de comandă
descriptionString?NuDescrierea comenzii
returnUrlString?NuRedirecționare după plata reușită
failureUrlString?NuRedirecționare la anulare/expirare/eroare
webhookUrlString?NuNotificări asincrone de schimbare status
localeString?NuLimba HPP (en-GB, de-DE, nl-NL, etc.)
paymentMethodsList<String>?NuFiltrare metode HPP
expirationPeriodString?NuDurată ISO 8601 (PT30M)

Metode de plată disponibile: credit-card, apple-pay, google-pay, vipps-mobilepay

client.getOrder(orderId): Order (suspend)

Preia detaliile comenzii prin GET /v1/orders/{id}/.

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

Emite o rambursare totală sau parțială prin POST /v1/orders/{id}/refunds/.

client.generatePaymentUrl(params): PaymentUrlResult (suspend)

Metodă de convenință care creează o comandă și returnează:

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

Generează o semnătură hex HMAC-SHA256. Mesajul canonic este $amount:$currency:$orderId, semnat cu cheia API.

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

Verificare cu timp constant a unei semnături HMAC-SHA256.

client.verifyWebhook(rawBody): VerifiedWebhook (suspend)

Parsează corpul webhook-ului, apoi apelează GET /v1/orders/{id}/ pentru a verifica statusul real.

Utilitare HMAC independente

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)

Din Java:

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

Gestionarea erorilor

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
}

Statusuri comandă

StatusFinal?Descriere
newNuComandă creată
processingNuPlată în curs
completedDaPlată reușită — livrați marfa
cancelledDaPlată anulată de client
expiredDaLinkul de plată a expirat
errorDaEroare tehnică

Bune practici pentru webhook-uri

  1. Verificați întotdeauna prin API — payload-ul webhook conține doar ID-ul comenzii, niciodată statusul. Metoda verifyWebhook() a SDK-ului face acest lucru automat.
  2. Returnați HTTP 200 pentru a confirma recepția. Orice alt cod declanșează până la 10 reîncercări (la 2 minute distanță).
  3. Implementați un poller de rezervă — pentru comenzile mai vechi de 10 minute care nu au ajuns la un status final, interogați getOrder() ca rețea de siguranță.
  4. Fiți idempotent — puteți primi același webhook de mai multe ori.

Carduri de test

Folosiți aceste carduri în modul de test Cost+ (site web sandbox):

CardNumărNote
Visa (succes)4111 1111 1111 1111Orice CVV
Mastercard (succes)5544 3300 0003 7Orice CVV
Visa (refuzat)4111 1111 1111 1105Do Not Honor
Visa (fonduri insuficiente)4111 1111 1111 1151Insufficient Funds

Folosiți orice dată de expirare viitoare și orice CVC de 3 cifre.

Aplicație demo

O aplicație demo bazată pe Docker (Ktor) este inclusă în depozitul GitHub pentru testarea fluxului complet de plată.

Suport

Aveți nevoie de ajutor? Contactați echipa noastră de suport la support@costplus.io.

On this page