progress on integration to sbz

This commit is contained in:
2025-06-23 10:45:05 +02:00
parent 9ae78635c7
commit fdd3a224ed
14 changed files with 247 additions and 19 deletions

View File

@@ -0,0 +1,52 @@
package zw.qantra.tm.domain.controllers;
import lombok.RequiredArgsConstructor;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import zw.qantra.tm.domain.models.Category;
import zw.qantra.tm.domain.services.CategoryService;
import zw.qantra.tm.rest.ApiResponse;
import java.util.UUID;
@RestController
@RequestMapping("/categories")
@RequiredArgsConstructor
public class CategoryController {
private final CategoryService categoryService;
@GetMapping
public ResponseEntity getAllCategories() {
return ApiResponse.ok(categoryService.getAllCategories());
}
@GetMapping("/{id}")
public ResponseEntity getCategory(@PathVariable UUID id) {
return categoryService.getCategory(id)
.map(ApiResponse::ok)
.orElse(ApiResponse.notFound());
}
@PostMapping
public ResponseEntity createCategory(@RequestBody Category category) {
return ApiResponse.ok(categoryService.createCategory(category));
}
@PutMapping("/{id}")
public ResponseEntity updateCategory(@PathVariable UUID id, @RequestBody Category category) {
Category updatedCategory = categoryService.updateCategory(id, category);
if (updatedCategory != null) {
return ApiResponse.ok(updatedCategory);
}
return ApiResponse.notFound();
}
@DeleteMapping("/{id}")
public ResponseEntity deleteCategory(@PathVariable UUID id) {
if (categoryService.deleteCategory(id)) {
return ApiResponse.ok("Category deleted successfully");
}
return ApiResponse.notFound();
}
}

View File

