PROX-392: bump payments (#63)

* PROX-392: bump payments
This commit is contained in:
Anatoly Cherkasov 2020-03-10 11:27:30 +03:00 committed by GitHub
parent 645f44a2cb
commit d1509861b3
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
98 changed files with 1637 additions and 1500 deletions

View File

@ -2,7 +2,7 @@
[![Build Status](http://ci.rbkmoney.com/buildStatus/icon?job=rbkmoney_private/proxy-mocketbank/master)](http://ci.rbkmoney.com/job/rbkmoney_private/proxy-mocketbank/master)
Сервис предназначен для эмулирования запросов между процессингом и банком
Сервис предназначен для эмулирования запросов между различными системами
### Developers
@ -10,20 +10,25 @@
- [Anatoly Cherkasov](https://github.com/avcherkasov)
### Оглавление:
### Оглавление
1. [Техническая документация](docs/tech.md)
1. [Полезные ссылки](docs/useful_links.md)
1. [FAQ](docs/faq.md)
1. [Настройки](docs/settings.md)
1. [Структура проекта](docs/structure.md)
Отправка запросов на сервис:
### Отправка запросов на сервис
##### Для внешних запросов
```
http(s)//{host}:8080/mocketbank - для внешних запросов
http(s)//{host}:8022/proxy/mocketbank - для трифтовых запросов (эквайринг)
http(s)//{host}:8022/proxy/mocketbank/p2p-credit - для трифтовых запросов (p2p credit)
http(s)//{host}:8022/proxy/mocketbank/p2p - для трифтовых запросов p2p
http(s)//{host}:8022/proxy/mocketbank/terminal - для трифтовых запросов по терминалам
http(s)//{host}:8022/proxy/mocketbank/mobile/operator - для трифтовых запросов для определения оператора мобильного телефона
http(s)//{host}:8022/proxy/mocketbank/operator - для трифтовых запросов для проведения оплаты с мобильного телефона
http(s)://{host}:8080/mocketbank
```
##### Для трифтовых запросов
```
http(s)://{host}:8022/proxy/mocketbank - эквайринг
http(s)://{host}:8022/proxy/mocketbank/p2p-credit - выплаты
http(s)://{host}:8022/proxy/mocketbank/p2p - p2p
http(s)://{host}:8022/proxy/mocketbank/terminal - оплата через терминал
http(s)://{host}:8022/proxy/mocketbank/mobile/operator - определение оператора мобильного телефона
http(s)://{host}:8022/proxy/mocketbank/mobile - оплата с мобильного телефона
```

View File

@ -1,15 +0,0 @@
# Proxy Test
## FAQ
Вопросы для обсуждения и ряд полученных ответов на них:
`Вопрос:`
> Описание вопроса
`Ответ:`
Описание ответа
---

54
docs/settings.md Normal file
View File

@ -0,0 +1,54 @@
## Настройки
#### Общие
Название параметра (при запуске) | Описание | Пример
------------ | ------------- | -------------
**adapter-mock-bank.callbackUrl** | URL адаптера на который будет возвращен ответ с результатом проверки 3DS со стороны банка | http://127.0.0.1:8080
**adapter-mock-bank.pathCallbackUrl** | Путь для URL адаптера на который будет возвращен ответ с результатом проверки 3DS со стороны банка | /mocketbank/term_url{?termination_uri}
**adapter-mock-bank.pathRecurrentCallbackUrl** | Путь для URL адаптера на который будет возвращен ответ с результатом проверки 3DS со стороны банка | /mocketbank/rec_term_url{?termination_uri}
**adapter-mock-mpi.url** | url для взаимодействия с заглушкой mpi | http://127.0.0.1:8079
---
#### CDS
Данные для работы с CDS (Card Data Storage)
Параметры, которые можно переопределить при запуске приложения:
Название | Описание | Пример
------------ | ------------- | -------------
**cds.client.storage.url** | URL для работы с CDS (storage) | http://127.0.0.1:8022/v1/storage
**cds.client.storage.networkTimeout** | таймаут | 5000
**cds.client.identity-document-storage.url** | URL для работы с CDS (storage) | http://127.0.0.1:8022/v1/identity_document_storage
**cds.client.identity-document-storage.networkTimeout** | таймаут | 5000
---
#### HellGate
Данные для работы с HellGate
Параметры, которые можно переопределить при запуске приложения:
Название | Описание | Пример
------------ | ------------- | -------------
**hellgate.client.adapter.url** | URL для работы с процессингом | http://127.0.0.1:8022/v1/proxyhost/provider
**hellgate.client.adapter.networkTimeout** | таймаут | 30000
---
#### Остальные настройки
Название параметра (можно переопределить при запуске) | Название параметра (можно переопределить в настройках) | Описание | Пример
------------ | ------------- | ------------- | -------------
**timer.redirectTimeout** | **redirect_timeout** | Время в течении которого ожидается ответ на suspend (секунды) | 3600
**rest-template.maxTotalPooling** | **-** | размер пула | 200
**rest-template.defaultMaxPerRoute** | **-** | количество потоков на один ендпоинт | 200
**rest-template.requestTimeout** | **-** | таймаут запроса | 60000
**rest-template.poolTimeout** | **-** | таймаут на получение треда из пула | 10000
**rest-template.connectionTimeout** | **-** | таймаут на откртие коннекта к ендпоинту | 10000
**fixture.cards** | **-** | фаил с номерами карт под различное поведение | classpath:fixture/cards.csv
**fixture.mobilephone** | **-** | фаил с номерами телефонов под различное поведение | classpath:fixture/mobilephone.csv

35
docs/structure.md Normal file
View File

@ -0,0 +1,35 @@
## Структура проекта
```
├── src
│   ├── main
│   │   ├── java
│   │   │   └── com
│   │   │   └── rbkmoney
│   │   │   └── proxy
│   │   │   └── mocketbank
│   │   │   ├── ProxyMocketBankApplication.java
│   │   │   ├── configuration - конфигурационные файлы
│   │   │   │   └── properties - параметры
│   │   │   ├── controller - контроллеры для обработки внешних запросов
│   │   │   ├── decorator - декораторы
│   │   │   ├── exception - исключения
│   │   │   ├── handler - обработчики
│   │   │   │   ├── mobile - определение мобильного оператора и оплата
│   │   │   │   ├── oct - выплаты
│   │   │   │   ├── p2p
│   │   │   │   ├── payment - эквайринговые платежи
│   │   │   │   └── terminal - оплата через терминал
│   │   │   ├── service - сервисы в данном проекте
│   │   │   │   └── mpi
│   │   │   ├── servlet - эндпоинты
│   │   │   ├── utils - вспомогательные классы
│   │   │   └── validator - валидаторы
│   │   └── resources
│   │   ├── application.yml
│   │   ├── fixture
│   │   │   ├── cards.csv - банковские карты под разное поведение
│   │   │   ├── errors.json - маппинг ошибок
│   │   │   └── mobilephone.csv - список мобильных телефонов для разного поведения
```

View File

@ -1,3 +0,0 @@
# Proxy Test
## Техническая документация

View File

@ -1,46 +0,0 @@
# Proxy Test
## Полезные ссылки
### Java
- [Официальная страница](http://www.oracle.com/technetwork/java/index.html)
- [Страница загрузки](http://www.oracle.com/technetwork/java/javase/downloads/jdk8-downloads-2133151.html)
### Maven
- [Официальная страница](https://maven.apache.org/)
- [Maven repository](http://mvnrepository.com/)
### Thrift
- [Официальная страница](https://thrift.apache.org)
- [thrift](https://github.com/rbkmoney/thrift)
### Woody Thrift
- [woody_java](https://github.com/rbkmoney/woody_java)
### Damsel
- [damsel](https://github.com/rbkmoney/damsel)
### CDS
- [cds](https://github.com/rbkmoney/cds)
### Hellgate
- [hellgate](https://github.com/rbkmoney/hellgate)
### Docker
- [Официальная страница](https://www.docker.com/)

View File

@ -120,6 +120,11 @@
<artifactId>adapter-common-lib</artifactId>
<version>0.0.12</version>
</dependency>
<dependency>
<groupId>com.rbkmoney</groupId>
<artifactId>error-mapping-java</artifactId>
<version>1.0.5</version>
</dependency>
<!--Test libs-->
<dependency>
<groupId>org.jsoup</groupId>

View File

@ -1,6 +1,8 @@
package com.rbkmoney.proxy.mocketbank.configuration;
import com.rbkmoney.proxy.mocketbank.utils.error_mapping.ErrorMapping;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.rbkmoney.error.mapping.ErrorMapping;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@ -19,8 +21,11 @@ public class ErrorMappingConfiguration {
@Bean
ErrorMapping errorMapping() throws IOException {
ErrorMapping errorMapping = new ErrorMapping(filePath.getInputStream(), patternReason);
errorMapping.validateMappingFormat();
ObjectMapper mapper = new ObjectMapper();
mapper.configure(JsonParser.Feature.ALLOW_SINGLE_QUOTES, true);
ErrorMapping errorMapping = new ErrorMapping(filePath.getInputStream(), patternReason, mapper);
errorMapping.validateMapping();
return errorMapping;
}

View File

@ -5,6 +5,7 @@ import com.rbkmoney.proxy.mocketbank.handler.mobile.MobileServerHandler;
import com.rbkmoney.proxy.mocketbank.handler.mobile.operator.MobileOperatorServerHandler;
import com.rbkmoney.proxy.mocketbank.handler.oct.OctServerHandler;
import com.rbkmoney.proxy.mocketbank.handler.p2p.P2pServerHandler;
import com.rbkmoney.proxy.mocketbank.handler.payment.PaymentServerHandler;
import com.rbkmoney.proxy.mocketbank.handler.terminal.TerminalServerHandler;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@ -20,27 +21,28 @@ public class HandlerConfiguration {
}
@Bean
@Primary
public MobileOperatorServerHandlerLog mobileOperatorServerHandlerLog(MobileOperatorServerHandler mobileOperatorServerHandler) {
return new MobileOperatorServerHandlerLog(mobileOperatorServerHandler);
}
@Bean
@Primary
public MobileServerHandlerLog mobileServerHandlerLog(MobileServerHandler mobileServerHandler) {
return new MobileServerHandlerLog(mobileServerHandler);
}
@Bean
@Primary
public P2pServerHandlerLog p2pServerHandlerLog(P2pServerHandler p2pServerHandler) {
return new P2pServerHandlerLog(p2pServerHandler);
}
@Bean
@Primary
public TerminalServerHandlerLog terminalServerHandlerLog(TerminalServerHandler terminalServerHandler) {
return new TerminalServerHandlerLog(terminalServerHandler);
}
@Bean
public PaymentServerHandlerMdcLog paymentServerHandlerLog(PaymentServerHandler paymentServerHandler) {
return new PaymentServerHandlerMdcLog(new PaymentServerHandlerLog(paymentServerHandler));
}
}

View File

@ -0,0 +1,27 @@
package com.rbkmoney.proxy.mocketbank.configuration.properties;
import lombok.Getter;
import lombok.Setter;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Configuration;
import org.springframework.validation.annotation.Validated;
import javax.validation.constraints.NotEmpty;
@Getter
@Setter
@Validated
@Configuration
@ConfigurationProperties("adapter-mock-bank")
public class AdapterMockBankProperties {
@NotEmpty
private String callbackUrl;
@NotEmpty
private String pathCallbackUrl;
@NotEmpty
private String pathRecurrentCallbackUrl;
}

View File

@ -0,0 +1,21 @@
package com.rbkmoney.proxy.mocketbank.configuration.properties;
import lombok.Getter;
import lombok.Setter;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Configuration;
import org.springframework.validation.annotation.Validated;
import javax.validation.constraints.NotNull;
@Getter
@Setter
@Validated
@Configuration
@ConfigurationProperties("timer")
public class TimerProperties {
@NotNull
private int redirectTimeout;
}

View File

@ -1,11 +1,12 @@
package com.rbkmoney.proxy.mocketbank.controller;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.rbkmoney.adapter.helpers.hellgate.HellgateAdapterClient;
import com.rbkmoney.adapter.helpers.hellgate.exception.HellgateException;
import com.rbkmoney.proxy.mocketbank.utils.Converter;
import com.rbkmoney.java.damsel.converter.CommonConverter;
import com.rbkmoney.proxy.mocketbank.utils.state.constant.SuspendPrefix;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
@ -16,57 +17,104 @@ import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.charset.StandardCharsets;
import java.util.Arrays;
import java.util.Collections;
import java.util.Map;
import java.util.stream.Collectors;
@Slf4j
@RestController
@RequiredArgsConstructor
@RequestMapping("/${server.rest.endpoint}")
public class MocketBankController {
@Autowired
private HellgateAdapterClient hellgateClient;
private final HellgateAdapterClient hellgateClient;
@RequestMapping(value = "term_url", method = RequestMethod.POST)
public String receiveIncomingParameters(HttpServletRequest request, HttpServletResponse servletResponse) throws IOException {
log.info("Input params: {}", request.getParameterMap());
String tag = "";
ByteBuffer callback = null;
String tag = SuspendPrefix.PAYMENT + getTag(request);
log.info("ReceivePaymentIncomingParameters with tag {}, info {}", tag, httpServletRequestToString(request));
String resp = "";
try {
callback = Converter.mapToByteBuffer(Converter.mapArrayToMap(request.getParameterMap()));
} catch (IOException e) {
log.warn("Exception Map to ByteBuffer in processCallback", e);
}
if (StringUtils.hasText(request.getParameter("MD"))) {
tag = request.getParameter("MD");
} else {
log.warn("Missing a required parameter 'MD' ");
}
// Узнать рекурент или нет, после чего вызвать тот или иной метод
try {
ByteBuffer response;
if (tag.startsWith(SuspendPrefix.RECURRENT.getPrefix())) {
response = hellgateClient.processRecurrentTokenCallback(tag, callback);
} else {
response = hellgateClient.processPaymentCallback(tag, callback);
}
ByteBuffer callback = prepareCallbackParams(request);
ByteBuffer response = hellgateClient.processPaymentCallback(tag, callback);
resp = new String(response.array(), StandardCharsets.UTF_8);
} catch (HellgateException e) {
log.warn("Exception in processPaymentCallback", e);
log.warn("Failed handle callback for payment", e);
} catch (Exception e) {
log.error("Exception in processPaymentCallback", e);
log.error("Failed handle callback for payment", e);
}
if (StringUtils.hasText(request.getParameter("termination_uri")))
servletResponse.sendRedirect(request.getParameter("termination_uri"));
sendRedirect(request, servletResponse);
return resp;
}
@RequestMapping(value = "/rec_term_url", method = RequestMethod.POST)
public String receiveRecurrentIncomingParameters(HttpServletRequest request, HttpServletResponse servletResponse) throws IOException {
String tag = SuspendPrefix.RECURRENT + getTag(request);
log.info("ReceiveRecurrentIncomingParameters with tag {}, info {}", tag, httpServletRequestToString(request));
String resp = "";
try {
ByteBuffer callback = prepareCallbackParams(request);
ByteBuffer response = hellgateClient.processRecurrentTokenCallback(tag, callback);
resp = new String(response.array(), StandardCharsets.UTF_8);
} catch (HellgateException e) {
log.warn("Failed handle callback for recurrent", e);
} catch (Exception e) {
log.error("Failed handle callback for recurrent", e);
}
sendRedirect(request, servletResponse);
return resp;
}
private String getTag(HttpServletRequest request) {
if (StringUtils.hasText(request.getParameter("MD"))) {
return request.getParameter("MD");
} else {
log.warn("Missing a required parameter 'MD' ");
}
return "";
}
private ByteBuffer prepareCallbackParams(HttpServletRequest request) throws JsonProcessingException {
Map<String, String> requestParams = CommonConverter.mapArrayToMap(request.getParameterMap());
return CommonConverter.mapToByteBuffer(requestParams);
}
private void sendRedirect(HttpServletRequest request, HttpServletResponse servletResponse) throws IOException {
if (StringUtils.hasText(request.getParameter("termination_uri"))) {
servletResponse.sendRedirect(request.getParameter("termination_uri"));
}
}
private String httpServletRequestToString(HttpServletRequest request) {
StringBuilder sb = new StringBuilder();
sb.append("Request Method = [").append(request.getMethod()).append("], ");
sb.append("Request URL Path = [").append(request.getRequestURL()).append("], ");
String headers = Collections.list(request.getHeaderNames())
.stream()
.map(headerName -> headerName + " : " + Collections.list(request.getHeaders(headerName)))
.collect(Collectors.joining(", "));
if (headers.isEmpty()) {
sb.append("Request headers: NONE,");
} else {
sb.append("Request headers: [").append(headers).append("],");
}
String parameters = Collections.list(request.getParameterNames())
.stream()
.map(p -> p + " : " + Arrays.asList(request.getParameterValues(p)))
.collect(Collectors.joining(", "));
if (parameters.isEmpty()) {
sb.append("Request parameters: NONE.");
} else {
sb.append("Request parameters: [").append(parameters).append("].");
}
return sb.toString();
}
}

View File

@ -20,8 +20,10 @@ public class MobileOperatorServerHandlerLog implements MnpSrv.Iface {
return responseData;
} catch (Exception ex) {
String message = String.format("Failed Lookup with requestParams=%s", requestParams);
ServerHandlerLogUtils.logMessage(ex, message);
ServerHandlerLogUtils.logMessage(ex, message, this.getClass());
throw ex;
}
}
}

View File

@ -2,7 +2,7 @@ package com.rbkmoney.proxy.mocketbank.decorator;
import com.rbkmoney.damsel.proxy_provider.*;
import com.rbkmoney.java.damsel.utils.extractors.ProxyProviderPackageExtractors;
import com.rbkmoney.proxy.mocketbank.converter.PaymentResourceTypeResolver;
import com.rbkmoney.proxy.mocketbank.utils.converter.PaymentResourceTypeResolver;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.thrift.TException;
@ -25,7 +25,7 @@ public class MobileServerHandlerLog implements ProviderProxySrv.Iface {
return proxyResult;
} catch (Exception ex) {
String message = String.format("Failed handle GenerateToken with recurrentId=%s", recurrentId);
ServerHandlerLogUtils.logMessage(ex, message);
ServerHandlerLogUtils.logMessage(ex, message, this.getClass());
throw ex;
}
}
@ -50,11 +50,11 @@ public class MobileServerHandlerLog implements ProviderProxySrv.Iface {
log.info("Process payment handle resource={}, status={} finished with invoiceId={} and proxyResult={}",
paymentResourceType, invoicePaymentStatus, invoiceId, proxyResult);
return proxyResult;
} catch (Exception e) {
} catch (Exception ex) {
String message = String.format("Failed handle resource=%s, status=%s process payment for operation with invoiceId %s",
paymentResourceType, invoicePaymentStatus, invoiceId);
ServerHandlerLogUtils.logMessage(e, message);
throw e;
ServerHandlerLogUtils.logMessage(ex, message, this.getClass());
throw ex;
}
}
@ -66,4 +66,5 @@ public class MobileServerHandlerLog implements ProviderProxySrv.Iface {
log.info("HandlePaymentCallback finish {} with invoiceId={}", result, invoiceId);
return result;
}
}

View File

@ -1,7 +1,7 @@
package com.rbkmoney.proxy.mocketbank.decorator;
import com.rbkmoney.damsel.p2p_adapter.*;
import com.rbkmoney.proxy.mocketbank.extractor.P2pAdapterExtractors;
import com.rbkmoney.proxy.mocketbank.utils.extractor.p2p.P2pAdapterExtractors;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.thrift.TException;
@ -22,7 +22,7 @@ public class P2pServerHandlerLog implements P2PAdapterSrv.Iface {
return result;
} catch (Exception ex) {
String message = String.format("Failed handle Process with sessionId=%s", sessionId);
ServerHandlerLogUtils.logMessage(ex, message);
ServerHandlerLogUtils.logMessage(ex, message, this.getClass());
throw ex;
}
}
@ -37,7 +37,7 @@ public class P2pServerHandlerLog implements P2PAdapterSrv.Iface {
return result;
} catch (Exception ex) {
String message = String.format("Failed handle HandleCallback with sessionId=%s", sessionId);
ServerHandlerLogUtils.logMessage(ex, message);
ServerHandlerLogUtils.logMessage(ex, message, this.getClass());
throw ex;
}
}

View File

@ -0,0 +1,70 @@
package com.rbkmoney.proxy.mocketbank.decorator;
import com.rbkmoney.damsel.proxy_provider.*;
import com.rbkmoney.java.damsel.utils.extractors.ProxyProviderPackageExtractors;
import com.rbkmoney.proxy.mocketbank.utils.converter.PaymentResourceTypeResolver;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.thrift.TException;
import java.nio.ByteBuffer;
@Slf4j
@RequiredArgsConstructor
public class PaymentServerHandlerLog implements ProviderProxySrv.Iface {
private final ProviderProxySrv.Iface handler;
@Override
public RecurrentTokenProxyResult generateToken(RecurrentTokenContext context) throws TException {
String recurrentId = ProxyProviderPackageExtractors.extractRecurrentId(context);
log.info("GenerateToken started with recurrentId={}", recurrentId);
try {
RecurrentTokenProxyResult proxyResult = handler.generateToken(context);
log.info("GenerateToken finished {} with recurrentId={}", proxyResult, recurrentId);
return proxyResult;
} catch (Exception ex) {
String message = String.format("Failed handle GenerateToken with recurrentId=%s", recurrentId);
ServerHandlerLogUtils.logMessage(ex, message, this.getClass());
throw ex;
}
}
@Override
public RecurrentTokenCallbackResult handleRecurrentTokenCallback(ByteBuffer byteBuffer, RecurrentTokenContext context) throws TException {
String recurrentId = ProxyProviderPackageExtractors.extractRecurrentId(context);
log.info("HandleRecurrentTokenCallback: start with recurrentId={}", recurrentId);
RecurrentTokenCallbackResult result = handler.handleRecurrentTokenCallback(byteBuffer, context);
log.info("HandleRecurrentTokenCallback end {} with recurrentId={}", result, recurrentId);
return result;
}
@Override
public PaymentProxyResult processPayment(PaymentContext context) throws TException {
String invoiceId = ProxyProviderPackageExtractors.extractInvoiceId(context);
String invoicePaymentStatus = ProxyProviderPackageExtractors.extractTargetInvoicePaymentStatus(context);
String paymentResourceType = PaymentResourceTypeResolver.extractPaymentResourceType(context);
log.info("Process payment handle resource={}, status={} start with invoiceId={}", paymentResourceType, invoicePaymentStatus, invoiceId);
try {
PaymentProxyResult proxyResult = handler.processPayment(context);
log.info("Process payment handle resource={}, status={} finished with invoiceId={} and proxyResult={}",
paymentResourceType, invoicePaymentStatus, invoiceId, proxyResult);
return proxyResult;
} catch (Exception ex) {
String message = String.format("Failed handle resource=%s, status=%s process payment for operation with invoiceId %s",
paymentResourceType, invoicePaymentStatus, invoiceId);
ServerHandlerLogUtils.logMessage(ex, message, this.getClass());
throw ex;
}
}
@Override
public PaymentCallbackResult handlePaymentCallback(ByteBuffer byteBuffer, PaymentContext context) throws TException {
String invoiceId = ProxyProviderPackageExtractors.extractInvoiceId(context);
log.info("HandlePaymentCallback start with invoiceId={}", invoiceId);
PaymentCallbackResult result = handler.handlePaymentCallback(byteBuffer, context);
log.info("HandlePaymentCallback finish {} with invoiceId={}", result, invoiceId);
return result;
}
}

View File

@ -1,28 +1,23 @@
package com.rbkmoney.proxy.mocketbank.handler;
package com.rbkmoney.proxy.mocketbank.decorator;
import com.rbkmoney.damsel.proxy_provider.*;
import lombok.extern.slf4j.Slf4j;
import lombok.RequiredArgsConstructor;
import org.apache.thrift.TException;
import org.slf4j.MDC;
import org.springframework.context.annotation.Primary;
import org.springframework.stereotype.Component;
import java.nio.ByteBuffer;
@Slf4j
@Primary
@Component
public class MocketBankServerHandlerMdcDecorator implements ProviderProxySrv.Iface {
import static com.rbkmoney.java.damsel.utils.extractors.ProxyProviderPackageExtractors.extractInvoiceId;
import static com.rbkmoney.java.damsel.utils.extractors.ProxyProviderPackageExtractors.extractPaymentId;
private final MocketBankServerHandler handler;
@RequiredArgsConstructor
public class PaymentServerHandlerMdcLog implements ProviderProxySrv.Iface {
public MocketBankServerHandlerMdcDecorator(final MocketBankServerHandler rtn) {
this.handler = rtn;
}
private final ProviderProxySrv.Iface handler;
private void mdcPut(PaymentContext context) {
String invoiceId = context.getPaymentInfo().getInvoice().getId();
String paymentId = context.getPaymentInfo().getPayment().getId();
String invoiceId = extractInvoiceId(context);
String paymentId = extractPaymentId(context);
MDC.put("invoiceId", invoiceId);
MDC.put("paymentId", paymentId);
}

View File

@ -1,19 +1,19 @@
package com.rbkmoney.proxy.mocketbank.decorator;
import com.rbkmoney.java.damsel.utils.verification.ProxyProviderVerification;
import lombok.AccessLevel;
import lombok.NoArgsConstructor;
import lombok.extern.slf4j.Slf4j;
@Slf4j
@NoArgsConstructor(access = AccessLevel.PRIVATE)
public class ServerHandlerLogUtils {
public static void logMessage(Exception ex, String message) {
public static final String MESSAGE_TEMPLATE = "Class {}, message {} ";
public static void logMessage(Exception ex, String message, Class<?> className) {
if (ProxyProviderVerification.isUndefinedResultOrUnavailable(ex)) {
log.warn(message, ex);
log.warn(MESSAGE_TEMPLATE, className, message, ex);
} else {
log.error(message, ex);
log.warn(MESSAGE_TEMPLATE, className, message, ex);
}
}
}
}

View File

@ -2,7 +2,7 @@ package com.rbkmoney.proxy.mocketbank.decorator;
import com.rbkmoney.damsel.proxy_provider.*;
import com.rbkmoney.java.damsel.utils.extractors.ProxyProviderPackageExtractors;
import com.rbkmoney.proxy.mocketbank.converter.PaymentResourceTypeResolver;
import com.rbkmoney.proxy.mocketbank.utils.converter.PaymentResourceTypeResolver;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.thrift.TException;
@ -25,7 +25,7 @@ public class TerminalServerHandlerLog implements ProviderProxySrv.Iface {
return proxyResult;
} catch (Exception ex) {
String message = String.format("Failed handle GenerateToken with recurrentId=%s", recurrentId);
ServerHandlerLogUtils.logMessage(ex, message);
ServerHandlerLogUtils.logMessage(ex, message, this.getClass());
throw ex;
}
}
@ -50,11 +50,11 @@ public class TerminalServerHandlerLog implements ProviderProxySrv.Iface {
log.info("Process payment handle resource={}, status={} finished with invoiceId={} and proxyResult={}",
paymentResourceType, invoicePaymentStatus, invoiceId, proxyResult);
return proxyResult;
} catch (Exception e) {
} catch (Exception ex) {
String message = String.format("Failed handle resource=%s, status=%s process payment for operation with invoiceId %s",
paymentResourceType, invoicePaymentStatus, invoiceId);
ServerHandlerLogUtils.logMessage(e, message);
throw e;
ServerHandlerLogUtils.logMessage(ex, message, this.getClass());
throw ex;
}
}
@ -66,4 +66,5 @@ public class TerminalServerHandlerLog implements ProviderProxySrv.Iface {
log.info("HandlePaymentCallback finish {} with invoiceId={}", result, invoiceId);
return result;
}
}

View File

@ -24,7 +24,7 @@ public class WithdrawalServerHandlerLog implements AdapterSrv.Iface {
return processResult;
} catch (Exception ex) {
String message = String.format("Failed processWithdrawal with withdrawalId=%s", withdrawalId);
ServerHandlerLogUtils.logMessage(ex, message);
ServerHandlerLogUtils.logMessage(ex, message, this.getClass());
throw ex;
}
}
@ -39,7 +39,7 @@ public class WithdrawalServerHandlerLog implements AdapterSrv.Iface {
return quote;
} catch (Exception ex) {
String message = String.format("Failed getQuote with idempotencyId=%s", idempotencyId);
ServerHandlerLogUtils.logMessage(ex, message);
ServerHandlerLogUtils.logMessage(ex, message, this.getClass());
throw ex;
}
}

View File

@ -0,0 +1,21 @@
package com.rbkmoney.proxy.mocketbank.exception;
public class CardException extends RuntimeException {
public CardException() {
super();
}
public CardException(String message) {
super(message);
}
public CardException(Throwable cause) {
super(cause);
}
public CardException(String message, Throwable cause) {
super(message, cause);
}
}

View File

@ -0,0 +1,21 @@
package com.rbkmoney.proxy.mocketbank.exception;
public class PaymentException extends RuntimeException {
public PaymentException() {
super();
}
public PaymentException(String message) {
super(message);
}
public PaymentException(Throwable cause) {
super(cause);
}
public PaymentException(String message, Throwable cause) {
super(message, cause);
}
}

View File

@ -1,21 +0,0 @@
package com.rbkmoney.proxy.mocketbank.extractor;
import com.rbkmoney.damsel.domain.PaymentTool;
import com.rbkmoney.damsel.proxy_provider.PaymentResource;
import com.rbkmoney.proxy.mocketbank.exception.MobileException;
import lombok.AccessLevel;
import lombok.NoArgsConstructor;
@NoArgsConstructor(access = AccessLevel.PRIVATE)
public class ProxyProviderPackageExtractors {
public static PaymentTool extractPaymentTool(PaymentResource paymentResource) {
if (paymentResource.isSetDisposablePaymentResource()) {
return paymentResource.getDisposablePaymentResource().getPaymentTool();
} else if (paymentResource.isSetRecurrentPaymentResource()) {
return paymentResource.getRecurrentPaymentResource().getPaymentTool();
}
throw new MobileException("Unknown Payment Resource");
}
}

View File

@ -1,578 +0,0 @@
package com.rbkmoney.proxy.mocketbank.handler;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.rbkmoney.cds.client.storage.CdsClientStorage;
import com.rbkmoney.cds.client.storage.model.CardDataProxyModel;
import com.rbkmoney.damsel.domain.*;
import com.rbkmoney.damsel.proxy_provider.InvoicePayment;
import com.rbkmoney.damsel.proxy_provider.InvoicePaymentRefund;
import com.rbkmoney.damsel.proxy_provider.*;
import com.rbkmoney.proxy.mocketbank.decorator.ServerHandlerLogUtils;
import com.rbkmoney.proxy.mocketbank.utils.Converter;
import com.rbkmoney.proxy.mocketbank.utils.PaymentUtils;
import com.rbkmoney.proxy.mocketbank.utils.error_mapping.ErrorMapping;
import com.rbkmoney.proxy.mocketbank.utils.mocketbank.MockMpiApi;
import com.rbkmoney.proxy.mocketbank.utils.mocketbank.MockMpiUtils;
import com.rbkmoney.proxy.mocketbank.utils.mocketbank.constant.MpiAction;
import com.rbkmoney.proxy.mocketbank.utils.mocketbank.constant.MpiEnrollmentStatus;
import com.rbkmoney.proxy.mocketbank.utils.mocketbank.constant.MpiField;
import com.rbkmoney.proxy.mocketbank.utils.mocketbank.constant.MpiTransactionStatus;
import com.rbkmoney.proxy.mocketbank.utils.mocketbank.model.ValidatePaResRequest;
import com.rbkmoney.proxy.mocketbank.utils.mocketbank.model.ValidatePaResResponse;
import com.rbkmoney.proxy.mocketbank.utils.mocketbank.model.VerifyEnrollmentRequest;
import com.rbkmoney.proxy.mocketbank.utils.mocketbank.model.VerifyEnrollmentResponse;
import com.rbkmoney.proxy.mocketbank.utils.model.Card;
import com.rbkmoney.proxy.mocketbank.utils.model.CardUtils;
import com.rbkmoney.proxy.mocketbank.utils.state.constant.PaymentState;
import com.rbkmoney.proxy.mocketbank.utils.state.constant.SuspendPrefix;
import lombok.extern.slf4j.Slf4j;
import org.apache.thrift.TException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import java.nio.ByteBuffer;
import java.util.*;
import static com.rbkmoney.java.damsel.utils.creators.DomainPackageCreators.createTransactionInfo;
import static com.rbkmoney.java.damsel.utils.creators.ProxyProviderPackageCreators.*;
import static com.rbkmoney.java.damsel.utils.verification.ProxyProviderVerification.isMakeRecurrent;
import static com.rbkmoney.proxy.mocketbank.utils.mocketbank.constant.MpiAction.*;
@Slf4j
@Component
public class MocketBankServerHandler implements ProviderProxySrv.Iface {
@Autowired
private CdsClientStorage cds;
@Autowired
private MockMpiApi mocketBankMpiApi;
@Autowired
private ErrorMapping errorMapping;
@Value("${proxy-mocketbank.callbackUrl}")
private String callbackUrl;
@Value("${timer.timeout}")
private int timerTimeout;
@Autowired
private List<Card> cardList;
@Override
public RecurrentTokenProxyResult generateToken(RecurrentTokenContext context) throws TException {
String recurrentId = context.getTokenInfo().getPaymentTool().getId();
log.info("GenerateToken: start with recurrentId {}", recurrentId);
RecurrentTokenIntent intent = createRecurrentTokenFinishIntentSuccess(recurrentId);
RecurrentTokenProxyResult proxyResult;
// Applepay, Samsungpay, Googlepay - always successful and does not depends on card
Optional<BankCardTokenProvider> bankCardTokenProvider = getBankCardTokenProvider(context);
if (bankCardTokenProvider.isPresent()) {
proxyResult = createRecurrentTokenProxyResult(intent);
log.info("Processed: success {} with invoiceId {}", proxyResult, recurrentId);
return proxyResult;
}
CardDataProxyModel cardData = cds.getCardData(context);
Optional<Card> card = CardUtils.extractCardByPan(cardList, cardData.getPan());
if (card.isPresent()) {
MpiAction action = MpiAction.findByValue(card.get().getAction());
if (!MpiAction.isCardEnrolled(card.get())) {
String error;
switch (action) {
case INSUFFICIENT_FUNDS:
error = INSUFFICIENT_FUNDS.getAction();
break;
case INVALID_CARD:
error = INVALID_CARD.getAction();
break;
case CVV_MATCH_FAIL:
error = CVV_MATCH_FAIL.getAction();
break;
case EXPIRED_CARD:
error = EXPIRED_CARD.getAction();
break;
case SUCCESS:
proxyResult = createRecurrentTokenProxyResult(
intent,
PaymentState.PROCESSED.getState().getBytes()
);
log.info("GenerateToken: success {} with recurrentId {}", proxyResult, recurrentId);
return proxyResult;
default:
error = UNKNOWN_FAILURE.getAction();
}
proxyResult = createRecurrentTokenProxyResultFailure(
errorMapping.getFailureByCodeAndDescription(error, error)
);
log.info("GenerateToken: failure {} with recurrentId {}", proxyResult, recurrentId);
return proxyResult;
}
} else {
proxyResult = createRecurrentTokenProxyResultFailure(
errorMapping.getFailureByCodeAndDescription(
UNSUPPORTED_CARD.getAction(),
UNSUPPORTED_CARD.getAction()
)
);
log.info("GenerateToken: failure {} with recurrentId {}", proxyResult, recurrentId);
return proxyResult;
}
VerifyEnrollmentResponse verifyEnrollmentResponse = mocketBankMpiApi.verifyEnrollment(
VerifyEnrollmentRequest.builder()
.pan(cardData.getPan())
.year(cardData.getExpYear())
.month(cardData.getExpMonth())
.build());
if (verifyEnrollmentResponse.getEnrolled().equals(MpiEnrollmentStatus.AUTHENTICATION_AVAILABLE.getStatus())) {
String tag = SuspendPrefix.RECURRENT.getPrefix() + context.getTokenInfo().getPaymentTool().getId();
log.info("GenerateToken: suspend tag {} with recurrentId {}", tag, recurrentId);
String url = verifyEnrollmentResponse.getAcsUrl();
Map<String, String> params = new HashMap<>();
params.put("PaReq", verifyEnrollmentResponse.getPaReq());
params.put("MD", tag);
params.put("TermUrl", MockMpiUtils.getCallbackUrl(callbackUrl, "/mocketbank/term_url{?termination_uri}"));
log.info("GenerateToken: prepare redirect params {} with recurrentId {}", params, recurrentId);
intent = createRecurrentTokenWithSuspendIntent(
tag, timerTimeout, createPostUserInteraction(url, params)
);
}
Map<String, String> extra = new HashMap<>();
extra.put(MpiField.PA_REQ.getValue(), verifyEnrollmentResponse.getPaReq());
log.info("GenerateToken: Extra map {} with recurrentId {}", extra, recurrentId);
byte[] state;
try {
state = Converter.mapToByteArray(extra);
} catch (JsonProcessingException ex) {
String message = "GenerateToken: can't convert map to byte array with recurrentId " + recurrentId;
log.error(message);
throw new IllegalArgumentException(message, ex);
}
RecurrentTokenProxyResult result = createRecurrentTokenProxyResult(intent, state);
log.info("GenerateToken: finish {} with recurrentId {} ", result, recurrentId);
return result;
}
@Override
public RecurrentTokenCallbackResult handleRecurrentTokenCallback(ByteBuffer byteBuffer, RecurrentTokenContext context) throws TException {
String recurrentId = context.getTokenInfo().getPaymentTool().getId();
log.info("handleRecurrentTokenCallback start with invoiceId {}", recurrentId);
HashMap<String, String> parameters;
try {
parameters = (HashMap<String, String>) Converter.byteArrayToMap(context.getSession().getState());
parameters.putAll(Converter.byteBufferToMap(byteBuffer));
log.info("handleRecurrentTokenCallback: merge params: recurrentId {}, params {}", recurrentId, parameters);
} catch (Exception ex) {
String message = "handleRecurrentTokenCallback: merge params error with recurrentId " + recurrentId;
log.error(message, ex);
throw new IllegalArgumentException(message, ex);
}
CardDataProxyModel cardData = cds.getCardData(context);
ValidatePaResResponse validatePaResResponse = mocketBankMpiApi.validatePaRes(
ValidatePaResRequest.builder()
.pan(cardData.getPan())
.paRes(parameters.get("paRes"))
.build());
log.info("handleRecurrentTokenCallback: validatePaResResponse {}", validatePaResResponse);
if (validatePaResResponse.getTransactionStatus().equals(MpiTransactionStatus.AUTHENTICATION_SUCCESSFUL.getStatus())) {
byte[] callbackResponse = new byte[0];
RecurrentTokenIntent intent = createRecurrentTokenFinishIntentSuccess(recurrentId);
RecurrentTokenProxyResult proxyResult = createRecurrentTokenProxyResult(intent, "processed".getBytes());
log.info("handleRecurrentTokenCallback: callbackResponse {}, proxyResult {}", callbackResponse, proxyResult);
return createRecurrentTokenCallbackResult(callbackResponse, proxyResult);
}
Optional<Card> card = CardUtils.extractCardByPan(cardList, cardData.getPan());
MpiAction action = MpiAction.findByValue(card.get().getAction());
String error;
switch (action) {
case THREE_D_SECURE_FAILURE:
error = THREE_D_SECURE_FAILURE.getAction();
break;
case THREE_D_SECURE_TIMEOUT:
error = THREE_D_SECURE_TIMEOUT.getAction();
break;
default:
error = UNKNOWN_FAILURE.getAction();
}
RecurrentTokenCallbackResult callbackResult = createRecurrentTokenCallbackResultFailure(
"error".getBytes(), errorMapping.getFailureByCodeAndDescription("error", error)
);
log.info("handleRecurrentTokenCallback finish {}, recurrent {}", callbackResult, recurrentId);
return callbackResult;
}
@Override
public PaymentProxyResult processPayment(PaymentContext context) throws TException {
String invoiceId = context.getPaymentInfo().getInvoice().getId();
log.info("processPayment start with invoiceId {}", invoiceId);
Map<String, String> options = (context.getOptions().size() > 0) ? context.getOptions() : new HashMap<>();
TargetInvoicePaymentStatus target = context.getSession().getTarget();
try {
if (target.isSetProcessed()) {
return processed(context, options);
} else if (target.isSetCaptured()) {
return captured(context, options);
} else if (target.isSetCancelled()) {
return cancelled(context, options);
} else if (target.isSetRefunded()) {
return refunded(context, options);
} else {
PaymentProxyResult proxyResult = createProxyResultFailure(
errorMapping.getFailureByCodeAndDescription(
"Unsupported method",
"Unsupported method"
)
);
log.error("Error unsupported method. proxyResult {} with invoiceId {}", proxyResult, invoiceId);
return proxyResult;
}
} catch (Exception ex) {
String message = "Exception in processPayment with invoiceId " + invoiceId;
ServerHandlerLogUtils.logMessage(ex, message);
throw ex;
}
}
private PaymentProxyResult processed(PaymentContext context, Map<String, String> options) {
com.rbkmoney.damsel.proxy_provider.InvoicePayment invoicePayment = context.getPaymentInfo().getPayment();
String invoiceId = context.getPaymentInfo().getInvoice().getId();
log.info("Processed start with invoiceId {}", invoiceId);
CardDataProxyModel cardData = cds.getCardData(context);
log.info("CardData: {}, pan: {}", cardData, cardData.getPan());
TransactionInfo transactionInfo = null;
Intent intent = createFinishIntentSuccess();
if (isMakeRecurrent(context)) {
intent = createFinishIntentSuccessWithToken(invoiceId);
}
PaymentProxyResult proxyResult;
// Applepay, Samsungpay, Googlepay - always successful and does not depends on card
Optional<BankCardTokenProvider> bankCardTokenProvider = getBankCardTokenProvider(context);
if (bankCardTokenProvider.isPresent()) {
transactionInfo = createTransactionInfo(
PaymentUtils.generateTransactionId(context.getPaymentInfo()),
Collections.emptyMap()
);
proxyResult = createPaymentProxyResult(
intent,
PaymentState.CAPTURED.getState().getBytes(),
transactionInfo
);
log.info("Processed: success {} with invoiceId {}", proxyResult, invoiceId);
return proxyResult;
}
Optional<Card> card = CardUtils.extractCardByPan(cardList, cardData.getPan());
if (card.isPresent()) {
MpiAction action = MpiAction.findByValue(card.get().getAction());
if (!MpiAction.isCardEnrolled(card.get())) {
String error;
switch (action) {
case INSUFFICIENT_FUNDS:
error = INSUFFICIENT_FUNDS.getAction();
break;
case INVALID_CARD:
error = INVALID_CARD.getAction();
break;
case CVV_MATCH_FAIL:
error = CVV_MATCH_FAIL.getAction();
break;
case APPLE_PAY_FAILURE:
error = APPLE_PAY_FAILURE.getAction();
break;
case SAMSUNG_PAY_FAILURE:
error = SAMSUNG_PAY_FAILURE.getAction();
break;
case GOOGLE_PAY_FAILURE:
error = GOOGLE_PAY_FAILURE.getAction();
break;
case EXPIRED_CARD:
error = EXPIRED_CARD.getAction();
break;
case SUCCESS:
transactionInfo = createTransactionInfo(
PaymentUtils.generateTransactionId(context.getPaymentInfo()),
Collections.emptyMap()
);
proxyResult = createPaymentProxyResult(
intent,
PaymentState.CAPTURED.getState().getBytes(),
transactionInfo
);
log.info("Processed: success {} with invoiceId {}", proxyResult, invoiceId);
return proxyResult;
default:
error = UNKNOWN_FAILURE.getAction();
}
proxyResult = createProxyResultFailure(
errorMapping.getFailureByCodeAndDescription(error, error)
);
log.info("Processed: failure {} with invoiceId {}", proxyResult, invoiceId);
return proxyResult;
}
} else {
proxyResult = createProxyResultFailure(
errorMapping.getFailureByCodeAndDescription(
UNSUPPORTED_CARD.getAction(),
UNSUPPORTED_CARD.getAction()
)
);
errorMapping.getFailureByCodeAndDescription(UNSUPPORTED_CARD.getAction(), UNSUPPORTED_CARD.getAction());
log.info("Processed: failure {} with invoiceId {}", proxyResult, invoiceId);
return proxyResult;
}
if (invoicePayment.getPaymentResource().isSetRecurrentPaymentResource()) {
transactionInfo = createTransactionInfo(
PaymentUtils.generateTransactionId(context.getPaymentInfo()),
Collections.emptyMap()
);
proxyResult = createPaymentProxyResult(
intent,
PaymentState.CAPTURED.getState().getBytes(),
transactionInfo
);
log.info("Processed: success {} with invoiceId {}", proxyResult, invoiceId);
return proxyResult;
}
VerifyEnrollmentResponse verifyEnrollmentResponse = mocketBankMpiApi.verifyEnrollment(
VerifyEnrollmentRequest.builder()
.pan(cardData.getPan())
.year(cardData.getExpYear())
.month(cardData.getExpMonth())
.build());
if (verifyEnrollmentResponse.getEnrolled().equals(MpiEnrollmentStatus.AUTHENTICATION_AVAILABLE.getStatus())) {
String tag = SuspendPrefix.PAYMENT.getPrefix() + PaymentUtils.generateTransactionId(context.getPaymentInfo());
log.info("Processed: suspend tag {} with invoiceId {}", tag, invoiceId);
String url = verifyEnrollmentResponse.getAcsUrl();
Map<String, String> params = new HashMap<>();
params.put("PaReq", verifyEnrollmentResponse.getPaReq());
params.put("MD", tag);
params.put("TermUrl", MockMpiUtils.getCallbackUrl(callbackUrl, "/mocketbank/term_url{?termination_uri}"));
log.info("Processed: prepare redirect params {} with invoiceId {}", params, invoiceId);
intent = createIntentWithSuspendIntent(
tag, timerTimeout, createPostUserInteraction(url, params)
);
}
Map<String, String> extra = new HashMap<>();
extra.put(MpiField.PA_REQ.getValue(), verifyEnrollmentResponse.getPaReq());
log.info("Processed: Extra map {} with invoiceId {}", extra, invoiceId);
byte[] state;
try {
state = Converter.mapToByteArray(extra);
} catch (JsonProcessingException ex) {
String message = "Processed: can't convert map to byte array with invoiceId " + invoiceId;
log.error(message);
throw new IllegalArgumentException(message, ex);
}
proxyResult = createPaymentProxyResult(intent, state, transactionInfo);
log.info("Processed: finish {} with invoiceId {}", proxyResult, invoiceId);
return proxyResult;
}
private PaymentProxyResult captured(PaymentContext context, Map<String, String> options) {
String invoiceId = context.getPaymentInfo().getInvoice().getId();
log.info("Captured start with invoiceId {}", invoiceId);
com.rbkmoney.damsel.proxy_provider.InvoicePayment payment = context.getPaymentInfo().getPayment();
TransactionInfo transactionInfoContractor = payment.getTrx();
TransactionInfo transactionInfo = createTransactionInfo(
transactionInfoContractor.getId(),
transactionInfoContractor.getExtra()
);
context.getSession().setState(PaymentState.CONFIRM.getState().getBytes());
Intent intent = createFinishIntentSuccess();
if (isMakeRecurrent(context)) {
intent = createFinishIntentSuccessWithToken(invoiceId);
}
PaymentProxyResult proxyResult = createPaymentProxyResult(intent, PaymentState.CONFIRM.getState().getBytes(), transactionInfo);
log.info("Captured: proxyResult {} with invoiceId {}", proxyResult, invoiceId);
return proxyResult;
}
private PaymentProxyResult cancelled(PaymentContext context, Map<String, String> options) {
String invoiceId = context.getPaymentInfo().getInvoice().getId();
log.info("Cancelled start with invoiceId {}", invoiceId);
PaymentProxyResult proxyResult = createPaymentProxyResult(
createFinishIntentSuccess(),
PaymentState.CANCELLED.getState().getBytes(),
context.getPaymentInfo().getPayment().getTrx()
);
log.info("Cancelled: proxyResult {} with invoiceId {}", proxyResult, invoiceId);
return proxyResult;
}
private PaymentProxyResult refunded(PaymentContext context, Map<String, String> options) {
String invoiceId = context.getPaymentInfo().getInvoice().getId();
log.info("Refunded start with invoiceId {}", invoiceId);
InvoicePaymentRefund invoicePaymentRefund = context.getPaymentInfo().getRefund();
TransactionInfo paymentRefundTrx = invoicePaymentRefund.getTrx();
TransactionInfo transactionInfo;
if (paymentRefundTrx == null || paymentRefundTrx.getId() == null) {
transactionInfo = createTransactionInfo(invoicePaymentRefund.getId(), options);
} else {
transactionInfo = paymentRefundTrx;
}
PaymentProxyResult proxyResult = createPaymentProxyResult(
createFinishIntentSuccess(),
PaymentState.REFUNDED.getState().getBytes(),
transactionInfo
);
log.info("Refunded end: proxyResult {} with invoiceId {}", proxyResult, invoiceId);
return proxyResult;
}
@Override
public PaymentCallbackResult handlePaymentCallback(ByteBuffer byteBuffer, PaymentContext context) throws TException {
String invoiceId = context.getPaymentInfo().getInvoice().getId();
log.info("handlePaymentCallback start with invoiceId {}", invoiceId);
HashMap<String, String> parameters;
try {
parameters = (HashMap<String, String>) Converter.byteArrayToMap(context.getSession().getState());
parameters.putAll(Converter.byteBufferToMap(byteBuffer));
log.info("handlePaymentCallback: merge params: invoiceId {}, params {}", invoiceId, parameters);
} catch (Exception ex) {
String message = "handlePaymentCallback: merge params error with invoiceId " + invoiceId;
log.error(message, ex);
throw new IllegalArgumentException(message, ex);
}
CardDataProxyModel cardData = cds.getCardData(context);
ValidatePaResResponse validatePaResResponse = mocketBankMpiApi.validatePaRes(
ValidatePaResRequest.builder()
.pan(cardData.getPan())
.paRes(parameters.get("paRes"))
.build());
log.info("handlePaymentCallback: validatePaResResponse {}", validatePaResResponse);
if (validatePaResResponse.getTransactionStatus().equals(MpiTransactionStatus.AUTHENTICATION_SUCCESSFUL.getStatus())) {
byte[] callbackResponse = new byte[0];
com.rbkmoney.damsel.proxy_provider.Intent intent = createFinishIntentSuccess();
TransactionInfo transactionInfo = createTransactionInfo(
PaymentUtils.generateTransactionId(context.getPaymentInfo()),
Collections.emptyMap()
);
PaymentCallbackProxyResult proxyResult = createCallbackProxyResult(
intent, PaymentState.CAPTURED.getState().getBytes(), transactionInfo
);
log.info("handlePaymentCallback: callbackResponse {}, proxyResult {}", callbackResponse, proxyResult);
return createCallbackResult(callbackResponse, proxyResult);
}
Optional<Card> card = CardUtils.extractCardByPan(cardList, cardData.getPan());
MpiAction action = MpiAction.findByValue(card.get().getAction());
String error;
switch (action) {
case THREE_D_SECURE_FAILURE:
error = THREE_D_SECURE_FAILURE.getAction();
break;
case THREE_D_SECURE_TIMEOUT:
error = THREE_D_SECURE_TIMEOUT.getAction();
break;
default:
error = UNKNOWN_FAILURE.getAction();
}
PaymentCallbackResult callbackResult = createCallbackResultFailure(
"error".getBytes(), errorMapping.getFailureByCodeAndDescription(
"HandlePaymentCallback: error", error
)
);
log.info("handlePaymentCallback finish {}, invoice {}", callbackResult, invoiceId);
return callbackResult;
}
public static Optional<BankCardTokenProvider> getBankCardTokenProvider(PaymentContext context) {
Optional<PaymentResource> paymentResource = Optional.ofNullable(context.getPaymentInfo())
.map(PaymentInfo::getPayment)
.map(InvoicePayment::getPaymentResource);
if (paymentResource.isPresent() && paymentResource.get().isSetDisposablePaymentResource()) {
return Optional.ofNullable(context.getPaymentInfo())
.map(PaymentInfo::getPayment)
.map(InvoicePayment::getPaymentResource)
.map(PaymentResource::getDisposablePaymentResource)
.map(DisposablePaymentResource::getPaymentTool)
.map(PaymentTool::getBankCard)
.map(BankCard::getTokenProvider);
}
return Optional.empty();
}
public static Optional<BankCardTokenProvider> getBankCardTokenProvider(RecurrentTokenContext context) {
Optional<DisposablePaymentResource> paymentResource = Optional.ofNullable(context.getTokenInfo())
.map(RecurrentTokenInfo::getPaymentTool)
.map(RecurrentPaymentTool::getPaymentResource);
if (paymentResource.isPresent()) {
return paymentResource
.map(DisposablePaymentResource::getPaymentTool)
.map(PaymentTool::getBankCard)
.map(BankCard::getTokenProvider);
}
return Optional.empty();
}
}

View File

@ -1,30 +1,27 @@
package com.rbkmoney.proxy.mocketbank.handler.mobile.payment;
import com.rbkmoney.damsel.domain.PaymentTool;
import com.rbkmoney.damsel.domain.TargetInvoicePaymentStatus;
import com.rbkmoney.damsel.domain.TransactionInfo;
import com.rbkmoney.damsel.proxy_provider.PaymentContext;
import com.rbkmoney.damsel.proxy_provider.PaymentProxyResult;
import com.rbkmoney.damsel.proxy_provider.PaymentResource;
import com.rbkmoney.proxy.mocketbank.extractor.ProxyProviderPackageExtractors;
import com.rbkmoney.error.mapping.ErrorMapping;
import com.rbkmoney.java.damsel.constant.PaymentState;
import com.rbkmoney.proxy.mocketbank.utils.creator.ProxyProviderCreator;
import com.rbkmoney.proxy.mocketbank.utils.extractor.proxy.ProxyProviderPackageExtractors;
import com.rbkmoney.proxy.mocketbank.handler.mobile.CommonMobileHandler;
import com.rbkmoney.proxy.mocketbank.utils.PaymentUtils;
import com.rbkmoney.proxy.mocketbank.utils.error_mapping.ErrorMapping;
import com.rbkmoney.proxy.mocketbank.utils.mobilephone.MobilePhone;
import com.rbkmoney.proxy.mocketbank.utils.mobilephone.MobilePhoneAction;
import com.rbkmoney.proxy.mocketbank.utils.mobilephone.MobilePhoneUtils;
import com.rbkmoney.proxy.mocketbank.utils.state.constant.PaymentState;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.thrift.TException;
import org.springframework.stereotype.Component;
import java.util.Collections;
import java.util.List;
import java.util.Optional;
import static com.rbkmoney.java.damsel.utils.creators.DomainPackageCreators.createTransactionInfo;
import static com.rbkmoney.java.damsel.utils.creators.ProxyProviderPackageCreators.*;
@Slf4j
@ -49,19 +46,17 @@ public class ProcessedMobileCommonHandler implements CommonMobileHandler {
if (!mobilePhone.isPresent()) {
String error = MobilePhoneAction.UNSUPPORTED_PHONE.getAction();
return createProxyResultFailure(errorMapping.getFailureByCodeAndDescription(error, error));
return createProxyResultFailure(errorMapping.mapFailure(error, error));
}
MobilePhoneAction mobilePhoneAction = MobilePhoneAction.findByValue(mobilePhone.get().getAction());
if (MobilePhoneAction.isFailedAction(mobilePhoneAction.getAction())) {
String error = mobilePhoneAction.getAction();
return createProxyResultFailure(errorMapping.getFailureByCodeAndDescription(error, error));
return createProxyResultFailure(errorMapping.mapFailure(error, error));
}
TransactionInfo transactionInfo = createTransactionInfo(
PaymentUtils.generateTransactionId(context.getPaymentInfo()), Collections.emptyMap()
);
return createPaymentProxyResult(createFinishIntentSuccess(), PaymentState.CAPTURED.getState().getBytes(), transactionInfo);
TransactionInfo transactionInfo = ProxyProviderCreator.createDefaultTransactionInfo(context);
return createPaymentProxyResult(createFinishIntentSuccess(), PaymentState.CAPTURED.getBytes(), transactionInfo);
}
}

View File

@ -1,7 +1,7 @@
package com.rbkmoney.proxy.mocketbank.handler.p2p;
import com.rbkmoney.damsel.p2p_adapter.*;
import com.rbkmoney.proxy.mocketbank.creator.P2pAdapterCreator;
import com.rbkmoney.proxy.mocketbank.utils.creator.P2pAdapterCreator;
import com.rbkmoney.proxy.mocketbank.exception.UnsupportedOperationException;
import lombok.extern.slf4j.Slf4j;
import org.apache.thrift.TException;

View File

@ -0,0 +1,15 @@
package com.rbkmoney.proxy.mocketbank.handler.payment;
import com.rbkmoney.damsel.domain.TargetInvoicePaymentStatus;
import com.rbkmoney.damsel.proxy_provider.PaymentContext;
import com.rbkmoney.damsel.proxy_provider.PaymentProxyResult;
import com.rbkmoney.damsel.proxy_provider.PaymentResource;
import org.apache.thrift.TException;
public interface CommonPaymentHandler {
boolean filter(final TargetInvoicePaymentStatus targetInvoicePaymentStatus, final PaymentResource paymentResource);
PaymentProxyResult handler(PaymentContext context) throws TException;
}

View File

@ -0,0 +1,21 @@
package com.rbkmoney.proxy.mocketbank.handler.payment;
import com.rbkmoney.damsel.domain.TargetInvoicePaymentStatus;
import com.rbkmoney.damsel.proxy_provider.PaymentContext;
import com.rbkmoney.damsel.proxy_provider.PaymentProxyResult;
import com.rbkmoney.damsel.proxy_provider.PaymentResource;
import org.apache.thrift.TException;
public class FallbackPaymentHandler implements CommonPaymentHandler {
@Override
public boolean filter(final TargetInvoicePaymentStatus targetInvoicePaymentStatus, final PaymentResource paymentResource) {
return false;
}
@Override
public PaymentProxyResult handler(final PaymentContext context) throws TException {
throw new TException("Unsupported method");
}
}

View File

@ -0,0 +1,52 @@
package com.rbkmoney.proxy.mocketbank.handler.payment;
import com.rbkmoney.damsel.proxy_provider.*;
import com.rbkmoney.proxy.mocketbank.handler.payment.callback.PaymentCallbackHandler;
import com.rbkmoney.proxy.mocketbank.handler.payment.callback.RecurrentTokenCallbackHandler;
import com.rbkmoney.proxy.mocketbank.handler.payment.recurrent.GenerateTokenHandler;
import com.rbkmoney.proxy.mocketbank.validator.PaymentValidator;
import lombok.RequiredArgsConstructor;
import org.apache.thrift.TException;
import org.springframework.stereotype.Component;
import java.nio.ByteBuffer;
import java.util.List;
@Component
@RequiredArgsConstructor
public class PaymentServerHandler implements ProviderProxySrv.Iface {
private final List<CommonPaymentHandler> handlers;
private final PaymentCallbackHandler paymentCallbackHandler;
private final GenerateTokenHandler generateTokenHandler;
private final RecurrentTokenCallbackHandler recurrentTokenCallbackHandler;
private final PaymentValidator paymentValidator;
@Override
public RecurrentTokenProxyResult generateToken(RecurrentTokenContext context) throws TException {
return generateTokenHandler.handler(context);
}
@Override
public RecurrentTokenCallbackResult handleRecurrentTokenCallback(ByteBuffer callback, RecurrentTokenContext context) throws TException {
return recurrentTokenCallbackHandler.handler(callback, context);
}
@Override
public PaymentProxyResult processPayment(PaymentContext context) throws TException {
paymentValidator.validate(context, context.getOptions());
return handlers.stream()
.filter(handler -> handler.filter(
context.getSession().getTarget(),
context.getPaymentInfo().getPayment().getPaymentResource()
))
.findFirst()
.orElse(new FallbackPaymentHandler())
.handler(context);
}
@Override
public PaymentCallbackResult handlePaymentCallback(ByteBuffer callback, PaymentContext context) throws TException {
return paymentCallbackHandler.handler(callback, context);
}
}

View File

@ -0,0 +1,57 @@
package com.rbkmoney.proxy.mocketbank.handler.payment.callback;
import com.rbkmoney.cds.client.storage.CdsClientStorage;
import com.rbkmoney.cds.client.storage.model.CardDataProxyModel;
import com.rbkmoney.damsel.domain.TransactionInfo;
import com.rbkmoney.damsel.proxy_provider.PaymentCallbackProxyResult;
import com.rbkmoney.damsel.proxy_provider.PaymentCallbackResult;
import com.rbkmoney.damsel.proxy_provider.PaymentContext;
import com.rbkmoney.error.mapping.ErrorMapping;
import com.rbkmoney.java.damsel.constant.Error;
import com.rbkmoney.java.damsel.constant.PaymentState;
import com.rbkmoney.proxy.mocketbank.service.mpi.MpiApi;
import com.rbkmoney.proxy.mocketbank.utils.model.CardAction;
import com.rbkmoney.proxy.mocketbank.service.mpi.model.ValidatePaResResponse;
import com.rbkmoney.proxy.mocketbank.utils.Converter;
import com.rbkmoney.proxy.mocketbank.utils.ErrorBuilder;
import com.rbkmoney.proxy.mocketbank.utils.model.Card;
import com.rbkmoney.proxy.mocketbank.utils.model.CardUtils;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import java.nio.ByteBuffer;
import java.util.HashMap;
import java.util.List;
import static com.rbkmoney.java.damsel.utils.creators.ProxyProviderPackageCreators.*;
import static com.rbkmoney.proxy.mocketbank.utils.creator.ProxyProviderCreator.createDefaultTransactionInfo;
import static com.rbkmoney.proxy.mocketbank.service.mpi.constant.TransactionStatus.isAuthenticationSuccessful;
@Slf4j
@Component
@RequiredArgsConstructor
public class PaymentCallbackHandler {
private final CdsClientStorage cds;
private final MpiApi mpiApi;
private final ErrorMapping errorMapping;
private final List<Card> cardList;
public PaymentCallbackResult handler(ByteBuffer byteBuffer, PaymentContext context) {
HashMap<String, String> parameters = Converter.mergeParams(byteBuffer, context.getSession().getState());
CardDataProxyModel cardData = cds.getCardData(context);
ValidatePaResResponse validatePaResResponse = mpiApi.validatePaRes(cardData, parameters);
if (isAuthenticationSuccessful(validatePaResResponse.getTransactionStatus())) {
TransactionInfo transactionInfo = createDefaultTransactionInfo(context);
PaymentCallbackProxyResult proxyResult = createCallbackProxyResult(
createFinishIntentSuccess(), PaymentState.CAPTURED.getBytes(), transactionInfo
);
return createCallbackResult("".getBytes(), proxyResult);
}
CardAction action = CardUtils.extractActionFromCard(cardList, cardData);
return ErrorBuilder.prepareCallbackError(errorMapping, Error.DEFAULT_ERROR_CODE, action);
}
}

View File

@ -0,0 +1,56 @@
package com.rbkmoney.proxy.mocketbank.handler.payment.callback;
import com.rbkmoney.cds.client.storage.CdsClientStorage;
import com.rbkmoney.cds.client.storage.model.CardDataProxyModel;
import com.rbkmoney.damsel.proxy_provider.RecurrentTokenCallbackResult;
import com.rbkmoney.damsel.proxy_provider.RecurrentTokenContext;
import com.rbkmoney.damsel.proxy_provider.RecurrentTokenIntent;
import com.rbkmoney.damsel.proxy_provider.RecurrentTokenProxyResult;
import com.rbkmoney.error.mapping.ErrorMapping;
import com.rbkmoney.java.damsel.constant.Error;
import com.rbkmoney.java.damsel.constant.PaymentState;
import com.rbkmoney.proxy.mocketbank.service.mpi.MpiApi;
import com.rbkmoney.proxy.mocketbank.utils.model.CardAction;
import com.rbkmoney.proxy.mocketbank.service.mpi.model.ValidatePaResResponse;
import com.rbkmoney.proxy.mocketbank.utils.Converter;
import com.rbkmoney.proxy.mocketbank.utils.ErrorBuilder;
import com.rbkmoney.proxy.mocketbank.utils.model.Card;
import com.rbkmoney.proxy.mocketbank.utils.model.CardUtils;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import java.nio.ByteBuffer;
import java.util.HashMap;
import java.util.List;
import static com.rbkmoney.java.damsel.utils.creators.ProxyProviderPackageCreators.*;
import static com.rbkmoney.java.damsel.utils.extractors.ProxyProviderPackageExtractors.extractRecurrentId;
import static com.rbkmoney.proxy.mocketbank.service.mpi.constant.TransactionStatus.isAuthenticationSuccessful;
@Slf4j
@Component
@RequiredArgsConstructor
public class RecurrentTokenCallbackHandler {
private final CdsClientStorage cds;
private final MpiApi mpiApi;
private final ErrorMapping errorMapping;
private final List<Card> cardList;
public RecurrentTokenCallbackResult handler(ByteBuffer byteBuffer, RecurrentTokenContext context) {
String recurrentId = extractRecurrentId(context);
HashMap<String, String> parameters = Converter.mergeParams(byteBuffer, context.getSession().getState());
CardDataProxyModel cardData = cds.getCardData(context);
ValidatePaResResponse validatePaResResponse = mpiApi.validatePaRes(cardData, parameters);
if (isAuthenticationSuccessful(validatePaResResponse.getTransactionStatus())) {
RecurrentTokenIntent intent = createRecurrentTokenFinishIntentSuccess(recurrentId);
RecurrentTokenProxyResult proxyResult = createRecurrentTokenProxyResult(intent, PaymentState.PENDING.getBytes());
return createRecurrentTokenCallbackResult("".getBytes(), proxyResult);
}
CardAction action = CardUtils.extractActionFromCard(cardList, cardData);
return ErrorBuilder.prepareRecurrentCallbackError(errorMapping, Error.DEFAULT_ERROR_CODE, action);
}
}

View File

@ -0,0 +1,34 @@
package com.rbkmoney.proxy.mocketbank.handler.payment.common;
import com.rbkmoney.damsel.domain.TargetInvoicePaymentStatus;
import com.rbkmoney.damsel.proxy_provider.PaymentContext;
import com.rbkmoney.damsel.proxy_provider.PaymentProxyResult;
import com.rbkmoney.damsel.proxy_provider.PaymentResource;
import com.rbkmoney.java.damsel.constant.PaymentState;
import com.rbkmoney.proxy.mocketbank.handler.payment.CommonPaymentHandler;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.thrift.TException;
import org.springframework.stereotype.Component;
import static com.rbkmoney.java.damsel.utils.creators.ProxyProviderPackageCreators.createFinishIntentSuccess;
import static com.rbkmoney.java.damsel.utils.creators.ProxyProviderPackageCreators.createPaymentProxyResult;
@Slf4j
@Component
@RequiredArgsConstructor
public class CancelledCommonPaymentHandler implements CommonPaymentHandler {
@Override
public boolean filter(TargetInvoicePaymentStatus targetInvoicePaymentStatus, PaymentResource paymentResource) {
return targetInvoicePaymentStatus.isSetCancelled();
}
@Override
public PaymentProxyResult handler(PaymentContext context) throws TException {
return createPaymentProxyResult(createFinishIntentSuccess(),
PaymentState.CANCELLED.getBytes(), context.getPaymentInfo().getPayment().getTrx()
);
}
}

View File

@ -0,0 +1,41 @@
package com.rbkmoney.proxy.mocketbank.handler.payment.common;
import com.rbkmoney.damsel.domain.TargetInvoicePaymentStatus;
import com.rbkmoney.damsel.proxy_provider.*;
import com.rbkmoney.java.damsel.constant.PaymentState;
import com.rbkmoney.proxy.mocketbank.handler.payment.CommonPaymentHandler;
import com.rbkmoney.proxy.mocketbank.validator.PaymentCapturedValidator;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.thrift.TException;
import org.springframework.stereotype.Component;
import static com.rbkmoney.java.damsel.utils.creators.ProxyProviderPackageCreators.*;
import static com.rbkmoney.java.damsel.utils.extractors.ProxyProviderPackageExtractors.extractInvoiceId;
import static com.rbkmoney.java.damsel.utils.verification.ProxyProviderVerification.isMakeRecurrent;
@Slf4j
@Component
@RequiredArgsConstructor
public class CapturedCommonPaymentHandler implements CommonPaymentHandler {
private final PaymentCapturedValidator paymentCapturedValidator;
@Override
public boolean filter(TargetInvoicePaymentStatus targetInvoicePaymentStatus, PaymentResource paymentResource) {
return targetInvoicePaymentStatus.isSetCaptured();
}
@Override
public PaymentProxyResult handler(PaymentContext context) throws TException {
paymentCapturedValidator.validate(context, context.getOptions());
Intent intent = createFinishIntentSuccess();
if (isMakeRecurrent(context)) {
String invoiceId = extractInvoiceId(context);
intent = createFinishIntentSuccessWithToken(invoiceId);
}
InvoicePayment payment = context.getPaymentInfo().getPayment();
return createPaymentProxyResult(intent, PaymentState.CONFIRM.getBytes(), payment.getTrx());
}
}

View File

@ -0,0 +1,127 @@
package com.rbkmoney.proxy.mocketbank.handler.payment.common;
import com.rbkmoney.cds.client.storage.CdsClientStorage;
import com.rbkmoney.cds.client.storage.model.CardDataProxyModel;
import com.rbkmoney.damsel.domain.Failure;
import com.rbkmoney.damsel.domain.OperationFailure;
import com.rbkmoney.damsel.domain.TargetInvoicePaymentStatus;
import com.rbkmoney.damsel.domain.TransactionInfo;
import com.rbkmoney.damsel.proxy_provider.Intent;
import com.rbkmoney.damsel.proxy_provider.PaymentContext;
import com.rbkmoney.damsel.proxy_provider.PaymentProxyResult;
import com.rbkmoney.damsel.proxy_provider.PaymentResource;
import com.rbkmoney.damsel.timeout_behaviour.TimeoutBehaviour;
import com.rbkmoney.error.mapping.ErrorMapping;
import com.rbkmoney.java.damsel.constant.PaymentState;
import com.rbkmoney.proxy.mocketbank.configuration.properties.AdapterMockBankProperties;
import com.rbkmoney.proxy.mocketbank.configuration.properties.TimerProperties;
import com.rbkmoney.proxy.mocketbank.handler.payment.CommonPaymentHandler;
import com.rbkmoney.proxy.mocketbank.service.bank.constant.CustomError;
import com.rbkmoney.proxy.mocketbank.service.mpi.MpiApi;
import com.rbkmoney.proxy.mocketbank.service.mpi.constant.EnrollmentStatus;
import com.rbkmoney.proxy.mocketbank.service.mpi.model.VerifyEnrollmentResponse;
import com.rbkmoney.proxy.mocketbank.utils.ErrorBuilder;
import com.rbkmoney.proxy.mocketbank.utils.UrlUtils;
import com.rbkmoney.proxy.mocketbank.utils.creator.ProxyProviderCreator;
import com.rbkmoney.proxy.mocketbank.utils.model.Card;
import com.rbkmoney.proxy.mocketbank.utils.model.CardAction;
import com.rbkmoney.proxy.mocketbank.utils.model.CardUtils;
import com.rbkmoney.proxy.mocketbank.utils.state.StateUtils;
import com.rbkmoney.proxy.mocketbank.utils.state.constant.SuspendPrefix;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.thrift.TException;
import org.springframework.stereotype.Component;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import static com.rbkmoney.java.damsel.constant.Error.DEFAULT_ERROR_CODE;
import static com.rbkmoney.java.damsel.utils.creators.ProxyProviderPackageCreators.*;
import static com.rbkmoney.java.damsel.utils.extractors.OptionsExtractors.extractRedirectTimeout;
import static com.rbkmoney.java.damsel.utils.extractors.ProxyProviderPackageExtractors.extractInvoiceId;
import static com.rbkmoney.java.damsel.utils.verification.ProxyProviderVerification.isMakeRecurrent;
import static com.rbkmoney.proxy.mocketbank.service.mpi.constant.EnrollmentStatus.isAuthenticationAvailable;
import static com.rbkmoney.proxy.mocketbank.utils.UrlUtils.prepareRedirectParams;
import static com.rbkmoney.proxy.mocketbank.utils.creator.ProxyProviderCreator.createDefaultTransactionInfo;
import static com.rbkmoney.proxy.mocketbank.utils.extractor.proxy.ProxyProviderPackageExtractors.hasBankCardTokenProvider;
import static com.rbkmoney.proxy.mocketbank.utils.model.CardAction.*;
@Slf4j
@Component
@RequiredArgsConstructor
public class ProcessedCommonPaymentHandler implements CommonPaymentHandler {
private final CdsClientStorage cds;
private final MpiApi mpiApi;
private final ErrorMapping errorMapping;
private final List<Card> cardList;
private final TimerProperties timerProperties;
private final AdapterMockBankProperties mockBankProperties;
@Override
public boolean filter(TargetInvoicePaymentStatus targetInvoicePaymentStatus, PaymentResource paymentResource) {
return targetInvoicePaymentStatus.isSetProcessed() && paymentResource.isSetDisposablePaymentResource();
}
@Override
public PaymentProxyResult handler(PaymentContext context) throws TException {
Intent intent = createFinishIntentSuccess();
if (isMakeRecurrent(context)) {
String invoiceId = extractInvoiceId(context);
intent = createFinishIntentSuccessWithToken(invoiceId);
}
// Applepay, Samsungpay, Googlepay - always successful and does not depends on card
TransactionInfo transactionInfo = createDefaultTransactionInfo(context);
if (hasBankCardTokenProvider(context)) {
return createPaymentProxyResult(intent, PaymentState.CAPTURED.getBytes(), transactionInfo);
}
CardDataProxyModel cardData = cds.getCardData(context);
Optional<Card> card = CardUtils.extractCardByPan(cardList, cardData.getPan());
if (card.isPresent()) {
CardAction action = CardAction.findByValue(card.get().getAction());
if (CardAction.isCardEnrolled(card.get())) {
return prepareEnrolledPaymentProxyResult(context, intent, transactionInfo, cardData);
}
return prepareNotEnrolledPaymentProxyResult(intent, transactionInfo, action);
}
return ErrorBuilder.prepareError(errorMapping, UNSUPPORTED_CARD);
}
private PaymentProxyResult prepareNotEnrolledPaymentProxyResult(Intent intent, TransactionInfo transactionInfo, CardAction action) {
if (isCardSuccess(action)) {
return createPaymentProxyResult(intent, PaymentState.CAPTURED.getBytes(), transactionInfo);
}
CardAction currentAction = isCardFailed(action) ? action : UNKNOWN_FAILURE;
return ErrorBuilder.prepareError(errorMapping, currentAction);
}
private PaymentProxyResult prepareEnrolledPaymentProxyResult(PaymentContext context, Intent intent, TransactionInfo transactionInfo, CardDataProxyModel cardData) {
Intent currentIntent = intent;
VerifyEnrollmentResponse verifyEnrollmentResponse = mpiApi.verifyEnrollment(cardData);
if (isAuthenticationAvailable(verifyEnrollmentResponse.getEnrolled())) {
String tag = SuspendPrefix.PAYMENT.getPrefix() + ProxyProviderCreator.createTransactionId(context.getPaymentInfo());
String termUrl = UrlUtils.getCallbackUrl(mockBankProperties.getCallbackUrl(), mockBankProperties.getPathCallbackUrl());
currentIntent = prepareRedirect(context, verifyEnrollmentResponse, tag, termUrl);
}
byte[] state = StateUtils.prepareState(verifyEnrollmentResponse);
return createPaymentProxyResult(currentIntent, state, transactionInfo);
}
private Intent prepareRedirect(PaymentContext context, VerifyEnrollmentResponse verifyEnrollmentResponse, String tag, String termUrl) {
String url = verifyEnrollmentResponse.getAcsUrl();
Map<String, String> params = prepareRedirectParams(verifyEnrollmentResponse, tag, termUrl);
Map<String, String> options = context.getOptions();
int timerRedirectTimeout = extractRedirectTimeout(options, timerProperties.getRedirectTimeout());
Intent intent = createIntentWithSuspendIntent(
tag, timerRedirectTimeout, createPostUserInteraction(url, params)
);
Failure failure = errorMapping.mapFailure(DEFAULT_ERROR_CODE, CustomError.THREE_DS_NOT_FINISHED);
intent.getSuspend().setTimeoutBehaviour(TimeoutBehaviour.operation_failure(OperationFailure.failure(failure)));
return intent;
}
}

View File

@ -0,0 +1,38 @@
package com.rbkmoney.proxy.mocketbank.handler.payment.common;
import com.rbkmoney.damsel.domain.TargetInvoicePaymentStatus;
import com.rbkmoney.damsel.proxy_provider.PaymentContext;
import com.rbkmoney.damsel.proxy_provider.PaymentProxyResult;
import com.rbkmoney.damsel.proxy_provider.PaymentResource;
import com.rbkmoney.java.damsel.constant.PaymentState;
import com.rbkmoney.proxy.mocketbank.handler.payment.CommonPaymentHandler;
import com.rbkmoney.proxy.mocketbank.validator.PaymentRefundedValidator;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.thrift.TException;
import org.springframework.stereotype.Component;
import static com.rbkmoney.java.damsel.utils.creators.ProxyProviderPackageCreators.createFinishIntentSuccess;
import static com.rbkmoney.java.damsel.utils.creators.ProxyProviderPackageCreators.createPaymentProxyResult;
@Slf4j
@Component
@RequiredArgsConstructor
public class RefundedCommonPaymentHandler implements CommonPaymentHandler {
private final PaymentRefundedValidator paymentRefundedValidator;
@Override
public boolean filter(TargetInvoicePaymentStatus targetInvoicePaymentStatus, PaymentResource paymentResource) {
return targetInvoicePaymentStatus.isSetRefunded();
}
@Override
public PaymentProxyResult handler(PaymentContext context) throws TException {
paymentRefundedValidator.validate(context, context.getOptions());
return createPaymentProxyResult(createFinishIntentSuccess(),
PaymentState.REFUNDED.getBytes(), context.getPaymentInfo().getRefund().getTrx()
);
}
}

View File

@ -0,0 +1,108 @@
package com.rbkmoney.proxy.mocketbank.handler.payment.recurrent;
import com.rbkmoney.cds.client.storage.CdsClientStorage;
import com.rbkmoney.cds.client.storage.model.CardDataProxyModel;
import com.rbkmoney.damsel.domain.Failure;
import com.rbkmoney.damsel.domain.OperationFailure;
import com.rbkmoney.damsel.proxy_provider.RecurrentTokenContext;
import com.rbkmoney.damsel.proxy_provider.RecurrentTokenIntent;
import com.rbkmoney.damsel.proxy_provider.RecurrentTokenProxyResult;
import com.rbkmoney.damsel.timeout_behaviour.TimeoutBehaviour;
import com.rbkmoney.error.mapping.ErrorMapping;
import com.rbkmoney.java.damsel.constant.PaymentState;
import com.rbkmoney.proxy.mocketbank.configuration.properties.AdapterMockBankProperties;
import com.rbkmoney.proxy.mocketbank.configuration.properties.TimerProperties;
import com.rbkmoney.proxy.mocketbank.service.bank.constant.CustomError;
import com.rbkmoney.proxy.mocketbank.service.mpi.MpiApi;
import com.rbkmoney.proxy.mocketbank.service.mpi.model.VerifyEnrollmentResponse;
import com.rbkmoney.proxy.mocketbank.utils.ErrorBuilder;
import com.rbkmoney.proxy.mocketbank.utils.UrlUtils;
import com.rbkmoney.proxy.mocketbank.utils.model.Card;
import com.rbkmoney.proxy.mocketbank.utils.model.CardAction;
import com.rbkmoney.proxy.mocketbank.utils.model.CardUtils;
import com.rbkmoney.proxy.mocketbank.utils.state.StateUtils;
import com.rbkmoney.proxy.mocketbank.utils.state.constant.SuspendPrefix;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import static com.rbkmoney.java.damsel.constant.Error.DEFAULT_ERROR_CODE;
import static com.rbkmoney.java.damsel.utils.creators.ProxyProviderPackageCreators.*;
import static com.rbkmoney.java.damsel.utils.extractors.OptionsExtractors.extractRedirectTimeout;
import static com.rbkmoney.java.damsel.utils.extractors.ProxyProviderPackageExtractors.extractRecurrentId;
import static com.rbkmoney.proxy.mocketbank.service.mpi.constant.EnrollmentStatus.isAuthenticationAvailable;
import static com.rbkmoney.proxy.mocketbank.utils.UrlUtils.prepareRedirectParams;
import static com.rbkmoney.proxy.mocketbank.utils.extractor.proxy.ProxyProviderPackageExtractors.hasBankCardTokenProvider;
import static com.rbkmoney.proxy.mocketbank.utils.model.CardAction.*;
@Slf4j
@Component
@RequiredArgsConstructor
public class GenerateTokenHandler {
private final CdsClientStorage cds;
private final MpiApi mpiApi;
private final ErrorMapping errorMapping;
private final List<Card> cardList;
private final TimerProperties timerProperties;
private final AdapterMockBankProperties mockBankProperties;
public RecurrentTokenProxyResult handler(RecurrentTokenContext context) {
String recurrentId = extractRecurrentId(context);
RecurrentTokenIntent intent = createRecurrentTokenFinishIntentSuccess(recurrentId);
// Applepay, Samsungpay, Googlepay - always successful and does not depends on card
if (hasBankCardTokenProvider(context)) {
return createRecurrentTokenProxyResult(intent);
}
CardDataProxyModel cardData = cds.getCardData(context);
Optional<Card> card = CardUtils.extractCardByPan(cardList, cardData.getPan());
if (card.isPresent()) {
CardAction action = CardAction.findByValue(card.get().getAction());
if (CardAction.isCardEnrolled(card.get())) {
return prepareEnrolledRecurrentTokenProxyResult(context, intent, cardData);
}
return prepareNotEnrolledRecurrentTokenProxyResult(intent, action);
}
return ErrorBuilder.prepareRecurrentTokenError(errorMapping, UNSUPPORTED_CARD);
}
private RecurrentTokenProxyResult prepareNotEnrolledRecurrentTokenProxyResult(RecurrentTokenIntent intent, CardAction action) {
if (isCardSuccess(action)) {
return createRecurrentTokenProxyResult(intent, PaymentState.CAPTURED.getBytes());
}
CardAction currentAction = isCardFailed(action) ? action : UNKNOWN_FAILURE;
return ErrorBuilder.prepareRecurrentTokenError(errorMapping, currentAction);
}
private RecurrentTokenProxyResult prepareEnrolledRecurrentTokenProxyResult(RecurrentTokenContext context, RecurrentTokenIntent intent, CardDataProxyModel cardData) {
RecurrentTokenIntent recurrentTokenIntent = intent;
VerifyEnrollmentResponse verifyEnrollmentResponse = mpiApi.verifyEnrollment(cardData);
if (isAuthenticationAvailable(verifyEnrollmentResponse.getEnrolled())) {
String tag = SuspendPrefix.RECURRENT.getPrefix() + context.getTokenInfo().getPaymentTool().getId();
String termUrl = UrlUtils.getCallbackUrl(mockBankProperties.getCallbackUrl(), mockBankProperties.getPathRecurrentCallbackUrl());
recurrentTokenIntent = prepareRedirect(context, verifyEnrollmentResponse, tag, termUrl);
}
byte[] state = StateUtils.prepareState(verifyEnrollmentResponse);
return createRecurrentTokenProxyResult(recurrentTokenIntent, state);
}
private RecurrentTokenIntent prepareRedirect(RecurrentTokenContext context, VerifyEnrollmentResponse verifyEnrollmentResponse, String tag, String termUrl) {
String url = verifyEnrollmentResponse.getAcsUrl();
Map<String, String> params = prepareRedirectParams(verifyEnrollmentResponse, tag, termUrl);
Map<String, String> options = context.getOptions();
int timerRedirectTimeout = extractRedirectTimeout(options, timerProperties.getRedirectTimeout());
RecurrentTokenIntent recurrentTokenIntent = createRecurrentTokenWithSuspendIntent(
tag, timerRedirectTimeout, createPostUserInteraction(url, params)
);
Failure failure = errorMapping.mapFailure(DEFAULT_ERROR_CODE, CustomError.THREE_DS_NOT_FINISHED);
recurrentTokenIntent.getSuspend().setTimeoutBehaviour(TimeoutBehaviour.operation_failure(OperationFailure.failure(failure)));
return recurrentTokenIntent;
}
}

View File

@ -0,0 +1,42 @@
package com.rbkmoney.proxy.mocketbank.handler.payment.recurrent;
import com.rbkmoney.damsel.domain.TargetInvoicePaymentStatus;
import com.rbkmoney.damsel.domain.TransactionInfo;
import com.rbkmoney.damsel.proxy_provider.Intent;
import com.rbkmoney.damsel.proxy_provider.PaymentContext;
import com.rbkmoney.damsel.proxy_provider.PaymentProxyResult;
import com.rbkmoney.damsel.proxy_provider.PaymentResource;
import com.rbkmoney.java.damsel.constant.PaymentState;
import com.rbkmoney.proxy.mocketbank.utils.creator.ProxyProviderCreator;
import com.rbkmoney.proxy.mocketbank.handler.payment.CommonPaymentHandler;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.thrift.TException;
import org.springframework.stereotype.Component;
import static com.rbkmoney.java.damsel.utils.creators.ProxyProviderPackageCreators.*;
import static com.rbkmoney.java.damsel.utils.extractors.ProxyProviderPackageExtractors.extractInvoiceId;
import static com.rbkmoney.java.damsel.utils.verification.ProxyProviderVerification.isMakeRecurrent;
@Slf4j
@Component
@RequiredArgsConstructor
public class ProcessedRecurrentCommonPaymentHandler implements CommonPaymentHandler {
@Override
public boolean filter(TargetInvoicePaymentStatus targetInvoicePaymentStatus, PaymentResource paymentResource) {
return targetInvoicePaymentStatus.isSetProcessed() && paymentResource.isSetRecurrentPaymentResource();
}
@Override
public PaymentProxyResult handler(PaymentContext context) throws TException {
Intent intent = createFinishIntentSuccess();
if (isMakeRecurrent(context)) {
String invoiceId = extractInvoiceId(context);
intent = createFinishIntentSuccessWithToken(invoiceId);
}
TransactionInfo transactionInfo = ProxyProviderCreator.createDefaultTransactionInfo(context);
return createPaymentProxyResult(intent, PaymentState.CAPTURED.getBytes(), transactionInfo);
}
}

View File

@ -4,14 +4,12 @@ import com.rbkmoney.damsel.proxy_provider.*;
import com.rbkmoney.proxy.mocketbank.handler.terminal.payment.UnsupportedTerminalHandler;
import com.rbkmoney.proxy.mocketbank.validator.TerminalValidator;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.thrift.TException;
import org.springframework.stereotype.Component;
import java.nio.ByteBuffer;
import java.util.List;
@Slf4j
@Component
@RequiredArgsConstructor
public class TerminalServerHandler implements ProviderProxySrv.Iface {

View File

@ -5,17 +5,14 @@ import com.rbkmoney.damsel.domain.TransactionInfo;
import com.rbkmoney.damsel.proxy_provider.PaymentContext;
import com.rbkmoney.damsel.proxy_provider.PaymentProxyResult;
import com.rbkmoney.damsel.proxy_provider.PaymentResource;
import com.rbkmoney.java.damsel.constant.PaymentState;
import com.rbkmoney.proxy.mocketbank.utils.creator.ProxyProviderCreator;
import com.rbkmoney.proxy.mocketbank.handler.terminal.CommonTerminalHandler;
import com.rbkmoney.proxy.mocketbank.utils.PaymentUtils;
import com.rbkmoney.proxy.mocketbank.utils.state.constant.PaymentState;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.thrift.TException;
import org.springframework.stereotype.Component;
import java.util.Collections;
import static com.rbkmoney.java.damsel.utils.creators.DomainPackageCreators.createTransactionInfo;
import static com.rbkmoney.java.damsel.utils.creators.ProxyProviderPackageCreators.createFinishIntentSuccess;
import static com.rbkmoney.java.damsel.utils.creators.ProxyProviderPackageCreators.createPaymentProxyResult;
@ -31,10 +28,8 @@ public class ProcessedTerminalCommonHandler implements CommonTerminalHandler {
@Override
public PaymentProxyResult handler(PaymentContext context) throws TException {
TransactionInfo transactionInfo = createTransactionInfo(
PaymentUtils.generateTransactionId(context.getPaymentInfo()), Collections.emptyMap()
);
return createPaymentProxyResult(createFinishIntentSuccess(), PaymentState.CAPTURED.getState().getBytes(), transactionInfo);
TransactionInfo transactionInfo = ProxyProviderCreator.createDefaultTransactionInfo(context);
return createPaymentProxyResult(createFinishIntentSuccess(), PaymentState.CAPTURED.getBytes(), transactionInfo);
}
}

View File

@ -0,0 +1,9 @@
package com.rbkmoney.proxy.mocketbank.service.bank.constant;
import lombok.AccessLevel;
import lombok.NoArgsConstructor;
@NoArgsConstructor(access = AccessLevel.PRIVATE)
public class CustomError {
public static final String THREE_DS_NOT_FINISHED = "3DS_NOT_FINISHED";
}

View File

@ -1,34 +1,58 @@
package com.rbkmoney.proxy.mocketbank.utils.mocketbank;
package com.rbkmoney.proxy.mocketbank.service.mpi;
import com.rbkmoney.cds.client.storage.model.CardDataProxyModel;
import com.rbkmoney.proxy.mocketbank.configuration.properties.AdapterMockMpiProperties;
import com.rbkmoney.proxy.mocketbank.utils.mocketbank.model.*;
import com.rbkmoney.proxy.mocketbank.service.mpi.model.*;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import org.springframework.web.client.RestTemplate;
import java.util.Map;
@Slf4j
@Component
@RequiredArgsConstructor
public class MockMpiApi {
public class MpiApi {
private final RestTemplate restTemplate;
private final AdapterMockMpiProperties adapterMockMpiProperties;
public VerifyEnrollmentResponse verifyEnrollment(CardDataProxyModel cardData) {
VerifyEnrollmentRequest request = VerifyEnrollmentRequest.builder()
.pan(cardData.getPan())
.year(cardData.getExpYear())
.month(cardData.getExpMonth())
.build();
return verifyEnrollment(request);
}
public VerifyEnrollmentResponse verifyEnrollment(VerifyEnrollmentRequest request) {
return sendMessage("verifyEnrollment", request, VerifyEnrollmentResponse.class);
}
public ValidatePaResResponse validatePaRes(CardDataProxyModel cardData, Map<String, String> options) {
ValidatePaResRequest request = ValidatePaResRequest.builder()
.pan(cardData.getPan())
.paRes(options.get("paRes"))
.build();
return validatePaRes(request);
}
public ValidatePaResResponse validatePaRes(ValidatePaResRequest request) {
return sendMessage("validatePaRes", request, ValidatePaResResponse.class);
}
private <T> T sendMessage(String methodName, PrepareFieldsObject request, Class<T> responseClass) {
String prepareUrl = MockMpiUtils.prepareUrl(adapterMockMpiProperties.getUrl(), methodName);
String prepareUrl = prepareUrl(adapterMockMpiProperties.getUrl(), methodName);
log.info("MockMpi {} url: {} with request: {}", methodName, prepareUrl, request);
T response = restTemplate.postForObject(prepareUrl, request.prepareFields(), responseClass);
log.info("MockMpi {} url: {} with response: {}", methodName, prepareUrl, response);
return response;
}
private String prepareUrl(String url, String path) {
return String.format("%s/mpi/%s", url, path);
}
}

View File

@ -1,4 +1,4 @@
package com.rbkmoney.proxy.mocketbank.utils.mocketbank.constant;
package com.rbkmoney.proxy.mocketbank.service.mpi.constant;
import lombok.Getter;
import lombok.RequiredArgsConstructor;
@ -9,7 +9,7 @@ import lombok.RequiredArgsConstructor;
*/
@Getter
@RequiredArgsConstructor
public enum MpiCavvAlgorithm {
public enum CavvAlgorithm {
/**
* 0: HMAC (as per SET TransStain) (no longer in use for version 1.0.2)

View File

@ -1,4 +1,4 @@
package com.rbkmoney.proxy.mocketbank.utils.mocketbank.constant;
package com.rbkmoney.proxy.mocketbank.service.mpi.constant;
import lombok.Getter;
import lombok.RequiredArgsConstructor;
@ -8,7 +8,7 @@ import lombok.RequiredArgsConstructor;
*/
@Getter
@RequiredArgsConstructor
public enum MpiEnrollmentStatus {
public enum EnrollmentStatus {
/**
* Authentication Available Cardholder is enrolled, Activation During Shopping is
@ -30,4 +30,8 @@ public enum MpiEnrollmentStatus {
private final String status;
public static boolean isAuthenticationAvailable(String status) {
return AUTHENTICATION_AVAILABLE.getStatus().equalsIgnoreCase(status);
}
}

View File

@ -1,4 +1,4 @@
package com.rbkmoney.proxy.mocketbank.utils.mocketbank.constant;
package com.rbkmoney.proxy.mocketbank.service.mpi.constant;
import lombok.Getter;
import lombok.RequiredArgsConstructor;
@ -9,11 +9,18 @@ public enum MpiField {
MESSAGE_ID("messageId"),
PA_REQ("PaReq"),
MD("MD"),
PA_RES("PaRes"),
TERM_URL("TermUrl"),
PA_REQ_CREATION_TIME("paReqCreationTime"),
ACS_URL("acsUrl"),
ACCT_ID("acctId"),
PURCHASE_XID("purchaseXId");
PURCHASE_XID("purchaseXId"),
PAN("pan"),
YEAR("year"),
PARES("paRes"),
MONTH("month");
private final String value;
}

View File

@ -1,11 +1,11 @@
package com.rbkmoney.proxy.mocketbank.utils.mocketbank.constant;
package com.rbkmoney.proxy.mocketbank.service.mpi.constant;
import lombok.Getter;
import lombok.RequiredArgsConstructor;
@Getter
@RequiredArgsConstructor
public enum MpiTransactionStatus {
public enum TransactionStatus {
/**
* The merchant submits an authorization request including the
@ -33,4 +33,8 @@ public enum MpiTransactionStatus {
private final String status;
public static boolean isAuthenticationSuccessful(String status) {
return AUTHENTICATION_SUCCESSFUL.getStatus().equalsIgnoreCase(status);
}
}

View File

@ -1,4 +1,4 @@
package com.rbkmoney.proxy.mocketbank.utils.mocketbank.model;
package com.rbkmoney.proxy.mocketbank.service.mpi.model;
import org.springframework.util.MultiValueMap;

View File

@ -1,6 +1,6 @@
package com.rbkmoney.proxy.mocketbank.utils.mocketbank.model;
package com.rbkmoney.proxy.mocketbank.service.mpi.model;
import com.rbkmoney.proxy.mocketbank.utils.mocketbank.constant.MpiRequestField;
import com.rbkmoney.proxy.mocketbank.service.mpi.constant.MpiField;
import com.rbkmoney.proxy.mocketbank.utils.model.CreditCardUtils;
import lombok.Builder;
import lombok.Data;
@ -19,8 +19,8 @@ public class ValidatePaResRequest implements PrepareFieldsObject {
@Override
public MultiValueMap<String, Object> prepareFields() {
MultiValueMap<String, Object> prepareFields = new LinkedMultiValueMap<>();
prepareFields.add(MpiRequestField.PAN.getValue(), pan);
prepareFields.add(MpiRequestField.PARES.getValue(), paRes);
prepareFields.add(MpiField.PAN.getValue(), pan);
prepareFields.add(MpiField.PARES.getValue(), paRes);
return prepareFields;
}

View File

@ -1,4 +1,4 @@
package com.rbkmoney.proxy.mocketbank.utils.mocketbank.model;
package com.rbkmoney.proxy.mocketbank.service.mpi.model;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonProperty;

View File

@ -1,6 +1,6 @@
package com.rbkmoney.proxy.mocketbank.utils.mocketbank.model;
package com.rbkmoney.proxy.mocketbank.service.mpi.model;
import com.rbkmoney.proxy.mocketbank.utils.mocketbank.constant.MpiRequestField;
import com.rbkmoney.proxy.mocketbank.service.mpi.constant.MpiField;
import com.rbkmoney.proxy.mocketbank.utils.model.CreditCardUtils;
import lombok.Builder;
import lombok.Data;
@ -20,9 +20,9 @@ public class VerifyEnrollmentRequest implements PrepareFieldsObject {
@Override
public MultiValueMap<String, Object> prepareFields() {
MultiValueMap<String, Object> prepareFields = new LinkedMultiValueMap<>();
prepareFields.add(MpiRequestField.PAN.getValue(), pan);
prepareFields.add(MpiRequestField.YEAR.getValue(), String.valueOf(year));
prepareFields.add(MpiRequestField.MONTH.getValue(), String.valueOf(month));
prepareFields.add(MpiField.PAN.getValue(), pan);
prepareFields.add(MpiField.YEAR.getValue(), String.valueOf(year));
prepareFields.add(MpiField.MONTH.getValue(), String.valueOf(month));
return prepareFields;
}

View File

@ -1,4 +1,4 @@
package com.rbkmoney.proxy.mocketbank.utils.mocketbank.model;
package com.rbkmoney.proxy.mocketbank.service.mpi.model;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonProperty;

View File

@ -1,7 +1,7 @@
package com.rbkmoney.proxy.mocketbank.servlet;
import com.rbkmoney.damsel.proxy_provider.ProviderProxySrv;
import com.rbkmoney.proxy.mocketbank.handler.MocketBankServerHandlerMdcDecorator;
import com.rbkmoney.proxy.mocketbank.decorator.PaymentServerHandlerMdcLog;
import com.rbkmoney.woody.thrift.impl.http.THServiceBuilder;
import lombok.RequiredArgsConstructor;
@ -13,7 +13,7 @@ import java.io.IOException;
@WebServlet("/proxy/mocketbank")
public class AdapterServletPayment extends GenericServlet {
private final transient MocketBankServerHandlerMdcDecorator handler;
private final transient PaymentServerHandlerMdcLog handler;
private transient Servlet servlet;
@Override

View File

@ -2,6 +2,8 @@ package com.rbkmoney.proxy.mocketbank.utils;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.AccessLevel;
import lombok.NoArgsConstructor;
import java.io.IOException;
import java.nio.ByteBuffer;
@ -9,6 +11,7 @@ import java.nio.charset.StandardCharsets;
import java.util.HashMap;
import java.util.Map;
@NoArgsConstructor(access = AccessLevel.PRIVATE)
public class Converter {
public static Map byteBufferToMap(ByteBuffer byteBuffer) throws IOException {
@ -38,4 +41,14 @@ public class Converter {
return new ObjectMapper().readValue(data, HashMap.class);
}
public static HashMap<String, String> mergeParams(ByteBuffer byteBuffer, byte[] state) {
try {
HashMap<String, String> parameters = (HashMap<String, String>) Converter.byteArrayToMap(state);
parameters.putAll(Converter.byteBufferToMap(byteBuffer));
return parameters;
} catch (Exception ex) {
throw new IllegalArgumentException(ex);
}
}
}

View File

@ -0,0 +1,62 @@
package com.rbkmoney.proxy.mocketbank.utils;
import com.rbkmoney.damsel.domain.Failure;
import com.rbkmoney.damsel.proxy_provider.PaymentCallbackResult;
import com.rbkmoney.damsel.proxy_provider.PaymentProxyResult;
import com.rbkmoney.damsel.proxy_provider.RecurrentTokenCallbackResult;
import com.rbkmoney.damsel.proxy_provider.RecurrentTokenProxyResult;
import com.rbkmoney.error.mapping.ErrorMapping;
import com.rbkmoney.proxy.mocketbank.utils.model.CardAction;
import lombok.AccessLevel;
import lombok.NoArgsConstructor;
import static com.rbkmoney.java.damsel.utils.creators.ProxyProviderPackageCreators.*;
@NoArgsConstructor(access = AccessLevel.PRIVATE)
public class ErrorBuilder {
public static PaymentProxyResult prepareError(ErrorMapping errorMapping, String code, String message) {
Failure failure = errorMapping.mapFailure(code, message);
return createProxyResultFailure(failure);
}
public static PaymentProxyResult prepareError(ErrorMapping errorMapping, CardAction action) {
return prepareError(errorMapping, action.getAction());
}
public static PaymentProxyResult prepareError(ErrorMapping errorMapping, String code) {
return prepareError(errorMapping, code, code);
}
public static RecurrentTokenProxyResult prepareRecurrentTokenError(ErrorMapping errorMapping, String code) {
return prepareRecurrentTokenError(errorMapping, code, code);
}
public static RecurrentTokenProxyResult prepareRecurrentTokenError(ErrorMapping errorMapping, CardAction action) {
return prepareRecurrentTokenError(errorMapping, action.getAction());
}
public static RecurrentTokenProxyResult prepareRecurrentTokenError(ErrorMapping errorMapping, String code, String message) {
Failure failure = errorMapping.mapFailure(code, message);
return createRecurrentTokenProxyResultFailure(failure);
}
public static PaymentCallbackResult prepareCallbackError(ErrorMapping errorMapping, String code, String message) {
Failure failure = errorMapping.mapFailure(code, message);
return createCallbackResultFailure(failure);
}
public static PaymentCallbackResult prepareCallbackError(ErrorMapping errorMapping, String code, CardAction action) {
return prepareCallbackError(errorMapping, code, action.getAction());
}
public static RecurrentTokenCallbackResult prepareRecurrentCallbackError(ErrorMapping errorMapping, String code, CardAction action) {
return prepareRecurrentCallbackError(errorMapping, code, action.getAction());
}
public static RecurrentTokenCallbackResult prepareRecurrentCallbackError(ErrorMapping errorMapping, String code, String message) {
Failure failure = errorMapping.mapFailure(code, message);
return createRecurrentTokenCallbackResultFailure(failure);
}
}

View File

@ -1,14 +0,0 @@
package com.rbkmoney.proxy.mocketbank.utils;
import com.rbkmoney.damsel.proxy_provider.PaymentInfo;
import lombok.AccessLevel;
import lombok.NoArgsConstructor;
@NoArgsConstructor(access = AccessLevel.PRIVATE)
public class PaymentUtils {
public static String generateTransactionId(PaymentInfo payment) {
return payment.getInvoice().getId() + payment.getPayment().getId();
}
}

View File

@ -0,0 +1,32 @@
package com.rbkmoney.proxy.mocketbank.utils;
import com.rbkmoney.proxy.mocketbank.service.mpi.constant.MpiField;
import com.rbkmoney.proxy.mocketbank.service.mpi.model.VerifyEnrollmentResponse;
import lombok.AccessLevel;
import lombok.NoArgsConstructor;
import org.springframework.web.util.UriComponentsBuilder;
import java.util.HashMap;
import java.util.Map;
@NoArgsConstructor(access = AccessLevel.PRIVATE)
public class UrlUtils {
public static String getCallbackUrl(String callbackUrl, String path) {
return UriComponentsBuilder.fromUriString(callbackUrl)
.path(path)
.build()
.toUriString();
}
public static Map<String, String> prepareRedirectParams(
VerifyEnrollmentResponse verifyEnrollmentResponse, String tag, String termUrl
) {
Map<String, String> params = new HashMap<>();
params.put(MpiField.PA_REQ.getValue(), verifyEnrollmentResponse.getPaReq());
params.put(MpiField.MD.getValue(), tag);
params.put(MpiField.TERM_URL.getValue(), termUrl);
return params;
}
}

View File

@ -1,4 +1,4 @@
package com.rbkmoney.proxy.mocketbank.converter;
package com.rbkmoney.proxy.mocketbank.utils.converter;
import lombok.AccessLevel;
import lombok.Getter;

View File

@ -1,4 +1,4 @@
package com.rbkmoney.proxy.mocketbank.converter;
package com.rbkmoney.proxy.mocketbank.utils.converter;
import com.rbkmoney.damsel.proxy_provider.PaymentContext;
import com.rbkmoney.damsel.proxy_provider.PaymentResource;

View File

@ -1,7 +1,7 @@
package com.rbkmoney.proxy.mocketbank.creator;
package com.rbkmoney.proxy.mocketbank.utils.creator;
import com.rbkmoney.damsel.p2p_adapter.*;
import com.rbkmoney.proxy.mocketbank.extractor.P2pAdapterExtractors;
import com.rbkmoney.proxy.mocketbank.utils.extractor.p2p.P2pAdapterExtractors;
import lombok.AccessLevel;
import lombok.NoArgsConstructor;

View File

@ -0,0 +1,25 @@
package com.rbkmoney.proxy.mocketbank.utils.creator;
import com.rbkmoney.damsel.domain.TransactionInfo;
import com.rbkmoney.damsel.proxy_provider.PaymentContext;
import com.rbkmoney.damsel.proxy_provider.PaymentInfo;
import lombok.AccessLevel;
import lombok.NoArgsConstructor;
import java.util.Collections;
import static com.rbkmoney.java.damsel.utils.creators.DomainPackageCreators.createTransactionInfo;
@NoArgsConstructor(access = AccessLevel.PRIVATE)
public class ProxyProviderCreator {
public static final String DELIMITER = ".";
public static TransactionInfo createDefaultTransactionInfo(PaymentContext context) {
return createTransactionInfo(createTransactionId(context.getPaymentInfo()), Collections.emptyMap());
}
public static String createTransactionId(PaymentInfo payment) {
return payment.getInvoice().getId() + DELIMITER + payment.getPayment().getId();
}
}

View File

@ -1,57 +0,0 @@
package com.rbkmoney.proxy.mocketbank.utils.error_mapping;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonProperty;
@JsonInclude(JsonInclude.Include.NON_NULL)
@JsonIgnoreProperties(ignoreUnknown = true)
public class Error {
private String code;
private String description;
private String regexp;
private String mapping;
@JsonProperty("code")
public String getCode() {
return code;
}
public void setCode(String code) {
this.code = code;
}
@JsonProperty("description")
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
@JsonProperty("regexp")
public String getRegexp() {
return regexp;
}
public void setRegexp(String regexp) {
this.regexp = regexp;
}
@JsonProperty("mapping")
public String getMapping() {
return mapping;
}
public void setMapping(String mapping) {
this.mapping = mapping;
}
}

View File

@ -1,148 +0,0 @@
package com.rbkmoney.proxy.mocketbank.utils.error_mapping;
import com.fasterxml.jackson.core.JsonParseException;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.JsonMappingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.rbkmoney.damsel.domain.Failure;
import com.rbkmoney.woody.api.flow.error.WUndefinedResultException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.IOException;
import java.io.InputStream;
import java.util.List;
import static com.rbkmoney.geck.serializer.kit.tbase.TErrorUtil.toGeneral;
/**
* @author Anatoly Cherkasov
*/
public class ErrorMapping {
private final Logger log = LoggerFactory.getLogger(this.getClass());
// ------------------------------------------------------------------------
// Constants
// ------------------------------------------------------------------------
private static final String DEFAULT_PATTERN_REASON = "'%s' - '%s'";
/**
* Pattern for reason failure
*/
private final String patternReason;
/**
* List of errors
*/
private final List<Error> errors;
// ------------------------------------------------------------------------
// Constructors
// ------------------------------------------------------------------------
public ErrorMapping(InputStream inputStream) {
this(inputStream, DEFAULT_PATTERN_REASON);
}
public ErrorMapping(InputStream inputStream, String patternReason) {
this(inputStream, patternReason, new ObjectMapper());
}
public ErrorMapping(InputStream inputStream, String patternReason, ObjectMapper objectMapper) {
this(patternReason, initErrorList(inputStream, objectMapper));
}
public ErrorMapping(String patternReason, List<Error> errors) {
this.patternReason = patternReason;
this.errors = errors;
}
public static List<Error> initErrorList(InputStream inputStream, ObjectMapper objectMapper) {
try {
return objectMapper.readValue(inputStream, new TypeReference<List<Error>>() {});
} catch (JsonParseException e) {
throw new ErrorMappingException("Json can't parse data from file", e);
} catch (JsonMappingException e) {
throw new ErrorMappingException("Json can't mapping data from file", e);
} catch (IOException e) {
throw new ErrorMappingException("Failed to initErrorList", e);
}
}
// ------------------------------------------------------------------------
// Public methods
// ------------------------------------------------------------------------
/**
* Get failure by code and description
*
* @param code String
* @param description String
* @return Failure
*/
public Failure getFailureByCodeAndDescription(String code, String description) {
Error error = findMatchWithPattern(errors, code, description);
Failure failure = toGeneral(error.getMapping());
failure.setReason(prepareReason(code, description));
return failure;
}
/**
* Find match code or description by pattern
*
* @param errors List<Error>
* @param code String
* @param description String
* @return com.rbkmoney.proxy.mocketbank.utils.model.Error
*/
private Error findMatchWithPattern(
List<Error> errors,
String code,
String description
) {
if (code == null || description == null) {
throw new IllegalArgumentException();
}
return errors.stream()
.filter(error ->
(code.matches(error.getRegexp())
|| description.matches(error.getRegexp())
)
)
.findFirst()
.orElseThrow(() -> new WUndefinedResultException(String.format("Undefined error. code %s, description %s", code, description)));
}
// ------------------------------------------------------------------------
// Private methods
// ------------------------------------------------------------------------
/**
* Prepare reason for {@link Failure}
*
* @param code String
* @param description String
* @return String
*/
private String prepareReason(String code, String description) {
return String.format(this.patternReason, code, description);
}
/**
* Validate mapping formate
*/
public void validateMappingFormat() {
errors.forEach(error -> StandardError.findByValue(error.getMapping()));
}
}

View File

@ -1,50 +0,0 @@
package com.rbkmoney.proxy.mocketbank.utils.error_mapping;
/**
* Handy class for wrapping runtime {@code Exceptions} with a root cause.
*
* @author Anatoly Cherkasov
* @see #getMessage()
* @see #printStackTrace
*/
public class ErrorMappingException extends RuntimeException {
/**
* Constructs a new {@code ErrorMappingException} with {@code null} as its detail message.
* The cause is not initialized, and may subsequently be initialized by a
* call to {@link #initCause}.
*/
public ErrorMappingException() {
super();
}
/**
* Construct a new {@code ErrorMappingException} with the specified detail message.
*
* @param message the detail message
*/
public ErrorMappingException(String message) {
super(message);
}
/**
* Construct a new {@code ErrorMappingException} with the cause.
*
* @param cause the root cause
*/
public ErrorMappingException(Throwable cause) {
super(cause);
}
/**
* Construct a new {@code ErrorMappingException} with the
* specified detail message and root cause.
*
* @param message the detail message
* @param cause the root cause
*/
public ErrorMappingException(String message, Throwable cause) {
super(message, cause);
}
}

View File

@ -1,51 +0,0 @@
package com.rbkmoney.proxy.mocketbank.utils.error_mapping;
import java.util.Arrays;
public enum StandardError {
PRE_AUTHORIZATION_FAILED("preauthorization_failed"),
REJECTED_BY_INSPECTOR("rejected_by_inspector"),
AUTH_FAILED_OPERATION_BLOCKED("authorization_failed:operation_blocked"),
AUTH_FAILED_MERCHANT_BLOCKED("authorization_failed:merchant_blocked"),
AUTH_FAILED_ACCOUNT_NOT_FOUND("authorization_failed:account_not_found"),
AUTH_FAILED_ACCOUNT_BLOCKED("authorization_failed:account_blocked"),
AUTH_FAILED_INSUFFICIENT_FUNDS("authorization_failed:insufficient_funds"),
AUTH_FAILED_ACCOUNT_STOLEN("authorization_failed:account_stolen"),
AUTH_FAILED_UNKNOWN("authorization_failed:unknown"),
AUTH_FAILED_ACCOUNT_EXCEEDED_AMOUNT("authorization_failed:account_limit_exceeded:amount"),
AUTH_FAILED_ACCOUNT_EXCEEDED_NUMBER("authorization_failed:account_limit_exceeded:number"),
AUTH_FAILED_ACCOUNT_EXCEEDED_UNKNOWN("authorization_failed:account_limit_exceeded:unknown"),
AUTH_FAILED_PROVIDER_EXCEEDED_AMOUNT("authorization_failed:provider_limit_exceeded:amount"),
AUTH_FAILED_PROVIDER_EXCEEDED_NUMBER("authorization_failed:provider_limit_exceeded:number"),
AUTH_FAILED_PROVIDER_EXCEEDED_UNKNOWN("authorization_failed:provider_limit_exceeded:unknown"),
AUTH_FAILED_BANK_CARD_CARD_EXPIRED("authorization_failed:payment_tool_rejected:bank_card_rejected:card_expired"),
AUTH_FAILED_BANK_CARD_CARD_NUMBER_INVALID("authorization_failed:payment_tool_rejected:bank_card_rejected:card_number_invalid"),
AUTH_FAILED_BANK_CARD_CARD_HOLDER_INVALID("authorization_failed:payment_tool_rejected:bank_card_rejected:card_holder_invalid"),
AUTH_FAILED_BANK_CARD_CVV_INVALID("authorization_failed:payment_tool_rejected:bank_card_rejected:cvv_invalid"),
AUTH_FAILED_BANK_CARD_CARD_UNSUPPORTED("authorization_failed:payment_tool_rejected:bank_card_rejected:card_unsupported"),
AUTH_FAILED_BANK_CARD_ISSUER_NOT_FOUND("authorization_failed:payment_tool_rejected:bank_card_rejected:issuer_not_found");
private final String error;
StandardError(String action) {
this.error = action;
}
public String getError() {
return error;
}
public static StandardError findByValue(String value) {
return Arrays.stream(StandardError.values()).filter((error) -> error.getError().equals(value))
.findFirst()
.orElseThrow(()->new IllegalStateException(String.format("Unsupported error '%s' does not match standard", value)));
}
}

View File

@ -1,4 +1,4 @@
package com.rbkmoney.proxy.mocketbank.extractor;
package com.rbkmoney.proxy.mocketbank.utils.extractor.p2p;
import com.rbkmoney.damsel.p2p_adapter.Context;
import lombok.AccessLevel;

View File

@ -0,0 +1,52 @@
package com.rbkmoney.proxy.mocketbank.utils.extractor.proxy;
import com.rbkmoney.damsel.domain.BankCardTokenProvider;
import com.rbkmoney.damsel.domain.PaymentTool;
import com.rbkmoney.damsel.proxy_provider.PaymentContext;
import com.rbkmoney.damsel.proxy_provider.PaymentResource;
import com.rbkmoney.damsel.proxy_provider.RecurrentTokenContext;
import com.rbkmoney.proxy.mocketbank.exception.MobileException;
import lombok.AccessLevel;
import lombok.NoArgsConstructor;
@NoArgsConstructor(access = AccessLevel.PRIVATE)
public class ProxyProviderPackageExtractors {
public static PaymentTool extractPaymentTool(PaymentResource paymentResource) {
if (paymentResource.isSetDisposablePaymentResource()) {
return paymentResource.getDisposablePaymentResource().getPaymentTool();
} else if (paymentResource.isSetRecurrentPaymentResource()) {
return paymentResource.getRecurrentPaymentResource().getPaymentTool();
}
throw new MobileException("Unknown Payment Resource");
}
public static BankCardTokenProvider extractBankCardTokenProvider(PaymentContext context) {
PaymentResource paymentResource = context.getPaymentInfo().getPayment().getPaymentResource();
if (paymentResource.isSetDisposablePaymentResource()) {
PaymentTool paymentTool = paymentResource.getDisposablePaymentResource().getPaymentTool();
if (paymentTool.isSetBankCard() && paymentTool.getBankCard().isSetTokenProvider()) {
return paymentTool.getBankCard().getTokenProvider();
}
}
return null;
}
public static BankCardTokenProvider extractBankCardTokenProvider(RecurrentTokenContext context) {
PaymentTool paymentTool = context.getTokenInfo().getPaymentTool().getPaymentResource().getPaymentTool();
if (paymentTool.isSetBankCard() && paymentTool.getBankCard().isSetTokenProvider()) {
return paymentTool.getBankCard().getTokenProvider();
}
return null;
}
public static boolean hasBankCardTokenProvider(Object object) {
BankCardTokenProvider bankCardTokenProvider;
if (object instanceof RecurrentTokenContext) {
bankCardTokenProvider = extractBankCardTokenProvider((RecurrentTokenContext) object);
} else {
bankCardTokenProvider = extractBankCardTokenProvider((PaymentContext) object);
}
return (bankCardTokenProvider != null);
}
}

View File

@ -1,21 +0,0 @@
package com.rbkmoney.proxy.mocketbank.utils.mocketbank;
import lombok.AccessLevel;
import lombok.NoArgsConstructor;
import org.springframework.web.util.UriComponentsBuilder;
@NoArgsConstructor(access = AccessLevel.PRIVATE)
public class MockMpiUtils {
public static String prepareUrl(String url, String path) {
return String.format("%s/mpi/%s", url, path);
}
public static String getCallbackUrl(String callbackUrl, String path) {
return UriComponentsBuilder.fromUriString(callbackUrl)
.path(path)
.build()
.toUriString();
}
}

View File

@ -1,56 +0,0 @@
package com.rbkmoney.proxy.mocketbank.utils.mocketbank.constant;
import com.rbkmoney.proxy.mocketbank.utils.model.Card;
import lombok.Getter;
import lombok.RequiredArgsConstructor;
import java.util.Arrays;
@Getter
@RequiredArgsConstructor
public enum MpiAction {
UNKNOWN("Unknown"),
UNSUPPORTED_CARD("Unsupported Card"),
SUCCESS("Success"),
THREE_D_SECURE_SUCCESS("3-D Secure Success"),
THREE_D_SECURE_FAILURE("3-D Secure Failure"),
THREE_D_SECURE_TIMEOUT("3-D Secure Timeout"),
INSUFFICIENT_FUNDS("Insufficient Funds"),
INVALID_CARD("Invalid Card"),
CVV_MATCH_FAIL("CVV Match Fail"),
EXPIRED_CARD("Expired Card"),
APPLE_PAY_FAILURE("Apple Pay Failure"),
APPLE_PAY_SUCCESS("Apple Pay Success"),
GOOGLE_PAY_FAILURE("Google Pay Failure"),
GOOGLE_PAY_SUCCESS("Google Pay Success"),
SAMSUNG_PAY_FAILURE("Samsung Pay Failure"),
SAMSUNG_PAY_SUCCESS("Samsung Pay Success"),
UNKNOWN_FAILURE("Unknown Failure");
private final String action;
public static MpiAction findByValue(String value) {
return Arrays.stream(values()).filter((action) -> action.getAction().equals(value))
.findFirst()
.orElse(UNKNOWN);
}
public static boolean isCardEnrolled(Card card) {
MpiAction action = MpiAction.findByValue(card.getAction());
return MpiAction.isCardEnrolled(action);
}
public static boolean isCardEnrolled(MpiAction action) {
return Arrays.asList(enrolledCard()).contains(action);
}
private static MpiAction[] enrolledCard() {
return new MpiAction[]{
THREE_D_SECURE_FAILURE,
THREE_D_SECURE_TIMEOUT,
THREE_D_SECURE_SUCCESS
};
}
}

View File

@ -1,16 +0,0 @@
package com.rbkmoney.proxy.mocketbank.utils.mocketbank.constant;
import lombok.Getter;
import lombok.RequiredArgsConstructor;
@Getter
@RequiredArgsConstructor
public enum MpiRequestField {
PAN("pan"),
YEAR("year"),
PARES("paRes"),
MONTH("month");
private final String value;
}

View File

@ -0,0 +1,89 @@
package com.rbkmoney.proxy.mocketbank.utils.model;
import lombok.Getter;
import lombok.RequiredArgsConstructor;
import java.util.Arrays;
@Getter
@RequiredArgsConstructor
public enum CardAction {
UNKNOWN("Unknown"),
UNSUPPORTED_CARD("Unsupported Card"),
SUCCESS("Success"),
SUCCESS_3DS("3-D Secure Success"),
FAILURE_3DS("3-D Secure Failure"),
TIMEOUT_3DS("3-D Secure Timeout"),
INSUFFICIENT_FUNDS("Insufficient Funds"),
INVALID_CARD("Invalid Card"),
CVV_MATCH_FAIL("CVV Match Fail"),
EXPIRED_CARD("Expired Card"),
APPLE_PAY_FAILURE("Apple Pay Failure"),
APPLE_PAY_SUCCESS("Apple Pay Success"),
GOOGLE_PAY_FAILURE("Google Pay Failure"),
GOOGLE_PAY_SUCCESS("Google Pay Success"),
SAMSUNG_PAY_FAILURE("Samsung Pay Failure"),
SAMSUNG_PAY_SUCCESS("Samsung Pay Success"),
UNKNOWN_FAILURE("Unknown Failure");
private static final CardAction[] ENROLLED_CARDS = {
FAILURE_3DS,
TIMEOUT_3DS,
SUCCESS_3DS
};
private static final CardAction[] FAILED_CARDS = {
INSUFFICIENT_FUNDS,
INVALID_CARD,
CVV_MATCH_FAIL,
APPLE_PAY_FAILURE,
SAMSUNG_PAY_FAILURE,
GOOGLE_PAY_FAILURE,
EXPIRED_CARD,
UNKNOWN_FAILURE
};
private static final CardAction[] SUCCESS_CARDS = {
SUCCESS,
APPLE_PAY_SUCCESS,
GOOGLE_PAY_SUCCESS,
SAMSUNG_PAY_SUCCESS
};
private static final CardAction[] MPI_FAILED_CARDS = {
FAILURE_3DS,
TIMEOUT_3DS,
UNKNOWN_FAILURE
};
private final String action;
public static CardAction findByValue(String value) {
return Arrays.stream(values()).filter((action) -> action.getAction().equals(value))
.findFirst()
.orElse(UNKNOWN);
}
public static boolean isCardEnrolled(Card card) {
CardAction action = CardAction.findByValue(card.getAction());
return CardAction.isCardEnrolled(action);
}
public static boolean isCardEnrolled(CardAction action) {
return Arrays.asList(ENROLLED_CARDS).contains(action);
}
public static boolean isCardFailed(CardAction action) {
return Arrays.asList(FAILED_CARDS).contains(action);
}
public static boolean isCardSuccess(CardAction action) {
return Arrays.asList(SUCCESS_CARDS).contains(action);
}
public static boolean isMpiCardFailed(CardAction action) {
return Arrays.asList(MPI_FAILED_CARDS).contains(action);
}
}

View File

@ -1,14 +1,29 @@
package com.rbkmoney.proxy.mocketbank.utils.model;
import com.rbkmoney.cds.client.storage.model.CardDataProxyModel;
import com.rbkmoney.proxy.mocketbank.exception.CardException;
import lombok.AccessLevel;
import lombok.NoArgsConstructor;
import java.util.List;
import java.util.Optional;
import static com.rbkmoney.proxy.mocketbank.utils.model.CardAction.UNKNOWN_FAILURE;
import static com.rbkmoney.proxy.mocketbank.utils.model.CardAction.isMpiCardFailed;
@NoArgsConstructor(access = AccessLevel.PRIVATE)
public class CardUtils {
public static Optional<Card> extractCardByPan(List<Card> cardList, String pan) {
return cardList.stream().filter(card -> card.getPan().equals(pan)).findFirst();
}
public static CardAction extractActionFromCard(List<Card> cardList, CardDataProxyModel cardData) {
Optional<Card> card = CardUtils.extractCardByPan(cardList, cardData.getPan());
if (!card.isPresent()) {
throw new CardException("Can't extract action from card");
}
CardAction action = CardAction.findByValue(card.get().getAction());
return isMpiCardFailed(action) ? action : UNKNOWN_FAILURE;
}
}

View File

@ -0,0 +1,26 @@
package com.rbkmoney.proxy.mocketbank.utils.state;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.rbkmoney.proxy.mocketbank.service.mpi.constant.MpiField;
import com.rbkmoney.proxy.mocketbank.service.mpi.model.VerifyEnrollmentResponse;
import com.rbkmoney.proxy.mocketbank.utils.Converter;
import lombok.AccessLevel;
import lombok.NoArgsConstructor;
import java.util.HashMap;
import java.util.Map;
@NoArgsConstructor(access = AccessLevel.PRIVATE)
public class StateUtils {
public static byte[] prepareState(VerifyEnrollmentResponse verifyEnrollmentResponse) {
Map<String, String> extra = new HashMap<>();
extra.put(MpiField.PA_REQ.getValue(), verifyEnrollmentResponse.getPaReq());
try {
return Converter.mapToByteArray(extra);
} catch (JsonProcessingException ex) {
throw new IllegalArgumentException(ex);
}
}
}

View File

@ -1,18 +0,0 @@
package com.rbkmoney.proxy.mocketbank.utils.state.constant;
import lombok.Getter;
import lombok.RequiredArgsConstructor;
@Getter
@RequiredArgsConstructor
public enum PaymentState {
PROCESSED("processed"),
CAPTURED("captured"),
CANCELLED("cancelled"),
REFUNDED("refunded"),
CONFIRM("confirm");
private final String state;
}

View File

@ -4,7 +4,7 @@ import com.rbkmoney.damsel.domain.PaymentTool;
import com.rbkmoney.damsel.proxy_provider.PaymentContext;
import com.rbkmoney.damsel.proxy_provider.PaymentResource;
import com.rbkmoney.proxy.mocketbank.exception.MobileException;
import com.rbkmoney.proxy.mocketbank.extractor.ProxyProviderPackageExtractors;
import com.rbkmoney.proxy.mocketbank.utils.extractor.proxy.ProxyProviderPackageExtractors;
import lombok.AccessLevel;
import lombok.NoArgsConstructor;
import org.springframework.stereotype.Component;

View File

@ -0,0 +1,22 @@
package com.rbkmoney.proxy.mocketbank.validator;
import com.rbkmoney.damsel.proxy_provider.PaymentContext;
import com.rbkmoney.proxy.mocketbank.exception.PaymentException;
import lombok.AccessLevel;
import lombok.NoArgsConstructor;
import org.springframework.stereotype.Component;
import java.util.Map;
@Component
@NoArgsConstructor(access = AccessLevel.PRIVATE)
public class PaymentCapturedValidator implements Validator<PaymentContext> {
public void validate(PaymentContext context, Map<String, String> options) {
if (!context.getPaymentInfo().isSetCapture()) {
throw new PaymentException("Captured not set");
}
}
}

View File

@ -0,0 +1,22 @@
package com.rbkmoney.proxy.mocketbank.validator;
import com.rbkmoney.damsel.proxy_provider.PaymentContext;
import com.rbkmoney.proxy.mocketbank.exception.PaymentException;
import lombok.AccessLevel;
import lombok.NoArgsConstructor;
import org.springframework.stereotype.Component;
import java.util.Map;
@Component
@NoArgsConstructor(access = AccessLevel.PRIVATE)
public class PaymentRefundedValidator implements Validator<PaymentContext> {
public void validate(PaymentContext context, Map<String, String> options) {
if (!context.getPaymentInfo().isSetRefund()) {
throw new PaymentException("Refund not set");
}
}
}

View File

@ -0,0 +1,29 @@
package com.rbkmoney.proxy.mocketbank.validator;
import com.rbkmoney.damsel.domain.PaymentTool;
import com.rbkmoney.damsel.proxy_provider.PaymentContext;
import com.rbkmoney.damsel.proxy_provider.PaymentResource;
import com.rbkmoney.proxy.mocketbank.exception.PaymentException;
import lombok.AccessLevel;
import lombok.NoArgsConstructor;
import org.springframework.stereotype.Component;
import java.util.Map;
import static com.rbkmoney.java.damsel.utils.extractors.ProxyProviderPackageExtractors.extractPaymentResource;
import static com.rbkmoney.proxy.mocketbank.utils.extractor.proxy.ProxyProviderPackageExtractors.extractPaymentTool;
@Component
@NoArgsConstructor(access = AccessLevel.PRIVATE)
public class PaymentValidator implements Validator<PaymentContext> {
public void validate(PaymentContext context, Map<String, String> options) {
PaymentResource paymentResource = extractPaymentResource(context);
PaymentTool paymentTool = extractPaymentTool(paymentResource);
if (!paymentResource.isSetRecurrentPaymentResource() && !paymentTool.isSetBankCard()) {
throw new PaymentException("Isn`t payment tool bank card");
}
}
}

View File

@ -4,7 +4,7 @@ import com.rbkmoney.damsel.domain.PaymentTool;
import com.rbkmoney.damsel.proxy_provider.PaymentContext;
import com.rbkmoney.damsel.proxy_provider.PaymentResource;
import com.rbkmoney.proxy.mocketbank.exception.TerminalException;
import com.rbkmoney.proxy.mocketbank.extractor.ProxyProviderPackageExtractors;
import com.rbkmoney.proxy.mocketbank.utils.extractor.proxy.ProxyProviderPackageExtractors;
import lombok.AccessLevel;
import lombok.NoArgsConstructor;
import org.springframework.stereotype.Component;

View File

@ -23,8 +23,10 @@ server:
adapter-mock-mpi:
url: http://127.0.0.1:8018
---
proxy-mocketbank:
adapter-mock-bank:
callbackUrl: http://127.0.0.1:8019
pathCallbackUrl: /${server.rest.endpoint}/term_url{?termination_uri}
pathRecurrentCallbackUrl: /${server.rest.endpoint}/term_rec_url{?termination_uri}
---
cds:
client:
@ -42,7 +44,7 @@ hellgate:
networkTimeout: 30000
---
timer:
timeout: 600
redirectTimeout: 600
---
fixture:
cards: classpath:fixture/cards.csv

View File

@ -1,62 +1,54 @@
[
{
"code":"Unsupported Card",
"description":"Unsupported Card",
"regexp":"^Unsupported\\sCard$",
"mapping":"authorization_failed:payment_tool_rejected:bank_card_rejected:card_unsupported"
"codeRegex": "^Unsupported\\sCard$",
"mapping": "authorization_failed:payment_tool_rejected:bank_card_rejected:issuer_not_found"
},
{
"code":"3-D Secure Failure",
"description":"3-D Secure Failure",
"regexp":"3-D Secure Failure",
"mapping":"preauthorization_failed"
"codeRegex": "3-D Secure Failure",
"mapping": "preauthorization_failed:unknown"
},
{
"code":"3-D Secure Timeout",
"description":"3-D Secure Timeout",
"regexp":"3-D Secure Timeout",
"mapping":"preauthorization_failed"
"codeRegex": "3-D Secure Timeout",
"mapping": "preauthorization_failed:unknown"
},
{
"code":"Invalid Card",
"description":"Invalid Card",
"regexp":"Invalid Card",
"mapping":"authorization_failed:payment_tool_rejected:bank_card_rejected:card_number_invalid"
"codeRegex": "Invalid Card",
"mapping": "authorization_failed:account_not_found"
},
{
"code":"CVV Match Fail",
"description":"CVV Match Fail",
"regexp":"CVV Match Fail",
"mapping":"authorization_failed:payment_tool_rejected:bank_card_rejected:cvv_invalid"
"codeRegex": "CVV Match Fail",
"mapping": "authorization_failed:payment_tool_rejected:bank_card_rejected:cvv_invalid"
},
{
"code":"Expired Card",
"description":"Expired Card",
"regexp":"Expired Card",
"mapping":"authorization_failed:payment_tool_rejected:bank_card_rejected:card_expired"
"codeRegex": "Expired Card",
"mapping": "authorization_failed:payment_tool_rejected:bank_card_rejected:card_expired"
},
{
"code":"Insufficient Funds",
"description":"Insufficient Funds",
"regexp":"Insufficient Funds",
"mapping":"authorization_failed:insufficient_funds"
"codeRegex": "Insufficient Funds",
"mapping": "authorization_failed:insufficient_funds"
},
{
"code":"Unknown",
"description":"Unknown",
"regexp":"Unknown",
"mapping":"authorization_failed:unknown"
"codeRegex": "Unknown",
"mapping": "authorization_failed:unknown"
},
{
"code":"Apple Pay Failure",
"description":"Apple Pay Failure",
"regexp":"Apple Pay Failure",
"mapping":"authorization_failed:unknown"
"codeRegex": "Apple Pay Failure",
"mapping": "authorization_failed:unknown"
},
{
"code":"Unknown Failure",
"description":"Unknown Failure",
"regexp":"Unknown Failure",
"mapping":"authorization_failed:unknown"
"codeRegex": "Google Pay Failure",
"mapping": "authorization_failed:unknown"
},
{
"codeRegex": "Samsung Pay Failure",
"mapping": "authorization_failed:unknown"
},
{
"codeRegex": "Unknown Failure",
"mapping": "authorization_failed:unknown"
},
{
"codeRegex": ".*",
"mapping": "authorization_failed:unknown"
}
]

View File

@ -28,21 +28,17 @@ public class TestData {
public static final String DEFAULT_ACS_URL = "http://localhost/acs";
public static final String DEFAULT_PAREQ = "PaReq";
public static CardData makeCardData() {
return createCardDataWithExpDate(
DEFAULT_CARDHOLDERNAME,
"123",
"4012001011000771",
"12", "2020"
);
}
public static final String DEFAULT_YEAR = "2020";
public static final String DEFAULT_MONTH = "12";
public static final String DEFAULT_CVV = "123";
public static final String DEFAULT_CARD = "4012001011000771";
public static final String DEFAULT_BIN = "123456";
public static CardDataProxyModel createCardDataProxyModel(String pan) {
return CardDataProxyModel.builder()
.pan(pan)
.expMonth(Byte.parseByte("12"))
.expYear(Short.parseShort("2020"))
.expMonth(Byte.parseByte(DEFAULT_MONTH))
.expYear(Short.parseShort(DEFAULT_YEAR))
.cardholderName(DEFAULT_CARDHOLDERNAME)
.build();
}
@ -50,18 +46,18 @@ public class TestData {
public static CardData createCardData(String pan) {
return createCardDataWithExpDate(
DEFAULT_CARDHOLDERNAME,
"123",
DEFAULT_CVV,
pan,
"12", "2020"
DEFAULT_MONTH, DEFAULT_YEAR
);
}
public static CardData createCardData() {
return createCardDataWithExpDate(
DEFAULT_CARDHOLDERNAME,
"123",
"4012001011000771",
"12", "2020"
DEFAULT_CVV,
DEFAULT_CARD,
DEFAULT_MONTH, DEFAULT_YEAR
);
}
@ -77,23 +73,7 @@ public class TestData {
cardData.getExpDate().getYear()
)
)
.setBin(cardData.pan.substring(0, 6))
.setLastDigits(cardData.pan.substring(cardData.pan.length() - 4));
}
public static BankCard makeBankCard(CardData cardData) {
String month = String.valueOf(cardData.getExpDate().getMonth());
String year = String.valueOf(cardData.getExpDate().getYear());
return DomainPackageCreators.createBankCard(month, year, cardData.getCardholderName())
.setPaymentSystem(BankCardPaymentSystem.mastercard)
.setExpDate(
createBankCardExpDate(
cardData.getExpDate().getMonth(),
cardData.getExpDate().getYear()
)
)
.setBin(cardData.pan.substring(0, 6))
.setBin(DEFAULT_BIN)
.setLastDigits(cardData.pan.substring(cardData.pan.length() - 4));
}

View File

@ -5,7 +5,7 @@ import com.rbkmoney.damsel.domain.*;
import com.rbkmoney.damsel.proxy_provider.Shop;
import com.rbkmoney.damsel.proxy_provider.*;
import com.rbkmoney.proxy.mocketbank.TestData;
import com.rbkmoney.proxy.mocketbank.utils.p2p.constant.testcards.Visa;
import com.rbkmoney.proxy.mocketbank.utils.constant.testcards.Visa;
import com.rbkmoney.woody.api.flow.error.WRuntimeException;
import com.rbkmoney.woody.api.flow.error.WUnavailableResultException;
import com.rbkmoney.woody.thrift.impl.http.THSpawnClientBuilder;

View File

@ -7,16 +7,18 @@ import com.rbkmoney.damsel.cds.CardData;
import com.rbkmoney.damsel.cds.CardSecurityCode;
import com.rbkmoney.damsel.domain.*;
import com.rbkmoney.damsel.proxy_provider.Cash;
import com.rbkmoney.damsel.proxy_provider.InvoicePaymentRefund;
import com.rbkmoney.damsel.proxy_provider.Shop;
import com.rbkmoney.damsel.proxy_provider.*;
import com.rbkmoney.java.damsel.utils.creators.CdsPackageCreators;
import com.rbkmoney.java.damsel.utils.creators.DomainPackageCreators;
import com.rbkmoney.proxy.mocketbank.TestData;
import com.rbkmoney.proxy.mocketbank.utils.mocketbank.MockMpiApi;
import com.rbkmoney.proxy.mocketbank.utils.mocketbank.constant.MpiEnrollmentStatus;
import com.rbkmoney.proxy.mocketbank.utils.mocketbank.constant.MpiTransactionStatus;
import com.rbkmoney.proxy.mocketbank.utils.mocketbank.model.ValidatePaResResponse;
import com.rbkmoney.proxy.mocketbank.utils.mocketbank.model.VerifyEnrollmentResponse;
import com.rbkmoney.proxy.mocketbank.decorator.PaymentServerHandlerMdcLog;
import com.rbkmoney.proxy.mocketbank.service.mpi.MpiApi;
import com.rbkmoney.proxy.mocketbank.service.mpi.constant.EnrollmentStatus;
import com.rbkmoney.proxy.mocketbank.service.mpi.constant.TransactionStatus;
import com.rbkmoney.proxy.mocketbank.service.mpi.model.ValidatePaResResponse;
import com.rbkmoney.proxy.mocketbank.service.mpi.model.VerifyEnrollmentResponse;
import lombok.extern.slf4j.Slf4j;
import org.mockito.Mockito;
import org.springframework.beans.factory.annotation.Autowired;
@ -35,18 +37,19 @@ import static org.mockito.ArgumentMatchers.anyString;
@Slf4j
public abstract class IntegrationTest {
protected String invoiceId = "TEST_INVOICE" + (int) (Math.random() * 50 + 1);
protected String paymentId = "TEST_PAYMENT" + (int) (Math.random() * 50 + 1);
protected String recurrentId = "TEST_RECURRENT" + (int) (Math.random() * 500 + 1);
protected String invoiceId = "TEST_INVOICE";
protected String paymentId = "TEST_PAYMENT";
protected String recurrentId = "TEST_RECURRENT";
protected String refundId = "TEST_REFUND";
@Autowired
protected MocketBankServerHandlerMdcDecorator handler;
protected PaymentServerHandlerMdcLog handler;
@MockBean
protected CdsClientStorage cdsStorage;
@MockBean
protected MockMpiApi mpiApi;
protected MpiApi mpiApi;
protected Map<String, String> prepareProxyOptions() {
return new HashMap<>();
@ -68,11 +71,21 @@ public abstract class IntegrationTest {
protected PaymentInfo getPaymentInfo(String sessionId, BankCard bankCard, TransactionInfo transactionInfo) {
PaymentResource paymentResource = getPaymentResource(sessionId, bankCard);
return getPaymentInfo(transactionInfo, paymentResource);
PaymentInfo paymentInfo = getPaymentInfo(transactionInfo, paymentResource);
paymentInfo.setCapture(prepareInvoicePaymentCapture());
paymentInfo.setRefund(createInvoicePaymentRefund(transactionInfo));
return paymentInfo;
}
private InvoicePaymentRefund createInvoicePaymentRefund(TransactionInfo transactionInfo) {
InvoicePaymentRefund invoicePaymentRefund = new InvoicePaymentRefund();
invoicePaymentRefund.setId(refundId);
invoicePaymentRefund.setTrx(transactionInfo);
return invoicePaymentRefund;
}
protected PaymentInfo getPaymentInfo(TransactionInfo transactionInfo, PaymentResource paymentResource) {
return createPaymentInfo(
PaymentInfo paymentInfo = createPaymentInfo(
createInvoice(
invoiceId,
TestData.CREATED_AT,
@ -86,6 +99,16 @@ public abstract class IntegrationTest {
prepareCash(),
transactionInfo
).setMakeRecurrent(Boolean.FALSE));
paymentInfo.setCapture(prepareInvoicePaymentCapture());
paymentInfo.setRefund(createInvoicePaymentRefund(transactionInfo));
return paymentInfo;
}
private InvoicePaymentCapture prepareInvoicePaymentCapture() {
InvoicePaymentCapture invoicePaymentCapture = new InvoicePaymentCapture();
invoicePaymentCapture.setCost(prepareCash());
return invoicePaymentCapture;
}
protected PaymentResource getPaymentResource(String sessionId, BankCard bankCard) {
@ -124,6 +147,23 @@ public abstract class IntegrationTest {
);
}
protected RecurrentTokenContext createRecurrentTokenContext(BankCard bankCard) {
RecurrentTokenContext context = new RecurrentTokenContext();
context.setSession(new RecurrentTokenSession());
context.setTokenInfo(
createRecurrentTokenInfo(
createRecurrentPaymentTool(
createDisposablePaymentResource(
createClientInfo(TestData.FINGERPRINT, TestData.IP_ADDRESS),
TestData.SESSION_ID,
createPaymentTool(bankCard)
)
).setId(recurrentId)
)
);
return context;
}
protected PaymentResource getPaymentResourceRecurrent(String token) {
return createPaymentResourceRecurrentPaymentResource(
createRecurrentPaymentResource(token)
@ -157,18 +197,18 @@ public abstract class IntegrationTest {
Mockito.when(cdsStorage.getSessionData((PaymentContext) any())).thenReturn(CdsPackageCreators.createSessionData(AuthData.card_security_code(new CardSecurityCode(cardData.getCvv()))));
}
protected void mockMpiVerify(MpiEnrollmentStatus mpiEnrollmentStatus) {
protected void mockMpiVerify(EnrollmentStatus mpiEnrollmentStatus) {
VerifyEnrollmentResponse response = new VerifyEnrollmentResponse();
response.setAcsUrl(TestData.DEFAULT_ACS_URL);
response.setEnrolled(mpiEnrollmentStatus.getStatus());
response.setPaReq(TestData.DEFAULT_PAREQ);
Mockito.when(mpiApi.verifyEnrollment(any())).thenReturn(response);
Mockito.when(mpiApi.verifyEnrollment((CardDataProxyModel) any())).thenReturn(response);
}
protected void mockMpi(MpiTransactionStatus mpiTransactionStatus) {
protected void mockMpi(TransactionStatus mpiTransactionStatus) {
ValidatePaResResponse paResResponse = new ValidatePaResResponse();
paResResponse.setTransactionStatus(mpiTransactionStatus.getStatus());
Mockito.when(mpiApi.validatePaRes(any())).thenReturn(paResResponse);
Mockito.when(mpiApi.validatePaRes(any(), any())).thenReturn(paResResponse);
}
}

View File

@ -4,9 +4,9 @@ import com.rbkmoney.damsel.cds.CardData;
import com.rbkmoney.damsel.domain.BankCard;
import com.rbkmoney.damsel.proxy_provider.PaymentProxyResult;
import com.rbkmoney.proxy.mocketbank.TestData;
import com.rbkmoney.proxy.mocketbank.utils.p2p.constant.testcards.Mastercard;
import com.rbkmoney.proxy.mocketbank.utils.p2p.constant.testcards.TestCard;
import com.rbkmoney.proxy.mocketbank.utils.p2p.constant.testcards.Visa;
import com.rbkmoney.proxy.mocketbank.utils.constant.testcards.Mastercard;
import com.rbkmoney.proxy.mocketbank.utils.constant.testcards.TestCard;
import com.rbkmoney.proxy.mocketbank.utils.constant.testcards.Visa;
import lombok.extern.slf4j.Slf4j;
import org.apache.thrift.TException;
import org.junit.Test;

View File

@ -6,12 +6,12 @@ import com.rbkmoney.damsel.proxy_provider.PaymentCallbackResult;
import com.rbkmoney.damsel.proxy_provider.PaymentContext;
import com.rbkmoney.damsel.proxy_provider.PaymentProxyResult;
import com.rbkmoney.proxy.mocketbank.TestData;
import com.rbkmoney.proxy.mocketbank.service.mpi.constant.EnrollmentStatus;
import com.rbkmoney.proxy.mocketbank.service.mpi.constant.TransactionStatus;
import com.rbkmoney.proxy.mocketbank.utils.Converter;
import com.rbkmoney.proxy.mocketbank.utils.mocketbank.constant.MpiEnrollmentStatus;
import com.rbkmoney.proxy.mocketbank.utils.mocketbank.constant.MpiTransactionStatus;
import com.rbkmoney.proxy.mocketbank.utils.p2p.constant.testcards.Mastercard;
import com.rbkmoney.proxy.mocketbank.utils.p2p.constant.testcards.TestCard;
import com.rbkmoney.proxy.mocketbank.utils.p2p.constant.testcards.Visa;
import com.rbkmoney.proxy.mocketbank.utils.constant.testcards.Mastercard;
import com.rbkmoney.proxy.mocketbank.utils.constant.testcards.TestCard;
import com.rbkmoney.proxy.mocketbank.utils.constant.testcards.Visa;
import lombok.extern.slf4j.Slf4j;
import org.apache.thrift.TException;
import org.junit.Test;
@ -60,8 +60,8 @@ public class MocketBankServerHandlerFailWith3DSIntegrationTest extends Integrati
private void processPaymentFail(CardData cardData) throws TException, IOException {
BankCard bankCard = TestData.createBankCard(cardData);
mockCds(cardData, bankCard);
mockMpiVerify(MpiEnrollmentStatus.AUTHENTICATION_AVAILABLE);
mockMpi(MpiTransactionStatus.AUTHENTICATION_FAILED);
mockMpiVerify(EnrollmentStatus.AUTHENTICATION_AVAILABLE);
mockMpi(TransactionStatus.AUTHENTICATION_FAILED);
PaymentContext paymentContext = getContext(bankCard, createTargetProcessed(), null);
PaymentProxyResult proxyResult = handler.processPayment(paymentContext);

View File

@ -4,12 +4,12 @@ import com.rbkmoney.damsel.cds.CardData;
import com.rbkmoney.damsel.domain.BankCard;
import com.rbkmoney.damsel.proxy_provider.*;
import com.rbkmoney.proxy.mocketbank.TestData;
import com.rbkmoney.proxy.mocketbank.service.mpi.constant.EnrollmentStatus;
import com.rbkmoney.proxy.mocketbank.service.mpi.constant.TransactionStatus;
import com.rbkmoney.proxy.mocketbank.utils.Converter;
import com.rbkmoney.proxy.mocketbank.utils.mocketbank.constant.MpiEnrollmentStatus;
import com.rbkmoney.proxy.mocketbank.utils.mocketbank.constant.MpiTransactionStatus;
import com.rbkmoney.proxy.mocketbank.utils.p2p.constant.testcards.Mastercard;
import com.rbkmoney.proxy.mocketbank.utils.p2p.constant.testcards.TestCard;
import com.rbkmoney.proxy.mocketbank.utils.p2p.constant.testcards.Visa;
import com.rbkmoney.proxy.mocketbank.utils.constant.testcards.Mastercard;
import com.rbkmoney.proxy.mocketbank.utils.constant.testcards.TestCard;
import com.rbkmoney.proxy.mocketbank.utils.constant.testcards.Visa;
import lombok.extern.slf4j.Slf4j;
import org.apache.thrift.TException;
import org.junit.Test;
@ -23,9 +23,8 @@ import java.nio.ByteBuffer;
import java.util.HashMap;
import java.util.Map;
import static com.rbkmoney.java.damsel.utils.creators.DomainPackageCreators.*;
import static com.rbkmoney.java.damsel.utils.creators.ProxyProviderPackageCreators.createRecurrentPaymentTool;
import static com.rbkmoney.java.damsel.utils.creators.ProxyProviderPackageCreators.createRecurrentTokenInfo;
import static com.rbkmoney.java.damsel.utils.creators.DomainPackageCreators.createTargetCaptured;
import static com.rbkmoney.java.damsel.utils.creators.DomainPackageCreators.createTargetProcessed;
import static com.rbkmoney.java.damsel.utils.verification.ProxyProviderVerification.isSuccess;
import static com.rbkmoney.java.damsel.utils.verification.ProxyProviderVerification.isSuspend;
import static com.rbkmoney.proxy.mocketbank.TestData.createCardData;
@ -59,23 +58,10 @@ public class MocketBankServerHandlerRecurrent3DSSuccessIntegrationTest extends I
BankCard bankCard = TestData.createBankCard(cardData);
bankCard.setToken(TestData.BANK_CARD_TOKEN);
mockCds(cardData, bankCard);
mockMpiVerify(MpiEnrollmentStatus.AUTHENTICATION_AVAILABLE);
mockMpi(MpiTransactionStatus.AUTHENTICATION_SUCCESSFUL);
RecurrentTokenContext context = new RecurrentTokenContext();
context.setSession(new RecurrentTokenSession());
context.setTokenInfo(
createRecurrentTokenInfo(
createRecurrentPaymentTool(
createDisposablePaymentResource(
createClientInfo(TestData.FINGERPRINT, TestData.IP_ADDRESS),
TestData.SESSION_ID,
createPaymentTool(bankCard)
)
).setId(recurrentId)
)
);
mockMpiVerify(EnrollmentStatus.AUTHENTICATION_AVAILABLE);
mockMpi(TransactionStatus.AUTHENTICATION_SUCCESSFUL);
RecurrentTokenContext context = createRecurrentTokenContext(bankCard);
RecurrentTokenProxyResult tokenProxyResult = handler.generateToken(context);
assertTrue("GenerateToken isn`t suspend", isSuspend(tokenProxyResult));

View File

@ -2,9 +2,12 @@ package com.rbkmoney.proxy.mocketbank.handler;
import com.rbkmoney.damsel.cds.CardData;
import com.rbkmoney.damsel.domain.BankCard;
import com.rbkmoney.damsel.proxy_provider.*;
import com.rbkmoney.damsel.proxy_provider.PaymentContext;
import com.rbkmoney.damsel.proxy_provider.PaymentProxyResult;
import com.rbkmoney.damsel.proxy_provider.RecurrentTokenContext;
import com.rbkmoney.damsel.proxy_provider.RecurrentTokenProxyResult;
import com.rbkmoney.proxy.mocketbank.TestData;
import com.rbkmoney.proxy.mocketbank.utils.p2p.constant.testcards.*;
import com.rbkmoney.proxy.mocketbank.utils.constant.testcards.*;
import lombok.extern.slf4j.Slf4j;
import org.apache.thrift.TException;
import org.junit.Test;
@ -15,9 +18,8 @@ import org.springframework.test.context.junit4.SpringRunner;
import java.io.IOException;
import static com.rbkmoney.java.damsel.utils.creators.DomainPackageCreators.*;
import static com.rbkmoney.java.damsel.utils.creators.ProxyProviderPackageCreators.createRecurrentPaymentTool;
import static com.rbkmoney.java.damsel.utils.creators.ProxyProviderPackageCreators.createRecurrentTokenInfo;
import static com.rbkmoney.java.damsel.utils.creators.DomainPackageCreators.createTargetCaptured;
import static com.rbkmoney.java.damsel.utils.creators.DomainPackageCreators.createTargetProcessed;
import static com.rbkmoney.java.damsel.utils.verification.ProxyProviderVerification.isSuccess;
import static com.rbkmoney.proxy.mocketbank.TestData.createCardData;
import static org.junit.Assert.assertTrue;
@ -53,27 +55,14 @@ public class MocketBankServerHandlerRecurrentSuccessIntegrationTest extends Inte
bankCard.setToken(TestData.BANK_CARD_TOKEN);
mockCds(cardData, bankCard);
RecurrentTokenContext context = new RecurrentTokenContext();
context.setSession(new RecurrentTokenSession());
context.setTokenInfo(
createRecurrentTokenInfo(
createRecurrentPaymentTool(
createDisposablePaymentResource(
createClientInfo(TestData.FINGERPRINT, TestData.IP_ADDRESS),
TestData.SESSION_ID,
createPaymentTool(bankCard)
)
).setId(recurrentId)
)
);
RecurrentTokenContext context = createRecurrentTokenContext(bankCard);
RecurrentTokenProxyResult generationProxyResult = handler.generateToken(context);
String token = generationProxyResult.getIntent().getFinish().getStatus().getSuccess().getToken();
PaymentContext paymentContext = getContext(getPaymentResourceRecurrent(token), createTargetProcessed(), null);
PaymentProxyResult proxyResult = handler.processPayment(paymentContext);
assertTrue("Process payment isn`t success", isSuccess(proxyResult));
assertTrue("Process Payment isn`t success", isSuccess(proxyResult));
paymentContext.getPaymentInfo().getPayment().setTrx(proxyResult.getTrx());
paymentContext.getSession().setTarget(createTargetCaptured());

View File

@ -5,8 +5,8 @@ import com.rbkmoney.damsel.domain.BankCard;
import com.rbkmoney.damsel.domain.BankCardTokenProvider;
import com.rbkmoney.damsel.proxy_provider.PaymentProxyResult;
import com.rbkmoney.proxy.mocketbank.TestData;
import com.rbkmoney.proxy.mocketbank.utils.p2p.constant.testcards.TestCard;
import com.rbkmoney.proxy.mocketbank.utils.p2p.constant.testcards.Visa;
import com.rbkmoney.proxy.mocketbank.utils.constant.testcards.TestCard;
import com.rbkmoney.proxy.mocketbank.utils.constant.testcards.Visa;
import lombok.extern.slf4j.Slf4j;
import org.apache.thrift.TException;
import org.junit.Test;

View File

@ -5,8 +5,8 @@ import com.rbkmoney.damsel.domain.BankCard;
import com.rbkmoney.damsel.domain.BankCardTokenProvider;
import com.rbkmoney.damsel.proxy_provider.PaymentProxyResult;
import com.rbkmoney.proxy.mocketbank.TestData;
import com.rbkmoney.proxy.mocketbank.utils.p2p.constant.testcards.Mastercard;
import com.rbkmoney.proxy.mocketbank.utils.p2p.constant.testcards.TestCard;
import com.rbkmoney.proxy.mocketbank.utils.constant.testcards.Mastercard;
import com.rbkmoney.proxy.mocketbank.utils.constant.testcards.TestCard;
import lombok.extern.slf4j.Slf4j;
import org.apache.thrift.TException;
import org.junit.Test;

View File

@ -5,7 +5,7 @@ import com.rbkmoney.damsel.domain.BankCard;
import com.rbkmoney.damsel.domain.TransactionInfo;
import com.rbkmoney.damsel.proxy_provider.PaymentProxyResult;
import com.rbkmoney.proxy.mocketbank.TestData;
import com.rbkmoney.proxy.mocketbank.utils.p2p.constant.testcards.*;
import com.rbkmoney.proxy.mocketbank.utils.constant.testcards.*;
import lombok.extern.slf4j.Slf4j;
import org.apache.thrift.TException;
import org.junit.Test;

View File

@ -5,8 +5,8 @@ import com.rbkmoney.damsel.domain.BankCard;
import com.rbkmoney.damsel.domain.BankCardTokenProvider;
import com.rbkmoney.damsel.proxy_provider.PaymentProxyResult;
import com.rbkmoney.proxy.mocketbank.TestData;
import com.rbkmoney.proxy.mocketbank.utils.p2p.constant.testcards.Mastercard;
import com.rbkmoney.proxy.mocketbank.utils.p2p.constant.testcards.TestCard;
import com.rbkmoney.proxy.mocketbank.utils.constant.testcards.Mastercard;
import com.rbkmoney.proxy.mocketbank.utils.constant.testcards.TestCard;
import lombok.extern.slf4j.Slf4j;
import org.apache.thrift.TException;
import org.junit.Test;

View File

@ -6,12 +6,12 @@ import com.rbkmoney.damsel.proxy_provider.PaymentCallbackResult;
import com.rbkmoney.damsel.proxy_provider.PaymentContext;
import com.rbkmoney.damsel.proxy_provider.PaymentProxyResult;
import com.rbkmoney.proxy.mocketbank.TestData;
import com.rbkmoney.proxy.mocketbank.service.mpi.constant.EnrollmentStatus;
import com.rbkmoney.proxy.mocketbank.service.mpi.constant.TransactionStatus;
import com.rbkmoney.proxy.mocketbank.utils.Converter;
import com.rbkmoney.proxy.mocketbank.utils.mocketbank.constant.MpiEnrollmentStatus;
import com.rbkmoney.proxy.mocketbank.utils.mocketbank.constant.MpiTransactionStatus;
import com.rbkmoney.proxy.mocketbank.utils.p2p.constant.testcards.Mastercard;
import com.rbkmoney.proxy.mocketbank.utils.p2p.constant.testcards.TestCard;
import com.rbkmoney.proxy.mocketbank.utils.p2p.constant.testcards.Visa;
import com.rbkmoney.proxy.mocketbank.utils.constant.testcards.Mastercard;
import com.rbkmoney.proxy.mocketbank.utils.constant.testcards.TestCard;
import com.rbkmoney.proxy.mocketbank.utils.constant.testcards.Visa;
import lombok.extern.slf4j.Slf4j;
import org.apache.thrift.TException;
import org.junit.Test;
@ -60,8 +60,8 @@ public class MocketBankServerHandlerSuccessWith3DSIntegrationTest extends Integr
private void processPaymentSuccess(CardData cardData) throws TException, IOException {
BankCard bankCard = TestData.createBankCard(cardData);
mockCds(cardData, bankCard);
mockMpiVerify(MpiEnrollmentStatus.AUTHENTICATION_AVAILABLE);
mockMpi(MpiTransactionStatus.AUTHENTICATION_SUCCESSFUL);
mockMpiVerify(EnrollmentStatus.AUTHENTICATION_AVAILABLE);
mockMpi(TransactionStatus.AUTHENTICATION_SUCCESSFUL);
PaymentContext paymentContext = getContext(bankCard, createTargetProcessed(), null);
PaymentProxyResult proxyResult = handler.processPayment(paymentContext);

View File

@ -1,4 +1,4 @@
package com.rbkmoney.proxy.mocketbank.utils.p2p.constant.testcards;
package com.rbkmoney.proxy.mocketbank.utils.constant.testcards;
import lombok.Getter;
import lombok.RequiredArgsConstructor;

View File

@ -1,4 +1,4 @@
package com.rbkmoney.proxy.mocketbank.utils.p2p.constant.testcards;
package com.rbkmoney.proxy.mocketbank.utils.constant.testcards;
import lombok.Getter;
import lombok.RequiredArgsConstructor;

View File

@ -1,4 +1,4 @@
package com.rbkmoney.proxy.mocketbank.utils.p2p.constant.testcards;
package com.rbkmoney.proxy.mocketbank.utils.constant.testcards;
import lombok.Getter;
import lombok.RequiredArgsConstructor;

View File

@ -0,0 +1,5 @@
package com.rbkmoney.proxy.mocketbank.utils.constant.testcards;
public interface TestCard {
String getCardNumber();
}

View File

@ -1,4 +1,4 @@
package com.rbkmoney.proxy.mocketbank.utils.p2p.constant.testcards;
package com.rbkmoney.proxy.mocketbank.utils.constant.testcards;
import lombok.Getter;
import lombok.RequiredArgsConstructor;

View File

@ -1,85 +0,0 @@
package com.rbkmoney.proxy.mocketbank.utils.damsel;
import com.rbkmoney.damsel.domain.Failure;
import com.rbkmoney.proxy.mocketbank.utils.error_mapping.ErrorMapping;
import com.rbkmoney.proxy.mocketbank.utils.mocketbank.constant.MpiAction;
import com.rbkmoney.woody.api.flow.error.WRuntimeException;
import lombok.extern.slf4j.Slf4j;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;
import java.util.HashMap;
import java.util.Map;
import static com.rbkmoney.geck.serializer.kit.tbase.TErrorUtil.toGeneral;
import static org.junit.Assert.assertEquals;
@Slf4j
@RunWith(SpringRunner.class)
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.DEFINED_PORT)
public class ErrorMappingTest {
@Autowired
private ErrorMapping errorMapping;
@Test(expected = WRuntimeException.class)
public void testMakeFailureByDescriptionException() {
errorMapping.getFailureByCodeAndDescription(
"wrong code",
"wrong description"
);
}
@Test
public void testMakeFailureByDescription() {
Map<String, String> map = new HashMap<>();
map.put(MpiAction.UNSUPPORTED_CARD.getAction(), "Failure(code:authorization_failed, reason:'Unsupported Card' - 'Unsupported Card', sub:SubFailure(code:payment_tool_rejected, sub:SubFailure(code:bank_card_rejected, sub:SubFailure(code:card_unsupported))))");
map.put(MpiAction.THREE_D_SECURE_FAILURE.getAction(), "Failure(code:preauthorization_failed, reason:'3-D Secure Failure' - '3-D Secure Failure')");
map.put(MpiAction.THREE_D_SECURE_TIMEOUT.getAction(), "Failure(code:preauthorization_failed, reason:'3-D Secure Timeout' - '3-D Secure Timeout')");
map.put(MpiAction.INSUFFICIENT_FUNDS.getAction(), "Failure(code:authorization_failed, reason:'Insufficient Funds' - 'Insufficient Funds', sub:SubFailure(code:insufficient_funds))");
map.put(MpiAction.INVALID_CARD.getAction(), "Failure(code:authorization_failed, reason:'Invalid Card' - 'Invalid Card', sub:SubFailure(code:payment_tool_rejected, sub:SubFailure(code:bank_card_rejected, sub:SubFailure(code:card_number_invalid))))");
map.put(MpiAction.CVV_MATCH_FAIL.getAction(), "Failure(code:authorization_failed, reason:'CVV Match Fail' - 'CVV Match Fail', sub:SubFailure(code:payment_tool_rejected, sub:SubFailure(code:bank_card_rejected, sub:SubFailure(code:cvv_invalid))))");
map.put(MpiAction.EXPIRED_CARD.getAction(), "Failure(code:authorization_failed, reason:'Expired Card' - 'Expired Card', sub:SubFailure(code:payment_tool_rejected, sub:SubFailure(code:bank_card_rejected, sub:SubFailure(code:card_expired))))");
map.put(MpiAction.UNKNOWN_FAILURE.getAction(), "Failure(code:authorization_failed, reason:'Unknown Failure' - 'Unknown Failure', sub:SubFailure(code:unknown))");
map.forEach((k, v) -> {
Failure failure = errorMapping.getFailureByCodeAndDescription(k, k);
log.info(failure.toString());
assertEquals(v, failure.toString());
}
);
}
@Test
public void testAttemptsWithMapWithoutWIldCard() {
Map<String, String> map = new HashMap<>();
map.put("Unsupported Card", "authorization_failed:payment_tool_rejected:bank_card_rejected:card_unsupported");
map.put("3-D Secure Failure", "preauthorization_error");
map.put("3-D Secure Timeout", "preauthorization_error");
map.put("Invalid Card", "authorization_failed:payment_tool_rejected:bank_card_rejected:card_number_invalid");
map.put("CVV Match Fail", "authorization_failed:payment_tool_rejected:bank_card_rejected:cvv_invalid");
map.put("Expired Card", "authorization_failed:payment_tool_rejected:bank_card_rejected:card_expired");
map.put("Unknown", "authorization_failed:unknown");
map.put("Unknown Failure", "authorization_failed:unknown");
String code = "Unsupported Card";
String type = map.entrySet().stream()
.filter(m -> m.getKey().contains(code))
.findFirst()
.orElseThrow(IllegalArgumentException::new)
.getValue();
Failure failure = toGeneral(type);
log.info(failure.toString());
assertEquals("Failure(code:authorization_failed, sub:SubFailure(code:payment_tool_rejected, sub:SubFailure(code:bank_card_rejected, sub:SubFailure(code:card_unsupported))))", failure.toString());
}
}

View File

@ -1,5 +0,0 @@
package com.rbkmoney.proxy.mocketbank.utils.p2p.constant.testcards;
public interface TestCard {
String getCardNumber();
}