diff --git a/docker-compose.yml b/docker-compose.yml
new file mode 100644
index 0000000000000000000000000000000000000000..a1da0d2f58152f42020f11d530eb45fe947dc135
--- /dev/null
+++ b/docker-compose.yml
@@ -0,0 +1,17 @@
+version: "3.1"
+
+services:
+  db:
+    image: mysql:8.2
+    restart: always
+    environment:
+      MYSQL_DATABASE: 'db'
+      MYSQL_USER: 'user'
+      MYSQL_PASSWORD: 'password'
+      MYSQL_ROOT_PASSWORD: 'password'
+    ports:
+      - '3306:3306'
+    volumes:
+      - my-db:/var/lib/mysql
+volumes:
+  my-db:
\ No newline at end of file
diff --git a/pom.xml b/pom.xml
new file mode 100644
index 0000000000000000000000000000000000000000..8ba5d3047f79443d7ce8f83dfa73a7adb5cd038d
--- /dev/null
+++ b/pom.xml
@@ -0,0 +1,117 @@
+<?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>
+
+  <groupId>com.kms</groupId>
+  <artifactId>soap</artifactId>
+  <version>0.0</version>
+
+  <name>soap</name>
+
+  <properties>
+    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+    <maven.compiler.source>21</maven.compiler.source>
+    <maven.compiler.target>21</maven.compiler.target>
+  </properties>
+
+  <dependencies>
+    <dependency>
+      <groupId>junit</groupId>
+      <artifactId>junit</artifactId>
+      <version>4.13.1</version>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.projectlombok</groupId>
+      <artifactId>lombok</artifactId>
+      <version>1.18.30</version>
+      <scope>provided</scope>
+    </dependency>
+    <dependency>
+      <groupId>com.sun.xml.ws</groupId>
+      <artifactId>jaxws-rt</artifactId>
+      <version>2.3.6</version>
+    </dependency>
+    <dependency>
+      <groupId>com.j256.ormlite</groupId>
+      <artifactId>ormlite-jdbc</artifactId>
+      <version>6.1</version>
+    </dependency>
+    <!-- https://mvnrepository.com/artifact/com.mysql/mysql-connector-j -->
+    <dependency>
+      <groupId>com.mysql</groupId>
+      <artifactId>mysql-connector-j</artifactId>
+      <version>8.2.0</version>
+    </dependency>
+
+  </dependencies>
+
+  <build>
+    <pluginManagement><!-- lock down plugins versions to avoid using Maven defaults (may be moved to parent pom) -->
+      <plugins>
+        <!-- clean lifecycle, see https://maven.apache.org/ref/current/maven-core/lifecycles.html#clean_Lifecycle -->
+        <plugin>
+          <artifactId>maven-clean-plugin</artifactId>
+          <version>3.1.0</version>
+        </plugin>
+        <!-- default lifecycle, jar packaging: see https://maven.apache.org/ref/current/maven-core/default-bindings.html#Plugin_bindings_for_jar_packaging -->
+        <plugin>
+          <artifactId>maven-resources-plugin</artifactId>
+          <version>3.0.2</version>
+        </plugin>
+        <plugin>
+          <artifactId>maven-compiler-plugin</artifactId>
+          <version>3.8.0</version>
+        </plugin>
+        <plugin>
+          <artifactId>maven-surefire-plugin</artifactId>
+          <version>2.22.1</version>
+        </plugin>
+        <plugin>
+          <artifactId>maven-jar-plugin</artifactId>
+          <version>3.0.2</version>
+        </plugin>
+        <plugin>
+          <artifactId>maven-install-plugin</artifactId>
+          <version>2.5.2</version>
+        </plugin>
+        <plugin>
+          <artifactId>maven-deploy-plugin</artifactId>
+          <version>2.8.2</version>
+        </plugin>
+        <!-- site lifecycle, see https://maven.apache.org/ref/current/maven-core/lifecycles.html#site_Lifecycle -->
+        <plugin>
+          <artifactId>maven-site-plugin</artifactId>
+          <version>3.7.1</version>
+        </plugin>
+        <plugin>
+          <artifactId>maven-project-info-reports-plugin</artifactId>
+          <version>3.0.0</version>
+        </plugin>
+        <plugin>
+          <groupId>org.jvnet.jax-ws-commons</groupId>
+          <artifactId>jaxws-maven-plugin</artifactId>
+          <version>2.2</version>
+          <executions>
+            <execution>
+              <id>SomeId</id>
+              <goals>
+                <goal>wsgen</goal>
+              </goals>
+              <phase>prepare-package</phase>
+              <configuration>
+                <sei>com.kms.service.PaymentService</sei>
+                <genWsdl>true</genWsdl>
+                <keep>true</keep>
+                <inlineSchemas>true</inlineSchemas>
+              </configuration>
+            </execution>
+          </executions>
+        </plugin>
+
+      </plugins>
+    </pluginManagement>
+  </build>
+</project>
diff --git a/sql/ddl.sql b/sql/ddl.sql
new file mode 100644
index 0000000000000000000000000000000000000000..267190e91187a34c9b21c87e34bac5328d66c2ce
--- /dev/null
+++ b/sql/ddl.sql
@@ -0,0 +1,20 @@
+CREATE TABLE `payment` (
+   `payment_id` int NOT NULL AUTO_INCREMENT,
+   `amount` double NOT NULL,
+   `payment_init_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
+   `status_paid` tinyint(1) NOT NULL DEFAULT '0',
+   `payment_paid_time` timestamp NULL DEFAULT NULL,
+   `description` varchar(200) DEFAULT NULL,
+   `initiator_id` varchar(100) NOT NULL,
+   PRIMARY KEY (`payment_id`)
+);
+
+CREATE TABLE `log` (
+    `log_id` int NOT NULL AUTO_INCREMENT,
+    `request_description` varchar(2000) NOT NULL,
+    `origin_ip` varchar(12) NOT NULL,
+    `endpoint` varchar(100) NOT NULL,
+    `request_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
+    `caller_id` varchar(100)  NOT NULL,
+    PRIMARY KEY (`log_id`)
+);
\ No newline at end of file
diff --git a/src/main/java/com/kms/App.java b/src/main/java/com/kms/App.java
new file mode 100644
index 0000000000000000000000000000000000000000..1b28d905343e33e24cfcf13c2dc24dd844f809d1
--- /dev/null
+++ b/src/main/java/com/kms/App.java
@@ -0,0 +1,34 @@
+package com.kms;
+
+import com.j256.ormlite.dao.Dao;
+import com.j256.ormlite.dao.DaoManager;
+import com.j256.ormlite.jdbc.JdbcConnectionSource;
+import com.j256.ormlite.support.ConnectionSource;
+import com.kms.crosscut.LoggingHelper;
+import com.kms.model.Log;
+import com.kms.model.Payment;
+import com.kms.service.PaymentHistoryService;
+import com.kms.service.PaymentService;
+import com.kms.task.PaymentCompletorTask;
+
+import javax.xml.ws.Endpoint;
+import java.sql.SQLException;
+import java.util.Timer;
+
+public class App {
+    public static void main( String[] args ) throws SQLException {
+        String databaseUrl = "jdbc:mysql://localhost:3306/db?user=user&password=password";
+        ConnectionSource connectionSource = new JdbcConnectionSource(databaseUrl);
+        Dao<Payment,Integer> paymentDao =
+                DaoManager.createDao(connectionSource, Payment.class);
+        Dao<Log,Integer> logDao = DaoManager.createDao(connectionSource, Log.class);
+        LoggingHelper.init(logDao);
+
+        Timer time = new Timer();
+        PaymentCompletorTask task = new PaymentCompletorTask(paymentDao);
+        time.schedule(task, 0, 25000);
+
+        Endpoint.publish("http://localhost:8080/paymentservice", new PaymentService(paymentDao));
+        Endpoint.publish("http://localhost:8080/paymenthistory", new PaymentHistoryService(paymentDao));
+    }
+}
diff --git a/src/main/java/com/kms/crosscut/LoggingHelper.java b/src/main/java/com/kms/crosscut/LoggingHelper.java
new file mode 100644
index 0000000000000000000000000000000000000000..f5ee1b1c8950141c6dcdf6871d5d4f748e1c5e70
--- /dev/null
+++ b/src/main/java/com/kms/crosscut/LoggingHelper.java
@@ -0,0 +1,41 @@
+package com.kms.crosscut;
+
+import com.j256.ormlite.dao.Dao;
+import com.kms.model.Log;
+
+import java.sql.SQLException;
+import java.sql.Timestamp;
+
+public class LoggingHelper {
+
+    private static LoggingHelper instance = null;
+    private final Dao<Log,Integer> logDao;
+
+    public LoggingHelper(Dao<Log,Integer> logDao) {
+        this.logDao = logDao;
+    }
+
+    public static void init(Dao<Log,Integer> logDao) {
+        instance = new LoggingHelper(logDao);
+    }
+
+    public static synchronized LoggingHelper getInstance() {
+        return instance;
+    }
+
+    public void log(String description, String ip, String endpoint) {
+        Log log = Log.builder()
+                .endpoint(endpoint)
+                .originIp(ip)
+                .requestDesc(description)
+                .requestTime(new Timestamp(System.currentTimeMillis()))
+                .build();
+
+        try {
+            logDao.create(log);
+        } catch (SQLException ignored) {
+            System.out.println(ignored);
+        }
+    }
+
+}
diff --git a/src/main/java/com/kms/dto/EmailReq.java b/src/main/java/com/kms/dto/EmailReq.java
new file mode 100644
index 0000000000000000000000000000000000000000..bb417f5664f9f9f4494351060eabee0f351db0aa
--- /dev/null
+++ b/src/main/java/com/kms/dto/EmailReq.java
@@ -0,0 +1,19 @@
+package com.kms.dto;
+
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+import lombok.NoArgsConstructor;
+import lombok.Setter;
+
+@Getter
+@Setter
+@AllArgsConstructor
+@NoArgsConstructor
+public class EmailReq {
+
+    private String recipient;
+    private String cc;
+    private String subject;
+    private String body;
+
+}
diff --git a/src/main/java/com/kms/dto/PaymentHistoryResp.java b/src/main/java/com/kms/dto/PaymentHistoryResp.java
new file mode 100644
index 0000000000000000000000000000000000000000..754d58650fb4ab51b59aa102370c6be675d81021
--- /dev/null
+++ b/src/main/java/com/kms/dto/PaymentHistoryResp.java
@@ -0,0 +1,21 @@
+package com.kms.dto;
+
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+import lombok.NoArgsConstructor;
+import lombok.Setter;
+
+import java.sql.Timestamp;
+
+@Getter
+@Setter
+@AllArgsConstructor
+@NoArgsConstructor
+public class PaymentHistoryResp {
+
+    private String paymentInitTime;
+    private String paymentPaidTime;
+    private double amount;
+    private String description;
+
+}
diff --git a/src/main/java/com/kms/dto/PaymentInitReq.java b/src/main/java/com/kms/dto/PaymentInitReq.java
new file mode 100644
index 0000000000000000000000000000000000000000..2bf3707b8a5d1a7b5badd35eb3d9cfe1e75484f0
--- /dev/null
+++ b/src/main/java/com/kms/dto/PaymentInitReq.java
@@ -0,0 +1,21 @@
+package com.kms.dto;
+
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+import lombok.NoArgsConstructor;
+import lombok.Setter;
+
+import javax.xml.bind.annotation.XmlElement;
+import javax.xml.bind.annotation.XmlRootElement;
+
+@Getter @Setter
+@AllArgsConstructor
+@NoArgsConstructor
+@XmlRootElement
+public class PaymentInitReq {
+
+    private double amount;
+    private String description;
+    private String initiatorId;
+
+}
diff --git a/src/main/java/com/kms/dto/PaymentInitResp.java b/src/main/java/com/kms/dto/PaymentInitResp.java
new file mode 100644
index 0000000000000000000000000000000000000000..e9e18c3750839fd5255b4b928f46f0e95e494a52
--- /dev/null
+++ b/src/main/java/com/kms/dto/PaymentInitResp.java
@@ -0,0 +1,17 @@
+package com.kms.dto;
+
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+import lombok.NoArgsConstructor;
+import lombok.Setter;
+
+@Getter
+@Setter
+@AllArgsConstructor
+@NoArgsConstructor
+public class PaymentInitResp {
+
+    private Integer paymentId;
+    private boolean success;
+
+}
diff --git a/src/main/java/com/kms/dto/PaymentStatusResp.java b/src/main/java/com/kms/dto/PaymentStatusResp.java
new file mode 100644
index 0000000000000000000000000000000000000000..d24d0cdc16ad5762cb338e1cf93ccef5cf1f123f
--- /dev/null
+++ b/src/main/java/com/kms/dto/PaymentStatusResp.java
@@ -0,0 +1,19 @@
+package com.kms.dto;
+
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Getter;
+import lombok.NoArgsConstructor;
+import lombok.Setter;
+
+@Getter
+@Setter
+@AllArgsConstructor
+@NoArgsConstructor
+@Builder
+public class PaymentStatusResp {
+
+    private Boolean paid;
+    private String description;
+
+}
diff --git a/src/main/java/com/kms/handler/LogHandler.java b/src/main/java/com/kms/handler/LogHandler.java
new file mode 100644
index 0000000000000000000000000000000000000000..d9d5a495863506f38db0e5cadbd7944fced2f8f9
--- /dev/null
+++ b/src/main/java/com/kms/handler/LogHandler.java
@@ -0,0 +1,61 @@
+package com.kms.handler;
+
+import com.kms.crosscut.LoggingHelper;
+import com.sun.net.httpserver.HttpExchange;
+import com.sun.xml.ws.developer.JAXWSProperties;
+
+import javax.xml.namespace.QName;
+import javax.xml.soap.SOAPBody;
+import javax.xml.soap.SOAPException;
+import javax.xml.ws.handler.MessageContext;
+import javax.xml.ws.handler.soap.SOAPHandler;
+import javax.xml.ws.handler.soap.SOAPMessageContext;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.net.InetSocketAddress;
+import java.util.Set;
+
+public class LogHandler implements SOAPHandler<SOAPMessageContext> {
+
+    @Override
+    public Set<QName> getHeaders() {
+        return null;
+    }
+
+    @Override
+    public boolean handleMessage(SOAPMessageContext soapMessageContext) {
+        boolean messageHandled = (boolean) soapMessageContext.getOrDefault("messageHandled", false);
+
+        if (messageHandled) {
+            return true;
+        }
+
+        soapMessageContext.put("messageHandled", true);
+
+        HttpExchange exchange = (HttpExchange)soapMessageContext.get(JAXWSProperties.HTTP_EXCHANGE);
+        InetSocketAddress remoteAddress = exchange.getRemoteAddress();
+        String remoteHost = remoteAddress.getHostName();
+
+        try {
+            SOAPBody soapBody = soapMessageContext.getMessage().getSOAPBody();
+            OutputStream outputStream = new ByteArrayOutputStream();
+            soapMessageContext.getMessage().writeTo(outputStream);
+
+            LoggingHelper loggingHelper = LoggingHelper.getInstance();
+            loggingHelper.log(outputStream.toString(), remoteHost, soapBody.getChildNodes().item(1).getNodeName());
+        } catch (SOAPException | IOException ignored) {
+        }
+        return true;
+    }
+
+    @Override
+    public boolean handleFault(SOAPMessageContext soapMessageContext) {
+        return false;
+    }
+
+    @Override
+    public void close(MessageContext messageContext) {
+
+    }
+}
diff --git a/src/main/java/com/kms/model/Log.java b/src/main/java/com/kms/model/Log.java
new file mode 100644
index 0000000000000000000000000000000000000000..a2e683d3cadd4bd22382e8678d1c3528f27d5c5f
--- /dev/null
+++ b/src/main/java/com/kms/model/Log.java
@@ -0,0 +1,34 @@
+package com.kms.model;
+
+import com.j256.ormlite.field.DatabaseField;
+import com.j256.ormlite.table.DatabaseTable;
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Getter;
+import lombok.NoArgsConstructor;
+import lombok.Setter;
+
+import java.sql.Timestamp;
+
+@AllArgsConstructor
+@Getter
+@Setter
+@NoArgsConstructor
+@DatabaseTable(tableName = "log")
+@Builder
+public class Log {
+
+    @DatabaseField(generatedId = true, columnName = "log_id")
+    private Integer id;
+    @DatabaseField(columnName = "request_description")
+    private String requestDesc;
+    @DatabaseField(columnName = "origin_ip")
+    private String originIp;
+    @DatabaseField(columnName = "endpoint")
+    private String endpoint;
+    @DatabaseField(columnName = "request_time")
+    private Timestamp requestTime;
+    @DatabaseField(columnName = "caller_id")
+    private String callerId;
+
+}
diff --git a/src/main/java/com/kms/model/Payment.java b/src/main/java/com/kms/model/Payment.java
new file mode 100644
index 0000000000000000000000000000000000000000..89fba01d3a284a5b3dafd177a06748ca5b97b908
--- /dev/null
+++ b/src/main/java/com/kms/model/Payment.java
@@ -0,0 +1,36 @@
+package com.kms.model;
+
+import com.j256.ormlite.field.DatabaseField;
+import com.j256.ormlite.table.DatabaseTable;
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Getter;
+import lombok.NoArgsConstructor;
+import lombok.Setter;
+
+import java.sql.Timestamp;
+
+@AllArgsConstructor
+@Getter @Setter
+@NoArgsConstructor
+@DatabaseTable(tableName = "payment")
+@Builder
+public class Payment {
+
+    @DatabaseField(generatedId = true, columnName = "payment_id")
+    private Integer paymentId;
+    @DatabaseField(columnName = "amount")
+    private double amount;
+    @DatabaseField(columnName = "payment_init_time")
+    private Timestamp paymentInitTime;
+    @DatabaseField(columnName = "status_paid")
+    private boolean paid;
+    @DatabaseField(columnName = "payment_paid_time")
+    private Timestamp paymentPaidTime;
+    @DatabaseField(columnName = "description")
+    private String description;
+    @DatabaseField(columnName = "initiator_id")
+    private String initiatorId;
+
+
+}
diff --git a/src/main/java/com/kms/repository/LogRepository.java b/src/main/java/com/kms/repository/LogRepository.java
new file mode 100644
index 0000000000000000000000000000000000000000..4efdb0c775017f073fae8c55a32cfb6cdbb41053
--- /dev/null
+++ b/src/main/java/com/kms/repository/LogRepository.java
@@ -0,0 +1,34 @@
+package com.kms.repository;
+
+import com.j256.ormlite.dao.Dao;
+import com.j256.ormlite.dao.DaoManager;
+import com.j256.ormlite.jdbc.JdbcConnectionSource;
+import com.j256.ormlite.support.ConnectionSource;
+import com.kms.crosscut.LoggingHelper;
+import com.kms.model.Log;
+import lombok.RequiredArgsConstructor;
+
+import java.sql.SQLException;
+
+@RequiredArgsConstructor
+public class LogRepository {
+
+    private final Dao<Log,Integer> logDao;
+    private static LogRepository instance;
+
+    private static void init() {
+        try {
+            String databaseUrl = "jdbc:mysql://localhost:3306/db?user=user&password=password";
+            ConnectionSource connectionSource = new JdbcConnectionSource(databaseUrl);
+            instance = new LogRepository(DaoManager.createDao(connectionSource, Log.class));
+        } catch (SQLException e) {
+        }
+    }
+
+    public static synchronized LogRepository getInstance() {
+        return instance;
+    }
+
+
+
+}
diff --git a/src/main/java/com/kms/repository/PaymentRepository.java b/src/main/java/com/kms/repository/PaymentRepository.java
new file mode 100644
index 0000000000000000000000000000000000000000..7ab4d24eafcbd5ba658b05d68942b5bf0f3955ad
--- /dev/null
+++ b/src/main/java/com/kms/repository/PaymentRepository.java
@@ -0,0 +1,33 @@
+package com.kms.repository;
+
+import com.j256.ormlite.dao.Dao;
+import com.j256.ormlite.dao.DaoManager;
+import com.j256.ormlite.jdbc.JdbcConnectionSource;
+import com.j256.ormlite.support.ConnectionSource;
+import com.kms.model.Log;
+import com.kms.model.Payment;
+import lombok.RequiredArgsConstructor;
+
+import java.sql.SQLException;
+
+@RequiredArgsConstructor
+public class PaymentRepository {
+
+    private final Dao<Payment,Integer> paymentDao;
+    private static PaymentRepository instance;
+
+    private static void init() {
+        try {
+            String databaseUrl = "jdbc:mysql://localhost:3306/db?user=user&password=password";
+            ConnectionSource connectionSource = new JdbcConnectionSource(databaseUrl);
+            instance = new PaymentRepository(DaoManager.createDao(connectionSource, Payment.class));
+        } catch (SQLException e) {
+        }
+    }
+
+    public static synchronized PaymentRepository getInstance() {
+        return instance;
+    }
+
+
+}
diff --git a/src/main/java/com/kms/service/EmailService.java b/src/main/java/com/kms/service/EmailService.java
new file mode 100644
index 0000000000000000000000000000000000000000..fbf023487737e499034375f243869d491c42c750
--- /dev/null
+++ b/src/main/java/com/kms/service/EmailService.java
@@ -0,0 +1,22 @@
+package com.kms.service;
+
+import com.kms.util.EmailUtil;
+
+public class EmailService {
+
+    public static void send(String recipient, String cc, String subject, String body) {
+        if (recipient == null || recipient.isEmpty() || !EmailUtil.isEmailValid(recipient)) {
+            return;
+        }
+
+        for (String x: cc.split(",")) {
+            x = x.trim();
+            if (!EmailUtil.isEmailValid(x)) {
+                return;
+            }
+        }
+
+        // TODO: send with smtp
+    }
+
+}
diff --git a/src/main/java/com/kms/service/PaymentHistoryService.java b/src/main/java/com/kms/service/PaymentHistoryService.java
new file mode 100644
index 0000000000000000000000000000000000000000..81fd853108f5a7c874177723fa03297e8ea4870c
--- /dev/null
+++ b/src/main/java/com/kms/service/PaymentHistoryService.java
@@ -0,0 +1,48 @@
+package com.kms.service;
+
+import com.j256.ormlite.dao.Dao;
+import com.kms.dto.EmailReq;
+import com.kms.dto.PaymentHistoryResp;
+
+import com.kms.model.Payment;
+import lombok.RequiredArgsConstructor;
+
+import javax.jws.HandlerChain;
+import javax.jws.WebMethod;
+import javax.jws.WebParam;
+import javax.jws.WebService;
+import java.sql.SQLException;
+import java.util.List;
+
+@WebService
+@RequiredArgsConstructor
+@HandlerChain(file = "handlers.xml")
+public class PaymentHistoryService {
+
+    private final Dao<Payment,Integer> paymentDao;
+
+    @WebMethod
+    public List<PaymentHistoryResp> getPaymentHistory(@WebParam(name = "initiatorId") String initiatorId,
+                                                      @WebParam(name = "sendMail") boolean sendMail,
+                                                      @WebParam(name = "mailData") EmailReq emailReq) {
+        try {
+            Payment filter = Payment.builder()
+                    .initiatorId(initiatorId)
+                    .paid(true)
+                    .build();
+            List<Payment> payments = paymentDao.queryForMatching(filter);
+
+            if (sendMail && emailReq != null) {
+                EmailService.send(emailReq.getRecipient(), emailReq.getCc(), emailReq.getSubject(), emailReq.getBody());
+            }
+
+            return payments.stream()
+                    .map(el -> new PaymentHistoryResp(el.getPaymentInitTime().toString(), el.getPaymentPaidTime().toString(),
+                                    el.getAmount(), el.getDescription()))
+                    .toList();
+        } catch (SQLException e) {
+            throw new RuntimeException(e);
+        }
+    }
+
+}
diff --git a/src/main/java/com/kms/service/PaymentService.java b/src/main/java/com/kms/service/PaymentService.java
new file mode 100644
index 0000000000000000000000000000000000000000..1ebe4e5eae23885c1c6cdacf7bf8e69338b41042
--- /dev/null
+++ b/src/main/java/com/kms/service/PaymentService.java
@@ -0,0 +1,58 @@
+package com.kms.service;
+
+import com.j256.ormlite.dao.Dao;
+import com.kms.dto.PaymentInitReq;
+import com.kms.dto.PaymentInitResp;
+import com.kms.dto.PaymentStatusResp;
+import com.kms.model.Payment;
+import lombok.RequiredArgsConstructor;
+
+import javax.annotation.Resource;
+import javax.jws.HandlerChain;
+import javax.jws.WebMethod;
+import javax.jws.WebParam;
+import javax.jws.WebService;
+import java.sql.SQLException;
+import java.sql.Timestamp;
+
+@WebService
+@HandlerChain(file = "handlers.xml")
+@RequiredArgsConstructor
+public class PaymentService {
+
+    private final Dao<Payment,Integer> paymentDao;
+
+
+    @WebMethod
+    public PaymentInitResp initPayment(@WebParam(name = "req") PaymentInitReq req) {
+        Payment payment = Payment.builder()
+                .amount(req.getAmount())
+                .paymentInitTime(new Timestamp(System.currentTimeMillis()))
+                .initiatorId(req.getInitiatorId())
+                .description(req.getDescription())
+                .build();
+
+        try {
+            paymentDao.create(payment);
+        } catch (SQLException e) {
+            return new PaymentInitResp(null, false);
+        }
+
+        return new PaymentInitResp(payment.getPaymentId(), true);
+    }
+
+    @WebMethod
+    public PaymentStatusResp checkPaymentStatus(@WebParam(name = "paymentId") Integer paymentId) {
+        try {
+            Payment payment = paymentDao.queryForId(paymentId);
+
+            if (payment == null) {
+                return new PaymentStatusResp(null, "Payment id not found");
+            }
+
+            return new PaymentStatusResp(payment.isPaid(), null);
+        } catch (SQLException e) {
+            return new PaymentStatusResp(null, "Unexpected error has happened");
+        }
+    }
+}
diff --git a/src/main/java/com/kms/task/PaymentCompletorTask.java b/src/main/java/com/kms/task/PaymentCompletorTask.java
new file mode 100644
index 0000000000000000000000000000000000000000..592a2f94b181389668a0b8be502cfd1b707b4cf8
--- /dev/null
+++ b/src/main/java/com/kms/task/PaymentCompletorTask.java
@@ -0,0 +1,32 @@
+package com.kms.task;
+
+import com.j256.ormlite.dao.Dao;
+import com.kms.model.Payment;
+
+import java.sql.SQLException;
+import java.util.List;
+import java.util.TimerTask;
+
+public class PaymentCompletorTask extends TimerTask {
+
+    private final Dao<Payment, Integer> paymentDao;
+
+    public PaymentCompletorTask(Dao<Payment, Integer> paymentDao) {
+        this.paymentDao = paymentDao;
+    }
+
+    @Override
+    public void run() {
+        try {
+            List<Payment> paymentsNotDone = paymentDao.queryForEq("status_paid", 0);
+
+            for (Payment p: paymentsNotDone) {
+                p.setPaid(true);
+                paymentDao.update(p);
+            }
+        } catch (SQLException e) {
+            throw new RuntimeException(e);
+        }
+
+    }
+}
diff --git a/src/main/java/com/kms/util/EmailUtil.java b/src/main/java/com/kms/util/EmailUtil.java
new file mode 100644
index 0000000000000000000000000000000000000000..99f4928b05355541371b864b21789fb933a3e8df
--- /dev/null
+++ b/src/main/java/com/kms/util/EmailUtil.java
@@ -0,0 +1,18 @@
+package com.kms.util;
+
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+public class EmailUtil {
+
+    private static final String EMAIL_PATTERN =
+            "^[_A-Za-z0-9-]+(\\.[_A-Za-z0-9-]+)*@[A-Za-z0-9]+(\\.[A-Za-z0-9]+)*(\\.[A-Za-z]{2,})$";
+
+    private static final Pattern pattern = Pattern.compile(EMAIL_PATTERN);
+
+    public static boolean isEmailValid(String email) {
+        Matcher matcher = pattern.matcher(email);
+        return matcher.matches();
+    }
+
+}
diff --git a/src/main/resources/handlers.xml b/src/main/resources/handlers.xml
new file mode 100644
index 0000000000000000000000000000000000000000..033b4d965df9095b8bc7d3020ade2099bc62a05d
--- /dev/null
+++ b/src/main/resources/handlers.xml
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<handler-chains xmlns="http://java.sun.com/xml/ns/javaee">
+    <handler-chain>
+        <handler>
+            <handler-class>com.kms.handler.LogHandler</handler-class>
+        </handler>
+    </handler-chain>
+</handler-chains>