Cost+Docs

Java / Kotlin

SDK oficial Kotlin/Java para o gateway de pagamento Cost+

SDK oficial Kotlin para o gateway de pagamento Cost+, totalmente interoperável com Java. Simplifica o fluxo de redirecionamento HPP (Página de Pagamento Alojada), assinatura de payloads HMAC e verificação de webhooks.

Funcionalidades

  • Kotlin-first, compatível com Java — data classes, coroutines, null safety; totalmente utilizável a partir de Java
  • kotlinx.serialization — sem dependência Gson/Jackson; mapeamento automático snake_case/camelCase
  • Geração de assinaturas HMAC-SHA256 e verificação em tempo constante
  • Análise de webhooks + verificação de encomendas baseada na API
  • Funções suspend para IO não bloqueante via Kotlin coroutines
  • HttpClient injetável para facilitar testes com transportes mock
  • Alvo Java 17+

Requisitos

Instalação

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>

Início Rápido (Kotlin)

1. Inicializar o Cliente

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

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

2. Criar um Pagamento e Redirecionar para o 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. Tratar o 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
}

Início Rápido (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);
    }
}

Referência da API

NoPaynClient(config, httpClient?)

ParâmetroTipoObrigatórioPredefinição
config.apiKeyStringSim
config.merchantIdStringSim
config.baseUrlStringNãohttps://api.nopayn.co.uk
httpClientjava.net.http.HttpClientNãoCliente predefinido

client.createOrder(params): Order (suspend)

Cria uma encomenda via POST /v1/orders/.

ParâmetroTipoObrigatórioDescrição
amountIntSimMontante na menor unidade monetária (cêntimos)
currencyStringSimCódigo ISO 4217 (EUR, GBP, USD, NOK, SEK)
merchantOrderIdString?NãoA sua referência interna da encomenda
descriptionString?NãoDescrição da encomenda
returnUrlString?NãoRedirecionamento após pagamento bem-sucedido
failureUrlString?NãoRedirecionamento em cancelamento/expiração/erro
webhookUrlString?NãoNotificações assíncronas de alteração de estado
localeString?NãoIdioma do HPP (en-GB, de-DE, nl-NL, etc.)
paymentMethodsList<String>?NãoFiltrar métodos do HPP
expirationPeriodString?NãoDuração ISO 8601 (PT30M)

Métodos de pagamento disponíveis: credit-card, apple-pay, google-pay, vipps-mobilepay

client.getOrder(orderId): Order (suspend)

Obtém detalhes da encomenda via GET /v1/orders/{id}/.

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

Emite um reembolso total ou parcial via POST /v1/orders/{id}/refunds/.

client.generatePaymentUrl(params): PaymentUrlResult (suspend)

Método de conveniência que cria uma encomenda e devolve:

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

Gera uma assinatura HMAC-SHA256 em hexadecimal. A mensagem canónica é $amount:$currency:$orderId, assinada com a chave API.

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

Verificação em tempo constante de uma assinatura HMAC-SHA256.

client.verifyWebhook(rawBody): VerifiedWebhook (suspend)

Analisa o corpo do webhook, depois chama GET /v1/orders/{id}/ para verificar o estado real.

Utilitários HMAC Autónomos

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)

A partir de Java:

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

Tratamento de Erros

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
}

Estados da Encomenda

EstadoFinal?Descrição
newNãoEncomenda criada
processingNãoPagamento em curso
completedSimPagamento bem-sucedido — entregue a mercadoria
cancelledSimPagamento cancelado pelo cliente
expiredSimLink de pagamento expirou
errorSimFalha técnica

Boas Práticas para Webhooks

  1. Verifique sempre através da API — o payload do webhook contém apenas o ID da encomenda, nunca o estado. O verifyWebhook() do SDK faz isto automaticamente.
  2. Devolva HTTP 200 para confirmar a receção. Qualquer outro código desencadeia até 10 tentativas (com 2 minutos de intervalo).
  3. Implemente um poller de backup — para encomendas com mais de 10 minutos que não atingiram um estado final, consulte getOrder() como rede de segurança.
  4. Seja idempotente — pode receber o mesmo webhook várias vezes.

Cartões de Teste

Utilize estes cartões no modo de teste da Cost+ (website sandbox):

CartãoNúmeroNotas
Visa (sucesso)4111 1111 1111 1111Qualquer CVV
Mastercard (sucesso)5544 3300 0003 7Qualquer CVV
Visa (recusado)4111 1111 1111 1105Do Not Honor
Visa (fundos insuficientes)4111 1111 1111 1151Insufficient Funds

Utilize qualquer data de validade futura e qualquer CVC de 3 dígitos.

Aplicação de Demonstração

Uma aplicação de demonstração baseada em Docker (Ktor) está incluída no repositório GitHub para testar o fluxo completo de pagamento.

Suporte

Precisa de ajuda? Contacte a nossa equipa de suporte em support@costplus.io.

On this page