Init classes

This commit is contained in:
k.struzhkin 2019-05-13 12:29:22 +03:00
parent 80b8a0fe47
commit 71bdcd7633
24 changed files with 533 additions and 0 deletions

4
.gitmodules vendored Normal file
View File

@ -0,0 +1,4 @@
[submodule "build_utils"]
path = build_utils
url = git@github.com:rbkmoney/build_utils.git
branch = master

7
.idea/vcs.xml Normal file
View File

@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="VcsDirectoryMappings">
<mapping directory="" vcs="Git" />
<mapping directory="$PROJECT_DIR$/build_utils" vcs="Git" />
</component>
</project>

1
build_utils Submodule

@ -0,0 +1 @@
Subproject commit ea4aa042f482551d624fd49a570d28488f479e93

View File

@ -0,0 +1,101 @@
package com.rbkmoney.adapter.bank.spring.boot.starter.config;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpRequest;
import org.springframework.http.HttpStatus;
import org.springframework.http.client.ClientHttpRequestExecution;
import org.springframework.http.client.ClientHttpRequestInterceptor;
import org.springframework.http.client.ClientHttpResponse;
import org.springframework.util.StreamUtils;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.nio.charset.StandardCharsets;
import java.util.concurrent.atomic.AtomicInteger;
@Slf4j
public class LoggingInterceptor implements ClientHttpRequestInterceptor {
private AtomicInteger requestNumberSequence = new AtomicInteger(0);
@Override
public ClientHttpResponse intercept(HttpRequest request, byte[] body, ClientHttpRequestExecution execution) throws IOException {
int requestNumber = requestNumberSequence.incrementAndGet();
logRequest(requestNumber, request, body);
ClientHttpResponse response = execution.execute(request, body);
response = new BufferedClientHttpResponse(response);
logResponse(requestNumber, response);
return response;
}
private void logRequest(int requestNumber, HttpRequest request, byte[] body) {
if (log.isDebugEnabled()) {
String prefix = requestNumber + " > ";
log.debug("{} Request: {} {}", prefix, request.getMethod(), request.getURI());
log.debug("{} Headers: {}", prefix, request.getHeaders());
if (body.length > 0) {
log.debug("{} Body: \n{}", prefix, new String(body, StandardCharsets.UTF_8));
}
}
}
private void logResponse(int requestNumber, ClientHttpResponse response) throws IOException {
if (log.isDebugEnabled()) {
String prefix = requestNumber + " < ";
log.debug("{} Response: {} {} {}", prefix, response.getStatusCode(), response.getStatusCode().name(), response.getStatusText());
log.debug("{} Headers: {}", prefix, response.getHeaders());
String body = StreamUtils.copyToString(response.getBody(), StandardCharsets.UTF_8);
if (body.length() > 0) {
log.debug("{} Body: \n{}", prefix, body);
}
}
}
/**
* Wrapper around ClientHttpResponse, buffers the body so it can be read repeatedly (for logging & consuming the result).
*/
private class BufferedClientHttpResponse implements ClientHttpResponse {
private final ClientHttpResponse response;
private byte[] body;
public BufferedClientHttpResponse(ClientHttpResponse response) {
this.response = response;
}
@Override
public HttpStatus getStatusCode() throws IOException {
return response.getStatusCode();
}
@Override
public int getRawStatusCode() throws IOException {
return response.getRawStatusCode();
}
@Override
public String getStatusText() throws IOException {
return response.getStatusText();
}
@Override
public void close() {
response.close();
}
@Override
public InputStream getBody() throws IOException {
if (body == null) {
body = StreamUtils.copyToByteArray(response.getBody());
}
return new ByteArrayInputStream(body);
}
@Override
public HttpHeaders getHeaders() {
return response.getHeaders();
}
}
}

View File

