completed zesa journey
This commit is contained in:
@@ -0,0 +1,66 @@
|
||||
package zw.qantra.tm.domain.controllers;
|
||||
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import zw.qantra.tm.domain.services.AdditionalDataService;
|
||||
import zw.qantra.tm.domain.models.AdditionalData;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
|
||||
@RestController
|
||||
@RequestMapping("/additional-data")
|
||||
@RequiredArgsConstructor
|
||||
public class AdditionalDataController {
|
||||
Logger logger = LoggerFactory.getLogger(AdditionalDataController.class);
|
||||
|
||||
private final AdditionalDataService additionalDataService;
|
||||
|
||||
@GetMapping
|
||||
public ResponseEntity<List<AdditionalData>> getAll() {
|
||||
return ResponseEntity.ok(additionalDataService.getAllAdditionalData());
|
||||
}
|
||||
|
||||
@GetMapping("/transaction/{transactionId}")
|
||||
public ResponseEntity<AdditionalData> getByTransactionId(@PathVariable UUID transactionId) {
|
||||
return additionalDataService.getAdditionalDataRepository().findByTransactionId(transactionId)
|
||||
.map(ResponseEntity::ok)
|
||||
.orElse(ResponseEntity.notFound().build());
|
||||
}
|
||||
|
||||
@GetMapping("/{id}")
|
||||
public ResponseEntity<AdditionalData> getById(@PathVariable UUID id) {
|
||||
return additionalDataService.getAdditionalData(id)
|
||||
.map(ResponseEntity::ok)
|
||||
.orElse(ResponseEntity.notFound().build());
|
||||
}
|
||||
|
||||
@PostMapping
|
||||
public ResponseEntity<AdditionalData> create(@RequestBody AdditionalData additionalData) {
|
||||
logger.info("incoming additional data: {}", additionalData);
|
||||
AdditionalData createdAdditionalData = additionalDataService.createAdditionalData(additionalData);
|
||||
logger.info("outgoing additional data: {}", createdAdditionalData);
|
||||
return ResponseEntity.ok(createdAdditionalData);
|
||||
}
|
||||
|
||||
@PutMapping("/{id}")
|
||||
public ResponseEntity<AdditionalData> update(@PathVariable UUID id, @RequestBody AdditionalData additionalData) {
|
||||
AdditionalData updatedAdditionalData = additionalDataService.updateAdditionalData(id, additionalData);
|
||||
if (updatedAdditionalData == null) {
|
||||
return ResponseEntity.notFound().build();
|
||||
}
|
||||
return ResponseEntity.ok(updatedAdditionalData);
|
||||
}
|
||||
|
||||
@DeleteMapping("/{id}")
|
||||
public ResponseEntity<Void> delete(@PathVariable UUID id) {
|
||||
boolean deleted = additionalDataService.deleteAdditionalData(id);
|
||||
if (!deleted) {
|
||||
return ResponseEntity.notFound().build();
|
||||
}
|
||||
return ResponseEntity.noContent().build();
|
||||
}
|
||||
}
|
||||
@@ -5,7 +5,6 @@ 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;
|
||||
|
||||
@@ -18,35 +17,35 @@ public class CategoryController {
|
||||
|
||||
@GetMapping
|
||||
public ResponseEntity getAllCategories() {
|
||||
return ApiResponse.ok(categoryService.getAllCategories());
|
||||
return ResponseEntity.ok(categoryService.getAllCategories());
|
||||
}
|
||||
|
||||
@GetMapping("/{id}")
|
||||
public ResponseEntity getCategory(@PathVariable UUID id) {
|
||||
return categoryService.getCategory(id)
|
||||
.map(ApiResponse::ok)
|
||||
.orElse(ApiResponse.notFound());
|
||||
.map(ResponseEntity::ok)
|
||||
.orElse(ResponseEntity.notFound().build());
|
||||
}
|
||||
|
||||
@PostMapping
|
||||
public ResponseEntity createCategory(@RequestBody Category category) {
|
||||
return ApiResponse.ok(categoryService.createCategory(category));
|
||||
return ResponseEntity.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 ResponseEntity.ok(updatedCategory);
|
||||
}
|
||||
return ApiResponse.notFound();
|
||||
return ResponseEntity.notFound().build();
|
||||
}
|
||||
|
||||
@DeleteMapping("/{id}")
|
||||
public ResponseEntity deleteCategory(@PathVariable UUID id) {
|
||||
if (categoryService.deleteCategory(id)) {
|
||||
return ApiResponse.ok("Category deleted successfully");
|
||||
return ResponseEntity.ok("Category deleted successfully");
|
||||
}
|
||||
return ApiResponse.notFound();
|
||||
return ResponseEntity.notFound().build();
|
||||
}
|
||||
}
|
||||
@@ -8,10 +8,16 @@ import org.springframework.web.bind.annotation.RestController;
|
||||
import zw.qantra.tm.domain.enums.ChargeConditionType;
|
||||
import zw.qantra.tm.domain.enums.ChargeLabelEnum;
|
||||
import zw.qantra.tm.domain.enums.CurrencyType;
|
||||
import zw.qantra.tm.domain.models.Category;
|
||||
import zw.qantra.tm.domain.models.Charge;
|
||||
import zw.qantra.tm.domain.models.ChargeCondition;
|
||||
import zw.qantra.tm.domain.models.PaymentProcessor;
|
||||
import zw.qantra.tm.domain.models.Provider;
|
||||
import zw.qantra.tm.domain.services.ChargeConditionService;
|
||||
import zw.qantra.tm.domain.services.ChargeService;
|
||||
import zw.qantra.tm.domain.services.CategoryService;
|
||||
import zw.qantra.tm.domain.services.PaymentProcessorService;
|
||||
import zw.qantra.tm.domain.services.ProviderService;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.util.Arrays;
|
||||
@@ -24,9 +30,90 @@ import java.util.List;
|
||||
public class ConfigController {
|
||||
private final ChargeConditionService chargeConditionService;
|
||||
private final ChargeService chargeService;
|
||||
|
||||
@GetMapping("/charges")
|
||||
private final PaymentProcessorService paymentProcessorService;
|
||||
private final ProviderService providerService;
|
||||
private final CategoryService categoryService;
|
||||
|
||||
@GetMapping("/seed")
|
||||
public ResponseEntity charges(){
|
||||
// clear existing categories before seeding
|
||||
categoryService.getCategoryRepository().deleteAll();
|
||||
// seed categories
|
||||
List<Category> categories = Arrays.asList(
|
||||
Category.builder()
|
||||
.name("Airtime")
|
||||
.description("Airtime for local mobile networks")
|
||||
.label("AIRTIME")
|
||||
.build(),
|
||||
Category.builder()
|
||||
.name("Utilities")
|
||||
.description("Council bills & rates")
|
||||
.label("UTILITIES")
|
||||
.build()
|
||||
);
|
||||
categoryService.getCategoryRepository().saveAll(categories);
|
||||
|
||||
// clear existing providers before seeding
|
||||
providerService.getProviderRepository().deleteAll();
|
||||
|
||||
// seed providers
|
||||
List<Provider> providers = Arrays.asList(
|
||||
Provider.builder()
|
||||
.description("Econet Airtime")
|
||||
.clientId("econet_airtime")
|
||||
.label("ECONET")
|
||||
.category("AIRTIME")
|
||||
.image("econet.png")
|
||||
.externalId("78f1f497-c9eb-401c-b22c-884756e68e40")
|
||||
.build(),
|
||||
Provider.builder()
|
||||
.description("NetOne Airtime")
|
||||
.clientId("netone_usd_airtime")
|
||||
.label("NETONE")
|
||||
.category("AIRTIME")
|
||||
.image("netone.png")
|
||||
.externalId("95d485a7-39c9-4559-8a27-6521969abe8f")
|
||||
.build(),
|
||||
Provider.builder()
|
||||
.description("Prepaid Zesa")
|
||||
.clientId("powertel_zesa")
|
||||
.label("ZESA")
|
||||
.category("UTILITIES")
|
||||
.image("zesa.png")
|
||||
.externalId("0f67f7cc-b62b-4fb5-915f-6740b2afdba6")
|
||||
.build(),
|
||||
Provider.builder()
|
||||
.description("Econet Broadband")
|
||||
.clientId("econet_broadband_usd")
|
||||
.label("ECONET_BROADBAND")
|
||||
.category("AIRTIME")
|
||||
.image("econet.png")
|
||||
.externalId("287863e2-a791-4106-b629-79dadc9a6779")
|
||||
.build()
|
||||
);
|
||||
providerService.getProviderRepository().saveAll(providers);
|
||||
|
||||
// Clear existing payment processors before seeding
|
||||
paymentProcessorService.getPaymentProcessorRepository().deleteAll();
|
||||
|
||||
// seed payment processors
|
||||
List<PaymentProcessor> paymentProcessors = Arrays.asList(
|
||||
PaymentProcessor.builder()
|
||||
.name("Ecocash")
|
||||
.label("ECOCASH")
|
||||
.type("GATEWAY")
|
||||
.image("https://www.ecocash.co.zw/images/logo.png")
|
||||
.build(),
|
||||
PaymentProcessor.builder()
|
||||
.name("Mastercard")
|
||||
.label("MPGS")
|
||||
.type("GATEWAY")
|
||||
.image("https://www.mastercard.com/content/dam/public/mastercardcom/global/en/icons/mc-symbol.svg")
|
||||
.build()
|
||||
);
|
||||
paymentProcessorService.getPaymentProcessorRepository().saveAll(paymentProcessors);
|
||||
|
||||
// Clear existing charges and charge conditions before seeding
|
||||
List<ChargeCondition> chargeConditions = Arrays.asList(
|
||||
ChargeCondition.builder()
|
||||
.name("Ecocash Gateway")
|
||||
@@ -78,6 +165,6 @@ public class ConfigController {
|
||||
|
||||
chargeService.getChargeRepository().saveAll(charges);
|
||||
|
||||
return ResponseEntity.ok("Charges configuration complete");
|
||||
return ResponseEntity.ok("Project configuration seeding complete");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,7 +5,6 @@ import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
import zw.qantra.tm.domain.models.Provider;
|
||||
import zw.qantra.tm.domain.services.ProviderService;
|
||||
import zw.qantra.tm.rest.ApiResponse;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
@@ -18,40 +17,40 @@ public class ProviderController {
|
||||
|
||||
@GetMapping
|
||||
public ResponseEntity getProviders(@RequestParam(required = false) String category) {
|
||||
return ApiResponse.ok(providerService.getProviders(category));
|
||||
return ResponseEntity.ok(providerService.getProviders(category));
|
||||
}
|
||||
|
||||
@GetMapping("/{id}/products")
|
||||
public ResponseEntity getProducts(@PathVariable UUID id) {
|
||||
return ApiResponse.ok(providerService.getProviderProducts(id));
|
||||
return ResponseEntity.ok(providerService.getProviderProducts(id));
|
||||
}
|
||||
|
||||
@GetMapping("/{id}")
|
||||
public ResponseEntity getProvider(@PathVariable UUID id) {
|
||||
return providerService.getProvider(id)
|
||||
.map(ApiResponse::ok)
|
||||
.orElse(ApiResponse.notFound());
|
||||
.map(ResponseEntity::ok)
|
||||
.orElse(ResponseEntity.notFound().build());
|
||||
}
|
||||
|
||||
@PostMapping
|
||||
public ResponseEntity createProvider(@RequestBody Provider provider) {
|
||||
return ApiResponse.ok(providerService.createProvider(provider));
|
||||
return ResponseEntity.ok(providerService.createProvider(provider));
|
||||
}
|
||||
|
||||
@PutMapping("/{id}")
|
||||
public ResponseEntity updateProvider(@PathVariable UUID id, @RequestBody Provider provider) {
|
||||
Provider updatedProvider = providerService.updateProvider(id, provider);
|
||||
if (updatedProvider != null) {
|
||||
return ApiResponse.ok(updatedProvider);
|
||||
return ResponseEntity.ok(updatedProvider);
|
||||
}
|
||||
return ApiResponse.notFound();
|
||||
return ResponseEntity.notFound().build();
|
||||
}
|
||||
|
||||
@DeleteMapping("/{id}")
|
||||
public ResponseEntity deleteProvider(@PathVariable UUID id) {
|
||||
if (providerService.deleteProvider(id)) {
|
||||
return ApiResponse.ok("Provider deleted successfully");
|
||||
return ResponseEntity.ok("Provider deleted successfully");
|
||||
}
|
||||
return ApiResponse.notFound();
|
||||
return ResponseEntity.notFound().build();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,8 +4,11 @@ import lombok.RequiredArgsConstructor;
|
||||
import zw.qantra.tm.domain.services.TransactionService;
|
||||
import zw.qantra.tm.domain.models.Transaction;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
|
||||
@@ -13,6 +16,7 @@ import java.util.UUID;
|
||||
@RequestMapping("/transaction")
|
||||
@RequiredArgsConstructor
|
||||
public class TransactonController {
|
||||
Logger logger = LoggerFactory.getLogger(TransactonController.class);
|
||||
|
||||
private final TransactionService transactionService;
|
||||
|
||||
@@ -28,9 +32,17 @@ public class TransactonController {
|
||||
.orElse(ResponseEntity.notFound().build());
|
||||
}
|
||||
|
||||
@GetMapping("/poll/{id}")
|
||||
public ResponseEntity<Transaction> poll(@PathVariable UUID id) {
|
||||
return ResponseEntity.ok(transactionService.poll(id));
|
||||
}
|
||||
|
||||
@PostMapping
|
||||
public ResponseEntity<Transaction> create(@RequestBody Transaction transaction) {
|
||||
return ResponseEntity.ok(transactionService.execute(transaction));
|
||||
logger.info("incoming transaction: {}", transaction);
|
||||
Transaction createdTransaction = transactionService.execute(transaction);
|
||||
logger.info("outgoing transaction: {}", createdTransaction);
|
||||
return ResponseEntity.ok(createdTransaction);
|
||||
}
|
||||
|
||||
@PutMapping("/{id}")
|
||||
|
||||
27
src/main/java/zw/qantra/tm/domain/dtos/SdkActionDto.java
Normal file
27
src/main/java/zw/qantra/tm/domain/dtos/SdkActionDto.java
Normal file
@@ -0,0 +1,27 @@
|
||||
package zw.qantra.tm.domain.dtos;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
@Data
|
||||
@Builder
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public class SdkActionDto {
|
||||
|
||||
private String clientId;
|
||||
private String clientSecret;
|
||||
private String phone;
|
||||
private String amount;
|
||||
private String currency;
|
||||
private String hash;
|
||||
private String authType;
|
||||
private String billerReference;
|
||||
private String action;
|
||||
private Boolean sandbox;
|
||||
private String paymentProcessorLabel;
|
||||
private String responseUrl;
|
||||
|
||||
}
|
||||
9
src/main/java/zw/qantra/tm/domain/enums/AuthType.java
Normal file
9
src/main/java/zw/qantra/tm/domain/enums/AuthType.java
Normal file
@@ -0,0 +1,9 @@
|
||||
package zw.qantra.tm.domain.enums;
|
||||
|
||||
public enum AuthType {
|
||||
WEB,
|
||||
USSD,
|
||||
WHATSAPP,
|
||||
MOBILE,
|
||||
REMOTE
|
||||
}
|
||||
@@ -1,6 +1,7 @@
|
||||
package zw.qantra.tm.domain.enums;
|
||||
|
||||
public enum RequestType {
|
||||
CONFIRM,
|
||||
REQUEST,
|
||||
CONFIRM
|
||||
INTEGRATION
|
||||
}
|
||||
|
||||
27
src/main/java/zw/qantra/tm/domain/models/AdditionalData.java
Normal file
27
src/main/java/zw/qantra/tm/domain/models/AdditionalData.java
Normal file
@@ -0,0 +1,27 @@
|
||||
package zw.qantra.tm.domain.models;
|
||||
|
||||
|
||||
import jakarta.persistence.Column;
|
||||
import jakarta.persistence.Entity;
|
||||
import jakarta.persistence.JoinColumn;
|
||||
import jakarta.persistence.OneToOne;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Getter;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.Setter;
|
||||
|
||||
@Getter
|
||||
@Setter
|
||||
@Entity
|
||||
@Builder
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
public class AdditionalData extends BaseEntity {
|
||||
@OneToOne
|
||||
@JoinColumn(name = "transaction_id")
|
||||
private Transaction transaction;
|
||||
|
||||
@Column(columnDefinition = "TEXT")
|
||||
private String jsonString;
|
||||
}
|
||||
@@ -1,5 +1,6 @@
|
||||
package zw.qantra.tm.domain.models;
|
||||
|
||||
import jakarta.persistence.Column;
|
||||
import jakarta.persistence.Entity;
|
||||
import lombok.*;
|
||||
|
||||
@@ -14,5 +15,6 @@ public class PaymentProcessor extends BaseEntity {
|
||||
private String description;
|
||||
private String label;
|
||||
private String type;
|
||||
@Column(columnDefinition = "TEXT")
|
||||
private String image;
|
||||
}
|
||||
|
||||
@@ -3,12 +3,12 @@ package zw.qantra.tm.domain.models;
|
||||
import com.fasterxml.jackson.annotation.JsonInclude;
|
||||
import jakarta.persistence.*;
|
||||
import lombok.*;
|
||||
import zw.qantra.tm.domain.enums.AuthType;
|
||||
import zw.qantra.tm.domain.enums.CurrencyType;
|
||||
import zw.qantra.tm.domain.enums.RequestType;
|
||||
import zw.qantra.tm.domain.enums.Status;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.util.List;
|
||||
|
||||
@Entity
|
||||
@Getter
|
||||
@@ -35,12 +35,14 @@ public class Transaction extends BaseEntity {
|
||||
private String channel;
|
||||
private String debitPhone;
|
||||
private String debitAccount;
|
||||
@Enumerated(EnumType.STRING)
|
||||
private CurrencyType debitCurrency;
|
||||
private String debitName;
|
||||
private String debitCard;
|
||||
private String debitRef;
|
||||
private String creditPhone;
|
||||
private String creditAccount;
|
||||
@Enumerated(EnumType.STRING)
|
||||
private CurrencyType creditCurrency;
|
||||
private String creditName;
|
||||
private String creditCard;
|
||||
@@ -50,12 +52,20 @@ public class Transaction extends BaseEntity {
|
||||
private String aggregatorId;
|
||||
private String billName;
|
||||
private String billProductName;
|
||||
@Enumerated(EnumType.STRING)
|
||||
private RequestType type;
|
||||
|
||||
@Enumerated(EnumType.STRING)
|
||||
private AuthType authType;
|
||||
|
||||
@Column(columnDefinition = "TEXT")
|
||||
private String errorMessage;
|
||||
private String responseCode;
|
||||
private Status status;
|
||||
@Column(columnDefinition = "TEXT")
|
||||
private String targetUrl;
|
||||
private String sdkActionId;
|
||||
|
||||
@Transient
|
||||
private List<Object> additionalData;
|
||||
private Object additionalData;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
package zw.qantra.tm.domain.repositories;
|
||||
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
import org.springframework.stereotype.Repository;
|
||||
import zw.qantra.tm.domain.models.AdditionalData;
|
||||
|
||||
import java.util.Optional;
|
||||
import java.util.UUID;
|
||||
|
||||
@Repository
|
||||
public interface AdditionalDataRepository extends JpaRepository<AdditionalData, UUID> {
|
||||
Optional<AdditionalData> findByTransactionId(UUID transactionId);
|
||||
}
|
||||
@@ -10,4 +10,5 @@ import java.util.UUID;
|
||||
@Repository
|
||||
public interface ProviderRepository extends JpaRepository<Provider, UUID> {
|
||||
List<Provider> findByCategory(String category);
|
||||
Provider findByClientId(String clientId);
|
||||
}
|
||||
@@ -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.AdditionalData;
|
||||
import zw.qantra.tm.domain.repositories.AdditionalDataRepository;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import java.util.UUID;
|
||||
|
||||
@Getter
|
||||
@Service
|
||||
@RequiredArgsConstructor
|
||||
public class AdditionalDataService {
|
||||
private final AdditionalDataRepository additionalDataRepository;
|
||||
|
||||
public List<AdditionalData> getAllAdditionalData() {
|
||||
return additionalDataRepository.findAll();
|
||||
}
|
||||
|
||||
public Optional<AdditionalData> getAdditionalData(UUID id) {
|
||||
return additionalDataRepository.findById(id);
|
||||
}
|
||||
|
||||
public AdditionalData createAdditionalData(AdditionalData additionalData) {
|
||||
return additionalDataRepository.save(additionalData);
|
||||
}
|
||||
|
||||
public AdditionalData updateAdditionalData(UUID id, AdditionalData additionalData) {
|
||||
if (additionalDataRepository.existsById(id)) {
|
||||
additionalData.setId(id);
|
||||
return additionalDataRepository.save(additionalData);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public boolean deleteAdditionalData(UUID id) {
|
||||
if (additionalDataRepository.existsById(id)) {
|
||||
additionalDataRepository.deleteById(id);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -3,6 +3,8 @@ package zw.qantra.tm.domain.services;
|
||||
import lombok.Getter;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.apache.commons.text.WordUtils;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.http.HttpHeaders;
|
||||
import org.springframework.http.MediaType;
|
||||
@@ -64,7 +66,7 @@ public class ProviderService {
|
||||
headers.setBearerAuth(token);
|
||||
|
||||
List<Provider> existingProviders;
|
||||
if (category != null) {
|
||||
if (category != null && !category.isEmpty()) {
|
||||
existingProviders = getProviderRepository().findByCategory(category);
|
||||
} else {
|
||||
existingProviders = getProviderRepository().findAll();
|
||||
@@ -84,6 +86,24 @@ public class ProviderService {
|
||||
LinkedHashMap body = (LinkedHashMap) response.get("body");
|
||||
List<LinkedHashMap> content = (List<LinkedHashMap>) body.get("content");
|
||||
|
||||
for (LinkedHashMap provider : content) {
|
||||
String clientId = (String) provider.get("clientId");
|
||||
if (existingProviderIds.contains(clientId)) {
|
||||
// Update existing provider
|
||||
Provider existingProvider = existingProviders.stream()
|
||||
.filter(p -> p.getClientId().equals(clientId))
|
||||
.findFirst()
|
||||
.orElse(null);
|
||||
if (existingProvider != null) {
|
||||
provider.put("name", WordUtils.capitalizeFully((String)provider.get("name")));
|
||||
provider.put("description", existingProvider.getDescription());
|
||||
provider.put("image", existingProvider.getImage());
|
||||
provider.put("label", existingProvider.getLabel());
|
||||
provider.put("category", existingProvider.getCategory());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return content;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,8 +1,17 @@
|
||||
package zw.qantra.tm.domain.services;
|
||||
|
||||
import lombok.Getter;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import zw.qantra.tm.domain.enums.RequestType;
|
||||
import zw.qantra.tm.domain.enums.Status;
|
||||
import zw.qantra.tm.domain.models.Provider;
|
||||
import zw.qantra.tm.domain.models.Transaction;
|
||||
import zw.qantra.tm.domain.repositories.TransactionRepository;
|
||||
import zw.qantra.tm.domain.services.factories.PaymentProcessorFactory;
|
||||
@@ -10,27 +19,54 @@ import zw.qantra.tm.domain.services.processors.TransactionProcessorInterface;
|
||||
import zw.qantra.tm.domain.services.processors.handlers.CalculateChargesHandler;
|
||||
import zw.qantra.tm.domain.services.processors.handlers.LogicPipeline;
|
||||
import zw.qantra.tm.domain.services.processors.handlers.ValidationHandler;
|
||||
import zw.qantra.tm.exceptions.ApiException;
|
||||
|
||||
@Service
|
||||
@RequiredArgsConstructor
|
||||
public class TransactionService {
|
||||
Logger logger = LoggerFactory.getLogger(TransactionService.class);
|
||||
|
||||
@Getter
|
||||
private final TransactionRepository transactionRepository;
|
||||
private final PaymentProcessorFactory paymentProcessorFactory;
|
||||
private final CalculateChargesHandler calculateChargesHandler;
|
||||
private final ProviderService providerService;
|
||||
|
||||
public TransactionRepository getTransactionRepository() {
|
||||
return transactionRepository;
|
||||
public Transaction poll(UUID uuid){
|
||||
if(!transactionRepository.existsById(uuid)){
|
||||
throw new ApiException("Transaction not found for ID: " + uuid);
|
||||
}
|
||||
|
||||
Transaction transaction = transactionRepository.findById(uuid).get();
|
||||
|
||||
// no persistence happens during polling unless the transaction status changes
|
||||
String label = getLabel(transaction);
|
||||
logger.info("label: {}", label);
|
||||
|
||||
TransactionProcessorInterface transactionProcessorInterface =
|
||||
(TransactionProcessorInterface) paymentProcessorFactory.getPaymentProcessor(label);
|
||||
try {
|
||||
transactionProcessorInterface.poll(transaction);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
transaction.setStatus(Status.FAILED);
|
||||
transaction.setResponseCode("01");
|
||||
transaction.setErrorMessage(e.getMessage());
|
||||
}
|
||||
return transaction;
|
||||
}
|
||||
|
||||
public Transaction execute(Transaction transaction) {
|
||||
transaction.setReference(UUID.randomUUID().toString());
|
||||
|
||||
LogicPipeline<Transaction, Transaction> transactionLogic =
|
||||
new LogicPipeline<>(calculateChargesHandler)
|
||||
.addHandler(new ValidationHandler());
|
||||
|
||||
transaction = transactionLogic.execute(transaction);
|
||||
|
||||
String label = transaction.getType() + "_" + transaction.getIntegrationProcessorLabel();
|
||||
String label = getLabel(transaction);
|
||||
logger.info("label: {}", label);
|
||||
|
||||
TransactionProcessorInterface transactionProcessorInterface =
|
||||
(TransactionProcessorInterface) paymentProcessorFactory.getPaymentProcessor(label);
|
||||
|
||||
@@ -46,4 +82,27 @@ public class TransactionService {
|
||||
}
|
||||
return transaction;
|
||||
}
|
||||
|
||||
private String getLabel(Transaction transaction){
|
||||
String label = "";
|
||||
if(transaction.getType() == RequestType.CONFIRM){
|
||||
// get processor label from billClientId
|
||||
Provider provider = providerService.getProviderRepository()
|
||||
.findByClientId(transaction.getBillClientId());
|
||||
if(provider == null){
|
||||
throw new ApiException("Provider not found for billClientId: " + transaction.getBillClientId());
|
||||
}
|
||||
label = transaction.getType() + "_" +
|
||||
provider.getLabel();
|
||||
}else{
|
||||
label = transaction.getType() + "_" +
|
||||
transaction.getPaymentProcessorLabel() + "_" +
|
||||
transaction.getAuthType();
|
||||
}
|
||||
return label;
|
||||
}
|
||||
|
||||
public Transaction save(Transaction transaction){
|
||||
return transactionRepository.save(transaction);
|
||||
}
|
||||
}
|
||||
@@ -5,4 +5,5 @@ import zw.qantra.tm.domain.models.Transaction;
|
||||
public interface TransactionProcessorInterface {
|
||||
Object process(Transaction transaction) throws Exception;
|
||||
Object reverse(Transaction transaction);
|
||||
Object poll(Transaction transaction) throws Exception;
|
||||
}
|
||||
|
||||
@@ -1,27 +1,45 @@
|
||||
package zw.qantra.tm.domain.services.processors.confirmations;
|
||||
|
||||
import lombok.RequiredArgsConstructor;
|
||||
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.slf4j.Logger;
|
||||
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.enums.Status;
|
||||
import zw.qantra.tm.domain.models.AdditionalData;
|
||||
import zw.qantra.tm.domain.models.Transaction;
|
||||
import zw.qantra.tm.domain.services.AdditionalDataService;
|
||||
import zw.qantra.tm.domain.services.TransactionService;
|
||||
import zw.qantra.tm.domain.services.processors.TransactionProcessorInterface;
|
||||
import zw.qantra.tm.rest.RestService;
|
||||
import zw.qantra.tm.utils.Utils;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.LinkedHashMap;
|
||||
|
||||
@Service("CONFIRM_ZESA")
|
||||
@RequiredArgsConstructor
|
||||
public class ZesaConfirmationProcessor implements TransactionProcessorInterface {
|
||||
Logger logger = LoggerFactory.getLogger(ZesaConfirmationProcessor.class);
|
||||
|
||||
private final RestService restService;
|
||||
private final TransactionService transactionService;
|
||||
private final AdditionalDataService additionalDataService;
|
||||
|
||||
@Value("${sbz.aggregator.url}")
|
||||
private String aggregatorUrl;
|
||||
@Value("${sbz.aggregator.client-id}")
|
||||
private String aggregatorClientId;
|
||||
@Value("${sbz.aggregator.phone}")
|
||||
private String aggregatorPhone;
|
||||
@Value("${sbz.aggregator.account}")
|
||||
private String aggregatorAccount;
|
||||
|
||||
@Override
|
||||
public Object process(Transaction transaction) throws Exception {
|
||||
System.out.println("processing transaction");
|
||||
logger.info("processing transaction");
|
||||
String token = restService.getMerchantToken();
|
||||
|
||||
BillPaymentDto request = BillPaymentDto.builder()
|
||||
@@ -30,25 +48,50 @@ public class ZesaConfirmationProcessor implements TransactionProcessorInterface
|
||||
.debitRef(transaction.getDebitRef())
|
||||
.debitCurrency(transaction.getDebitCurrency())
|
||||
.amount(transaction.getAmount())
|
||||
.aggregatorId(transaction.getAggregatorId())
|
||||
.debitPhone(transaction.getDebitPhone())
|
||||
.debitAccount(transaction.getDebitAccount())
|
||||
.creditAccount(transaction.getCreditAccount())
|
||||
.creditPhone(transaction.getCreditPhone())
|
||||
.aggregatorId(aggregatorClientId)
|
||||
.debitPhone(aggregatorPhone) // qantra mobile number
|
||||
.debitAccount(aggregatorAccount) // qantra corporate account
|
||||
.creditAccount(transaction.getCreditAccount()) // customer's zesa meter number
|
||||
.creditPhone(transaction.getCreditPhone()) // customer's contact phone number
|
||||
.billName(transaction.getBillName())
|
||||
.build();
|
||||
|
||||
String url = aggregatorUrl + "/v1/merchant/aggregation/transaction";
|
||||
String url = aggregatorUrl + "/merchant/aggregation/transaction";
|
||||
|
||||
Map response = restService.postWithToken(token, url, request, Map.class);
|
||||
LinkedHashMap response = restService.postWithToken(token, url, request, LinkedHashMap.class);
|
||||
|
||||
System.out.println(response);
|
||||
logger.info("response: {}", response.toString());
|
||||
|
||||
return transaction;
|
||||
LinkedHashMap body = (LinkedHashMap) response.get("body");
|
||||
|
||||
if (body.get("status").equals("SUCCESS")) {
|
||||
transaction.setStatus(Status.SUCCESS);
|
||||
transaction.setResponseCode((String) body.get("responseCode"));
|
||||
transaction.setAdditionalData(body.get("additionalData"));
|
||||
transactionService.save(transaction);
|
||||
|
||||
AdditionalData additionalData = AdditionalData.builder()
|
||||
.transaction(transaction)
|
||||
.jsonString(Utils.toJson(body.get("additionalData")))
|
||||
.build();
|
||||
additionalDataService.getAdditionalDataRepository().save(additionalData);
|
||||
|
||||
} else {
|
||||
transaction.setStatus(Status.FAILED);
|
||||
transaction.setErrorMessage((String) body.get("message"));
|
||||
transaction.setResponseCode((String) body.get("responseCode"));
|
||||
}
|
||||
|
||||
return transactionService.save(transaction);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object reverse(Transaction transaction) {
|
||||
return transaction;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object poll(Transaction transaction) {
|
||||
return transaction;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,11 +1,12 @@
|
||||
package zw.qantra.tm.domain.services.processors.handlers;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
import zw.qantra.tm.domain.models.Charge;
|
||||
import zw.qantra.tm.domain.models.ChargeCondition;
|
||||
import zw.qantra.tm.domain.models.Transaction;
|
||||
import zw.qantra.tm.domain.services.ChargeConditionService;
|
||||
import zw.qantra.tm.domain.services.ChargeService;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
@@ -15,15 +16,16 @@ import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
|
||||
@AllArgsConstructor
|
||||
@Service
|
||||
public class CalculateChargesHandler implements LogicHandler<Transaction, Transaction> {
|
||||
private ChargeConditionService chargeConditionService;
|
||||
Logger logger = LoggerFactory.getLogger(CalculateChargesHandler.class);
|
||||
|
||||
@Autowired
|
||||
private ChargeService chargeService;
|
||||
|
||||
@Override
|
||||
public Transaction process(Transaction transaction) {
|
||||
System.out.println("processing charges");
|
||||
logger.info("processing charges");
|
||||
transaction.setCharge(BigDecimal.ZERO);
|
||||
transaction.setTax(BigDecimal.ZERO);
|
||||
transaction.setGatewayCharge(BigDecimal.ZERO);
|
||||
@@ -122,6 +124,12 @@ public class CalculateChargesHandler implements LogicHandler<Transaction, Transa
|
||||
applyCharge(transaction, charge, chargeAmount);
|
||||
}
|
||||
|
||||
// calculate total amount for ease of use later
|
||||
transaction.setTotalAmount(
|
||||
transaction.getCharge().add(
|
||||
transaction.getTax().add(
|
||||
transaction.getGatewayCharge())));
|
||||
|
||||
return transaction;
|
||||
}
|
||||
|
||||
|
||||
@@ -25,4 +25,10 @@ public class ZesaIntegrationProcessor implements TransactionProcessorInterface {
|
||||
public Object reverse(Transaction transaction) {
|
||||
return transaction;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object poll(Transaction transaction) {
|
||||
return transaction;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,159 @@
|
||||
package zw.qantra.tm.domain.services.processors.payments;
|
||||
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.http.HttpHeaders;
|
||||
import org.springframework.stereotype.Service;
|
||||
import zw.qantra.tm.domain.dtos.SdkActionDto;
|
||||
import zw.qantra.tm.domain.enums.Status;
|
||||
import zw.qantra.tm.domain.models.Transaction;
|
||||
import zw.qantra.tm.domain.services.TransactionService;
|
||||
import zw.qantra.tm.domain.services.processors.TransactionProcessorInterface;
|
||||
import zw.qantra.tm.rest.RestService;
|
||||
import zw.qantra.tm.utils.Utils;
|
||||
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.security.MessageDigest;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.util.LinkedHashMap;
|
||||
|
||||
@Service("REQUEST_MPGS_WEB")
|
||||
@RequiredArgsConstructor
|
||||
public class MPGSWebPaymentProcessor implements TransactionProcessorInterface {
|
||||
private final Logger logger = LoggerFactory.getLogger(MPGSWebPaymentProcessor.class);
|
||||
private final RestService restService;
|
||||
private final TransactionService transactionService;
|
||||
|
||||
@Value("${sbz.aggregator.encryption-key}")
|
||||
private String encryptionKey;
|
||||
@Value("${sbz.aggregator.client-id}")
|
||||
private String clientId;
|
||||
@Value("${sbz.aggregator.client-secret}")
|
||||
private String clientSecret;
|
||||
@Value("${steward.payment.processor.url}")
|
||||
private String url;
|
||||
|
||||
@Override
|
||||
public Object process(Transaction transaction) throws Exception {
|
||||
logger.info("processing transaction");
|
||||
String token = restService.getMerchantToken();
|
||||
|
||||
String concat = clientId+
|
||||
encryptionKey+
|
||||
transaction.getCreditPhone()+
|
||||
transaction.getAmount();
|
||||
|
||||
String hex = getHash(concat);
|
||||
|
||||
SdkActionDto sdkActionDto = SdkActionDto.builder()
|
||||
.clientId(clientId)
|
||||
.clientSecret(clientSecret)
|
||||
.phone(transaction.getCreditPhone())
|
||||
.amount(transaction.getAmount().toString())
|
||||
.currency(transaction.getDebitCurrency().toString())
|
||||
.hash(hex)
|
||||
.authType("WEB")
|
||||
.billerReference(transaction.getReference())
|
||||
.action("PAYMENT")
|
||||
.sandbox(true)
|
||||
.paymentProcessorLabel("MPGS")
|
||||
.responseUrl("https://www.google.com")
|
||||
.build();
|
||||
|
||||
HttpHeaders headers = new HttpHeaders();
|
||||
headers.set("Authorization", "Bearer " + token);
|
||||
headers.set("Content-Type", "application/json");
|
||||
|
||||
try {
|
||||
LinkedHashMap response = restService.postAs(url + "/merchant/sdk/action",
|
||||
sdkActionDto, headers, LinkedHashMap.class);
|
||||
logger.info("response: {}", Utils.toJson(response));
|
||||
|
||||
LinkedHashMap body = (LinkedHashMap) response.get("body");
|
||||
transaction.setSdkActionId((String) body.get("uid"));
|
||||
|
||||
if(!body.get("status").equals("FAILED")){
|
||||
transaction.setStatus(Status.PENDING);
|
||||
transaction.setResponseCode("00");
|
||||
transaction.setTargetUrl((String) body.get("targetUrl"));
|
||||
}else{
|
||||
transaction.setStatus(Status.FAILED);
|
||||
transaction.setResponseCode("01");
|
||||
transaction.setErrorMessage((String) body.get("message"));
|
||||
}
|
||||
} catch (Exception e) {
|
||||
logger.error("Network error during payment processing: {}", e.getMessage(), e);
|
||||
transaction.setStatus(Status.FAILED);
|
||||
transaction.setResponseCode("99");
|
||||
transaction.setErrorMessage("Network error: " + e.getMessage());
|
||||
}
|
||||
|
||||
return transactionService.save(transaction);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object poll(Transaction transaction) throws Exception {
|
||||
logger.info("polling transaction");
|
||||
String token = restService.getMerchantToken();
|
||||
|
||||
HttpHeaders headers = new HttpHeaders();
|
||||
headers.set("Authorization", "Bearer " + token);
|
||||
headers.set("Content-Type", "application/json");
|
||||
|
||||
try {
|
||||
LinkedHashMap response = restService.getAs(url + "/merchant/sdk/mpgs/poll/" + transaction.getSdkActionId(),
|
||||
headers, LinkedHashMap.class);
|
||||
logger.info("response: {}", Utils.toJson(response));
|
||||
|
||||
LinkedHashMap body = (LinkedHashMap) response.get("body");
|
||||
|
||||
// only update tran status if polling returns a success
|
||||
if(body.get("status").equals("SUCCESS")){
|
||||
transaction.setStatus(Status.SUCCESS);
|
||||
transaction.setResponseCode("00");
|
||||
transaction.setTargetUrl((String) body.get("targetUrl"));
|
||||
transactionService.save(transaction);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
logger.error("Network error during payment processing: {}", e.getMessage(), e);
|
||||
transaction.setStatus(Status.FAILED);
|
||||
transaction.setResponseCode("99");
|
||||
transaction.setErrorMessage("Network error: " + e.getMessage());
|
||||
}
|
||||
|
||||
return transaction;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object reverse(Transaction transaction) {
|
||||
return transaction;
|
||||
}
|
||||
|
||||
public String getHash(String originalString){
|
||||
String hex = "";
|
||||
MessageDigest digest = null;
|
||||
try {
|
||||
digest = MessageDigest.getInstance("SHA-256");
|
||||
byte[] encodedhash = digest.digest(
|
||||
originalString.getBytes(StandardCharsets.UTF_8));
|
||||
hex = bytesToHex(encodedhash);
|
||||
} catch (NoSuchAlgorithmException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return hex;
|
||||
}
|
||||
|
||||
private static String bytesToHex(byte[] hash) {
|
||||
StringBuilder hexString = new StringBuilder(2 * hash.length);
|
||||
for (int i = 0; i < hash.length; i++) {
|
||||
String hex = Integer.toHexString(0xff & hash[i]);
|
||||
if(hex.length() == 1) {
|
||||
hexString.append('0');
|
||||
}
|
||||
hexString.append(hex);
|
||||
}
|
||||
return hexString.toString();
|
||||
}
|
||||
}
|
||||
@@ -1,24 +1,131 @@
|
||||
package zw.qantra.tm.domain.services.processors.payments;
|
||||
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.security.MessageDigest;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.util.LinkedHashMap;
|
||||
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.http.HttpHeaders;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import zw.qantra.tm.domain.dtos.SdkActionDto;
|
||||
import zw.qantra.tm.domain.enums.Status;
|
||||
import zw.qantra.tm.domain.models.Transaction;
|
||||
import zw.qantra.tm.domain.services.processors.TransactionProcessorInterface;
|
||||
import zw.qantra.tm.domain.services.TransactionService;
|
||||
import zw.qantra.tm.rest.RestService;
|
||||
import zw.qantra.tm.utils.Utils;
|
||||
|
||||
@Service("STEWARD_WEB")
|
||||
@Service("REQUEST_STEWARD_WEB")
|
||||
@RequiredArgsConstructor
|
||||
public class StewardWebPaymentProcessor implements TransactionProcessorInterface {
|
||||
private final Logger logger = LoggerFactory.getLogger(StewardWebPaymentProcessor.class);
|
||||
private final RestService restService;
|
||||
private final TransactionService transactionService;
|
||||
|
||||
@Value("${sbz.aggregator.encryption-key}")
|
||||
private String encryptionKey;
|
||||
@Value("${sbz.aggregator.client-id}")
|
||||
private String clientId;
|
||||
@Value("${sbz.aggregator.client-secret}")
|
||||
private String clientSecret;
|
||||
@Value("${steward.payment.processor.url}")
|
||||
private String url;
|
||||
|
||||
@Override
|
||||
public Object process(Transaction transaction) throws Exception {
|
||||
return transaction;
|
||||
logger.info("processing transaction");
|
||||
String token = restService.getMerchantToken();
|
||||
|
||||
String concat = clientId+
|
||||
encryptionKey+
|
||||
transaction.getCreditPhone()+
|
||||
transaction.getAmount();
|
||||
|
||||
String hex = getHash(concat);
|
||||
|
||||
SdkActionDto sdkActionDto = SdkActionDto.builder()
|
||||
.clientId(clientId)
|
||||
.clientSecret(clientSecret)
|
||||
.phone(transaction.getCreditPhone())
|
||||
.amount(transaction.getAmount().toString())
|
||||
.currency(transaction.getDebitCurrency().toString())
|
||||
.hash(hex)
|
||||
.authType("WEB")
|
||||
.billerReference(transaction.getReference())
|
||||
.action("PAYMENT")
|
||||
.sandbox(true)
|
||||
.paymentProcessorLabel("STEWARD")
|
||||
.responseUrl("https://www.google.com")
|
||||
.build();
|
||||
|
||||
HttpHeaders headers = new HttpHeaders();
|
||||
headers.set("Authorization", "Bearer " + token);
|
||||
headers.set("Content-Type", "application/json");
|
||||
|
||||
try {
|
||||
LinkedHashMap response = restService.postAs(url + "/merchant/sdk/action", sdkActionDto, headers, LinkedHashMap.class);
|
||||
logger.info("response: {}", Utils.toJson(response));
|
||||
|
||||
LinkedHashMap body = (LinkedHashMap) response.get("body");
|
||||
transaction.setSdkActionId((String) body.get("uid"));
|
||||
|
||||
if(!body.get("status").equals("FAILED")){
|
||||
transaction.setStatus(Status.SUCCESS);
|
||||
transaction.setResponseCode("00");
|
||||
transaction.setTargetUrl((String) body.get("targetUrl"));
|
||||
}else{
|
||||
transaction.setStatus(Status.FAILED);
|
||||
transaction.setResponseCode("01");
|
||||
transaction.setErrorMessage((String) body.get("message"));
|
||||
}
|
||||
} catch (Exception e) {
|
||||
logger.error("Network error during payment processing: {}", e.getMessage(), e);
|
||||
transaction.setStatus(Status.FAILED);
|
||||
transaction.setResponseCode("99");
|
||||
transaction.setErrorMessage("Network error: " + e.getMessage());
|
||||
}
|
||||
|
||||
return transactionService.save(transaction);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object reverse(Transaction transaction) {
|
||||
return transaction;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object poll(Transaction transaction) {
|
||||
return transaction;
|
||||
}
|
||||
|
||||
public String getHash(String originalString){
|
||||
String hex = "";
|
||||
MessageDigest digest = null;
|
||||
try {
|
||||
digest = MessageDigest.getInstance("SHA-256");
|
||||
byte[] encodedhash = digest.digest(
|
||||
originalString.getBytes(StandardCharsets.UTF_8));
|
||||
hex = bytesToHex(encodedhash);
|
||||
} catch (NoSuchAlgorithmException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return hex;
|
||||
}
|
||||
|
||||
private static String bytesToHex(byte[] hash) {
|
||||
StringBuilder hexString = new StringBuilder(2 * hash.length);
|
||||
for (int i = 0; i < hash.length; i++) {
|
||||
String hex = Integer.toHexString(0xff & hash[i]);
|
||||
if(hex.length() == 1) {
|
||||
hexString.append('0');
|
||||
}
|
||||
hexString.append(hex);
|
||||
}
|
||||
return hexString.toString();
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user