implements CommonHandler requestFunction;
+ private final ConverterIllegalArgumentException
if the supplied charset is not 62 characters long.
+ */
+ public Base62(String characters) {
+ if (!(characters.length() == 62)) {
+ throw new IllegalArgumentException("Invalid string length, must be 62.");
+ }
+ this.characters = characters;
+ }
+
+ /**
+ * Encodes a decimal value to a Base62
String
.
+ *
+ * @param b10
+ * the decimal value to encode, must be nonnegative.
+ * @return the number encoded as a Base62 String
.
+ */
+ public String encodeBase10(Long b10) {
+ if (b10 < 0) {
+ throw new IllegalArgumentException("b10 must be nonnegative");
+ }
+ String ret = "";
+ while (b10 > 0) {
+ ret = characters.charAt((int) (b10 % 62)) + ret;
+ b10 /= 62;
+ }
+ return ret;
+
+ }
+
+ /**
+ * Decodes a Base62 String
returning a long
.
+ *
+ * @param b62
+ * the Base62 String
to decode.
+ * @return the decoded number as a long
.
+ * @throws IllegalArgumentException
+ * if the given String
contains characters not
+ * specified in the constructor.
+ */
+ public long decodeBase62(String b62) {
+ for (char character : b62.toCharArray()) {
+ if (!characters.contains(String.valueOf(character))) {
+ throw new IllegalArgumentException("Invalid character(s) in string: " + character);
+ }
+ }
+ long ret = 0;
+ b62 = new StringBuffer(b62).reverse().toString();
+ long count = 1;
+ for (char character : b62.toCharArray()) {
+ ret += characters.indexOf(character) * count;
+ count *= 62;
+ }
+ return ret;
+ }
+
+}
diff --git a/src/main/java/com/rbkmoney/adapter/common/utils/converter/CardDataUtils.java b/src/main/java/com/rbkmoney/adapter/common/utils/converter/CardDataUtils.java
new file mode 100644
index 0000000..ddbb4e4
--- /dev/null
+++ b/src/main/java/com/rbkmoney/adapter/common/utils/converter/CardDataUtils.java
@@ -0,0 +1,53 @@
+package com.rbkmoney.adapter.common.utils.converter;
+
+import com.rbkmoney.damsel.cds.ExpDate;
+import com.rbkmoney.damsel.cds.SessionData;
+import lombok.AccessLevel;
+import lombok.NoArgsConstructor;
+
+import java.util.Calendar;
+
+@NoArgsConstructor(access = AccessLevel.PRIVATE)
+public class CardDataUtils {
+
+ public static String getYearFromExpDate(Short year) {
+ return String.format("%1$02d", year % 100);
+ }
+
+ public static String getYearFromExpDate(ExpDate expDate) {
+ return getYearFromExpDate(expDate.getYear());
+ }
+
+ public static String getFullDateFromExpDate(ExpDate expDate) {
+ int correctYear = expDate.getYear() / 100 == 0 ? expDate.getYear() + 2000 : expDate.getYear();
+ return String.format("%1$04d%2$02d%3$02d", correctYear, expDate.getMonth(), getDayOfMonth(expDate));
+ }
+
+ public static Integer getDayOfMonth(ExpDate expDate) {
+ Calendar calendar = Calendar.getInstance();
+ calendar.set(expDate.getYear(), expDate.getMonth(), -1);
+ return calendar.getActualMaximum(Calendar.DAY_OF_MONTH);
+ }
+
+ public static String getMonthFromExpDate(Byte month) {
+ return String.format("%1$02d", month);
+ }
+
+ public static String getMonthFromExpDate(ExpDate expDate) {
+ return String.format("%02d", expDate.getMonth());
+ }
+
+ public static String getMonthFromByte(byte month) {
+ return String.format("%02d", month);
+ }
+
+ public static String getCvv2(SessionData sessionData) {
+ if (sessionData == null
+ || sessionData.getAuthData() == null
+ || !sessionData.getAuthData().isSetCardSecurityCode()) {
+ return null;
+ }
+ return sessionData.getAuthData().getCardSecurityCode().getValue();
+ }
+
+}
diff --git a/src/main/java/com/rbkmoney/adapter/common/utils/converter/PaymentDataConverterUtils.java b/src/main/java/com/rbkmoney/adapter/common/utils/converter/PaymentDataConverterUtils.java
new file mode 100644
index 0000000..ac29ac3
--- /dev/null
+++ b/src/main/java/com/rbkmoney/adapter/common/utils/converter/PaymentDataConverterUtils.java
@@ -0,0 +1,78 @@
+package com.rbkmoney.adapter.common.utils.converter;
+
+import com.rbkmoney.adapter.common.enums.TargetStatus;
+import com.rbkmoney.damsel.domain.TargetInvoicePaymentStatus;
+import com.rbkmoney.damsel.proxy_provider.PaymentContext;
+import com.rbkmoney.damsel.proxy_provider.PaymentInfo;
+import lombok.AccessLevel;
+import lombok.NoArgsConstructor;
+
+import java.math.BigDecimal;
+import java.util.Random;
+
+@NoArgsConstructor(access = AccessLevel.PRIVATE)
+public final class PaymentDataConverterUtils {
+
+ private static final String DEFAULT_ID = "1";
+
+ public static String makeHex16length() {
+ return String.format("%016X", new Random().nextLong()).toUpperCase();
+ }
+
+ public static BigDecimal getFormattedAmount(long amount) {
+ return new BigDecimal(amount).movePointLeft(2);
+ }
+
+ public static String prepareOrder(String invoiceId) {
+ return prepareOrder(invoiceId, DEFAULT_ID);
+ }
+
+ public static String prepareOrder(PaymentInfo paymentInfo) {
+ return prepareOrder(paymentInfo.getInvoice().getId(), paymentInfo.getPayment().getId());
+ }
+
+ public static String prepareOrder(String invoiceId, String paymentId) {
+ return Long.toString(new Base62().decodeBase62(invoiceId) ^ Integer.parseInt(paymentId));
+ }
+
+ public static String extractEmail(PaymentInfo paymentInfo) {
+ if (paymentInfo == null
+ || paymentInfo.getPayment() == null
+ || paymentInfo.getPayment().getContactInfo() == null
+ || paymentInfo.getPayment().getContactInfo().getEmail() == null) {
+ return "";
+ } else {
+ return paymentInfo.getPayment().getContactInfo().getEmail();
+ }
+ }
+
+ public static TargetStatus getTargetStatus(PaymentContext paymentContext) {
+ if (paymentContext == null) {
+ throw new IllegalArgumentException("PaymentContext cannot be empty");
+ } else if (paymentContext.getSession() == null) {
+ throw new IllegalArgumentException("Payment context session cannot be empty");
+ } else {
+ return getTargetStatus(paymentContext.getSession().getTarget());
+ }
+ }
+
+ public static TargetStatus getTargetStatus(TargetInvoicePaymentStatus targetInvoicePaymentStatus) {
+ if (targetInvoicePaymentStatus == null) {
+ throw new IllegalArgumentException("Argument targetInvoicePaymentStatus cannot be empty");
+ }
+ TargetStatus targetStatus;
+ if (targetInvoicePaymentStatus.isSetProcessed()) {
+ targetStatus = TargetStatus.PROCESSED;
+ } else if (targetInvoicePaymentStatus.isSetCancelled()) {
+ targetStatus = TargetStatus.CANCELLED;
+ } else if (targetInvoicePaymentStatus.isSetCaptured()) {
+ targetStatus = TargetStatus.CAPTURED;
+ } else if (targetInvoicePaymentStatus.isSetRefunded()) {
+ targetStatus = TargetStatus.REFUNDED;
+ } else {
+ throw new IllegalStateException("Unknown target status: " + targetInvoicePaymentStatus);
+ }
+ return targetStatus;
+ }
+
+}
diff --git a/src/main/java/com/rbkmoney/adapter/common/utils/converter/RedirectUtils.java b/src/main/java/com/rbkmoney/adapter/common/utils/converter/RedirectUtils.java
new file mode 100644
index 0000000..bb806f3
--- /dev/null
+++ b/src/main/java/com/rbkmoney/adapter/common/utils/converter/RedirectUtils.java
@@ -0,0 +1,15 @@
+package com.rbkmoney.adapter.common.utils.converter;
+
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.web.util.UriComponentsBuilder;
+
+@Slf4j
+public class RedirectUtils {
+
+ public static String getCallbackUrl(String callbackUrl, String path) {
+ return UriComponentsBuilder.fromUriString(callbackUrl)
+ .path(path)
+ .build()
+ .toUriString();
+ }
+}
diff --git a/src/main/java/com/rbkmoney/adapter/common/utils/encryption/HmacEncryption.java b/src/main/java/com/rbkmoney/adapter/common/utils/encryption/HmacEncryption.java
new file mode 100644
index 0000000..d3151a7
--- /dev/null
+++ b/src/main/java/com/rbkmoney/adapter/common/utils/encryption/HmacEncryption.java
@@ -0,0 +1,74 @@
+package com.rbkmoney.adapter.common.utils.encryption;
+
+import lombok.AccessLevel;
+import lombok.NoArgsConstructor;
+import org.apache.commons.codec.binary.Hex;
+import org.springframework.util.MultiValueMap;
+
+import javax.crypto.Mac;
+import javax.crypto.spec.SecretKeySpec;
+import java.nio.charset.StandardCharsets;
+import java.util.Arrays;
+
+@NoArgsConstructor(access = AccessLevel.PRIVATE)
+public final class HmacEncryption {
+
+ public static final String HMAC_SHA1 = "HmacSHA1";
+
+ public static final String HMAC_SHA256 = "HmacSHA256";
+
+ public static String calculateHMacSha1(String data, String key) {
+ return calculateHMAC(data, key, HMAC_SHA1);
+ }
+
+ public static String calculateHMacSha256(String data, String key) {
+ return calculateHMAC(data, key, HMAC_SHA256);
+ }
+
+ public static String calculateHMAC(String data, String key, String algorithm) {
+
+ try {
+ byte[] decodedKey = Hex.decodeHex(key.toCharArray());
+ SecretKeySpec keySpec = new SecretKeySpec(decodedKey, algorithm);
+ Mac mac = Mac.getInstance(algorithm);
+ mac.init(keySpec);
+
+ byte[] dataBytes = data.getBytes(StandardCharsets.UTF_8);
+ byte[] signatureBytes = mac.doFinal(dataBytes);
+
+ return new String(new Hex().encode(signatureBytes));
+ } catch (Exception ex) {
+ throw new RuntimeException(ex);
+ }
+ }
+
+ public static String prepareDataForHmac(String[] fields, MultiValueMap