SDKs

Java

Read identification events with a secret key and verify signed webhooks from Java 11 and newer, and from Kotlin and Scala on the JVM.

The Java library reads stored events by request ID and verifies webhook signatures. It uses the JDK's java.net.http client, and the client is thread-safe: build one and share it.

Requirements

Install

implementation("io.fingerly:fingerly-server:0.1.0")

Read an event

Create one client with your secret key and reuse it. The key decides the regional API and the environment the client reads.

Java
import io.fingerly.server.FingerlyClient;

FingerlyClient fingerly = FingerlyClient.builder()
    .secretKey(System.getenv("FINGERLY_SECRET_KEY"))
    .build();

Event event = fingerly.events().get("01a0a84b-e6a2-7c09-9f51-0b3d7a26c8e4");

An event has the fields listed in Get an event. suspect_score is null when the request was not scored.

Verify a checkout

Read the event your client identified, check it belongs to this action and is recent, then decide on its level. See server-side verification.

Java
public String decide(String orderId, String requestId) {
    Event event;
    try {
        event = fingerly.events().get(requestId);
    } catch (FingerlyApiException e) {
        if (e.getStatus() == 404) return "refuse";
        throw e;
    }

    if (!("checkout:" + orderId).equals(event.getTag())) return "refuse";
    if (event.getOccurredAt().isBefore(Instant.now().minus(Duration.ofMinutes(2)))) return "refuse";

    return switch (String.valueOf(event.getSuspectLevel())) {
        case "high" -> "review";
        case "medium" -> "challenge";
        default -> "allow";
    };
}

Verify a webhook

Check the signature over the raw request body before parsing it. The helper rejects timestamps more than five minutes from now.

Java
@PostMapping("/webhooks/fingerly")
public ResponseEntity<Void> receive(
        @RequestBody byte[] body,
        @RequestHeader("x-fingerly-timestamp") String timestamp,
        @RequestHeader("x-fingerly-signature") String signature) {

    if (!Webhooks.verify(webhookSecret, body, timestamp, signature)) {
        return ResponseEntity.badRequest().build();
    }

    WebhookEvent event = Webhooks.parse(body);
    events.enqueue(event.getId(), body);   // deduplicate on the event ID
    return ResponseEntity.noContent().build();
}

API

MemberReturnsNotes
FingerlyClient.builder().secretKey(key).build()FingerlyClientAlso .endpoint(url) and .httpClient(client).
events().get(requestId)EventThrows FingerlyApiException with getStatus() for a non-2xx response.
events().list(EventListParams)EventPageEventListParams.builder() takes from, to (Instant), page, limit, visitor, level.
Webhooks.verify(secret, body, timestamp, signature)booleanFive minutes of tolerance.