@ -0,0 +1,23 @@
package com.rbkmoney.adapter.bank.spring.boot.starter.constants;
import lombok.Getter;
import lombok.RequiredArgsConstructor;
@Getter
@RequiredArgsConstructor
public enum OperationCode {
SALE(1),
FINISH_THREE_DS(2),
AUTH(3),
CAPTURED(5),
REVERSAL(6),
REFUND(7),
RECURRING_INIT_SALE(10),
RECURRING_INIT_AUTH(11),
RECURRING_SALE(12),
STATUS(30);
private final Integer code;
}

View File

@ -0,0 +1,10 @@
package com.rbkmoney.adapter.bank.spring.boot.starter.constants;
public class OptionalField {
public static final String MERCHANT_SITE = "merchant_site";
public static final String CITY = "city";
public static final String REGION = "region";
public static final String COUNTRY = "country";
}

View File

@ -0,0 +1,9 @@
package com.rbkmoney.adapter.bank.spring.boot.starter.constants;
public enum TargetStatus {
PROCESSED,
CAPTURED,
CANCELLED,
REFUNDED,
AUTH_RECURRENT
}

View File

@ -0,0 +1,10 @@
package com.rbkmoney.adapter.bank.spring.boot.starter.constants;
public class ThreeDsFields {
public static final String MD = "MD";
public static final String PA_REQ = "PaReq";
public static final String PA_RES = "PaRes";
public static final String TERM_URL = "TermUrl";
}

View File

@ -0,0 +1,30 @@
package com.rbkmoney.adapter.bank.spring.boot.starter.constants;
import lombok.RequiredArgsConstructor;
import java.util.HashMap;
import java.util.Map;
@RequiredArgsConstructor
public enum TrxStatus {
INIT(0),
DECLINED(1),
AUTHORIZED(2),
CAPTURED(3),
RECONCILED(4),
SETTLED(5);
private final Integer code;
private static final Map<Integer, TrxStatus> valueMap = new HashMap<>();
static {
for (TrxStatus value : TrxStatus.values()) {
valueMap.put(value.code, value);
}
}
public static TrxStatus statusByCode(Integer code) {
return valueMap.get(code);
}
}

View File

@ -0,0 +1,32 @@
package com.rbkmoney.adapter.bank.spring.boot.starter.constants;
import lombok.Getter;
import lombok.RequiredArgsConstructor;
import java.util.HashMap;
import java.util.Map;
@Getter
@RequiredArgsConstructor
public enum TrxType {
AUTH(2),
REFUND(3),
REVERSAL(4),
RECURRING(5),
RECURRING_INIT(6),
RECURRING_AUTH(7);
private final Integer code;
private static final Map<Integer, TrxType> valueMap = new HashMap<>();
static {
for (TrxType value : TrxType.values()) {
valueMap.put(value.code, value);
}
}
public static TrxType statusByCode(Integer code) {
return valueMap.get(code);
}
}

View File

