Cost+Docs

Java / Kotlin

Officiele Kotlin/Java SDK voor de Cost+ betaalgateway

Officiele Kotlin SDK voor de Cost+ betaalgateway, volledig interoperabel met Java. Vereenvoudigt de HPP (Hosted Payment Page) doorverwijzingsflow, HMAC-payloadondertekening en webhookverificatie.

Kenmerken

  • Kotlin-first, Java-vriendelijk — data classes, coroutines, null safety; volledig bruikbaar vanuit Java
  • kotlinx.serialization — geen Gson/Jackson-afhankelijkheid; automatische snake_case/camelCase-mapping
  • HMAC-SHA256-handtekeninggeneratie en constant-time verificatie
  • Webhook-parsing + API-gebaseerde bestellingsverificatie
  • Suspend-functies voor niet-blokkerende IO via Kotlin-coroutines
  • Injecteerbare HttpClient voor eenvoudig testen met mock-transports
  • Vereist Java 17+

Vereisten

Installatie

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>

Snelstart (Kotlin)

1. De client initialiseren

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

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

2. Een betaling aanmaken en doorverwijzen naar de 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. De webhook afhandelen

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

Snelstart (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-referentie

NoPaynClient(config, httpClient?)

ParameterTypeVereistStandaard
config.apiKeyStringJa
config.merchantIdStringJa
config.baseUrlStringNeehttps://api.nopayn.co.uk
httpClientjava.net.http.HttpClientNeeStandaard client

client.createOrder(params): Order (suspend)

Maakt een bestelling aan via POST /v1/orders/.

ParameterTypeVereistBeschrijving
amountIntJaBedrag in kleinste valuta-eenheid (centen)
currencyStringJaISO 4217-code (EUR, GBP, USD, NOK, SEK)
merchantOrderIdString?NeeUw interne bestellingsreferentie
descriptionString?NeeBestellingsbeschrijving
returnUrlString?NeeDoorverwijzing na geslaagde betaling
failureUrlString?NeeDoorverwijzing bij annulering/verloop/fout
webhookUrlString?NeeAsynchrone statuswijzigingsmeldingen
localeString?NeeHPP-taal (en-GB, de-DE, nl-NL, enz.)
paymentMethodsList<String>?NeeHPP-methoden filteren
expirationPeriodString?NeeISO 8601-duur (PT30M)

Beschikbare betaalmethoden: credit-card, apple-pay, google-pay, vipps-mobilepay

client.getOrder(orderId): Order (suspend)

Haalt bestellingsdetails op via GET /v1/orders/{id}/.

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

Voert een volledige of gedeeltelijke terugbetaling uit via POST /v1/orders/{id}/refunds/.

client.generatePaymentUrl(params): PaymentUrlResult (suspend)

Hulpmethode die een bestelling aanmaakt en retourneert:

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

Genereert een HMAC-SHA256 hex-handtekening. Het canonieke bericht is $amount:$currency:$orderId, ondertekend met de API-sleutel.

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

Constant-time verificatie van een HMAC-SHA256-handtekening.

client.verifyWebhook(rawBody): VerifiedWebhook (suspend)

Parst de webhook-body en roept vervolgens GET /v1/orders/{id}/ aan om de werkelijke status te verifieren.

Standalone HMAC-hulpmiddelen

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)

Vanuit Java:

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

Foutafhandeling

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
}

Bestellingsstatussen

StatusDefinitief?Beschrijving
newNeeBestelling aangemaakt
processingNeeBetaling wordt verwerkt
completedJaBetaling geslaagd — lever de goederen
cancelledJaBetaling geannuleerd door klant
expiredJaBetaallink verlopen
errorJaTechnische storing

Best practices voor webhooks

  1. Verifieer altijd via de API — de webhook-payload bevat alleen het bestelling-ID, nooit de status. De verifyWebhook() van de SDK doet dit automatisch.
  2. Retourneer HTTP 200 om de ontvangst te bevestigen. Elke andere code triggert tot 10 herhaalpogingen (2 minuten tussenpozen).
  3. Implementeer een backup-poller — voor bestellingen ouder dan 10 minuten die nog geen definitieve status hebben bereikt, poll getOrder() als vangnet.
  4. Wees idempotent — u kunt dezelfde webhook meerdere keren ontvangen.

Testkaarten

Gebruik deze kaarten in Cost+ testmodus (sandbox-website):

KaartNummerOpmerkingen
Visa (geslaagd)4111 1111 1111 1111Willekeurige CVV
Mastercard (geslaagd)5544 3300 0003 7Willekeurige CVV
Visa (geweigerd)4111 1111 1111 1105Do Not Honor
Visa (onvoldoende saldo)4111 1111 1111 1151Insufficient Funds

Gebruik een willekeurige toekomstige vervaldatum en een willekeurige 3-cijferige CVC.

Demo-app

Een op Docker gebaseerde demo-app (Ktor) is opgenomen in de GitHub-repository om de volledige betalingsflow te testen.

Ondersteuning

Hulp nodig? Neem contact op met ons supportteam via support@costplus.io.

On this page