SDKsJavaHTTP Frameworks

HTTP Framework Integrations

The Java SDK provides payment filters for 6 HTTP frameworks: Jakarta Servlet, Spring MVC, Spring WebFlux, Micronaut, Quarkus (JAX-RS), and generic JAX-RS. Each filter implements the full T402 v2 payment lifecycle with V2-first header detection and V1 fallback.

Framework Overview

FrameworkPackageFilter ClassType
Jakarta Servletio.t402.serverPaymentFilterSynchronous
Spring MVCio.t402.springPaymentInterceptorSynchronous
Spring WebFluxio.t402.spring.reactivePaymentWebFilterReactive
Micronautio.t402.micronautPaymentFilterReactive
Quarkus (JAX-RS)io.t402.quarkusPaymentFilterSynchronous (JAX-RS)

Jakarta Servlet

The base PaymentFilter works with any Jakarta Servlet 6.0+ container (Tomcat, Jetty, Undertow).

import io.t402.server.PaymentFilter;
import io.t402.client.HttpFacilitatorClient;
 
FacilitatorClient facilitator = new HttpFacilitatorClient(
    "https://facilitator.t402.io"
);
 
PaymentFilter filter = new PaymentFilter(facilitator);
 
// Register with your servlet container
FilterRegistration.Dynamic registration = servletContext.addFilter("t402", filter);
registration.addMappingForUrlPatterns(
    EnumSet.of(DispatcherType.REQUEST),
    true,
    "/api/*"
);

Spring MVC

Spring Boot auto-configuration registers the payment filter automatically.

t402:
  enabled: true
  facilitator-url: https://facilitator.t402.io
  network: eip155:8453
  pay-to: "0xYourReceiverAddress"
  asset: "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913"
  token-name: "USD Coin"
  token-version: "2"

Use @RequirePayment for fine-grained control:

import io.t402.spring.RequirePayment;
 
@RestController
public class ApiController {
 
    @RequirePayment(amount = "$0.01", description = "Premium API")
    @GetMapping("/api/premium")
    public Map<String, String> premiumContent() {
        return Map.of("data", "Premium content!");
    }
}

See the Spring Boot page for full details.

Spring WebFlux

For reactive applications using Spring WebFlux:

import io.t402.spring.reactive.PaymentWebFilter;
 
@Configuration
@EnableWebFlux
public class WebFluxConfig {
 
    @Bean
    public PaymentWebFilter paymentWebFilter(FacilitatorClient facilitator) {
        return new PaymentWebFilter(facilitator, routeConfigs);
    }
}

Or enable via auto-configuration:

t402:
  enabled: true
  webflux: true
  facilitator-url: https://facilitator.t402.io

WebFlux uses route-based configuration only. The @RequirePayment annotation is not supported in reactive applications.

Micronaut

The Micronaut filter implements HttpServerFilter for reactive request handling.

import io.t402.micronaut.PaymentFilter;
import io.t402.client.HttpFacilitatorClient;
import io.micronaut.context.annotation.Factory;
import io.micronaut.context.annotation.Bean;
 
@Factory
public class T402Factory {
 
    @Bean
    public PaymentFilter paymentFilter() {
        Map<String, BigInteger> priceTable = Map.of(
            "/api/premium", BigInteger.valueOf(10000),   // 0.01 USDC
            "/api/report",  BigInteger.valueOf(1000000)  // 1.00 USDC
        );
 
        return new PaymentFilter(
            "0xYourWalletAddress",
            priceTable,
            new HttpFacilitatorClient("https://facilitator.t402.io"),
            "eip155:8453",                                        // network
            "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913"          // asset
        );
    }
}

Micronaut Controller

import io.micronaut.http.annotation.Controller;
import io.micronaut.http.annotation.Get;
 
@Controller("/api")
public class ApiController {
 
    @Get("/premium")
    public Map<String, String> premium() {
        return Map.of("data", "Premium content!");
    }
 
    @Get("/report")
    public Map<String, String> report() {
        return Map.of("report", "Full report data");
    }
}

Micronaut Configuration

Micronaut uses application.yml for configuration:

t402:
  pay-to: "0xYourWalletAddress"
  facilitator-url: "https://facilitator.t402.io"
  network: "eip155:8453"
  asset: "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913"

Quarkus (JAX-RS)

The Quarkus filter implements ContainerRequestFilter and ContainerResponseFilter for the full payment lifecycle. It works with any JAX-RS runtime (RESTEasy, Jersey, etc.) and is annotated with @Provider for auto-discovery.

import io.t402.quarkus.PaymentFilter;
import io.t402.client.HttpFacilitatorClient;
import jakarta.enterprise.context.ApplicationScoped;
import jakarta.enterprise.inject.Produces;
 
@ApplicationScoped
public class T402Producer {
 
    @Produces
    @ApplicationScoped
    public PaymentFilter paymentFilter() {
        Map<String, BigInteger> priceTable = Map.of(
            "/api/premium", BigInteger.valueOf(10000),   // 0.01 USDC
            "/api/report",  BigInteger.valueOf(1000000)  // 1.00 USDC
        );
 
        return new PaymentFilter(
            "0xYourWalletAddress",
            priceTable,
            new HttpFacilitatorClient("https://facilitator.t402.io"),
            "eip155:8453",
            "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913"
        );
    }
}

Quarkus Resource

import jakarta.ws.rs.GET;
import jakarta.ws.rs.Path;
import jakarta.ws.rs.Produces;
import jakarta.ws.rs.core.MediaType;
 
@Path("/api")
public class ApiResource {
 
    @GET
    @Path("/premium")
    @Produces(MediaType.APPLICATION_JSON)
    public Map<String, String> premium() {
        return Map.of("data", "Premium content!");
    }
 
    @GET
    @Path("/report")
    @Produces(MediaType.APPLICATION_JSON)
    public Map<String, String> report() {
        return Map.of("report", "Full report data");
    }
}

Quarkus Configuration

Configure via application.properties:

t402.pay-to=0xYourWalletAddress
t402.facilitator-url=https://facilitator.t402.io
t402.network=eip155:8453
t402.asset=0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913

The Quarkus filter uses the @Provider annotation, so it is auto-discovered when the JAR is on the classpath. No manual registration is needed.

Common Configuration

All filters (Micronaut, Quarkus) share the same constructor pattern:

// Basic constructor (uses default network and asset)
new PaymentFilter(payTo, priceTable, facilitator);
 
// With custom network and asset
new PaymentFilter(payTo, priceTable, facilitator, network, asset);
ParameterTypeDescription
payToStringYour wallet address for receiving payments
priceTableMap<String, BigInteger>Maps request paths to payment amounts (atomic units)
facilitatorFacilitatorClientClient for payment verification and settlement
networkStringBlockchain network in CAIP-2 format (default: eip155:84532)
assetStringToken contract address

V2 Header Detection

All filters detect payment headers using V2-first ordering:

  1. Check Payment-Signature header (V2)
  2. Fall back to X-Payment header (V1)
  3. Response headers use the matching version (Payment-Response or X-Payment-Response)