Add work with card holders files (#42)

This commit is contained in:
struga 2022-07-13 14:31:16 +03:00 committed by GitHub
parent 7c2237f9c6
commit d72bb3eccd
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
13 changed files with 271 additions and 13 deletions

View File

@ -12,7 +12,7 @@
</parent> </parent>
<artifactId>adapter-flow-lib</artifactId> <artifactId>adapter-flow-lib</artifactId>
<version>0.1.12</version> <version>0.1.13</version>
<packaging>jar</packaging> <packaging>jar</packaging>
<name>adapter-flow-lib</name> <name>adapter-flow-lib</name>
@ -62,7 +62,7 @@
<spring.version>5.3.19</spring.version> <spring.version>5.3.19</spring.version>
<spring-boot-starter.version>2.6.7</spring-boot-starter.version> <spring-boot-starter.version>2.6.7</spring-boot-starter.version>
<cds-proto.version>1.66-01353ce</cds-proto.version> <cds-proto.version>1.66-01353ce</cds-proto.version>
<adapter-common-lib.version>1.1.1</adapter-common-lib.version> <adapter-common-lib.version>1.1.2</adapter-common-lib.version>
</properties> </properties>
<dependencies> <dependencies>

View File

@ -2,6 +2,7 @@ package dev.vality.adapter.flow.lib.constant;
public enum OptionFields { public enum OptionFields {
STAGE STAGE,
CARD_HOLDER_FROM_FILE,
} }

View File

@ -1,6 +1,5 @@
package dev.vality.adapter.flow.lib.converter.entry; package dev.vality.adapter.flow.lib.converter.entry;
import dev.vality.adapter.common.cds.BankCardExtractor;
import dev.vality.adapter.common.cds.CdsStorageClient; import dev.vality.adapter.common.cds.CdsStorageClient;
import dev.vality.adapter.common.cds.model.CardDataProxyModel; import dev.vality.adapter.common.cds.model.CardDataProxyModel;
import dev.vality.adapter.common.damsel.ProxyProviderPackageCreators; import dev.vality.adapter.common.damsel.ProxyProviderPackageCreators;
@ -10,6 +9,7 @@ import dev.vality.adapter.flow.lib.constant.Step;
import dev.vality.adapter.flow.lib.constant.TargetStatus; import dev.vality.adapter.flow.lib.constant.TargetStatus;
import dev.vality.adapter.flow.lib.model.*; import dev.vality.adapter.flow.lib.model.*;
import dev.vality.adapter.flow.lib.serde.TemporaryContextDeserializer; import dev.vality.adapter.flow.lib.serde.TemporaryContextDeserializer;
import dev.vality.adapter.flow.lib.service.CardDataService;
import dev.vality.adapter.flow.lib.service.IdGenerator; import dev.vality.adapter.flow.lib.service.IdGenerator;
import dev.vality.adapter.flow.lib.service.TemporaryContextService; import dev.vality.adapter.flow.lib.service.TemporaryContextService;
import dev.vality.adapter.flow.lib.utils.CallbackUrlExtractor; import dev.vality.adapter.flow.lib.utils.CallbackUrlExtractor;
@ -37,6 +37,7 @@ public class CtxToEntryModelConverter implements Converter<PaymentContext, Entry
private final IdGenerator idGenerator; private final IdGenerator idGenerator;
private final TemporaryContextService temporaryContextService; private final TemporaryContextService temporaryContextService;
private final CallbackUrlExtractor callbackUrlExtractor; private final CallbackUrlExtractor callbackUrlExtractor;
private final CardDataService cardDataService;
@Override @Override
public EntryStateModel convert(PaymentContext context) { public EntryStateModel convert(PaymentContext context) {
@ -166,9 +167,10 @@ public class CtxToEntryModelConverter implements Converter<PaymentContext, Entry
String cardToken = ProxyProviderPackageExtractors.extractBankCardToken(paymentResource); String cardToken = ProxyProviderPackageExtractors.extractBankCardToken(paymentResource);
CardData cardData = cdsStorageClient.getCardData(cardToken); CardData cardData = cdsStorageClient.getCardData(cardToken);
BankCard bankCard = ProxyProviderPackageExtractors.extractBankCard(context); BankCard bankCard = ProxyProviderPackageExtractors.extractBankCard(context);
return BankCardExtractor.initCardDataProxyModel(bankCard, cardData); return cardDataService.getCardDataProxyModel(context, cardData, bankCard);
} }
return cdsStorageClient.getCardData(context); return cardDataService.getCardDataProxyModelFromCds(context);
} }
} }

