import java.util.*; import java.util.concurrent.*; import java.util.concurrent.atomic.AtomicLong;
public class PaymentSystem { public enum PaymentStatus { PENDING, PROCESSING, COMPLETED, FAILED, CANCELLED, REFUNDED } public enum PaymentType { CREDIT_CARD, DEBIT_CARD, BANK_TRANSFER, DIGITAL_WALLET, CRYPTO } public static class PaymentTransaction { private String transactionId; private String userId; private BigDecimal amount; private PaymentType paymentType; private PaymentStatus status; private String merchantId; private String orderId; private Date createdAt; private Date updatedAt; private String errorMessage; public PaymentTransaction(String userId, BigDecimal amount, PaymentType paymentType, String merchantId) { this.transactionId = UUID.randomUUID().toString(); this.userId = userId; this.amount = amount; this.paymentType = paymentType; this.merchantId = merchantId; this.status = PaymentStatus.PENDING; this.createdAt = new Date(); this.updatedAt = new Date(); } } public static class PaymentProcessor { private final ExecutorService executor; private final Map<PaymentType, PaymentGateway> gateways; private final Queue<PaymentTransaction> queue; private final Map<String, PaymentTransaction> transactions; private final AtomicLong counter = new AtomicLong(0); public PaymentProcessor() { this.executor = Executors.newFixedThreadPool(10); this.gateways = new EnumMap<>(PaymentType.class); this.queue = new ConcurrentLinkedQueue<>(); this.transactions = new ConcurrentHashMap<>(); gateways.put(PaymentType.CREDIT_CARD, new CreditCardGateway()); gateways.put(PaymentType.DEBIT_CARD, new DebitCardGateway()); gateways.put(PaymentType.BANK_TRANSFER, new BankTransferGateway()); gateways.put(PaymentType.DIGITAL_WALLET, new DigitalWalletGateway()); startProcessing(); } public String createPayment(String userId, BigDecimal amount, PaymentType paymentType, String merchantId) { PaymentTransaction transaction = new PaymentTransaction(userId, amount, paymentType, merchantId); transactions.put(transaction.transactionId, transaction); queue.offer(transaction); return transaction.transactionId; } private void startProcessing() { for (int i = 0; i < 5; i++) { executor.submit(() -> { while (true) { try { PaymentTransaction transaction = queue.poll(); if (transaction != null) { processPayment(transaction); } else { Thread.sleep(100); } } catch (Exception e) { } } }); } } private void processPayment(PaymentTransaction transaction) { try { transaction.status = PaymentStatus.PROCESSING; transaction.updatedAt = new Date(); PaymentGateway gateway = gateways.get(transaction.paymentType); if (gateway == null) { throw new RuntimeException("Unsupported payment type: " + transaction.paymentType); } PaymentResult result = gateway.processPayment( transaction.userId, transaction.amount, transaction.merchantId ); if (result.isSuccess()) { transaction.status = PaymentStatus.COMPLETED; transaction.updatedAt = new Date(); PaymentEvent event = new PaymentEvent( transaction.transactionId, PaymentEvent.EventType.PAYMENT_SUCCESS, result.getTransactionId() ); eventBus.publish(event); } else { transaction.status = PaymentStatus.FAILED; transaction.errorMessage = result.getErrorMessage(); transaction.updatedAt = new Date(); PaymentEvent event = new PaymentEvent( transaction.transactionId, PaymentEvent.EventType.PAYMENT_FAILED, result.getErrorMessage() ); eventBus.publish(event); } } catch (Exception e) { transaction.status = PaymentStatus.FAILED; transaction.errorMessage = e.getMessage(); transaction.updatedAt = new Date(); } } public PaymentTransaction getTransaction(String transactionId) { return transactions.get(transactionId); } public List<PaymentTransaction> getUserTransactions(String userId) { return transactions.values().stream() .filter(t -> t.userId.equals(userId)) .sorted((a, b) -> b.updatedAt.compareTo(a.updatedAt)) .collect(Collectors.toList()); } } public interface PaymentGateway { PaymentResult processPayment(String userId, BigDecimal amount, String merchantId); } public static class PaymentResult { private final boolean success; private final String transactionId; private final String errorMessage; private final Date processedAt; public PaymentResult(boolean success, String transactionId, String errorMessage) { this.success = success; this.transactionId = transactionId; this.errorMessage = errorMessage; this.processedAt = new Date(); } public boolean isSuccess() { return success; } public String getTransactionId() { return transactionId; } public String getErrorMessage() { return errorMessage; } public Date getProcessedAt() { return processedAt; } } public static class CreditCardGateway implements PaymentGateway { @Override public PaymentResult processPayment(String userId, BigDecimal amount, String merchantId) { try { if (!validateCreditCard(userId)) { return new PaymentResult(false, null, "Invalid credit card information"); } if (!checkCreditLimit(userId, amount)) { return new PaymentResult(false, null, "Insufficient credit limit"); } String transactionId = deductCredit(userId, amount, merchantId); return new PaymentResult(true, transactionId, null); } catch (Exception e) { return new PaymentResult(false, null, e.getMessage()); } } private boolean validateCreditCard(String userId) { return true; } private boolean checkCreditLimit(String userId, BigDecimal amount) { return true; } private String deductCredit(String userId, BigDecimal amount, String merchantId) { return UUID.randomUUID().toString(); } } public static class EventBus { private final Map<PaymentEvent.EventType, List<Consumer<PaymentEvent>>> listeners = new ConcurrentHashMap<>(); public void subscribe(PaymentEvent.EventType eventType, Consumer<PaymentEvent> listener) { listeners.computeIfAbsent(eventType, k -> new CopyOnWriteArrayList<>()).add(listener); } public void publish(PaymentEvent event) { List<Consumer<PaymentEvent>> eventListeners = listeners.get(event.eventType); if (eventListeners != null) { eventListeners.forEach(listener -> { try { listener.accept(event); } catch (Exception e) { } }); } } } public static class PaymentEvent { public enum EventType { PAYMENT_SUCCESS, PAYMENT_FAILED, PAYMENT_CANCELLED, REFUND_SUCCESS } private final String transactionId; private final EventType eventType; private final String message; private final Date timestamp; public PaymentEvent(String transactionId, EventType eventType, String message) { this.transactionId = transactionId; this.eventType = eventType; this.message = message; this.timestamp = new Date(); } } public static class RiskManagement { private final List<RiskRule> rules; public RiskManagement() { this.rules = Arrays.asList( new TransactionAmountRule(), new FrequencyRule(), new GeographicRule(), new DeviceFingerprintRule() ); } public RiskAssessment assessRisk(PaymentTransaction transaction) { RiskAssessment assessment = new RiskAssessment(); for (RiskRule rule : rules) { RiskResult result = rule.evaluate(transaction); assessment.addResult(result); if (result.isBlock()) { assessment.setBlocked(true); assessment.setReason(result.getMessage()); break; } } return assessment; } } public interface RiskRule { RiskResult evaluate(PaymentTransaction transaction); } public static class RiskResult { private final boolean block; private final String message; private final RiskLevel level; public RiskResult(boolean block, String message, RiskLevel level) { this.block = block; this.message = message; this.level = level; } public boolean isBlock() { return block; } public String getMessage() { return message; } public RiskLevel getLevel() { return level; } } public enum RiskLevel { LOW, MEDIUM, HIGH, CRITICAL } public static class RiskAssessment { private boolean blocked; private String reason; private List<RiskResult> results; public RiskAssessment() { this.results = new ArrayList<>(); } public void addResult(RiskResult result) { results.add(result); } public void setBlocked(boolean blocked) { this.blocked = blocked; } public void setReason(String reason) { this.reason = reason; } public boolean isBlocked() { return blocked; } public String getReason() { return reason; } public List<RiskResult> getResults() { return results; } } public static class TransactionAmountRule implements RiskRule { @Override public RiskResult evaluate(PaymentTransaction transaction) { if (transaction.amount.compareTo(new BigDecimal("10000")) > 0) { return new RiskResult(true, "Transaction amount exceeds limit", RiskLevel.CRITICAL); } return new RiskResult(false, "Amount within limits", RiskLevel.LOW); } } public static class FrequencyRule implements RiskRule { @Override public RiskResult evaluate(PaymentTransaction transaction) { return new RiskResult(false, "Frequency check passed", RiskLevel.LOW); } } public static class GeographicRule implements RiskRule { @Override public RiskResult evaluate(PaymentTransaction transaction) { return new RiskResult(false, "Geographic check passed", RiskLevel.LOW); } } public static class DeviceFingerprintRule implements RiskRule { @Override public RiskResult evaluate(PaymentTransaction transaction) { return new RiskResult(false, "Device fingerprint check passed", RiskLevel.LOW); } } }
|