package ru.soune.nocopy.service.payment; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import ru.soune.ReferralService; import ru.soune.nocopy.entity.payment.Payment; import ru.soune.nocopy.entity.payment.PaymentOperationType; import ru.soune.nocopy.entity.payment.PaymentStatus; import ru.soune.nocopy.entity.tarif.Tariff; import ru.soune.nocopy.entity.tarif.TariffInfo; import ru.soune.nocopy.entity.tarif.TariffStatus; import ru.soune.nocopy.entity.user.User; import ru.soune.nocopy.exception.PaymentNotFoundException; import ru.soune.nocopy.exception.TariffNotFoundException; import ru.soune.nocopy.exception.UserNotFoundException; import ru.soune.nocopy.repository.PaymentRepository; import ru.soune.nocopy.repository.TariffInfoRepository; import ru.soune.nocopy.repository.TariffRepository; import ru.soune.nocopy.repository.UserRepository; import ru.soune.nocopy.service.tariff.TariffInfoService; import java.time.LocalDateTime; import java.util.List; import java.util.Map; @Service @RequiredArgsConstructor @Slf4j public class PaymentService { private final PaymentRepository paymentRepository; private final UserRepository userRepository; private final TariffRepository tariffRepository; private final TariffInfoRepository tariffInfoRepository; private final TariffInfoService tariffInfoService; private final ReferralService referralService; @Transactional public Payment createPayment(String email, Long tariffId, String operationType, String paymentUuid) { User user = userRepository.findByEmail(email); if (user == null) { throw new UserNotFoundException(email); } Tariff tariff = tariffRepository.findById(tariffId).orElseThrow(() -> new TariffNotFoundException("Tariff not found")); Payment payment = new Payment(); payment.setStatus(PaymentStatus.PENDING); payment.setAmount(tariff.getPrice()); payment.setOperationType(PaymentOperationType.valueOf(operationType)); payment.setUser(user); payment.setTariff(tariff); payment.setPaymentUuid(paymentUuid); return paymentRepository.save(payment); } @Transactional public void handlePaymentNotification(Map notification) { String eventType = (String) notification.get("event"); Map object = (Map) notification.get("object"); String paymentUuid = (String) object.get("id"); Payment payment = paymentRepository.findByPaymentUuid(paymentUuid) .orElseThrow(() -> new PaymentNotFoundException("Payment not found")); if ("payment.succeeded".equals(eventType)) { Tariff tariff = payment.getTariff(); double price = tariff.getPrice(); int intPrice = (int) Math.round(price); payment.setStatus(PaymentStatus.SUCCEEDED); payment.setCancellationReason(null); activateTariffForUser(payment.getUser(), tariff); referralService.onUserAccountRefill(payment.getUser().getId(), intPrice); } else if ("payment.canceled".equals(eventType)) { payment.setStatus(PaymentStatus.CANCELED); Map cancellationDetails = (Map) object.get("cancellation_details"); if (cancellationDetails != null) { String reason = (String) cancellationDetails.get("reason"); payment.setCancellationReason(reason); } } else if ("payment.waiting_for_capture".equals(eventType)) { payment.setStatus(PaymentStatus.WAITING); payment.setCancellationReason(null); } else { payment.setStatus(PaymentStatus.FAILED); Map cancellationDetails = (Map) object.get("cancellation_details"); if (cancellationDetails != null) { String reason = (String) cancellationDetails.get("reason"); payment.setCancellationReason(reason); } } paymentRepository.save(payment); } public List userPayments(String email) { User user = userRepository.findByEmail(email); if (user == null) { throw new UserNotFoundException("User not found"); } return paymentRepository.findByUserId(user.getId()); } public Payment paymentInfo(String uuid) { return paymentRepository.findByPaymentUuid(uuid).orElseThrow(() -> new PaymentNotFoundException("Payment not found")); } private void activateTariffForUser(User user, Tariff tariff) { String type = tariff.getType(); if (type.equals("token")) { TariffInfo activeTariffInfo = user.getActiveTariffInfo(); Integer tokens = activeTariffInfo.getTokens() + tariff.getTokens(); activeTariffInfo.setTokens(tokens); tariffInfoRepository.save(activeTariffInfo); } else { TariffInfo tariffInfo = new TariffInfo(); tariffInfo.setStatus(TariffStatus.ACTIVE); tariffInfo.setStartTariff(LocalDateTime.now()); tariffInfo.setEndTariff(LocalDateTime.now().plusMonths(1)); tariffInfo.setTokens(tariff.getTokens()); tariffInfo.setTariff(tariff); tariffInfoService.linkUserTariffInfo(user, tariffInfoService.addTariffInfo(tariffInfo)); } } }