Stripe SDK for Java covering Payment Intents (one-time payments) and Subscriptions (recurring billing). Framework-agnostic patterns that work with any Java application.
Payment processing with Stripe: one-time payments and subscriptions.
<dependency>
<groupId>com.stripe</groupId>
<artifactId>stripe-java</artifactId>
<version>24.0.0</version>
</dependency>
// Set API key at application startup
Stripe.apiKey = System.getenv("STRIPE_SECRET_KEY");
// Optional: Set API version
Stripe.setApiVersion("2023-10-16");
STRIPE_SECRET_KEY=sk_test_...
STRIPE_PUBLISHABLE_KEY=pk_test_...
STRIPE_WEBHOOK_SECRET=whsec_...
Customer
|-- PaymentMethod (card, bank account)
|-- Subscription
| |-- SubscriptionItem
| | |-- Price -> Product
|-- Invoice
|-- PaymentIntent (one-time payment)
public class StripeCustomerService {
public Customer createCustomer(String email, String name) throws StripeException {
CustomerCreateParams params = CustomerCreateParams.builder()
.setEmail(email)
.setName(name)
.putMetadata("app_user_id", "internal-id-123")
.build();
return Customer.create(params);
}
public Customer getCustomer(String customerId) throws StripeException {
return Customer.retrieve(customerId);
}
public Customer updateCustomer(String customerId, String newEmail) throws StripeException {
Customer customer = Customer.retrieve(customerId);
CustomerUpdateParams params = CustomerUpdateParams.builder()
.setEmail(newEmail)
.build();
return customer.update(params);
}
public Customer deleteCustomer(String customerId) throws StripeException {
Customer customer = Customer.retrieve(customerId);
return customer.delete();
}
}
public class StripeProductService {
// Create a product (e.g., "Pro Plan")
public Product createProduct(String name, String description) throws StripeException {
ProductCreateParams params = ProductCreateParams.builder()
.setName(name)
.setDescription(description)
.build();
return Product.create(params);
}
// Create a recurring price (subscription)
public Price createRecurringPrice(
String productId,
long amountCents,
String currency,
String interval) throws StripeException {
PriceCreateParams params = PriceCreateParams.builder()
.setProduct(productId)
.setUnitAmount(amountCents) // e.g., 1999 = $19.99
.setCurrency(currency) // e.g., "usd", "brl"
.setRecurring(
PriceCreateParams.Recurring.builder()
.setInterval(PriceCreateParams.Recurring.Interval.valueOf(interval.toUpperCase()))
.build()
)
.build();
return Price.create(params);
}
// Create a one-time price
public Price createOneTimePrice(
String productId,
long amountCents,
String currency) throws StripeException {
PriceCreateParams params = PriceCreateParams.builder()
.setProduct(productId)
.setUnitAmount(amountCents)
.setCurrency(currency)
.build();
return Price.create(params);
}
}
public class StripePaymentService {
/**
* Create a PaymentIntent for one-time payment.
* Returns client_secret for frontend to confirm payment.
*/
public PaymentIntent createPaymentIntent(
String customerId,
long amountCents,
String currency,
String description) throws StripeException {
PaymentIntentCreateParams params = PaymentIntentCreateParams.builder()
.setCustomer(customerId)
.setAmount(amountCents)
.setCurrency(currency)
.setDescription(description)
.setAutomaticPaymentMethods(
PaymentIntentCreateParams.AutomaticPaymentMethods.builder()
.setEnabled(true)
.build()
)
.putMetadata("order_id", "order-123")
.build();
return PaymentIntent.create(params);
}
/**
* Retrieve PaymentIntent to check status.
*/
public PaymentIntent getPaymentIntent(String paymentIntentId) throws StripeException {
return PaymentIntent.retrieve(paymentIntentId);
}
/**
* Cancel a PaymentIntent.
*/
public PaymentIntent cancelPaymentIntent(String paymentIntentId) throws StripeException {
PaymentIntent intent = PaymentIntent.retrieve(paymentIntentId);
return intent.cancel();
}
}
requires_payment_method -> requires_confirmation -> requires_action -> processing -> succeeded
-> canceled
-> requires_payment_method (failed)
public class StripeSubscriptionService {
/**
* Create a subscription for a customer.
*/
public Subscription createSubscription(
String customerId,
String priceId) throws StripeException {
SubscriptionCreateParams params = SubscriptionCreateParams.builder()
.setCustomer(customerId)
.addItem(
SubscriptionCreateParams.Item.builder()
.setPrice(priceId)
.build()
)
.setPaymentBehavior(SubscriptionCreateParams.PaymentBehavior.DEFAULT_INCOMPLETE)
.addExpand("latest_invoice.payment_intent")
.build();
return Subscription.create(params);
}
/**
* Create subscription with trial period.
*/
public Subscription createSubscriptionWithTrial(
String customerId,
String priceId,
int trialDays) throws StripeException {
SubscriptionCreateParams params = SubscriptionCreateParams.builder()
.setCustomer(customerId)
.addItem(
SubscriptionCreateParams.Item.builder()
.setPrice(priceId)
.build()
)
.setTrialPeriodDays((long) trialDays)
.build();
return Subscription.create(params);
}
/**
* Get subscription details.
*/
public Subscription getSubscription(String subscriptionId) throws StripeException {
return Subscription.retrieve(subscriptionId);
}
/**
* Cancel subscription at period end (user keeps access until end of billing period).
*/
public Subscription cancelAtPeriodEnd(String subscriptionId) throws StripeException {
Subscription subscription = Subscription.retrieve(subscriptionId);
SubscriptionUpdateParams params = SubscriptionUpdateParams.builder()
.setCancelAtPeriodEnd(true)
.build();
return subscription.update(params);
}
/**
* Cancel subscription immediately.
*/
public Subscription cancelImmediately(String subscriptionId) throws StripeException {
Subscription subscription = Subscription.retrieve(subscriptionId);
return subscription.cancel();
}
/**
* Change subscription plan (upgrade/downgrade).
*/
public Subscription changePlan(
String subscriptionId,
String newPriceId) throws StripeException {
Subscription subscription = Subscription.retrieve(subscriptionId);
String itemId = subscription.getItems().getData().get(0).getId();
SubscriptionUpdateParams params = SubscriptionUpdateParams.builder()
.addItem(
SubscriptionUpdateParams.Item.builder()
.setId(itemId)
.setPrice(newPriceId)
.build()
)
.setProrationBehavior(SubscriptionUpdateParams.ProrationBehavior.CREATE_PRORATIONS)
.build();
return subscription.update(params);
}
/**
* Resume a canceled subscription (if still in period).
*/
public Subscription resumeSubscription(String subscriptionId) throws StripeException {
Subscription subscription = Subscription.retrieve(subscriptionId);
SubscriptionUpdateParams params = SubscriptionUpdateParams.builder()
.setCancelAtPeriodEnd(false)
.build();
return subscription.update(params);
}
}
| Status | Description |
|---|---|
incomplete | Payment failed on creation |
incomplete_expired | First payment never completed |
trialing | In trial period |
active | Paid and active |
past_due | Payment failed, retrying |
canceled | Canceled |
unpaid | All retries failed |
public class StripePaymentMethodService {
/**
* Attach a payment method to a customer.
*/
public PaymentMethod attachToCustomer(
String paymentMethodId,
String customerId) throws StripeException {
PaymentMethod paymentMethod = PaymentMethod.retrieve(paymentMethodId);
PaymentMethodAttachParams params = PaymentMethodAttachParams.builder()
.setCustomer(customerId)
.build();
return paymentMethod.attach(params);
}
/**
* Set as default payment method for invoices.
*/
public Customer setDefaultPaymentMethod(
String customerId,
String paymentMethodId) throws StripeException {
Customer customer = Customer.retrieve(customerId);
CustomerUpdateParams params = CustomerUpdateParams.builder()
.setInvoiceSettings(
CustomerUpdateParams.InvoiceSettings.builder()
.setDefaultPaymentMethod(paymentMethodId)
.build()
)
.build();
return customer.update(params);
}
/**
* List customer's payment methods.
*/
public List<PaymentMethod> listPaymentMethods(String customerId) throws StripeException {
PaymentMethodListParams params = PaymentMethodListParams.builder()
.setCustomer(customerId)
.setType(PaymentMethodListParams.Type.CARD)
.build();
return PaymentMethod.list(params).getData();
}
/**
* Detach payment method from customer.
*/
public PaymentMethod detach(String paymentMethodId) throws StripeException {
PaymentMethod paymentMethod = PaymentMethod.retrieve(paymentMethodId);
return paymentMethod.detach();
}
}
public class StripeErrorHandler {
public void handleStripeOperation(Runnable operation) {
try {
operation.run();
} catch (CardException e) {
// Card was declined
String code = e.getCode(); // e.g., "card_declined", "insufficient_funds"
String message = e.getMessage();
log.error("Card error [{}]: {}", code, message);
throw new PaymentDeclinedException(message, code);
} catch (RateLimitException e) {
// Too many requests
log.warn("Stripe rate limit hit, retrying...");
throw new PaymentServiceUnavailableException("Please try again");
} catch (InvalidRequestException e) {
// Invalid parameters
log.error("Invalid Stripe request: {}", e.getMessage());
throw new PaymentConfigurationException(e.getMessage());
} catch (AuthenticationException e) {
// API key problems
log.error("Stripe authentication failed");
throw new PaymentConfigurationException("Payment service configuration error");
} catch (ApiConnectionException e) {
// Network problems
log.error("Could not connect to Stripe: {}", e.getMessage());
throw new PaymentServiceUnavailableException("Payment service unavailable");
} catch (StripeException e) {
// Generic Stripe error
log.error("Stripe error: {}", e.getMessage());
throw new PaymentException("Payment processing failed");
}
}
}
Use test API keys (sk_test_...) and test card numbers:
| Card Number | Scenario |
|---|---|
| 4242424242424242 | Successful payment |
| 4000000000000002 | Card declined |
| 4000000000009995 | Insufficient funds |
| 4000002500003155 | Requires 3D Secure |
// Create test clock for time manipulation
TestClockCreateParams clockParams = TestClockCreateParams.builder()
.setFrozenTime(Instant.now().getEpochSecond())
.build();
TestClock testClock = TestClock.create(clockParams);
// Create customer attached to test clock
CustomerCreateParams customerParams = CustomerCreateParams.builder()
.setEmail("[email protected]")
.setTestClock(testClock.getId())
.build();
// Advance time to test billing cycles
TestClockAdvanceParams advanceParams = TestClockAdvanceParams.builder()
.setFrozenTime(Instant.now().plus(32, ChronoUnit.DAYS).getEpochSecond())
.build();
testClock.advance(advanceParams);
references/stripe-objects.md for object referenceexamples/ for complete code examples