mirror of
https://github.com/valitydev/anapi-v2.git
synced 2024-11-06 08:35:19 +00:00
Merge pull request #2 from rbkmoney/ft/JD-599/payments-search
JD-599: Payments search impl
This commit is contained in:
commit
97fd4e130e
78
.gitignore
vendored
Normal file
78
.gitignore
vendored
Normal file
@ -0,0 +1,78 @@
|
||||
# Created by .ignore support plugin (hsz.mobi)
|
||||
.eunit
|
||||
deps
|
||||
*.o
|
||||
*.beam
|
||||
*.plt
|
||||
erl_crash.dump
|
||||
ebin/*.beam
|
||||
rel/example_project
|
||||
.concrete/DEV_MODE
|
||||
.rebar
|
||||
target/
|
||||
pom.xml.tag
|
||||
pom.xml.releaseBackup
|
||||
pom.xml.versionsBackup
|
||||
pom.xml.next
|
||||
release.properties
|
||||
dependency-reduced-pom.xml
|
||||
buildNumber.properties
|
||||
.mvn/timing.properties
|
||||
# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio and Webstorm
|
||||
# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839
|
||||
|
||||
# User-specific stuff:
|
||||
.idea/
|
||||
.idea/workspace.xml
|
||||
.idea/tasks.xml
|
||||
.idea/dictionaries
|
||||
.idea/vcs.xml
|
||||
.idea/jsLibraryMappings.xml
|
||||
|
||||
# Sensitive or high-churn files:
|
||||
.idea/dataSources.ids
|
||||
.idea/dataSources.xml
|
||||
.idea/dataSources.local.xml
|
||||
.idea/sqlDataSources.xml
|
||||
.idea/dynamic.xml
|
||||
.idea/uiDesigner.xml
|
||||
|
||||
# Gradle:
|
||||
.idea/gradle.xml
|
||||
.idea/libraries
|
||||
|
||||
# Mongo Explorer plugin:
|
||||
.idea/mongoSettings.xml
|
||||
|
||||
*.iws
|
||||
*.ipr
|
||||
*.iml
|
||||
|
||||
|
||||
# IntelliJ
|
||||
/out/
|
||||
|
||||
# mpeltonen/sbt-idea plugin
|
||||
.idea_modules/
|
||||
|
||||
# JIRA plugin
|
||||
atlassian-ide-plugin.xml
|
||||
|
||||
# Crashlytics plugin (for Android Studio and IntelliJ)
|
||||
com_crashlytics_export_strings.xml
|
||||
crashlytics.properties
|
||||
crashlytics-build.properties
|
||||
fabric.properties
|
||||
*.class
|
||||
|
||||
# Mobile Tools for Java (J2ME)
|
||||
.mtj.tmp/
|
||||
|
||||
# Package Files #
|
||||
*.jar
|
||||
*.war
|
||||
*.ear
|
||||
|
||||
# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml
|
||||
hs_err_pid*
|
||||
env.list
|
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
|
15
Jenkinsfile
vendored
Normal file
15
Jenkinsfile
vendored
Normal file
@ -0,0 +1,15 @@
|
||||
#!groovy
|
||||
build('anapi-v2', 'java-maven') {
|
||||
checkoutRepo()
|
||||
loadBuildUtils()
|
||||
|
||||
def javaServicePipeline
|
||||
runStage('load JavaService pipeline') {
|
||||
javaServicePipeline = load("build_utils/jenkins_lib/pipeJavaServiceInsideDocker.groovy")
|
||||
}
|
||||
|
||||
def serviceName = env.REPO_NAME
|
||||
def mvnArgs = '-DjvmArgs="-Xmx256m"'
|
||||
|
||||
javaServicePipeline(serviceName, mvnArgs)
|
||||
}
|
1
build_utils
Submodule
1
build_utils
Submodule
@ -0,0 +1 @@
|
||||
Subproject commit c12c9dd296912ec3c34ad443b448df98fef2556a
|
313
pom.xml
Normal file
313
pom.xml
Normal file
@ -0,0 +1,313 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<parent>
|
||||
<groupId>com.rbkmoney</groupId>
|
||||
<artifactId>service-parent-pom</artifactId>
|
||||
<version>2.0.7</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>anapi-v2</artifactId>
|
||||
<version>1.0.0</version>
|
||||
<packaging>jar</packaging>
|
||||
|
||||
<name>anapi-v2</name>
|
||||
<description>anapi v2</description>
|
||||
|
||||
<properties>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
|
||||
<java.version>15</java.version>
|
||||
<server.port>8022</server.port>
|
||||
<management.port>8023</management.port>
|
||||
<exposed.ports>${server.port} ${management.port}</exposed.ports>
|
||||
<dockerfile.registry>${env.REGISTRY}</dockerfile.registry>
|
||||
<springfox-version>2.9.2</springfox-version>
|
||||
<servlet-api-version>2.5</servlet-api-version>
|
||||
<jackson-version>2.12.5</jackson-version>
|
||||
<spring-version>2.5.3</spring-version>
|
||||
<javax-annotation-api-version>1.3.2</javax-annotation-api-version>
|
||||
<jaxb-version>2.3.1</jaxb-version>
|
||||
</properties>
|
||||
|
||||
<dependencies>
|
||||
|
||||
<!--rbkmoney-->
|
||||
<dependency>
|
||||
<groupId>com.rbkmoney</groupId>
|
||||
<artifactId>custom-metrics-spring-boot-starter</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.rbkmoney</groupId>
|
||||
<artifactId>custom-actuator-endpoints</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.rbkmoney.woody</groupId>
|
||||
<artifactId>woody-thrift</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.rbkmoney</groupId>
|
||||
<artifactId>shared-resources</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.rbkmoney</groupId>
|
||||
<artifactId>bouncer-proto</artifactId>
|
||||
<version>1.27-cc50cc4</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.rbkmoney</groupId>
|
||||
<artifactId>org-management-proto</artifactId>
|
||||
<version>1.3-39d8513</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.rbkmoney</groupId>
|
||||
<artifactId>payout-manager-proto</artifactId>
|
||||
<version>1.17-8aa3eb8</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.rbkmoney</groupId>
|
||||
<artifactId>swag-anapi-v2</artifactId>
|
||||
<version>1.47-23587c8-server</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.rbkmoney</groupId>
|
||||
<artifactId>magista-proto</artifactId>
|
||||
<version>1.20-f95c236</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.rbkmoney</groupId>
|
||||
<artifactId>vortigon-proto</artifactId>
|
||||
<version>1.13-0c92608</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.rbkmoney.geck</groupId>
|
||||
<artifactId>serializer</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.rbkmoney</groupId>
|
||||
<artifactId>damsel</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!--spring-->
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-security</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.security</groupId>
|
||||
<artifactId>spring-security-config</artifactId>
|
||||
<version>5.5.2</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.security</groupId>
|
||||
<artifactId>spring-security-web</artifactId>
|
||||
<version>5.5.2</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<artifactId>keycloak-admin-client</artifactId>
|
||||
<version>15.0.2</version>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<groupId>org.jboss.resteasy</groupId>
|
||||
<artifactId>resteasy-client</artifactId>
|
||||
</exclusion>
|
||||
<exclusion>
|
||||
<groupId>org.jboss.resteasy</groupId>
|
||||
<artifactId>resteasy-multipart-provider</artifactId>
|
||||
</exclusion>
|
||||
<exclusion>
|
||||
<groupId>org.jboss.resteasy</groupId>
|
||||
<artifactId>resteasy-jackson2-provider</artifactId>
|
||||
</exclusion>
|
||||
<exclusion>
|
||||
<groupId>org.jboss.resteasy</groupId>
|
||||
<artifactId>resteasy-jaxb-provider</artifactId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<artifactId>keycloak-spring-security-adapter</artifactId>
|
||||
<version>15.0.2</version>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<groupId>org.bouncycastle</groupId>
|
||||
<artifactId>bcprov-jdk15on</artifactId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-validation</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-web</artifactId>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<groupId>org.hibernate</groupId>
|
||||
<artifactId>hibernate-validator</artifactId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-actuator</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-configuration-processor</artifactId>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
|
||||
<!--third party-->
|
||||
<dependency>
|
||||
<groupId>javax.servlet</groupId>
|
||||
<artifactId>javax.servlet-api</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>io.swagger</groupId>
|
||||
<artifactId>swagger-annotations</artifactId>
|
||||
<version>1.6.2</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>io.springfox</groupId>
|
||||
<artifactId>springfox-swagger2</artifactId>
|
||||
<version>${springfox-version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>io.springfox</groupId>
|
||||
<artifactId>springfox-swagger-ui</artifactId>
|
||||
<version>${springfox-version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.projectlombok</groupId>
|
||||
<artifactId>lombok</artifactId>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>javax.servlet</groupId>
|
||||
<artifactId>servlet-api</artifactId>
|
||||
<version>${servlet-api-version}</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>javax.annotation</groupId>
|
||||
<artifactId>javax.annotation-api</artifactId>
|
||||
<version>${javax-annotation-api-version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>javax.validation</groupId>
|
||||
<artifactId>validation-api</artifactId>
|
||||
<version>2.0.1.Final</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>javax.xml.bind</groupId>
|
||||
<artifactId>jaxb-api</artifactId>
|
||||
<version>${jaxb-version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.google.code.findbugs</groupId>
|
||||
<artifactId>jsr305</artifactId>
|
||||
<version>3.0.2</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.openapitools</groupId>
|
||||
<artifactId>jackson-databind-nullable</artifactId>
|
||||
<version>0.2.1</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.bouncycastle</groupId>
|
||||
<artifactId>bcprov-jdk15on</artifactId>
|
||||
<version>1.69</version>
|
||||
</dependency>
|
||||
|
||||
<!--test-->
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-test</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>io.jsonwebtoken</groupId>
|
||||
<artifactId>jjwt</artifactId>
|
||||
<version>0.9.1</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.cloud</groupId>
|
||||
<artifactId>spring-cloud-contract-wiremock</artifactId>
|
||||
<version>3.0.3</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
<sourceDirectory>${project.basedir}/src/main/java</sourceDirectory>
|
||||
<testSourceDirectory>${project.basedir}/src/test/java</testSourceDirectory>
|
||||
<resources>
|
||||
<resource>
|
||||
<directory>${project.build.directory}/maven-shared-archive-resources</directory>
|
||||
<targetPath>${project.build.directory}</targetPath>
|
||||
<includes>
|
||||
<include>Dockerfile</include>
|
||||
</includes>
|
||||
<filtering>true</filtering>
|
||||
</resource>
|
||||
<resource>
|
||||
<directory>${project.build.directory}/maven-shared-archive-resources</directory>
|
||||
<filtering>true</filtering>
|
||||
<excludes>
|
||||
<exclude>Dockerfile</exclude>
|
||||
</excludes>
|
||||
</resource>
|
||||
<resource>
|
||||
<directory>src/main/resources</directory>
|
||||
<filtering>true</filtering>
|
||||
</resource>
|
||||
</resources>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-maven-plugin</artifactId>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-remote-resources-plugin</artifactId>
|
||||
<version>1.6.0</version>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.apache.maven.shared</groupId>
|
||||
<artifactId>maven-filtering</artifactId>
|
||||
<version>1.3</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
<configuration>
|
||||
<resourceBundles>
|
||||
<resourceBundle>com.rbkmoney:shared-resources:${shared-resources.version}</resourceBundle>
|
||||
</resourceBundles>
|
||||
<attachToMain>false</attachToMain>
|
||||
<attachToTest>false</attachToTest>
|
||||
</configuration>
|
||||
<executions>
|
||||
<execution>
|
||||
<goals>
|
||||
<goal>process</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
</project>
|
15
src/main/java/com/rbkmoney/anapi/v2/AnapiV2Application.java
Normal file
15
src/main/java/com/rbkmoney/anapi/v2/AnapiV2Application.java
Normal file
@ -0,0 +1,15 @@
|
||||
package com.rbkmoney.anapi.v2;
|
||||
|
||||
import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
import org.springframework.boot.web.servlet.ServletComponentScan;
|
||||
|
||||
@ServletComponentScan
|
||||
@SpringBootApplication
|
||||
public class AnapiV2Application extends SpringApplication {
|
||||
|
||||
public static void main(String[] args) {
|
||||
SpringApplication.run(AnapiV2Application.class, args);
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,70 @@
|
||||
package com.rbkmoney.anapi.v2.config;
|
||||
|
||||
import com.rbkmoney.bouncer.decisions.ArbiterSrv;
|
||||
import com.rbkmoney.damsel.vortigon.VortigonServiceSrv;
|
||||
import com.rbkmoney.magista.MerchantStatisticsServiceSrv;
|
||||
import com.rbkmoney.orgmanagement.AuthContextProviderSrv;
|
||||
import com.rbkmoney.woody.api.trace.context.metadata.user.UserIdentityEmailExtensionKit;
|
||||
import com.rbkmoney.woody.api.trace.context.metadata.user.UserIdentityIdExtensionKit;
|
||||
import com.rbkmoney.woody.api.trace.context.metadata.user.UserIdentityRealmExtensionKit;
|
||||
import com.rbkmoney.woody.api.trace.context.metadata.user.UserIdentityUsernameExtensionKit;
|
||||
import com.rbkmoney.woody.thrift.impl.http.THSpawnClientBuilder;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.core.io.Resource;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
|
||||
@Configuration
|
||||
public class ApplicationConfig {
|
||||
|
||||
@Bean
|
||||
public MerchantStatisticsServiceSrv.Iface magistaClient(
|
||||
@Value("${service.magista.url}") Resource resource,
|
||||
@Value("${service.magista.networkTimeout}") int networkTimeout
|
||||
) throws IOException {
|
||||
return new THSpawnClientBuilder()
|
||||
.withNetworkTimeout(networkTimeout)
|
||||
.withAddress(resource.getURI()).build(MerchantStatisticsServiceSrv.Iface.class);
|
||||
}
|
||||
|
||||
@Bean
|
||||
public VortigonServiceSrv.Iface vortigonClient(
|
||||
@Value("${service.vortigon.url}") Resource resource,
|
||||
@Value("${service.vortigon.networkTimeout}") int networkTimeout
|
||||
) throws IOException {
|
||||
return new THSpawnClientBuilder()
|
||||
.withNetworkTimeout(networkTimeout)
|
||||
.withAddress(resource.getURI()).build(VortigonServiceSrv.Iface.class);
|
||||
}
|
||||
|
||||
@Bean
|
||||
public AuthContextProviderSrv.Iface orgManagerClient(
|
||||
@Value("${service.orgManagement.url}") Resource resource,
|
||||
@Value("${service.orgManagement.networkTimeout}") int networkTimeout
|
||||
) throws IOException {
|
||||
return new THSpawnClientBuilder()
|
||||
.withNetworkTimeout(networkTimeout)
|
||||
.withMetaExtensions(
|
||||
List.of(
|
||||
UserIdentityIdExtensionKit.INSTANCE,
|
||||
UserIdentityEmailExtensionKit.INSTANCE,
|
||||
UserIdentityUsernameExtensionKit.INSTANCE,
|
||||
UserIdentityRealmExtensionKit.INSTANCE
|
||||
)
|
||||
)
|
||||
.withAddress(resource.getURI()).build(AuthContextProviderSrv.Iface.class);
|
||||
}
|
||||
|
||||
@Bean
|
||||
public ArbiterSrv.Iface bouncerClient(
|
||||
@Value("${service.bouncer.url}") Resource resource,
|
||||
@Value("${service.bouncer.networkTimeout}") int networkTimeout
|
||||
) throws IOException {
|
||||
return new THSpawnClientBuilder()
|
||||
.withNetworkTimeout(networkTimeout)
|
||||
.withAddress(resource.getURI()).build(ArbiterSrv.Iface.class);
|
||||
}
|
||||
}
|
135
src/main/java/com/rbkmoney/anapi/v2/config/SecurityConfig.java
Normal file
135
src/main/java/com/rbkmoney/anapi/v2/config/SecurityConfig.java
Normal file
@ -0,0 +1,135 @@
|
||||
package com.rbkmoney.anapi.v2.config;
|
||||
|
||||
import org.keycloak.adapters.KeycloakConfigResolver;
|
||||
import org.keycloak.adapters.KeycloakDeployment;
|
||||
import org.keycloak.adapters.KeycloakDeploymentBuilder;
|
||||
import org.keycloak.adapters.springsecurity.KeycloakSecurityComponents;
|
||||
import org.keycloak.adapters.springsecurity.config.KeycloakWebSecurityConfigurerAdapter;
|
||||
import org.keycloak.representations.adapters.config.AdapterConfig;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.ComponentScan;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.annotation.FilterType;
|
||||
import org.springframework.http.HttpMethod;
|
||||
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
|
||||
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
|
||||
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
|
||||
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
|
||||
import org.springframework.security.web.authentication.session.NullAuthenticatedSessionStrategy;
|
||||
import org.springframework.security.web.authentication.session.SessionAuthenticationStrategy;
|
||||
import org.springframework.util.StringUtils;
|
||||
import org.springframework.web.cors.CorsConfiguration;
|
||||
import org.springframework.web.cors.CorsConfigurationSource;
|
||||
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Paths;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@Configuration
|
||||
@EnableWebSecurity
|
||||
@ComponentScan(
|
||||
basePackageClasses = KeycloakSecurityComponents.class,
|
||||
excludeFilters = @ComponentScan.Filter(
|
||||
type = FilterType.REGEX,
|
||||
pattern = "org.keycloak.adapters.springsecurity.management.HttpSessionManager"))
|
||||
@EnableGlobalMethodSecurity(prePostEnabled = true, proxyTargetClass = true)
|
||||
@ConditionalOnProperty(value = "auth.enabled", havingValue = "true")
|
||||
public class SecurityConfig extends KeycloakWebSecurityConfigurerAdapter {
|
||||
|
||||
@Value("${keycloak.realm}")
|
||||
private String keycloakRealmName;
|
||||
|
||||
@Value("${keycloak.resource}")
|
||||
private String keycloakResourceName;
|
||||
|
||||
@Value("${keycloak.realm-public-key}")
|
||||
private String keycloakRealmPublicKey;
|
||||
|
||||
@Value("${keycloak.realm-public-key.file-path:}")
|
||||
private String keycloakRealmPublicKeyFile;
|
||||
|
||||
@Value("${keycloak.auth-server-url}")
|
||||
private String keycloakAuthServerUrl;
|
||||
|
||||
@Value("${keycloak.ssl-required}")
|
||||
private String keycloakSSLRequired;
|
||||
|
||||
@Value("${keycloak.not-before}")
|
||||
private int keycloakTokenNotBefore;
|
||||
|
||||
@Bean
|
||||
@Override
|
||||
protected SessionAuthenticationStrategy sessionAuthenticationStrategy() {
|
||||
return new NullAuthenticatedSessionStrategy();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void configure(HttpSecurity http) throws Exception {
|
||||
super.configure(http);
|
||||
http
|
||||
.cors().and()
|
||||
.csrf().disable()
|
||||
.authorizeRequests()
|
||||
.antMatchers(HttpMethod.OPTIONS, "/**").permitAll()
|
||||
.antMatchers(HttpMethod.GET, "/**/health").permitAll()
|
||||
.anyRequest().authenticated();
|
||||
}
|
||||
|
||||
@Autowired
|
||||
public void configureGlobal(AuthenticationManagerBuilder auth) {
|
||||
auth.authenticationProvider(keycloakAuthenticationProvider());
|
||||
}
|
||||
|
||||
@Bean
|
||||
public KeycloakConfigResolver keycloakConfigResolver() {
|
||||
return facade -> {
|
||||
KeycloakDeployment deployment = KeycloakDeploymentBuilder.build(adapterConfig());
|
||||
deployment.setNotBefore(keycloakTokenNotBefore);
|
||||
return deployment;
|
||||
};
|
||||
}
|
||||
|
||||
@Bean
|
||||
public CorsConfigurationSource corsConfigurationSource() {
|
||||
CorsConfiguration configuration = new CorsConfiguration();
|
||||
configuration.applyPermitDefaultValues();
|
||||
configuration.addAllowedMethod(HttpMethod.PUT);
|
||||
configuration.addAllowedMethod(HttpMethod.DELETE);
|
||||
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
|
||||
source.registerCorsConfiguration("/**", configuration);
|
||||
return source;
|
||||
}
|
||||
|
||||
private AdapterConfig adapterConfig() {
|
||||
if (StringUtils.hasLength(keycloakRealmPublicKeyFile)) {
|
||||
keycloakRealmPublicKey = readKeyFromFile(keycloakRealmPublicKeyFile);
|
||||
}
|
||||
|
||||
AdapterConfig adapterConfig = new AdapterConfig();
|
||||
adapterConfig.setRealm(keycloakRealmName);
|
||||
adapterConfig.setRealmKey(keycloakRealmPublicKey);
|
||||
adapterConfig.setResource(keycloakResourceName);
|
||||
adapterConfig.setAuthServerUrl(keycloakAuthServerUrl);
|
||||
adapterConfig.setUseResourceRoleMappings(true);
|
||||
adapterConfig.setBearerOnly(true);
|
||||
adapterConfig.setSslRequired(keycloakSSLRequired);
|
||||
return adapterConfig;
|
||||
}
|
||||
|
||||
private String readKeyFromFile(String filePath) {
|
||||
try {
|
||||
List<String> strings = Files.readAllLines(Paths.get(filePath));
|
||||
strings.remove(strings.size() - 1);
|
||||
strings.remove(0);
|
||||
return strings.stream().map(String::trim).collect(Collectors.joining());
|
||||
} catch (IOException ex) {
|
||||
throw new RuntimeException(ex);
|
||||
}
|
||||
}
|
||||
}
|
105
src/main/java/com/rbkmoney/anapi/v2/config/WebConfig.java
Normal file
105
src/main/java/com/rbkmoney/anapi/v2/config/WebConfig.java
Normal file
@ -0,0 +1,105 @@
|
||||
package com.rbkmoney.anapi.v2.config;
|
||||
|
||||
import com.rbkmoney.woody.api.flow.WFlow;
|
||||
import com.rbkmoney.woody.api.trace.context.metadata.user.UserIdentityEmailExtensionKit;
|
||||
import com.rbkmoney.woody.api.trace.context.metadata.user.UserIdentityIdExtensionKit;
|
||||
import com.rbkmoney.woody.api.trace.context.metadata.user.UserIdentityRealmExtensionKit;
|
||||
import com.rbkmoney.woody.api.trace.context.metadata.user.UserIdentityUsernameExtensionKit;
|
||||
import org.keycloak.KeycloakSecurityContext;
|
||||
import org.keycloak.adapters.springsecurity.token.KeycloakAuthenticationToken;
|
||||
import org.keycloak.representations.AccessToken;
|
||||
import org.springframework.boot.web.servlet.FilterRegistrationBean;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.web.filter.OncePerRequestFilter;
|
||||
|
||||
import javax.servlet.Filter;
|
||||
import javax.servlet.FilterChain;
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.io.IOException;
|
||||
import java.security.Principal;
|
||||
import java.time.Instant;
|
||||
import java.time.temporal.ChronoUnit;
|
||||
|
||||
import static com.rbkmoney.anapi.v2.util.DeadlineUtil.*;
|
||||
import static com.rbkmoney.woody.api.trace.ContextUtils.setCustomMetadataValue;
|
||||
import static com.rbkmoney.woody.api.trace.ContextUtils.setDeadline;
|
||||
|
||||
@Configuration
|
||||
@SuppressWarnings({"ParameterName", "LocalVariableName"})
|
||||
public class WebConfig {
|
||||
|
||||
@Bean
|
||||
public FilterRegistrationBean woodyFilter() {
|
||||
WFlow woodyFlow = new WFlow();
|
||||
Filter filter = new OncePerRequestFilter() {
|
||||
|
||||
@Override
|
||||
protected void doFilterInternal(HttpServletRequest request,
|
||||
HttpServletResponse response,
|
||||
FilterChain filterChain) throws ServletException, IOException {
|
||||
woodyFlow.createServiceFork(
|
||||
() -> {
|
||||
try {
|
||||
if (request.getUserPrincipal() != null) {
|
||||
addWoodyContext(request.getUserPrincipal());
|
||||
}
|
||||
|
||||
setWoodyDeadline(request);
|
||||
|
||||
filterChain.doFilter(request, response);
|
||||
} catch (IOException | ServletException e) {
|
||||
sneakyThrow(e);
|
||||
}
|
||||
}
|
||||
)
|
||||
.run();
|
||||
}
|
||||
|
||||
private <E extends Throwable, T> T sneakyThrow(Throwable t) throws E {
|
||||
throw (E) t;
|
||||
}
|
||||
};
|
||||
|
||||
FilterRegistrationBean filterRegistrationBean = new FilterRegistrationBean();
|
||||
filterRegistrationBean.setFilter(filter);
|
||||
filterRegistrationBean.setOrder(-50);
|
||||
filterRegistrationBean.setName("woodyFilter");
|
||||
filterRegistrationBean.addUrlPatterns("*");
|
||||
return filterRegistrationBean;
|
||||
}
|
||||
|
||||
private void addWoodyContext(Principal principal) {
|
||||
KeycloakSecurityContext keycloakSecurityContext =
|
||||
((KeycloakAuthenticationToken) principal).getAccount().getKeycloakSecurityContext();
|
||||
AccessToken accessToken = keycloakSecurityContext.getToken();
|
||||
|
||||
setCustomMetadataValue(UserIdentityIdExtensionKit.KEY, accessToken.getSubject());
|
||||
setCustomMetadataValue(UserIdentityUsernameExtensionKit.KEY, accessToken.getPreferredUsername());
|
||||
setCustomMetadataValue(UserIdentityEmailExtensionKit.KEY, accessToken.getEmail());
|
||||
setCustomMetadataValue(UserIdentityRealmExtensionKit.KEY, keycloakSecurityContext.getRealm());
|
||||
}
|
||||
|
||||
private void setWoodyDeadline(HttpServletRequest request) {
|
||||
String xRequestDeadline = request.getHeader("X-Request-Deadline");
|
||||
String xRequestId = request.getHeader("X-Request-ID");
|
||||
if (xRequestDeadline != null) {
|
||||
setDeadline(getInstant(xRequestDeadline, xRequestId));
|
||||
}
|
||||
}
|
||||
|
||||
private Instant getInstant(String xRequestDeadline, String xRequestId) {
|
||||
Instant instant;
|
||||
if (containsRelativeValues(xRequestDeadline, xRequestId)) {
|
||||
instant = Instant.now()
|
||||
.plus(extractMilliseconds(xRequestDeadline, xRequestId), ChronoUnit.MILLIS)
|
||||
.plus(extractSeconds(xRequestDeadline, xRequestId), ChronoUnit.MILLIS)
|
||||
.plus(extractMinutes(xRequestDeadline, xRequestId), ChronoUnit.MILLIS);
|
||||
} else {
|
||||
instant = Instant.parse(xRequestDeadline);
|
||||
}
|
||||
return instant;
|
||||
}
|
||||
}
|
@ -0,0 +1,28 @@
|
||||
package com.rbkmoney.anapi.v2.config.properties;
|
||||
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
|
||||
import javax.validation.constraints.NotEmpty;
|
||||
|
||||
@Getter
|
||||
@Setter
|
||||
@Component
|
||||
@Validated
|
||||
@ConfigurationProperties(prefix = "service.bouncer")
|
||||
public class BouncerProperties {
|
||||
|
||||
@NotEmpty
|
||||
private String contextFragmentId;
|
||||
@NotEmpty
|
||||
private String deploymentId;
|
||||
@NotEmpty
|
||||
private String authMethod;
|
||||
@NotEmpty
|
||||
private String realm;
|
||||
@NotEmpty
|
||||
private String ruleSetId;
|
||||
}
|
@ -0,0 +1,86 @@
|
||||
package com.rbkmoney.anapi.v2.controller;
|
||||
|
||||
import com.rbkmoney.anapi.v2.exception.AuthorizationException;
|
||||
import com.rbkmoney.anapi.v2.exception.BadRequestException;
|
||||
import com.rbkmoney.anapi.v2.exception.DeadlineException;
|
||||
import com.rbkmoney.openapi.anapi_v2.model.DefaultLogicError;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.security.access.AccessDeniedException;
|
||||
import org.springframework.web.bind.MissingServletRequestParameterException;
|
||||
import org.springframework.web.bind.annotation.ExceptionHandler;
|
||||
import org.springframework.web.bind.annotation.ResponseStatus;
|
||||
import org.springframework.web.bind.annotation.RestControllerAdvice;
|
||||
|
||||
import javax.validation.ConstraintViolation;
|
||||
import javax.validation.ConstraintViolationException;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@Slf4j
|
||||
@RestControllerAdvice
|
||||
@RequiredArgsConstructor
|
||||
public class ErrorControllerAdvice {
|
||||
|
||||
@ExceptionHandler({ConstraintViolationException.class})
|
||||
@ResponseStatus(HttpStatus.BAD_REQUEST)
|
||||
public Object handleConstraintViolationException(ConstraintViolationException e) {
|
||||
log.warn("<- Res [400]: Not valid", e);
|
||||
Set<ConstraintViolation<?>> constraintViolations =
|
||||
e.getConstraintViolations();
|
||||
String errorMessage =
|
||||
constraintViolations.stream()
|
||||
.map(violation -> violation.getPropertyPath() + ": " + violation.getMessage())
|
||||
.collect(Collectors.joining(", "));
|
||||
return new DefaultLogicError()
|
||||
.code(DefaultLogicError.CodeEnum.INVALIDREQUEST)
|
||||
.message(errorMessage);
|
||||
}
|
||||
|
||||
@ExceptionHandler({BadRequestException.class})
|
||||
@ResponseStatus(HttpStatus.BAD_REQUEST)
|
||||
public Object handleBadRequestException(BadRequestException e) {
|
||||
log.warn("<- Res [400]: Not valid", e);
|
||||
return new DefaultLogicError()
|
||||
.code(DefaultLogicError.CodeEnum.INVALIDREQUEST)
|
||||
.message(e.getMessage());
|
||||
}
|
||||
|
||||
@ExceptionHandler({MissingServletRequestParameterException.class})
|
||||
@ResponseStatus(HttpStatus.BAD_REQUEST)
|
||||
public Object handleMissingServletRequestParameterException(MissingServletRequestParameterException e) {
|
||||
log.warn("<- Res [400]: Missing ServletRequestParameter", e);
|
||||
return new DefaultLogicError()
|
||||
.code(DefaultLogicError.CodeEnum.INVALIDREQUEST)
|
||||
.message(e.getMessage());
|
||||
}
|
||||
|
||||
@ExceptionHandler({DeadlineException.class})
|
||||
@ResponseStatus(HttpStatus.BAD_REQUEST)
|
||||
public Object handleDeadlineException(DeadlineException e) {
|
||||
log.warn("<- Res [400]: Not valid", e);
|
||||
return new DefaultLogicError()
|
||||
.code(DefaultLogicError.CodeEnum.INVALIDDEADLINE)
|
||||
.message(e.getMessage());
|
||||
}
|
||||
|
||||
@ExceptionHandler({AccessDeniedException.class})
|
||||
@ResponseStatus(HttpStatus.FORBIDDEN)
|
||||
public void handleAccessDeniedException(AccessDeniedException e) {
|
||||
log.warn("<- Res [403]: Request denied access", e);
|
||||
}
|
||||
|
||||
@ExceptionHandler({AuthorizationException.class})
|
||||
@ResponseStatus(HttpStatus.FORBIDDEN)
|
||||
public void handleAccessDeniedException(AuthorizationException e) {
|
||||
log.warn("<- Res [403]: Request denied access", e);
|
||||
}
|
||||
|
||||
@ExceptionHandler(Exception.class)
|
||||
@ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
|
||||
public void handleException(Exception e) {
|
||||
log.error("<- Res [500]: Unrecognized inner error", e);
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,269 @@
|
||||
package com.rbkmoney.anapi.v2.controller;
|
||||
|
||||
import com.rbkmoney.anapi.v2.converter.search.request.*;
|
||||
import com.rbkmoney.anapi.v2.security.AccessService;
|
||||
import com.rbkmoney.anapi.v2.service.SearchService;
|
||||
import com.rbkmoney.magista.*;
|
||||
import com.rbkmoney.openapi.anapi_v2.api.*;
|
||||
import com.rbkmoney.openapi.anapi_v2.model.*;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.web.context.request.NativeWebRequest;
|
||||
|
||||
import javax.validation.Valid;
|
||||
import javax.validation.constraints.*;
|
||||
import java.time.OffsetDateTime;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
import static com.rbkmoney.anapi.v2.util.ConverterUtil.merge;
|
||||
import static com.rbkmoney.anapi.v2.util.DeadlineUtil.checkDeadline;
|
||||
|
||||
|
||||
@Slf4j
|
||||
@PreAuthorize("hasAuthority('invoices:read')")
|
||||
@Controller
|
||||
@RequiredArgsConstructor
|
||||
@SuppressWarnings("ParameterName")
|
||||
public class SearchController implements PaymentsApi, ChargebacksApi, InvoicesApi, PayoutsApi, RefundsApi {
|
||||
|
||||
private final SearchService searchService;
|
||||
private final AccessService accessService;
|
||||
private final ParamsToPaymentSearchQueryConverter paymentSearchConverter;
|
||||
private final ParamsToChargebackSearchQueryConverter chargebackSearchConverter;
|
||||
private final ParamsToInvoiceSearchQueryConverter invoiceSearchConverter;
|
||||
private final ParamsToPayoutSearchQueryConverter payoutSearchConverter;
|
||||
private final ParamsToRefundSearchQueryConverter refundSearchConverter;
|
||||
|
||||
@Override
|
||||
public Optional<NativeWebRequest> getRequest() {
|
||||
return PaymentsApi.super.getRequest();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ResponseEntity<InlineResponse20010> searchPayments(String xRequestID,
|
||||
@NotNull @Size(min = 1, max = 40) @Valid String partyID,
|
||||
@NotNull @Valid OffsetDateTime fromTime,
|
||||
@NotNull @Valid OffsetDateTime toTime,
|
||||
@NotNull @Min(1L) @Max(1000L) @Valid Integer limit,
|
||||
String xRequestDeadline,
|
||||
@Size(min = 1, max = 40) @Valid String shopID,
|
||||
@Valid List<String> shopIDs,
|
||||
@Valid String paymentInstitutionRealm,
|
||||
@Valid List<String> invoiceIDs,
|
||||
@Valid String paymentStatus, @Valid String paymentFlow,
|
||||
@Valid String paymentMethod,
|
||||
@Valid String paymentTerminalProvider,
|
||||
@Size(min = 1, max = 40) @Valid String invoiceID,
|
||||
@Size(min = 1, max = 40) @Valid String paymentID,
|
||||
@Size(min = 1, max = 40) @Valid String externalID,
|
||||
@Size(max = 100) @Email @Valid String payerEmail,
|
||||
@Size(max = 45) @Valid String payerIP,
|
||||
@Size(max = 1000) @Valid String payerFingerprint,
|
||||
@Size(min = 1, max = 40) @Valid String customerID,
|
||||
@Pattern(regexp = "^\\d{6}$") @Valid String first6,
|
||||
@Pattern(regexp = "^\\d{4}$") @Valid String last4,
|
||||
@Pattern(regexp = "^[a-zA-Z0-9]{12}$") @Valid String rrn,
|
||||
@Size(min = 1, max = 40) @Valid String approvalCode,
|
||||
@Valid String bankCardTokenProvider,
|
||||
@Valid String bankCardPaymentSystem,
|
||||
@Min(1L) @Valid Long paymentAmountFrom,
|
||||
@Min(1L) @Valid Long paymentAmountTo,
|
||||
@Valid List<String> excludedShops,
|
||||
@Valid String continuationToken) {
|
||||
log.info("-> Req: xRequestID={}", xRequestID);
|
||||
checkDeadline(xRequestDeadline, xRequestID);
|
||||
shopIDs = accessService
|
||||
.getAccessibleShops("searchPayments", partyID, merge(shopID, shopIDs), paymentInstitutionRealm);
|
||||
|
||||
PaymentSearchQuery query = paymentSearchConverter.convert(partyID,
|
||||
fromTime,
|
||||
toTime,
|
||||
limit,
|
||||
shopIDs,
|
||||
invoiceIDs,
|
||||
paymentStatus, paymentFlow,
|
||||
paymentMethod,
|
||||
paymentTerminalProvider,
|
||||
invoiceID,
|
||||
paymentID,
|
||||
externalID,
|
||||
payerEmail,
|
||||
payerIP,
|
||||
payerFingerprint,
|
||||
customerID,
|
||||
first6,
|
||||
last4,
|
||||
rrn,
|
||||
approvalCode,
|
||||
bankCardTokenProvider,
|
||||
bankCardPaymentSystem,
|
||||
paymentAmountFrom,
|
||||
paymentAmountTo,
|
||||
excludedShops,
|
||||
continuationToken);
|
||||
InlineResponse20010 response = searchService.findPayments(query);
|
||||
log.info("<- Res [200]: xRequestID={}", xRequestID);
|
||||
return ResponseEntity.ok(response);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ResponseEntity<InlineResponse2008> searchChargebacks(String xRequestID,
|
||||
@NotNull @Size(min = 1, max = 40) @Valid String partyID,
|
||||
@NotNull @Valid OffsetDateTime fromTime,
|
||||
@NotNull @Valid OffsetDateTime toTime,
|
||||
@NotNull @Min(1L) @Max(1000L) @Valid Integer limit,
|
||||
String xRequestDeadline,
|
||||
@Size(min = 1, max = 40) @Valid String shopID,
|
||||
@Valid List<String> shopIDs,
|
||||
@Valid String paymentInstitutionRealm,
|
||||
//Not used by magista
|
||||
@Min(0L) @Valid @Deprecated Integer offset,
|
||||
@Size(min = 1, max = 40) @Valid String invoiceID,
|
||||
@Size(min = 1, max = 40) @Valid String paymentID,
|
||||
@Size(min = 1, max = 40) @Valid String chargebackID,
|
||||
@Valid List<String> chargebackStatuses,
|
||||
@Valid List<String> chargebackStages,
|
||||
@Valid List<String> chargebackCategories,
|
||||
@Valid String continuationToken) {
|
||||
log.info("-> Req: xRequestID={}", xRequestID);
|
||||
checkDeadline(xRequestDeadline, xRequestID);
|
||||
shopIDs = accessService
|
||||
.getAccessibleShops("searchChargebacks", partyID, merge(shopID, shopIDs), paymentInstitutionRealm);
|
||||
ChargebackSearchQuery query = chargebackSearchConverter.convert(partyID,
|
||||
fromTime,
|
||||
toTime,
|
||||
limit,
|
||||
shopIDs,
|
||||
invoiceID,
|
||||
paymentID,
|
||||
chargebackID,
|
||||
chargebackStatuses,
|
||||
chargebackStages,
|
||||
chargebackCategories,
|
||||
continuationToken);
|
||||
InlineResponse2008 response = searchService
|
||||
.findChargebacks(query);
|
||||
log.info("<- Res [200]: xRequestID={}", xRequestID);
|
||||
return ResponseEntity.ok(response);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ResponseEntity<InlineResponse2009> searchInvoices(String xRequestID,
|
||||
@NotNull @Size(min = 1, max = 40) @Valid String partyID,
|
||||
@NotNull @Valid OffsetDateTime fromTime,
|
||||
@NotNull @Valid OffsetDateTime toTime,
|
||||
@NotNull @Min(1L) @Max(1000L) @Valid Integer limit,
|
||||
String xRequestDeadline,
|
||||
@Size(min = 1, max = 40) @Valid String shopID,
|
||||
@Valid List<String> shopIDs,
|
||||
@Valid String paymentInstitutionRealm,
|
||||
@Valid List<String> invoiceIDs,
|
||||
@Valid String invoiceStatus,
|
||||
@Size(min = 1, max = 40) @Valid String invoiceID,
|
||||
@Size(min = 1, max = 40) @Valid String externalID,
|
||||
@Min(1L) @Valid Long invoiceAmountFrom,
|
||||
@Min(1L) @Valid Long invoiceAmountTo,
|
||||
//Not used by magista
|
||||
@Valid @Deprecated List<String> excludedShops,
|
||||
@Valid String continuationToken) {
|
||||
log.info("-> Req: xRequestID={}", xRequestID);
|
||||
checkDeadline(xRequestDeadline, xRequestID);
|
||||
shopIDs = accessService
|
||||
.getAccessibleShops("searchInvoices", partyID, merge(shopID, shopIDs), paymentInstitutionRealm);
|
||||
InvoiceSearchQuery query = invoiceSearchConverter.convert(partyID,
|
||||
fromTime,
|
||||
toTime,
|
||||
limit,
|
||||
shopIDs,
|
||||
invoiceIDs,
|
||||
invoiceStatus,
|
||||
invoiceID,
|
||||
externalID,
|
||||
invoiceAmountFrom,
|
||||
invoiceAmountTo,
|
||||
continuationToken);
|
||||
InlineResponse2009 response = searchService.findInvoices(query);
|
||||
log.info("<- Res [200]: xRequestID={}", xRequestID);
|
||||
return ResponseEntity.ok(response);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ResponseEntity<InlineResponse20011> searchPayouts(String xRequestID,
|
||||
@NotNull @Size(min = 1, max = 40) @Valid String partyID,
|
||||
@NotNull @Valid OffsetDateTime fromTime,
|
||||
@NotNull @Valid OffsetDateTime toTime,
|
||||
@NotNull @Min(1L) @Max(1000L) @Valid Integer limit,
|
||||
String xRequestDeadline,
|
||||
@Size(min = 1, max = 40) @Valid String shopID,
|
||||
@Valid List<String> shopIDs,
|
||||
@Valid String paymentInstitutionRealm,
|
||||
//Not used by magista
|
||||
@Min(0L) @Valid @Deprecated Integer offset,
|
||||
@Size(min = 1, max = 40) @Valid String payoutID,
|
||||
@Valid String payoutToolType,
|
||||
//Not used by magista
|
||||
@Valid @Deprecated List<String> excludedShops,
|
||||
@Valid String continuationToken) {
|
||||
log.info("-> Req: xRequestID={}", xRequestID);
|
||||
checkDeadline(xRequestDeadline, xRequestID);
|
||||
shopIDs = accessService
|
||||
.getAccessibleShops("searchPayouts", partyID, merge(shopID, shopIDs), paymentInstitutionRealm);
|
||||
PayoutSearchQuery query = payoutSearchConverter.convert(partyID,
|
||||
fromTime,
|
||||
toTime,
|
||||
limit,
|
||||
shopIDs,
|
||||
payoutID,
|
||||
payoutToolType,
|
||||
continuationToken);
|
||||
InlineResponse20011 response = searchService.findPayouts(query);
|
||||
log.info("<- Res [200]: xRequestID={}", xRequestID);
|
||||
return ResponseEntity.ok(response);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ResponseEntity<InlineResponse20012> searchRefunds(String xRequestID,
|
||||
@NotNull @Size(min = 1, max = 40) @Valid String partyID,
|
||||
@NotNull @Valid OffsetDateTime fromTime,
|
||||
@NotNull @Valid OffsetDateTime toTime,
|
||||
@NotNull @Min(1L) @Max(1000L) @Valid Integer limit,
|
||||
String xRequestDeadline,
|
||||
@Size(min = 1, max = 40) @Valid String shopID,
|
||||
@Valid List<String> shopIDs,
|
||||
@Valid String paymentInstitutionRealm,
|
||||
//Not used by magista
|
||||
@Min(0L) @Valid @Deprecated Integer offset,
|
||||
@Valid List<String> invoiceIDs,
|
||||
@Size(min = 1, max = 40) @Valid String invoiceID,
|
||||
@Size(min = 1, max = 40) @Valid String paymentID,
|
||||
@Size(min = 1, max = 40) @Valid String refundID,
|
||||
@Size(min = 1, max = 40) @Valid String externalID,
|
||||
@Valid String refundStatus,
|
||||
//Not used by magista
|
||||
@Valid @Deprecated List<String> excludedShops,
|
||||
@Valid String continuationToken) {
|
||||
log.info("-> Req: xRequestID={}", xRequestID);
|
||||
checkDeadline(xRequestDeadline, xRequestID);
|
||||
shopIDs = accessService
|
||||
.getAccessibleShops("searchRefunds", partyID, merge(shopID, shopIDs), paymentInstitutionRealm);
|
||||
RefundSearchQuery query = refundSearchConverter.convert(partyID,
|
||||
fromTime,
|
||||
toTime,
|
||||
limit,
|
||||
shopIDs,
|
||||
invoiceIDs,
|
||||
invoiceID,
|
||||
paymentID,
|
||||
refundID,
|
||||
externalID,
|
||||
refundStatus,
|
||||
continuationToken);
|
||||
InlineResponse20012 response = searchService.findRefunds(query);
|
||||
log.info("<- Res [200]: xRequestID={}", xRequestID);
|
||||
return ResponseEntity.ok(response);
|
||||
}
|
||||
}
|
@ -0,0 +1,118 @@
|
||||
package com.rbkmoney.anapi.v2.converter.search.request;
|
||||
|
||||
import com.rbkmoney.anapi.v2.exception.BadRequestException;
|
||||
import com.rbkmoney.damsel.domain.*;
|
||||
import com.rbkmoney.magista.ChargebackSearchQuery;
|
||||
import com.rbkmoney.openapi.anapi_v2.model.ChargebackCategory;
|
||||
import com.rbkmoney.openapi.anapi_v2.model.ChargebackStage;
|
||||
import com.rbkmoney.openapi.anapi_v2.model.ChargebackStatus;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.time.OffsetDateTime;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import static com.rbkmoney.anapi.v2.util.ConverterUtil.fillCommonParams;
|
||||
|
||||
@Component
|
||||
public class ParamsToChargebackSearchQueryConverter {
|
||||
|
||||
public ChargebackSearchQuery convert(String partyID,
|
||||
OffsetDateTime fromTime,
|
||||
OffsetDateTime toTime,
|
||||
Integer limit,
|
||||
List<String> shopIDs,
|
||||
String invoiceID,
|
||||
String paymentID,
|
||||
String chargebackID,
|
||||
List<String> chargebackStatuses,
|
||||
List<String> chargebackStages,
|
||||
List<String> chargebackCategories,
|
||||
String continuationToken) {
|
||||
return new ChargebackSearchQuery()
|
||||
.setCommonSearchQueryParams(
|
||||
fillCommonParams(fromTime, toTime, limit, partyID, shopIDs, continuationToken))
|
||||
.setInvoiceIds(invoiceID != null ? List.of(invoiceID) : null)
|
||||
.setPaymentId(paymentID)
|
||||
.setChargebackId(chargebackID)
|
||||
.setChargebackStatuses(chargebackStatuses != null
|
||||
? chargebackStatuses.stream()
|
||||
.map(this::mapStatus)
|
||||
.collect(Collectors.toList())
|
||||
: null
|
||||
)
|
||||
.setChargebackStages(chargebackStages != null
|
||||
? chargebackStages.stream()
|
||||
.map(this::mapStage)
|
||||
.collect(Collectors.toList())
|
||||
: null
|
||||
)
|
||||
.setChargebackCategories(chargebackCategories != null
|
||||
? chargebackCategories.stream()
|
||||
.map(this::mapCategory)
|
||||
.collect(Collectors.toList())
|
||||
: null);
|
||||
}
|
||||
|
||||
protected InvoicePaymentChargebackStage mapStage(String chargebackStage) {
|
||||
try {
|
||||
var stage = ChargebackStage.fromValue(chargebackStage);
|
||||
var damselStage = new InvoicePaymentChargebackStage();
|
||||
switch (stage) {
|
||||
case CHARGEBACK -> damselStage.setChargeback(new InvoicePaymentChargebackStageChargeback());
|
||||
case PRE_ARBITRATION -> damselStage.setPreArbitration(
|
||||
new InvoicePaymentChargebackStagePreArbitration());
|
||||
case ARBITRATION -> damselStage.setArbitration(new InvoicePaymentChargebackStageArbitration());
|
||||
default -> throw new BadRequestException(
|
||||
String.format("Chargeback stage %s cannot be processed", chargebackStage));
|
||||
}
|
||||
|
||||
return damselStage;
|
||||
|
||||
} catch (Exception e) {
|
||||
throw new BadRequestException(e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
protected InvoicePaymentChargebackStatus mapStatus(String chargebackStatus) {
|
||||
try {
|
||||
var status = ChargebackStatus.fromValue(chargebackStatus);
|
||||
var damselStatus = new InvoicePaymentChargebackStatus();
|
||||
switch (status) {
|
||||
case PENDING -> damselStatus.setPending(new InvoicePaymentChargebackPending());
|
||||
case ACCEPTED -> damselStatus.setAccepted(new InvoicePaymentChargebackAccepted());
|
||||
case REJECTED -> damselStatus.setRejected(new InvoicePaymentChargebackRejected());
|
||||
case CANCELLED -> damselStatus.setCancelled(new InvoicePaymentChargebackCancelled());
|
||||
default -> throw new BadRequestException(
|
||||
String.format("Chargeback status %s cannot be processed", chargebackStatus));
|
||||
}
|
||||
|
||||
return damselStatus;
|
||||
|
||||
} catch (Exception e) {
|
||||
throw new BadRequestException(e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
protected InvoicePaymentChargebackCategory mapCategory(String chargebackCategory) {
|
||||
try {
|
||||
var category = ChargebackCategory.fromValue(chargebackCategory);
|
||||
var damselCategory = new InvoicePaymentChargebackCategory();
|
||||
switch (category) {
|
||||
case FRAUD -> damselCategory.setFraud(new InvoicePaymentChargebackCategoryFraud());
|
||||
case DISPUTE -> damselCategory.setDispute(new InvoicePaymentChargebackCategoryDispute());
|
||||
case AUTHORISATION -> damselCategory
|
||||
.setAuthorisation(new InvoicePaymentChargebackCategoryAuthorisation());
|
||||
case PROCESSING_ERROR -> damselCategory
|
||||
.setProcessingError(new InvoicePaymentChargebackCategoryProcessingError());
|
||||
default -> throw new BadRequestException(
|
||||
String.format("Chargeback category %s cannot be processed", chargebackCategory));
|
||||
}
|
||||
|
||||
return damselCategory;
|
||||
|
||||
} catch (Exception e) {
|
||||
throw new BadRequestException(e.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,59 @@
|
||||
package com.rbkmoney.anapi.v2.converter.search.request;
|
||||
|
||||
import com.rbkmoney.anapi.v2.exception.BadRequestException;
|
||||
import com.rbkmoney.magista.InvoiceSearchQuery;
|
||||
import com.rbkmoney.magista.InvoiceStatus;
|
||||
import com.rbkmoney.magista.PaymentParams;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.time.OffsetDateTime;
|
||||
import java.util.List;
|
||||
|
||||
import static com.rbkmoney.anapi.v2.util.ConverterUtil.fillCommonParams;
|
||||
import static com.rbkmoney.anapi.v2.util.ConverterUtil.merge;
|
||||
|
||||
@Component
|
||||
public class ParamsToInvoiceSearchQueryConverter {
|
||||
|
||||
public InvoiceSearchQuery convert(String partyID,
|
||||
OffsetDateTime fromTime,
|
||||
OffsetDateTime toTime,
|
||||
Integer limit,
|
||||
List<String> shopIDs,
|
||||
List<String> invoiceIDs,
|
||||
String invoiceStatus,
|
||||
String invoiceID,
|
||||
String externalID,
|
||||
Long invoiceAmountFrom,
|
||||
Long invoiceAmountTo,
|
||||
String continuationToken) {
|
||||
return new InvoiceSearchQuery()
|
||||
.setCommonSearchQueryParams(
|
||||
fillCommonParams(fromTime, toTime, limit, partyID, shopIDs, continuationToken))
|
||||
.setPaymentParams(
|
||||
mapPaymentParams(invoiceAmountFrom, invoiceAmountTo)
|
||||
)
|
||||
.setInvoiceStatus(invoiceStatus != null ? mapStatus(invoiceStatus) : null)
|
||||
.setInvoiceIds(merge(invoiceID, invoiceIDs))
|
||||
.setExternalId(externalID);
|
||||
}
|
||||
|
||||
protected PaymentParams mapPaymentParams(Long invoiceAmountFrom, Long invoiceAmountTo) {
|
||||
var params = new PaymentParams();
|
||||
if (invoiceAmountFrom != null) {
|
||||
params.setPaymentAmountFrom(invoiceAmountFrom);
|
||||
}
|
||||
if (invoiceAmountTo != null) {
|
||||
params.setPaymentAmountTo(invoiceAmountTo);
|
||||
}
|
||||
return params;
|
||||
}
|
||||
|
||||
protected InvoiceStatus mapStatus(String status) {
|
||||
try {
|
||||
return InvoiceStatus.valueOf(status);
|
||||
} catch (IllegalArgumentException e) {
|
||||
throw new BadRequestException(String.format("Invoice status %s cannot be processed", status));
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,146 @@
|
||||
package com.rbkmoney.anapi.v2.converter.search.request;
|
||||
|
||||
import com.rbkmoney.anapi.v2.exception.BadRequestException;
|
||||
import com.rbkmoney.damsel.domain.LegacyBankCardPaymentSystem;
|
||||
import com.rbkmoney.damsel.domain.LegacyBankCardTokenProvider;
|
||||
import com.rbkmoney.damsel.domain.LegacyTerminalPaymentProvider;
|
||||
import com.rbkmoney.magista.*;
|
||||
import com.rbkmoney.openapi.anapi_v2.model.PaymentStatus;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.time.OffsetDateTime;
|
||||
import java.util.List;
|
||||
|
||||
import static com.rbkmoney.anapi.v2.util.ConverterUtil.fillCommonParams;
|
||||
import static com.rbkmoney.anapi.v2.util.ConverterUtil.merge;
|
||||
import static com.rbkmoney.magista.InvoicePaymentStatus.*;
|
||||
import static com.rbkmoney.magista.PaymentToolType.bank_card;
|
||||
import static com.rbkmoney.magista.PaymentToolType.payment_terminal;
|
||||
|
||||
@Component
|
||||
public class ParamsToPaymentSearchQueryConverter {
|
||||
|
||||
public PaymentSearchQuery convert(String partyID,
|
||||
OffsetDateTime fromTime,
|
||||
OffsetDateTime toTime,
|
||||
Integer limit,
|
||||
List<String> shopIDs,
|
||||
List<String> invoiceIDs,
|
||||
String paymentStatus, String paymentFlow,
|
||||
String paymentMethod,
|
||||
String paymentTerminalProvider,
|
||||
String invoiceID,
|
||||
String paymentID,
|
||||
String externalID,
|
||||
String payerEmail,
|
||||
String payerIP,
|
||||
String payerFingerprint,
|
||||
String customerID,
|
||||
String first6,
|
||||
String last4,
|
||||
String rrn,
|
||||
String approvalCode,
|
||||
String bankCardTokenProvider,
|
||||
String bankCardPaymentSystem,
|
||||
Long paymentAmountFrom,
|
||||
Long paymentAmountTo,
|
||||
List<String> excludedShops,
|
||||
String continuationToken) {
|
||||
PaymentSearchQuery query = new PaymentSearchQuery()
|
||||
.setCommonSearchQueryParams(
|
||||
fillCommonParams(fromTime, toTime, limit, partyID, shopIDs, continuationToken))
|
||||
.setExcludedShopIds(excludedShops)
|
||||
.setExternalId(externalID)
|
||||
.setInvoiceIds(merge(invoiceID, invoiceIDs));
|
||||
|
||||
PaymentParams paymentParams = new PaymentParams()
|
||||
.setPaymentTool(paymentMethod != null ? mapPaymentTool(paymentMethod) : null)
|
||||
.setPaymentFlow(paymentFlow != null ? mapInvoicePaymentFlow(paymentFlow) : null)
|
||||
.setPaymentTerminalProvider(
|
||||
paymentTerminalProvider != null ? mapTerminalProvider(paymentTerminalProvider) : null)
|
||||
.setPaymentTokenProvider(
|
||||
bankCardTokenProvider != null ? mapTokenProvider(bankCardTokenProvider) : null)
|
||||
.setPaymentEmail(payerEmail)
|
||||
.setPaymentApprovalCode(approvalCode)
|
||||
.setPaymentCustomerId(customerID)
|
||||
.setPaymentFingerprint(payerFingerprint)
|
||||
.setPaymentFirst6(first6)
|
||||
.setPaymentLast4(last4)
|
||||
.setPaymentId(paymentID)
|
||||
.setPaymentIp(payerIP)
|
||||
.setPaymentRrn(rrn)
|
||||
.setPaymentStatus(paymentStatus != null ? mapStatus(paymentStatus) : null)
|
||||
.setPaymentSystem(bankCardPaymentSystem != null
|
||||
? mapPaymentSystem(bankCardPaymentSystem) : null);
|
||||
if (paymentAmountFrom != null) {
|
||||
paymentParams.setPaymentAmountFrom(paymentAmountFrom);
|
||||
}
|
||||
if (paymentAmountTo != null) {
|
||||
paymentParams.setPaymentAmountTo(paymentAmountTo);
|
||||
}
|
||||
query.setPaymentParams(paymentParams);
|
||||
return query;
|
||||
}
|
||||
|
||||
protected LegacyTerminalPaymentProvider mapTerminalProvider(String provider) {
|
||||
try {
|
||||
return LegacyTerminalPaymentProvider.valueOf(provider);
|
||||
} catch (IllegalArgumentException e) {
|
||||
throw new BadRequestException(String.format("Terminal provider %s cannot be processed", provider));
|
||||
}
|
||||
}
|
||||
|
||||
protected LegacyBankCardTokenProvider mapTokenProvider(String provider) {
|
||||
try {
|
||||
return LegacyBankCardTokenProvider.valueOf(provider);
|
||||
} catch (IllegalArgumentException e) {
|
||||
throw new BadRequestException(String.format("Token provider %s cannot be processed", provider));
|
||||
}
|
||||
}
|
||||
|
||||
protected LegacyBankCardPaymentSystem mapPaymentSystem(String system) {
|
||||
try {
|
||||
return LegacyBankCardPaymentSystem.valueOf(system);
|
||||
} catch (IllegalArgumentException e) {
|
||||
throw new BadRequestException(
|
||||
String.format("Payment system %s cannot be processed", system));
|
||||
}
|
||||
}
|
||||
|
||||
protected PaymentToolType mapPaymentTool(String paymentMethod) {
|
||||
return switch (paymentMethod) {
|
||||
case "bankCard" -> bank_card;
|
||||
case "paymentTerminal" -> payment_terminal;
|
||||
default -> throw new BadRequestException(
|
||||
String.format("Payment method %s cannot be processed", paymentMethod));
|
||||
};
|
||||
}
|
||||
|
||||
protected com.rbkmoney.magista.InvoicePaymentFlowType mapInvoicePaymentFlow(String paymentFlow) {
|
||||
try {
|
||||
return InvoicePaymentFlowType.valueOf(paymentFlow);
|
||||
} catch (IllegalArgumentException e) {
|
||||
throw new BadRequestException(
|
||||
String.format("Payment flow %s cannot be processed", paymentFlow));
|
||||
}
|
||||
}
|
||||
|
||||
protected InvoicePaymentStatus mapStatus(String paymentStatus) {
|
||||
try {
|
||||
var status = PaymentStatus.StatusEnum.fromValue(paymentStatus);
|
||||
return switch (status) {
|
||||
case PENDING -> pending;
|
||||
case PROCESSED -> processed;
|
||||
case CAPTURED -> captured;
|
||||
case CANCELLED -> cancelled;
|
||||
case REFUNDED -> refunded;
|
||||
case FAILED -> failed;
|
||||
case CHARGEDBACK -> charged_back;
|
||||
default -> throw new BadRequestException(
|
||||
String.format("Payment status %s cannot be processed", paymentStatus));
|
||||
};
|
||||
} catch (Exception e) {
|
||||
throw new BadRequestException(e.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,40 @@
|
||||
package com.rbkmoney.anapi.v2.converter.search.request;
|
||||
|
||||
import com.rbkmoney.anapi.v2.exception.BadRequestException;
|
||||
import com.rbkmoney.magista.PayoutSearchQuery;
|
||||
import com.rbkmoney.magista.PayoutToolType;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.time.OffsetDateTime;
|
||||
import java.util.List;
|
||||
|
||||
import static com.rbkmoney.anapi.v2.util.ConverterUtil.fillCommonParams;
|
||||
|
||||
@Component
|
||||
public class ParamsToPayoutSearchQueryConverter {
|
||||
|
||||
public PayoutSearchQuery convert(String partyID,
|
||||
OffsetDateTime fromTime,
|
||||
OffsetDateTime toTime,
|
||||
Integer limit,
|
||||
List<String> shopIDs,
|
||||
String payoutID,
|
||||
String payoutToolType,
|
||||
String continuationToken) {
|
||||
return new PayoutSearchQuery()
|
||||
.setCommonSearchQueryParams(
|
||||
fillCommonParams(fromTime, toTime, limit, partyID, shopIDs, continuationToken))
|
||||
.setPayoutId(payoutID)
|
||||
.setPayoutType(payoutToolType != null ? mapPayoutToolType(payoutToolType) : null);
|
||||
}
|
||||
|
||||
protected PayoutToolType mapPayoutToolType(String payoutToolType) {
|
||||
return switch (payoutToolType) {
|
||||
case "PayoutAccount" -> PayoutToolType.payout_account;
|
||||
case "Wallet" -> PayoutToolType.wallet;
|
||||
case "PaymentInstitutionAccount" -> PayoutToolType.payment_institution_account;
|
||||
default -> throw new BadRequestException(
|
||||
String.format("PayoutToolType %s cannot be processed", payoutToolType));
|
||||
};
|
||||
}
|
||||
}
|
@ -0,0 +1,48 @@
|
||||
package com.rbkmoney.anapi.v2.converter.search.request;
|
||||
|
||||
import com.rbkmoney.anapi.v2.exception.BadRequestException;
|
||||
import com.rbkmoney.magista.InvoicePaymentRefundStatus;
|
||||
import com.rbkmoney.magista.RefundSearchQuery;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.time.OffsetDateTime;
|
||||
import java.util.List;
|
||||
|
||||
import static com.rbkmoney.anapi.v2.util.ConverterUtil.fillCommonParams;
|
||||
import static com.rbkmoney.anapi.v2.util.ConverterUtil.merge;
|
||||
|
||||
@Component
|
||||
public class ParamsToRefundSearchQueryConverter {
|
||||
|
||||
public RefundSearchQuery convert(String partyID,
|
||||
OffsetDateTime fromTime,
|
||||
OffsetDateTime toTime,
|
||||
Integer limit,
|
||||
List<String> shopIDs,
|
||||
List<String> invoiceIDs,
|
||||
String invoiceID,
|
||||
String paymentID,
|
||||
String refundID,
|
||||
String externalID,
|
||||
String refundStatus,
|
||||
String continuationToken) {
|
||||
return new RefundSearchQuery()
|
||||
.setCommonSearchQueryParams(
|
||||
fillCommonParams(fromTime, toTime, limit, partyID, shopIDs, continuationToken))
|
||||
.setRefundStatus(refundStatus != null ? mapStatus(refundStatus) : null)
|
||||
.setInvoiceIds(merge(invoiceID, invoiceIDs))
|
||||
.setExternalId(externalID)
|
||||
.setPaymentId(paymentID)
|
||||
.setRefundId(refundID);
|
||||
}
|
||||
|
||||
protected InvoicePaymentRefundStatus mapStatus(String status) {
|
||||
try {
|
||||
return InvoicePaymentRefundStatus.valueOf(status);
|
||||
} catch (IllegalArgumentException e) {
|
||||
throw new BadRequestException(
|
||||
String.format("Refund status %s cannot be processed", status));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,49 @@
|
||||
package com.rbkmoney.anapi.v2.converter.search.response;
|
||||
|
||||
import com.rbkmoney.damsel.domain.InvoicePaymentChargebackCategory;
|
||||
import com.rbkmoney.geck.common.util.TypeUtil;
|
||||
import com.rbkmoney.magista.StatChargeback;
|
||||
import com.rbkmoney.openapi.anapi_v2.model.Chargeback;
|
||||
import com.rbkmoney.openapi.anapi_v2.model.ChargebackCategory;
|
||||
import com.rbkmoney.openapi.anapi_v2.model.ChargebackReason;
|
||||
import com.rbkmoney.openapi.anapi_v2.model.Content;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.time.ZoneOffset;
|
||||
|
||||
@Component
|
||||
public class StatChargebackToChargebackConverter {
|
||||
|
||||
public Chargeback convert(StatChargeback chargeback) {
|
||||
return new Chargeback()
|
||||
.bodyAmount(chargeback.getAmount())
|
||||
.createdAt(TypeUtil.stringToInstant(chargeback.getCreatedAt()).atOffset(ZoneOffset.UTC))
|
||||
.chargebackId(chargeback.getChargebackId())
|
||||
.fee(chargeback.getFee())
|
||||
.chargebackReason(chargeback.isSetChargebackReason()
|
||||
? new ChargebackReason()
|
||||
.category(mapCategory(chargeback.getChargebackReason().getCategory()))
|
||||
.code(chargeback.getChargebackReason().getCode()) : null)
|
||||
.content(chargeback.isSetContent()
|
||||
? new Content().data(chargeback.getContent().getData())
|
||||
.type(chargeback.getContent().getType()) : null)
|
||||
.bodyCurrency(chargeback.getCurrencyCode().getSymbolicCode());
|
||||
}
|
||||
|
||||
protected ChargebackCategory mapCategory(InvoicePaymentChargebackCategory chargebackCategory) {
|
||||
try {
|
||||
var field = InvoicePaymentChargebackCategory._Fields.findByName(
|
||||
chargebackCategory.getSetField().getFieldName());
|
||||
return switch (field) {
|
||||
case FRAUD -> ChargebackCategory.FRAUD;
|
||||
case DISPUTE -> ChargebackCategory.DISPUTE;
|
||||
case AUTHORISATION -> ChargebackCategory.AUTHORISATION;
|
||||
case PROCESSING_ERROR -> ChargebackCategory.PROCESSING_ERROR;
|
||||
default -> throw new IllegalArgumentException();
|
||||
};
|
||||
} catch (Exception e) {
|
||||
throw new IllegalArgumentException(
|
||||
String.format("Chargeback category %s cannot be processed", chargebackCategory));
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,75 @@
|
||||
package com.rbkmoney.anapi.v2.converter.search.response;
|
||||
|
||||
import com.rbkmoney.damsel.domain.InvoiceStatus;
|
||||
import com.rbkmoney.damsel.msgpack.Value;
|
||||
import com.rbkmoney.geck.common.util.TypeUtil;
|
||||
import com.rbkmoney.magista.StatInvoice;
|
||||
import com.rbkmoney.openapi.anapi_v2.model.Invoice;
|
||||
import com.rbkmoney.openapi.anapi_v2.model.InvoiceLine;
|
||||
import com.rbkmoney.openapi.anapi_v2.model.InvoiceLineTaxMode;
|
||||
import com.rbkmoney.openapi.anapi_v2.model.InvoiceLineTaxVAT;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.time.ZoneOffset;
|
||||
import java.util.Map;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@Component
|
||||
public class StatInvoiceToInvoiceConverter {
|
||||
|
||||
public Invoice convert(StatInvoice invoice) {
|
||||
Invoice result = new Invoice()
|
||||
.amount(invoice.getAmount())
|
||||
.createdAt(TypeUtil.stringToInstant(invoice.getCreatedAt()).atOffset(ZoneOffset.UTC))
|
||||
.currency(invoice.getCurrencySymbolicCode())
|
||||
.externalID(invoice.getExternalId())
|
||||
.cart(invoice.isSetCart()
|
||||
? invoice.getCart().getLines().stream().map(invoiceLine -> new InvoiceLine()
|
||||
.cost(invoiceLine.getQuantity() * invoiceLine.getPrice().getAmount())
|
||||
.price(invoiceLine.getPrice().getAmount())
|
||||
.product(invoiceLine.getProduct())
|
||||
.taxMode(mapTaxMode(invoiceLine.getMetadata()))
|
||||
).collect(Collectors.toList()) : null)
|
||||
.description(invoice.getDescription())
|
||||
.dueDate(TypeUtil.stringToInstant(invoice.getDue()).atOffset(ZoneOffset.UTC))
|
||||
.id(invoice.getId())
|
||||
.product(invoice.getProduct())
|
||||
.shopID(invoice.getShopId());
|
||||
|
||||
mapStatusInfo(result, invoice.getStatus());
|
||||
return result;
|
||||
}
|
||||
|
||||
protected void mapStatusInfo(Invoice invoice, InvoiceStatus status) {
|
||||
try {
|
||||
var field = InvoiceStatus._Fields.findByName(status.getSetField().getFieldName());
|
||||
switch (field) {
|
||||
case FULFILLED -> {
|
||||
invoice.setReason(status.getFulfilled().getDetails());
|
||||
invoice.setStatus(Invoice.StatusEnum.FULFILLED);
|
||||
}
|
||||
case CANCELLED -> {
|
||||
invoice.setReason(status.getCancelled().getDetails());
|
||||
invoice.setStatus(Invoice.StatusEnum.CANCELLED);
|
||||
}
|
||||
case PAID -> invoice.setStatus(Invoice.StatusEnum.PAID);
|
||||
case UNPAID -> invoice.setStatus(Invoice.StatusEnum.UNPAID);
|
||||
default -> throw new IllegalArgumentException();
|
||||
}
|
||||
} catch (Exception e) {
|
||||
throw new IllegalArgumentException(
|
||||
String.format("Invoice status %s cannot be processed", status));
|
||||
}
|
||||
}
|
||||
|
||||
protected InvoiceLineTaxMode mapTaxMode(Map<String, Value> metadata) {
|
||||
Value taxMode = metadata.get("TaxMode");
|
||||
if (taxMode != null) {
|
||||
return new InvoiceLineTaxVAT()
|
||||
.rate(InvoiceLineTaxVAT.RateEnum.fromValue(
|
||||
taxMode.getStr()));
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,83 @@
|
||||
package com.rbkmoney.anapi.v2.converter.search.response;
|
||||
|
||||
import com.rbkmoney.damsel.domain.InvoicePaymentStatus;
|
||||
import com.rbkmoney.geck.common.util.TypeUtil;
|
||||
import com.rbkmoney.magista.StatPayment;
|
||||
import com.rbkmoney.openapi.anapi_v2.model.*;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.time.ZoneOffset;
|
||||
|
||||
import static com.rbkmoney.openapi.anapi_v2.model.PaymentSearchResult.StatusEnum.*;
|
||||
|
||||
@Component
|
||||
public class StatPaymentToPaymentSearchResultConverter {
|
||||
|
||||
public PaymentSearchResult convert(StatPayment payment) {
|
||||
return new PaymentSearchResult()
|
||||
.amount(payment.getAmount())
|
||||
.createdAt(TypeUtil.stringToInstant(payment.getCreatedAt()).atOffset(ZoneOffset.UTC))
|
||||
.currency(payment.getCurrencySymbolicCode())
|
||||
.externalID(payment.getExternalId())
|
||||
.fee(payment.getFee())
|
||||
.flow(new PaymentFlow()
|
||||
.type(payment.getFlow().isSetHold() ? PaymentFlow.TypeEnum.PAYMENTFLOWHOLD :
|
||||
PaymentFlow.TypeEnum.PAYMENTFLOWINSTANT))
|
||||
.geoLocationInfo(payment.isSetLocationInfo() ? new GeoLocationInfo()
|
||||
.cityGeoID(payment.getLocationInfo().getCityGeoId())
|
||||
.countryGeoID(payment.getLocationInfo().getCountryGeoId())
|
||||
: null)
|
||||
.status(mapStatus(payment.getStatus()))
|
||||
.error(payment.getStatus().isSetFailed()
|
||||
? new PaymentError().code(payment.getStatus().getFailed().getFailure().getFailure().getCode())
|
||||
: null)
|
||||
.statusChangedAt(payment.isSetStatusChangedAt()
|
||||
? TypeUtil.stringToInstant(payment.getStatusChangedAt()).atOffset(ZoneOffset.UTC) : null)
|
||||
.id(payment.getId())
|
||||
.invoiceID(payment.getInvoiceId())
|
||||
.makeRecurrent(payment.isMakeRecurrent())
|
||||
.payer(mapPayer(payment.getPayer()))
|
||||
.shopID(payment.getShopId())
|
||||
.shortID(payment.getShortId())
|
||||
.transactionInfo(payment.isSetAdditionalTransactionInfo()
|
||||
? new TransactionInfo()
|
||||
.approvalCode(payment.getAdditionalTransactionInfo().getApprovalCode())
|
||||
.rrn(payment.getAdditionalTransactionInfo().getRrn())
|
||||
: null);
|
||||
}
|
||||
|
||||
protected Payer mapPayer(com.rbkmoney.magista.Payer payer) {
|
||||
try {
|
||||
var field = com.rbkmoney.magista.Payer._Fields.findByName(payer.getSetField().getFieldName());
|
||||
return switch (field) {
|
||||
case CUSTOMER -> new Payer().payerType(Payer.PayerTypeEnum.CUSTOMERPAYER);
|
||||
case PAYMENT_RESOURCE -> new Payer().payerType(Payer.PayerTypeEnum.PAYMENTRESOURCEPAYER);
|
||||
case RECURRENT -> new Payer().payerType(Payer.PayerTypeEnum.RECURRENTPAYER);
|
||||
default -> throw new IllegalArgumentException();
|
||||
};
|
||||
} catch (Exception e) {
|
||||
throw new IllegalArgumentException(
|
||||
String.format("Payer %s cannot be processed", payer));
|
||||
}
|
||||
}
|
||||
|
||||
protected PaymentSearchResult.StatusEnum mapStatus(InvoicePaymentStatus status) {
|
||||
try {
|
||||
var field = InvoicePaymentStatus._Fields.findByName(status.getSetField().getFieldName());
|
||||
return switch (field) {
|
||||
case PENDING -> PENDING;
|
||||
case PROCESSED -> PROCESSED;
|
||||
case CAPTURED -> CAPTURED;
|
||||
case CANCELLED -> CANCELLED;
|
||||
case REFUNDED -> REFUNDED;
|
||||
case FAILED -> FAILED;
|
||||
case CHARGED_BACK -> CHARGEDBACK;
|
||||
default -> throw new IllegalArgumentException();
|
||||
};
|
||||
} catch (Exception e) {
|
||||
throw new IllegalArgumentException(
|
||||
String.format("Payment status %s cannot be processed", status));
|
||||
}
|
||||
|
||||
}
|
||||
}
|
@ -0,0 +1,125 @@
|
||||
package com.rbkmoney.anapi.v2.converter.search.response;
|
||||
|
||||
import com.rbkmoney.damsel.domain.CountryCode;
|
||||
import com.rbkmoney.damsel.domain.PayoutToolInfo;
|
||||
import com.rbkmoney.geck.common.util.TypeUtil;
|
||||
import com.rbkmoney.magista.PayoutStatus;
|
||||
import com.rbkmoney.magista.StatPayout;
|
||||
import com.rbkmoney.openapi.anapi_v2.model.*;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import java.time.ZoneOffset;
|
||||
|
||||
@Component
|
||||
public class StatPayoutToPayoutConverter {
|
||||
|
||||
public Payout convert(StatPayout payout) {
|
||||
return new Payout()
|
||||
.amount(payout.getAmount())
|
||||
.createdAt(TypeUtil.stringToInstant(payout.getCreatedAt()).atOffset(ZoneOffset.UTC))
|
||||
.currency(payout.getCurrencySymbolicCode())
|
||||
.fee(payout.getFee())
|
||||
.id(payout.getId())
|
||||
.payoutToolDetails(mapPayoutToolDetails(payout.getPayoutToolInfo()))
|
||||
.shopID(payout.getShopId())
|
||||
.status(mapStatus(payout.getStatus()))
|
||||
.cancellationDetails(
|
||||
payout.getStatus().isSetCancelled()
|
||||
? payout.getStatus().getCancelled().getDetails()
|
||||
: null);
|
||||
}
|
||||
|
||||
protected String mapStatus(PayoutStatus status) {
|
||||
try {
|
||||
var field = PayoutStatus._Fields.findByName(status.getSetField().getFieldName());
|
||||
return switch (field) {
|
||||
case UNPAID -> "Unpaid";
|
||||
case PAID -> "Paid";
|
||||
case CANCELLED -> "Cancelled";
|
||||
case CONFIRMED -> "Confirmed";
|
||||
default -> throw new IllegalArgumentException();
|
||||
};
|
||||
} catch (Exception e) {
|
||||
throw new IllegalArgumentException(
|
||||
String.format("Payout status %s cannot be processed", status));
|
||||
}
|
||||
}
|
||||
|
||||
protected PayoutToolDetails mapPayoutToolDetails(PayoutToolInfo payoutToolInfo) {
|
||||
try {
|
||||
var field = PayoutToolInfo._Fields.findByName(payoutToolInfo.getSetField().getFieldName());
|
||||
switch (field) {
|
||||
case RUSSIAN_BANK_ACCOUNT -> {
|
||||
var account = payoutToolInfo.getRussianBankAccount();
|
||||
return new PayoutToolDetailsBankAccount()
|
||||
.account(account.getAccount())
|
||||
.bankBik(account.getBankBik())
|
||||
.bankName(account.getBankName())
|
||||
.bankPostAccount(account.getBankPostAccount())
|
||||
.detailsType("PayoutToolDetailsBankAccount");
|
||||
}
|
||||
case INTERNATIONAL_BANK_ACCOUNT -> {
|
||||
var account = payoutToolInfo.getInternationalBankAccount();
|
||||
return new PayoutToolDetailsInternationalBankAccount()
|
||||
.iban(account.getIban())
|
||||
.number(account.getNumber())
|
||||
.bankDetails(account.isSetBank()
|
||||
? new InternationalBankDetails()
|
||||
.name(account.getBank().getName())
|
||||
.bic(account.getBank().getBic())
|
||||
.countryCode(mapCountryCode(account.getBank().getCountry()))
|
||||
.address(account.getBank().getAddress())
|
||||
.abartn(account.getBank().getAbaRtn())
|
||||
: null)
|
||||
.correspondentBankAccount(
|
||||
mapInternationalCorrespondentBankAccount(account.getCorrespondentAccount()))
|
||||
.detailsType("PayoutToolDetailsInternationalBankAccount");
|
||||
}
|
||||
case WALLET_INFO -> {
|
||||
return new PayoutToolDetailsWalletInfo()
|
||||
.walletID(payoutToolInfo.getWalletInfo().getWalletId())
|
||||
.detailsType("PayoutToolDetailsWalletInfo");
|
||||
}
|
||||
case PAYMENT_INSTITUTION_ACCOUNT -> {
|
||||
return new PayoutToolDetailsPaymentInstitutionAccount()
|
||||
.detailsType("PayoutToolDetailsPaymentInstitutionAccount");
|
||||
}
|
||||
default -> throw new IllegalArgumentException();
|
||||
}
|
||||
} catch (Exception e) {
|
||||
throw new IllegalArgumentException(
|
||||
String.format("PayoutToolInfo %s cannot be processed", payoutToolInfo));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
protected String mapCountryCode(@Nullable CountryCode countryCode) {
|
||||
if (countryCode == null) {
|
||||
return null;
|
||||
}
|
||||
return countryCode.name();
|
||||
}
|
||||
|
||||
protected InternationalCorrespondentBankAccount mapInternationalCorrespondentBankAccount(
|
||||
com.rbkmoney.damsel.domain.InternationalBankAccount account) {
|
||||
if (account == null) {
|
||||
return null;
|
||||
}
|
||||
var details = account.getBank();
|
||||
return new InternationalCorrespondentBankAccount()
|
||||
.bankDetails(details != null
|
||||
? new InternationalBankDetails()
|
||||
.name(details.getName())
|
||||
.bic(details.getBic())
|
||||
.countryCode(details.getCountry().name())
|
||||
.address(details.getAddress())
|
||||
.abartn(details.getAbaRtn())
|
||||
: null)
|
||||
.iban(account.getIban())
|
||||
.number(account.getNumber())
|
||||
.correspondentBankAccount(account.isSetCorrespondentAccount()
|
||||
? mapInternationalCorrespondentBankAccount(account.getCorrespondentAccount())
|
||||
: null);
|
||||
}
|
||||
}
|
@ -0,0 +1,55 @@
|
||||
package com.rbkmoney.anapi.v2.converter.search.response;
|
||||
|
||||
import com.rbkmoney.damsel.domain.InvoicePaymentRefundStatus;
|
||||
import com.rbkmoney.geck.common.util.TypeUtil;
|
||||
import com.rbkmoney.magista.StatRefund;
|
||||
import com.rbkmoney.openapi.anapi_v2.model.RefundSearchResult;
|
||||
import com.rbkmoney.openapi.anapi_v2.model.RefundStatusError;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.time.ZoneOffset;
|
||||
|
||||
@Component
|
||||
public class StatRefundToRefundSearchResultConverter {
|
||||
|
||||
public RefundSearchResult convert(StatRefund refund) {
|
||||
return new RefundSearchResult()
|
||||
.amount(refund.getAmount())
|
||||
.createdAt(TypeUtil.stringToInstant(refund.getCreatedAt()).atOffset(ZoneOffset.UTC))
|
||||
.currency(refund.getCurrencySymbolicCode())
|
||||
.id(refund.getId())
|
||||
.shopID(refund.getShopId())
|
||||
.status(mapStatus(refund.getStatus()))
|
||||
.externalID(refund.getExternalId())
|
||||
.error(mapStatusError(refund.getStatus()))
|
||||
.invoiceID(refund.getInvoiceId())
|
||||
.paymentID(refund.getPaymentId())
|
||||
.reason(refund.getReason());
|
||||
}
|
||||
|
||||
protected RefundStatusError mapStatusError(InvoicePaymentRefundStatus status) {
|
||||
if (status.isSetFailed() && status.getFailed().getFailure().isSetFailure()) {
|
||||
var failure = status.getFailed().getFailure().getFailure();
|
||||
return new RefundStatusError()
|
||||
.code(failure.getCode())
|
||||
.message(failure.getReason());
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
protected RefundSearchResult.StatusEnum mapStatus(InvoicePaymentRefundStatus status) {
|
||||
try {
|
||||
var field = InvoicePaymentRefundStatus._Fields.findByName(status.getSetField().getFieldName());
|
||||
return switch (field) {
|
||||
case PENDING -> RefundSearchResult.StatusEnum.PENDING;
|
||||
case SUCCEEDED -> RefundSearchResult.StatusEnum.SUCCEEDED;
|
||||
case FAILED -> RefundSearchResult.StatusEnum.FAILED;
|
||||
default -> throw new IllegalArgumentException();
|
||||
};
|
||||
} catch (Exception e) {
|
||||
throw new IllegalArgumentException(
|
||||
String.format("Refund status %s cannot be processed", status));
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,12 @@
|
||||
package com.rbkmoney.anapi.v2.exception;
|
||||
|
||||
public class AuthorizationException extends RuntimeException {
|
||||
|
||||
public AuthorizationException(String s) {
|
||||
super(s);
|
||||
}
|
||||
|
||||
public AuthorizationException(String message, Throwable cause) {
|
||||
super(message, cause);
|
||||
}
|
||||
}
|
@ -0,0 +1,19 @@
|
||||
package com.rbkmoney.anapi.v2.exception;
|
||||
|
||||
import com.rbkmoney.openapi.anapi_v2.model.DefaultLogicError;
|
||||
import lombok.Getter;
|
||||
|
||||
public class BadRequestException extends IllegalArgumentException {
|
||||
|
||||
@Getter
|
||||
private DefaultLogicError.CodeEnum errorCode = DefaultLogicError.CodeEnum.INVALIDREQUEST;
|
||||
|
||||
public BadRequestException(String s) {
|
||||
super(s);
|
||||
}
|
||||
|
||||
public BadRequestException(String s, DefaultLogicError.CodeEnum errorCode) {
|
||||
super(s);
|
||||
this.errorCode = errorCode;
|
||||
}
|
||||
}
|
@ -0,0 +1,11 @@
|
||||
package com.rbkmoney.anapi.v2.exception;
|
||||
|
||||
public class BouncerException extends AuthorizationException {
|
||||
public BouncerException(String s) {
|
||||
super(s);
|
||||
}
|
||||
|
||||
public BouncerException(String message, Throwable cause) {
|
||||
super(message, cause);
|
||||
}
|
||||
}
|
@ -0,0 +1,23 @@
|
||||
package com.rbkmoney.anapi.v2.exception;
|
||||
|
||||
public class DeadlineException extends RuntimeException {
|
||||
|
||||
public DeadlineException() {
|
||||
}
|
||||
|
||||
public DeadlineException(String message) {
|
||||
super(message);
|
||||
}
|
||||
|
||||
public DeadlineException(String message, Throwable cause) {
|
||||
super(message, cause);
|
||||
}
|
||||
|
||||
public DeadlineException(Throwable cause) {
|
||||
super(cause);
|
||||
}
|
||||
|
||||
public DeadlineException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) {
|
||||
super(message, cause, enableSuppression, writableStackTrace);
|
||||
}
|
||||
}
|
@ -0,0 +1,77 @@
|
||||
package com.rbkmoney.anapi.v2.security;
|
||||
|
||||
import com.rbkmoney.anapi.v2.exception.AuthorizationException;
|
||||
import com.rbkmoney.anapi.v2.service.BouncerService;
|
||||
import com.rbkmoney.anapi.v2.service.KeycloakService;
|
||||
import com.rbkmoney.anapi.v2.service.VortigonService;
|
||||
import com.rbkmoney.bouncer.base.Entity;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.keycloak.representations.AccessToken;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@Slf4j
|
||||
@RequiredArgsConstructor
|
||||
@Service
|
||||
public class AccessService {
|
||||
|
||||
private final VortigonService vortigonService;
|
||||
private final BouncerService bouncerService;
|
||||
private final KeycloakService keycloakService;
|
||||
|
||||
@Value("${service.bouncer.auth.enabled}")
|
||||
private boolean authEnabled;
|
||||
|
||||
public List<String> getAccessibleShops(String operationId, String partyId, List<String> requestShopIds,
|
||||
String realm) {
|
||||
|
||||
List<String> shopIds = vortigonService.getShopIds(partyId, Objects.requireNonNullElse(realm, "live"));
|
||||
|
||||
if (!requestShopIds.isEmpty()) {
|
||||
shopIds = requestShopIds.stream()
|
||||
.filter(shopIds::contains)
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
log.info("Check the user's rights to perform the operation {}", operationId);
|
||||
var ctx = buildAnapiBouncerContext(operationId, partyId, shopIds);
|
||||
var resolution = bouncerService.getResolution(ctx);
|
||||
if (resolution.isSetForbidden()) {
|
||||
if (authEnabled) {
|
||||
throw new AuthorizationException(String.format("No rights to perform %s", operationId));
|
||||
} else {
|
||||
log.warn("No rights to perform {}", operationId);
|
||||
}
|
||||
}
|
||||
|
||||
if (resolution.isSetRestricted()) {
|
||||
if (authEnabled) {
|
||||
return resolution.getRestricted().getRestrictions().getAnapi().getOp().getShops().stream()
|
||||
.map(Entity::getId)
|
||||
.collect(Collectors.toList());
|
||||
} else {
|
||||
log.warn("Rights to perform {} are restricted", operationId);
|
||||
}
|
||||
}
|
||||
|
||||
return new ArrayList<>(shopIds);
|
||||
}
|
||||
|
||||
private AnapiBouncerContext buildAnapiBouncerContext(String operationId, String partyId, List<String> shopIds) {
|
||||
AccessToken token = keycloakService.getAccessToken();
|
||||
return AnapiBouncerContext.builder()
|
||||
.operationId(operationId)
|
||||
.partyId(partyId)
|
||||
.shopIds(shopIds)
|
||||
.tokenExpiration(token.getExp())
|
||||
.tokenId(token.getId())
|
||||
.userId(token.getSubject())
|
||||
.build();
|
||||
}
|
||||
}
|
@ -0,0 +1,18 @@
|
||||
package com.rbkmoney.anapi.v2.security;
|
||||
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Builder
|
||||
@Data
|
||||
public class AnapiBouncerContext {
|
||||
|
||||
private final long tokenExpiration;
|
||||
private final String tokenId;
|
||||
private final String userId;
|
||||
private final String operationId;
|
||||
private final String partyId;
|
||||
private final List<String> shopIds;
|
||||
}
|
@ -0,0 +1,81 @@
|
||||
package com.rbkmoney.anapi.v2.security;
|
||||
|
||||
import com.rbkmoney.anapi.v2.config.properties.BouncerProperties;
|
||||
import com.rbkmoney.anapi.v2.service.KeycloakService;
|
||||
import com.rbkmoney.anapi.v2.service.OrgMgmtService;
|
||||
import com.rbkmoney.bouncer.base.Entity;
|
||||
import com.rbkmoney.bouncer.context.v1.*;
|
||||
import com.rbkmoney.bouncer.ctx.ContextFragmentType;
|
||||
import com.rbkmoney.bouncer.decisions.Context;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.SneakyThrows;
|
||||
import org.apache.thrift.TSerializer;
|
||||
import org.keycloak.representations.AccessToken;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.time.Instant;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@RequiredArgsConstructor
|
||||
@Component
|
||||
public class BouncerContextFactory {
|
||||
|
||||
private final BouncerProperties bouncerProperties;
|
||||
private final OrgMgmtService orgMgmtService;
|
||||
private final KeycloakService keycloakService;
|
||||
|
||||
@SneakyThrows
|
||||
public Context buildContext(AnapiBouncerContext bouncerContext) {
|
||||
ContextFragment contextFragment = buildContextFragment(bouncerContext);
|
||||
var serializer = new TSerializer();
|
||||
var fragment = new com.rbkmoney.bouncer.ctx.ContextFragment()
|
||||
.setType(ContextFragmentType.v1_thrift_binary)
|
||||
.setContent(serializer.serialize(contextFragment));
|
||||
|
||||
com.rbkmoney.bouncer.ctx.ContextFragment
|
||||
userFragment = orgMgmtService.getUserAuthContext(keycloakService.getAccessToken().getSubject());
|
||||
Context context = new Context();
|
||||
context.putToFragments(bouncerProperties.getContextFragmentId(), fragment);
|
||||
context.putToFragments("user", userFragment);
|
||||
return context;
|
||||
}
|
||||
|
||||
private ContextFragment buildContextFragment(AnapiBouncerContext bouncerContext) {
|
||||
Environment env = buildEnvironment();
|
||||
AccessToken accessToken = keycloakService.getAccessToken();
|
||||
ContextAnalyticsAPI contextAnalyticsApi = buildAnapiContext(bouncerContext);
|
||||
return new ContextFragment()
|
||||
.setAuth(buildAuth(bouncerContext, accessToken))
|
||||
.setEnv(env)
|
||||
.setAnapi(contextAnalyticsApi);
|
||||
}
|
||||
|
||||
private Auth buildAuth(AnapiBouncerContext bouncerContext, AccessToken accessToken) {
|
||||
Auth auth = new Auth();
|
||||
Set<AuthScope> authScopeSet = bouncerContext.getShopIds().stream()
|
||||
.map(shopId -> new AuthScope()
|
||||
.setParty(new Entity().setId(bouncerContext.getPartyId()))
|
||||
.setShop(new Entity().setId(shopId)))
|
||||
.collect(Collectors.toSet());
|
||||
return auth.setToken(new Token().setId(accessToken.getId()))
|
||||
.setMethod(bouncerProperties.getAuthMethod())
|
||||
.setExpiration(Instant.ofEpochSecond(accessToken.getExp()).toString())
|
||||
.setScope(authScopeSet);
|
||||
}
|
||||
|
||||
private Environment buildEnvironment() {
|
||||
Deployment deployment = new Deployment()
|
||||
.setId(bouncerProperties.getDeploymentId());
|
||||
return new Environment()
|
||||
.setDeployment(deployment)
|
||||
.setNow(Instant.now().toString());
|
||||
}
|
||||
|
||||
private ContextAnalyticsAPI buildAnapiContext(AnapiBouncerContext ctx) {
|
||||
return new ContextAnalyticsAPI()
|
||||
.setOp(new AnalyticsAPIOperation()
|
||||
.setId(ctx.getOperationId()));
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,39 @@
|
||||
package com.rbkmoney.anapi.v2.service;
|
||||
|
||||
import com.rbkmoney.anapi.v2.config.properties.BouncerProperties;
|
||||
import com.rbkmoney.anapi.v2.exception.BouncerException;
|
||||
import com.rbkmoney.anapi.v2.security.AnapiBouncerContext;
|
||||
import com.rbkmoney.anapi.v2.security.BouncerContextFactory;
|
||||
import com.rbkmoney.bouncer.decisions.ArbiterSrv;
|
||||
import com.rbkmoney.bouncer.decisions.Context;
|
||||
import com.rbkmoney.bouncer.decisions.Judgement;
|
||||
import com.rbkmoney.bouncer.decisions.Resolution;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.thrift.TException;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
@Slf4j
|
||||
@Service
|
||||
@RequiredArgsConstructor
|
||||
public class BouncerService {
|
||||
|
||||
private final BouncerProperties bouncerProperties;
|
||||
private final BouncerContextFactory bouncerContextFactory;
|
||||
private final ArbiterSrv.Iface bouncerClient;
|
||||
|
||||
public Resolution getResolution(AnapiBouncerContext bouncerContext) {
|
||||
log.debug("Check access with bouncer context: {}", bouncerContext);
|
||||
Context context = bouncerContextFactory.buildContext(bouncerContext);
|
||||
log.debug("Built thrift context: {}", context);
|
||||
try {
|
||||
Judgement judge = bouncerClient.judge(bouncerProperties.getRuleSetId(), context);
|
||||
log.debug("Have judge: {}", judge);
|
||||
Resolution resolution = judge.getResolution();
|
||||
log.debug("Resolution: {}", resolution);
|
||||
return resolution;
|
||||
} catch (TException e) {
|
||||
throw new BouncerException("Error while call bouncer", e);
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,17 @@
|
||||
package com.rbkmoney.anapi.v2.service;
|
||||
|
||||
import org.keycloak.KeycloakPrincipal;
|
||||
import org.keycloak.representations.AccessToken;
|
||||
import org.springframework.security.core.context.SecurityContextHolder;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
@Service
|
||||
public class KeycloakService {
|
||||
|
||||
public AccessToken getAccessToken() {
|
||||
var keycloakPrincipal = (KeycloakPrincipal) SecurityContextHolder.getContext()
|
||||
.getAuthentication()
|
||||
.getPrincipal();
|
||||
return keycloakPrincipal.getKeycloakSecurityContext().getToken();
|
||||
}
|
||||
}
|
@ -0,0 +1,22 @@
|
||||
package com.rbkmoney.anapi.v2.service;
|
||||
|
||||
import com.rbkmoney.bouncer.ctx.ContextFragment;
|
||||
import com.rbkmoney.orgmanagement.AuthContextProviderSrv;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
@RequiredArgsConstructor
|
||||
@Service
|
||||
public class OrgMgmtService {
|
||||
|
||||
private final AuthContextProviderSrv.Iface orgMgmtClient;
|
||||
|
||||
public ContextFragment getUserAuthContext(String userId) {
|
||||
try {
|
||||
return orgMgmtClient.getUserContext(userId);
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException(String.format("Can't get user auth context: userId = %s", userId), e);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,74 @@
|
||||
package com.rbkmoney.anapi.v2.service;
|
||||
|
||||
import com.rbkmoney.anapi.v2.converter.search.response.*;
|
||||
import com.rbkmoney.magista.*;
|
||||
import com.rbkmoney.openapi.anapi_v2.model.*;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.SneakyThrows;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@Service
|
||||
@RequiredArgsConstructor
|
||||
public class SearchService {
|
||||
|
||||
private final MerchantStatisticsServiceSrv.Iface magistaClient;
|
||||
private final StatPaymentToPaymentSearchResultConverter paymentResponseConverter;
|
||||
private final StatChargebackToChargebackConverter chargebackResponseConverter;
|
||||
private final StatInvoiceToInvoiceConverter invoiceResponseConverter;
|
||||
private final StatPayoutToPayoutConverter payoutResponseConverter;
|
||||
private final StatRefundToRefundSearchResultConverter refundResponseConverter;
|
||||
|
||||
@SneakyThrows
|
||||
public InlineResponse20010 findPayments(PaymentSearchQuery query) {
|
||||
StatPaymentResponse magistaResponse = magistaClient.searchPayments(query);
|
||||
return new InlineResponse20010()
|
||||
.result(magistaResponse.getPayments().stream()
|
||||
.map(paymentResponseConverter::convert)
|
||||
.collect(Collectors.toList()))
|
||||
.continuationToken(magistaResponse.getContinuationToken());
|
||||
}
|
||||
|
||||
@SneakyThrows
|
||||
public InlineResponse2008 findChargebacks(ChargebackSearchQuery query) {
|
||||
StatChargebackResponse magistaResponse = magistaClient.searchChargebacks(query);
|
||||
return new InlineResponse2008()
|
||||
.result(magistaResponse.getChargebacks().stream()
|
||||
.map(chargebackResponseConverter::convert)
|
||||
.collect(Collectors.toList()))
|
||||
.continuationToken(magistaResponse.getContinuationToken());
|
||||
}
|
||||
|
||||
|
||||
@SneakyThrows
|
||||
public InlineResponse2009 findInvoices(InvoiceSearchQuery query) {
|
||||
StatInvoiceResponse magistaResponse = magistaClient.searchInvoices(query);
|
||||
return new InlineResponse2009()
|
||||
.result(magistaResponse.getInvoices().stream()
|
||||
.map(invoiceResponseConverter::convert)
|
||||
.collect(Collectors.toList()))
|
||||
.continuationToken(magistaResponse.getContinuationToken());
|
||||
}
|
||||
|
||||
@SneakyThrows
|
||||
public InlineResponse20011 findPayouts(PayoutSearchQuery query) {
|
||||
StatPayoutResponse magistaResponse = magistaClient.searchPayouts(query);
|
||||
return new InlineResponse20011()
|
||||
.result(magistaResponse.getPayouts().stream()
|
||||
.map(payoutResponseConverter::convert)
|
||||
.collect(Collectors.toList()))
|
||||
.continuationToken(magistaResponse.getContinuationToken());
|
||||
}
|
||||
|
||||
@SneakyThrows
|
||||
public InlineResponse20012 findRefunds(RefundSearchQuery query) {
|
||||
StatRefundResponse magistaResponse = magistaClient.searchRefunds(query);
|
||||
return new InlineResponse20012()
|
||||
.result(magistaResponse.getRefunds().stream()
|
||||
.map(refundResponseConverter::convert)
|
||||
.collect(Collectors.toList()))
|
||||
.continuationToken(magistaResponse.getContinuationToken());
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,31 @@
|
||||
package com.rbkmoney.anapi.v2.service;
|
||||
|
||||
import com.rbkmoney.anapi.v2.exception.BadRequestException;
|
||||
import com.rbkmoney.damsel.vortigon.PaymentInstitutionRealm;
|
||||
import com.rbkmoney.damsel.vortigon.VortigonServiceSrv;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.SneakyThrows;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Service
|
||||
@RequiredArgsConstructor
|
||||
public class VortigonService {
|
||||
|
||||
private final VortigonServiceSrv.Iface vortigonClient;
|
||||
|
||||
@SneakyThrows
|
||||
public List<String> getShopIds(String partyId, String realm) {
|
||||
return vortigonClient.getShopsIds(partyId, mapRealm(realm));
|
||||
}
|
||||
|
||||
private PaymentInstitutionRealm mapRealm(String realm) {
|
||||
try {
|
||||
return PaymentInstitutionRealm.valueOf(realm);
|
||||
} catch (IllegalArgumentException e) {
|
||||
throw new BadRequestException(
|
||||
String.format("Realm %s cannot be processed", realm));
|
||||
}
|
||||
}
|
||||
}
|
39
src/main/java/com/rbkmoney/anapi/v2/util/ConverterUtil.java
Normal file
39
src/main/java/com/rbkmoney/anapi/v2/util/ConverterUtil.java
Normal file
@ -0,0 +1,39 @@
|
||||
package com.rbkmoney.anapi.v2.util;
|
||||
|
||||
import com.rbkmoney.geck.common.util.TypeUtil;
|
||||
import com.rbkmoney.magista.CommonSearchQueryParams;
|
||||
import lombok.experimental.UtilityClass;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import java.time.OffsetDateTime;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
@UtilityClass
|
||||
public class ConverterUtil {
|
||||
|
||||
public static List<String> merge(@Nullable String id, @Nullable List<String> ids) {
|
||||
List<String> identifiers = new ArrayList<>();
|
||||
if (id != null) {
|
||||
identifiers.add(id);
|
||||
}
|
||||
|
||||
if (ids != null && !ids.isEmpty()) {
|
||||
identifiers.addAll(ids);
|
||||
}
|
||||
return identifiers;
|
||||
}
|
||||
|
||||
public static CommonSearchQueryParams fillCommonParams(OffsetDateTime fromTime, OffsetDateTime toTime,
|
||||
Integer limit,
|
||||
String partyId, List<String> shopIDs,
|
||||
String continuationToken) {
|
||||
return new CommonSearchQueryParams()
|
||||
.setContinuationToken(continuationToken)
|
||||
.setFromTime(TypeUtil.temporalToString(fromTime.toLocalDateTime()))
|
||||
.setToTime(TypeUtil.temporalToString(toTime.toLocalDateTime()))
|
||||
.setLimit(limit)
|
||||
.setPartyId(partyId)
|
||||
.setShopIds(shopIDs);
|
||||
}
|
||||
}
|
111
src/main/java/com/rbkmoney/anapi/v2/util/DeadlineUtil.java
Normal file
111
src/main/java/com/rbkmoney/anapi/v2/util/DeadlineUtil.java
Normal file
@ -0,0 +1,111 @@
|
||||
package com.rbkmoney.anapi.v2.util;
|
||||
|
||||
import com.rbkmoney.anapi.v2.exception.DeadlineException;
|
||||
import lombok.experimental.UtilityClass;
|
||||
|
||||
import java.time.Instant;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
@UtilityClass
|
||||
@SuppressWarnings("ParameterName")
|
||||
public class DeadlineUtil {
|
||||
|
||||
public static void checkDeadline(String xRequestDeadline, String xRequestId) {
|
||||
if (xRequestDeadline == null) {
|
||||
return;
|
||||
}
|
||||
if (containsRelativeValues(xRequestDeadline, xRequestId)) {
|
||||
return;
|
||||
}
|
||||
try {
|
||||
Instant instant = Instant.parse(xRequestDeadline);
|
||||
|
||||
if (Instant.now().isAfter(instant)) {
|
||||
throw new DeadlineException(String.format("Deadline has expired, xRequestId=%s ", xRequestId));
|
||||
}
|
||||
} catch (Exception ex) {
|
||||
throw new DeadlineException(
|
||||
String.format("Deadline has invalid 'Instant' format, xRequestId=%s ", xRequestId));
|
||||
}
|
||||
}
|
||||
|
||||
public static boolean containsRelativeValues(String xRequestDeadline, String xRequestId) {
|
||||
return (extractMinutes(xRequestDeadline, xRequestId) + extractSeconds(xRequestDeadline, xRequestId) +
|
||||
extractMilliseconds(xRequestDeadline, xRequestId)) > 0;
|
||||
}
|
||||
|
||||
public static Long extractMinutes(String xRequestDeadline, String xRequestId) {
|
||||
String format = "minutes";
|
||||
|
||||
checkNegativeValues(xRequestDeadline, xRequestId, "([-][0-9]+([.][0-9]+)?(?!ms)[m])", format);
|
||||
|
||||
Double minutes = extractValue(xRequestDeadline, "([0-9]+([.][0-9]+)?(?!ms)[m])", xRequestId, format);
|
||||
|
||||
return Optional.ofNullable(minutes).map(min -> min * 60000.0).map(Double::longValue).orElse(0L);
|
||||
}
|
||||
|
||||
public static Long extractSeconds(String xRequestDeadline, String xRequestId) {
|
||||
String format = "seconds";
|
||||
|
||||
checkNegativeValues(xRequestDeadline, xRequestId, "([-][0-9]+([.][0-9]+)?[s])", format);
|
||||
|
||||
Double seconds = extractValue(xRequestDeadline, "([0-9]+([.][0-9]+)?[s])", xRequestId, format);
|
||||
|
||||
return Optional.ofNullable(seconds).map(s -> s * 1000.0).map(Double::longValue).orElse(0L);
|
||||
}
|
||||
|
||||
public static Long extractMilliseconds(String xRequestDeadline, String xRequestId) {
|
||||
String format = "milliseconds";
|
||||
|
||||
checkNegativeValues(xRequestDeadline, xRequestId, "([-][0-9]+([.][0-9]+)?[m][s])", format);
|
||||
|
||||
Double milliseconds = extractValue(xRequestDeadline, "([0-9]+([.][0-9]+)?[m][s])", xRequestId, format);
|
||||
|
||||
if (milliseconds != null && Math.ceil(milliseconds % 1) > 0) {
|
||||
throw new DeadlineException(
|
||||
String.format("Deadline 'milliseconds' parameter can have only integer value, xRequestId=%s ",
|
||||
xRequestId));
|
||||
}
|
||||
|
||||
return Optional.ofNullable(milliseconds).map(Double::longValue).orElse(0L);
|
||||
}
|
||||
|
||||
private static void checkNegativeValues(String xRequestDeadline, String xRequestId, String regex, String format) {
|
||||
if (!match(regex, xRequestDeadline).isEmpty()) {
|
||||
throw new DeadlineException(
|
||||
String.format("Deadline '%s' parameter has negative value, xRequestId=%s ", format, xRequestId));
|
||||
}
|
||||
}
|
||||
|
||||
private static Double extractValue(String xRequestDeadline, String formatRegex, String xRequestId, String format) {
|
||||
String numberRegex = "([0-9]+([.][0-9]+)?)";
|
||||
|
||||
List<String> doubles = new ArrayList<>();
|
||||
for (String string : match(formatRegex, xRequestDeadline)) {
|
||||
doubles.addAll(match(numberRegex, string));
|
||||
}
|
||||
if (doubles.size() > 1) {
|
||||
throw new DeadlineException(
|
||||
String.format("Deadline '%s' parameter has a few relative value, xRequestId=%s ", format,
|
||||
xRequestId));
|
||||
}
|
||||
if (doubles.isEmpty()) {
|
||||
return null;
|
||||
}
|
||||
return Double.valueOf(doubles.get(0));
|
||||
}
|
||||
|
||||
private static List<String> match(String regex, String data) {
|
||||
Pattern pattern = Pattern.compile(regex);
|
||||
Matcher matcher = pattern.matcher(data);
|
||||
List<String> strings = new ArrayList<>();
|
||||
while (matcher.find()) {
|
||||
strings.add(matcher.group());
|
||||
}
|
||||
return strings;
|
||||
}
|
||||
}
|
67
src/main/resources/application.yml
Normal file
67
src/main/resources/application.yml
Normal file
@ -0,0 +1,67 @@
|
||||
server:
|
||||
port: '@server.port@'
|
||||
|
||||
management:
|
||||
security:
|
||||
flag: false
|
||||
server:
|
||||
port: '@management.port@'
|
||||
metrics:
|
||||
export:
|
||||
statsd:
|
||||
flavor: etsy
|
||||
enabled: false
|
||||
prometheus:
|
||||
enabled: false
|
||||
endpoint:
|
||||
health:
|
||||
show-details: always
|
||||
metrics:
|
||||
enabled: true
|
||||
prometheus:
|
||||
enabled: true
|
||||
endpoints:
|
||||
web:
|
||||
exposure:
|
||||
include: health,info,prometheus
|
||||
|
||||
service:
|
||||
magista:
|
||||
url: http://localhost:8022/change_it
|
||||
networkTimeout: 5000
|
||||
vortigon:
|
||||
url: http://localhost:8022/change_it
|
||||
networkTimeout: 5000
|
||||
orgManagement:
|
||||
url: http://localhost:8022/change_it
|
||||
networkTimeout: 5000
|
||||
bouncer:
|
||||
url: http://localhost:8022/change_it
|
||||
networkTimeout: 10000
|
||||
context-fragment-id: anapi
|
||||
deployment-id: production
|
||||
auth-method: SessionToken
|
||||
realm: external
|
||||
rule-set-id: change_it
|
||||
auth:
|
||||
enabled: false
|
||||
|
||||
spring:
|
||||
application:
|
||||
name: '@project.name@'
|
||||
output:
|
||||
ansi:
|
||||
enabled: always
|
||||
info:
|
||||
version: '@project.version@'
|
||||
stage: dev
|
||||
|
||||
keycloak:
|
||||
realm: internal
|
||||
auth-server-url: http://keycloak:8080/auth/
|
||||
resource: common-api
|
||||
not-before: 0
|
||||
ssl-required: none
|
||||
realm-public-key:
|
||||
|
||||
auth.enabled: true
|
153
src/test/java/com/rbkmoney/anapi/v2/SearchChargebacksTest.java
Normal file
153
src/test/java/com/rbkmoney/anapi/v2/SearchChargebacksTest.java
Normal file
@ -0,0 +1,153 @@
|
||||
package com.rbkmoney.anapi.v2;
|
||||
|
||||
import com.rbkmoney.anapi.v2.config.AbstractKeycloakOpenIdAsWiremockConfig;
|
||||
import com.rbkmoney.anapi.v2.testutil.MagistaUtil;
|
||||
import com.rbkmoney.anapi.v2.testutil.OpenApiUtil;
|
||||
import com.rbkmoney.bouncer.decisions.ArbiterSrv;
|
||||
import com.rbkmoney.damsel.vortigon.VortigonServiceSrv;
|
||||
import com.rbkmoney.magista.MerchantStatisticsServiceSrv;
|
||||
import com.rbkmoney.openapi.anapi_v2.model.DefaultLogicError;
|
||||
import com.rbkmoney.orgmanagement.AuthContextProviderSrv;
|
||||
import lombok.SneakyThrows;
|
||||
import org.apache.thrift.TException;
|
||||
import org.junit.jupiter.api.AfterEach;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.mockito.MockitoAnnotations;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.test.mock.mockito.MockBean;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.test.web.servlet.MockMvc;
|
||||
import org.springframework.util.MultiValueMap;
|
||||
|
||||
import java.time.Instant;
|
||||
import java.time.temporal.ChronoUnit;
|
||||
import java.util.List;
|
||||
|
||||
import static com.rbkmoney.anapi.v2.testutil.MagistaUtil.createContextFragment;
|
||||
import static com.rbkmoney.anapi.v2.testutil.MagistaUtil.createJudgementAllowed;
|
||||
import static java.util.UUID.randomUUID;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.Mockito.*;
|
||||
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
|
||||
import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print;
|
||||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath;
|
||||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
|
||||
|
||||
|
||||
class SearchChargebacksTest extends AbstractKeycloakOpenIdAsWiremockConfig {
|
||||
|
||||
@MockBean
|
||||
public MerchantStatisticsServiceSrv.Iface magistaClient;
|
||||
@MockBean
|
||||
public VortigonServiceSrv.Iface vortigonClient;
|
||||
@MockBean
|
||||
public AuthContextProviderSrv.Iface orgMgmtClient;
|
||||
@MockBean
|
||||
public ArbiterSrv.Iface bouncerClient;
|
||||
|
||||
@Autowired
|
||||
private MockMvc mvc;
|
||||
|
||||
private AutoCloseable mocks;
|
||||
|
||||
private Object[] preparedMocks;
|
||||
|
||||
@BeforeEach
|
||||
public void init() {
|
||||
mocks = MockitoAnnotations.openMocks(this);
|
||||
preparedMocks = new Object[] {magistaClient, vortigonClient, orgMgmtClient, bouncerClient};
|
||||
}
|
||||
|
||||
@AfterEach
|
||||
public void clean() throws Exception {
|
||||
verifyNoMoreInteractions(preparedMocks);
|
||||
mocks.close();
|
||||
}
|
||||
|
||||
@Test
|
||||
@SneakyThrows
|
||||
void searchChargebacksRequiredParamsRequestSuccess() {
|
||||
when(vortigonClient.getShopsIds(any(), any())).thenReturn(List.of("1", "2", "3"));
|
||||
when(orgMgmtClient.getUserContext(any())).thenReturn(createContextFragment());
|
||||
when(bouncerClient.judge(any(), any())).thenReturn(createJudgementAllowed());
|
||||
when(magistaClient.searchChargebacks(any())).thenReturn(MagistaUtil.createSearchChargebackRequiredResponse());
|
||||
mvc.perform(get("/chargebacks")
|
||||
.header("Authorization", "Bearer " + generateInvoicesReadJwt())
|
||||
.header("X-Request-ID", randomUUID())
|
||||
.header("X-Request-Deadline", Instant.now().plus(1, ChronoUnit.DAYS).toString())
|
||||
.params(OpenApiUtil.getSearchRequiredParams())
|
||||
.contentType(MediaType.APPLICATION_JSON_UTF8)
|
||||
.content(""))
|
||||
.andDo(print())
|
||||
.andExpect(status().is2xxSuccessful())
|
||||
.andExpect(jsonPath("$").exists());
|
||||
verify(vortigonClient, times(1)).getShopsIds(any(), any());
|
||||
verify(orgMgmtClient, times(1)).getUserContext(any());
|
||||
verify(bouncerClient, times(1)).judge(any(), any());
|
||||
verify(magistaClient, times(1)).searchChargebacks(any());
|
||||
}
|
||||
|
||||
@Test
|
||||
@SneakyThrows
|
||||
void searchChargebacksAllParamsRequestSuccess() {
|
||||
when(vortigonClient.getShopsIds(any(), any())).thenReturn(List.of("1", "2", "3"));
|
||||
when(orgMgmtClient.getUserContext(any())).thenReturn(createContextFragment());
|
||||
when(bouncerClient.judge(any(), any())).thenReturn(createJudgementAllowed());
|
||||
when(magistaClient.searchChargebacks(any())).thenReturn(MagistaUtil.createSearchChargebackAllResponse());
|
||||
mvc.perform(get("/chargebacks")
|
||||
.header("Authorization", "Bearer " + generateInvoicesReadJwt())
|
||||
.header("X-Request-ID", randomUUID())
|
||||
.header("X-Request-Deadline", Instant.now().plus(1, ChronoUnit.DAYS).toString())
|
||||
.params(OpenApiUtil.getSearchChargebackAllParams())
|
||||
.contentType(MediaType.APPLICATION_JSON_UTF8)
|
||||
.content(""))
|
||||
.andDo(print())
|
||||
.andExpect(status().is2xxSuccessful())
|
||||
.andExpect(jsonPath("$").exists());
|
||||
verify(vortigonClient, times(1)).getShopsIds(any(), any());
|
||||
verify(orgMgmtClient, times(1)).getUserContext(any());
|
||||
verify(bouncerClient, times(1)).judge(any(), any());
|
||||
verify(magistaClient, times(1)).searchChargebacks(any());
|
||||
}
|
||||
|
||||
@Test
|
||||
@SneakyThrows
|
||||
void searchChargebacksRequestInvalid() {
|
||||
MultiValueMap<String, String> params = OpenApiUtil.getSearchRequiredParams();
|
||||
params.remove("partyID");
|
||||
mvc.perform(get("/chargebacks")
|
||||
.header("Authorization", "Bearer " + generateInvoicesReadJwt())
|
||||
.header("X-Request-ID", randomUUID())
|
||||
.header("X-Request-Deadline", Instant.now().plus(1, ChronoUnit.DAYS).toString())
|
||||
.params(params)
|
||||
.contentType(MediaType.APPLICATION_JSON_UTF8)
|
||||
.content(""))
|
||||
.andDo(print())
|
||||
.andExpect(status().is4xxClientError())
|
||||
.andExpect(jsonPath("$.code").value(DefaultLogicError.CodeEnum.INVALIDREQUEST.getValue()))
|
||||
.andExpect(jsonPath("$.message").isNotEmpty());
|
||||
}
|
||||
|
||||
@Test
|
||||
@SneakyThrows
|
||||
void searchChargebacksRequestMagistaUnavailable() {
|
||||
when(vortigonClient.getShopsIds(any(), any())).thenReturn(List.of("1", "2", "3"));
|
||||
when(orgMgmtClient.getUserContext(any())).thenReturn(createContextFragment());
|
||||
when(bouncerClient.judge(any(), any())).thenReturn(createJudgementAllowed());
|
||||
when(magistaClient.searchPayments(any())).thenThrow(TException.class);
|
||||
mvc.perform(get("/chargebacks")
|
||||
.header("Authorization", "Bearer " + generateInvoicesReadJwt())
|
||||
.header("X-Request-ID", randomUUID())
|
||||
.header("X-Request-Deadline", Instant.now().plus(1, ChronoUnit.DAYS).toString())
|
||||
.params(OpenApiUtil.getSearchRequiredParams())
|
||||
.contentType(MediaType.APPLICATION_JSON_UTF8)
|
||||
.content(""))
|
||||
.andDo(print())
|
||||
.andExpect(status().is5xxServerError());
|
||||
verify(vortigonClient, times(1)).getShopsIds(any(), any());
|
||||
verify(orgMgmtClient, times(1)).getUserContext(any());
|
||||
verify(bouncerClient, times(1)).judge(any(), any());
|
||||
verify(magistaClient, times(1)).searchChargebacks(any());
|
||||
}
|
||||
}
|
152
src/test/java/com/rbkmoney/anapi/v2/SearchInvoicesTest.java
Normal file
152
src/test/java/com/rbkmoney/anapi/v2/SearchInvoicesTest.java
Normal file
@ -0,0 +1,152 @@
|
||||
package com.rbkmoney.anapi.v2;
|
||||
|
||||
import com.rbkmoney.anapi.v2.config.AbstractKeycloakOpenIdAsWiremockConfig;
|
||||
import com.rbkmoney.anapi.v2.testutil.MagistaUtil;
|
||||
import com.rbkmoney.anapi.v2.testutil.OpenApiUtil;
|
||||
import com.rbkmoney.bouncer.decisions.ArbiterSrv;
|
||||
import com.rbkmoney.damsel.vortigon.VortigonServiceSrv;
|
||||
import com.rbkmoney.magista.MerchantStatisticsServiceSrv;
|
||||
import com.rbkmoney.openapi.anapi_v2.model.DefaultLogicError;
|
||||
import com.rbkmoney.orgmanagement.AuthContextProviderSrv;
|
||||
import lombok.SneakyThrows;
|
||||
import org.apache.thrift.TException;
|
||||
import org.junit.jupiter.api.AfterEach;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.mockito.MockitoAnnotations;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.test.mock.mockito.MockBean;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.test.web.servlet.MockMvc;
|
||||
import org.springframework.util.MultiValueMap;
|
||||
|
||||
import java.time.Instant;
|
||||
import java.time.temporal.ChronoUnit;
|
||||
import java.util.List;
|
||||
|
||||
import static com.rbkmoney.anapi.v2.testutil.MagistaUtil.createContextFragment;
|
||||
import static com.rbkmoney.anapi.v2.testutil.MagistaUtil.createJudgementAllowed;
|
||||
import static java.util.UUID.randomUUID;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.Mockito.*;
|
||||
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
|
||||
import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print;
|
||||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath;
|
||||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
|
||||
|
||||
class SearchInvoicesTest extends AbstractKeycloakOpenIdAsWiremockConfig {
|
||||
|
||||
@MockBean
|
||||
public MerchantStatisticsServiceSrv.Iface magistaClient;
|
||||
@MockBean
|
||||
public VortigonServiceSrv.Iface vortigonClient;
|
||||
@MockBean
|
||||
public AuthContextProviderSrv.Iface orgMgmtClient;
|
||||
@MockBean
|
||||
public ArbiterSrv.Iface bouncerClient;
|
||||
|
||||
@Autowired
|
||||
private MockMvc mvc;
|
||||
|
||||
private AutoCloseable mocks;
|
||||
|
||||
private Object[] preparedMocks;
|
||||
|
||||
@BeforeEach
|
||||
public void init() {
|
||||
mocks = MockitoAnnotations.openMocks(this);
|
||||
preparedMocks = new Object[] {magistaClient, vortigonClient, orgMgmtClient, bouncerClient};
|
||||
}
|
||||
|
||||
@AfterEach
|
||||
public void clean() throws Exception {
|
||||
verifyNoMoreInteractions(preparedMocks);
|
||||
mocks.close();
|
||||
}
|
||||
|
||||
@Test
|
||||
@SneakyThrows
|
||||
void searchInvoicesRequiredParamsRequestSuccess() {
|
||||
when(vortigonClient.getShopsIds(any(), any())).thenReturn(List.of("1", "2", "3"));
|
||||
when(orgMgmtClient.getUserContext(any())).thenReturn(createContextFragment());
|
||||
when(bouncerClient.judge(any(), any())).thenReturn(createJudgementAllowed());
|
||||
when(magistaClient.searchInvoices(any())).thenReturn(MagistaUtil.createSearchInvoiceRequiredResponse());
|
||||
mvc.perform(get("/invoices")
|
||||
.header("Authorization", "Bearer " + generateInvoicesReadJwt())
|
||||
.header("X-Request-ID", randomUUID())
|
||||
.header("X-Request-Deadline", Instant.now().plus(1, ChronoUnit.DAYS).toString())
|
||||
.params(OpenApiUtil.getSearchRequiredParams())
|
||||
.contentType(MediaType.APPLICATION_JSON_UTF8)
|
||||
.content(""))
|
||||
.andDo(print())
|
||||
.andExpect(status().is2xxSuccessful())
|
||||
.andExpect(jsonPath("$").exists());
|
||||
verify(vortigonClient, times(1)).getShopsIds(any(), any());
|
||||
verify(orgMgmtClient, times(1)).getUserContext(any());
|
||||
verify(bouncerClient, times(1)).judge(any(), any());
|
||||
verify(magistaClient, times(1)).searchInvoices(any());
|
||||
}
|
||||
|
||||
@Test
|
||||
@SneakyThrows
|
||||
void searchInvoicesAllParamsRequestSuccess() {
|
||||
when(vortigonClient.getShopsIds(any(), any())).thenReturn(List.of("1", "2", "3"));
|
||||
when(orgMgmtClient.getUserContext(any())).thenReturn(createContextFragment());
|
||||
when(bouncerClient.judge(any(), any())).thenReturn(createJudgementAllowed());
|
||||
when(magistaClient.searchInvoices(any())).thenReturn(MagistaUtil.createSearchInvoiceAllResponse());
|
||||
mvc.perform(get("/invoices")
|
||||
.header("Authorization", "Bearer " + generateInvoicesReadJwt())
|
||||
.header("X-Request-ID", randomUUID())
|
||||
.header("X-Request-Deadline", Instant.now().plus(1, ChronoUnit.DAYS).toString())
|
||||
.params(OpenApiUtil.getSearchInvoiceAllParams())
|
||||
.contentType(MediaType.APPLICATION_JSON_UTF8)
|
||||
.content(""))
|
||||
.andDo(print())
|
||||
.andExpect(status().is2xxSuccessful())
|
||||
.andExpect(jsonPath("$").exists());
|
||||
verify(vortigonClient, times(1)).getShopsIds(any(), any());
|
||||
verify(orgMgmtClient, times(1)).getUserContext(any());
|
||||
verify(bouncerClient, times(1)).judge(any(), any());
|
||||
verify(magistaClient, times(1)).searchInvoices(any());
|
||||
}
|
||||
|
||||
@Test
|
||||
@SneakyThrows
|
||||
void searchInvoicesRequestInvalid() {
|
||||
MultiValueMap<String, String> params = OpenApiUtil.getSearchRequiredParams();
|
||||
params.remove("partyID");
|
||||
mvc.perform(get("/invoices")
|
||||
.header("Authorization", "Bearer " + generateInvoicesReadJwt())
|
||||
.header("X-Request-ID", randomUUID())
|
||||
.header("X-Request-Deadline", Instant.now().plus(1, ChronoUnit.DAYS).toString())
|
||||
.params(params)
|
||||
.contentType(MediaType.APPLICATION_JSON_UTF8)
|
||||
.content(""))
|
||||
.andDo(print())
|
||||
.andExpect(status().is4xxClientError())
|
||||
.andExpect(jsonPath("$.code").value(DefaultLogicError.CodeEnum.INVALIDREQUEST.getValue()))
|
||||
.andExpect(jsonPath("$.message").isNotEmpty());
|
||||
}
|
||||
|
||||
@Test
|
||||
@SneakyThrows
|
||||
void searchInvoicesRequestMagistaUnavailable() {
|
||||
when(vortigonClient.getShopsIds(any(), any())).thenReturn(List.of("1", "2", "3"));
|
||||
when(orgMgmtClient.getUserContext(any())).thenReturn(createContextFragment());
|
||||
when(bouncerClient.judge(any(), any())).thenReturn(createJudgementAllowed());
|
||||
when(magistaClient.searchInvoices(any())).thenThrow(TException.class);
|
||||
mvc.perform(get("/invoices")
|
||||
.header("Authorization", "Bearer " + generateInvoicesReadJwt())
|
||||
.header("X-Request-ID", randomUUID())
|
||||
.header("X-Request-Deadline", Instant.now().plus(1, ChronoUnit.DAYS).toString())
|
||||
.params(OpenApiUtil.getSearchRequiredParams())
|
||||
.contentType(MediaType.APPLICATION_JSON_UTF8)
|
||||
.content(""))
|
||||
.andDo(print())
|
||||
.andExpect(status().is5xxServerError());
|
||||
verify(vortigonClient, times(1)).getShopsIds(any(), any());
|
||||
verify(orgMgmtClient, times(1)).getUserContext(any());
|
||||
verify(bouncerClient, times(1)).judge(any(), any());
|
||||
verify(magistaClient, times(1)).searchInvoices(any());
|
||||
}
|
||||
}
|
153
src/test/java/com/rbkmoney/anapi/v2/SearchPaymentsTest.java
Normal file
153
src/test/java/com/rbkmoney/anapi/v2/SearchPaymentsTest.java
Normal file
@ -0,0 +1,153 @@
|
||||
package com.rbkmoney.anapi.v2;
|
||||
|
||||
import com.rbkmoney.anapi.v2.config.AbstractKeycloakOpenIdAsWiremockConfig;
|
||||
import com.rbkmoney.anapi.v2.testutil.MagistaUtil;
|
||||
import com.rbkmoney.anapi.v2.testutil.OpenApiUtil;
|
||||
import com.rbkmoney.bouncer.decisions.ArbiterSrv;
|
||||
import com.rbkmoney.damsel.vortigon.VortigonServiceSrv;
|
||||
import com.rbkmoney.magista.MerchantStatisticsServiceSrv;
|
||||
import com.rbkmoney.openapi.anapi_v2.model.DefaultLogicError;
|
||||
import com.rbkmoney.orgmanagement.AuthContextProviderSrv;
|
||||
import lombok.SneakyThrows;
|
||||
import org.apache.thrift.TException;
|
||||
import org.junit.jupiter.api.AfterEach;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.mockito.MockitoAnnotations;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.test.mock.mockito.MockBean;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.test.web.servlet.MockMvc;
|
||||
import org.springframework.util.MultiValueMap;
|
||||
|
||||
import java.time.Instant;
|
||||
import java.time.temporal.ChronoUnit;
|
||||
import java.util.List;
|
||||
|
||||
import static com.rbkmoney.anapi.v2.testutil.MagistaUtil.createContextFragment;
|
||||
import static com.rbkmoney.anapi.v2.testutil.MagistaUtil.createJudgementAllowed;
|
||||
import static java.util.UUID.randomUUID;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.Mockito.*;
|
||||
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
|
||||
import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print;
|
||||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath;
|
||||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
|
||||
|
||||
|
||||
class SearchPaymentsTest extends AbstractKeycloakOpenIdAsWiremockConfig {
|
||||
|
||||
@MockBean
|
||||
public MerchantStatisticsServiceSrv.Iface magistaClient;
|
||||
@MockBean
|
||||
public VortigonServiceSrv.Iface vortigonClient;
|
||||
@MockBean
|
||||
public AuthContextProviderSrv.Iface orgMgmtClient;
|
||||
@MockBean
|
||||
public ArbiterSrv.Iface bouncerClient;
|
||||
|
||||
@Autowired
|
||||
private MockMvc mvc;
|
||||
|
||||
private AutoCloseable mocks;
|
||||
|
||||
private Object[] preparedMocks;
|
||||
|
||||
@BeforeEach
|
||||
public void init() {
|
||||
mocks = MockitoAnnotations.openMocks(this);
|
||||
preparedMocks = new Object[] {magistaClient, vortigonClient, orgMgmtClient, bouncerClient};
|
||||
}
|
||||
|
||||
@AfterEach
|
||||
public void clean() throws Exception {
|
||||
verifyNoMoreInteractions(preparedMocks);
|
||||
mocks.close();
|
||||
}
|
||||
|
||||
@Test
|
||||
@SneakyThrows
|
||||
void searchPaymentsRequiredParamsRequestSuccess() {
|
||||
when(vortigonClient.getShopsIds(any(), any())).thenReturn(List.of("1", "2", "3"));
|
||||
when(orgMgmtClient.getUserContext(any())).thenReturn(createContextFragment());
|
||||
when(bouncerClient.judge(any(), any())).thenReturn(createJudgementAllowed());
|
||||
when(magistaClient.searchPayments(any())).thenReturn(MagistaUtil.createSearchPaymentRequiredResponse());
|
||||
mvc.perform(get("/payments")
|
||||
.header("Authorization", "Bearer " + generateInvoicesReadJwt())
|
||||
.header("X-Request-ID", randomUUID())
|
||||
.header("X-Request-Deadline", Instant.now().plus(1, ChronoUnit.DAYS).toString())
|
||||
.params(OpenApiUtil.getSearchRequiredParams())
|
||||
.contentType(MediaType.APPLICATION_JSON_UTF8)
|
||||
.content(""))
|
||||
.andDo(print())
|
||||
.andExpect(status().is2xxSuccessful())
|
||||
.andExpect(jsonPath("$").exists());
|
||||
verify(vortigonClient, times(1)).getShopsIds(any(), any());
|
||||
verify(orgMgmtClient, times(1)).getUserContext(any());
|
||||
verify(bouncerClient, times(1)).judge(any(), any());
|
||||
verify(magistaClient, times(1)).searchPayments(any());
|
||||
}
|
||||
|
||||
@Test
|
||||
@SneakyThrows
|
||||
void searchPaymentsAllParamsRequestSuccess() {
|
||||
when(vortigonClient.getShopsIds(any(), any())).thenReturn(List.of("1", "2", "3"));
|
||||
when(orgMgmtClient.getUserContext(any())).thenReturn(createContextFragment());
|
||||
when(bouncerClient.judge(any(), any())).thenReturn(createJudgementAllowed());
|
||||
when(magistaClient.searchPayments(any())).thenReturn(MagistaUtil.createSearchPaymentAllResponse());
|
||||
mvc.perform(get("/payments")
|
||||
.header("Authorization", "Bearer " + generateInvoicesReadJwt())
|
||||
.header("X-Request-ID", randomUUID())
|
||||
.header("X-Request-Deadline", Instant.now().plus(1, ChronoUnit.DAYS).toString())
|
||||
.params(OpenApiUtil.getSearchPaymentAllParams())
|
||||
.contentType(MediaType.APPLICATION_JSON_UTF8)
|
||||
.content(""))
|
||||
.andDo(print())
|
||||
.andExpect(status().is2xxSuccessful())
|
||||
.andExpect(jsonPath("$").exists());
|
||||
verify(vortigonClient, times(1)).getShopsIds(any(), any());
|
||||
verify(orgMgmtClient, times(1)).getUserContext(any());
|
||||
verify(bouncerClient, times(1)).judge(any(), any());
|
||||
verify(magistaClient, times(1)).searchPayments(any());
|
||||
}
|
||||
|
||||
@Test
|
||||
@SneakyThrows
|
||||
void searchPaymentsRequestInvalid() {
|
||||
MultiValueMap<String, String> params = OpenApiUtil.getSearchRequiredParams();
|
||||
params.remove("partyID");
|
||||
mvc.perform(get("/payments")
|
||||
.header("Authorization", "Bearer " + generateInvoicesReadJwt())
|
||||
.header("X-Request-ID", randomUUID())
|
||||
.header("X-Request-Deadline", Instant.now().plus(1, ChronoUnit.DAYS).toString())
|
||||
.params(params)
|
||||
.contentType(MediaType.APPLICATION_JSON_UTF8)
|
||||
.content(""))
|
||||
.andDo(print())
|
||||
.andExpect(status().is4xxClientError())
|
||||
.andExpect(jsonPath("$.code").value(DefaultLogicError.CodeEnum.INVALIDREQUEST.getValue()))
|
||||
.andExpect(jsonPath("$.message").isNotEmpty());
|
||||
}
|
||||
|
||||
@Test
|
||||
@SneakyThrows
|
||||
void searchPaymentsRequestMagistaUnavailable() {
|
||||
when(vortigonClient.getShopsIds(any(), any())).thenReturn(List.of("1", "2", "3"));
|
||||
when(orgMgmtClient.getUserContext(any())).thenReturn(createContextFragment());
|
||||
when(bouncerClient.judge(any(), any())).thenReturn(createJudgementAllowed());
|
||||
when(magistaClient.searchPayments(any())).thenThrow(TException.class);
|
||||
mvc.perform(get("/payments")
|
||||
.header("Authorization", "Bearer " + generateInvoicesReadJwt())
|
||||
.header("X-Request-ID", randomUUID())
|
||||
.header("X-Request-Deadline", Instant.now().plus(1, ChronoUnit.DAYS).toString())
|
||||
.params(OpenApiUtil.getSearchRequiredParams())
|
||||
.contentType(MediaType.APPLICATION_JSON_UTF8)
|
||||
.content(""))
|
||||
.andDo(print())
|
||||
.andExpect(status().is5xxServerError());
|
||||
verify(vortigonClient, times(1)).getShopsIds(any(), any());
|
||||
verify(orgMgmtClient, times(1)).getUserContext(any());
|
||||
verify(bouncerClient, times(1)).judge(any(), any());
|
||||
verify(magistaClient, times(1)).searchPayments(any());
|
||||
}
|
||||
}
|
152
src/test/java/com/rbkmoney/anapi/v2/SearchPayoutsTest.java
Normal file
152
src/test/java/com/rbkmoney/anapi/v2/SearchPayoutsTest.java
Normal file
@ -0,0 +1,152 @@
|
||||
package com.rbkmoney.anapi.v2;
|
||||
|
||||
import com.rbkmoney.anapi.v2.config.AbstractKeycloakOpenIdAsWiremockConfig;
|
||||
import com.rbkmoney.anapi.v2.testutil.MagistaUtil;
|
||||
import com.rbkmoney.anapi.v2.testutil.OpenApiUtil;
|
||||
import com.rbkmoney.bouncer.decisions.ArbiterSrv;
|
||||
import com.rbkmoney.damsel.vortigon.VortigonServiceSrv;
|
||||
import com.rbkmoney.magista.MerchantStatisticsServiceSrv;
|
||||
import com.rbkmoney.openapi.anapi_v2.model.DefaultLogicError;
|
||||
import com.rbkmoney.orgmanagement.AuthContextProviderSrv;
|
||||
import lombok.SneakyThrows;
|
||||
import org.apache.thrift.TException;
|
||||
import org.junit.jupiter.api.AfterEach;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.mockito.MockitoAnnotations;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.test.mock.mockito.MockBean;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.test.web.servlet.MockMvc;
|
||||
import org.springframework.util.MultiValueMap;
|
||||
|
||||
import java.time.Instant;
|
||||
import java.time.temporal.ChronoUnit;
|
||||
import java.util.List;
|
||||
|
||||
import static com.rbkmoney.anapi.v2.testutil.MagistaUtil.createContextFragment;
|
||||
import static com.rbkmoney.anapi.v2.testutil.MagistaUtil.createJudgementAllowed;
|
||||
import static java.util.UUID.randomUUID;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.Mockito.*;
|
||||
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
|
||||
import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print;
|
||||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath;
|
||||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
|
||||
|
||||
class SearchPayoutsTest extends AbstractKeycloakOpenIdAsWiremockConfig {
|
||||
|
||||
@MockBean
|
||||
public MerchantStatisticsServiceSrv.Iface magistaClient;
|
||||
@MockBean
|
||||
public VortigonServiceSrv.Iface vortigonClient;
|
||||
@MockBean
|
||||
public AuthContextProviderSrv.Iface orgMgmtClient;
|
||||
@MockBean
|
||||
public ArbiterSrv.Iface bouncerClient;
|
||||
|
||||
@Autowired
|
||||
private MockMvc mvc;
|
||||
|
||||
private AutoCloseable mocks;
|
||||
|
||||
private Object[] preparedMocks;
|
||||
|
||||
@BeforeEach
|
||||
public void init() {
|
||||
mocks = MockitoAnnotations.openMocks(this);
|
||||
preparedMocks = new Object[] {magistaClient, vortigonClient, orgMgmtClient, bouncerClient};
|
||||
}
|
||||
|
||||
@AfterEach
|
||||
public void clean() throws Exception {
|
||||
verifyNoMoreInteractions(preparedMocks);
|
||||
mocks.close();
|
||||
}
|
||||
|
||||
@Test
|
||||
@SneakyThrows
|
||||
void searchPayoutsRequiredParamsRequestSuccess() {
|
||||
when(vortigonClient.getShopsIds(any(), any())).thenReturn(List.of("1", "2", "3"));
|
||||
when(orgMgmtClient.getUserContext(any())).thenReturn(createContextFragment());
|
||||
when(bouncerClient.judge(any(), any())).thenReturn(createJudgementAllowed());
|
||||
when(magistaClient.searchPayouts(any())).thenReturn(MagistaUtil.createSearchPayoutRequiredResponse());
|
||||
mvc.perform(get("/payouts")
|
||||
.header("Authorization", "Bearer " + generateInvoicesReadJwt())
|
||||
.header("X-Request-ID", randomUUID())
|
||||
.header("X-Request-Deadline", Instant.now().plus(1, ChronoUnit.DAYS).toString())
|
||||
.params(OpenApiUtil.getSearchRequiredParams())
|
||||
.contentType(MediaType.APPLICATION_JSON_UTF8)
|
||||
.content(""))
|
||||
.andDo(print())
|
||||
.andExpect(status().is2xxSuccessful())
|
||||
.andExpect(jsonPath("$").exists());
|
||||
verify(vortigonClient, times(1)).getShopsIds(any(), any());
|
||||
verify(orgMgmtClient, times(1)).getUserContext(any());
|
||||
verify(bouncerClient, times(1)).judge(any(), any());
|
||||
verify(magistaClient, times(1)).searchPayouts(any());
|
||||
}
|
||||
|
||||
@Test
|
||||
@SneakyThrows
|
||||
void searchPayoutsAllParamsRequestSuccess() {
|
||||
when(vortigonClient.getShopsIds(any(), any())).thenReturn(List.of("1", "2", "3"));
|
||||
when(orgMgmtClient.getUserContext(any())).thenReturn(createContextFragment());
|
||||
when(bouncerClient.judge(any(), any())).thenReturn(createJudgementAllowed());
|
||||
when(magistaClient.searchPayouts(any())).thenReturn(MagistaUtil.createSearchPayoutAllResponse());
|
||||
mvc.perform(get("/payouts")
|
||||
.header("Authorization", "Bearer " + generateInvoicesReadJwt())
|
||||
.header("X-Request-ID", randomUUID())
|
||||
.header("X-Request-Deadline", Instant.now().plus(1, ChronoUnit.DAYS).toString())
|
||||
.params(OpenApiUtil.getSearchPayoutAllParams())
|
||||
.contentType(MediaType.APPLICATION_JSON_UTF8)
|
||||
.content(""))
|
||||
.andDo(print())
|
||||
.andExpect(status().is2xxSuccessful())
|
||||
.andExpect(jsonPath("$").exists());
|
||||
verify(vortigonClient, times(1)).getShopsIds(any(), any());
|
||||
verify(orgMgmtClient, times(1)).getUserContext(any());
|
||||
verify(bouncerClient, times(1)).judge(any(), any());
|
||||
verify(magistaClient, times(1)).searchPayouts(any());
|
||||
}
|
||||
|
||||
@Test
|
||||
@SneakyThrows
|
||||
void searchPayoutsRequestInvalid() {
|
||||
MultiValueMap<String, String> params = OpenApiUtil.getSearchRequiredParams();
|
||||
params.remove("partyID");
|
||||
mvc.perform(get("/payouts")
|
||||
.header("Authorization", "Bearer " + generateInvoicesReadJwt())
|
||||
.header("X-Request-ID", randomUUID())
|
||||
.header("X-Request-Deadline", Instant.now().plus(1, ChronoUnit.DAYS).toString())
|
||||
.params(params)
|
||||
.contentType(MediaType.APPLICATION_JSON_UTF8)
|
||||
.content(""))
|
||||
.andDo(print())
|
||||
.andExpect(status().is4xxClientError())
|
||||
.andExpect(jsonPath("$.code").value(DefaultLogicError.CodeEnum.INVALIDREQUEST.getValue()))
|
||||
.andExpect(jsonPath("$.message").isNotEmpty());
|
||||
}
|
||||
|
||||
@Test
|
||||
@SneakyThrows
|
||||
void searchPayoutsRequestMagistaUnavailable() {
|
||||
when(vortigonClient.getShopsIds(any(), any())).thenReturn(List.of("1", "2", "3"));
|
||||
when(orgMgmtClient.getUserContext(any())).thenReturn(createContextFragment());
|
||||
when(bouncerClient.judge(any(), any())).thenReturn(createJudgementAllowed());
|
||||
when(magistaClient.searchPayouts(any())).thenThrow(TException.class);
|
||||
mvc.perform(get("/payouts")
|
||||
.header("Authorization", "Bearer " + generateInvoicesReadJwt())
|
||||
.header("X-Request-ID", randomUUID())
|
||||
.header("X-Request-Deadline", Instant.now().plus(1, ChronoUnit.DAYS).toString())
|
||||
.params(OpenApiUtil.getSearchRequiredParams())
|
||||
.contentType(MediaType.APPLICATION_JSON_UTF8)
|
||||
.content(""))
|
||||
.andDo(print())
|
||||
.andExpect(status().is5xxServerError());
|
||||
verify(vortigonClient, times(1)).getShopsIds(any(), any());
|
||||
verify(orgMgmtClient, times(1)).getUserContext(any());
|
||||
verify(bouncerClient, times(1)).judge(any(), any());
|
||||
verify(magistaClient, times(1)).searchPayouts(any());
|
||||
}
|
||||
}
|
152
src/test/java/com/rbkmoney/anapi/v2/SearchRefundsTest.java
Normal file
152
src/test/java/com/rbkmoney/anapi/v2/SearchRefundsTest.java
Normal file
@ -0,0 +1,152 @@
|
||||
package com.rbkmoney.anapi.v2;
|
||||
|
||||
import com.rbkmoney.anapi.v2.config.AbstractKeycloakOpenIdAsWiremockConfig;
|
||||
import com.rbkmoney.anapi.v2.testutil.MagistaUtil;
|
||||
import com.rbkmoney.anapi.v2.testutil.OpenApiUtil;
|
||||
import com.rbkmoney.bouncer.decisions.ArbiterSrv;
|
||||
import com.rbkmoney.damsel.vortigon.VortigonServiceSrv;
|
||||
import com.rbkmoney.magista.MerchantStatisticsServiceSrv;
|
||||
import com.rbkmoney.openapi.anapi_v2.model.DefaultLogicError;
|
||||
import com.rbkmoney.orgmanagement.AuthContextProviderSrv;
|
||||
import lombok.SneakyThrows;
|
||||
import org.apache.thrift.TException;
|
||||
import org.junit.jupiter.api.AfterEach;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.mockito.MockitoAnnotations;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.test.mock.mockito.MockBean;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.test.web.servlet.MockMvc;
|
||||
import org.springframework.util.MultiValueMap;
|
||||
|
||||
import java.time.Instant;
|
||||
import java.time.temporal.ChronoUnit;
|
||||
import java.util.List;
|
||||
|
||||
import static com.rbkmoney.anapi.v2.testutil.MagistaUtil.createContextFragment;
|
||||
import static com.rbkmoney.anapi.v2.testutil.MagistaUtil.createJudgementAllowed;
|
||||
import static java.util.UUID.randomUUID;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.Mockito.*;
|
||||
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
|
||||
import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print;
|
||||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath;
|
||||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
|
||||
|
||||
class SearchRefundsTest extends AbstractKeycloakOpenIdAsWiremockConfig {
|
||||
|
||||
@MockBean
|
||||
public MerchantStatisticsServiceSrv.Iface magistaClient;
|
||||
@MockBean
|
||||
public VortigonServiceSrv.Iface vortigonClient;
|
||||
@MockBean
|
||||
public AuthContextProviderSrv.Iface orgMgmtClient;
|
||||
@MockBean
|
||||
public ArbiterSrv.Iface bouncerClient;
|
||||
|
||||
@Autowired
|
||||
private MockMvc mvc;
|
||||
|
||||
private AutoCloseable mocks;
|
||||
|
||||
private Object[] preparedMocks;
|
||||
|
||||
@BeforeEach
|
||||
public void init() {
|
||||
mocks = MockitoAnnotations.openMocks(this);
|
||||
preparedMocks = new Object[] {magistaClient, vortigonClient, orgMgmtClient, bouncerClient};
|
||||
}
|
||||
|
||||
@AfterEach
|
||||
public void clean() throws Exception {
|
||||
verifyNoMoreInteractions(preparedMocks);
|
||||
mocks.close();
|
||||
}
|
||||
|
||||
@Test
|
||||
@SneakyThrows
|
||||
void searchRefundsRequiredParamsRequestSuccess() {
|
||||
when(vortigonClient.getShopsIds(any(), any())).thenReturn(List.of("1", "2", "3"));
|
||||
when(orgMgmtClient.getUserContext(any())).thenReturn(createContextFragment());
|
||||
when(bouncerClient.judge(any(), any())).thenReturn(createJudgementAllowed());
|
||||
when(magistaClient.searchRefunds(any())).thenReturn(MagistaUtil.createSearchRefundRequiredResponse());
|
||||
mvc.perform(get("/refunds")
|
||||
.header("Authorization", "Bearer " + generateInvoicesReadJwt())
|
||||
.header("X-Request-ID", randomUUID())
|
||||
.header("X-Request-Deadline", Instant.now().plus(1, ChronoUnit.DAYS).toString())
|
||||
.params(OpenApiUtil.getSearchRequiredParams())
|
||||
.contentType(MediaType.APPLICATION_JSON_UTF8)
|
||||
.content(""))
|
||||
.andDo(print())
|
||||
.andExpect(status().is2xxSuccessful())
|
||||
.andExpect(jsonPath("$").exists());
|
||||
verify(vortigonClient, times(1)).getShopsIds(any(), any());
|
||||
verify(orgMgmtClient, times(1)).getUserContext(any());
|
||||
verify(bouncerClient, times(1)).judge(any(), any());
|
||||
verify(magistaClient, times(1)).searchRefunds(any());
|
||||
}
|
||||
|
||||
@Test
|
||||
@SneakyThrows
|
||||
void searchRefundsAllParamsRequestSuccess() {
|
||||
when(vortigonClient.getShopsIds(any(), any())).thenReturn(List.of("1", "2", "3"));
|
||||
when(orgMgmtClient.getUserContext(any())).thenReturn(createContextFragment());
|
||||
when(bouncerClient.judge(any(), any())).thenReturn(createJudgementAllowed());
|
||||
when(magistaClient.searchRefunds(any())).thenReturn(MagistaUtil.createSearchRefundAllResponse());
|
||||
mvc.perform(get("/refunds")
|
||||
.header("Authorization", "Bearer " + generateInvoicesReadJwt())
|
||||
.header("X-Request-ID", randomUUID())
|
||||
.header("X-Request-Deadline", Instant.now().plus(1, ChronoUnit.DAYS).toString())
|
||||
.params(OpenApiUtil.getSearchRefundAllParams())
|
||||
.contentType(MediaType.APPLICATION_JSON_UTF8)
|
||||
.content(""))
|
||||
.andDo(print())
|
||||
.andExpect(status().is2xxSuccessful())
|
||||
.andExpect(jsonPath("$").exists());
|
||||
verify(vortigonClient, times(1)).getShopsIds(any(), any());
|
||||
verify(orgMgmtClient, times(1)).getUserContext(any());
|
||||
verify(bouncerClient, times(1)).judge(any(), any());
|
||||
verify(magistaClient, times(1)).searchRefunds(any());
|
||||
}
|
||||
|
||||
@Test
|
||||
@SneakyThrows
|
||||
void searchRefundsRequestInvalid() {
|
||||
MultiValueMap<String, String> params = OpenApiUtil.getSearchRequiredParams();
|
||||
params.remove("partyID");
|
||||
mvc.perform(get("/refunds")
|
||||
.header("Authorization", "Bearer " + generateInvoicesReadJwt())
|
||||
.header("X-Request-ID", randomUUID())
|
||||
.header("X-Request-Deadline", Instant.now().plus(1, ChronoUnit.DAYS).toString())
|
||||
.params(params)
|
||||
.contentType(MediaType.APPLICATION_JSON_UTF8)
|
||||
.content(""))
|
||||
.andDo(print())
|
||||
.andExpect(status().is4xxClientError())
|
||||
.andExpect(jsonPath("$.code").value(DefaultLogicError.CodeEnum.INVALIDREQUEST.getValue()))
|
||||
.andExpect(jsonPath("$.message").isNotEmpty());
|
||||
}
|
||||
|
||||
@Test
|
||||
@SneakyThrows
|
||||
void searchRefundsRequestMagistaUnavailable() {
|
||||
when(vortigonClient.getShopsIds(any(), any())).thenReturn(List.of("1", "2", "3"));
|
||||
when(orgMgmtClient.getUserContext(any())).thenReturn(createContextFragment());
|
||||
when(bouncerClient.judge(any(), any())).thenReturn(createJudgementAllowed());
|
||||
when(magistaClient.searchRefunds(any())).thenThrow(TException.class);
|
||||
mvc.perform(get("/refunds")
|
||||
.header("Authorization", "Bearer " + generateInvoicesReadJwt())
|
||||
.header("X-Request-ID", randomUUID())
|
||||
.header("X-Request-Deadline", Instant.now().plus(1, ChronoUnit.DAYS).toString())
|
||||
.params(OpenApiUtil.getSearchRequiredParams())
|
||||
.contentType(MediaType.APPLICATION_JSON_UTF8)
|
||||
.content(""))
|
||||
.andDo(print())
|
||||
.andExpect(status().is5xxServerError());
|
||||
verify(vortigonClient, times(1)).getShopsIds(any(), any());
|
||||
verify(orgMgmtClient, times(1)).getUserContext(any());
|
||||
verify(bouncerClient, times(1)).judge(any(), any());
|
||||
verify(magistaClient, times(1)).searchRefunds(any());
|
||||
}
|
||||
}
|
@ -0,0 +1,45 @@
|
||||
package com.rbkmoney.anapi.v2.auth;
|
||||
|
||||
import com.rbkmoney.anapi.v2.auth.utils.JwtTokenBuilder;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.support.PropertySourcesPlaceholderConfigurer;
|
||||
import org.springframework.core.io.ClassPathResource;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.security.*;
|
||||
import java.security.spec.InvalidKeySpecException;
|
||||
import java.security.spec.X509EncodedKeySpec;
|
||||
import java.util.Base64;
|
||||
import java.util.Properties;
|
||||
|
||||
@Configuration
|
||||
public class JwtTokenTestConfiguration {
|
||||
|
||||
@Bean
|
||||
public static PropertySourcesPlaceholderConfigurer properties(KeyPair keyPair)
|
||||
throws NoSuchAlgorithmException, InvalidKeySpecException, IOException {
|
||||
KeyFactory fact = KeyFactory.getInstance("RSA");
|
||||
X509EncodedKeySpec spec = fact.getKeySpec(keyPair.getPublic(), X509EncodedKeySpec.class);
|
||||
String publicKey = Base64.getEncoder().encodeToString(spec.getEncoded());
|
||||
PropertySourcesPlaceholderConfigurer pspc = new PropertySourcesPlaceholderConfigurer();
|
||||
Properties properties = new Properties();
|
||||
properties.load(new ClassPathResource("application.yml").getInputStream());
|
||||
properties.setProperty("keycloak.realm-public-key", publicKey);
|
||||
pspc.setProperties(properties);
|
||||
pspc.setLocalOverride(true);
|
||||
return pspc;
|
||||
}
|
||||
|
||||
@Bean
|
||||
public JwtTokenBuilder jwtTokenBuilder(KeyPair keyPair) {
|
||||
return new JwtTokenBuilder(keyPair.getPrivate());
|
||||
}
|
||||
|
||||
@Bean
|
||||
public KeyPair keyPair() throws GeneralSecurityException {
|
||||
KeyPairGenerator keyGen = KeyPairGenerator.getInstance("RSA");
|
||||
keyGen.initialize(2048);
|
||||
return keyGen.generateKeyPair();
|
||||
}
|
||||
}
|
@ -0,0 +1,18 @@
|
||||
package com.rbkmoney.anapi.v2.auth;
|
||||
|
||||
import com.rbkmoney.anapi.v2.auth.utils.JwtTokenBuilder;
|
||||
import com.rbkmoney.anapi.v2.auth.utils.KeycloakOpenIdStub;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
@Configuration
|
||||
public class KeycloakOpenIdTestConfiguration {
|
||||
|
||||
@Bean
|
||||
public KeycloakOpenIdStub keycloakOpenIdStub(@Value("${keycloak.auth-server-url}") String keycloakAuthServerUrl,
|
||||
@Value("${keycloak.realm}") String keycloakRealm,
|
||||
JwtTokenBuilder jwtTokenBuilder) {
|
||||
return new KeycloakOpenIdStub(keycloakAuthServerUrl, keycloakRealm, jwtTokenBuilder);
|
||||
}
|
||||
}
|
@ -0,0 +1,73 @@
|
||||
package com.rbkmoney.anapi.v2.auth.utils;
|
||||
|
||||
import io.jsonwebtoken.Jwts;
|
||||
import io.jsonwebtoken.SignatureAlgorithm;
|
||||
import org.json.JSONArray;
|
||||
import org.json.JSONException;
|
||||
import org.json.JSONObject;
|
||||
|
||||
import java.security.PrivateKey;
|
||||
import java.time.Instant;
|
||||
import java.util.UUID;
|
||||
|
||||
public class JwtTokenBuilder {
|
||||
|
||||
public static final String DEFAULT_USERNAME = "Darth Vader";
|
||||
|
||||
public static final String DEFAULT_EMAIL = "darkside-the-best@mail.com";
|
||||
|
||||
private final String userId;
|
||||
|
||||
private final String username;
|
||||
|
||||
private final String email;
|
||||
|
||||
private final PrivateKey privateKey;
|
||||
|
||||
public JwtTokenBuilder(PrivateKey privateKey) {
|
||||
this(UUID.randomUUID().toString(), DEFAULT_USERNAME, DEFAULT_EMAIL, privateKey);
|
||||
}
|
||||
|
||||
public JwtTokenBuilder(String userId, String username, String email, PrivateKey privateKey) {
|
||||
this.userId = userId;
|
||||
this.username = username;
|
||||
this.email = email;
|
||||
this.privateKey = privateKey;
|
||||
}
|
||||
|
||||
public String generateJwtWithRoles(String issuer, String... roles) {
|
||||
long iat = Instant.now().getEpochSecond();
|
||||
long exp = iat + 60 * 10;
|
||||
return generateJwtWithRoles(iat, exp, issuer, roles);
|
||||
}
|
||||
|
||||
public String generateJwtWithRoles(long iat, long exp, String issuer, String... roles) {
|
||||
String payload;
|
||||
try {
|
||||
payload = new JSONObject()
|
||||
.put("jti", UUID.randomUUID().toString())
|
||||
.put("exp", exp)
|
||||
.put("nbf", "0")
|
||||
.put("iat", iat)
|
||||
.put("iss", issuer)
|
||||
.put("aud", "private-api")
|
||||
.put("sub", userId)
|
||||
.put("typ", "Bearer")
|
||||
.put("azp", "private-api")
|
||||
.put("resource_access", new JSONObject()
|
||||
.put("common-api", new JSONObject()
|
||||
.put("roles", new JSONArray(roles))))
|
||||
.put("preferred_username", username)
|
||||
.put("email", email).toString();
|
||||
} catch (JSONException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
|
||||
String jwt = Jwts.builder()
|
||||
.setPayload(payload)
|
||||
.signWith(SignatureAlgorithm.RS256, privateKey)
|
||||
.compact();
|
||||
return jwt;
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,55 @@
|
||||
package com.rbkmoney.anapi.v2.auth.utils;
|
||||
|
||||
import static com.github.tomakehurst.wiremock.client.WireMock.*;
|
||||
|
||||
public class KeycloakOpenIdStub {
|
||||
|
||||
private final String keycloakRealm;
|
||||
private final String issuer;
|
||||
private final String openidConfig;
|
||||
private final JwtTokenBuilder jwtTokenBuilder;
|
||||
|
||||
public KeycloakOpenIdStub(String keycloakAuthServerUrl, String keycloakRealm, JwtTokenBuilder jwtTokenBuilder) {
|
||||
this.keycloakRealm = keycloakRealm;
|
||||
this.jwtTokenBuilder = jwtTokenBuilder;
|
||||
this.issuer = keycloakAuthServerUrl + "/realms/" + keycloakRealm;
|
||||
this.openidConfig = "{\n" +
|
||||
" \"issuer\": \"" + issuer + "\",\n" +
|
||||
" \"authorization_endpoint\": \"" + keycloakAuthServerUrl + "/realms/" + keycloakRealm +
|
||||
"/protocol/openid-connect/auth\",\n" +
|
||||
" \"token_endpoint\": \"" + keycloakAuthServerUrl + "/realms/" + keycloakRealm +
|
||||
"/protocol/openid-connect/token\",\n" +
|
||||
" \"token_introspection_endpoint\": \"" + keycloakAuthServerUrl + "/realms/" + keycloakRealm +
|
||||
"/protocol/openid-connect/token/introspect\",\n" +
|
||||
" \"userinfo_endpoint\": \"" + keycloakAuthServerUrl + "/realms/" + keycloakRealm +
|
||||
"/protocol/openid-connect/userinfo\",\n" +
|
||||
" \"end_session_endpoint\": \"" + keycloakAuthServerUrl + "/realms/" + keycloakRealm +
|
||||
"/protocol/openid-connect/logout\",\n" +
|
||||
" \"jwks_uri\": \"" + keycloakAuthServerUrl + "/realms/" + keycloakRealm +
|
||||
"/protocol/openid-connect/certs\",\n" +
|
||||
" \"check_session_iframe\": \"" + keycloakAuthServerUrl + "/realms/" + keycloakRealm +
|
||||
"/protocol/openid-connect/login-status-iframe.html\",\n" +
|
||||
" \"registration_endpoint\": \"" + keycloakAuthServerUrl + "/realms/" + keycloakRealm +
|
||||
"/clients-registrations/openid-connect\",\n" +
|
||||
" \"introspection_endpoint\": \"" + keycloakAuthServerUrl + "/realms/" + keycloakRealm +
|
||||
"/protocol/openid-connect/token/introspect\"\n" +
|
||||
"}";
|
||||
}
|
||||
|
||||
public void givenStub() {
|
||||
stubFor(get(urlEqualTo(String.format("/auth/realms/%s/.well-known/openid-configuration", keycloakRealm)))
|
||||
.willReturn(aResponse()
|
||||
.withHeader("Content-Type", "application/json")
|
||||
.withBody(openidConfig)
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
public String generateJwt(String... roles) {
|
||||
return jwtTokenBuilder.generateJwtWithRoles(issuer, roles);
|
||||
}
|
||||
|
||||
public String generateJwt(long iat, long exp, String... roles) {
|
||||
return jwtTokenBuilder.generateJwtWithRoles(iat, exp, issuer, roles);
|
||||
}
|
||||
}
|
@ -0,0 +1,35 @@
|
||||
package com.rbkmoney.anapi.v2.config;
|
||||
|
||||
import com.rbkmoney.anapi.v2.AnapiV2Application;
|
||||
import com.rbkmoney.anapi.v2.auth.utils.KeycloakOpenIdStub;
|
||||
import org.junit.jupiter.api.BeforeAll;
|
||||
import org.junit.jupiter.api.extension.ExtendWith;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
|
||||
import org.springframework.boot.test.context.SpringBootTest;
|
||||
import org.springframework.cloud.contract.wiremock.AutoConfigureWireMock;
|
||||
import org.springframework.test.context.junit.jupiter.SpringExtension;
|
||||
|
||||
@SpringBootTest(
|
||||
webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT,
|
||||
classes = {AnapiV2Application.class},
|
||||
properties = {
|
||||
"wiremock.server.baseUrl=http://localhost:${wiremock.server.port}",
|
||||
"keycloak.auth-server-url=${wiremock.server.baseUrl}/auth"})
|
||||
@AutoConfigureMockMvc
|
||||
@AutoConfigureWireMock(port = 0)
|
||||
@ExtendWith(SpringExtension.class)
|
||||
public abstract class AbstractKeycloakOpenIdAsWiremockConfig {
|
||||
|
||||
@Autowired
|
||||
private KeycloakOpenIdStub keycloakOpenIdStub;
|
||||
|
||||
@BeforeAll
|
||||
public static void setUp(@Autowired KeycloakOpenIdStub keycloakOpenIdStub) throws Exception {
|
||||
keycloakOpenIdStub.givenStub();
|
||||
}
|
||||
|
||||
protected String generateInvoicesReadJwt() {
|
||||
return keycloakOpenIdStub.generateJwt("invoices:read");
|
||||
}
|
||||
}
|
@ -0,0 +1,199 @@
|
||||
package com.rbkmoney.anapi.v2.controller;
|
||||
|
||||
import com.rbkmoney.anapi.v2.config.AbstractKeycloakOpenIdAsWiremockConfig;
|
||||
import com.rbkmoney.anapi.v2.converter.search.request.ParamsToRefundSearchQueryConverter;
|
||||
import com.rbkmoney.anapi.v2.exception.BadRequestException;
|
||||
import com.rbkmoney.anapi.v2.testutil.OpenApiUtil;
|
||||
import com.rbkmoney.bouncer.decisions.ArbiterSrv;
|
||||
import com.rbkmoney.damsel.vortigon.VortigonServiceSrv;
|
||||
import com.rbkmoney.openapi.anapi_v2.model.DefaultLogicError;
|
||||
import com.rbkmoney.orgmanagement.AuthContextProviderSrv;
|
||||
import org.junit.jupiter.api.AfterEach;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.mockito.MockitoAnnotations;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.test.mock.mockito.MockBean;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.test.web.servlet.MockMvc;
|
||||
import org.springframework.util.MultiValueMap;
|
||||
|
||||
import java.time.Instant;
|
||||
import java.time.temporal.ChronoUnit;
|
||||
import java.util.List;
|
||||
|
||||
import static com.rbkmoney.anapi.v2.testutil.MagistaUtil.createContextFragment;
|
||||
import static com.rbkmoney.anapi.v2.testutil.MagistaUtil.createJudgementAllowed;
|
||||
import static java.util.UUID.randomUUID;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.Mockito.*;
|
||||
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
|
||||
import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print;
|
||||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath;
|
||||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
|
||||
|
||||
class ErrorControllerTest extends AbstractKeycloakOpenIdAsWiremockConfig {
|
||||
|
||||
@Autowired
|
||||
private MockMvc mockMvc;
|
||||
@MockBean
|
||||
private ParamsToRefundSearchQueryConverter refundSearchConverter;
|
||||
@MockBean
|
||||
public VortigonServiceSrv.Iface vortigonClient;
|
||||
@MockBean
|
||||
public AuthContextProviderSrv.Iface orgMgmtClient;
|
||||
@MockBean
|
||||
public ArbiterSrv.Iface bouncerClient;
|
||||
|
||||
private AutoCloseable mocks;
|
||||
|
||||
private Object[] preparedMocks;
|
||||
|
||||
@BeforeEach
|
||||
public void init() {
|
||||
mocks = MockitoAnnotations.openMocks(this);
|
||||
preparedMocks = new Object[] {refundSearchConverter, vortigonClient, orgMgmtClient, bouncerClient};
|
||||
}
|
||||
|
||||
@AfterEach
|
||||
public void clean() throws Exception {
|
||||
verifyNoMoreInteractions(preparedMocks);
|
||||
mocks.close();
|
||||
}
|
||||
|
||||
@Test
|
||||
void testConstraintViolationException() throws Exception {
|
||||
MultiValueMap<String, String> params = OpenApiUtil.getSearchRequiredParams();
|
||||
params.set("limit", "1001");
|
||||
|
||||
mockMvc.perform(
|
||||
get("/payments")
|
||||
.header("Authorization", "Bearer " + generateInvoicesReadJwt())
|
||||
.header("X-Request-ID", randomUUID())
|
||||
.header("X-Request-Deadline", Instant.now().plus(1, ChronoUnit.DAYS).toString())
|
||||
.params(params)
|
||||
.contentType(MediaType.APPLICATION_JSON_UTF8)
|
||||
.content(""))
|
||||
.andDo(print())
|
||||
.andExpect(status().isBadRequest())
|
||||
.andExpect(jsonPath("$.code").value(DefaultLogicError.CodeEnum.INVALIDREQUEST.getValue()))
|
||||
.andExpect(jsonPath("$.message").isNotEmpty());
|
||||
}
|
||||
|
||||
@Test
|
||||
void testBadRequestException() throws Exception {
|
||||
when(vortigonClient.getShopsIds(any(), any())).thenReturn(List.of("1", "2", "3"));
|
||||
when(orgMgmtClient.getUserContext(any())).thenReturn(createContextFragment());
|
||||
when(bouncerClient.judge(any(), any())).thenReturn(createJudgementAllowed());
|
||||
String message = "Error!";
|
||||
doThrow(new BadRequestException(message)).when(refundSearchConverter)
|
||||
.convert(any(), any(), any(), any(),
|
||||
any(), any(), any(), any(),
|
||||
any(), any(), any(), any());
|
||||
|
||||
MultiValueMap<String, String> params = OpenApiUtil.getSearchRequiredParams();
|
||||
|
||||
mockMvc.perform(
|
||||
get("/refunds")
|
||||
.header("Authorization", "Bearer " + generateInvoicesReadJwt())
|
||||
.header("X-Request-ID", randomUUID())
|
||||
.header("X-Request-Deadline", Instant.now().plus(1, ChronoUnit.DAYS).toString())
|
||||
.params(params)
|
||||
.contentType(MediaType.APPLICATION_JSON_UTF8)
|
||||
.content(""))
|
||||
.andDo(print())
|
||||
.andExpect(status().isBadRequest())
|
||||
.andExpect(jsonPath("$.code").value(DefaultLogicError.CodeEnum.INVALIDREQUEST.getValue()))
|
||||
.andExpect(jsonPath("$.message").value(message));
|
||||
verify(vortigonClient, times(1)).getShopsIds(any(), any());
|
||||
verify(orgMgmtClient, times(1)).getUserContext(any());
|
||||
verify(bouncerClient, times(1)).judge(any(), any());
|
||||
verify(refundSearchConverter, times(1))
|
||||
.convert(any(), any(), any(), any(),
|
||||
any(), any(), any(), any(),
|
||||
any(), any(), any(), any());
|
||||
}
|
||||
|
||||
@Test
|
||||
void testMissingServletRequestParameterException() throws Exception {
|
||||
|
||||
MultiValueMap<String, String> params = OpenApiUtil.getSearchRequiredParams();
|
||||
params.remove("limit");
|
||||
|
||||
mockMvc.perform(
|
||||
get("/refunds")
|
||||
.header("Authorization", "Bearer " + generateInvoicesReadJwt())
|
||||
.header("X-Request-ID", randomUUID())
|
||||
.header("X-Request-Deadline", Instant.now().plus(1, ChronoUnit.DAYS).toString())
|
||||
.params(params)
|
||||
.contentType(MediaType.APPLICATION_JSON_UTF8)
|
||||
.content(""))
|
||||
.andDo(print())
|
||||
.andExpect(status().isBadRequest())
|
||||
.andExpect(jsonPath("$.code").value(DefaultLogicError.CodeEnum.INVALIDREQUEST.getValue()))
|
||||
.andExpect(jsonPath("$.message").isNotEmpty());
|
||||
}
|
||||
|
||||
@Test
|
||||
void testDeadlineException() throws Exception {
|
||||
mockMvc.perform(
|
||||
get("/refunds")
|
||||
.header("Authorization", "Bearer " + generateInvoicesReadJwt())
|
||||
.header("X-Request-ID", randomUUID())
|
||||
.header("X-Request-Deadline", "fail")
|
||||
.params(OpenApiUtil.getSearchRequiredParams())
|
||||
.contentType(MediaType.APPLICATION_JSON_UTF8)
|
||||
.content(""))
|
||||
.andDo(print())
|
||||
.andExpect(status().isBadRequest())
|
||||
.andExpect(jsonPath("$.code").value(DefaultLogicError.CodeEnum.INVALIDDEADLINE.getValue()))
|
||||
.andExpect(jsonPath("$.message").isNotEmpty());
|
||||
}
|
||||
|
||||
@Test
|
||||
void testInternalException() throws Exception {
|
||||
when(vortigonClient.getShopsIds(any(), any())).thenReturn(List.of("1", "2", "3"));
|
||||
when(orgMgmtClient.getUserContext(any())).thenReturn(createContextFragment());
|
||||
when(bouncerClient.judge(any(), any())).thenReturn(createJudgementAllowed());
|
||||
doThrow(new RuntimeException()).when(refundSearchConverter)
|
||||
.convert(any(), any(), any(), any(),
|
||||
any(), any(), any(), any(),
|
||||
any(), any(), any(), any());
|
||||
|
||||
MultiValueMap<String, String> params = OpenApiUtil.getSearchRequiredParams();
|
||||
|
||||
mockMvc.perform(
|
||||
get("/refunds")
|
||||
.header("Authorization", "Bearer " + generateInvoicesReadJwt())
|
||||
.header("X-Request-ID", randomUUID())
|
||||
.header("X-Request-Deadline", Instant.now().plus(1, ChronoUnit.DAYS).toString())
|
||||
.params(params)
|
||||
.contentType(MediaType.APPLICATION_JSON_UTF8)
|
||||
.content(""))
|
||||
.andDo(print())
|
||||
.andExpect(status().isInternalServerError())
|
||||
.andExpect(jsonPath("$").doesNotExist());
|
||||
verify(vortigonClient, times(1)).getShopsIds(any(), any());
|
||||
verify(orgMgmtClient, times(1)).getUserContext(any());
|
||||
verify(bouncerClient, times(1)).judge(any(), any());
|
||||
verify(refundSearchConverter, times(1))
|
||||
.convert(any(), any(), any(), any(),
|
||||
any(), any(), any(), any(),
|
||||
any(), any(), any(), any());
|
||||
}
|
||||
|
||||
@Test
|
||||
void testUnauthorizedException() throws Exception {
|
||||
mockMvc.perform(
|
||||
get("/refunds")
|
||||
.header("X-Request-ID", randomUUID())
|
||||
.header("X-Request-Deadline", "fail")
|
||||
.params(OpenApiUtil.getSearchRequiredParams())
|
||||
.contentType(MediaType.APPLICATION_JSON_UTF8)
|
||||
.content(""))
|
||||
.andDo(print())
|
||||
.andExpect(status().isUnauthorized())
|
||||
.andExpect(jsonPath("$").doesNotExist());
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,61 @@
|
||||
package com.rbkmoney.anapi.v2.converter.search.request;
|
||||
|
||||
import com.rbkmoney.anapi.v2.exception.BadRequestException;
|
||||
import com.rbkmoney.magista.ChargebackSearchQuery;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import java.time.OffsetDateTime;
|
||||
import java.util.List;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
|
||||
class ParamsToChargebackSearchQueryConverterTest {
|
||||
|
||||
private static final ParamsToChargebackSearchQueryConverter converter =
|
||||
new ParamsToChargebackSearchQueryConverter();
|
||||
|
||||
@Test
|
||||
void convert() {
|
||||
ChargebackSearchQuery query = converter.convert("1",
|
||||
OffsetDateTime.MIN,
|
||||
OffsetDateTime.MAX,
|
||||
10,
|
||||
List.of("1", "2"),
|
||||
"1",
|
||||
"2",
|
||||
"3",
|
||||
List.of("pending", "accepted"),
|
||||
List.of("pre_arbitration"),
|
||||
List.of("fraud"),
|
||||
"test"
|
||||
);
|
||||
assertNotNull(query);
|
||||
}
|
||||
|
||||
@Test
|
||||
void mapStage() {
|
||||
assertTrue(converter.mapStage("chargeback").isSetChargeback());
|
||||
assertTrue(converter.mapStage("pre_arbitration").isSetPreArbitration());
|
||||
assertTrue(converter.mapStage("arbitration").isSetArbitration());
|
||||
assertThrows(BadRequestException.class, () -> converter.mapStage("unexpected"));
|
||||
}
|
||||
|
||||
@Test
|
||||
void mapStatus() {
|
||||
assertTrue(converter.mapStatus("pending").isSetPending());
|
||||
assertTrue(converter.mapStatus("accepted").isSetAccepted());
|
||||
assertTrue(converter.mapStatus("rejected").isSetRejected());
|
||||
assertTrue(converter.mapStatus("cancelled").isSetCancelled());
|
||||
assertThrows(BadRequestException.class, () -> converter.mapStatus("unexpected"));
|
||||
}
|
||||
|
||||
@Test
|
||||
void mapCategory() {
|
||||
assertTrue(converter.mapCategory("fraud").isSetFraud());
|
||||
assertTrue(converter.mapCategory("dispute").isSetDispute());
|
||||
assertTrue(converter.mapCategory("authorisation").isSetAuthorisation());
|
||||
assertTrue(converter.mapCategory("processing_error").isSetProcessingError());
|
||||
assertThrows(BadRequestException.class, () -> converter.mapCategory("unexpected"));
|
||||
|
||||
}
|
||||
}
|
@ -0,0 +1,52 @@
|
||||
package com.rbkmoney.anapi.v2.converter.search.request;
|
||||
|
||||
import com.rbkmoney.anapi.v2.exception.BadRequestException;
|
||||
import com.rbkmoney.magista.InvoiceSearchQuery;
|
||||
import com.rbkmoney.magista.InvoiceStatus;
|
||||
import com.rbkmoney.magista.PaymentParams;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import java.time.OffsetDateTime;
|
||||
import java.util.List;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
|
||||
class ParamsToInvoiceSearchQueryConverterTest {
|
||||
|
||||
private static final ParamsToInvoiceSearchQueryConverter converter =
|
||||
new ParamsToInvoiceSearchQueryConverter();
|
||||
|
||||
@Test
|
||||
void convert() {
|
||||
InvoiceSearchQuery query = converter.convert("1",
|
||||
OffsetDateTime.MIN,
|
||||
OffsetDateTime.MAX,
|
||||
10,
|
||||
List.of("1", "2"),
|
||||
List.of("1", "2"),
|
||||
"paid",
|
||||
"1",
|
||||
"2",
|
||||
0L,
|
||||
1000L,
|
||||
"test");
|
||||
assertNotNull(query);
|
||||
}
|
||||
|
||||
@Test
|
||||
void mapPaymentParams() {
|
||||
Long amountFrom = 0L;
|
||||
Long amountTo = 1000L;
|
||||
PaymentParams params = converter.mapPaymentParams(amountFrom, amountTo);
|
||||
assertEquals(amountFrom, params.getPaymentAmountFrom());
|
||||
assertEquals(amountTo, params.getPaymentAmountTo());
|
||||
}
|
||||
|
||||
@Test
|
||||
void mapStatus() {
|
||||
for (InvoiceStatus status : InvoiceStatus.values()) {
|
||||
assertEquals(status, converter.mapStatus(status.name()));
|
||||
}
|
||||
assertThrows(BadRequestException.class, () -> converter.mapStatus("unexpected"));
|
||||
}
|
||||
}
|
@ -0,0 +1,100 @@
|
||||
package com.rbkmoney.anapi.v2.converter.search.request;
|
||||
|
||||
import com.rbkmoney.anapi.v2.exception.BadRequestException;
|
||||
import com.rbkmoney.damsel.domain.LegacyBankCardPaymentSystem;
|
||||
import com.rbkmoney.damsel.domain.LegacyBankCardTokenProvider;
|
||||
import com.rbkmoney.damsel.domain.LegacyTerminalPaymentProvider;
|
||||
import com.rbkmoney.magista.InvoicePaymentFlowType;
|
||||
import com.rbkmoney.magista.PaymentSearchQuery;
|
||||
import com.rbkmoney.magista.PaymentToolType;
|
||||
import com.rbkmoney.openapi.anapi_v2.model.PaymentStatus;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import java.time.OffsetDateTime;
|
||||
import java.util.List;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
|
||||
class ParamsToPaymentSearchQueryConverterTest {
|
||||
|
||||
private static final ParamsToPaymentSearchQueryConverter converter = new ParamsToPaymentSearchQueryConverter();
|
||||
|
||||
@Test
|
||||
void convert() {
|
||||
PaymentSearchQuery query = converter.convert("1",
|
||||
OffsetDateTime.MIN,
|
||||
OffsetDateTime.MAX,
|
||||
10,
|
||||
List.of("1", "2", "3"),
|
||||
List.of("1", "2", "3"),
|
||||
"cancelled",
|
||||
"hold",
|
||||
"paymentTerminal",
|
||||
"euroset",
|
||||
"1",
|
||||
"1",
|
||||
"1",
|
||||
"mail@mail.com",
|
||||
"127.0.0.1",
|
||||
"fingerprint",
|
||||
"1",
|
||||
"123456",
|
||||
"7890",
|
||||
"012345678",
|
||||
"123456",
|
||||
"applepay",
|
||||
"mastercard",
|
||||
0L,
|
||||
1000L,
|
||||
List.of("1", "2", "3"),
|
||||
"test");
|
||||
assertNotNull(query);
|
||||
}
|
||||
|
||||
@Test
|
||||
void mapPaymentTool() {
|
||||
assertEquals(PaymentToolType.bank_card, converter.mapPaymentTool("bankCard"));
|
||||
assertEquals(PaymentToolType.payment_terminal, converter.mapPaymentTool("paymentTerminal"));
|
||||
assertThrows(BadRequestException.class, () -> converter.mapPaymentTool("unexpected"));
|
||||
}
|
||||
|
||||
@Test
|
||||
void mapInvoicePaymentFlow() {
|
||||
assertEquals(InvoicePaymentFlowType.instant, converter.mapInvoicePaymentFlow("instant"));
|
||||
assertEquals(InvoicePaymentFlowType.hold, converter.mapInvoicePaymentFlow("hold"));
|
||||
assertThrows(BadRequestException.class, () -> converter.mapInvoicePaymentFlow("unexpected"));
|
||||
}
|
||||
|
||||
@Test
|
||||
void mapStatus() {
|
||||
for (PaymentStatus.StatusEnum status : PaymentStatus.StatusEnum.values()) {
|
||||
assertNotNull(converter.mapStatus(status.getValue()));
|
||||
}
|
||||
|
||||
assertThrows(BadRequestException.class, () -> converter.mapStatus("unexpected"));
|
||||
}
|
||||
|
||||
@Test
|
||||
void mapTerminalProvider() {
|
||||
for (LegacyTerminalPaymentProvider provider : LegacyTerminalPaymentProvider.values()) {
|
||||
assertEquals(provider, converter.mapTerminalProvider(provider.name()));
|
||||
}
|
||||
assertThrows(BadRequestException.class, () -> converter.mapTerminalProvider("unexpected"));
|
||||
}
|
||||
|
||||
@Test
|
||||
void mapTokenProvider() {
|
||||
for (LegacyBankCardTokenProvider provider : LegacyBankCardTokenProvider.values()) {
|
||||
assertEquals(provider, converter.mapTokenProvider(provider.name()));
|
||||
}
|
||||
assertThrows(BadRequestException.class, () -> converter.mapTokenProvider("unexpected"));
|
||||
}
|
||||
|
||||
@Test
|
||||
void mapPaymentSystem() {
|
||||
for (LegacyBankCardPaymentSystem system : LegacyBankCardPaymentSystem.values()) {
|
||||
assertEquals(system, converter.mapPaymentSystem(system.name()));
|
||||
}
|
||||
assertThrows(BadRequestException.class, () -> converter.mapPaymentSystem("unexpected"));
|
||||
}
|
||||
}
|
@ -0,0 +1,38 @@
|
||||
package com.rbkmoney.anapi.v2.converter.search.request;
|
||||
|
||||
import com.rbkmoney.anapi.v2.exception.BadRequestException;
|
||||
import com.rbkmoney.magista.PayoutSearchQuery;
|
||||
import com.rbkmoney.magista.PayoutToolType;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import java.time.OffsetDateTime;
|
||||
import java.util.List;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
|
||||
class ParamsToPayoutSearchQueryConverterTest {
|
||||
|
||||
private static final ParamsToPayoutSearchQueryConverter converter = new ParamsToPayoutSearchQueryConverter();
|
||||
|
||||
@Test
|
||||
void convert() {
|
||||
PayoutSearchQuery query = converter.convert("1",
|
||||
OffsetDateTime.MIN,
|
||||
OffsetDateTime.MAX,
|
||||
10,
|
||||
List.of("1", "2", "3"),
|
||||
"1",
|
||||
"Wallet",
|
||||
"test");
|
||||
assertNotNull(query);
|
||||
}
|
||||
|
||||
@Test
|
||||
void mapPayoutToolType() {
|
||||
assertEquals(PayoutToolType.payout_account, converter.mapPayoutToolType("PayoutAccount"));
|
||||
assertEquals(PayoutToolType.wallet, converter.mapPayoutToolType("Wallet"));
|
||||
assertEquals(PayoutToolType.payment_institution_account,
|
||||
converter.mapPayoutToolType("PaymentInstitutionAccount"));
|
||||
assertThrows(BadRequestException.class, () -> converter.mapPayoutToolType("unexpected"));
|
||||
}
|
||||
}
|
@ -0,0 +1,41 @@
|
||||
package com.rbkmoney.anapi.v2.converter.search.request;
|
||||
|
||||
import com.rbkmoney.anapi.v2.exception.BadRequestException;
|
||||
import com.rbkmoney.magista.InvoicePaymentRefundStatus;
|
||||
import com.rbkmoney.magista.RefundSearchQuery;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import java.time.OffsetDateTime;
|
||||
import java.util.List;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
|
||||
class ParamsToRefundSearchQueryConverterTest {
|
||||
|
||||
private static final ParamsToRefundSearchQueryConverter converter = new ParamsToRefundSearchQueryConverter();
|
||||
|
||||
@Test
|
||||
void convert() {
|
||||
RefundSearchQuery query = converter.convert("1",
|
||||
OffsetDateTime.MIN,
|
||||
OffsetDateTime.MAX,
|
||||
10,
|
||||
List.of("1", "2", "3"),
|
||||
List.of("1", "2", "3"),
|
||||
"1",
|
||||
"1",
|
||||
"1",
|
||||
"1",
|
||||
"pending",
|
||||
"test");
|
||||
assertNotNull(query);
|
||||
}
|
||||
|
||||
@Test
|
||||
void mapRefundStatus() {
|
||||
assertEquals(InvoicePaymentRefundStatus.succeeded, converter.mapStatus("succeeded"));
|
||||
assertEquals(InvoicePaymentRefundStatus.failed, converter.mapStatus("failed"));
|
||||
assertEquals(InvoicePaymentRefundStatus.pending, converter.mapStatus("pending"));
|
||||
assertThrows(BadRequestException.class, () -> converter.mapStatus("unexpected"));
|
||||
}
|
||||
}
|
@ -0,0 +1,56 @@
|
||||
package com.rbkmoney.anapi.v2.converter.search.response;
|
||||
|
||||
import com.rbkmoney.damsel.base.Content;
|
||||
import com.rbkmoney.damsel.domain.*;
|
||||
import com.rbkmoney.magista.StatChargeback;
|
||||
import com.rbkmoney.magista.StatChargebackResponse;
|
||||
import com.rbkmoney.openapi.anapi_v2.model.Chargeback;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import static com.rbkmoney.anapi.v2.testutil.MagistaUtil.createSearchChargebackAllResponse;
|
||||
import static com.rbkmoney.anapi.v2.testutil.RandomUtil.randomBytes;
|
||||
import static com.rbkmoney.anapi.v2.testutil.RandomUtil.randomString;
|
||||
import static com.rbkmoney.openapi.anapi_v2.model.ChargebackCategory.*;
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
|
||||
class StatChargebackToChargebackConverterTest {
|
||||
|
||||
private static final StatChargebackToChargebackConverter converter = new StatChargebackToChargebackConverter();
|
||||
|
||||
@Test
|
||||
void convert() {
|
||||
StatChargebackResponse magistaResponse = createSearchChargebackAllResponse();
|
||||
StatChargeback magistaChargeback = magistaResponse.getChargebacks().get(0);
|
||||
magistaChargeback.setContent(new Content()
|
||||
.setType(randomString(10))
|
||||
.setData(randomBytes(10)));
|
||||
Chargeback result = converter.convert(magistaChargeback);
|
||||
assertAll(
|
||||
() -> assertEquals(magistaChargeback.getAmount(), result.getBodyAmount()),
|
||||
() -> assertEquals(magistaChargeback.getCreatedAt(), result.getCreatedAt().toString()),
|
||||
() -> assertEquals(magistaChargeback.getChargebackId(), result.getChargebackId()),
|
||||
() -> assertEquals(magistaChargeback.getChargebackReason().getCode(),
|
||||
result.getChargebackReason().getCode()),
|
||||
() -> assertArrayEquals(magistaChargeback.getContent().getData(), result.getContent().getData()),
|
||||
() -> assertEquals(magistaChargeback.getContent().getType(), result.getContent().getType()),
|
||||
() -> assertEquals(magistaChargeback.getCurrencyCode().getSymbolicCode(), result.getBodyCurrency())
|
||||
);
|
||||
}
|
||||
|
||||
@Test
|
||||
void mapCategory() {
|
||||
assertAll(
|
||||
() -> assertEquals(AUTHORISATION, converter.mapCategory(InvoicePaymentChargebackCategory.authorisation(
|
||||
new InvoicePaymentChargebackCategoryAuthorisation()))),
|
||||
() -> assertEquals(DISPUTE, converter.mapCategory(
|
||||
InvoicePaymentChargebackCategory.dispute(new InvoicePaymentChargebackCategoryDispute()))),
|
||||
() -> assertEquals(FRAUD, converter.mapCategory(
|
||||
InvoicePaymentChargebackCategory.fraud(new InvoicePaymentChargebackCategoryFraud()))),
|
||||
() -> assertEquals(PROCESSING_ERROR, converter.mapCategory(
|
||||
InvoicePaymentChargebackCategory.processing_error(
|
||||
new InvoicePaymentChargebackCategoryProcessingError()))),
|
||||
() -> assertThrows(IllegalArgumentException.class,
|
||||
() -> converter.mapCategory(new InvoicePaymentChargebackCategory()))
|
||||
);
|
||||
}
|
||||
}
|
@ -0,0 +1,91 @@
|
||||
package com.rbkmoney.anapi.v2.converter.search.response;
|
||||
|
||||
import com.rbkmoney.damsel.domain.*;
|
||||
import com.rbkmoney.damsel.msgpack.Value;
|
||||
import com.rbkmoney.magista.StatInvoice;
|
||||
import com.rbkmoney.magista.StatInvoiceResponse;
|
||||
import com.rbkmoney.openapi.anapi_v2.model.Invoice;
|
||||
import com.rbkmoney.openapi.anapi_v2.model.InvoiceLineTaxVAT;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import static com.rbkmoney.anapi.v2.testutil.MagistaUtil.createSearchInvoiceAllResponse;
|
||||
import static com.rbkmoney.anapi.v2.testutil.RandomUtil.randomInt;
|
||||
import static com.rbkmoney.anapi.v2.testutil.RandomUtil.randomString;
|
||||
import static com.rbkmoney.openapi.anapi_v2.model.Invoice.StatusEnum.*;
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
|
||||
class StatInvoiceToInvoiceConverterTest {
|
||||
|
||||
private static final StatInvoiceToInvoiceConverter converter = new StatInvoiceToInvoiceConverter();
|
||||
|
||||
@Test
|
||||
void convert() {
|
||||
StatInvoiceResponse magistaResponse = createSearchInvoiceAllResponse();
|
||||
StatInvoice magistaInvoice = magistaResponse.getInvoices().get(0);
|
||||
magistaInvoice.getCart().getLines().get(0).setMetadata(Map.of("TaxMode", Value.str("10%")))
|
||||
.setQuantity(randomInt(1, 10000))
|
||||
.setPrice(new Cash()
|
||||
.setAmount(randomInt(0, 1000000)));
|
||||
Invoice result = converter.convert(magistaInvoice);
|
||||
var expectedLine = magistaInvoice.getCart().getLines().get(0);
|
||||
var actualLine = result.getCart().get(0);
|
||||
assertAll(
|
||||
() -> assertEquals(magistaInvoice.getAmount(), result.getAmount()),
|
||||
() -> assertEquals(magistaInvoice.getCreatedAt(), result.getCreatedAt().toString()),
|
||||
() -> assertEquals(magistaInvoice.getCurrencySymbolicCode(), result.getCurrency()),
|
||||
() -> assertEquals(magistaInvoice.getExternalId(), result.getExternalID()),
|
||||
() -> assertEquals(expectedLine.getPrice().getAmount(), actualLine.getPrice()),
|
||||
() -> assertEquals(expectedLine.getProduct(), actualLine.getProduct()),
|
||||
() -> assertEquals(expectedLine.getQuantity() * expectedLine.getPrice().getAmount(),
|
||||
actualLine.getCost()),
|
||||
() -> assertEquals(expectedLine.getMetadata().get("TaxMode").getStr(),
|
||||
((InvoiceLineTaxVAT) actualLine.getTaxMode()).getRate().getValue()),
|
||||
() -> assertEquals(magistaInvoice.getDescription(), result.getDescription()),
|
||||
() -> assertEquals(magistaInvoice.getDue(), result.getDueDate().toString()),
|
||||
() -> assertEquals(magistaInvoice.getId(), result.getId()),
|
||||
() -> assertEquals(magistaInvoice.getProduct(), result.getProduct()),
|
||||
() -> assertEquals(magistaInvoice.getShopId(), result.getShopID())
|
||||
);
|
||||
}
|
||||
|
||||
@Test
|
||||
void mapStatusInfo() {
|
||||
Invoice invoice = new Invoice();
|
||||
InvoiceStatus status = InvoiceStatus.fulfilled(new InvoiceFulfilled()
|
||||
.setDetails(randomString(10)));
|
||||
converter.mapStatusInfo(invoice, status);
|
||||
assertEquals(FULFILLED, invoice.getStatus());
|
||||
assertEquals(status.getFulfilled().getDetails(), invoice.getReason());
|
||||
|
||||
invoice = new Invoice();
|
||||
status = InvoiceStatus.paid(new InvoicePaid());
|
||||
converter.mapStatusInfo(invoice, status);
|
||||
assertEquals(PAID, invoice.getStatus());
|
||||
|
||||
invoice = new Invoice();
|
||||
status = InvoiceStatus.unpaid(new InvoiceUnpaid());
|
||||
converter.mapStatusInfo(invoice, status);
|
||||
assertEquals(UNPAID, invoice.getStatus());
|
||||
|
||||
invoice = new Invoice();
|
||||
status = InvoiceStatus.cancelled(new InvoiceCancelled()
|
||||
.setDetails(randomString(10)));
|
||||
converter.mapStatusInfo(invoice, status);
|
||||
assertEquals(CANCELLED, invoice.getStatus());
|
||||
assertEquals(status.getCancelled().getDetails(), invoice.getReason());
|
||||
|
||||
assertThrows(IllegalArgumentException.class, () -> converter.mapStatusInfo(new Invoice(), new InvoiceStatus()));
|
||||
}
|
||||
|
||||
@Test
|
||||
void mapTaxMode() {
|
||||
assertNull(converter.mapTaxMode(Map.of()));
|
||||
String taxMode = "10%";
|
||||
Map<String, Value> metadata = new HashMap<>();
|
||||
metadata.put("TaxMode", Value.str(taxMode));
|
||||
assertEquals(taxMode, ((InvoiceLineTaxVAT)converter.mapTaxMode(metadata)).getRate().getValue());
|
||||
}
|
||||
}
|
@ -0,0 +1,96 @@
|
||||
package com.rbkmoney.anapi.v2.converter.search.response;
|
||||
|
||||
import com.rbkmoney.damsel.domain.InvoicePaymentStatus;
|
||||
import com.rbkmoney.damsel.domain.*;
|
||||
import com.rbkmoney.geck.common.util.TypeUtil;
|
||||
import com.rbkmoney.magista.CustomerPayer;
|
||||
import com.rbkmoney.magista.InvoicePaymentFlow;
|
||||
import com.rbkmoney.magista.InvoicePaymentFlowHold;
|
||||
import com.rbkmoney.magista.Payer;
|
||||
import com.rbkmoney.magista.*;
|
||||
import com.rbkmoney.openapi.anapi_v2.model.PaymentFlow;
|
||||
import com.rbkmoney.openapi.anapi_v2.model.PaymentSearchResult;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import java.time.OffsetDateTime;
|
||||
|
||||
import static com.rbkmoney.anapi.v2.testutil.MagistaUtil.createSearchPaymentAllResponse;
|
||||
import static com.rbkmoney.anapi.v2.testutil.RandomUtil.randomString;
|
||||
import static com.rbkmoney.openapi.anapi_v2.model.Payer.PayerTypeEnum.*;
|
||||
import static com.rbkmoney.openapi.anapi_v2.model.PaymentSearchResult.StatusEnum.*;
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
|
||||
class StatPaymentToPaymentSearchResultConverterTest {
|
||||
|
||||
private static final StatPaymentToPaymentSearchResultConverter converter =
|
||||
new StatPaymentToPaymentSearchResultConverter();
|
||||
|
||||
@Test
|
||||
void convert() {
|
||||
StatPaymentResponse magistaResponse = createSearchPaymentAllResponse();
|
||||
StatPayment magistaPayment = magistaResponse.getPayments().get(0);
|
||||
magistaPayment.setFlow(InvoicePaymentFlow.hold(new InvoicePaymentFlowHold()));
|
||||
magistaPayment.setStatusChangedAt(TypeUtil.temporalToString(OffsetDateTime.now().toLocalDateTime()));
|
||||
magistaPayment.setAdditionalTransactionInfo(new AdditionalTransactionInfo()
|
||||
.setRrn(randomString(10))
|
||||
.setApprovalCode(randomString(10)));
|
||||
PaymentSearchResult result = converter.convert(magistaPayment);
|
||||
assertAll(
|
||||
() -> assertEquals(magistaPayment.getAmount(), result.getAmount()),
|
||||
() -> assertEquals(magistaPayment.getCreatedAt(), result.getCreatedAt().toString()),
|
||||
() -> assertEquals(magistaPayment.getCurrencySymbolicCode(), result.getCurrency()),
|
||||
() -> assertEquals(magistaPayment.getExternalId(), result.getExternalID()),
|
||||
() -> assertEquals(magistaPayment.getFee(), result.getFee()),
|
||||
() -> assertEquals(PaymentFlow.TypeEnum.PAYMENTFLOWHOLD, result.getFlow().getType()),
|
||||
() -> assertEquals(magistaPayment.getLocationInfo().getCityGeoId(),
|
||||
result.getGeoLocationInfo().getCityGeoID()),
|
||||
() -> assertEquals(magistaPayment.getLocationInfo().getCountryGeoId(),
|
||||
result.getGeoLocationInfo().getCountryGeoID()),
|
||||
() -> assertEquals(magistaPayment.getStatusChangedAt(), result.getStatusChangedAt().toString()),
|
||||
() -> assertEquals(magistaPayment.getId(), result.getId()),
|
||||
() -> assertEquals(magistaPayment.getInvoiceId(), result.getInvoiceID()),
|
||||
() -> assertEquals(magistaPayment.isMakeRecurrent(), result.getMakeRecurrent()),
|
||||
() -> assertEquals(magistaPayment.getShopId(), result.getShopID()),
|
||||
() -> assertEquals(magistaPayment.getShortId(), result.getShortID()),
|
||||
() -> assertEquals(magistaPayment.getAdditionalTransactionInfo().getApprovalCode(),
|
||||
result.getTransactionInfo().getApprovalCode()),
|
||||
() -> assertEquals(magistaPayment.getAdditionalTransactionInfo().getRrn(),
|
||||
result.getTransactionInfo().getRrn())
|
||||
);
|
||||
}
|
||||
|
||||
@Test
|
||||
void mapPayer() {
|
||||
assertEquals(CUSTOMERPAYER, converter.mapPayer(Payer.customer(new CustomerPayer())).getPayerType());
|
||||
assertEquals(PAYMENTRESOURCEPAYER,
|
||||
converter.mapPayer(Payer.payment_resource(new PaymentResourcePayer())).getPayerType());
|
||||
assertEquals(RECURRENTPAYER, converter.mapPayer(Payer.recurrent(new RecurrentPayer())).getPayerType());
|
||||
assertThrows(IllegalArgumentException.class, () -> converter.mapPayer(new Payer()));
|
||||
}
|
||||
|
||||
@Test
|
||||
void mapStatus() {
|
||||
var status = InvoicePaymentStatus.pending(new InvoicePaymentPending());
|
||||
assertEquals(PENDING, converter.mapStatus(status));
|
||||
|
||||
status = InvoicePaymentStatus.processed(new InvoicePaymentProcessed());
|
||||
assertEquals(PROCESSED, converter.mapStatus(status));
|
||||
|
||||
status = InvoicePaymentStatus.captured(new InvoicePaymentCaptured());
|
||||
assertEquals(CAPTURED, converter.mapStatus(status));
|
||||
|
||||
status = InvoicePaymentStatus.cancelled(new InvoicePaymentCancelled());
|
||||
assertEquals(CANCELLED, converter.mapStatus(status));
|
||||
|
||||
status = InvoicePaymentStatus.refunded(new InvoicePaymentRefunded());
|
||||
assertEquals(REFUNDED, converter.mapStatus(status));
|
||||
|
||||
status = InvoicePaymentStatus.failed(new InvoicePaymentFailed());
|
||||
assertEquals(FAILED, converter.mapStatus(status));
|
||||
|
||||
status = InvoicePaymentStatus.charged_back(new InvoicePaymentChargedBack());
|
||||
assertEquals(CHARGEDBACK, converter.mapStatus(status));
|
||||
|
||||
assertThrows(IllegalArgumentException.class, () -> converter.mapStatus(new InvoicePaymentStatus()));
|
||||
}
|
||||
}
|
@ -0,0 +1,190 @@
|
||||
package com.rbkmoney.anapi.v2.converter.search.response;
|
||||
|
||||
import com.rbkmoney.damsel.domain.InternationalBankAccount;
|
||||
import com.rbkmoney.damsel.domain.InternationalBankDetails;
|
||||
import com.rbkmoney.damsel.domain.*;
|
||||
import com.rbkmoney.magista.*;
|
||||
import com.rbkmoney.openapi.anapi_v2.model.*;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import static com.rbkmoney.anapi.v2.testutil.MagistaUtil.createSearchPayoutAllResponse;
|
||||
import static com.rbkmoney.anapi.v2.testutil.RandomUtil.randomString;
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
|
||||
class StatPayoutToPayoutConverterTest {
|
||||
|
||||
private static final StatPayoutToPayoutConverter converter = new StatPayoutToPayoutConverter();
|
||||
|
||||
@Test
|
||||
void convert() {
|
||||
StatPayoutResponse magistaResponse = createSearchPayoutAllResponse();
|
||||
StatPayout magistaPayout = magistaResponse.getPayouts().get(0);
|
||||
Payout result = converter.convert(magistaPayout);
|
||||
assertAll(
|
||||
() -> assertEquals(magistaPayout.getAmount(), result.getAmount()),
|
||||
() -> assertEquals(magistaPayout.getCreatedAt(), result.getCreatedAt().toString()),
|
||||
() -> assertEquals(magistaPayout.getCurrencySymbolicCode(), result.getCurrency()),
|
||||
() -> assertEquals(magistaPayout.getFee(), result.getFee()),
|
||||
() -> assertEquals(magistaPayout.getId(), result.getId()),
|
||||
() -> assertEquals(magistaPayout.getShopId(), result.getShopID())
|
||||
);
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
void mapPayoutStatus() {
|
||||
assertAll(
|
||||
() -> assertEquals("Cancelled", converter.mapStatus(PayoutStatus.cancelled(new PayoutCancelled()))),
|
||||
() -> assertEquals("Paid", converter.mapStatus(PayoutStatus.paid(new PayoutPaid()))),
|
||||
() -> assertEquals("Confirmed", converter.mapStatus(PayoutStatus.confirmed(new PayoutConfirmed()))),
|
||||
() -> assertEquals("Unpaid", converter.mapStatus(PayoutStatus.unpaid(new PayoutUnpaid()))),
|
||||
() -> assertThrows(IllegalArgumentException.class, () -> converter.mapStatus(new PayoutStatus()))
|
||||
);
|
||||
}
|
||||
|
||||
@Test
|
||||
void mapPayoutToolDetails() {
|
||||
//RussianBankAccount
|
||||
PayoutToolInfo toolInfo = new PayoutToolInfo();
|
||||
toolInfo.setRussianBankAccount(new RussianBankAccount()
|
||||
.setAccount(randomString(10))
|
||||
.setBankBik(randomString(10))
|
||||
.setBankName(randomString(10))
|
||||
.setBankPostAccount(randomString(10)));
|
||||
|
||||
PayoutToolDetailsBankAccount actualRussianBankAccount =
|
||||
(PayoutToolDetailsBankAccount) converter.mapPayoutToolDetails(toolInfo);
|
||||
RussianBankAccount expectedRussianBankAccount = toolInfo.getRussianBankAccount();
|
||||
assertAll(
|
||||
() -> assertEquals(expectedRussianBankAccount.getAccount(), actualRussianBankAccount.getAccount()),
|
||||
() -> assertEquals(expectedRussianBankAccount.getBankBik(), actualRussianBankAccount.getBankBik()),
|
||||
() -> assertEquals(expectedRussianBankAccount.getBankName(), actualRussianBankAccount.getBankName()),
|
||||
() -> assertEquals(expectedRussianBankAccount.getBankPostAccount(),
|
||||
actualRussianBankAccount.getBankPostAccount())
|
||||
);
|
||||
|
||||
//WalletInfo
|
||||
toolInfo = new PayoutToolInfo();
|
||||
toolInfo.setWalletInfo(new WalletInfo()
|
||||
.setWalletId(randomString(10)));
|
||||
|
||||
PayoutToolDetailsWalletInfo walletActual =
|
||||
(PayoutToolDetailsWalletInfo) converter.mapPayoutToolDetails(toolInfo);
|
||||
WalletInfo walletExpected = toolInfo.getWalletInfo();
|
||||
assertEquals(walletExpected.getWalletId(), walletActual.getWalletID());
|
||||
|
||||
//PaymentInstitutionAccount
|
||||
toolInfo = new PayoutToolInfo();
|
||||
toolInfo.setPaymentInstitutionAccount(new PaymentInstitutionAccount());
|
||||
|
||||
PayoutToolDetailsPaymentInstitutionAccount actualPaymentInstitutionAccount =
|
||||
(PayoutToolDetailsPaymentInstitutionAccount) converter.mapPayoutToolDetails(toolInfo);
|
||||
PaymentInstitutionAccount expectedPaymentInstitutionAccount = toolInfo.getPaymentInstitutionAccount();
|
||||
assertNotNull(expectedPaymentInstitutionAccount);
|
||||
|
||||
//InternationalBankAccount
|
||||
toolInfo = new PayoutToolInfo();
|
||||
toolInfo.setInternationalBankAccount(new InternationalBankAccount()
|
||||
.setAccountHolder(randomString(10))
|
||||
.setIban(randomString(10))
|
||||
.setNumber(randomString(10))
|
||||
.setBank(new InternationalBankDetails()
|
||||
.setName(randomString(10))
|
||||
.setAbaRtn(randomString(10))
|
||||
.setAddress(randomString(10))
|
||||
.setBic(randomString(10))
|
||||
.setCountry(CountryCode.ABW)));
|
||||
|
||||
PayoutToolDetailsInternationalBankAccount actualInternationalBankAccount =
|
||||
(PayoutToolDetailsInternationalBankAccount) converter.mapPayoutToolDetails(toolInfo);
|
||||
InternationalBankAccount expectedInternationalBankAccount = toolInfo.getInternationalBankAccount();
|
||||
|
||||
assertAll(
|
||||
() -> assertEquals(expectedInternationalBankAccount.getIban(),
|
||||
actualInternationalBankAccount.getIban()),
|
||||
() -> assertEquals(expectedInternationalBankAccount.getNumber(),
|
||||
actualInternationalBankAccount.getNumber()),
|
||||
() -> assertEquals(expectedInternationalBankAccount.getBank().getAbaRtn(),
|
||||
actualInternationalBankAccount.getBankDetails().getAbartn()),
|
||||
() -> assertEquals(expectedInternationalBankAccount.getBank().getAddress(),
|
||||
actualInternationalBankAccount.getBankDetails().getAddress()),
|
||||
() -> assertEquals(expectedInternationalBankAccount.getBank().getBic(),
|
||||
actualInternationalBankAccount.getBankDetails().getBic()),
|
||||
() -> assertEquals(expectedInternationalBankAccount.getBank().getName(),
|
||||
actualInternationalBankAccount.getBankDetails().getName()),
|
||||
() -> assertEquals(expectedInternationalBankAccount.getBank().getCountry().name(),
|
||||
actualInternationalBankAccount.getBankDetails().getCountryCode()),
|
||||
//tested via mapInternationalCorrespondentBankAccount test
|
||||
() -> assertNull(actualInternationalBankAccount.getCorrespondentBankAccount())
|
||||
);
|
||||
|
||||
//Some missing type
|
||||
assertThrows(IllegalArgumentException.class, () -> converter.mapPayoutToolDetails(new PayoutToolInfo()));
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
void mapCountryCode() {
|
||||
CountryCode countryCode = CountryCode.ABH;
|
||||
assertEquals("ABH", converter.mapCountryCode(countryCode));
|
||||
assertNull(converter.mapCountryCode(null));
|
||||
}
|
||||
|
||||
@Test
|
||||
void mapInternationalCorrespondentBankAccount() {
|
||||
InternationalBankAccount expected = new InternationalBankAccount()
|
||||
.setAccountHolder(randomString(10))
|
||||
.setIban(randomString(10))
|
||||
.setNumber(randomString(10))
|
||||
.setBank(new InternationalBankDetails()
|
||||
.setName(randomString(10))
|
||||
.setAbaRtn(randomString(10))
|
||||
.setAddress(randomString(10))
|
||||
.setBic(randomString(10))
|
||||
.setCountry(CountryCode.ABW))
|
||||
.setCorrespondentAccount(new InternationalBankAccount()
|
||||
.setAccountHolder(randomString(5))
|
||||
.setIban(randomString(5))
|
||||
.setNumber(randomString(5))
|
||||
.setBank(new InternationalBankDetails()
|
||||
.setName(randomString(5))
|
||||
.setAbaRtn(randomString(5))
|
||||
.setAddress(randomString(5))
|
||||
.setBic(randomString(5))
|
||||
.setCountry(CountryCode.RUS)));
|
||||
|
||||
InternationalCorrespondentBankAccount actual = converter.mapInternationalCorrespondentBankAccount(expected);
|
||||
|
||||
assertAll(
|
||||
() -> assertEquals(expected.getIban(),
|
||||
actual.getIban()),
|
||||
() -> assertEquals(expected.getNumber(),
|
||||
actual.getNumber()),
|
||||
() -> assertEquals(expected.getBank().getAbaRtn(),
|
||||
actual.getBankDetails().getAbartn()),
|
||||
() -> assertEquals(expected.getBank().getAddress(),
|
||||
actual.getBankDetails().getAddress()),
|
||||
() -> assertEquals(expected.getBank().getBic(),
|
||||
actual.getBankDetails().getBic()),
|
||||
() -> assertEquals(expected.getBank().getName(),
|
||||
actual.getBankDetails().getName()),
|
||||
() -> assertEquals(expected.getBank().getCountry().name(),
|
||||
actual.getBankDetails().getCountryCode()),
|
||||
() -> assertEquals(expected.getCorrespondentAccount().getIban(),
|
||||
actual.getCorrespondentBankAccount().getIban()),
|
||||
() -> assertEquals(expected.getCorrespondentAccount().getNumber(),
|
||||
actual.getCorrespondentBankAccount().getNumber()),
|
||||
() -> assertEquals(expected.getCorrespondentAccount().getBank().getAbaRtn(),
|
||||
actual.getCorrespondentBankAccount().getBankDetails().getAbartn()),
|
||||
() -> assertEquals(expected.getCorrespondentAccount().getBank().getAddress(),
|
||||
actual.getCorrespondentBankAccount().getBankDetails().getAddress()),
|
||||
() -> assertEquals(expected.getCorrespondentAccount().getBank().getBic(),
|
||||
actual.getCorrespondentBankAccount().getBankDetails().getBic()),
|
||||
() -> assertEquals(expected.getCorrespondentAccount().getBank().getName(),
|
||||
actual.getCorrespondentBankAccount().getBankDetails().getName()),
|
||||
() -> assertEquals(expected.getCorrespondentAccount().getBank().getCountry().name(),
|
||||
actual.getCorrespondentBankAccount().getBankDetails().getCountryCode()),
|
||||
() -> assertNull(actual.getCorrespondentBankAccount().getCorrespondentBankAccount())
|
||||
);
|
||||
}
|
||||
}
|
@ -0,0 +1,63 @@
|
||||
package com.rbkmoney.anapi.v2.converter.search.response;
|
||||
|
||||
import com.rbkmoney.damsel.domain.*;
|
||||
import com.rbkmoney.magista.StatRefund;
|
||||
import com.rbkmoney.magista.StatRefundResponse;
|
||||
import com.rbkmoney.openapi.anapi_v2.model.RefundSearchResult;
|
||||
import com.rbkmoney.openapi.anapi_v2.model.RefundStatusError;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import static com.rbkmoney.anapi.v2.testutil.MagistaUtil.createSearchRefundAllResponse;
|
||||
import static com.rbkmoney.anapi.v2.testutil.RandomUtil.randomString;
|
||||
import static com.rbkmoney.openapi.anapi_v2.model.RefundSearchResult.StatusEnum.*;
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
|
||||
class StatRefundToRefundSearchResultConverterTest {
|
||||
|
||||
private static final StatRefundToRefundSearchResultConverter converter =
|
||||
new StatRefundToRefundSearchResultConverter();
|
||||
|
||||
@Test
|
||||
void convert() {
|
||||
StatRefundResponse magistaResponse = createSearchRefundAllResponse();
|
||||
StatRefund magistaRefund = magistaResponse.getRefunds().get(0);
|
||||
RefundSearchResult result = converter.convert(magistaRefund);
|
||||
assertAll(
|
||||
() -> assertEquals(magistaRefund.getAmount(), result.getAmount()),
|
||||
() -> assertEquals(magistaRefund.getCreatedAt(), result.getCreatedAt().toString()),
|
||||
() -> assertEquals(magistaRefund.getCurrencySymbolicCode(), result.getCurrency()),
|
||||
() -> assertEquals(magistaRefund.getId(), result.getId()),
|
||||
() -> assertEquals(magistaRefund.getShopId(), result.getShopID()),
|
||||
() -> assertEquals(magistaRefund.getExternalId(), result.getExternalID()),
|
||||
() -> assertEquals(magistaRefund.getInvoiceId(), result.getInvoiceID()),
|
||||
() -> assertEquals(magistaRefund.getPaymentId(), result.getPaymentID()),
|
||||
() -> assertEquals(magistaRefund.getReason(), result.getReason())
|
||||
);
|
||||
}
|
||||
|
||||
@Test
|
||||
void mapStatusError() {
|
||||
assertNull(converter.mapStatusError(new InvoicePaymentRefundStatus()));
|
||||
String reason = randomString(10);
|
||||
String code = randomString(10);
|
||||
InvoicePaymentRefundStatus status = InvoicePaymentRefundStatus
|
||||
.failed(new InvoicePaymentRefundFailed()
|
||||
.setFailure(OperationFailure.failure(new Failure()
|
||||
.setReason(reason)
|
||||
.setCode(code))));
|
||||
RefundStatusError statusError = converter.mapStatusError(status);
|
||||
assertEquals(reason, statusError.getMessage());
|
||||
assertEquals(code, statusError.getCode());
|
||||
}
|
||||
|
||||
@Test
|
||||
void mapStatus() {
|
||||
assertEquals(PENDING,
|
||||
converter.mapStatus(InvoicePaymentRefundStatus.pending(new InvoicePaymentRefundPending())));
|
||||
assertEquals(FAILED,
|
||||
converter.mapStatus(InvoicePaymentRefundStatus.failed(new InvoicePaymentRefundFailed())));
|
||||
assertEquals(SUCCEEDED,
|
||||
converter.mapStatus(InvoicePaymentRefundStatus.succeeded(new InvoicePaymentRefundSucceeded())));
|
||||
assertThrows(IllegalArgumentException.class, () -> converter.mapStatus(new InvoicePaymentRefundStatus()));
|
||||
}
|
||||
}
|
158
src/test/java/com/rbkmoney/anapi/v2/testutil/MagistaUtil.java
Normal file
158
src/test/java/com/rbkmoney/anapi/v2/testutil/MagistaUtil.java
Normal file
@ -0,0 +1,158 @@
|
||||
package com.rbkmoney.anapi.v2.testutil;
|
||||
|
||||
import com.rbkmoney.bouncer.ctx.ContextFragment;
|
||||
import com.rbkmoney.bouncer.decisions.Judgement;
|
||||
import com.rbkmoney.bouncer.decisions.Resolution;
|
||||
import com.rbkmoney.bouncer.decisions.ResolutionAllowed;
|
||||
import com.rbkmoney.damsel.domain.InvoicePaymentRefundStatus;
|
||||
import com.rbkmoney.damsel.domain.InvoicePaymentStatus;
|
||||
import com.rbkmoney.damsel.domain.InvoiceStatus;
|
||||
import com.rbkmoney.damsel.domain.*;
|
||||
import com.rbkmoney.damsel.geo_ip.LocationInfo;
|
||||
import com.rbkmoney.geck.serializer.kit.mock.FieldHandler;
|
||||
import com.rbkmoney.geck.serializer.kit.mock.MockMode;
|
||||
import com.rbkmoney.geck.serializer.kit.mock.MockTBaseProcessor;
|
||||
import com.rbkmoney.geck.serializer.kit.tbase.TBaseHandler;
|
||||
import com.rbkmoney.magista.InvoicePaymentFlow;
|
||||
import com.rbkmoney.magista.InvoicePaymentFlowInstant;
|
||||
import com.rbkmoney.magista.*;
|
||||
import lombok.SneakyThrows;
|
||||
import lombok.experimental.UtilityClass;
|
||||
import org.apache.thrift.TBase;
|
||||
|
||||
import java.time.Instant;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
@UtilityClass
|
||||
public class MagistaUtil {
|
||||
|
||||
private static final MockTBaseProcessor mockRequiredTBaseProcessor;
|
||||
|
||||
static {
|
||||
mockRequiredTBaseProcessor = new MockTBaseProcessor(MockMode.REQUIRED_ONLY, 15, 1);
|
||||
Map.Entry<FieldHandler, String[]> timeFields = Map.entry(
|
||||
structHandler -> structHandler.value(Instant.now().toString()),
|
||||
new String[] {"created_at", "at", "due", "status_changed_at"}
|
||||
);
|
||||
mockRequiredTBaseProcessor.addFieldHandler(timeFields.getKey(), timeFields.getValue());
|
||||
}
|
||||
|
||||
public static StatPaymentResponse createSearchPaymentRequiredResponse() {
|
||||
return fillRequiredTBaseObject(new StatPaymentResponse(), StatPaymentResponse.class);
|
||||
}
|
||||
|
||||
public static StatChargebackResponse createSearchChargebackRequiredResponse() {
|
||||
return fillRequiredTBaseObject(new StatChargebackResponse(), StatChargebackResponse.class);
|
||||
}
|
||||
|
||||
public static StatPaymentResponse createSearchPaymentAllResponse() {
|
||||
var payment = fillRequiredTBaseObject(new StatPayment(), StatPayment.class);
|
||||
var status = new InvoicePaymentStatus();
|
||||
status.setPending(new InvoicePaymentPending());
|
||||
var cart = fillRequiredTBaseObject(new InvoiceCart(), InvoiceCart.class);
|
||||
var line = fillRequiredTBaseObject(new InvoiceLine(), InvoiceLine.class);
|
||||
var instant = fillRequiredTBaseObject(new InvoicePaymentFlowInstant(), InvoicePaymentFlowInstant.class);
|
||||
var locationInfo = fillRequiredTBaseObject(new LocationInfo(), LocationInfo.class);
|
||||
var response = fillRequiredTBaseObject(new StatPaymentResponse(), StatPaymentResponse.class);
|
||||
|
||||
return response.setPayments(
|
||||
List.of(payment
|
||||
.setStatus(status)
|
||||
.setCart(cart.setLines(List.of(line)))
|
||||
.setFlow(InvoicePaymentFlow
|
||||
.instant(instant))
|
||||
.setLocationInfo(locationInfo)));
|
||||
}
|
||||
|
||||
public static StatChargebackResponse createSearchChargebackAllResponse() {
|
||||
var chargeback = fillRequiredTBaseObject(new StatChargeback(), StatChargeback.class);
|
||||
var stage = fillRequiredTBaseObject(new InvoicePaymentChargebackStage(), InvoicePaymentChargebackStage.class);
|
||||
var reason =
|
||||
fillRequiredTBaseObject(new InvoicePaymentChargebackReason(), InvoicePaymentChargebackReason.class);
|
||||
var status =
|
||||
fillRequiredTBaseObject(new InvoicePaymentChargebackStatus(), InvoicePaymentChargebackStatus.class);
|
||||
var response = fillRequiredTBaseObject(new StatChargebackResponse(), StatChargebackResponse.class);
|
||||
|
||||
return response.setChargebacks(
|
||||
List.of(chargeback
|
||||
.setStage(stage)
|
||||
.setChargebackReason(reason)
|
||||
.setChargebackStatus(status))
|
||||
);
|
||||
}
|
||||
|
||||
public static StatRefundResponse createSearchRefundRequiredResponse() {
|
||||
return fillRequiredTBaseObject(new StatRefundResponse(), StatRefundResponse.class);
|
||||
}
|
||||
|
||||
public static StatRefundResponse createSearchRefundAllResponse() {
|
||||
var refund = fillRequiredTBaseObject(new StatRefund(), StatRefund.class);
|
||||
var cart = fillRequiredTBaseObject(new InvoiceCart(), InvoiceCart.class);
|
||||
var line = fillRequiredTBaseObject(new InvoiceLine(), InvoiceLine.class);
|
||||
var cash = fillRequiredTBaseObject(new Cash(), Cash.class);
|
||||
var status = fillRequiredTBaseObject(new InvoicePaymentRefundStatus(), InvoicePaymentRefundStatus.class);
|
||||
var response = fillRequiredTBaseObject(new StatRefundResponse(), StatRefundResponse.class);
|
||||
|
||||
return response.setRefunds(
|
||||
List.of(refund
|
||||
.setCart(cart
|
||||
.setLines(List.of(line.setPrice(cash))))
|
||||
.setStatus(status))
|
||||
);
|
||||
}
|
||||
|
||||
public static StatInvoiceResponse createSearchInvoiceRequiredResponse() {
|
||||
return fillRequiredTBaseObject(new StatInvoiceResponse(), StatInvoiceResponse.class);
|
||||
}
|
||||
|
||||
public static StatInvoiceResponse createSearchInvoiceAllResponse() {
|
||||
var invoice = fillRequiredTBaseObject(new StatInvoice(), StatInvoice.class);
|
||||
var cart = fillRequiredTBaseObject(new InvoiceCart(), InvoiceCart.class);
|
||||
var line = fillRequiredTBaseObject(new InvoiceLine(), InvoiceLine.class);
|
||||
var cash = fillRequiredTBaseObject(new Cash(), Cash.class);
|
||||
var status = fillRequiredTBaseObject(new InvoiceStatus(),
|
||||
InvoiceStatus.class);
|
||||
var response = fillRequiredTBaseObject(new StatInvoiceResponse(), StatInvoiceResponse.class);
|
||||
|
||||
return response.setInvoices(
|
||||
List.of(invoice
|
||||
.setCart(cart
|
||||
.setLines(List.of(line.setPrice(cash))))
|
||||
.setStatus(status))
|
||||
);
|
||||
}
|
||||
|
||||
public static StatPayoutResponse createSearchPayoutRequiredResponse() {
|
||||
return fillRequiredTBaseObject(new StatPayoutResponse(), StatPayoutResponse.class);
|
||||
}
|
||||
|
||||
public static StatPayoutResponse createSearchPayoutAllResponse() {
|
||||
var payout = fillRequiredTBaseObject(new StatPayout(), StatPayout.class);
|
||||
var toolInfo = fillRequiredTBaseObject(new PayoutToolInfo(), PayoutToolInfo.class);
|
||||
var bank = fillRequiredTBaseObject(new RussianBankAccount(), RussianBankAccount.class);
|
||||
var status = fillRequiredTBaseObject(new PayoutStatus(), PayoutStatus.class);
|
||||
var response = fillRequiredTBaseObject(new StatPayoutResponse(), StatPayoutResponse.class);
|
||||
toolInfo.setRussianBankAccount(bank);
|
||||
return response.setPayouts(
|
||||
List.of(payout
|
||||
.setPayoutToolInfo(toolInfo)
|
||||
.setStatus(status))
|
||||
);
|
||||
}
|
||||
|
||||
public static ContextFragment createContextFragment() {
|
||||
return fillRequiredTBaseObject(new ContextFragment(), ContextFragment.class);
|
||||
}
|
||||
|
||||
public static Judgement createJudgementAllowed() {
|
||||
Resolution resolution = new Resolution();
|
||||
resolution.setAllowed(new ResolutionAllowed());
|
||||
return new Judgement().setResolution(resolution);
|
||||
}
|
||||
|
||||
@SneakyThrows
|
||||
public static <T extends TBase> T fillRequiredTBaseObject(T tbase, Class<T> type) {
|
||||
return mockRequiredTBaseProcessor.process(tbase, new TBaseHandler<>(type));
|
||||
}
|
||||
}
|
127
src/test/java/com/rbkmoney/anapi/v2/testutil/OpenApiUtil.java
Normal file
127
src/test/java/com/rbkmoney/anapi/v2/testutil/OpenApiUtil.java
Normal file
@ -0,0 +1,127 @@
|
||||
package com.rbkmoney.anapi.v2.testutil;
|
||||
|
||||
import com.rbkmoney.damsel.domain.PaymentInstitutionRealm;
|
||||
import com.rbkmoney.damsel.merch_stat.TerminalPaymentProvider;
|
||||
import com.rbkmoney.openapi.anapi_v2.model.*;
|
||||
import lombok.experimental.UtilityClass;
|
||||
import org.springframework.util.LinkedMultiValueMap;
|
||||
import org.springframework.util.MultiValueMap;
|
||||
|
||||
import static com.rbkmoney.anapi.v2.testutil.RandomUtil.randomIntegerAsString;
|
||||
|
||||
@UtilityClass
|
||||
public class OpenApiUtil {
|
||||
|
||||
public static MultiValueMap<String, String> getSearchRequiredParams() {
|
||||
MultiValueMap<String, String> params = new LinkedMultiValueMap<>();
|
||||
params.add("partyID", randomIntegerAsString(1, 1000));
|
||||
params.add("fromTime", "2007-12-03T10:15:30+01:00");
|
||||
params.add("toTime", "2020-12-03T10:15:30+01:00");
|
||||
params.add("limit", randomIntegerAsString(1, 40));
|
||||
return params;
|
||||
}
|
||||
|
||||
public static MultiValueMap<String, String> getSearchPaymentAllParams() {
|
||||
MultiValueMap<String, String> params = getSearchRequiredParams();
|
||||
params.add("shopID", randomIntegerAsString(1, 10));
|
||||
params.add("shopIDs", randomIntegerAsString(11, 20));
|
||||
params.add("shopIDs", randomIntegerAsString(21, 30));
|
||||
params.add("paymentInstitutionRealm", PaymentInstitutionRealm.live.name());
|
||||
params.add("invoiceIDs", randomIntegerAsString(1, 10));
|
||||
params.add("invoiceIDs", randomIntegerAsString(11, 20));
|
||||
params.add("paymentStatus", PaymentStatus.StatusEnum.PENDING.getValue());
|
||||
params.add("paymentFlow", "instant");
|
||||
params.add("paymentMethod", "paymentTerminal");
|
||||
params.add("paymentTerminalProvider", TerminalPaymentProvider.alipay.name());
|
||||
params.add("invoiceID", randomIntegerAsString(1, 1000));
|
||||
params.add("paymentID", randomIntegerAsString(1, 1000));
|
||||
params.add("externalID", randomIntegerAsString(1, 1000));
|
||||
params.add("payerEmail", "payer@mail.com");
|
||||
params.add("payerIP", "0.0.0.0");
|
||||
params.add("payerFingerprint", "iamveryunique");
|
||||
params.add("first6", randomIntegerAsString(100000, 999999));
|
||||
params.add("last4", randomIntegerAsString(1000, 9999));
|
||||
params.add("rrn", "123456789010");
|
||||
params.add("approvalCode", "QWERTY");
|
||||
params.add("bankCardTokenProvider", "applepay");
|
||||
params.add("bankCardPaymentSystem", "mastercard");
|
||||
params.add("paymentAmountFrom", randomIntegerAsString(1, 9999));
|
||||
params.add("paymentAmountTo", randomIntegerAsString(9999, 999999));
|
||||
params.add("excludedShops", randomIntegerAsString(1, 10));
|
||||
params.add("excludedShops", randomIntegerAsString(11, 20));
|
||||
params.add("continuationToken", "test");
|
||||
return params;
|
||||
}
|
||||
|
||||
public static MultiValueMap<String, String> getSearchChargebackAllParams() {
|
||||
MultiValueMap<String, String> params = getSearchRequiredParams();
|
||||
params.add("shopID", randomIntegerAsString(1, 10));
|
||||
params.add("shopIDs", randomIntegerAsString(11, 20));
|
||||
params.add("shopIDs", randomIntegerAsString(21, 30));
|
||||
params.add("paymentInstitutionRealm", PaymentInstitutionRealm.live.name());
|
||||
params.add("offset", randomIntegerAsString(1, 10));
|
||||
params.add("invoiceID", randomIntegerAsString(1, 1000));
|
||||
params.add("paymentID", randomIntegerAsString(1, 1000));
|
||||
params.add("chargebackID", randomIntegerAsString(1, 1000));
|
||||
params.add("chargebackStatuses", ChargebackStatus.PENDING.getValue());
|
||||
params.add("chargebackStages", ChargebackStage.CHARGEBACK.getValue());
|
||||
params.add("chargebackCategories", ChargebackCategory.AUTHORISATION.getValue());
|
||||
params.add("continuationToken", "test");
|
||||
return params;
|
||||
}
|
||||
|
||||
public static MultiValueMap<String, String> getSearchRefundAllParams() {
|
||||
MultiValueMap<String, String> params = getSearchRequiredParams();
|
||||
params.add("shopID", randomIntegerAsString(1, 10));
|
||||
params.add("shopIDs", randomIntegerAsString(11, 20));
|
||||
params.add("shopIDs", randomIntegerAsString(21, 30));
|
||||
params.add("paymentInstitutionRealm", PaymentInstitutionRealm.live.name());
|
||||
params.add("offset", randomIntegerAsString(1, 10));
|
||||
params.add("invoiceIDs", randomIntegerAsString(1, 10));
|
||||
params.add("invoiceIDs", randomIntegerAsString(11, 20));
|
||||
params.add("invoiceID", randomIntegerAsString(1, 1000));
|
||||
params.add("paymentID", randomIntegerAsString(1, 1000));
|
||||
params.add("refundID", randomIntegerAsString(1, 1000));
|
||||
params.add("externalID", randomIntegerAsString(1, 1000));
|
||||
params.add("refundStatus", "pending");
|
||||
params.add("excludedShops", randomIntegerAsString(1, 10));
|
||||
params.add("excludedShops", randomIntegerAsString(11, 20));
|
||||
params.add("continuationToken", "test");
|
||||
return params;
|
||||
}
|
||||
|
||||
public static MultiValueMap<String, String> getSearchInvoiceAllParams() {
|
||||
MultiValueMap<String, String> params = getSearchRequiredParams();
|
||||
params.add("shopID", randomIntegerAsString(1, 10));
|
||||
params.add("shopIDs", randomIntegerAsString(11, 20));
|
||||
params.add("shopIDs", randomIntegerAsString(21, 30));
|
||||
params.add("paymentInstitutionRealm", PaymentInstitutionRealm.live.name());
|
||||
params.add("invoiceIDs", randomIntegerAsString(1, 10));
|
||||
params.add("invoiceIDs", randomIntegerAsString(11, 20));
|
||||
params.add("invoiceStatus", "paid");
|
||||
params.add("invoiceID", randomIntegerAsString(1, 1000));
|
||||
params.add("externalID", randomIntegerAsString(1, 1000));
|
||||
params.add("invoiceAmountFrom", randomIntegerAsString(1, 1000));
|
||||
params.add("invoiceAmountTo", randomIntegerAsString(1, 1000));
|
||||
params.add("excludedShops", randomIntegerAsString(1, 10));
|
||||
params.add("excludedShops", randomIntegerAsString(11, 20));
|
||||
params.add("continuationToken", "test");
|
||||
|
||||
return params;
|
||||
}
|
||||
|
||||
public static MultiValueMap<String, String> getSearchPayoutAllParams() {
|
||||
MultiValueMap<String, String> params = getSearchRequiredParams();
|
||||
params.add("shopID", randomIntegerAsString(1, 10));
|
||||
params.add("shopIDs", randomIntegerAsString(11, 20));
|
||||
params.add("shopIDs", randomIntegerAsString(21, 30));
|
||||
params.add("paymentInstitutionRealm", PaymentInstitutionRealm.live.name());
|
||||
params.add("offset", randomIntegerAsString(1, 10));
|
||||
params.add("payoutID", randomIntegerAsString(1, 1000));
|
||||
params.add("payoutToolType", "PayoutAccount");
|
||||
params.add("excludedShops", randomIntegerAsString(1, 10));
|
||||
params.add("excludedShops", randomIntegerAsString(11, 20));
|
||||
params.add("continuationToken", "test");
|
||||
return params;
|
||||
}
|
||||
}
|
31
src/test/java/com/rbkmoney/anapi/v2/testutil/RandomUtil.java
Normal file
31
src/test/java/com/rbkmoney/anapi/v2/testutil/RandomUtil.java
Normal file
@ -0,0 +1,31 @@
|
||||
package com.rbkmoney.anapi.v2.testutil;
|
||||
|
||||
import lombok.experimental.UtilityClass;
|
||||
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.Random;
|
||||
|
||||
@UtilityClass
|
||||
public class RandomUtil {
|
||||
|
||||
private static final Random random = new Random();
|
||||
|
||||
public static int randomInt(int from, int to) {
|
||||
return random.nextInt(to - from) + from;
|
||||
}
|
||||
|
||||
public static String randomIntegerAsString(int from, int to) {
|
||||
return String.valueOf(random.nextInt(to - from) + from);
|
||||
}
|
||||
|
||||
public static String randomString(int length) {
|
||||
return new String(randomBytes(length), StandardCharsets.UTF_8);
|
||||
}
|
||||
|
||||
public static byte[] randomBytes(int length) {
|
||||
byte[] array = new byte[length];
|
||||
new Random().nextBytes(array);
|
||||
return array;
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,28 @@
|
||||
package com.rbkmoney.anapi.v2.util;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertNotNull;
|
||||
|
||||
class ConverterUtilTest {
|
||||
|
||||
@Test
|
||||
void testMerge() {
|
||||
String id = "1";
|
||||
List<String> ids = List.of("2", "3");
|
||||
List<String> result = ConverterUtil.merge(id, ids);
|
||||
assertEquals(List.of("1", "2", "3"), result);
|
||||
|
||||
result = ConverterUtil.merge(null, ids);
|
||||
assertEquals(List.of("2", "3"), result);
|
||||
|
||||
result = ConverterUtil.merge(id, null);
|
||||
assertEquals(List.of("1"), result);
|
||||
|
||||
result = ConverterUtil.merge(null, null);
|
||||
assertNotNull(result);
|
||||
}
|
||||
}
|
@ -0,0 +1,87 @@
|
||||
package com.rbkmoney.anapi.v2.util;
|
||||
|
||||
import com.rbkmoney.anapi.v2.exception.DeadlineException;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import java.time.Instant;
|
||||
import java.time.temporal.ChronoUnit;
|
||||
|
||||
import static com.rbkmoney.anapi.v2.util.DeadlineUtil.*;
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
|
||||
class DeadlineUtilTest {
|
||||
|
||||
@Test
|
||||
void checkDeadlineTest() {
|
||||
checkDeadline(null, null);
|
||||
|
||||
checkDeadline("12m", null);
|
||||
checkDeadline("1.2m", null);
|
||||
assertThrows(DeadlineException.class, () -> checkDeadline("-1.2m", null));
|
||||
|
||||
checkDeadline("12s", null);
|
||||
checkDeadline("1.2s", null);
|
||||
assertThrows(DeadlineException.class, () -> checkDeadline("-1.2s", null));
|
||||
|
||||
checkDeadline("12ms", null);
|
||||
assertThrows(DeadlineException.class, () -> checkDeadline("1.2ms", null));
|
||||
assertThrows(DeadlineException.class, () -> checkDeadline("-12ms", null));
|
||||
|
||||
checkDeadline("12m12s12ms", null);
|
||||
checkDeadline("1.2m1.2s12ms", null);
|
||||
assertThrows(DeadlineException.class, () -> checkDeadline("1.2m1.2s1.2ms", null));
|
||||
assertThrows(DeadlineException.class, () -> checkDeadline("12s12s", null));
|
||||
assertThrows(DeadlineException.class, () -> checkDeadline("12m12m", null));
|
||||
assertThrows(DeadlineException.class, () -> checkDeadline("12ms12ms", null));
|
||||
assertThrows(DeadlineException.class, () -> checkDeadline("12s12ms12ms", null));
|
||||
assertThrows(DeadlineException.class, () -> checkDeadline("12s12s12ms", null));
|
||||
|
||||
checkDeadline(Instant.now().plus(1, ChronoUnit.DAYS).toString(), null);
|
||||
assertThrows(DeadlineException.class,
|
||||
() -> checkDeadline(Instant.now().minus(1, ChronoUnit.DAYS).toString(), null));
|
||||
|
||||
assertThrows(DeadlineException.class, () -> checkDeadline("undefined", null));
|
||||
}
|
||||
|
||||
@Test
|
||||
void extractMillisecondsTest() {
|
||||
assertEquals(12, (long) extractMilliseconds("12ms", null));
|
||||
assertEquals(12, (long) extractMilliseconds("1.2m1.2s12ms", null));
|
||||
assertThrows(DeadlineException.class, () -> extractMilliseconds("1.2ms", null));
|
||||
assertThrows(DeadlineException.class, () -> extractMilliseconds("-12ms", null));
|
||||
assertThrows(DeadlineException.class, () -> extractMilliseconds("12ms12ms", null));
|
||||
}
|
||||
|
||||
@Test
|
||||
void extractSecondsTest() {
|
||||
assertEquals(12000, (long) extractSeconds("12s", null));
|
||||
assertEquals(1200, (long) extractSeconds("1.2s", null));
|
||||
assertEquals(1200, (long) extractSeconds("1.2m1.2s12ms", null));
|
||||
assertThrows(DeadlineException.class, () -> extractSeconds("-1.2s", null));
|
||||
assertThrows(DeadlineException.class, () -> extractSeconds("12s12s", null));
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
void extractMinutesTest() {
|
||||
assertEquals(720000, (long) extractMinutes("12m", null));
|
||||
assertEquals(72000, (long) extractMinutes("1.2m", null));
|
||||
assertEquals(72000, (long) extractMinutes("1.2m1.2s12ms", null));
|
||||
assertThrows(DeadlineException.class, () -> extractMinutes("-1.2m", null));
|
||||
assertThrows(DeadlineException.class, () -> extractMinutes("12m12m", null));
|
||||
}
|
||||
|
||||
@Test
|
||||
void containsRelativeValuesTest() {
|
||||
assertTrue(containsRelativeValues("12m", null));
|
||||
assertTrue(containsRelativeValues("12s", null));
|
||||
assertTrue(containsRelativeValues("12ms", null));
|
||||
assertTrue(containsRelativeValues("1.2m1.2s12ms", null));
|
||||
|
||||
assertThrows(DeadlineException.class, () -> containsRelativeValues("-1.2s", null));
|
||||
assertThrows(DeadlineException.class, () -> containsRelativeValues("12s12s", null));
|
||||
|
||||
assertFalse(containsRelativeValues(Instant.now().toString(), null));
|
||||
assertFalse(containsRelativeValues("asd", null));
|
||||
}
|
||||
}
|
10
src/test/resources/logback-test.xml
Normal file
10
src/test/resources/logback-test.xml
Normal file
@ -0,0 +1,10 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<configuration>
|
||||
<include resource="org/springframework/boot/logging/logback/defaults.xml"/>
|
||||
<include resource="org/springframework/boot/logging/logback/console-appender.xml"/>
|
||||
|
||||
<root level="warn">
|
||||
<appender-ref ref="CONSOLE"/>
|
||||
</root>
|
||||
<logger name="com.rbkmoney.woody" level="ALL"/>
|
||||
</configuration>
|
Loading…
Reference in New Issue
Block a user