feat: HelloAsso payment
This commit is contained in:
@@ -0,0 +1,161 @@
|
||||
package fr.titionfire.ffsaf.domain.service;
|
||||
|
||||
import fr.titionfire.ffsaf.data.model.CheckoutModel;
|
||||
import fr.titionfire.ffsaf.data.model.LogModel;
|
||||
import fr.titionfire.ffsaf.data.repository.CheckoutRepository;
|
||||
import fr.titionfire.ffsaf.data.repository.LicenceRepository;
|
||||
import fr.titionfire.ffsaf.rest.client.HelloAssoService;
|
||||
import fr.titionfire.ffsaf.rest.client.dto.CheckoutIntentsRequest;
|
||||
import fr.titionfire.ffsaf.rest.client.dto.CheckoutIntentsResponse;
|
||||
import fr.titionfire.ffsaf.rest.client.dto.CheckoutMetadata;
|
||||
import fr.titionfire.ffsaf.rest.exception.DInternalError;
|
||||
import fr.titionfire.ffsaf.utils.SecurityCtx;
|
||||
import fr.titionfire.ffsaf.utils.Utils;
|
||||
import io.quarkus.hibernate.reactive.panache.Panache;
|
||||
import io.quarkus.hibernate.reactive.panache.common.WithSession;
|
||||
import io.smallrye.mutiny.Uni;
|
||||
import jakarta.enterprise.context.ApplicationScoped;
|
||||
import jakarta.inject.Inject;
|
||||
import jakarta.ws.rs.core.Response;
|
||||
import org.eclipse.microprofile.config.inject.ConfigProperty;
|
||||
import org.eclipse.microprofile.rest.client.inject.RestClient;
|
||||
import org.hibernate.reactive.mutiny.Mutiny;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@WithSession
|
||||
@ApplicationScoped
|
||||
public class CheckoutService {
|
||||
|
||||
@Inject
|
||||
CheckoutRepository repository;
|
||||
|
||||
@Inject
|
||||
LicenceRepository licenceRepository;
|
||||
|
||||
@Inject
|
||||
MembreService membreService;
|
||||
|
||||
@Inject
|
||||
LicenceService licenceService;
|
||||
|
||||
@Inject
|
||||
LoggerService ls;
|
||||
|
||||
@RestClient
|
||||
HelloAssoService helloAssoService;
|
||||
|
||||
@ConfigProperty(name = "frontRootUrl")
|
||||
String frontRootUrl;
|
||||
|
||||
@ConfigProperty(name = "unitLicencePrice")
|
||||
int unitLicencePrice;
|
||||
|
||||
@ConfigProperty(name = "helloasso.organizationSlug")
|
||||
String organizationSlug;
|
||||
|
||||
public Uni<Boolean> canDeleteLicence(long id) {
|
||||
return repository.find("?1 IN licenseIds", id).count().map(count -> count == 0);
|
||||
}
|
||||
|
||||
public Uni<String> create(List<Long> ids, SecurityCtx securityCtx) {
|
||||
return membreService.getByAccountId(securityCtx.getSubject())
|
||||
.call(membreModel -> Mutiny.fetch(membreModel.getClub()))
|
||||
.chain(membreModel -> {
|
||||
CheckoutModel model = new CheckoutModel();
|
||||
model.setMembre(membreModel);
|
||||
model.setLicenseIds(ids);
|
||||
model.setPaymentStatus(CheckoutModel.PaymentStatus.UNKNOW);
|
||||
|
||||
return Panache.withTransaction(() -> repository.persist(model));
|
||||
})
|
||||
.chain(checkoutModel -> {
|
||||
CheckoutIntentsRequest request = new CheckoutIntentsRequest();
|
||||
request.setTotalAmount(unitLicencePrice * checkoutModel.getLicenseIds().size());
|
||||
request.setInitialAmount(unitLicencePrice * checkoutModel.getLicenseIds().size());
|
||||
request.setItemName("%d licences %d-%d pour %s".formatted(checkoutModel.getLicenseIds().size(),
|
||||
Utils.getSaison(), Utils.getSaison() + 1, checkoutModel.getMembre().getClub().getName()));
|
||||
request.setBackUrl(frontRootUrl + "/club/member/pay");
|
||||
request.setErrorUrl(frontRootUrl + "/club/member/pay/error");
|
||||
request.setReturnUrl(frontRootUrl + "/club/member/pay/return");
|
||||
request.setContainsDonation(false);
|
||||
request.setPayer(new CheckoutIntentsRequest.Payer(checkoutModel.getMembre().getFname(),
|
||||
checkoutModel.getMembre().getLname(), checkoutModel.getMembre().getEmail()));
|
||||
request.setMetadata(new CheckoutMetadata(checkoutModel.getId()));
|
||||
|
||||
return helloAssoService.checkout(organizationSlug, request)
|
||||
.call(response -> {
|
||||
checkoutModel.setCheckoutId(response.getId());
|
||||
return Panache.withTransaction(() -> repository.persist(checkoutModel));
|
||||
});
|
||||
})
|
||||
.onFailure().transform(t -> new DInternalError(t.getMessage()))
|
||||
.map(CheckoutIntentsResponse::getRedirectUrl);
|
||||
}
|
||||
|
||||
public Uni<Response> paymentStatusChange(String state, CheckoutMetadata metadata) {
|
||||
return repository.findById(metadata.getCheckoutDBId())
|
||||
.chain(checkoutModel -> {
|
||||
CheckoutModel.PaymentStatus newStatus = CheckoutModel.PaymentStatus.valueOf(state.toUpperCase());
|
||||
|
||||
Uni<?> uni = Uni.createFrom().nullItem();
|
||||
|
||||
if (checkoutModel.getPaymentStatus().equals(newStatus))
|
||||
return uni;
|
||||
|
||||
if (newStatus.equals(CheckoutModel.PaymentStatus.AUTHORIZED)) {
|
||||
for (Long id : checkoutModel.getLicenseIds()) {
|
||||
uni = uni.chain(__ -> licenceRepository.findById(id)
|
||||
.onFailure().recoverWithNull()
|
||||
.call(licenceModel -> {
|
||||
if (licenceModel == null) {
|
||||
ls.logAnonymous(LogModel.ActionType.UPDATE, LogModel.ObjectType.Licence,
|
||||
"Fail to save payment for licence (checkout n°" + checkoutModel.getCheckoutId() + ")",
|
||||
"", id);
|
||||
return Uni.createFrom().nullItem();
|
||||
}
|
||||
|
||||
ls.logUpdateAnonymous("Paiement de la licence", licenceModel);
|
||||
licenceModel.setPay(true);
|
||||
|
||||
if (licenceModel.getCertificate() != null && licenceModel.getCertificate()
|
||||
.length() > 3) {
|
||||
if (!licenceModel.isValidate())
|
||||
ls.logUpdateAnonymous("Validation automatique de la licence",
|
||||
licenceModel);
|
||||
return licenceService.validateLicences(licenceModel);
|
||||
} else {
|
||||
return Panache.withTransaction(
|
||||
() -> licenceRepository.persist(licenceModel));
|
||||
}
|
||||
}));
|
||||
}
|
||||
} else if (checkoutModel.getPaymentStatus().equals(CheckoutModel.PaymentStatus.AUTHORIZED)) {
|
||||
for (Long id : checkoutModel.getLicenseIds()) {
|
||||
uni = uni.chain(__ -> licenceRepository.findById(id)
|
||||
.onFailure().recoverWithNull()
|
||||
.call(licenceModel -> {
|
||||
if (licenceModel == null)
|
||||
return Uni.createFrom().nullItem();
|
||||
|
||||
ls.logUpdateAnonymous("Annulation automatique du paiement de la licence",
|
||||
licenceModel);
|
||||
licenceModel.setPay(false);
|
||||
if (licenceModel.isValidate())
|
||||
ls.logUpdateAnonymous(
|
||||
"Annulation automatique de la validation de la licence",
|
||||
licenceModel);
|
||||
licenceModel.setValidate(false);
|
||||
return Panache.withTransaction(() -> licenceRepository.persist(licenceModel));
|
||||
}));
|
||||
}
|
||||
}
|
||||
uni = uni.call(__ -> ls.append());
|
||||
|
||||
checkoutModel.setPaymentStatus(newStatus);
|
||||
return uni.chain(__ -> Panache.withTransaction(() -> repository.persist(checkoutModel)));
|
||||
})
|
||||
.onFailure().invoke(Throwable::printStackTrace)
|
||||
.map(__ -> Response.ok().build());
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user