View File

@ -1,6 +1,5 @@
package dev.vality.adapter.flow.lib.converter.entry; package dev.vality.adapter.flow.lib.converter.entry;
import dev.vality.adapter.common.cds.BankCardExtractor;
import dev.vality.adapter.common.cds.CdsStorageClient; import dev.vality.adapter.common.cds.CdsStorageClient;
import dev.vality.adapter.common.cds.model.CardDataProxyModel; import dev.vality.adapter.common.cds.model.CardDataProxyModel;
import dev.vality.adapter.common.damsel.ProxyProviderPackageCreators; import dev.vality.adapter.common.damsel.ProxyProviderPackageCreators;
@ -8,6 +7,7 @@ import dev.vality.adapter.common.damsel.ProxyProviderPackageExtractors;
import dev.vality.adapter.flow.lib.constant.MetaData; import dev.vality.adapter.flow.lib.constant.MetaData;
import dev.vality.adapter.flow.lib.model.*; import dev.vality.adapter.flow.lib.model.*;
import dev.vality.adapter.flow.lib.serde.TemporaryContextDeserializer; import dev.vality.adapter.flow.lib.serde.TemporaryContextDeserializer;
import dev.vality.adapter.flow.lib.service.CardDataService;
import dev.vality.adapter.flow.lib.service.IdGenerator; import dev.vality.adapter.flow.lib.service.IdGenerator;
import dev.vality.adapter.flow.lib.service.TemporaryContextService; import dev.vality.adapter.flow.lib.service.TemporaryContextService;
import dev.vality.adapter.flow.lib.utils.CardDataUtils; import dev.vality.adapter.flow.lib.utils.CardDataUtils;
@ -34,6 +34,7 @@ public class RecCtxToEntryModelConverter implements Converter<RecurrentTokenCont
private final CdsStorageClient cdsStorageClient; private final CdsStorageClient cdsStorageClient;
private final IdGenerator idGenerator; private final IdGenerator idGenerator;
private final TemporaryContextService temporaryContextService; private final TemporaryContextService temporaryContextService;
private final CardDataService cardDataService;
@Override @Override
public EntryStateModel convert(RecurrentTokenContext context) { public EntryStateModel convert(RecurrentTokenContext context) {
@ -141,6 +142,7 @@ public class RecCtxToEntryModelConverter implements Converter<RecurrentTokenCont
String cardToken = ProxyProviderPackageExtractors.extractBankCardToken(paymentResource); String cardToken = ProxyProviderPackageExtractors.extractBankCardToken(paymentResource);
CardData cardData = cdsStorageClient.getCardData(cardToken); CardData cardData = cdsStorageClient.getCardData(cardToken);
BankCard bankCard = ProxyProviderPackageExtractors.extractBankCard(context); BankCard bankCard = ProxyProviderPackageExtractors.extractBankCard(context);
return BankCardExtractor.initCardDataProxyModel(bankCard, cardData); return cardDataService.getCardDataProxyModel(context, cardData, bankCard);
} }
} }

View File

@ -4,7 +4,6 @@ import dev.vality.adapter.flow.lib.constant.Status;
import dev.vality.adapter.flow.lib.constant.Step; import dev.vality.adapter.flow.lib.constant.Step;
import dev.vality.adapter.flow.lib.constant.TargetStatus; import dev.vality.adapter.flow.lib.constant.TargetStatus;
import dev.vality.adapter.flow.lib.flow.ResultIntentResolver; import dev.vality.adapter.flow.lib.flow.ResultIntentResolver;
import dev.vality.adapter.flow.lib.model.EntryStateModel;
import dev.vality.adapter.flow.lib.model.ExitStateModel; import dev.vality.adapter.flow.lib.model.ExitStateModel;
import dev.vality.adapter.flow.lib.service.IntentResultFactory; import dev.vality.adapter.flow.lib.service.IntentResultFactory;
import dev.vality.damsel.proxy_provider.Intent; import dev.vality.damsel.proxy_provider.Intent;

View File

