mirror of
https://github.com/valitydev/adapter-bank-spring-boot-starter.git
synced 2024-11-06 01:05:20 +00:00
Init classes
This commit is contained in:
parent
80b8a0fe47
commit
71bdcd7633
4
.gitmodules
vendored
Normal file
4
.gitmodules
vendored
Normal 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
7
.idea/vcs.xml
Normal 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
1
build_utils
Submodule
@ -0,0 +1 @@
|
||||
Subproject commit ea4aa042f482551d624fd49a570d28488f479e93
|
@ -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();
|
||||
}
|
||||
}
|
||||
}
|
@ -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;
|
||||
|
||||
}
|
@ -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";
|
||||
|
||||
}
|
@ -0,0 +1,9 @@
|
||||
package com.rbkmoney.adapter.bank.spring.boot.starter.constants;
|
||||
|
||||
public enum TargetStatus {
|
||||
PROCESSED,
|
||||
CAPTURED,
|
||||
CANCELLED,
|
||||
REFUNDED,
|
||||
AUTH_RECURRENT
|
||||
}
|
@ -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";
|
||||
|
||||
}
|
@ -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);
|
||||
}
|
||||
}
|
@ -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);
|
||||
}
|
||||
}
|
@ -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();
|
||||
}
|
||||
}
|
||||
}
|
@ -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);
|
||||
|
||||
}
|
@ -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();
|
||||
}
|
@ -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;
|
||||
}
|
||||
}
|
@ -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;
|
||||
|
||||
}
|
@ -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;
|
||||
}
|
@ -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;
|
||||
}
|
@ -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;
|
||||
|
||||
}
|
@ -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;
|
||||
|
||||
}
|
@ -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;
|
||||
|
||||
}
|
@ -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);
|
||||
|
||||
}
|
@ -0,0 +1,5 @@
|
||||
package com.rbkmoney.adapter.bank.spring.boot.starter.validator;
|
||||
|
||||
public interface Validator<T> {
|
||||
void validate(T request);
|
||||
}
|
4
src/main/resources/META-INF/spring.factories
Normal file
4
src/main/resources/META-INF/spring.factories
Normal 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
|
5
src/main/resources/application.yml
Normal file
5
src/main/resources/application.yml
Normal file
@ -0,0 +1,5 @@
|
||||
---
|
||||
time.config:
|
||||
redirectTimeout: 600
|
||||
maxTimePolling: 600
|
||||
pollingDelay: 10
|
Loading…
Reference in New Issue
Block a user