google-site-verification: google61fe8ba583a51912.html
Mollie Payments in Java: Complete Implementation Guide

Introduction to Mollie Payments

Mollie is a popular European payment service provider that offers easy integration for various payment methods. This guide covers building a comprehensive Java client for Mollie's API, supporting payments, refunds, subscriptions, and webhook handling.

Key Features

  • Payment Processing for multiple payment methods
  • Refund Management for processing returns
  • Subscription Handling for recurring payments
  • Webhook Integration for payment status updates
  • Customer Management for storing payment details
  • Order Management for complex payment flows

Dependencies and Setup

Maven Configuration

<properties> <okhttp.version>4.12.0</okhttp.version> <jackson.version>2.15.2</jackson.version> <spring.boot.version>2.7.0</spring.boot.version> </properties> <dependencies> <!-- HTTP Client --> <dependency> <groupId>com.squareup.okhttp3</groupId> <artifactId>okhttp</artifactId> <version>${okhttp.version}</version> </dependency> <!-- JSON Processing --> <dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-core</artifactId> <version>${jackson.version}</version> </dependency> <dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-databind</artifactId> <version>${jackson.version}</version> </dependency> <dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-annotations</artifactId> <version>${jackson.version}</version> </dependency> <!-- Spring Boot (Optional) --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> <version>${spring.boot.version}</version> <optional>true</optional> </dependency> <!-- Logging --> <dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-api</artifactId> <version>2.0.7</version> </dependency> <!-- Testing --> <dependency> <groupId>org.junit.jupiter</groupId> <artifactId>junit-jupiter</artifactId> <version>5.9.3</version> <scope>test</scope> </dependency> </dependencies>

Core Mollie Client Implementation

Main Mollie Client