@ -0,0 +1,20 @@
package dev.vality.adapter.flow.lib.service;
import dev.vality.adapter.common.cds.model.CardDataProxyModel;
import dev.vality.cds.storage.CardData;
import dev.vality.damsel.domain.BankCard;
import dev.vality.damsel.proxy_provider.PaymentContext;
import dev.vality.damsel.proxy_provider.RecurrentTokenContext;
public interface CardDataService {
CardDataProxyModel getCardDataProxyModel(RecurrentTokenContext context,
CardData cardData,
BankCard bankCard);
CardDataProxyModel getCardDataProxyModel(PaymentContext context, CardData cardData, BankCard bankCard);
CardDataProxyModel getCardDataProxyModelFromCds(PaymentContext context);
}

View File

@ -0,0 +1,35 @@
package dev.vality.adapter.flow.lib.service;
import dev.vality.adapter.common.cds.BankCardExtractor;
import dev.vality.adapter.common.cds.CdsStorageClient;
import dev.vality.adapter.common.cds.model.CardDataProxyModel;
import dev.vality.cds.storage.CardData;
import dev.vality.damsel.domain.BankCard;
import dev.vality.damsel.proxy_provider.PaymentContext;
import dev.vality.damsel.proxy_provider.RecurrentTokenContext;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
@Slf4j
@RequiredArgsConstructor
public class CardDataServiceDefaultImpl implements CardDataService {
private final CdsStorageClient cdsStorageClient;
@Override
public CardDataProxyModel getCardDataProxyModel(RecurrentTokenContext context,
CardData cardData,
BankCard bankCard) {
return BankCardExtractor.initCardDataProxyModel(bankCard, cardData);
}
@Override
public CardDataProxyModel getCardDataProxyModel(PaymentContext context, CardData cardData, BankCard bankCard) {
return BankCardExtractor.initCardDataProxyModel(bankCard, cardData);
}
@Override
public CardDataProxyModel getCardDataProxyModelFromCds(PaymentContext context) {
return cdsStorageClient.getCardData(context);
}
}

View File

@ -0,0 +1,48 @@
package dev.vality.adapter.flow.lib.service;
import dev.vality.adapter.common.cds.BankCardExtractor;
import dev.vality.adapter.common.cds.CdsStorageClient;
import dev.vality.adapter.common.cds.model.CardDataProxyModel;
import dev.vality.adapter.flow.lib.constant.OptionFields;
import dev.vality.cds.storage.CardData;
import dev.vality.damsel.domain.BankCard;
import dev.vality.damsel.proxy_provider.PaymentContext;
import dev.vality.damsel.proxy_provider.RecurrentTokenContext;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
@Slf4j
@RequiredArgsConstructor
public class CardDataServiceWithHolderNamesImpl implements CardDataService {
private final CdsStorageClient cdsStorageClient;
private final CardHolderNamesService cardHolderNamesService;
@Override
public CardDataProxyModel getCardDataProxyModel(RecurrentTokenContext context,
CardData cardData,
BankCard bankCard) {
if (context.getOptions().containsKey(OptionFields.CARD_HOLDER_FROM_FILE.name())) {
return BankCardExtractor.initCardDataProxyModel(bankCard, cardData,
cardHolderNamesService.getCardHoldersNames());
}
return BankCardExtractor.initCardDataProxyModel(bankCard, cardData);
}
@Override
public CardDataProxyModel getCardDataProxyModel(PaymentContext context, CardData cardData, BankCard bankCard) {
if (context.getOptions().containsKey(OptionFields.CARD_HOLDER_FROM_FILE.name())) {
return BankCardExtractor.initCardDataProxyModel(bankCard, cardData,
cardHolderNamesService.getCardHoldersNames());
}
return BankCardExtractor.initCardDataProxyModel(bankCard, cardData);
}
@Override
public CardDataProxyModel getCardDataProxyModelFromCds(PaymentContext context) {
if (context.getOptions().containsKey(OptionFields.CARD_HOLDER_FROM_FILE.name())) {
return cdsStorageClient.getCardDataWithListHolders(context, cardHolderNamesService.getCardHoldersNames());
}
return cdsStorageClient.getCardData(context);
}
}

View File