@ -0,0 +1,79 @@
package com.rbkmoney.adapter.bank.spring.boot.starter.flow;
import com.rbkmoney.adapter.bank.spring.boot.starter.model.AdapterContext;
import com.rbkmoney.adapter.bank.spring.boot.starter.model.EntryStateModel;
import com.rbkmoney.adapter.bank.spring.boot.starter.model.ExitStateModel;
import com.rbkmoney.adapter.bank.spring.boot.starter.model.Step;
import org.springframework.stereotype.Component;
@Component
public class DefaultStepResolverImpl implements StepResolver {
@Override
public Step resolveEntry(EntryStateModel stateModel) {
switch (stateModel.getTargetStatus()) {
case PROCESSED:
return resolveProcessedSteps(stateModel);
case CAPTURED:
return Step.CAPTURE;
case REFUNDED:
return Step.REFUND;
case CANCELLED:
return Step.CANCEL;
case AUTH_RECURRENT:
return resolveAuthRecurrent(stateModel);
default:
return null;
}
}
private Step resolveProcessedSteps(EntryStateModel stateModel) {
if (isNextThreeDs(stateModel)) {
return Step.FINISH_THREE_DS;
} else if (stateModel.isMakeRecurrent()) {
return Step.AUTH_RECURRENT;
} else if (stateModel.getRecToken() != null) {
return Step.RECURRENT;
}
return Step.AUTH;
}
private Step resolveAuthRecurrent(EntryStateModel stateModel) {
AdapterContext adapterContext = stateModel.getAdapterContext();
if (adapterContext != null
&& (Step.GENERATE_TOKEN_FINISH_THREE_DS.equals(adapterContext.getNextStep())
|| Step.GENERATE_TOKEN_CAPTURE.equals(adapterContext.getNextStep())
|| Step.GENERATE_TOKEN_REFUND.equals(adapterContext.getNextStep()))) {
return adapterContext.getNextStep();
}
return Step.AUTH_RECURRENT;
}
private static boolean isNextThreeDs(EntryStateModel stateModel) {
return stateModel.getAdapterContext() != null && stateModel.getAdapterContext().getNextStep() != null
&& (Step.FINISH_THREE_DS.equals(stateModel.getAdapterContext().getNextStep())
|| Step.GENERATE_TOKEN_FINISH_THREE_DS.equals(stateModel.getAdapterContext().getNextStep()));
}
@Override
public Step resolveExit(ExitStateModel stateModel) {
EntryStateModel entryStateModel = stateModel.getEntryStateModel();
Step step = entryStateModel.getStep();
switch (step) {
case AUTH_RECURRENT:
if (Step.FINISH_THREE_DS.equals(stateModel.getNextStep())) {
return Step.GENERATE_TOKEN_FINISH_THREE_DS;
} else {
return Step.GENERATE_TOKEN_CAPTURE;
}
case GENERATE_TOKEN_FINISH_THREE_DS:
return Step.GENERATE_TOKEN_CAPTURE;
case GENERATE_TOKEN_CAPTURE:
return Step.GENERATE_TOKEN_REFUND;
case GENERATE_TOKEN_REFUND:
return Step.GENERATE_TOKEN_FINISH;
default:
return stateModel.getNextStep();
}
}
}

View File

@ -0,0 +1,13 @@
package com.rbkmoney.adapter.bank.spring.boot.starter.flow;
import com.rbkmoney.adapter.bank.spring.boot.starter.model.EntryStateModel;
import com.rbkmoney.adapter.bank.spring.boot.starter.model.ExitStateModel;
import com.rbkmoney.adapter.bank.spring.boot.starter.model.Step;
public interface StepResolver {
Step resolveEntry(EntryStateModel stateModel);
Step resolveExit(ExitStateModel stateModel);
}

View File

@ -0,0 +1,14 @@
package com.rbkmoney.adapter.bank.spring.boot.starter.handler;
import com.rbkmoney.adapter.bank.spring.boot.starter.model.EntryStateModel;
import com.rbkmoney.adapter.bank.spring.boot.starter.processor.Processor;
import org.apache.thrift.TException;
public interface CommonHandler<T, R, E extends EntryStateModel> {
boolean isHandle(final E entryStateModel);
T handle(E context) throws TException;
Processor<T, R> getProcessor();
}

View File

@ -0,0 +1,31 @@
package com.rbkmoney.adapter.bank.spring.boot.starter.handler;
import com.rbkmoney.adapter.bank.spring.boot.starter.model.EntryStateModel;
import com.rbkmoney.adapter.bank.spring.boot.starter.processor.Processor;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.core.convert.converter.Converter;
import java.util.function.Function;
@Slf4j
@RequiredArgsConstructor
public abstract class CommonHandlerImpl<T, P, R, E extends EntryStateModel> implements CommonHandler<T, R, E> {
private final Function<P, R> requestFunction;
private final Converter<E, P> converter;
private final Processor<T, R> processor;
@Override
public T handle(E entryStateModel) {
P request = converter.convert(entryStateModel);
R response = requestFunction.apply(request);
return processor.process(response, entryStateModel);
}
@Override
public Processor<T, R> getProcessor() {
return processor;
}
}

View File