package com.mollie.client; import com.fasterxml.jackson.core.type.TypeReference; import com.fasterxml.jackson.databind.ObjectMapper; import okhttp3.*; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.io.IOException; import java.util.HashMap; import java.util.Map; import java.util.concurrent.TimeUnit; public class MollieClient { private static final Logger logger = LoggerFactory.getLogger(MollieClient.class); private final String apiKey; private final boolean testMode; private final OkHttpClient httpClient; private final ObjectMapper objectMapper; private final String baseUrl; public MollieClient(String apiKey) { this(apiKey, true); } public MollieClient(String apiKey, boolean testMode) { this.apiKey = apiKey; this.testMode = testMode; this.objectMapper = new ObjectMapper(); this.httpClient = new OkHttpClient.Builder() .connectTimeout(30, TimeUnit.SECONDS) .readTimeout(60, TimeUnit.SECONDS) .writeTimeout(30, TimeUnit.SECONDS) .build(); this.baseUrl = "https://api.mollie.com/v2"; } /** * Execute API request with authentication */ private Response executeRequest(Request request) throws MollieException { try { Response response = httpClient.newCall(request).execute(); if (!response.isSuccessful()) { handleErrorResponse(response); } return response; } catch (IOException e) { throw new MollieException("API request failed", e); } } /** * Handle error responses from Mollie API */ private void handleErrorResponse(Response response) throws IOException, MollieException { String errorBody = response.body().string(); logger.error("Mollie API error: {} - {}", response.code(), errorBody); try { ErrorResponse errorResponse = objectMapper.readValue(errorBody, ErrorResponse.class); throw new MollieException( errorResponse.getDetail() != null ? errorResponse.getDetail() : errorResponse.getTitle(), response.code() ); } catch (Exception e) { throw new MollieException("HTTP " + response.code() + ": " + errorBody, response.code()); } } /** * Create authenticated request builder */ private Request.Builder createAuthenticatedRequest() { return new Request.Builder() .addHeader("Authorization", "Bearer " + apiKey) .addHeader("Content-Type", "application/json"); } /** * Create a new payment */ public Payment createPayment(PaymentRequest paymentRequest) throws MollieException { try { String requestBody = objectMapper.writeValueAsString(paymentRequest); Request request = createAuthenticatedRequest() .url(baseUrl + "/payments") .post(RequestBody.create(requestBody, MediaType.parse("application/json"))) .build(); try (Response response = executeRequest(request)) { String responseBody = response.body().string(); return objectMapper.readValue(responseBody, Payment.class); } } catch (IOException e) { throw new MollieException("Failed to create payment", e); } } /** * Get payment by ID */ public Payment getPayment(String paymentId) throws MollieException { try { Request request = createAuthenticatedRequest() .url(baseUrl + "/payments/" + paymentId) .get() .build(); try (Response response = executeRequest(request)) { String responseBody = response.body().string(); return objectMapper.readValue(responseBody, Payment.class); } } catch (IOException e) { throw new MollieException("Failed to get payment: " + paymentId, e); } } /** * List payments with pagination */ public PaginatedResponse<Payment> listPayments(int limit, String from) throws MollieException { try { HttpUrl.Builder urlBuilder = HttpUrl.parse(baseUrl + "/payments").newBuilder() .addQueryParameter("limit", String.valueOf(limit)); if (from != null) { urlBuilder.addQueryParameter("from", from); } Request request = createAuthenticatedRequest() .url(urlBuilder.build()) .get() .build(); try (Response response = executeRequest(request)) { String responseBody = response.body().string(); return objectMapper.readValue(responseBody, new TypeReference<PaginatedResponse<Payment>>() {}); } } catch (IOException e) { throw new MollieException("Failed to list payments", e); } } /** * Cancel payment (if possible) */ public Payment cancelPayment(String paymentId) throws MollieException { try { Request request = createAuthenticatedRequest() .url(baseUrl + "/payments/" + paymentId) .delete() .build(); try (Response response = executeRequest(request)) { String responseBody = response.body().string(); return objectMapper.readValue(responseBody, Payment.class); } } catch (IOException e) { throw new MollieException("Failed to cancel payment: " + paymentId, e); } } /** * Create a refund */ public Refund createRefund(String paymentId, RefundRequest refundRequest) throws MollieException { try { String requestBody = objectMapper.writeValueAsString(refundRequest); Request request = createAuthenticatedRequest() .url(baseUrl + "/payments/" + paymentId + "/refunds") .post(RequestBody.create(requestBody, MediaType.parse("application/json"))) .build(); try (Response response = executeRequest(request)) { String responseBody = response.body().string(); return objectMapper.readValue(responseBody, Refund.class); } } catch (IOException e) { throw new MollieException("Failed to create refund", e); } } /** * Get refund by ID */ public Refund getRefund(String paymentId, String refundId) throws MollieException { try { Request request = createAuthenticatedRequest() .url(baseUrl + "/payments/" + paymentId + "/refunds/" + refundId) .get() .build(); try (Response response = executeRequest(request)) { String responseBody = response.body().string(); return objectMapper.readValue(responseBody, Refund.class); } } catch (IOException e) { throw new MollieException("Failed to get refund: " + refundId, e); } } /** * List refunds for a payment */ public PaginatedResponse<Refund> listRefunds(String paymentId, int limit, String from) throws MollieException { try { HttpUrl.Builder urlBuilder = HttpUrl.parse(baseUrl + "/payments/" + paymentId + "/refunds").newBuilder() .addQueryParameter("limit", String.valueOf(limit)); if (from != null) { urlBuilder.addQueryParameter("from", from); } Request request = createAuthenticatedRequest() .url(urlBuilder.build()) .get() .build(); try (Response response = executeRequest(request)) { String responseBody = response.body().string(); return objectMapper.readValue(responseBody, new TypeReference<PaginatedResponse<Refund>>() {}); } } catch (IOException e) { throw new MollieException("Failed to list refunds", e); } } /** * Cancel refund (if possible) */ public Refund cancelRefund(String paymentId, String refundId) throws MollieException { try { Request request = createAuthenticatedRequest() .url(baseUrl + "/payments/" + paymentId + "/refunds/" + refundId) .delete() .build(); try (Response response = executeRequest(request)) { String responseBody = response.body().string(); return objectMapper.readValue(responseBody, Refund.class); } } catch (IOException e) { throw new MollieException("Failed to cancel refund: " + refundId, e); } } /** * Create a customer */ public Customer createCustomer(CustomerRequest customerRequest) throws MollieException { try { String requestBody = objectMapper.writeValueAsString(customerRequest); Request request = createAuthenticatedRequest() .url(baseUrl + "/customers") .post(RequestBody.create(requestBody, MediaType.parse("application/json"))) .build(); try (Response response = executeRequest(request)) { String responseBody = response.body().string(); return objectMapper.readValue(responseBody, Customer.class); } } catch (IOException e) { throw new MollieException("Failed to create customer", e); } } /** * Get customer by ID */ public Customer getCustomer(String customerId) throws MollieException { try { Request request = createAuthenticatedRequest() .url(baseUrl + "/customers/" + customerId) .get() .build(); try (Response response = executeRequest(request)) { String responseBody = response.body().string(); return objectMapper.readValue(responseBody, Customer.class); } } catch (IOException e) { throw new MollieException("Failed to get customer: " + customerId, e); } } /** * Update customer */ public Customer updateCustomer(String customerId, CustomerRequest customerRequest) throws MollieException { try { String requestBody = objectMapper.writeValueAsString(customerRequest); Request request = createAuthenticatedRequest() .url(baseUrl + "/customers/" + customerId) .patch(RequestBody.create(requestBody, MediaType.parse("application/json"))) .build(); try (Response response = executeRequest(request)) { String responseBody = response.body().string(); return objectMapper.readValue(responseBody, Customer.class); } } catch (IOException e) { throw new MollieException("Failed to update customer: " + customerId, e); } } /** * Delete customer */ public void deleteCustomer(String customerId) throws MollieException { try { Request request = createAuthenticatedRequest() .url(baseUrl + "/customers/" + customerId) .delete() .build(); try (Response response = executeRequest(request)) { if (!response.isSuccessful()) { handleErrorResponse(response); } } } catch (IOException e) { throw new MollieException("Failed to delete customer: " + customerId, e); } } /** * List customers with pagination */ public PaginatedResponse<Customer> listCustomers(int limit, String from) throws MollieException { try { HttpUrl.Builder urlBuilder = HttpUrl.parse(baseUrl + "/customers").newBuilder() .addQueryParameter("limit", String.valueOf(limit)); if (from != null) { urlBuilder.addQueryParameter("from", from); } Request request = createAuthenticatedRequest() .url(urlBuilder.build()) .get() .build(); try (Response response = executeRequest(request)) { String responseBody = response.body().string(); return objectMapper.readValue(responseBody, new TypeReference<PaginatedResponse<Customer>>() {}); } } catch (IOException e) { throw new MollieException("Failed to list customers", e); } } /** * Create customer payment */ public Payment createCustomerPayment(String customerId, PaymentRequest paymentRequest) throws MollieException { try { String requestBody = objectMapper.writeValueAsString(paymentRequest); Request request = createAuthenticatedRequest() .url(baseUrl + "/customers/" + customerId + "/payments") .post(RequestBody.create(requestBody, MediaType.parse("application/json"))) .build(); try (Response response = executeRequest(request)) { String responseBody = response.body().string(); return objectMapper.readValue(responseBody, Payment.class); } } catch (IOException e) { throw new MollieException("Failed to create customer payment", e); } } /** * List methods available for your account */ public PaginatedResponse<Method> listMethods(Double amount, String currency, String resource) throws MollieException { try { HttpUrl.Builder urlBuilder = HttpUrl.parse(baseUrl + "/methods").newBuilder(); if (amount != null) { urlBuilder.addQueryParameter("amount[value]", String.format("%.2f", amount)); } if (currency != null) { urlBuilder.addQueryParameter("amount[currency]", currency); } if (resource != null) { urlBuilder.addQueryParameter("resource", resource); } Request request = createAuthenticatedRequest() .url(urlBuilder.build()) .get() .build(); try (Response response = executeRequest(request)) { String responseBody = response.body().string(); return objectMapper.readValue(responseBody, new TypeReference<PaginatedResponse<Method>>() {}); } } catch (IOException e) { throw new MollieException("Failed to list methods", e); } } /** * Get specific method */ public Method getMethod(String methodId, Double amount, String currency) throws MollieException { try { HttpUrl.Builder urlBuilder = HttpUrl.parse(baseUrl + "/methods/" + methodId).newBuilder(); if (amount != null && currency != null) { urlBuilder.addQueryParameter("amount[value]", String.format("%.2f", amount)); urlBuilder.addQueryParameter("amount[currency]", currency); } Request request = createAuthenticatedRequest() .url(urlBuilder.build()) .get() .build(); try (Response response = executeRequest(request)) { String responseBody = response.body().string(); return objectMapper.readValue(responseBody, Method.class); } } catch (IOException e) { throw new MollieException("Failed to get method: " + methodId, e); } } // Custom exception public static class MollieException extends Exception { private final int statusCode; public MollieException(String message) { super(message); this.statusCode = 0; } public MollieException(String message, Throwable cause) { super(message, cause); this.statusCode = 0; } public MollieException(String message, int statusCode) { super(message); this.statusCode = statusCode; } public int getStatusCode() { return statusCode; } } }

Data Models

Core Data Classes

package com.mollie.model; import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import com.fasterxml.jackson.annotation.JsonProperty; import java.time.OffsetDateTime; import java.util.List; import java.util.Map; // Payment Request @JsonIgnoreProperties(ignoreUnknown = true) public class PaymentRequest { private Amount amount; private String description; private String redirectUrl; private String webhookUrl; private String method; private Map<String, Object> metadata; private String customerId; private String sequenceType; private String mandateId; private String locale; private Map<String, Object> billingAddress; private Map<String, Object> shippingAddress; private String orderId; private Map<String, Object> applicationFee; private Map<String, Object> profileId; private Boolean testmode; // Getters and setters public Amount getAmount() { return amount; } public void setAmount(Amount amount) { this.amount = amount; } public String getDescription() { return description; } public void setDescription(String description) { this.description = description; } public String getRedirectUrl() { return redirectUrl; } public void setRedirectUrl(String redirectUrl) { this.redirectUrl = redirectUrl; } public String getWebhookUrl() { return webhookUrl; } public void setWebhookUrl(String webhookUrl) { this.webhookUrl = webhookUrl; } public String getMethod() { return method; } public void setMethod(String method) { this.method = method; } public Map<String, Object> getMetadata() { return metadata; } public void setMetadata(Map<String, Object> metadata) { this.metadata = metadata; } public String getCustomerId() { return customerId; } public void setCustomerId(String customerId) { this.customerId = customerId; } public String getSequenceType() { return sequenceType; } public void setSequenceType(String sequenceType) { this.sequenceType = sequenceType; } public String getMandateId() { return mandateId; } public void setMandateId(String mandateId) { this.mandateId = mandateId; } public String getLocale() { return locale; } public void setLocale(String locale) { this.locale = locale; } public Map<String, Object> getBillingAddress() { return billingAddress; } public void setBillingAddress(Map<String, Object> billingAddress) { this.billingAddress = billingAddress; } public Map<String, Object> getShippingAddress() { return shippingAddress; } public void setShippingAddress(Map<String, Object> shippingAddress) { this.shippingAddress = shippingAddress; } public String getOrderId() { return orderId; } public void setOrderId(String orderId) { this.orderId = orderId; } public Map<String, Object> getApplicationFee() { return applicationFee; } public void setApplicationFee(Map<String, Object> applicationFee) { this.applicationFee = applicationFee; } public Map<String, Object> getProfileId() { return profileId; } public void setProfileId(Map<String, Object> profileId) { this.profileId = profileId; } public Boolean getTestmode() { return testmode; } public void setTestmode(Boolean testmode) { this.testmode = testmode; } } // Payment Response @JsonIgnoreProperties(ignoreUnknown = true) class Payment { private String id; private String mode; private OffsetDateTime createdAt; private String status; private Boolean isCancelable; private Amount amount; private Amount amountRefunded; private Amount amountRemaining; private Amount amountCaptured; private String description; private String method; private Map<String, Object> metadata; private Map<String, Object> details; private String profileId; private String sequenceType; private String redirectUrl; private String webhookUrl; private Links links; private Customer customer; private String mandateId; private String subscriptionId; private String orderId; private String settlementId; private String locale; private Map<String, Object> billingAddress; private Map<String, Object> shippingAddress; private Map<String, Object> applicationFee; private OffsetDateTime expiredAt; private OffsetDateTime paidAt; private OffsetDateTime canceledAt; private OffsetDateTime failedAt; // Getters and setters public String getId() { return id; } public void setId(String id) { this.id = id; } public String getMode() { return mode; } public void setMode(String mode) { this.mode = mode; } public OffsetDateTime getCreatedAt() { return createdAt; } public void setCreatedAt(OffsetDateTime createdAt) { this.createdAt = createdAt; } public String getStatus() { return status; } public void setStatus(String status) { this.status = status; } public Boolean getIsCancelable() { return isCancelable; } public void setIsCancelable(Boolean isCancelable) { this.isCancelable = isCancelable; } public Amount getAmount() { return amount; } public void setAmount(Amount amount) { this.amount = amount; } public Amount getAmountRefunded() { return amountRefunded; } public void setAmountRefunded(Amount amountRefunded) { this.amountRefunded = amountRefunded; } public Amount getAmountRemaining() { return amountRemaining; } public void setAmountRemaining(Amount amountRemaining) { this.amountRemaining = amountRemaining; } public Amount getAmountCaptured() { return amountCaptured; } public void setAmountCaptured(Amount amountCaptured) { this.amountCaptured = amountCaptured; } public String getDescription() { return description; } public void setDescription(String description) { this.description = description; } public String getMethod() { return method; } public void setMethod(String method) { this.method = method; } public Map<String, Object> getMetadata() { return metadata; } public void setMetadata(Map<String, Object> metadata) { this.metadata = metadata; } public Map<String, Object> getDetails() { return details; } public void setDetails(Map<String, Object> details) { this.details = details; } public String getProfileId() { return profileId; } public void setProfileId(String profileId) { this.profileId = profileId; } public String getSequenceType() { return sequenceType; } public void setSequenceType(String sequenceType) { this.sequenceType = sequenceType; } public String getRedirectUrl() { return redirectUrl; } public void setRedirectUrl(String redirectUrl) { this.redirectUrl = redirectUrl; } public String getWebhookUrl() { return webhookUrl; } public void setWebhookUrl(String webhookUrl) { this.webhookUrl = webhookUrl; } public Links getLinks() { return links; } public void setLinks(Links links) { this.links = links; } public Customer getCustomer() { return customer; } public void setCustomer(Customer customer) { this.customer = customer; } public String getMandateId() { return mandateId; } public void setMandateId(String mandateId) { this.mandateId = mandateId; } public String getSubscriptionId() { return subscriptionId; } public void setSubscriptionId(String subscriptionId) { this.subscriptionId = subscriptionId; } public String getOrderId() { return orderId; } public void setOrderId(String orderId) { this.orderId = orderId; } public String getSettlementId() { return settlementId; } public void setSettlementId(String settlementId) { this.settlementId = settlementId; } public String getLocale() { return locale; } public void setLocale(String locale) { this.locale = locale; } public Map<String, Object> getBillingAddress() { return billingAddress; } public void setBillingAddress(Map<String, Object> billingAddress) { this.billingAddress = billingAddress; } public Map<String, Object> getShippingAddress() { return shippingAddress; } public void setShippingAddress(Map<String, Object> shippingAddress) { this.shippingAddress = shippingAddress; } public Map<String, Object> getApplicationFee() { return applicationFee; } public void setApplicationFee(Map<String, Object> applicationFee) { this.applicationFee = applicationFee; } public OffsetDateTime getExpiredAt() { return expiredAt; } public void setExpiredAt(OffsetDateTime expiredAt) { this.expiredAt = expiredAt; } public OffsetDateTime getPaidAt() { return paidAt; } public void setPaidAt(OffsetDateTime paidAt) { this.paidAt = paidAt; } public OffsetDateTime getCanceledAt() { return canceledAt; } public void setCanceledAt(OffsetDateTime canceledAt) { this.canceledAt = canceledAt; } public OffsetDateTime getFailedAt() { return failedAt; } public void setFailedAt(OffsetDateTime failedAt) { this.failedAt = failedAt; } } // Amount @JsonIgnoreProperties(ignoreUnknown = true) class Amount { private String currency; private String value; public Amount() {} public Amount(String currency, String value) { this.currency = currency; this.value = value; } public Amount(String currency, double value) { this.currency = currency; this.value = String.format("%.2f", value); } // Getters and setters public String getCurrency() { return currency; } public void setCurrency(String currency) { this.currency = currency; } public String getValue() { return value; } public void setValue(String value) { this.value = value; } } // Links @JsonIgnoreProperties(ignoreUnknown = true) class Links { private String self; private String checkout; private String dashboard; private String documentation; private String changePaymentState; private String refunds; private String capture; private String settle; private String customer; private String mandate; private String subscription; private String order; // Getters and setters public String getSelf() { return self; } public void setSelf(String self) { this.self = self; } public String getCheckout() { return checkout; } public void setCheckout(String checkout) { this.checkout = checkout; } public String getDashboard() { return dashboard; } public void setDashboard(String dashboard) { this.dashboard = dashboard; } public String getDocumentation() { return documentation; } public void setDocumentation(String documentation) { this.documentation = documentation; } public String getChangePaymentState() { return changePaymentState; } public void setChangePaymentState(String changePaymentState) { this.changePaymentState = changePaymentState; } public String getRefunds() { return refunds; } public void setRefunds(String refunds) { this.refunds = refunds; } public String getCapture() { return capture; } public void setCapture(String capture) { this.capture = capture; } public String getSettle() { return settle; } public void setSettle(String settle) { this.settle = settle; } public String getCustomer() { return customer; } public void setCustomer(String customer) { this.customer = customer; } public String getMandate() { return mandate; } public void setMandate(String mandate) { this.mandate = mandate; } public String getSubscription() { return subscription; } public void setSubscription(String subscription) { this.subscription = subscription; } public String getOrder() { return order; } public void setOrder(String order) { this.order = order; } } // Customer @JsonIgnoreProperties(ignoreUnknown = true) class Customer { private String id; private String mode; private String name; private String email; private String locale; private Map<String, Object> metadata; private OffsetDateTime createdAt; private Links links; // Getters and setters public String getId() { return id; } public void setId(String id) { this.id = id; } public String getMode() { return mode; } public void setMode(String mode) { this.mode = mode; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getEmail() { return email; } public void setEmail(String email) { this.email = email; } public String getLocale() { return locale; } public void setLocale(String locale) { this.locale = locale; } public Map<String, Object> getMetadata() { return metadata; } public void setMetadata(Map<String, Object> metadata) { this.metadata = metadata; } public OffsetDateTime getCreatedAt() { return createdAt; } public void setCreatedAt(OffsetDateTime createdAt) { this.createdAt = createdAt; } public Links getLinks() { return links; } public void setLinks(Links links) { this.links = links; } } // Customer Request @JsonIgnoreProperties(ignoreUnknown = true) class CustomerRequest { private String name; private String email; private String locale; private Map<String, Object> metadata; // Getters and setters public String getName() { return name; } public void setName(String name) { this.name = name; } public String getEmail() { return email; } public void setEmail(String email) { this.email = email; } public String getLocale() { return locale; } public void setLocale(String locale) { this.locale = locale; } public Map<String, Object> getMetadata() { return metadata; } public void setMetadata(Map<String, Object> metadata) { this.metadata = metadata; } } // Refund Request @JsonIgnoreProperties(ignoreUnknown = true) class RefundRequest { private Amount amount; private String description; private Map<String, Object> metadata; private Boolean testmode; // Getters and setters public Amount getAmount() { return amount; } public void setAmount(Amount amount) { this.amount = amount; } public String getDescription() { return description; } public void setDescription(String description) { this.description = description; } public Map<String, Object> getMetadata() { return metadata; } public void setMetadata(Map<String, Object> metadata) { this.metadata = metadata; } public Boolean getTestmode() { return testmode; } public void setTestmode(Boolean testmode) { this.testmode = testmode; } } // Refund @JsonIgnoreProperties(ignoreUnknown = true) class Refund { private String id; private Amount amount; private String settlementId; private OffsetDateTime createdAt; private String description; private Map<String, Object> metadata; private String paymentId; private String status; private Links links; // Getters and setters public String getId() { return id; } public void setId(String id) { this.id = id; } public Amount getAmount() { return amount; } public void setAmount(Amount amount) { this.amount = amount; } public String getSettlementId() { return settlementId; } public void setSettlementId(String settlementId) { this.settlementId = settlementId; } public OffsetDateTime getCreatedAt() { return createdAt; } public void setCreatedAt(OffsetDateTime createdAt) { this.createdAt = createdAt; } public String getDescription() { return description; } public void setDescription(String description) { this.description = description; } public Map<String, Object> getMetadata() { return metadata; } public void setMetadata(Map<String, Object> metadata) { this.metadata = metadata; } public String getPaymentId() { return paymentId; } public void setPaymentId(String paymentId) { this.paymentId = paymentId; } public String getStatus() { return status; } public void setStatus(String status) { this.status = status; } public Links getLinks() { return links; } public void setLinks(Links links) { this.links = links; } } // Method @JsonIgnoreProperties(ignoreUnknown = true) class Method { private String id; private String description; private Amount minimumAmount; private Amount maximumAmount; private String status; private Image image; private Map<String, Object> pricing; // Getters and setters public String getId() { return id; } public void setId(String id) { this.id = id; } public String getDescription() { return description; } public void setDescription(String description) { this.description = description; } public Amount getMinimumAmount() { return minimumAmount; } public void setMinimumAmount(Amount minimumAmount) { this.minimumAmount = minimumAmount; } public Amount getMaximumAmount() { return maximumAmount; } public void setMaximumAmount(Amount maximumAmount) { this.maximumAmount = maximumAmount; } public String getStatus() { return status; } public void setStatus(String status) { this.status = status; } public Image getImage() { return image; } public void setImage(Image image) { this.image = image; } public Map<String, Object> getPricing() { return pricing; } public void setPricing(Map<String, Object> pricing) { this.pricing = pricing; } } // Image @JsonIgnoreProperties(ignoreUnknown = true) class Image { private String size1x; private String size2x; private String svg; // Getters and setters public String getSize1x() { return size1x; } public void setSize1x(String size1x) { this.size1x = size1x; } public String getSize2x() { return size2x; } public void setSize2x(String size2x) { this.size2x = size2x; } public String getSvg() { return svg; } public void setSvg(String svg) { this.svg = svg; } } // Paginated Response @JsonIgnoreProperties(ignoreUnknown = true) class PaginatedResponse<T> { private Integer count; private List<T> data; private Links links; // Getters and setters public Integer getCount() { return count; } public void setCount(Integer count) { this.count = count; } public List<T> getData() { return data; } public void setData(List<T> data) { this.data = data; } public Links getLinks() { return links; } public void setLinks(Links links) { this.links = links; } } // Error Response @JsonIgnoreProperties(ignoreUnknown = true) class ErrorResponse { private String status; private String title; private String detail; private String field; private Links links; // Getters and setters public String getStatus() { return status; } public void setStatus(String status) { this.status = status; } public String getTitle() { return title; } public void setTitle(String title) { this.title = title; } public String getDetail() { return detail; } public void setDetail(String detail) { this.detail = detail; } public String getField() { return field; } public void setField(String field) { this.field = field; } public Links getLinks() { return links; } public void setLinks(Links links) { this.links = links; } }

Payment Service

Comprehensive Payment Service

package com.mollie.service; import com.mollie.client.MollieClient; import com.mollie.model.*; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.util.HashMap; import java.util.List; import java.util.Map; public class PaymentService { private static final Logger logger = LoggerFactory.getLogger(PaymentService.class); private final MollieClient client; private final String webhookBaseUrl; private final String redirectBaseUrl; public PaymentService(MollieClient client, String webhookBaseUrl, String redirectBaseUrl) { this.client = client; this.webhookBaseUrl = webhookBaseUrl; this.redirectBaseUrl = redirectBaseUrl; } /** * Create a simple payment */ public Payment createSimplePayment(double amount, String currency, String description, String orderId, Map<String, Object> metadata) throws MollieException { PaymentRequest request = new PaymentRequest(); request.setAmount(new Amount(currency, amount)); request.setDescription(description); request.setRedirectUrl(redirectBaseUrl + "/payment/return"); request.setWebhookUrl(webhookBaseUrl + "/webhook/payment"); request.setMetadata(metadata); if (orderId != null) { request.setOrderId(orderId); } return client.createPayment(request); } /** * Create payment with specific method */ public Payment createPaymentWithMethod(double amount, String currency, String description, String method, String orderId, Map<String, Object> metadata) throws MollieException { PaymentRequest request = new PaymentRequest(); request.setAmount(new Amount(currency, amount)); request.setDescription(description); request.setMethod(method); request.setRedirectUrl(redirectBaseUrl + "/payment/return"); request.setWebhookUrl(webhookBaseUrl + "/webhook/payment"); request.setMetadata(metadata); if (orderId != null) { request.setOrderId(orderId); } return client.createPayment(request); } /** * Create recurring payment for customer */ public Payment createRecurringPayment(String customerId, double amount, String currency, String description, String mandateId, Map<String, Object> metadata) throws MollieException { PaymentRequest request = new PaymentRequest(); request.setAmount(new Amount(currency, amount)); request.setDescription(description); request.setCustomerId(customerId); request.setSequenceType("recurring"); request.setMandateId(mandateId); request.setMetadata(metadata); return client.createPayment(request); } /** * Create payment for existing customer */ public Payment createCustomerPayment(String customerId, double amount, String currency, String description, String method, Map<String, Object> metadata) throws MollieException { PaymentRequest request = new PaymentRequest(); request.setAmount(new Amount(currency, amount)); request.setDescription(description); request.setCustomerId(customerId); request.setMethod(method); request.setRedirectUrl(redirectBaseUrl + "/payment/return"); request.setWebhookUrl(webhookBaseUrl + "/webhook/payment"); request.setMetadata(metadata); return client.createCustomerPayment(customerId, request); } /** * Check if payment is successful */ public boolean isPaymentSuccessful(String paymentId) throws MollieException { Payment payment = client.getPayment(paymentId); return "paid".equals(payment.getStatus()); } /** * Check if payment is pending */ public boolean isPaymentPending(String paymentId) throws MollieException { Payment payment = client.getPayment(paymentId); return "pending".equals(payment.getStatus()) || "open".equals(payment.getStatus()); } /** * Check if payment has failed */ public boolean isPaymentFailed(String paymentId) throws MollieException { Payment payment = client.getPayment(paymentId); return "failed".equals(payment.getStatus()) || "expired".equals(payment.getStatus()) || "canceled".equals(payment.getStatus()); } /** * Get payment status */ public String getPaymentStatus(String paymentId) throws MollieException { Payment payment = client.getPayment(paymentId); return payment.getStatus(); } /** * Process refund for payment */ public Refund processRefund(String paymentId, double amount, String currency, String description, Map<String, Object> metadata) throws MollieException { RefundRequest request = new RefundRequest(); request.setAmount(new Amount(currency, amount)); request.setDescription(description); request.setMetadata(metadata); return client.createRefund(paymentId, request); } /** * Process full refund */ public Refund processFullRefund(String paymentId, String description, Map<String, Object> metadata) throws MollieException { Payment payment = client.getPayment(paymentId); return processRefund(paymentId, Double.parseDouble(payment.getAmount().getValue()), payment.getAmount().getCurrency(), description, metadata); } /** * Get available payment methods for amount */ public List<Method> getAvailableMethods(double amount, String currency) throws MollieException { PaginatedResponse<Method> response = client.listMethods(amount, currency, "orders"); return response.getData(); } /** * Check if method is available for amount */ public boolean isMethodAvailable(String methodId, double amount, String currency) throws MollieException { try { Method method = client.getMethod(methodId, amount, currency); return "activated".equals(method.getStatus()); } catch (MollieException e) { if (e.getStatusCode() == 404) { return false; } throw e; } } /** * Create customer with basic info */ public Customer createCustomer(String name, String email, String locale, Map<String, Object> metadata) throws MollieException { CustomerRequest request = new CustomerRequest(); request.setName(name); request.setEmail(email); request.setLocale(locale); request.setMetadata(metadata); return client.createCustomer(request); } /** * Update customer information */ public Customer updateCustomer(String customerId, String name, String email, Map<String, Object> metadata) throws MollieException { CustomerRequest request = new CustomerRequest(); request.setName(name); request.setEmail(email); request.setMetadata(metadata); return client.updateCustomer(customerId, request); } /** * Get customer payments */ public List<Payment> getCustomerPayments(String customerId, int limit) throws MollieException { // Note: This would require additional implementation in the client // For now, we'll list all payments and filter by customer PaginatedResponse<Payment> payments = client.listPayments(limit, null); return payments.getData().stream() .filter(p -> customerId.equals(p.getCustomer() != null ? p.getCustomer().getId() : null)) .toList(); } /** * Validate webhook signature (basic implementation) */ public boolean validateWebhookSignature(String body, String signature) { // In a real implementation, you would verify the signature // This is a simplified version logger.info("Webhook received with signature: {}", signature); return true; } /** * Process webhook notification */ public WebhookResult processWebhook(String body, String signature) { try { if (!validateWebhookSignature(body, signature)) { return new WebhookResult(false, "Invalid signature"); } // Parse webhook body Payment payment = client.getObjectMapper().readValue(body, Payment.class); String paymentId = payment.getId(); String status = payment.getStatus(); logger.info("Processing webhook for payment {} with status {}", paymentId, status); // Handle different statuses switch (status) { case "paid": handlePaidPayment(payment); break; case "failed": handleFailedPayment(payment); break; case "canceled": handleCanceledPayment(payment); break; case "expired": handleExpiredPayment(payment); break; case "pending": handlePendingPayment(payment); break; default: logger.warn("Unknown payment status: {}", status); } return new WebhookResult(true, "Webhook processed successfully"); } catch (Exception e) { logger.error("Error processing webhook", e); return new WebhookResult(false, "Error processing webhook: " + e.getMessage()); } } // Webhook handlers private void handlePaidPayment(Payment payment) { // Update order status in your system // Send confirmation email // Fulfill order logger.info("Payment {} completed successfully", payment.getId()); // Extract metadata for your business logic Map<String, Object> metadata = payment.getMetadata(); if (metadata != null) { String orderId = (String) metadata.get("orderId"); if (orderId != null) { // Update your order system logger.info("Updating order {} to paid", orderId); } } } private void handleFailedPayment(Payment payment) { // Notify customer // Update order status logger.warn("Payment {} failed", payment.getId()); } private void handleCanceledPayment(Payment payment) { // Handle canceled payment logger.info("Payment {} was canceled", payment.getId()); } private void handleExpiredPayment(Payment payment) { // Handle expired payment logger.info("Payment {} expired", payment.getId()); } private void handlePendingPayment(Payment payment) { // Handle pending payment (e.g., bank transfer) logger.info("Payment {} is pending", payment.getId()); } // Webhook result public static class WebhookResult { private final boolean success; private final String message; public WebhookResult(boolean success, String message) { this.success = success; this.message = message; } public boolean isSuccess() { return success; } public String getMessage() { return message; } } }

Spring Boot Integration

Configuration Class

package com.mollie.config; import com.mollie.client.MollieClient; import com.mollie.service.PaymentService; import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @Configuration public class MollieConfig { @Value("${mollie.api.key}") private String apiKey; @Value("${mollie.test.mode:true}") private boolean testMode; @Value("${app.webhook.base.url}") private String webhookBaseUrl; @Value("${app.redirect.base.url}") private String redirectBaseUrl; @Bean public MollieClient mollieClient() { return new MollieClient(apiKey, testMode); } @Bean public PaymentService paymentService() { return new PaymentService(mollieClient(), webhookBaseUrl, redirectBaseUrl); } }

REST Controller

package com.mollie.controller; import com.mollie.model.*; import com.mollie.service.PaymentService; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.*; import java.util.HashMap; import java.util.List; import java.util.Map; @RestController @RequestMapping("/api/payments") public class PaymentController { private static final Logger logger = LoggerFactory.getLogger(PaymentController.class); @Autowired private PaymentService paymentService; @PostMapping("/create") public ResponseEntity<Map<String, Object>> createPayment(@RequestBody CreatePaymentRequest request) { Map<String, Object> response = new HashMap<>(); try { Payment payment = paymentService.createSimplePayment( request.getAmount(), request.getCurrency(), request.getDescription(), request.getOrderId(), request.getMetadata() ); response.put("success", true); response.put("paymentId", payment.getId()); response.put("checkoutUrl", payment.getLinks().getCheckout()); response.put("status", payment.getStatus()); return ResponseEntity.ok(response); } catch (Exception e) { logger.error("Failed to create payment", e); response.put("success", false); response.put("error", e.getMessage()); return ResponseEntity.badRequest().body(response); } } @PostMapping("/create-with-method") public ResponseEntity<Map<String, Object>> createPaymentWithMethod(@RequestBody CreatePaymentMethodRequest request) { Map<String, Object> response = new HashMap<>(); try { Payment payment = paymentService.createPaymentWithMethod( request.getAmount(), request.getCurrency(), request.getDescription(), request.getMethod(), request.getOrderId(), request.getMetadata() ); response.put("success", true); response.put("paymentId", payment.getId()); response.put("checkoutUrl", payment.getLinks().getCheckout()); response.put("status", payment.getStatus()); return ResponseEntity.ok(response); } catch (Exception e) { logger.error("Failed to create payment with method", e); response.put("success", false); response.put("error", e.getMessage()); return ResponseEntity.badRequest().body(response); } } @GetMapping("/{paymentId}") public ResponseEntity<Map<String, Object>> getPayment(@PathVariable String paymentId) { Map<String, Object> response = new HashMap<>(); try { Payment payment = paymentService.getPayment(paymentId); response.put("success", true); response.put("payment", payment); response.put("status", payment.getStatus()); response.put("isSuccessful", paymentService.isPaymentSuccessful(paymentId)); return ResponseEntity.ok(response); } catch (Exception e) { logger.error("Failed to get payment: {}", paymentId, e); response.put("success", false); response.put("error", e.getMessage()); return ResponseEntity.badRequest().body(response); } } @GetMapping("/{paymentId}/status") public ResponseEntity<Map<String, Object>> getPaymentStatus(@PathVariable String paymentId) { Map<String, Object> response = new HashMap<>(); try { String status = paymentService.getPaymentStatus(paymentId); response.put("success", true); response.put("paymentId", paymentId); response.put("status", status); response.put("isSuccessful", "paid".equals(status)); response.put("isPending", "pending".equals(status) || "open".equals(status)); response.put("isFailed", "failed".equals(status) || "expired".equals(status) || "canceled".equals(status)); return ResponseEntity.ok(response); } catch (Exception e) { logger.error("Failed to get payment status: {}", paymentId, e); response.put("success", false); response.put("error", e.getMessage()); return ResponseEntity.badRequest().body(response); } } @PostMapping("/{paymentId}/refund") public ResponseEntity<Map<String, Object>> createRefund( @PathVariable String paymentId, @RequestBody CreateRefundRequest request) { Map<String, Object> response = new HashMap<>(); try { Refund refund = paymentService.processRefund( paymentId, request.getAmount(), request.getCurrency(), request.getDescription(), request.getMetadata() ); response.put("success", true); response.put("refundId", refund.getId()); response.put("status", refund.getStatus()); return ResponseEntity.ok(response); } catch (Exception e) { logger.error("Failed to create refund for payment: {}", paymentId, e); response.put("success", false); response.put("error", e.getMessage()); return ResponseEntity.badRequest().body(response); } } @PostMapping("/{paymentId}/refund/full") public ResponseEntity<Map<String, Object>> createFullRefund( @PathVariable String paymentId, @RequestBody CreateRefundRequest request) { Map<String, Object> response = new HashMap<>(); try { Refund refund = paymentService.processFullRefund( paymentId, request.getDescription(), request.getMetadata() ); response.put("success", true); response.put("refundId", refund.getId()); response.put("status", refund.getStatus()); return ResponseEntity.ok(response); } catch (Exception e) { logger.error("Failed to create full refund for payment: {}", paymentId, e); response.put("success", false); response.put("error", e.getMessage()); return ResponseEntity.badRequest().body(response); } } @GetMapping("/methods") public ResponseEntity<Map<String, Object>> getAvailableMethods( @RequestParam double amount, @RequestParam String currency) { Map<String, Object> response = new HashMap<>(); try { List<Method> methods = paymentService.getAvailableMethods(amount, currency); response.put("success", true); response.put("methods", methods); response.put("count", methods.size()); return ResponseEntity.ok(response); } catch (Exception e) { logger.error("Failed to get available methods", e); response.put("success", false); response.put("error", e.getMessage()); return ResponseEntity.badRequest().body(response); } } @PostMapping("/webhook") public ResponseEntity<Map<String, Object>> handleWebhook( @RequestBody String body, @RequestHeader(value = "Signature", required = false) String signature) { Map<String, Object> response = new HashMap<>(); try { PaymentService.WebhookResult result = paymentService.processWebhook(body, signature); if (result.isSuccess()) { response.put("success", true); response.put("message", result.getMessage()); return ResponseEntity.ok(response); } else { response.put("success", false); response.put("error", result.getMessage()); return ResponseEntity.badRequest().body(response); } } catch (Exception e) { logger.error("Failed to process webhook", e); response.put("success", false); response.put("error", e.getMessage()); return ResponseEntity.badRequest().body(response); } } // Request DTOs public static class CreatePaymentRequest { private double amount; private String currency; private String description; private String orderId; private Map<String, Object> metadata; // Getters and setters public double getAmount() { return amount; } public void setAmount(double amount) { this.amount = amount; } public String getCurrency() { return currency; } public void setCurrency(String currency) { this.currency = currency; } public String getDescription() { return description; } public void setDescription(String description) { this.description = description; } public String getOrderId() { return orderId; } public void setOrderId(String orderId) { this.orderId = orderId; } public Map<String, Object> getMetadata() { return metadata; } public void setMetadata(Map<String, Object> metadata) { this.metadata = metadata; } } public static class CreatePaymentMethodRequest { private double amount; private String currency; private String description; private String method; private String orderId; private Map<String, Object> metadata; // Getters and setters public double getAmount() { return amount; } public void setAmount(double amount) { this.amount = amount; } public String getCurrency() { return currency; } public void setCurrency(String currency) { this.currency = currency; } public String getDescription() { return description; } public void setDescription(String description) { this.description = description; } public String getMethod() { return method; } public void setMethod(String method) { this.method = method; } public String getOrderId() { return orderId; } public void setOrderId(String orderId) { this.orderId = orderId; } public Map<String, Object> getMetadata() { return metadata; } public void setMetadata(Map<String, Object> metadata) { this.metadata = metadata; } } public static class CreateRefundRequest { private double amount; private String currency; private String description; private Map<String, Object> metadata; // Getters and setters public double getAmount() { return amount; } public void setAmount(double amount) { this.amount = amount; } public String getCurrency() { return currency; } public void setCurrency(String currency) { this.currency = currency; } public String getDescription() { return description; } public void setDescription(String description) { this.description = description; } public Map<String, Object> getMetadata() { return metadata; } public void setMetadata(Map<String, Object> metadata) { this.metadata = metadata; } } }

Customer Management Controller

package com.mollie.controller; import com.mollie.model.Customer; import com.mollie.model.CustomerRequest; import com.mollie.model.PaginatedResponse; import com.mollie.model.Payment; import com.mollie.service.PaymentService; import com.mollie.client.MollieClient; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.*; import java.util.HashMap; import java.util.List; import java.util.Map; @RestController @RequestMapping("/api/customers") public class CustomerController { private static final Logger logger = LoggerFactory.getLogger(CustomerController.class); @Autowired private MollieClient mollieClient; @Autowired private PaymentService paymentService; @PostMapping public ResponseEntity<Map<String, Object>> createCustomer(@RequestBody CustomerRequest request) { Map<String, Object> response = new HashMap<>(); try { Customer customer = mollieClient.createCustomer(request); response.put("success", true); response.put("customerId", customer.getId()); response.put("customer", customer); return ResponseEntity.ok(response); } catch (Exception e) { logger.error("Failed to create customer", e); response.put("success", false); response.put("error", e.getMessage()); return ResponseEntity.badRequest().body(response); } } @GetMapping("/{customerId}") public ResponseEntity<Map<String, Object>> getCustomer(@PathVariable String customerId) { Map<String, Object> response = new HashMap<>(); try { Customer customer = mollieClient.getCustomer(customerId); response.put("success", true); response.put("customer", customer); return ResponseEntity.ok(response); } catch (Exception e) { logger.error("Failed to get customer: {}", customerId, e); response.put("success", false); response.put("error", e.getMessage()); return ResponseEntity.badRequest().body(response); } } @PutMapping("/{customerId}") public ResponseEntity<Map<String, Object>> updateCustomer( @PathVariable String customerId, @RequestBody CustomerRequest request) { Map<String, Object> response = new HashMap<>(); try { Customer customer = mollieClient.updateCustomer(customerId, request); response.put("success", true); response.put("customer", customer); return ResponseEntity.ok(response); } catch (Exception e) { logger.error("Failed to update customer: {}", customerId, e); response.put("success", false); response.put("error", e.getMessage()); return ResponseEntity.badRequest().body(response); } } @DeleteMapping("/{customerId}") public ResponseEntity<Map<String, Object>> deleteCustomer(@PathVariable String customerId) { Map<String, Object> response = new HashMap<>(); try { mollieClient.deleteCustomer(customerId); response.put("success", true); response.put("message", "Customer deleted successfully"); return ResponseEntity.ok(response); } catch (Exception e) { logger.error("Failed to delete customer: {}", customerId, e); response.put("success", false); response.put("error", e.getMessage()); return ResponseEntity.badRequest().body(response); } } @GetMapping public ResponseEntity<Map<String, Object>> listCustomers( @RequestParam(defaultValue = "10") int limit, @RequestParam(required = false) String from) { Map<String, Object> response = new HashMap<>(); try { PaginatedResponse<Customer> customers = mollieClient.listCustomers(limit, from); response.put("success", true); response.put("customers", customers.getData()); response.put("count", customers.getCount()); response.put("hasNext", customers.getLinks() != null && customers.getLinks().getNext() != null); return ResponseEntity.ok(response); } catch (Exception e) { logger.error("Failed to list customers", e); response.put("success", false); response.put("error", e.getMessage()); return ResponseEntity.badRequest().body(response); } } @GetMapping("/{customerId}/payments") public ResponseEntity<Map<String, Object>> getCustomerPayments( @PathVariable String customerId, @RequestParam(defaultValue = "10") int limit) { Map<String, Object> response = new HashMap<>(); try { List<Payment> payments = paymentService.getCustomerPayments(customerId, limit); response.put("success", true); response.put("payments", payments); response.put("count", payments.size()); return ResponseEntity.ok(response); } catch (Exception e) { logger.error("Failed to get customer payments: {}", customerId, e); response.put("success", false); response.put("error", e.getMessage()); return ResponseEntity.badRequest().body(response); } } }

Application Properties

# Mollie Configuration mollie.api.key=your_mollie_api_key_here mollie.test.mode=true # Application Configuration app.webhook.base.url=https://yourdomain.com app.redirect.base.url=https://yourdomain.com # Server Configuration server.port=8080 # Logging logging.level.com.mollie=INFO

Usage Examples

Basic Usage

package com.mollie.examples; import com.mollie.client.MollieClient; import com.mollie.model.*; import com.mollie.service.PaymentService; import java.util.HashMap; import java.util.Map; public class MollieExamples { public static void main(String[] args) { // Initialize client MollieClient client = new MollieClient("your_mollie_api_key", true); PaymentService paymentService = new PaymentService(client, "https://yourdomain.com", "https://yourdomain.com"); try { // Example 1: Create a simple payment Map<String, Object> metadata = new HashMap<>(); metadata.put("orderId", "ORDER-123"); metadata.put("userId", "USER-456"); Payment payment = paymentService.createSimplePayment( 29.99, "EUR", "Order #ORDER-123", "ORDER-123", metadata); System.out.println("Payment created: " + payment.getId()); System.out.println("Checkout URL: " + payment.getLinks().getCheckout()); // Example 2: Check payment status String paymentId = payment.getId(); String status = paymentService.getPaymentStatus(paymentId); System.out.println("Payment status: " + status); // Example 3: Create a customer Customer customer = paymentService.createCustomer( "John Doe", "[email protected]", "en_US", new HashMap<>()); System.out.println("Customer created: " + customer.getId()); // Example 4: Create recurring payment for customer // Note: You would need a mandate ID for recurring payments // Payment recurringPayment = paymentService.createRecurringPayment( // customer.getId(), 29.99, "EUR", "Monthly subscription", "mandate_id", metadata); } catch (Exception e) { e.printStackTrace(); } } }

Conclusion

This comprehensive Mollie Payments Java client provides:

  1. Complete API coverage for payments, refunds, and customers
  2. Payment processing for one-time and recurring payments
  3. Customer management for storing payment details
  4. Refund handling for processing returns
  5. Webhook integration for real-time payment updates
  6. Spring Boot integration for easy configuration

Key features:

  • Multiple payment methods support (iDEAL, credit card, PayPal, etc.)
  • Recurring payments for subscriptions
  • Comprehensive error handling with proper status codes
  • Type-safe models for all Mollie entities
  • Webhook processing for payment status updates
  • Customer management for improved user experience

This implementation enables Java applications to seamlessly integrate with Mollie's payment platform, providing robust payment processing capabilities for e-commerce applications, subscription services, and other payment-related use cases.

Leave a Reply

Your email address will not be published. Required fields are marked *


Macro Nepal Helper