@ -0,0 +1,29 @@
package dev.vality.adapter.flow.lib.service;
import dev.vality.adapter.flow.lib.utils.AdapterProperties;
import lombok.Getter;
import lombok.extern.slf4j.Slf4j;
import java.io.IOException;
import java.nio.file.Files;
import java.util.List;
import java.util.stream.Collectors;
@Slf4j
public class CardHolderNamesService {
@Getter
private final List<String> cardHoldersNames;
public CardHolderNamesService(AdapterProperties properties) throws IOException {
if (properties.getCardHolderNamesFile() != null) {
this.cardHoldersNames = Files.readAllLines(properties.getCardHolderNamesFile().getFile().toPath())
.stream()
.sorted()
.collect(Collectors.toList());
} else {
this.cardHoldersNames = List.of();
}
}
}

View File

@ -2,6 +2,7 @@ package dev.vality.adapter.flow.lib.utils;
import lombok.Data; import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.core.io.Resource;
import org.springframework.validation.annotation.Validated; import org.springframework.validation.annotation.Validated;
import javax.validation.constraints.NotEmpty; import javax.validation.constraints.NotEmpty;
@ -34,4 +35,6 @@ public class AdapterProperties {
"tag" "tag"
); );
private Resource cardHolderNamesFile;
} }

View File

