Cost+Docs

Java / Kotlin

Officiellt Kotlin/Java SDK för Cost+ betalningsgateway

Officiellt Kotlin SDK för Cost+ betalningsgateway, fullt interoperabelt med Java. Förenklar HPP-omdirigeringsflödet (Hosted Payment Page), HMAC payload-signering och webhook-verifiering.

Funktioner

  • Kotlin-först, Java-vänligt — data classes, coroutines, null safety; fullt användbart från Java
  • kotlinx.serialization — inget Gson/Jackson-beroende; automatisk snake_case/camelCase-mappning
  • HMAC-SHA256 signaturgenerering och verifiering med konstant tid
  • Webhook-tolkning + API-baserad orderverifiering
  • Suspend-funktioner för icke-blockerande IO via Kotlin coroutines
  • Injicerbar HttpClient för enkel testning med mock-transporter
  • Riktar sig mot Java 17+

Krav

Installation

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>

Snabbstart (Kotlin)

1. Initiera klienten

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

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

2. Skapa en betalning och omdirigera till 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. Hantera webhooken

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

Snabbstart (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-referens

NoPaynClient(config, httpClient?)

ParameterTypObligatoriskStandard
config.apiKeyStringJa
config.merchantIdStringJa
config.baseUrlStringNejhttps://api.nopayn.co.uk
httpClientjava.net.http.HttpClientNejStandardklient

client.createOrder(params): Order (suspend)

Skapar en order via POST /v1/orders/.

ParameterTypObligatoriskBeskrivning
amountIntJaBelopp i minsta valutaenhet (cent)
currencyStringJaISO 4217-kod (EUR, GBP, USD, NOK, SEK)
merchantOrderIdString?NejDin interna orderreferens
descriptionString?NejOrderbeskrivning
returnUrlString?NejOmdirigering efter lyckad betalning
failureUrlString?NejOmdirigering vid avbrytning/utgång/fel
webhookUrlString?NejAsynkrona statusändringsnotifieringar
localeString?NejHPP-språk (en-GB, de-DE, nl-NL, etc.)
paymentMethodsList<String>?NejFiltrera HPP-metoder
expirationPeriodString?NejISO 8601-duration (PT30M)

Tillgängliga betalningsmetoder: credit-card, apple-pay, google-pay, vipps-mobilepay

client.getOrder(orderId): Order (suspend)

Hämtar orderdetaljer via GET /v1/orders/{id}/.

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

Utfärdar en fullständig eller partiell återbetalning via POST /v1/orders/{id}/refunds/.

client.generatePaymentUrl(params): PaymentUrlResult (suspend)

Bekvämlighetsmetod som skapar en order och returnerar:

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

Genererar en HMAC-SHA256 hex-signatur. Det kanoniska meddelandet är $amount:$currency:$orderId, signerat med API-nyckeln.

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

Verifiering med konstant tid av en HMAC-SHA256-signatur.

client.verifyWebhook(rawBody): VerifiedWebhook (suspend)

Tolkar webhook-kroppen och anropar sedan GET /v1/orders/{id}/ för att verifiera faktisk status.

Fristående HMAC-verktyg

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)

Från Java:

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

Felhantering

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
}

Orderstatusar

StatusSlutgiltig?Beskrivning
newNejOrder skapad
processingNejBetalning pågår
completedJaBetalning lyckades — leverera varorna
cancelledJaBetalning avbruten av kunden
expiredJaBetalningslänken löpte ut
errorJaTekniskt fel

Bästa praxis för webhooks

  1. Verifiera alltid via API:et — webhook-payloaden innehåller bara order-ID:t, aldrig statusen. SDK:ts verifyWebhook() gör detta automatiskt.
  2. Returnera HTTP 200 för att bekräfta mottagandet. Annan kod utlöser upp till 10 omförsök (2 minuter emellan).
  3. Implementera en reservpoller — för ordrar äldre än 10 minuter som inte har nått slutgiltig status, polla getOrder() som säkerhetsnät.
  4. Var idempotent — du kan ta emot samma webhook flera gånger.

Testkort

Använd dessa kort i Cost+ testläge (sandbox-webbplats):

KortNummerNoteringar
Visa (lyckad)4111 1111 1111 1111Valfritt CVV
Mastercard (lyckad)5544 3300 0003 7Valfritt CVV
Visa (nekad)4111 1111 1111 1105Do Not Honor
Visa (otillräckligt saldo)4111 1111 1111 1151Insufficient Funds

Använd valfritt framtida utgångsdatum och valfri 3-siffrig CVC.

Demoapplikation

En Docker-baserad demoapplikation (Ktor) ingår i GitHub-repositoryt för att testa det fullständiga betalningsflödet.

Support

Behöver du hjälp? Kontakta vårt supportteam på support@costplus.io.

On this page