soutenance de stage
Ingénieur études et développement - progiciel monétique
NGUYEN Clément - INFO5
2023
> Entreprise : Sopra Banking Software
> Objectif : Développement de nouvelles fonctionnalités sur des progiciels monétique
> Participation au développement de RTSI (Real-Time Systems Inferface)
INTRODUCTION
PLAN
- Filiale du groupe Sopra Steria
- Spécialisée dans le secteur bancaire
- Agence "Cards" : département R&D monétique
- Monétique : Front and Back office
1. SOPRA banking software
Contexte RTSI (Real-Time Systems Interface) :
Visa a crée un système en ligne nommée VROL
> permet d'échanger des documents liés à des litiges
Application RTSI
> permet de déclarer des litiges auprès de VROL
Temps de développement : 2 mois
2.1. Présentation de RTSI
Text
2.2. architecture du service
1. Organisation de l'équipe
2. Les technologies utilisées
3. l'environnement de travail
Méthode Agile
- Agile Manager
- Scrum Master
- Product Owner
- Developers
1) Sprint planning
>> Product backlog
>> Grooming
3.1. l'organisation de l'équipe
2) Sprint
>> 2 semaines
3) Sprint Review
>> Démonstration
4) Rétrospective
>> Ce qu'on a aimé
>> Ce qu'on a appris
>> Ce qui a manqué
>> Les actions à faire
3.2. les technologies utilisées
Architecture en microservices
> Spring boot : framework pour applications Java
- Automatise la configuration
- Automatise la mise en place d'applications
- Gestion de dépendances
> On gagne en productivité
3.2. les technologies utilisées
Programmation réactive
> Approche de programmation pour gérer les flux de données et les événements.
> Réagit rapidement et de manière asynchrone aux changements.
Reactor
> Bibliothèque de programmation réactive.
> Gère les flux de données et les événements de manière asynchrone.
1. Processus de RTSI
2. Développement avec un scénario d'exemple
3. Les tests
4. le développement de rtsi
4. 1. processus de rtsi
4.1. processus de rtsi
Scénario d'exemple :
Appel n°1 : SubmitTranInquiry
> Récupérer informations de la transaction
Appel n°2 : InitiateDisputeFromTransaction
> Initialisation du dossier de litige
Si FraudRptInd = "NotExist"
> Exception
- FraudRptInd
4.2. Le développement
Etape 1 : Configuration du JMS pour se connecter à ActiveMQ
@Configuration
@EnableJms
public class JmsConfiguration implements JmsListenerConfigurer {
private final ActiveMQProperties activeMqProperties;
public JmsConfiguration(ActiveMQProperties activeMqProperties) {
this.activeMqProperties = activeMqProperties;
}
@Bean
public ConnectionFactory activeMQConnectionFactory() {
ActiveMQConnectionFactory connectionFactory =
new ActiveMQConnectionFactory(activeMqProperties.credentials().userId(),
activeMqProperties.credentials().password(),
activeMqProperties.brokerUrl());
connectionFactory.setTrustedPackages(List.of(DXP_BASE_PACKAGE));
return connectionFactory;
}
}
> communication entre applications
4.2. Le développement
Etape 2 : Configuration du clientDto
public record TranInquiryRequestClientDto(
@JsonProperty("RequestHeader")
RequestHeaderClientDto requestHeader,
@Valid
@JsonProperty("RequestData")
RequestDataClientDto requestData
) {}
public record RequestHeaderClientDto(
@JsonProperty("User")
UserClientDto user,
@JsonProperty("MemberRole")
MemberRole memberRole
) {}
public record RequestDataClientDto(
@JsonProperty("TransactionID")
String transactionID
) {}
> création de l'objet de la requête pour appeler /SubmitTranInquiry
user, memberRole et transactionID nécessaires pour appeler l'API
4.2. Le développement
Etape 3 : Création du mapper
public static TranInquiryRequestClientDto toRequestClientDto(String input, CompanyCodesProperties properties) {
CompanyCodesProperties.CompanyCodeProperties property = getCompanyCodeFromProperties(input, properties);
return new TranInquiryRequestClientDto(
new RequestHeaderClientDto(new UserClientDto(property.userId(),
property.userType()),
toMemberRole(property)),
new RequestDataClientDto(getFieldValue("IdTransactionUniq", input))
);
}
> convertit des données d'un format en un autre
<message>
<entete>
<codReg>13001</codReg>
<codMessage>string</codMessage>
</entete>
<body>
<refIntOperation>string</refIntOperation>
<idTransactionUniq>1010000</idTransactionUniq>
<mntImpayeComp>4934200</mntImpayeComp>
<codDevMntBrutComp>840</codDevMntBrutComp>
</body>
</message>
transactionID = 1010000
4.2. Le développement
Etape 4 : Création du consumer
> écouter et consommer les messages provenant de la queue
@JmsListener(destination = "${queues.queueChargebackRequest}")
public void processIssuerMessage(String message) {
Mono.just(message)
.doOnSubscribe(m -> logger.debug("Received message from Issuer: {}", message))
.filter(xmlMessageService::isMessageValid)
.flatMap(visaService::processVisaStages)
.flatMap(r -> sendResponse(toXml(r)))
.onErrorResume(Exception.class, e -> sendResponse(toXml(toResponse(message, emptyList(), e))))
.subscribe();
}
isMessageValid() : Vérification du message XML
processVisaStages() : Traitement du message
sendResponse() : Envoie d'un message retour dans une autre queue
4.2. Le développement
Etape 5 : Traitement du message (scénario d'exemple)
public Mono<Response> processVisaStages(String issuerMsg) {
Map<VisaApi, Object> mapResponses = new EnumMap<>(VisaApi.class);
List<StepDone> steps = new ArrayList<>();
return Mono.just(mapResponses)
.flatMap(r -> checkIfChargebackIsNotAFraud(r, issuerMsg))
.flatMap(r -> processStageSubmitTranInquiry(issuerMsg, r, steps))
.flatMap(r -> processStageInitiateDisputeFromTransactionOrCase(issuerMsg, r, steps))
.flatMap(this::stopProcessWhenFraudReportNotExist)
.flatMap(r -> continueProcessIfFraudReportExist(issuerMsg, r, steps))
.map(r -> toResponse(issuerMsg, steps, null))
.onErrorResume(Exception.class, e -> Mono.just(toResponse(issuerMsg, steps, e)));
}
1
2
3
4.2. Le développement
Etape 6 : Préparation de la requête et appel de l'API SubmitTranInquiry
private Mono<Map> processStageSubmitTranInquiry(String issuerMsg,
Map<VisaApi, Object> mapResponses,
List<StepDone> steps) {
return Mono.just(toRequestClientDto(issuerMsg, companyCodesProperties))
.map(validatorService::validate)
.flatMap(r -> submitTranInquiryService.submitTranInquiry(r, issuerMsg, steps))
.map(r -> putObjectInMap(mapResponses, SUBMIT_TRAN_INQUIRY, r));
}
public Mono<TranInquiryResponseClientDto> submitTranInquiry(
TranInquiryRequestClientDto request
) {
String requestId = String.valueOf(UUID.randomUUID());
return webClient.post()
.uri(API.getUri())
.bodyValue(request)
.retrieve()
.toEntity(TranInquiryResponseClientDto.class)
.doOnSubscribe(s -> logger.info(LOG_REQUEST, API.getUri(), requestId, toMaskedJson(request)))
.doOnNext(
r -> logger.info(LOG_RESPONSE, API.getUri(), requestId, r.getStatusCodeValue(), toMaskedJson(r.getBody())))
.map(HttpEntity::getBody);
}
URI = /submitTranInquiry
4.3. Les tests
Etape 1 : Création des mocks
> Pas accès aux APIs de Visa
> Mockito : simuler les appels à Visa
Comment simuler l'appel de la première API ?
{
"request": {
"method": "POST",
"urlPathPattern": "/rsrv_rolti-mte2/api/submitTranInquiry",
"bodyPatterns": [
{
"matchesJsonPath": "$.RequestData[?(@.TransactionID == '1000000200')]"
}
]
},
"response": {
"status": 200,
"headers": {
"Content-Type": "application/json"
},
"jsonBody": {
"Status": [
{
"Code": "I-300000000",
"Message": "Successfully completed Operation."
}
],
"ResponseData": {
"TIEventID": 27855353,
"TransactionSummary": [
{
"RolTransactionId": 172632355,
"TransactionType": "TC05"
}
]
}
}
}
}
4.3. Les tests
Etape 2 : Tests unitaires
> Testons la fonction précédemment démontrée
@Test
void submitTranInquiry_shouldSucceed_whenStatus200() {
TranInquiryRequestClientDto request = datasetTranInquiryRequest("1000000200");
String issuerMessage = datasetXml("13001", "1000000200");
test(service.submitTranInquiry(request, issuerMessage, new ArrayList<>()))
.expectSubscription()
.consumeNextWith(r -> {
assertThat(r).isNotNull();
assertThat(r.status().get(0).code()).isEqualTo("I-300000000");
assertThat(r.responseData().tiEventID()).isEqualTo(27855353);
assertThat(r.responseData().transactionSummary().get(0).rolTransactionId()).isEqualTo(172632355);
})
.verifyComplete();
}
Idée de carrière
Amélioration de compétences techniques et transversales
Mon futur dans l'entreprise
5. bilan du stage
Merci
Avez-vous des questions ?
SoutenanceStageINFO5-2023-NGUYEN-Clément
By Clément Nguyen
SoutenanceStageINFO5-2023-NGUYEN-Clément
- 61