Cost+Docs

Java / Kotlin

SDK officiel Kotlin/Java pour la passerelle de paiement Cost+

SDK officiel Kotlin pour la passerelle de paiement Cost+, entièrement interopérable avec Java. Simplifie le flux de redirection HPP (page de paiement hébergée), la signature de payload HMAC et la vérification des webhooks.

Fonctionnalités

  • Kotlin-first, compatible Java — data classes, coroutines, null safety ; entièrement utilisable depuis Java
  • kotlinx.serialization — aucune dépendance Gson/Jackson ; mappage automatique snake_case/camelCase
  • Génération de signature HMAC-SHA256 et vérification en temps constant
  • Analyse des webhooks + vérification des commandes via l'API
  • Fonctions suspend pour les I/O non bloquantes via les coroutines Kotlin
  • HttpClient injectable pour faciliter les tests avec des transports simulés
  • Cible Java 17+

Prérequis

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>

Démarrage rapide (Kotlin)

1. Initialiser le client

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

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

2. Créer un paiement et rediriger vers la 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. Gérer le webhook

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

Démarrage rapide (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);
    }
}

Référence API

NoPaynClient(config, httpClient?)

ParamètreTypeObligatoirePar défaut
config.apiKeyStringOui
config.merchantIdStringOui
config.baseUrlStringNonhttps://api.nopayn.co.uk
httpClientjava.net.http.HttpClientNonClient par défaut

client.createOrder(params): Order (suspend)

Crée une commande via POST /v1/orders/.

ParamètreTypeObligatoireDescription
amountIntOuiMontant dans la plus petite unité monétaire (centimes)
currencyStringOuiCode ISO 4217 (EUR, GBP, USD, NOK, SEK)
merchantOrderIdString?NonVotre référence interne de commande
descriptionString?NonDescription de la commande
returnUrlString?NonRedirection après paiement réussi
failureUrlString?NonRedirection en cas d'annulation/expiration/erreur
webhookUrlString?NonNotifications asynchrones de changement de statut
localeString?NonLangue de la HPP (en-GB, de-DE, nl-NL, etc.)
paymentMethodsList<String>?NonFiltrer les méthodes HPP
expirationPeriodString?NonDurée ISO 8601 (PT30M)

Méthodes de paiement disponibles : credit-card, apple-pay, google-pay, vipps-mobilepay

client.getOrder(orderId): Order (suspend)

Récupère les détails de la commande via GET /v1/orders/{id}/.

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

Effectue un remboursement total ou partiel via POST /v1/orders/{id}/refunds/.

client.generatePaymentUrl(params): PaymentUrlResult (suspend)

Méthode utilitaire qui crée une commande et renvoie :

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

Génère une signature HMAC-SHA256 hexadécimale. Le message canonique est $amount:$currency:$orderId, signé avec la clé API.

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

Vérification en temps constant d'une signature HMAC-SHA256.

client.verifyWebhook(rawBody): VerifiedWebhook (suspend)

Analyse le corps du webhook, puis appelle GET /v1/orders/{id}/ pour vérifier le statut réel.

Utilitaires HMAC autonomes

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)

Depuis Java :

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

Gestion des erreurs

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
}

Statuts des commandes

StatutFinal ?Description
newNonCommande créée
processingNonPaiement en cours
completedOuiPaiement réussi — livrez les marchandises
cancelledOuiPaiement annulé par le client
expiredOuiLe lien de paiement a expiré
errorOuiErreur technique

Bonnes pratiques pour les webhooks

  1. Vérifiez toujours via l'API — le payload du webhook contient uniquement l'identifiant de la commande, jamais le statut. Le verifyWebhook() du SDK le fait automatiquement.
  2. Renvoyez HTTP 200 pour accuser réception. Tout autre code déclenche jusqu'à 10 tentatives (espacées de 2 minutes).
  3. Implémentez un polling de secours — pour les commandes de plus de 10 minutes qui n'ont pas atteint un statut final, interrogez getOrder() comme filet de sécurité.
  4. Soyez idempotent — vous pouvez recevoir le même webhook plusieurs fois.

Cartes de test

Utilisez ces cartes en mode test Cost+ (site web sandbox) :

CarteNuméroNotes
Visa (succès)4111 1111 1111 1111N'importe quel CVV
Mastercard (succès)5544 3300 0003 7N'importe quel CVV
Visa (refusée)4111 1111 1111 1105Do Not Honor
Visa (fonds insuffisants)4111 1111 1111 1151Insufficient Funds

Utilisez n'importe quelle date d'expiration future et n'importe quel CVC à 3 chiffres.

Application de démonstration

Une application de démonstration basée sur Docker (Ktor) est incluse dans le dépôt GitHub pour tester le flux de paiement complet.

Support

Besoin d'aide ? Contactez notre équipe de support à support@costplus.io.

On this page