@ -31,7 +31,9 @@ import dev.vality.damsel.proxy_provider.ProviderProxySrv;
import lombok.RequiredArgsConstructor; import lombok.RequiredArgsConstructor;
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Configuration;
import org.springframework.core.io.ClassPathResource;
import java.io.IOException;
import java.util.List; import java.util.List;
@Configuration @Configuration
@ -82,17 +84,30 @@ public class HandlerConfig {
temporaryContextService); temporaryContextService);
} }
@Bean
public CardHolderNamesService cardHolderNamesService(AdapterProperties properties) throws IOException {
return new CardHolderNamesService(properties);
}
@Bean
public CardDataServiceWithHolderNamesImpl cardDataService(CdsStorageClient cdsStorageClient,
CardHolderNamesService cardHolderNamesService) {
return new CardDataServiceWithHolderNamesImpl(cdsStorageClient, cardHolderNamesService);
}
@Bean @Bean
public CtxToEntryModelConverter ctxToEntryModelConverter(CdsStorageClient cdsStorageClient, public CtxToEntryModelConverter ctxToEntryModelConverter(CdsStorageClient cdsStorageClient,
TemporaryContextDeserializer adapterDeserializer, TemporaryContextDeserializer adapterDeserializer,
IdGenerator idGenerator, IdGenerator idGenerator,
TemporaryContextService temporaryContextService, TemporaryContextService temporaryContextService,
CallbackUrlExtractor callbackUrlExtractor) { CallbackUrlExtractor callbackUrlExtractor,
CardDataServiceWithHolderNamesImpl cardDataService) {
return new CtxToEntryModelConverter(cdsStorageClient, return new CtxToEntryModelConverter(cdsStorageClient,
adapterDeserializer, adapterDeserializer,
idGenerator, idGenerator,
temporaryContextService, temporaryContextService,
callbackUrlExtractor); callbackUrlExtractor,
cardDataService);
} }
@Bean @Bean
@ -100,6 +115,7 @@ public class HandlerConfig {
AdapterProperties adapterProperties = new AdapterProperties(); AdapterProperties adapterProperties = new AdapterProperties();
adapterProperties.setCallbackUrl("http://localhost:8080/adapter/term_url"); adapterProperties.setCallbackUrl("http://localhost:8080/adapter/term_url");
adapterProperties.setSuccessRedirectUrl("http://localhost:8080/adapter/term_url"); adapterProperties.setSuccessRedirectUrl("http://localhost:8080/adapter/term_url");
adapterProperties.setCardHolderNamesFile(new ClassPathResource("csv/holders.csv"));
return adapterProperties; return adapterProperties;
} }
@ -107,11 +123,13 @@ public class HandlerConfig {
public RecCtxToEntryModelConverter recCtxToEntryModelConverter(CdsStorageClient cdsStorageClient, public RecCtxToEntryModelConverter recCtxToEntryModelConverter(CdsStorageClient cdsStorageClient,
TemporaryContextDeserializer adapterDeserializer, TemporaryContextDeserializer adapterDeserializer,
IdGenerator idGenerator, IdGenerator idGenerator,
TemporaryContextService temporaryContextService) { TemporaryContextService temporaryContextService,
CardDataServiceWithHolderNamesImpl cardDataService) {
return new RecCtxToEntryModelConverter(adapterDeserializer, return new RecCtxToEntryModelConverter(adapterDeserializer,
cdsStorageClient, cdsStorageClient,
idGenerator, idGenerator,
temporaryContextService); temporaryContextService,
cardDataService);
} }
@Bean @Bean

View File

@ -0,0 +1,99 @@
package dev.vality.adapter.flow.lib.service;
import dev.vality.adapter.common.cds.model.CardDataProxyModel;
import dev.vality.adapter.flow.lib.constant.OptionFields;
import dev.vality.adapter.flow.lib.flow.AbstractPaymentTest;
import dev.vality.adapter.flow.lib.flow.simple.redirect.config.SimpleRedirectWithPollingDsFlowConfig;
import dev.vality.cds.storage.CardData;
import dev.vality.damsel.domain.BankCard;
import dev.vality.damsel.domain.BankCardExpDate;
import dev.vality.damsel.proxy_provider.PaymentContext;
import dev.vality.damsel.proxy_provider.RecurrentTokenContext;
import org.apache.thrift.TException;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.MockitoAnnotations;
import org.mockito.stubbing.Answer;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.TestPropertySource;
import org.springframework.test.context.junit.jupiter.SpringExtension;
import java.util.Map;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.doAnswer;
@ExtendWith(SpringExtension.class)
@ContextConfiguration(classes = SimpleRedirectWithPollingDsFlowConfig.class)
@TestPropertySource(properties = {"server.rest.port=8083",
"error-mapping.file=classpath:fixture/errors.json"})
class CardDataServiceWithHolderNamesImplTest extends AbstractPaymentTest {
public static final String TEST_1 = "TEST 1";
@Autowired
private CardDataServiceWithHolderNamesImpl cardDataServiceWithHolderNames;
@BeforeEach
public void setUp() throws TException {
MockitoAnnotations.openMocks(this);
doAnswer((Answer<CardDataProxyModel>) invocationOnMock -> CardDataProxyModel.builder()
.cardholderName(TEST_1)
.build()).when(cdsStorageClient).getCardDataWithListHolders(any(PaymentContext.class), any());
}
@Test
void getCardDataProxyModel() {
CardDataProxyModel cardDataProxyModel = cardDataServiceWithHolderNames.getCardDataProxyModel(
new PaymentContext()
.setOptions(Map.of(OptionFields.CARD_HOLDER_FROM_FILE.name(), "true")),
new CardData(),
new BankCard()
.setToken("test")
.setExpDate(new BankCardExpDate()));
Assertions.assertEquals(TEST_1, cardDataProxyModel.getCardholderName());
cardDataProxyModel = cardDataServiceWithHolderNames.getCardDataProxyModel(
new PaymentContext()
.setOptions(Map.of()),
new CardData(),
new BankCard().setToken("test")
.setExpDate(new BankCardExpDate()));
Assertions.assertNotEquals(TEST_1, cardDataProxyModel.getCardholderName());
}
@Test
void testGetCardDataProxyModel() {
CardDataProxyModel cardDataProxyModel = cardDataServiceWithHolderNames.getCardDataProxyModel(
new RecurrentTokenContext()
.setOptions(Map.of(OptionFields.CARD_HOLDER_FROM_FILE.name(), "true")),
new CardData(),
new BankCard()
.setToken("test")
.setExpDate(new BankCardExpDate()));
Assertions.assertEquals(TEST_1, cardDataProxyModel.getCardholderName());
cardDataProxyModel = cardDataServiceWithHolderNames.getCardDataProxyModel(
new RecurrentTokenContext()
.setOptions(Map.of()),
new CardData(),
new BankCard().setToken("test")
.setExpDate(new BankCardExpDate()));
Assertions.assertNotEquals(TEST_1, cardDataProxyModel.getCardholderName());
}
@Test
void getCardDataProxyModelFromCds() {
CardDataProxyModel cardDataProxyModel = cardDataServiceWithHolderNames.getCardDataProxyModelFromCds(
new PaymentContext().setOptions(Map.of(OptionFields.CARD_HOLDER_FROM_FILE.name(), "true")));
Assertions.assertEquals(TEST_1, cardDataProxyModel.getCardholderName());
}
}

View File

@ -0,0 +1,2 @@
TEST 1
TEST 2
1 TEST 1
2 TEST 2