PaymentGateway.java
package com.rbctcsworld.ecommerce.payment;
import java.math.BigDecimal;
/**
* A payment provider. app.payment.provider selects it: "mock" (default, deterministic test cards) or
* "stripe" (Stripe PaymentIntents and Refunds API, test mode or stripe-mock).
*/
public interface PaymentGateway {
/** Charges the card. Declines come back as a result; an unreachable provider throws PaymentUnavailableException. */
GatewayResult charge(Long orderId, String cardNumber, BigDecimal amount);
/**
* Turns a card into the provider's own token for later payments, so the card number never has to be kept.
* Returns null when the provider cannot use this card (Stripe test mode: only its test cards).
*/
String tokenize(String cardNumber);
/** Charges a token made by {@link #tokenize}. Same results as {@link #charge}. */
GatewayResult chargeToken(Long orderId, String token, BigDecimal amount);
/**
* Refunds (part of) an earlier successful charge, identified by the provider's reference.
* refundNumber = 1 for the first refund of the order, 2 for the second...: part of the idempotency key,
* so a retried refund is not paid twice while a second, real refund still goes through.
*/
GatewayResult refund(Long orderId, String chargeReference, BigDecimal amount, int refundNumber);
/** Short name stored with every transaction: mock | stripe. */
String name();
/** reference = the provider's id (Stripe: pi_... / re_...); kept for refunds and support, never shown to customers. */
record GatewayResult(boolean approved, String reason, String reference) {
public static GatewayResult ok(String reference) {
return new GatewayResult(true, null, reference);
}
public static GatewayResult decline(String reason, String reference) {
return new GatewayResult(false, reason, reference);
}
}
}