All Downloads are FREE. Search and download functionalities are using the official Maven repository.

de.adorsys.multibanking.hbci.HbciBanking Maven / Gradle / Ivy

The newest version!
/*
 * Copyright 2018-2019 adorsys GmbH & Co KG
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package de.adorsys.multibanking.hbci;

import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import com.fasterxml.jackson.datatype.jdk8.Jdk8Module;
import de.adorsys.multibanking.domain.BankAccount;
import de.adorsys.multibanking.domain.BankApi;
import de.adorsys.multibanking.domain.BankApiUser;
import de.adorsys.multibanking.domain.request.TransactionRequest;
import de.adorsys.multibanking.domain.response.*;
import de.adorsys.multibanking.domain.spi.OnlineBankingService;
import de.adorsys.multibanking.domain.spi.StrongCustomerAuthorisable;
import de.adorsys.multibanking.domain.transaction.*;
import de.adorsys.multibanking.hbci.job.*;
import de.adorsys.multibanking.hbci.model.HbciConsent;
import de.adorsys.multibanking.hbci.util.HbciErrorUtils;
import org.kapott.hbci.exceptions.HBCI_Exception;
import org.kapott.hbci.manager.HBCIProduct;
import org.kapott.hbci.manager.HBCIUtils;

import java.io.IOException;
import java.io.InputStream;
import java.util.Optional;

import static de.adorsys.multibanking.domain.ScaStatus.FINALISED;

public class HbciBanking implements OnlineBankingService {

    private static final ObjectMapper OBJECT_MAPPER = new ObjectMapper();

    private final HbciBpdCacheHolder hbciBpdCacheHolder;
    private final HbciScaHandler hbciScaHandler;

    private final long sysIdMaxAgeMs;
    private final long updMaxAgeMs;

    public HbciBanking(HBCIProduct hbciProduct, long sysIdMaxAgeMs, long updMaxAgeMs, long bpdMaxAgeMs) {
        this(hbciProduct, null, sysIdMaxAgeMs, updMaxAgeMs, bpdMaxAgeMs);
    }

    public HbciBanking(HBCIProduct hbciProduct, InputStream customBankConfigInput, long sysIdMaxAgeMs, long updMaxAgeMs, long bpdMaxAgeMs) {
        this.hbciBpdCacheHolder = new HbciBpdCacheHolder(bpdMaxAgeMs);
        this.hbciScaHandler = new HbciScaHandler(hbciProduct, sysIdMaxAgeMs, updMaxAgeMs, hbciBpdCacheHolder);

        try (InputStream inputStream = Optional.ofNullable(customBankConfigInput)
            .orElseGet(this::getDefaultBanksInput)) {
            HBCIUtils.refreshBLZList(inputStream);
        } catch (Exception e) {
            throw new IllegalStateException(e);
        }

        OBJECT_MAPPER.configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false);
        OBJECT_MAPPER.setSerializationInclusion(JsonInclude.Include.NON_NULL);
        OBJECT_MAPPER.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
        OBJECT_MAPPER.registerModule(new Jdk8Module());

        this.sysIdMaxAgeMs = sysIdMaxAgeMs;
        this.updMaxAgeMs = updMaxAgeMs;
    }

    private InputStream getDefaultBanksInput() {
        return Optional.ofNullable(HBCIUtils.class.getClassLoader().getResource("blz.properties"))
            .map(url -> {
                try {
                    return url.openStream();
                } catch (IOException e) {
                    throw new IllegalStateException(e);
                }
            })
            .orElseThrow(() -> new RuntimeException("blz.properties not exists in classpath"));
    }

    @Override
    public BankApi bankApi() {
        return BankApi.HBCI;
    }

    @Override
    public boolean externalBankAccountRequired() {
        return false;
    }

    @Override
    public boolean userRegistrationRequired() {
        return false;
    }

    @Override
    public BankApiUser registerUser(String userId) {
        //no registration needed
        return null;
    }

    @Override
    public void removeUser(BankApiUser bankApiUser) {
        //not needed
    }

    @Override
    public boolean bookingsCategorized() {
        return false;
    }

    @Override
    public AccountInformationResponse loadBankAccounts(TransactionRequest request) {
        HbciConsent hbciConsent = (HbciConsent) request.getBankApiConsentData();
        hbciConsent.checkUpdSysIdCache(sysIdMaxAgeMs, updMaxAgeMs);

        try {
            if (hbciConsent.getHbciTanSubmit() == null || hbciConsent.getStatus() == FINALISED) {
                HbciBpdUpdCallback hbciCallback = HbciBpdUpdCallback.createCallback(request.getBank(), hbciBpdCacheHolder);

                AccountInformationJob accountInformationJob = new AccountInformationJob(request, hbciBpdCacheHolder);
                AccountInformationResponse response = accountInformationJob.execute(hbciCallback);
                response.setBankApiConsentData(hbciCallback.updateConsentUpd(hbciConsent));
                return response;
            } else {
                TransactionAuthorisationResponse transactionAuthorisationResponse =
                    transactionAuthorisation(new TransactionAuthorisation<>(request));

                hbciConsent.afterTransactionAuthorisation(transactionAuthorisationResponse.getScaStatus());

                return (AccountInformationResponse) transactionAuthorisationResponse.getJobResponse();
            }
        } catch (HBCI_Exception e) {
            throw HbciErrorUtils.handleHbciException(e);
        }
    }

    @Override
    public TransactionsResponse loadTransactions(TransactionRequest loadTransactionsRequest) {
        HbciConsent hbciConsent = (HbciConsent) loadTransactionsRequest.getBankApiConsentData();
        hbciConsent.checkUpdSysIdCache(sysIdMaxAgeMs, updMaxAgeMs);

        try {
            if (hbciConsent.getHbciTanSubmit() == null || hbciConsent.getStatus() == FINALISED) {
                HbciBpdUpdCallback hbciCallback = HbciBpdUpdCallback.createCallback(loadTransactionsRequest.getBank(), hbciBpdCacheHolder);

                LoadTransactionsJob loadBookingsJob = new LoadTransactionsJob(loadTransactionsRequest, hbciBpdCacheHolder);
                TransactionsResponse response = loadBookingsJob.execute(hbciCallback);
                response.setBankApiConsentData(hbciCallback.updateConsentUpd(hbciConsent));
                return response;
            } else {
                TransactionAuthorisationResponse transactionAuthorisationResponse =
                    transactionAuthorisation(new TransactionAuthorisation<>(loadTransactionsRequest));

                hbciConsent.afterTransactionAuthorisation(transactionAuthorisationResponse.getScaStatus());

                return (TransactionsResponse) transactionAuthorisationResponse.getJobResponse();
            }
        } catch (HBCI_Exception e) {
            throw HbciErrorUtils.handleHbciException(e);
        }
    }

    @Override
    public StandingOrdersResponse loadStandingOrders(TransactionRequest loadStandingOrdersRequest) {
        HbciConsent hbciConsent = (HbciConsent) loadStandingOrdersRequest.getBankApiConsentData();
        hbciConsent.checkUpdSysIdCache(sysIdMaxAgeMs, updMaxAgeMs);

        try {
            if (hbciConsent.getHbciTanSubmit() == null || hbciConsent.getStatus() == FINALISED) {
                HbciBpdUpdCallback hbciCallback = HbciBpdUpdCallback.createCallback(loadStandingOrdersRequest.getBank(), hbciBpdCacheHolder);

                LoadStandingOrdersJob loadStandingOrdersJob = new LoadStandingOrdersJob(loadStandingOrdersRequest, hbciBpdCacheHolder);
                StandingOrdersResponse response = loadStandingOrdersJob.execute(hbciCallback);
                response.setBankApiConsentData(hbciCallback.updateConsentUpd(hbciConsent));
                return response;
            } else {
                TransactionAuthorisationResponse transactionAuthorisationResponse =
                    transactionAuthorisation(new TransactionAuthorisation<>(loadStandingOrdersRequest));

                hbciConsent.afterTransactionAuthorisation(transactionAuthorisationResponse.getScaStatus());

                return (StandingOrdersResponse) transactionAuthorisationResponse.getJobResponse();
            }
        } catch (HBCI_Exception e) {
            throw HbciErrorUtils.handleHbciException(e);
        }
    }

    @Override
    public LoadBalancesResponse loadBalances(TransactionRequest request) {
        HbciConsent hbciConsent = (HbciConsent) request.getBankApiConsentData();
        hbciConsent.checkUpdSysIdCache(sysIdMaxAgeMs, updMaxAgeMs);

        try {
            if (hbciConsent.getHbciTanSubmit() == null || hbciConsent.getStatus() == FINALISED) {
                HbciBpdUpdCallback hbciCallback = HbciBpdUpdCallback.createCallback(request.getBank(), hbciBpdCacheHolder);

                LoadBalancesJob loadBalancesJob = new LoadBalancesJob(request, hbciBpdCacheHolder);
                LoadBalancesResponse response = loadBalancesJob.execute(hbciCallback);
                response.setBankApiConsentData(hbciCallback.updateConsentUpd(hbciConsent));
                return response;
            } else {
                TransactionAuthorisationResponse transactionAuthorisationResponse =
                    transactionAuthorisation(new TransactionAuthorisation<>(request));

                hbciConsent.afterTransactionAuthorisation(transactionAuthorisationResponse.getScaStatus());

                return (LoadBalancesResponse) transactionAuthorisationResponse.getJobResponse();
            }
        } catch (HBCI_Exception e) {
            throw HbciErrorUtils.handleHbciException(e);
        }
    }

    @Override
    public PaymentResponse executePayment(TransactionRequest request) {
        HbciConsent hbciConsent = (HbciConsent) request.getBankApiConsentData();
        hbciConsent.checkUpdSysIdCache(sysIdMaxAgeMs, updMaxAgeMs);

        try {
            if (hbciConsent.getHbciTanSubmit() == null || hbciConsent.getStatus() == FINALISED) {
                HbciBpdUpdCallback hbciCallback = HbciBpdUpdCallback.createCallback(request.getBank(), hbciBpdCacheHolder);

                ScaAwareJob paymentJob = createScaJob(request);

                PaymentResponse response = paymentJob.execute(hbciCallback);
                response.setBankApiConsentData(hbciCallback.updateConsentUpd(hbciConsent));

                return response;
            } else {
                TransactionAuthorisationResponse transactionAuthorisationResponse =
                    transactionAuthorisation(new TransactionAuthorisation<>(request));

                hbciConsent.afterTransactionAuthorisation(transactionAuthorisationResponse.getScaStatus());

                return (PaymentResponse) transactionAuthorisationResponse.getJobResponse();
            }
        } catch (HBCI_Exception e) {
            throw HbciErrorUtils.handleHbciException(e);
        }
    }

    @Override
    public StrongCustomerAuthorisable getStrongCustomerAuthorisation() {
        return hbciScaHandler;
    }

    private  TransactionAuthorisationResponse transactionAuthorisation(TransactionAuthorisation transactionAuthorisation) {
        try {
            ScaAwareJob scaJob = createScaJob(transactionAuthorisation.getOriginTransactionRequest());

            TransactionAuthorisationJob transactionAuthorisationJob = new TransactionAuthorisationJob<>(scaJob, transactionAuthorisation);
            TransactionAuthorisationResponse response = transactionAuthorisationJob.execute();

            HbciConsent hbciConsent = ((HbciConsent) transactionAuthorisation.getOriginTransactionRequest().getBankApiConsentData());
            hbciConsent.afterTransactionAuthorisation(response.getScaStatus());

            return response;
        } catch (HBCI_Exception e) {
            throw HbciErrorUtils.handleHbciException(e);
        }
    }

    @Override
    public void removeBankAccount(BankAccount bankAccount, BankApiUser bankApiUser) {
        //not needed
    }

    @Override
    public boolean bankSupported(String bankCode) {
        return Optional.ofNullable(HBCIUtils.getBankInfo(bankCode))
            .map(bankInfo -> bankInfo.getPinTanVersion() != null)
            .orElse(false);
    }

    @SuppressWarnings("unchecked")
    private  ScaAwareJob createScaJob(TransactionRequest transactionRequest) {
        switch (transactionRequest.getTransaction().getTransactionType()) {
            case SINGLE_PAYMENT:
            case FUTURE_SINGLE_PAYMENT:
            case INSTANT_PAYMENT:
                return (ScaAwareJob) new SinglePaymentJob((TransactionRequest) transactionRequest, hbciBpdCacheHolder);
            case TRANSFER_PAYMENT:
                return (ScaAwareJob) new TransferJob((TransactionRequest) transactionRequest, hbciBpdCacheHolder);
            case FOREIGN_PAYMENT:
                return (ScaAwareJob) new ForeignPaymentJob((TransactionRequest) transactionRequest, hbciBpdCacheHolder);
            case BULK_PAYMENT:
            case FUTURE_BULK_PAYMENT:
                return (ScaAwareJob) new BulkPaymentJob((TransactionRequest) transactionRequest, hbciBpdCacheHolder);
            case STANDING_ORDER:
                return (ScaAwareJob) new PeriodicPaymentJob((TransactionRequest) transactionRequest, hbciBpdCacheHolder);
            case RAW_SEPA:
                return (ScaAwareJob) new RawSepaJob((TransactionRequest) transactionRequest, hbciBpdCacheHolder);
            case FUTURE_SINGLE_PAYMENT_DELETE:
                return (ScaAwareJob) new DeleteFutureSinglePaymentJob((TransactionRequest) transactionRequest, hbciBpdCacheHolder);
            case FUTURE_BULK_PAYMENT_DELETE:
                return (ScaAwareJob) new DeleteFutureBulkPaymentJob((TransactionRequest) transactionRequest, hbciBpdCacheHolder);
            case STANDING_ORDER_DELETE:
                return (ScaAwareJob) new DeleteStandingOrderJob((TransactionRequest) transactionRequest, hbciBpdCacheHolder);
            case TAN_REQUEST:
                return (ScaAwareJob) new TanRequestJob((TransactionRequest) transactionRequest, hbciBpdCacheHolder);
            case LOAD_BANKACCOUNTS:
                return (ScaAwareJob) new AccountInformationJob((TransactionRequest) transactionRequest, hbciBpdCacheHolder);
            case LOAD_BALANCES:
                return (ScaAwareJob) new LoadBalancesJob((TransactionRequest) transactionRequest, hbciBpdCacheHolder);
            case LOAD_TRANSACTIONS:
                return (ScaAwareJob) new LoadTransactionsJob((TransactionRequest) transactionRequest, hbciBpdCacheHolder);
            case LOAD_STANDING_ORDERS:
                return (ScaAwareJob) new LoadStandingOrdersJob((TransactionRequest) transactionRequest, hbciBpdCacheHolder);
            case GET_PAYMENT_STATUS:
                return (ScaAwareJob) new InstantPaymentStatusJob((TransactionRequest) transactionRequest, hbciBpdCacheHolder);
            default:
                throw new IllegalArgumentException("invalid transaction type " + transactionRequest.getTransaction().getTransactionType());
        }
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy