completed initial setup
This commit is contained in:
20
pom.xml
20
pom.xml
@@ -83,6 +83,26 @@
|
|||||||
<artifactId>commons-collections4</artifactId>
|
<artifactId>commons-collections4</artifactId>
|
||||||
<version>4.4</version>
|
<version>4.4</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>jakarta.persistence</groupId>
|
||||||
|
<artifactId>jakarta.persistence-api</artifactId>
|
||||||
|
<version>3.1.0</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.googlecode.libphonenumber</groupId>
|
||||||
|
<artifactId>libphonenumber</artifactId>
|
||||||
|
<version>8.12.10</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.google.code.gson</groupId>
|
||||||
|
<artifactId>gson</artifactId>
|
||||||
|
<version>2.10.1</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.json</groupId>
|
||||||
|
<artifactId>json</artifactId>
|
||||||
|
<version>20231013</version> <!-- Use the latest version available -->
|
||||||
|
</dependency>
|
||||||
</dependencies>
|
</dependencies>
|
||||||
|
|
||||||
<build>
|
<build>
|
||||||
|
|||||||
@@ -0,0 +1,18 @@
|
|||||||
|
package zw.qantra.tm.domain.controllers;
|
||||||
|
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
import org.springframework.http.ResponseEntity;
|
||||||
|
import org.springframework.web.bind.annotation.PostMapping;
|
||||||
|
import org.springframework.web.bind.annotation.RequestBody;
|
||||||
|
import org.springframework.web.bind.annotation.RequestMapping;
|
||||||
|
import org.springframework.web.bind.annotation.RestController;
|
||||||
|
|
||||||
|
@RestController
|
||||||
|
@RequestMapping("/confirm/transaction")
|
||||||
|
@RequiredArgsConstructor
|
||||||
|
public class ConfirmationController {
|
||||||
|
@PostMapping()
|
||||||
|
public ResponseEntity post(@RequestBody Object transactionRequest) {
|
||||||
|
return ResponseEntity.ok("Transaction endpoint is working");
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,18 @@
|
|||||||
|
package zw.qantra.tm.domain.controllers;
|
||||||
|
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
import org.springframework.http.ResponseEntity;
|
||||||
|
import org.springframework.web.bind.annotation.PostMapping;
|
||||||
|
import org.springframework.web.bind.annotation.RequestBody;
|
||||||
|
import org.springframework.web.bind.annotation.RequestMapping;
|
||||||
|
import org.springframework.web.bind.annotation.RestController;
|
||||||
|
|
||||||
|
@RestController
|
||||||
|
@RequestMapping("/integration/transaction")
|
||||||
|
@RequiredArgsConstructor
|
||||||
|
public class IntegrationController {
|
||||||
|
@PostMapping()
|
||||||
|
public ResponseEntity post(@RequestBody Object transactionRequest) {
|
||||||
|
return ResponseEntity.ok("Transaction endpoint is working");
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,18 @@
|
|||||||
|
package zw.qantra.tm.domain.controllers;
|
||||||
|
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
import org.springframework.http.ResponseEntity;
|
||||||
|
import org.springframework.web.bind.annotation.PostMapping;
|
||||||
|
import org.springframework.web.bind.annotation.RequestBody;
|
||||||
|
import org.springframework.web.bind.annotation.RequestMapping;
|
||||||
|
import org.springframework.web.bind.annotation.RestController;
|
||||||
|
|
||||||
|
@RestController
|
||||||
|
@RequestMapping("/transaction")
|
||||||
|
@RequiredArgsConstructor
|
||||||
|
public class TransactonController {
|
||||||
|
@PostMapping()
|
||||||
|
public ResponseEntity post(@RequestBody Object transactionRequest) {
|
||||||
|
return ResponseEntity.ok("Transaction endpoint is working");
|
||||||
|
}
|
||||||
|
}
|
||||||
6
src/main/java/zw/qantra/tm/domain/enums/RequestType.java
Normal file
6
src/main/java/zw/qantra/tm/domain/enums/RequestType.java
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
package zw.qantra.tm.domain.enums;
|
||||||
|
|
||||||
|
public enum RequestType {
|
||||||
|
REQUEST,
|
||||||
|
CONFIRM
|
||||||
|
}
|
||||||
@@ -0,0 +1,52 @@
|
|||||||
|
package zw.qantra.tm.domain.models;
|
||||||
|
|
||||||
|
import jakarta.persistence.Entity;
|
||||||
|
import jakarta.persistence.GeneratedValue;
|
||||||
|
import jakarta.persistence.GenerationType;
|
||||||
|
import jakarta.persistence.Id;
|
||||||
|
import lombok.*;
|
||||||
|
import zw.qantra.tm.domain.enums.RequestType;
|
||||||
|
|
||||||
|
import java.math.BigDecimal;
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
@Entity
|
||||||
|
@Getter
|
||||||
|
@Setter
|
||||||
|
@Builder
|
||||||
|
@AllArgsConstructor
|
||||||
|
@NoArgsConstructor
|
||||||
|
public class ConfirmTransaction {
|
||||||
|
@Id
|
||||||
|
@GeneratedValue(strategy = GenerationType.UUID)
|
||||||
|
private UUID id;
|
||||||
|
|
||||||
|
private String trace;
|
||||||
|
private BigDecimal amount;
|
||||||
|
private String reference;
|
||||||
|
private String providerUid;
|
||||||
|
private String productUid;
|
||||||
|
private String paymentProcessorLabel;
|
||||||
|
private String integrationProcessorLabel;
|
||||||
|
private String rrn;
|
||||||
|
private String channelName;
|
||||||
|
private String channel;
|
||||||
|
private String debitPhone;
|
||||||
|
private String debitAccount;
|
||||||
|
private String debitCurrency;
|
||||||
|
private String debitName;
|
||||||
|
private String debitCard;
|
||||||
|
private String debitRef;
|
||||||
|
private String creditPhone;
|
||||||
|
private String creditAccount;
|
||||||
|
private String creditCurrency;
|
||||||
|
private String creditName;
|
||||||
|
private String creditCard;
|
||||||
|
private String creditRef;
|
||||||
|
private String billClientId;
|
||||||
|
private String clientSecret;
|
||||||
|
private String aggregatorId;
|
||||||
|
private String billName;
|
||||||
|
private String billProductName;
|
||||||
|
private RequestType type;
|
||||||
|
}
|
||||||
25
src/main/java/zw/qantra/tm/domain/models/Currency.java
Normal file
25
src/main/java/zw/qantra/tm/domain/models/Currency.java
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
package zw.qantra.tm.domain.models;
|
||||||
|
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
import jakarta.persistence.Entity;
|
||||||
|
import jakarta.persistence.GeneratedValue;
|
||||||
|
import jakarta.persistence.GenerationType;
|
||||||
|
import jakarta.persistence.Id;
|
||||||
|
import lombok.*;
|
||||||
|
|
||||||
|
@Entity
|
||||||
|
@Getter
|
||||||
|
@Setter
|
||||||
|
@Builder
|
||||||
|
@AllArgsConstructor
|
||||||
|
@NoArgsConstructor
|
||||||
|
public class Currency {
|
||||||
|
@Id
|
||||||
|
@GeneratedValue(strategy = GenerationType.UUID)
|
||||||
|
private UUID id;
|
||||||
|
|
||||||
|
private String isoCode;
|
||||||
|
private String name;
|
||||||
|
private String displayName;
|
||||||
|
}
|
||||||
@@ -0,0 +1,25 @@
|
|||||||
|
package zw.qantra.tm.domain.models;
|
||||||
|
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
import jakarta.persistence.Entity;
|
||||||
|
import jakarta.persistence.GeneratedValue;
|
||||||
|
import jakarta.persistence.GenerationType;
|
||||||
|
import jakarta.persistence.Id;
|
||||||
|
import lombok.*;
|
||||||
|
|
||||||
|
@Entity
|
||||||
|
@Getter
|
||||||
|
@Setter
|
||||||
|
@Builder
|
||||||
|
@AllArgsConstructor
|
||||||
|
@NoArgsConstructor
|
||||||
|
public class IntegrationProcessor {
|
||||||
|
@Id
|
||||||
|
@GeneratedValue(strategy = GenerationType.UUID)
|
||||||
|
private UUID id;
|
||||||
|
|
||||||
|
private String name;
|
||||||
|
private String description;
|
||||||
|
private String type;
|
||||||
|
}
|
||||||
@@ -0,0 +1,26 @@
|
|||||||
|
package zw.qantra.tm.domain.models;
|
||||||
|
|
||||||
|
import jakarta.persistence.Entity;
|
||||||
|
import jakarta.persistence.GeneratedValue;
|
||||||
|
import jakarta.persistence.GenerationType;
|
||||||
|
import jakarta.persistence.Id;
|
||||||
|
import lombok.*;
|
||||||
|
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
@Entity
|
||||||
|
@Getter
|
||||||
|
@Setter
|
||||||
|
@Builder
|
||||||
|
@AllArgsConstructor
|
||||||
|
@NoArgsConstructor
|
||||||
|
public class PaymentProcessor {
|
||||||
|
@Id
|
||||||
|
@GeneratedValue(strategy = GenerationType.UUID)
|
||||||
|
private UUID id;
|
||||||
|
|
||||||
|
private String name;
|
||||||
|
private String description;
|
||||||
|
private String label;
|
||||||
|
private String type;
|
||||||
|
}
|
||||||
25
src/main/java/zw/qantra/tm/domain/models/Provider.java
Normal file
25
src/main/java/zw/qantra/tm/domain/models/Provider.java
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
package zw.qantra.tm.domain.models;
|
||||||
|
|
||||||
|
import jakarta.persistence.Entity;
|
||||||
|
import jakarta.persistence.GeneratedValue;
|
||||||
|
import jakarta.persistence.GenerationType;
|
||||||
|
import jakarta.persistence.Id;
|
||||||
|
import lombok.*;
|
||||||
|
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
@Entity
|
||||||
|
@Getter
|
||||||
|
@Setter
|
||||||
|
@Builder
|
||||||
|
@AllArgsConstructor
|
||||||
|
@NoArgsConstructor
|
||||||
|
public class Provider {
|
||||||
|
@Id
|
||||||
|
@GeneratedValue(strategy = GenerationType.UUID)
|
||||||
|
private UUID id;
|
||||||
|
|
||||||
|
private String clientId;
|
||||||
|
private String name;
|
||||||
|
private String description;
|
||||||
|
}
|
||||||
28
src/main/java/zw/qantra/tm/domain/models/Setting.java
Normal file
28
src/main/java/zw/qantra/tm/domain/models/Setting.java
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
package zw.qantra.tm.domain.models;
|
||||||
|
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
import jakarta.persistence.Entity;
|
||||||
|
import jakarta.persistence.GeneratedValue;
|
||||||
|
import jakarta.persistence.GenerationType;
|
||||||
|
import jakarta.persistence.Id;
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.Builder;
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.NoArgsConstructor;
|
||||||
|
import lombok.Setter;
|
||||||
|
|
||||||
|
@Entity
|
||||||
|
@Getter
|
||||||
|
@Setter
|
||||||
|
@Builder
|
||||||
|
@AllArgsConstructor
|
||||||
|
@NoArgsConstructor
|
||||||
|
public class Setting {
|
||||||
|
@Id
|
||||||
|
@GeneratedValue(strategy = GenerationType.UUID)
|
||||||
|
private UUID id;
|
||||||
|
|
||||||
|
private String name;
|
||||||
|
private String value;
|
||||||
|
}
|
||||||
49
src/main/java/zw/qantra/tm/domain/models/Transaction.java
Normal file
49
src/main/java/zw/qantra/tm/domain/models/Transaction.java
Normal file
@@ -0,0 +1,49 @@
|
|||||||
|
package zw.qantra.tm.domain.models;
|
||||||
|
|
||||||
|
import jakarta.persistence.*;
|
||||||
|
import lombok.*;
|
||||||
|
import zw.qantra.tm.domain.enums.RequestType;
|
||||||
|
|
||||||
|
import java.math.BigDecimal;
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
@Entity
|
||||||
|
@Getter
|
||||||
|
@Setter
|
||||||
|
@Builder
|
||||||
|
@AllArgsConstructor
|
||||||
|
@NoArgsConstructor
|
||||||
|
public class Transaction {
|
||||||
|
@Id
|
||||||
|
@GeneratedValue(strategy = GenerationType.UUID)
|
||||||
|
private UUID id;
|
||||||
|
|
||||||
|
private String trace;
|
||||||
|
private BigDecimal amount;
|
||||||
|
private String reference;
|
||||||
|
private String providerUid;
|
||||||
|
private String productUid;
|
||||||
|
private String paymentProcessorLabel;
|
||||||
|
private String integrationProcessorLabel;
|
||||||
|
private String rrn;
|
||||||
|
private String channelName;
|
||||||
|
private String channel;
|
||||||
|
private String debitPhone;
|
||||||
|
private String debitAccount;
|
||||||
|
private String debitCurrency;
|
||||||
|
private String debitName;
|
||||||
|
private String debitCard;
|
||||||
|
private String debitRef;
|
||||||
|
private String creditPhone;
|
||||||
|
private String creditAccount;
|
||||||
|
private String creditCurrency;
|
||||||
|
private String creditName;
|
||||||
|
private String creditCard;
|
||||||
|
private String creditRef;
|
||||||
|
private String billClientId;
|
||||||
|
private String clientSecret;
|
||||||
|
private String aggregatorId;
|
||||||
|
private String billName;
|
||||||
|
private String billProductName;
|
||||||
|
private RequestType type;
|
||||||
|
}
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
package zw.qantra.tm.domain.repositories;
|
||||||
|
|
||||||
|
import org.springframework.data.jpa.repository.JpaRepository;
|
||||||
|
import org.springframework.stereotype.Repository;
|
||||||
|
import zw.qantra.tm.domain.models.ConfirmTransaction;
|
||||||
|
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
@Repository
|
||||||
|
public interface ConfirmTransactionRepository extends JpaRepository<ConfirmTransaction, UUID> {
|
||||||
|
}
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
package zw.qantra.tm.domain.repositories;
|
||||||
|
|
||||||
|
import org.springframework.data.jpa.repository.JpaRepository;
|
||||||
|
import org.springframework.stereotype.Repository;
|
||||||
|
import zw.qantra.tm.domain.models.Currency;
|
||||||
|
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
@Repository
|
||||||
|
public interface CurrencyRepository extends JpaRepository<Currency, UUID> {
|
||||||
|
}
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
package zw.qantra.tm.domain.repositories;
|
||||||
|
|
||||||
|
import org.springframework.data.jpa.repository.JpaRepository;
|
||||||
|
import org.springframework.stereotype.Repository;
|
||||||
|
import zw.qantra.tm.domain.models.IntegrationProcessor;
|
||||||
|
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
@Repository
|
||||||
|
public interface IntegrationProcessorRepository extends JpaRepository<IntegrationProcessor, UUID> {
|
||||||
|
}
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
package zw.qantra.tm.domain.repositories;
|
||||||
|
|
||||||
|
import org.springframework.data.jpa.repository.JpaRepository;
|
||||||
|
import org.springframework.stereotype.Repository;
|
||||||
|
import zw.qantra.tm.domain.models.PaymentProcessor;
|
||||||
|
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
@Repository
|
||||||
|
public interface PaymentProcessorRepository extends JpaRepository<PaymentProcessor, UUID> {
|
||||||
|
}
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
package zw.qantra.tm.domain.repositories;
|
||||||
|
|
||||||
|
import org.springframework.data.jpa.repository.JpaRepository;
|
||||||
|
import org.springframework.stereotype.Repository;
|
||||||
|
import zw.qantra.tm.domain.models.Provider;
|
||||||
|
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
@Repository
|
||||||
|
public interface ProviderRepository extends JpaRepository<Provider, UUID> {
|
||||||
|
}
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
package zw.qantra.tm.domain.repositories;
|
||||||
|
|
||||||
|
import org.springframework.data.jpa.repository.JpaRepository;
|
||||||
|
import org.springframework.stereotype.Repository;
|
||||||
|
import zw.qantra.tm.domain.models.Setting;
|
||||||
|
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
@Repository
|
||||||
|
public interface SettingRepository extends JpaRepository<Setting, UUID> {
|
||||||
|
}
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
package zw.qantra.tm.domain.repositories;
|
||||||
|
|
||||||
|
import org.springframework.data.jpa.repository.JpaRepository;
|
||||||
|
import org.springframework.stereotype.Repository;
|
||||||
|
import zw.qantra.tm.domain.models.Transaction;
|
||||||
|
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
@Repository
|
||||||
|
public interface TransactionRepository extends JpaRepository<Transaction, UUID> {
|
||||||
|
}
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
package zw.qantra.tm.domain.services;
|
||||||
|
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
import zw.qantra.tm.domain.repositories.ConfirmTransactionRepository;
|
||||||
|
|
||||||
|
@Service
|
||||||
|
@RequiredArgsConstructor
|
||||||
|
public class ConfirmTransactionService {
|
||||||
|
private final ConfirmTransactionRepository confirmTransactionRepository;
|
||||||
|
}
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
package zw.qantra.tm.domain.services;
|
||||||
|
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
import zw.qantra.tm.domain.repositories.CurrencyRepository;
|
||||||
|
|
||||||
|
@Service
|
||||||
|
@RequiredArgsConstructor
|
||||||
|
public class CurrencyService {
|
||||||
|
private final CurrencyRepository currencyRepository;
|
||||||
|
}
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
package zw.qantra.tm.domain.services;
|
||||||
|
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
import zw.qantra.tm.domain.repositories.IntegrationProcessorRepository;
|
||||||
|
|
||||||
|
@Service
|
||||||
|
@RequiredArgsConstructor
|
||||||
|
public class IntegrationProcessorService {
|
||||||
|
private final IntegrationProcessorRepository integrationProcessorRepository;
|
||||||
|
}
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
package zw.qantra.tm.domain.services;
|
||||||
|
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
import zw.qantra.tm.domain.repositories.PaymentProcessorRepository;
|
||||||
|
|
||||||
|
@Service
|
||||||
|
@RequiredArgsConstructor
|
||||||
|
public class PaymentProcessorService {
|
||||||
|
private final PaymentProcessorRepository paymentProcessorRepository;
|
||||||
|
}
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
package zw.qantra.tm.domain.services;
|
||||||
|
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
import zw.qantra.tm.domain.repositories.ProviderRepository;
|
||||||
|
|
||||||
|
@Service
|
||||||
|
@RequiredArgsConstructor
|
||||||
|
public class ProviderService {
|
||||||
|
private final ProviderRepository providerRepository;
|
||||||
|
}
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
package zw.qantra.tm.domain.services;
|
||||||
|
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
import zw.qantra.tm.domain.repositories.SettingRepository;
|
||||||
|
|
||||||
|
@Service
|
||||||
|
@RequiredArgsConstructor
|
||||||
|
public class SettingService {
|
||||||
|
private final SettingRepository settingRepository;
|
||||||
|
}
|
||||||
@@ -0,0 +1,21 @@
|
|||||||
|
package zw.qantra.tm.domain.services;
|
||||||
|
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
import zw.qantra.tm.domain.models.PaymentProcessor;
|
||||||
|
import zw.qantra.tm.domain.models.Transaction;
|
||||||
|
import zw.qantra.tm.domain.repositories.TransactionRepository;
|
||||||
|
import zw.qantra.tm.domain.services.factories.PaymentProcessorFactory;
|
||||||
|
|
||||||
|
@Service
|
||||||
|
@RequiredArgsConstructor
|
||||||
|
public class TransactionService {
|
||||||
|
private final TransactionRepository transactionRepository;
|
||||||
|
private final PaymentProcessorFactory paymentProcessorFactory;
|
||||||
|
|
||||||
|
private Transaction bootstrap(Transaction transaction) {
|
||||||
|
String label = transaction.getType() + "_" + transaction.getPaymentProcessorLabel();
|
||||||
|
// PaymentProcessor paymentProcessor = paymentProcessorFactory.getPaymentProcessor(label);
|
||||||
|
return transaction;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,40 @@
|
|||||||
|
package zw.qantra.tm.domain.services.factories;
|
||||||
|
|
||||||
|
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
import org.springframework.beans.BeansException;
|
||||||
|
import org.springframework.beans.factory.NoSuchBeanDefinitionException;
|
||||||
|
import org.springframework.context.ApplicationContext;
|
||||||
|
import org.springframework.context.ApplicationContextAware;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
@Component
|
||||||
|
@RequiredArgsConstructor
|
||||||
|
public class PaymentProcessorFactory implements ApplicationContextAware {
|
||||||
|
private final Logger logger = LoggerFactory.getLogger(this.getClass().getName());
|
||||||
|
|
||||||
|
private ApplicationContext applicationContext;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
|
||||||
|
this.applicationContext = applicationContext;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Object getPaymentProcessor(String paymentProcessorName) {
|
||||||
|
Object paymentProcessor;
|
||||||
|
|
||||||
|
try {
|
||||||
|
paymentProcessor = applicationContext.getBean(paymentProcessorName);
|
||||||
|
} catch (NoSuchBeanDefinitionException exception) {
|
||||||
|
logger.error("Couldn't find payment processor: {}", exception.getMessage());
|
||||||
|
return null;
|
||||||
|
} catch (BeansException e) {
|
||||||
|
logger.error("Error retrieving payment processor bean: {}", e.getMessage());
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return paymentProcessor;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
package zw.qantra.tm.domain.services.processors;
|
||||||
|
|
||||||
|
import zw.qantra.tm.domain.models.Transaction;
|
||||||
|
|
||||||
|
public interface TransactionProcessorInterface {
|
||||||
|
Object process(Transaction transaction);
|
||||||
|
Object reverse(Transaction transaction);
|
||||||
|
}
|
||||||
@@ -0,0 +1,25 @@
|
|||||||
|
package zw.qantra.tm.domain.services.processors.confirmations;
|
||||||
|
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
import zw.qantra.tm.domain.models.Transaction;
|
||||||
|
import zw.qantra.tm.domain.services.processors.TransactionProcessorInterface;
|
||||||
|
import zw.qantra.tm.rest.RestService;
|
||||||
|
|
||||||
|
@Service("CONFIRM_POWERTEL_ZESA")
|
||||||
|
@RequiredArgsConstructor
|
||||||
|
public class ZesaConfirmationProcessor implements TransactionProcessorInterface {
|
||||||
|
private final RestService restService;
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Object process(Transaction transaction) {
|
||||||
|
|
||||||
|
return transaction;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Object reverse(Transaction transaction) {
|
||||||
|
return transaction;
|
||||||
|
}
|
||||||
|
}
|
||||||
195
src/main/java/zw/qantra/tm/rest/RestService.java
Executable file
195
src/main/java/zw/qantra/tm/rest/RestService.java
Executable file
@@ -0,0 +1,195 @@
|
|||||||
|
package zw.qantra.tm.rest;
|
||||||
|
|
||||||
|
import com.google.gson.Gson;
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.beans.factory.annotation.Value;
|
||||||
|
import org.springframework.http.*;
|
||||||
|
import org.springframework.http.client.BufferingClientHttpRequestFactory;
|
||||||
|
import org.springframework.http.client.ClientHttpRequestInterceptor;
|
||||||
|
import org.springframework.http.client.SimpleClientHttpRequestFactory;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
import org.springframework.util.CollectionUtils;
|
||||||
|
import org.springframework.util.LinkedMultiValueMap;
|
||||||
|
import org.springframework.util.MultiValueMap;
|
||||||
|
import org.springframework.web.client.RestTemplate;
|
||||||
|
import zw.qantra.tm.exceptions.RestTemplateResponseErrorHandler;
|
||||||
|
|
||||||
|
import java.lang.reflect.Type;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Rest service that facilitates communication between services. Authentication
|
||||||
|
* is either based on client credentials, user credentials or is open. User credentials
|
||||||
|
* are only available for registered users
|
||||||
|
* */
|
||||||
|
|
||||||
|
@Service
|
||||||
|
@RequiredArgsConstructor
|
||||||
|
public class RestService {
|
||||||
|
Logger logger = LoggerFactory.getLogger(this.getClass().toString());
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private Gson gson;
|
||||||
|
|
||||||
|
public final RestTemplate restTemplate;
|
||||||
|
|
||||||
|
public RestService() {
|
||||||
|
this.restTemplate = new RestTemplate(
|
||||||
|
new BufferingClientHttpRequestFactory(
|
||||||
|
new SimpleClientHttpRequestFactory()
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
this.restTemplate.setErrorHandler(new RestTemplateResponseErrorHandler());
|
||||||
|
|
||||||
|
// bootstrap rest template
|
||||||
|
List<ClientHttpRequestInterceptor> interceptors
|
||||||
|
= this.restTemplate.getInterceptors();
|
||||||
|
if (CollectionUtils.isEmpty(interceptors)) {
|
||||||
|
interceptors = new ArrayList<>();
|
||||||
|
}
|
||||||
|
interceptors.add(new RestTemplateInterceptor(gson));
|
||||||
|
this.restTemplate.setInterceptors(interceptors);
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getUserToken(){
|
||||||
|
String token = "Utils.getToken()";
|
||||||
|
logger.info(token);
|
||||||
|
return token;
|
||||||
|
}
|
||||||
|
|
||||||
|
// client token is retrieved from open ID identity provider and
|
||||||
|
// cached for 20 days for easy reuse.
|
||||||
|
|
||||||
|
// todo: definitely not the best way to do this, tried implementing caching but
|
||||||
|
// that needs a bit of time to do correctly
|
||||||
|
public String getClientToken(){
|
||||||
|
logger.info("Getting client token");
|
||||||
|
MultiValueMap<String, String> payload = new LinkedMultiValueMap<>();
|
||||||
|
payload.add("grant_type", "client_credentials");
|
||||||
|
Map tokenResponse = getToken(payload);
|
||||||
|
assert tokenResponse != null;
|
||||||
|
|
||||||
|
String clientToken = (String) tokenResponse.get("access_token");
|
||||||
|
logger.info("client access token", "log", clientToken);
|
||||||
|
return clientToken;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Map getToken(MultiValueMap payload){
|
||||||
|
HttpHeaders headers = new HttpHeaders();
|
||||||
|
headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);
|
||||||
|
// build the request
|
||||||
|
HttpEntity entity = new HttpEntity<>(payload, headers);
|
||||||
|
return this.restTemplate.postForObject("tokenUrl", entity, Map.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
public <T> T getAsClient(String path, Class<T> clazz){
|
||||||
|
HttpHeaders headers = new HttpHeaders();
|
||||||
|
headers.setBearerAuth(getClientToken());
|
||||||
|
HttpEntity entity = new HttpEntity<>(headers);
|
||||||
|
return this.restTemplate.getForObject(path, clazz, entity);
|
||||||
|
}
|
||||||
|
|
||||||
|
public <T> ResponseEntity<T> getExchangeAsClient(String path, Class<T> clazz){
|
||||||
|
HttpHeaders headers = new HttpHeaders();
|
||||||
|
headers.setBearerAuth(getClientToken());
|
||||||
|
HttpEntity entity = new HttpEntity<>(headers);
|
||||||
|
return this.restTemplate.exchange(path, HttpMethod.GET, entity, clazz);
|
||||||
|
}
|
||||||
|
|
||||||
|
public <T> ResponseEntity<T> postAsClient(String path, Object payload, Class<T> clazz){
|
||||||
|
HttpHeaders headers = new HttpHeaders();
|
||||||
|
headers.setContentType(MediaType.APPLICATION_JSON);
|
||||||
|
headers.setAccept(Collections.singletonList(MediaType.APPLICATION_JSON));
|
||||||
|
headers.setBearerAuth(getClientToken());
|
||||||
|
// build the request
|
||||||
|
HttpEntity entity = new HttpEntity<>(payload, headers);
|
||||||
|
ResponseEntity responseEntity = this.restTemplate.postForEntity(path, entity, clazz);
|
||||||
|
return responseEntity;
|
||||||
|
}
|
||||||
|
|
||||||
|
public <T> T postAs(String path, Object payload, HttpHeaders headers, Class<T> clazz){
|
||||||
|
// build the request
|
||||||
|
HttpEntity entity = new HttpEntity<>(payload, headers);
|
||||||
|
return this.restTemplate.postForObject(path, entity, clazz);
|
||||||
|
}
|
||||||
|
|
||||||
|
public <T> T post(String path, Object payload, Class<T> clazz){
|
||||||
|
HttpHeaders headers = new HttpHeaders();
|
||||||
|
headers.setContentType(MediaType.APPLICATION_JSON);
|
||||||
|
headers.setAccept(Collections.singletonList(MediaType.APPLICATION_JSON));
|
||||||
|
headers.setBearerAuth(getUserToken());
|
||||||
|
// build the request
|
||||||
|
HttpEntity entity = new HttpEntity<>(payload, headers);
|
||||||
|
T t = this.restTemplate.postForObject(path, entity, clazz);
|
||||||
|
return t;
|
||||||
|
}
|
||||||
|
|
||||||
|
public <T> T postWithToken(String token , String path, Object payload, Class<T> clazz){
|
||||||
|
HttpHeaders headers = new HttpHeaders();
|
||||||
|
headers.setContentType(MediaType.APPLICATION_JSON);
|
||||||
|
headers.setAccept(Collections.singletonList(MediaType.APPLICATION_JSON));
|
||||||
|
headers.setBearerAuth(token);
|
||||||
|
// build the request
|
||||||
|
HttpEntity entity = new HttpEntity<>(payload, headers);
|
||||||
|
T t = this.restTemplate.postForObject(path, entity, clazz);
|
||||||
|
return t;
|
||||||
|
}
|
||||||
|
|
||||||
|
public <T> T postFormData(String path, MultiValueMap<String, Object> payload, Class<T> clazz)
|
||||||
|
{
|
||||||
|
HttpHeaders headers = new HttpHeaders();
|
||||||
|
headers.setAccept(Collections.singletonList(MediaType.APPLICATION_JSON));
|
||||||
|
headers.setContentType(MediaType.MULTIPART_FORM_DATA);
|
||||||
|
|
||||||
|
HttpEntity<MultiValueMap<String, Object>> request = new HttpEntity<>(payload, headers);
|
||||||
|
|
||||||
|
return this.restTemplate.postForEntity(path, request, clazz).getBody();
|
||||||
|
}
|
||||||
|
|
||||||
|
public <T> T get(String path, Type clazz){
|
||||||
|
HttpHeaders headers = new HttpHeaders();
|
||||||
|
headers.setBearerAuth(getUserToken());
|
||||||
|
HttpEntity entity = new HttpEntity<>(headers);
|
||||||
|
|
||||||
|
ResponseEntity<String> responseEntity = this.restTemplate.exchange(path, HttpMethod.GET, entity, String.class);
|
||||||
|
T response = gson.fromJson(responseEntity.getBody(), clazz);
|
||||||
|
return response;
|
||||||
|
}
|
||||||
|
|
||||||
|
// make post request to endpoint without bearer auth
|
||||||
|
public <T> T postNoAuth(String path, Object payload, Class<T> clazz){
|
||||||
|
HttpHeaders headers = new HttpHeaders();
|
||||||
|
headers.setContentType(MediaType.APPLICATION_JSON);
|
||||||
|
headers.setAccept(Collections.singletonList(MediaType.APPLICATION_JSON));
|
||||||
|
// build the request
|
||||||
|
HttpEntity entity = new HttpEntity<>(payload, headers);
|
||||||
|
T t = this.restTemplate.postForObject(path, entity, clazz);
|
||||||
|
return t;
|
||||||
|
}
|
||||||
|
|
||||||
|
// make post request to endpoint without bearer auth
|
||||||
|
public <T> T postWithExternalAuth(String path, Object payload, HttpHeaders headers, Class<T> clazz){
|
||||||
|
headers.setContentType(MediaType.APPLICATION_JSON);
|
||||||
|
headers.setAccept(Collections.singletonList(MediaType.APPLICATION_JSON));
|
||||||
|
// build the request
|
||||||
|
HttpEntity entity = new HttpEntity<>(payload, headers);
|
||||||
|
T t = this.restTemplate.postForObject(path, entity, clazz);
|
||||||
|
return t;
|
||||||
|
}
|
||||||
|
|
||||||
|
// make get request to endpoint without bearer auth
|
||||||
|
public <T> T getNoAuth(String path, Class<T> clazz){
|
||||||
|
return this.restTemplate.getForObject(path, clazz);
|
||||||
|
}
|
||||||
|
|
||||||
|
public <T> ResponseEntity<?> exchangeGetNoAuth(String path, HttpEntity<?> httpEntity, Class<?> clazz, String pathVariable) {
|
||||||
|
return this.restTemplate.exchange(path, HttpMethod.GET, httpEntity, clazz, pathVariable);
|
||||||
|
}
|
||||||
|
}
|
||||||
72
src/main/java/zw/qantra/tm/rest/RestTemplateInterceptor.java
Executable file
72
src/main/java/zw/qantra/tm/rest/RestTemplateInterceptor.java
Executable file
@@ -0,0 +1,72 @@
|
|||||||
|
package zw.qantra.tm.rest;
|
||||||
|
|
||||||
|
import com.google.gson.Gson;
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
import org.json.JSONArray;
|
||||||
|
import org.json.JSONException;
|
||||||
|
import org.json.JSONObject;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
import org.springframework.http.HttpRequest;
|
||||||
|
import org.springframework.http.client.ClientHttpRequestExecution;
|
||||||
|
import org.springframework.http.client.ClientHttpRequestInterceptor;
|
||||||
|
import org.springframework.http.client.ClientHttpResponse;
|
||||||
|
|
||||||
|
import java.io.BufferedReader;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStreamReader;
|
||||||
|
import java.nio.charset.StandardCharsets;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
@RequiredArgsConstructor
|
||||||
|
public class RestTemplateInterceptor
|
||||||
|
implements ClientHttpRequestInterceptor {
|
||||||
|
private final Logger logger = LoggerFactory.getLogger(getClass().getName());
|
||||||
|
private final Gson gson;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ClientHttpResponse intercept(
|
||||||
|
HttpRequest request,
|
||||||
|
byte[] reqBody,
|
||||||
|
ClientHttpRequestExecution execution) throws IOException {
|
||||||
|
String requestBody = new String(reqBody, StandardCharsets.UTF_8);
|
||||||
|
if(!isJSONValid(requestBody)) requestBody = toBasicJson(requestBody);
|
||||||
|
|
||||||
|
// we don't log file data
|
||||||
|
if(request.getHeaders().getContentLength() < 10000){
|
||||||
|
logger.info("Request: "
|
||||||
|
+ request.getMethod() + ": "
|
||||||
|
+ request.getURI(), "http", gson.fromJson(requestBody, HashMap.class));
|
||||||
|
}
|
||||||
|
ClientHttpResponse response = execution.execute(request, reqBody);
|
||||||
|
InputStreamReader isr = new InputStreamReader(response.getBody());
|
||||||
|
String body = new BufferedReader(isr).lines()
|
||||||
|
.collect(Collectors.joining("\n"));
|
||||||
|
try{
|
||||||
|
logger.info("Response body: {}", "http", gson.fromJson(body, HashMap.class));
|
||||||
|
}catch (Exception exception){
|
||||||
|
logger.info("Problem serializing resp: {}", "http", exception.getMessage());
|
||||||
|
}
|
||||||
|
return response;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String toBasicJson(String string){
|
||||||
|
HashMap map = new HashMap();
|
||||||
|
map.put("log", string);
|
||||||
|
return gson.toJson(map);
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isJSONValid(String test) {
|
||||||
|
try {
|
||||||
|
new JSONObject(test);
|
||||||
|
} catch (JSONException ex) {
|
||||||
|
try {
|
||||||
|
new JSONArray(test);
|
||||||
|
} catch (JSONException ex1) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -5,7 +5,7 @@ logging.level.org.springframework.boot.autoconfigure=INFO
|
|||||||
|
|
||||||
server.port=6950
|
server.port=6950
|
||||||
|
|
||||||
spring.jpa.hibernate.ddl-auto=validate
|
spring.jpa.hibernate.ddl-auto=update
|
||||||
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
|
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
|
||||||
spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MySQLDialect
|
spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MySQLDialect
|
||||||
|
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ logging.level.org.springframework.boot.autoconfigure=INFO
|
|||||||
|
|
||||||
server.port=6950
|
server.port=6950
|
||||||
|
|
||||||
spring.jpa.hibernate.ddl-auto=validate
|
spring.jpa.hibernate.ddl-auto=update
|
||||||
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
|
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
|
||||||
spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MySQLDialect
|
spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MySQLDialect
|
||||||
|
|
||||||
|
|||||||
@@ -4,6 +4,6 @@ username=root
|
|||||||
password=password
|
password=password
|
||||||
|
|
||||||
driver=com.mysql.cj.jdbc.Driver
|
driver=com.mysql.cj.jdbc.Driver
|
||||||
referenceUrl=hibernate:spring:zw.qantra.tm.domain.models?dialect=org.hibernate.dialect.MySQL5Dialect&hibernate.implicit_naming_strategy=org.springframework.boot.orm.jpa.hibernate.SpringImplicitNamingStrategy&hibernate.physical_naming_strategy=org.hibernate.boot.model.naming.CamelCaseToUnderscoresNamingStrategy
|
referenceUrl=hibernate:spring:zw.qantra.tm.domain.models?dialect=org.hibernate.dialect.MySQLDialect&hibernate.implicit_naming_strategy=org.springframework.boot.orm.jpa.hibernate.SpringImplicitNamingStrategy&hibernate.physical_naming_strategy=org.hibernate.boot.model.naming.CamelCaseToUnderscoresNamingStrategy
|
||||||
diffChangeLogFile=src/main/resources/liquibase-diff-changeLog.xml
|
diffChangeLogFile=src/main/resources/liquibase-diff-changeLog.xml
|
||||||
outputChangeLogFile=src/main/resources/liquibase-changeLog.xml
|
outputChangeLogFile=src/main/resources/liquibase-changeLog.xml
|
||||||
|
|||||||
Reference in New Issue
Block a user