diff --git a/pom.xml b/pom.xml
index 848a990..97ac52f 100644
--- a/pom.xml
+++ b/pom.xml
@@ -11,7 +11,7 @@
fraudo
- 0.0.19
+ 0.0.20
Fraudo
Language for describing antifraud patterns
diff --git a/src/main/antlr4/com.rbkmoney.fraudo/FraudoPayment.g4 b/src/main/antlr4/com.rbkmoney.fraudo/FraudoPayment.g4
index 4095a8c..26fc5a5 100644
--- a/src/main/antlr4/com.rbkmoney.fraudo/FraudoPayment.g4
+++ b/src/main/antlr4/com.rbkmoney.fraudo/FraudoPayment.g4
@@ -36,6 +36,8 @@ relationalExpression
| in_grey_list
| in_list
| like
+ | is_mobile
+ | is_recurrent
;
unaryExpression
@@ -97,4 +99,12 @@ sum_refund
in
: 'in' LPAREN (stringExpression) DELIMETER string_list RPAREN
+ ;
+
+is_mobile
+ : 'isMobile' LPAREN RPAREN
+ ;
+
+is_recurrent
+ : 'isRecurrent' LPAREN RPAREN
;
\ No newline at end of file
diff --git a/src/main/antlr4/imports/Fraudo.g4 b/src/main/antlr4/imports/Fraudo.g4
index c9fedd0..df91aee 100644
--- a/src/main/antlr4/imports/Fraudo.g4
+++ b/src/main/antlr4/imports/Fraudo.g4
@@ -32,6 +32,14 @@ currency
: 'currency' LPAREN RPAREN
;
+payer_type
+ : 'payerType' LPAREN RPAREN
+ ;
+
+token_provider
+ : 'tokenProvider' LPAREN RPAREN
+ ;
+
count
: 'count' LPAREN STRING time_window (group_by)? RPAREN
;
diff --git a/src/main/java/com/rbkmoney/fraudo/payment/factory/FraudVisitorFactory.java b/src/main/java/com/rbkmoney/fraudo/payment/factory/FraudVisitorFactory.java
index 5ec4a85..04daa09 100644
--- a/src/main/java/com/rbkmoney/fraudo/payment/factory/FraudVisitorFactory.java
+++ b/src/main/java/com/rbkmoney/fraudo/payment/factory/FraudVisitorFactory.java
@@ -7,6 +7,7 @@ import com.rbkmoney.fraudo.payment.aggregator.CountPaymentAggregator;
import com.rbkmoney.fraudo.payment.aggregator.SumPaymentAggregator;
import com.rbkmoney.fraudo.payment.resolver.PaymentGroupResolver;
import com.rbkmoney.fraudo.payment.resolver.PaymentTimeWindowResolver;
+import com.rbkmoney.fraudo.payment.resolver.PaymentTypeResolver;
import com.rbkmoney.fraudo.payment.visitor.impl.FirstFindVisitorImpl;
import com.rbkmoney.fraudo.resolver.CountryResolver;
import com.rbkmoney.fraudo.resolver.FieldResolver;
@@ -20,6 +21,7 @@ public interface FraudVisitorFactory {
InListFinder listFinder,
FieldResolver fieldPairResolver,
PaymentGroupResolver paymentGroupResolver,
- PaymentTimeWindowResolver timeWindowResolver);
+ PaymentTimeWindowResolver timeWindowResolver,
+ PaymentTypeResolver paymentTypeResolver);
}
diff --git a/src/main/java/com/rbkmoney/fraudo/payment/factory/FraudVisitorFactoryImpl.java b/src/main/java/com/rbkmoney/fraudo/payment/factory/FraudVisitorFactoryImpl.java
index d7ce304..46e613d 100644
--- a/src/main/java/com/rbkmoney/fraudo/payment/factory/FraudVisitorFactoryImpl.java
+++ b/src/main/java/com/rbkmoney/fraudo/payment/factory/FraudVisitorFactoryImpl.java
@@ -7,6 +7,7 @@ import com.rbkmoney.fraudo.payment.aggregator.CountPaymentAggregator;
import com.rbkmoney.fraudo.payment.aggregator.SumPaymentAggregator;
import com.rbkmoney.fraudo.payment.resolver.PaymentGroupResolver;
import com.rbkmoney.fraudo.payment.resolver.PaymentTimeWindowResolver;
+import com.rbkmoney.fraudo.payment.resolver.PaymentTypeResolver;
import com.rbkmoney.fraudo.payment.visitor.CountVisitor;
import com.rbkmoney.fraudo.payment.visitor.CustomFuncVisitor;
import com.rbkmoney.fraudo.payment.visitor.ListVisitor;
@@ -26,12 +27,18 @@ public class FraudVisitorFactoryImpl implements FraudVisitorFactory {
InListFinder listFinder,
FieldResolver fieldResolver,
PaymentGroupResolver paymentGroupResolver,
- PaymentTimeWindowResolver timeWindowResolver) {
+ PaymentTimeWindowResolver timeWindowResolver,
+ PaymentTypeResolver paymentTypeResolver) {
CountVisitor countVisitor = new CountVisitorImpl<>(countPaymentAggregator, fieldResolver, paymentGroupResolver, timeWindowResolver);
SumVisitor sumVisitor = new SumVisitorImpl<>(sumPaymentAggregator, fieldResolver, paymentGroupResolver, timeWindowResolver);
ListVisitor listVisitor = new ListVisitorImpl<>(listFinder, fieldResolver);
CustomFuncVisitor customFuncVisitor = new CustomFuncVisitorImpl<>(
- uniqueValueAggregator, countryResolver, fieldResolver, paymentGroupResolver, timeWindowResolver);
+ uniqueValueAggregator,
+ countryResolver,
+ fieldResolver,
+ paymentGroupResolver,
+ timeWindowResolver,
+ paymentTypeResolver);
return new FirstFindVisitorImpl<>(countVisitor, sumVisitor, listVisitor, customFuncVisitor, fieldResolver);
}
diff --git a/src/main/java/com/rbkmoney/fraudo/payment/factory/FullVisitorFactoryImpl.java b/src/main/java/com/rbkmoney/fraudo/payment/factory/FullVisitorFactoryImpl.java
index 0531610..bcaa0ec 100644
--- a/src/main/java/com/rbkmoney/fraudo/payment/factory/FullVisitorFactoryImpl.java
+++ b/src/main/java/com/rbkmoney/fraudo/payment/factory/FullVisitorFactoryImpl.java
@@ -7,6 +7,7 @@ import com.rbkmoney.fraudo.payment.aggregator.CountPaymentAggregator;
import com.rbkmoney.fraudo.payment.aggregator.SumPaymentAggregator;
import com.rbkmoney.fraudo.payment.resolver.PaymentGroupResolver;
import com.rbkmoney.fraudo.payment.resolver.PaymentTimeWindowResolver;
+import com.rbkmoney.fraudo.payment.resolver.PaymentTypeResolver;
import com.rbkmoney.fraudo.payment.visitor.CountVisitor;
import com.rbkmoney.fraudo.payment.visitor.CustomFuncVisitor;
import com.rbkmoney.fraudo.payment.visitor.ListVisitor;
@@ -26,12 +27,18 @@ public class FullVisitorFactoryImpl implements FraudVisitorFactory {
InListFinder listFinder,
FieldResolver fieldResolver,
PaymentGroupResolver paymentGroupResolver,
- PaymentTimeWindowResolver timeWindowResolver) {
+ PaymentTimeWindowResolver timeWindowResolver,
+ PaymentTypeResolver paymentTypeResolver) {
CountVisitor countVisitor = new CountVisitorImpl<>(countPaymentAggregator, fieldResolver, paymentGroupResolver, timeWindowResolver);
SumVisitor sumVisitor = new SumVisitorImpl<>(sumPaymentAggregator, fieldResolver, paymentGroupResolver, timeWindowResolver);
ListVisitor listVisitor = new ListVisitorImpl<>(listFinder, fieldResolver);
CustomFuncVisitor customFuncVisitor = new CustomFuncVisitorImpl<>(
- uniqueValueAggregator, countryResolver, fieldResolver, paymentGroupResolver, timeWindowResolver);
+ uniqueValueAggregator,
+ countryResolver,
+ fieldResolver,
+ paymentGroupResolver,
+ timeWindowResolver,
+ paymentTypeResolver);
return new FullVisitorImpl<>(countVisitor, sumVisitor, listVisitor, customFuncVisitor, fieldResolver);
}
diff --git a/src/main/java/com/rbkmoney/fraudo/payment/resolver/PaymentTypeResolver.java b/src/main/java/com/rbkmoney/fraudo/payment/resolver/PaymentTypeResolver.java
new file mode 100644
index 0000000..372c14b
--- /dev/null
+++ b/src/main/java/com/rbkmoney/fraudo/payment/resolver/PaymentTypeResolver.java
@@ -0,0 +1,9 @@
+package com.rbkmoney.fraudo.payment.resolver;
+
+public interface PaymentTypeResolver {
+
+ Boolean isMobile(T model);
+
+ Boolean isRecurrent(T model);
+
+}
diff --git a/src/main/java/com/rbkmoney/fraudo/payment/visitor/CustomFuncVisitor.java b/src/main/java/com/rbkmoney/fraudo/payment/visitor/CustomFuncVisitor.java
index 8960d5b..77558cb 100644
--- a/src/main/java/com/rbkmoney/fraudo/payment/visitor/CustomFuncVisitor.java
+++ b/src/main/java/com/rbkmoney/fraudo/payment/visitor/CustomFuncVisitor.java
@@ -10,4 +10,8 @@ public interface CustomFuncVisitor {
Integer visitUnique(UniqueContext ctx, T model);
+ boolean visitCheckMobile(Is_mobileContext ctx, T model);
+
+ boolean visitCheckRecurrent(Is_recurrentContext ctx, T model);
+
}
diff --git a/src/main/java/com/rbkmoney/fraudo/payment/visitor/impl/CustomFuncVisitorImpl.java b/src/main/java/com/rbkmoney/fraudo/payment/visitor/impl/CustomFuncVisitorImpl.java
index 4b9e77e..30f59b3 100644
--- a/src/main/java/com/rbkmoney/fraudo/payment/visitor/impl/CustomFuncVisitorImpl.java
+++ b/src/main/java/com/rbkmoney/fraudo/payment/visitor/impl/CustomFuncVisitorImpl.java
@@ -4,6 +4,7 @@ import com.rbkmoney.fraudo.aggregator.UniqueValueAggregator;
import com.rbkmoney.fraudo.model.Pair;
import com.rbkmoney.fraudo.payment.resolver.PaymentGroupResolver;
import com.rbkmoney.fraudo.payment.resolver.PaymentTimeWindowResolver;
+import com.rbkmoney.fraudo.payment.resolver.PaymentTypeResolver;
import com.rbkmoney.fraudo.payment.visitor.CustomFuncVisitor;
import com.rbkmoney.fraudo.resolver.CountryResolver;
import com.rbkmoney.fraudo.resolver.FieldResolver;
@@ -20,6 +21,7 @@ public class CustomFuncVisitorImpl implements CustomFuncVisitor {
private final FieldResolver fieldResolver;
private final PaymentGroupResolver groupResolver;
private final PaymentTimeWindowResolver timeWindowResolver;
+ private final PaymentTypeResolver paymentTypeResolver;
@Override
public String visitCountryBy(Country_byContext ctx, T model) {
@@ -49,4 +51,14 @@ public class CustomFuncVisitorImpl implements CustomFuncVisitor {
);
}
+ @Override
+ public boolean visitCheckMobile(Is_mobileContext ctx, T model) {
+ return paymentTypeResolver.isMobile(model);
+ }
+
+ @Override
+ public boolean visitCheckRecurrent(Is_recurrentContext ctx, T model) {
+ return paymentTypeResolver.isRecurrent(model);
+ }
+
}
diff --git a/src/main/java/com/rbkmoney/fraudo/payment/visitor/impl/FirstFindVisitorImpl.java b/src/main/java/com/rbkmoney/fraudo/payment/visitor/impl/FirstFindVisitorImpl.java
index a642955..845221a 100644
--- a/src/main/java/com/rbkmoney/fraudo/payment/visitor/impl/FirstFindVisitorImpl.java
+++ b/src/main/java/com/rbkmoney/fraudo/payment/visitor/impl/FirstFindVisitorImpl.java
@@ -365,4 +365,13 @@ public class FirstFindVisitorImpl extends FraudoPaymentB
);
}
+ @Override
+ public Boolean visitIs_mobile(Is_mobileContext ctx) {
+ return customFuncVisitor.visitCheckMobile(ctx, threadLocalModel.get());
+ }
+
+ @Override
+ public Boolean visitIs_recurrent(Is_recurrentContext ctx) {
+ return customFuncVisitor.visitCheckRecurrent(ctx, threadLocalModel.get());
+ }
}
diff --git a/src/test/java/com/rbkmoney/fraudo/AbstractPaymentTest.java b/src/test/java/com/rbkmoney/fraudo/AbstractPaymentTest.java
index c387a5b..0de7598 100644
--- a/src/test/java/com/rbkmoney/fraudo/AbstractPaymentTest.java
+++ b/src/test/java/com/rbkmoney/fraudo/AbstractPaymentTest.java
@@ -10,6 +10,7 @@ import com.rbkmoney.fraudo.payment.factory.FraudVisitorFactoryImpl;
import com.rbkmoney.fraudo.payment.factory.FullVisitorFactoryImpl;
import com.rbkmoney.fraudo.payment.resolver.PaymentGroupResolver;
import com.rbkmoney.fraudo.payment.resolver.PaymentTimeWindowResolver;
+import com.rbkmoney.fraudo.payment.resolver.PaymentTypeResolver;
import com.rbkmoney.fraudo.resolver.CountryResolver;
import com.rbkmoney.fraudo.resolver.FieldResolver;
import com.rbkmoney.fraudo.test.constant.PaymentCheckedField;
@@ -36,6 +37,8 @@ public class AbstractPaymentTest {
InListFinder inListFinder;
@Mock
PaymentTimeWindowResolver timeWindowResolver;
+ @Mock
+ PaymentTypeResolver paymentModelPaymentTypeResolver;
private FieldResolver fieldResolver = new PaymentModelFieldResolver();
private PaymentGroupResolver paymentGroupResolver = new PaymentGroupResolver<>(fieldResolver);
@@ -60,7 +63,8 @@ public class AbstractPaymentTest {
inListFinder,
fieldResolver,
paymentGroupResolver,
- timeWindowResolver)
+ timeWindowResolver,
+ paymentModelPaymentTypeResolver)
.visit(parse, model);
}
@@ -74,7 +78,8 @@ public class AbstractPaymentTest {
inListFinder,
fieldResolver,
paymentGroupResolver,
- timeWindowResolver)
+ timeWindowResolver,
+ paymentModelPaymentTypeResolver)
.visit(parse, model);
}
diff --git a/src/test/java/com/rbkmoney/fraudo/CustomTest.java b/src/test/java/com/rbkmoney/fraudo/CustomTest.java
index fe7f41b..7dee2ae 100644
--- a/src/test/java/com/rbkmoney/fraudo/CustomTest.java
+++ b/src/test/java/com/rbkmoney/fraudo/CustomTest.java
@@ -123,6 +123,28 @@ public class CustomTest extends AbstractPaymentTest {
assertEquals(ResultStatus.ACCEPT, ResultUtils.findFirstNotNotifyStatus(result).get().getResultStatus());
}
+ @Test
+ public void tokenProviderTest() throws Exception {
+ InputStream resourceAsStream = CustomTest.class.getResourceAsStream("/rules/is_mobile.frd");
+ when(paymentModelPaymentTypeResolver.isMobile(any())).thenReturn(true);
+
+ ParseContext parseContext = getParseContext(resourceAsStream);
+ PaymentModel model = new PaymentModel();
+ ResultModel result = invoke(parseContext, model);
+ assertEquals(ResultStatus.ACCEPT, ResultUtils.findFirstNotNotifyStatus(result).get().getResultStatus());
+ }
+
+ @Test
+ public void payerTypeTest() throws Exception {
+ InputStream resourceAsStream = CustomTest.class.getResourceAsStream("/rules/is_recurrent.frd");
+ when(paymentModelPaymentTypeResolver.isRecurrent(any())).thenReturn(true);
+
+ ParseContext parseContext = getParseContext(resourceAsStream);
+ PaymentModel model = new PaymentModel();
+ ResultModel result = invoke(parseContext, model);
+ assertEquals(ResultStatus.DECLINE, ResultUtils.findFirstNotNotifyStatus(result).get().getResultStatus());
+ }
+
@Test
public void amountTest() throws Exception {
InputStream resourceAsStream = CustomTest.class.getResourceAsStream("/rules/amount.frd");
diff --git a/src/test/resources/rules/is_mobile.frd b/src/test/resources/rules/is_mobile.frd
new file mode 100644
index 0000000..c5a6107
--- /dev/null
+++ b/src/test/resources/rules/is_mobile.frd
@@ -0,0 +1 @@
+rule: isMobile() -> accept;
\ No newline at end of file
diff --git a/src/test/resources/rules/is_recurrent.frd b/src/test/resources/rules/is_recurrent.frd
new file mode 100644
index 0000000..e73d668
--- /dev/null
+++ b/src/test/resources/rules/is_recurrent.frd
@@ -0,0 +1 @@
+rule: isRecurrent() -> decline;
\ No newline at end of file