@@ -17,8 +17,8 @@ public class ProviderController {
private final ProviderService providerService;
@GetMapping
public ResponseEntity getProviders() {
return ApiResponse.ok(providerService.getProviders());
public ResponseEntity getProviders(@RequestParam(required = false) String category) {
return ApiResponse.ok(providerService.getProviders(category));
}
@GetMapping("/{id}/products")

View File

@@ -0,0 +1,31 @@
package zw.qantra.tm.domain.dtos;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import zw.qantra.tm.domain.enums.CurrencyType;
import zw.qantra.tm.domain.enums.RequestType;
import java.math.BigDecimal;
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
@JsonIgnoreProperties(ignoreUnknown = true)
public class BillPaymentDto {
private RequestType type;
private String billClientId;
private String debitRef;
private CurrencyType debitCurrency;
private BigDecimal amount;
private String aggregatorId;
private String debitPhone;
private String debitAccount;
private String creditAccount;
private CurrencyType creditCurrency;
private String creditPhone;
private String billName;
}

View File

@@ -1,5 +1,6 @@
package zw.qantra.tm.domain.dtos;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
@@ -12,6 +13,7 @@ import java.util.UUID;
@Builder
@NoArgsConstructor
@AllArgsConstructor
@JsonIgnoreProperties(ignoreUnknown = true)
public class SBZProductDto {
private String name;
private String description;
@@ -19,4 +21,4 @@ public class SBZProductDto {
private BigDecimal defaultAmount;
private boolean requiresAmount;
private UUID uid;
}
}

View File

@@ -0,0 +1,19 @@
package zw.qantra.tm.domain.dtos;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import lombok.Data;
import java.util.UUID;
@Data
@JsonIgnoreProperties(ignoreUnknown = true)
public class SBZProviderDto {
private String clientId;
private boolean requiresAccount;
private boolean requiresAmount;
private boolean requiresAmountFromMerchant;
private boolean requiresPhone;
private boolean requiresReversal;
private String additionalDataString;
private String processorType;
}

View File

@@ -0,0 +1,17 @@
package zw.qantra.tm.domain.models;
import jakarta.persistence.Entity;
import lombok.*;
@Entity
@Setter
@Getter
@Builder
@AllArgsConstructor
@NoArgsConstructor
public class Category extends BaseEntity {
private String name;
private String image;
private String description;
private String label;
}

View File

@@ -1,13 +1,8 @@
package zw.qantra.tm.domain.models;
import jakarta.persistence.Entity;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.GenerationType;
import jakarta.persistence.Column;
import lombok.*;
import java.util.UUID;
@Entity
@Getter
@Setter
@@ -15,12 +10,9 @@ import java.util.UUID;
@AllArgsConstructor
@NoArgsConstructor
public class PaymentProcessor extends BaseEntity {
@GeneratedValue(strategy = GenerationType.UUID)
@Column(columnDefinition = "VARCHAR(36)")
private UUID id;
private String name;
private String description;
private String label;
private String type;
private String image;
}

View File

@@ -15,4 +15,6 @@ public class Provider extends BaseEntity {
private String label;
private String description;
private String externalId;
private String image;
private String category;
}

View File

@@ -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.Category;
import java.util.UUID;
@Repository
public interface CategoryRepository extends JpaRepository<Category, UUID> {
}

View File

@@ -4,8 +4,10 @@ import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
import zw.qantra.tm.domain.models.Provider;
import java.util.List;
import java.util.UUID;
@Repository
public interface ProviderRepository extends JpaRepository<Provider, UUID> {
List<Provider> findByCategory(String category);
}

View File

@@ -0,0 +1,46 @@
package zw.qantra.tm.domain.services;
import lombok.Getter;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import zw.qantra.tm.domain.models.Category;
import zw.qantra.tm.domain.repositories.CategoryRepository;
import java.util.List;
import java.util.Optional;
import java.util.UUID;
@Getter
@Service
@RequiredArgsConstructor
public class CategoryService {
private final CategoryRepository categoryRepository;
public List<Category> getAllCategories() {
return categoryRepository.findAll();
}
public Optional<Category> getCategory(UUID id) {
return categoryRepository.findById(id);
}
public Category createCategory(Category category) {
return categoryRepository.save(category);
}
public Category updateCategory(UUID id, Category category) {
if (categoryRepository.existsById(id)) {
category.setId(id);
return categoryRepository.save(category);
}
return null;
}
public boolean deleteCategory(UUID id) {
if (categoryRepository.existsById(id)) {
categoryRepository.deleteById(id);
return true;
}
return false;
}
}

View File

@@ -1,5 +1,6 @@
package zw.qantra.tm.domain.services;
import lombok.Getter;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.factory.annotation.Value;
@@ -11,25 +12,22 @@ import com.fasterxml.jackson.databind.ObjectMapper;
import zw.qantra.tm.domain.dtos.SBZProductDto;
import zw.qantra.tm.domain.models.Provider;
import zw.qantra.tm.domain.repositories.ChargeRepository;
import zw.qantra.tm.domain.repositories.ProviderRepository;
import zw.qantra.tm.rest.RestService;
import java.util.*;
import java.util.stream.Collectors;
@Service
@RequiredArgsConstructor
public class ProviderService {
@Getter
private final ProviderRepository providerRepository;
private final RestService restService;
@Value("${sbz.aggregator.url}")
private String aggregatorUrl;
public ProviderRepository getProviderRepository() {
return providerRepository;
}
public List<SBZProductDto> getProviderProducts(UUID providerId) {
String token = restService.getMerchantToken();
@@ -57,8 +55,36 @@ public class ProviderService {
return products;
}
public List<Provider> getProviders() {
return providerRepository.findAll();
public Object getProviders(String category) {
String token = restService.getMerchantToken();
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON);
headers.setAccept(Collections.singletonList(MediaType.APPLICATION_JSON));
headers.setBearerAuth(token);
List<Provider> existingProviders;
if (category != null) {
existingProviders = getProviderRepository().findByCategory(category);
} else {
existingProviders = getProviderRepository().findAll();
}
List<String> existingProviderIds = existingProviders.stream()
.map(Provider::getClientId)
.collect(Collectors.toList());
String existingProviderIdsString = String.join(",", existingProviderIds);
LinkedHashMap response = this.restService.getAs(
aggregatorUrl + "/merchant/aggregation/providers?supportedCurrencies=USD&clientIdIn=" + existingProviderIdsString,
headers,
LinkedHashMap.class
);
LinkedHashMap body = (LinkedHashMap) response.get("body");
List<LinkedHashMap> content = (List<LinkedHashMap>) body.get("content");
return content;
}
public Optional<Provider> getProvider(UUID id) {

View File

@@ -3,10 +3,14 @@ package zw.qantra.tm.domain.services.processors.confirmations;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import zw.qantra.tm.domain.dtos.BillPaymentDto;
import zw.qantra.tm.domain.enums.RequestType;
import zw.qantra.tm.domain.models.Transaction;
import zw.qantra.tm.domain.services.processors.TransactionProcessorInterface;
import zw.qantra.tm.rest.RestService;
import java.util.Map;
@Service("CONFIRM_ZESA")
@RequiredArgsConstructor
public class ZesaConfirmationProcessor implements TransactionProcessorInterface {
@@ -18,8 +22,27 @@ public class ZesaConfirmationProcessor implements TransactionProcessorInterface
@Override
public Object process(Transaction transaction) throws Exception {
System.out.println("processing transaction");
String token = restService.getMerchantToken();
BillPaymentDto request = BillPaymentDto.builder()
.type(RequestType.CONFIRM)
.billClientId(transaction.getBillClientId())
.debitRef(transaction.getDebitRef())
.debitCurrency(transaction.getDebitCurrency())
.amount(transaction.getAmount())
.aggregatorId(transaction.getAggregatorId())
.debitPhone(transaction.getDebitPhone())
.debitAccount(transaction.getDebitAccount())
.creditAccount(transaction.getCreditAccount())
.creditPhone(transaction.getCreditPhone())
.billName(transaction.getBillName())
.build();
String url = aggregatorUrl + "/v1/merchant/aggregation/transaction";
Map response = restService.postWithToken(token, url, request, Map.class);
System.out.println(response);
return transaction;
}