@ -0,0 +1,27 @@
package com.rbkmoney.adapter.bank.spring.boot.starter.model;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Getter;
import lombok.Setter;
import lombok.ToString;
import java.time.Instant;
@Getter
@Setter
@ToString
@JsonInclude(JsonInclude.Include.NON_NULL)
@JsonIgnoreProperties(ignoreUnknown = true)
public class AdapterContext {
@JsonProperty(value = "max_date_time_polling")
private Instant maxDateTimePolling;
private Step nextStep;
private String pares;
@JsonProperty(value = "trx_id")
private String trxId;
}

View File

@ -0,0 +1,14 @@
package com.rbkmoney.adapter.bank.spring.boot.starter.model;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Data;
@Data
public class Callback {
@JsonProperty(value = "MD")
private String md;
@JsonProperty(value = "PaRes")
private String paRes;
@JsonProperty(value = "termination_uri")
private String terminationUri;
}

View File

@ -0,0 +1,45 @@
package com.rbkmoney.adapter.bank.spring.boot.starter.model;
import com.rbkmoney.adapter.bank.spring.boot.starter.constants.TargetStatus;
import com.rbkmoney.damsel.cds.ExpDate;
import lombok.Builder;
import lombok.Data;
import lombok.ToString;
import java.util.Map;
@Data
@Builder
@ToString(exclude = {"pan", "cvv2", "expDate"})
public class EntryStateModel {
private String merchantUid;
private String merchantSite;
private String pan;
private ExpDate expDate;
private String cvv2;
private String amount;
private Short currency;
private String modifiers;
private String cardName;
private String orderId;
private String ip;
private String email;
private String country;
private String city;
private String region;
private String address;
private String phone;
private String callbackUrl;
private String trxId;
private String key;
private String refundId;
private String recToken;
private TargetStatus targetStatus;
private boolean makeRecurrent;
private AdapterContext adapterContext;
private Map<String, String> parameters;
private Step step;
}

View File

@ -0,0 +1,22 @@
package com.rbkmoney.adapter.bank.spring.boot.starter.model;
import lombok.Builder;
import lombok.Data;
@Data
@Builder
public class ExitStateModel {
private Step nextStep;
private String errorCode;
private String errorMessage;
private AdapterContext adapterContext;
private EntryStateModel entryStateModel;
private String pareq;
private String refundId;
private String md;
private String acsUrl;
private Long txnId;
private Long newTxnId;
}

View File

@ -0,0 +1,21 @@
package com.rbkmoney.adapter.bank.spring.boot.starter.model;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Getter;
import lombok.Setter;
import lombok.ToString;
@Getter
@Setter
@ToString
@JsonInclude(JsonInclude.Include.NON_NULL)
@JsonIgnoreProperties(ignoreUnknown = true)
public class RecurrentContext {
@JsonProperty(value = "trx_id")
private String trxId;
}

View File

@ -0,0 +1,17 @@
package com.rbkmoney.adapter.bank.spring.boot.starter.model;
public enum Step {
AUTH,
RECURRENT,
AUTH_RECURRENT,
CANCEL,
FINISH_THREE_DS,
GENERATE_TOKEN_FINISH_THREE_DS,
GENERATE_TOKEN_CAPTURE,
GENERATE_TOKEN_REFUND,
GENERATE_TOKEN_FINISH,
CAPTURE,
REFUND;
}

View File

@ -0,0 +1,9 @@
package com.rbkmoney.adapter.bank.spring.boot.starter.processor;
import com.rbkmoney.adapter.bank.spring.boot.starter.model.EntryStateModel;
public interface Processor<T, R> {
T process(R response, EntryStateModel context);
}

View File

@ -0,0 +1,5 @@
package com.rbkmoney.adapter.bank.spring.boot.starter.validator;
public interface Validator<T> {
void validate(T request);
}

View File

@ -0,0 +1,4 @@
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
com.rbkmoney.adapter.bank.spring.boot.starter.config.ErrorMappingConfiguration,\
com.rbkmoney.adapter.bank.spring.boot.starter.config.properties.TimerProperties,\
com.rbkmoney.adapter.bank.spring.boot.starter.flow.DefaultStepResolverImpl

View File

@ -0,0 +1,5 @@
---
time.config:
redirectTimeout: 600
maxTimePolling: 600
pollingDelay: 10