poc completed
This commit is contained in:
22
.giltab-ci.yml
Normal file
22
.giltab-ci.yml
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
image: docker:19.03.1
|
||||||
|
|
||||||
|
variables:
|
||||||
|
REGISTRY: 144.91.121.112:8082
|
||||||
|
DEV_TAG: q-cbs-transaction-manager-spring-boot:develop
|
||||||
|
TAG: q-cbs-transaction-manager-spring-boot:0.0.0-RELEASE
|
||||||
|
DOCKER_OPTS: "--insecure-registry=$REGISTRY"
|
||||||
|
|
||||||
|
stages:
|
||||||
|
- package_test
|
||||||
|
|
||||||
|
before_script:
|
||||||
|
- docker info
|
||||||
|
- docker login -u admin -p 1aae6202-7d42-44e4-bdc7-d988a95fdfe2 $REGISTRY
|
||||||
|
|
||||||
|
package_test:
|
||||||
|
stage: package_test
|
||||||
|
script:
|
||||||
|
- docker build -f Dockerfile-lab -t "$REGISTRY/$DEV_TAG" .
|
||||||
|
- docker push "$REGISTRY/$DEV_TAG"
|
||||||
|
only:
|
||||||
|
- develop
|
||||||
7
Dockerfile-lab
Normal file
7
Dockerfile-lab
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
FROM 144.91.121.112:8082/java-17
|
||||||
|
RUN mkdir /app
|
||||||
|
COPY . /app
|
||||||
|
WORKDIR /app
|
||||||
|
RUN mvn clean compile -P develop package
|
||||||
|
ENTRYPOINT ["/usr/bin/dumb-init", "--"]
|
||||||
|
CMD ["java", "-Duser.timezone=CAT", "-Dspring.profiles.active=lab", "-jar", "/app/target/cbs-transaction-manager-0.0.1-SNAPSHOT.jar"]
|
||||||
17
src/main/java/zw/qantra/tm/configs/SpecificationConfig.java
Normal file
17
src/main/java/zw/qantra/tm/configs/SpecificationConfig.java
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
package zw.qantra.tm.configs;
|
||||||
|
|
||||||
|
import net.kaczmarzyk.spring.data.jpa.web.SpecificationArgumentResolver;
|
||||||
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
import org.springframework.web.method.support.HandlerMethodArgumentResolver;
|
||||||
|
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
@Configuration
|
||||||
|
public class SpecificationConfig implements WebMvcConfigurer {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void addArgumentResolvers(List<HandlerMethodArgumentResolver> argumentResolvers) {
|
||||||
|
argumentResolvers.add(new SpecificationArgumentResolver());
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -11,10 +11,12 @@ import zw.qantra.tm.domain.enums.CurrencyType;
|
|||||||
import zw.qantra.tm.domain.models.Category;
|
import zw.qantra.tm.domain.models.Category;
|
||||||
import zw.qantra.tm.domain.models.Charge;
|
import zw.qantra.tm.domain.models.Charge;
|
||||||
import zw.qantra.tm.domain.models.ChargeCondition;
|
import zw.qantra.tm.domain.models.ChargeCondition;
|
||||||
|
import zw.qantra.tm.domain.models.IntegrationProcessor;
|
||||||
import zw.qantra.tm.domain.models.PaymentProcessor;
|
import zw.qantra.tm.domain.models.PaymentProcessor;
|
||||||
import zw.qantra.tm.domain.models.Provider;
|
import zw.qantra.tm.domain.models.Provider;
|
||||||
import zw.qantra.tm.domain.services.ChargeConditionService;
|
import zw.qantra.tm.domain.services.ChargeConditionService;
|
||||||
import zw.qantra.tm.domain.services.ChargeService;
|
import zw.qantra.tm.domain.services.ChargeService;
|
||||||
|
import zw.qantra.tm.domain.services.IntegrationProcessorService;
|
||||||
import zw.qantra.tm.domain.services.CategoryService;
|
import zw.qantra.tm.domain.services.CategoryService;
|
||||||
import zw.qantra.tm.domain.services.PaymentProcessorService;
|
import zw.qantra.tm.domain.services.PaymentProcessorService;
|
||||||
import zw.qantra.tm.domain.services.ProviderService;
|
import zw.qantra.tm.domain.services.ProviderService;
|
||||||
@@ -33,9 +35,20 @@ public class ConfigController {
|
|||||||
private final PaymentProcessorService paymentProcessorService;
|
private final PaymentProcessorService paymentProcessorService;
|
||||||
private final ProviderService providerService;
|
private final ProviderService providerService;
|
||||||
private final CategoryService categoryService;
|
private final CategoryService categoryService;
|
||||||
|
private final IntegrationProcessorService integrationProcessorService;
|
||||||
|
|
||||||
@GetMapping("/seed")
|
@GetMapping("/seed")
|
||||||
public ResponseEntity charges(){
|
public ResponseEntity charges(){
|
||||||
|
|
||||||
|
integrationProcessorService.getIntegrationProcessorRepository().deleteAll();
|
||||||
|
integrationProcessorService.getIntegrationProcessorRepository().saveAll(Arrays.asList(
|
||||||
|
IntegrationProcessor.builder()
|
||||||
|
.name("STEWARD")
|
||||||
|
.label("STEWARD")
|
||||||
|
.description("Steward Integration Processor")
|
||||||
|
.build()
|
||||||
|
));
|
||||||
|
|
||||||
// clear existing categories before seeding
|
// clear existing categories before seeding
|
||||||
categoryService.getCategoryRepository().deleteAll();
|
categoryService.getCategoryRepository().deleteAll();
|
||||||
// seed categories
|
// seed categories
|
||||||
@@ -65,6 +78,7 @@ public class ConfigController {
|
|||||||
.category("AIRTIME")
|
.category("AIRTIME")
|
||||||
.image("econet.png")
|
.image("econet.png")
|
||||||
.externalId("78f1f497-c9eb-401c-b22c-884756e68e40")
|
.externalId("78f1f497-c9eb-401c-b22c-884756e68e40")
|
||||||
|
.integrationProcessorLabel("STEWARD")
|
||||||
.build(),
|
.build(),
|
||||||
Provider.builder()
|
Provider.builder()
|
||||||
.description("NetOne Airtime")
|
.description("NetOne Airtime")
|
||||||
@@ -73,6 +87,7 @@ public class ConfigController {
|
|||||||
.category("AIRTIME")
|
.category("AIRTIME")
|
||||||
.image("netone.png")
|
.image("netone.png")
|
||||||
.externalId("95d485a7-39c9-4559-8a27-6521969abe8f")
|
.externalId("95d485a7-39c9-4559-8a27-6521969abe8f")
|
||||||
|
.integrationProcessorLabel("STEWARD")
|
||||||
.build(),
|
.build(),
|
||||||
Provider.builder()
|
Provider.builder()
|
||||||
.description("Prepaid Zesa")
|
.description("Prepaid Zesa")
|
||||||
@@ -81,6 +96,7 @@ public class ConfigController {
|
|||||||
.category("UTILITIES")
|
.category("UTILITIES")
|
||||||
.image("zesa.png")
|
.image("zesa.png")
|
||||||
.externalId("0f67f7cc-b62b-4fb5-915f-6740b2afdba6")
|
.externalId("0f67f7cc-b62b-4fb5-915f-6740b2afdba6")
|
||||||
|
.integrationProcessorLabel("STEWARD")
|
||||||
.build(),
|
.build(),
|
||||||
Provider.builder()
|
Provider.builder()
|
||||||
.description("Econet Broadband")
|
.description("Econet Broadband")
|
||||||
@@ -89,6 +105,7 @@ public class ConfigController {
|
|||||||
.category("AIRTIME")
|
.category("AIRTIME")
|
||||||
.image("econet.png")
|
.image("econet.png")
|
||||||
.externalId("287863e2-a791-4106-b629-79dadc9a6779")
|
.externalId("287863e2-a791-4106-b629-79dadc9a6779")
|
||||||
|
.integrationProcessorLabel("STEWARD")
|
||||||
.build()
|
.build()
|
||||||
);
|
);
|
||||||
providerService.getProviderRepository().saveAll(providers);
|
providerService.getProviderRepository().saveAll(providers);
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ public class ProviderController {
|
|||||||
|
|
||||||
@GetMapping
|
@GetMapping
|
||||||
public ResponseEntity getProviders(@RequestParam(required = false) String category) {
|
public ResponseEntity getProviders(@RequestParam(required = false) String category) {
|
||||||
return ResponseEntity.ok(providerService.getProviders(category));
|
return ResponseEntity.ok(providerService.getProvidersByCategory(category));
|
||||||
}
|
}
|
||||||
|
|
||||||
@GetMapping("/{id}/products")
|
@GetMapping("/{id}/products")
|
||||||
@@ -25,6 +25,16 @@ public class ProviderController {
|
|||||||
return ResponseEntity.ok(providerService.getProviderProducts(id));
|
return ResponseEntity.ok(providerService.getProviderProducts(id));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@GetMapping("/{id}/products/{productId}")
|
||||||
|
public ResponseEntity getProducts(@PathVariable UUID id, @PathVariable UUID productId) {
|
||||||
|
return ResponseEntity.ok(providerService.getProviderProduct(id, productId));
|
||||||
|
}
|
||||||
|
|
||||||
|
@GetMapping("/client/{clientId}")
|
||||||
|
public ResponseEntity getProviderByClientId(@PathVariable String clientId) {
|
||||||
|
return ResponseEntity.ok(providerService.getProviderByClientId(clientId));
|
||||||
|
}
|
||||||
|
|
||||||
@GetMapping("/{id}")
|
@GetMapping("/{id}")
|
||||||
public ResponseEntity getProvider(@PathVariable UUID id) {
|
public ResponseEntity getProvider(@PathVariable UUID id) {
|
||||||
return providerService.getProvider(id)
|
return providerService.getProvider(id)
|
||||||
|
|||||||
@@ -0,0 +1,73 @@
|
|||||||
|
package zw.qantra.tm.domain.controllers;
|
||||||
|
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
import net.kaczmarzyk.spring.data.jpa.domain.Equal;
|
||||||
|
import net.kaczmarzyk.spring.data.jpa.domain.Like;
|
||||||
|
import net.kaczmarzyk.spring.data.jpa.web.annotation.Spec;
|
||||||
|
import net.kaczmarzyk.spring.data.jpa.web.annotation.Or;
|
||||||
|
import org.springframework.data.jpa.domain.Specification;
|
||||||
|
import org.springframework.http.ResponseEntity;
|
||||||
|
import org.springframework.web.bind.annotation.*;
|
||||||
|
import zw.qantra.tm.domain.models.Recipient;
|
||||||
|
import zw.qantra.tm.domain.services.RecipientService;
|
||||||
|
import net.kaczmarzyk.spring.data.jpa.web.annotation.And;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
@RestController
|
||||||
|
@RequestMapping("/recipients")
|
||||||
|
@RequiredArgsConstructor
|
||||||
|
public class RecipientController {
|
||||||
|
|
||||||
|
private final RecipientService recipientService;
|
||||||
|
|
||||||
|
@GetMapping
|
||||||
|
public ResponseEntity<List<Recipient>> getAllRecipients() {
|
||||||
|
return ResponseEntity.ok(recipientService.getAllRecipients());
|
||||||
|
}
|
||||||
|
|
||||||
|
@GetMapping("/{account}/user/{userId}")
|
||||||
|
public ResponseEntity<Recipient> getRecipient(@PathVariable String account, @PathVariable String userId) {
|
||||||
|
List<Recipient> recipients = recipientService.getRecipient(account, userId);
|
||||||
|
if(recipients.size() > 0){
|
||||||
|
return ResponseEntity.ok(recipients.get(0));
|
||||||
|
}
|
||||||
|
return ResponseEntity.notFound().build();
|
||||||
|
}
|
||||||
|
|
||||||
|
@PostMapping
|
||||||
|
public ResponseEntity<Recipient> createRecipient(@RequestBody Recipient recipient) {
|
||||||
|
return ResponseEntity.ok(recipientService.save(recipient));
|
||||||
|
}
|
||||||
|
|
||||||
|
@PutMapping("/{id}")
|
||||||
|
public ResponseEntity<Recipient> updateRecipient(@PathVariable UUID id, @RequestBody Recipient recipient) {
|
||||||
|
Recipient updatedRecipient = recipientService.updateRecipient(id, recipient);
|
||||||
|
if (updatedRecipient != null) {
|
||||||
|
return ResponseEntity.ok(updatedRecipient);
|
||||||
|
}
|
||||||
|
return ResponseEntity.notFound().build();
|
||||||
|
}
|
||||||
|
|
||||||
|
@DeleteMapping("/{id}")
|
||||||
|
public ResponseEntity<String> deleteRecipient(@PathVariable UUID id) {
|
||||||
|
if (recipientService.deleteRecipient(id)) {
|
||||||
|
return ResponseEntity.ok("Recipient deleted successfully");
|
||||||
|
}
|
||||||
|
return ResponseEntity.notFound().build();
|
||||||
|
}
|
||||||
|
|
||||||
|
@GetMapping("/search")
|
||||||
|
public ResponseEntity<List<Recipient>> searchRecipients(
|
||||||
|
@And({
|
||||||
|
@Spec(path = "name", spec = Equal.class),
|
||||||
|
@Spec(path = "email", spec = Equal.class),
|
||||||
|
@Spec(path = "phoneNumber", spec = Equal.class),
|
||||||
|
@Spec(path = "account", spec = Equal.class),
|
||||||
|
@Spec(path = "latestProviderLabel", spec = Equal.class),
|
||||||
|
@Spec(path = "userId", spec = Equal.class)
|
||||||
|
}) Specification<Recipient> specification) {
|
||||||
|
return ResponseEntity.ok(recipientService.searchRecipients(specification));
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,6 +1,12 @@
|
|||||||
package zw.qantra.tm.domain.controllers;
|
package zw.qantra.tm.domain.controllers;
|
||||||
|
|
||||||
import lombok.RequiredArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
|
import net.kaczmarzyk.spring.data.jpa.domain.Equal;
|
||||||
|
import net.kaczmarzyk.spring.data.jpa.web.annotation.And;
|
||||||
|
import net.kaczmarzyk.spring.data.jpa.web.annotation.Or;
|
||||||
|
import net.kaczmarzyk.spring.data.jpa.web.annotation.Spec;
|
||||||
|
import net.kaczmarzyk.spring.data.jpa.web.annotation.Conjunction;
|
||||||
|
import org.springframework.data.jpa.domain.Specification;
|
||||||
import zw.qantra.tm.domain.services.TransactionService;
|
import zw.qantra.tm.domain.services.TransactionService;
|
||||||
import zw.qantra.tm.domain.models.Transaction;
|
import zw.qantra.tm.domain.models.Transaction;
|
||||||
|
|
||||||
@@ -8,6 +14,7 @@ import org.slf4j.Logger;
|
|||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
import org.springframework.http.ResponseEntity;
|
import org.springframework.http.ResponseEntity;
|
||||||
import org.springframework.web.bind.annotation.*;
|
import org.springframework.web.bind.annotation.*;
|
||||||
|
import zw.qantra.tm.utils.Utils;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
@@ -21,15 +28,40 @@ public class TransactonController {
|
|||||||
private final TransactionService transactionService;
|
private final TransactionService transactionService;
|
||||||
|
|
||||||
@GetMapping
|
@GetMapping
|
||||||
public ResponseEntity<List<Transaction>> getAll() {
|
public ResponseEntity<List<Transaction>> getAll(
|
||||||
return ResponseEntity.ok(transactionService.getTransactionRepository().findAll());
|
@Conjunction(value = {
|
||||||
|
@Or({
|
||||||
|
@Spec(path = "status", spec = Equal.class),
|
||||||
|
@Spec(path = "createdAt", spec = Equal.class),
|
||||||
|
@Spec(path = "providerLabel", spec = Equal.class),
|
||||||
|
@Spec(path = "billClientId", spec = Equal.class),
|
||||||
|
@Spec(path = "productUid", spec = Equal.class),
|
||||||
|
@Spec(path = "productName", spec = Equal.class),
|
||||||
|
@Spec(path = "debitName", spec = Equal.class),
|
||||||
|
@Spec(path = "debitAccount", spec = Equal.class),
|
||||||
|
@Spec(path = "debitCurrency", spec = Equal.class),
|
||||||
|
@Spec(path = "debitPhone", spec = Equal.class),
|
||||||
|
@Spec(path = "creditName", spec = Equal.class),
|
||||||
|
@Spec(path = "creditAccount", spec = Equal.class),
|
||||||
|
@Spec(path = "creditCurrency", spec = Equal.class),
|
||||||
|
@Spec(path = "creditPhone", spec = Equal.class),
|
||||||
|
@Spec(path = "amount", spec = Equal.class),
|
||||||
|
@Spec(path = "reference", spec = Equal.class),
|
||||||
|
@Spec(path = "totalAmount", spec = Equal.class),
|
||||||
|
@Spec(path = "authType", spec = Equal.class),
|
||||||
|
@Spec(path = "sdkActionId", spec = Equal.class),
|
||||||
|
@Spec(path = "paymentProcessorLabel", spec = Equal.class),
|
||||||
|
})
|
||||||
|
}, and = {
|
||||||
|
@Spec(path = "type", spec = Equal.class),
|
||||||
|
@Spec(path = "userId", spec = Equal.class),
|
||||||
|
}) Specification<Transaction> specification) {
|
||||||
|
return ResponseEntity.ok(transactionService.findAll(specification));
|
||||||
}
|
}
|
||||||
|
|
||||||
@GetMapping("/{id}")
|
@GetMapping("/{id}")
|
||||||
public ResponseEntity<Transaction> getById(@PathVariable UUID id) {
|
public ResponseEntity<Transaction> getById(@PathVariable UUID id) {
|
||||||
return transactionService.getTransactionRepository().findById(id)
|
return ResponseEntity.ok(transactionService.findById(id));
|
||||||
.map(ResponseEntity::ok)
|
|
||||||
.orElse(ResponseEntity.notFound().build());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@GetMapping("/poll/{id}")
|
@GetMapping("/poll/{id}")
|
||||||
@@ -39,9 +71,9 @@ public class TransactonController {
|
|||||||
|
|
||||||
@PostMapping
|
@PostMapping
|
||||||
public ResponseEntity<Transaction> create(@RequestBody Transaction transaction) {
|
public ResponseEntity<Transaction> create(@RequestBody Transaction transaction) {
|
||||||
logger.info("incoming transaction: {}", transaction);
|
logger.info("incoming transaction: {}", Utils.toJson(transaction));
|
||||||
Transaction createdTransaction = transactionService.execute(transaction);
|
Transaction createdTransaction = transactionService.execute(transaction);
|
||||||
logger.info("outgoing transaction: {}", createdTransaction);
|
logger.info("outgoing transaction: {}", Utils.toJson(createdTransaction));
|
||||||
return ResponseEntity.ok(createdTransaction);
|
return ResponseEntity.ok(createdTransaction);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import lombok.AllArgsConstructor;
|
|||||||
import lombok.Builder;
|
import lombok.Builder;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
import lombok.NoArgsConstructor;
|
import lombok.NoArgsConstructor;
|
||||||
|
import zw.qantra.tm.domain.enums.AuthType;
|
||||||
import zw.qantra.tm.domain.enums.CurrencyType;
|
import zw.qantra.tm.domain.enums.CurrencyType;
|
||||||
import zw.qantra.tm.domain.enums.RequestType;
|
import zw.qantra.tm.domain.enums.RequestType;
|
||||||
|
|
||||||
@@ -17,6 +18,7 @@ import java.math.BigDecimal;
|
|||||||
@JsonIgnoreProperties(ignoreUnknown = true)
|
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||||
public class BillPaymentDto {
|
public class BillPaymentDto {
|
||||||
private RequestType type;
|
private RequestType type;
|
||||||
|
private AuthType authType;
|
||||||
private String billClientId;
|
private String billClientId;
|
||||||
private String debitRef;
|
private String debitRef;
|
||||||
private CurrencyType debitCurrency;
|
private CurrencyType debitCurrency;
|
||||||
@@ -28,4 +30,5 @@ public class BillPaymentDto {
|
|||||||
private CurrencyType creditCurrency;
|
private CurrencyType creditCurrency;
|
||||||
private String creditPhone;
|
private String creditPhone;
|
||||||
private String billName;
|
private String billName;
|
||||||
|
private String trace;
|
||||||
}
|
}
|
||||||
@@ -6,10 +6,13 @@ import jakarta.persistence.Id;
|
|||||||
import jakarta.persistence.MappedSuperclass;
|
import jakarta.persistence.MappedSuperclass;
|
||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
import lombok.Setter;
|
import lombok.Setter;
|
||||||
|
import org.hibernate.annotations.CreationTimestamp;
|
||||||
import org.hibernate.annotations.GenericGenerator;
|
import org.hibernate.annotations.GenericGenerator;
|
||||||
import org.hibernate.annotations.JdbcTypeCode;
|
import org.hibernate.annotations.JdbcTypeCode;
|
||||||
|
import org.hibernate.annotations.UpdateTimestamp;
|
||||||
import org.hibernate.type.SqlTypes;
|
import org.hibernate.type.SqlTypes;
|
||||||
|
|
||||||
|
import java.time.LocalDateTime;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
|
||||||
@Getter
|
@Getter
|
||||||
@@ -25,4 +28,13 @@ public class BaseEntity {
|
|||||||
@JdbcTypeCode(SqlTypes.UUID)
|
@JdbcTypeCode(SqlTypes.UUID)
|
||||||
@Column(name = "id", updatable = false, nullable = false)
|
@Column(name = "id", updatable = false, nullable = false)
|
||||||
private UUID id;
|
private UUID id;
|
||||||
|
|
||||||
|
@CreationTimestamp
|
||||||
|
@Column(name = "created_at", nullable = true, updatable = false)
|
||||||
|
private LocalDateTime createdAt; // Or Date, Timestamp
|
||||||
|
|
||||||
|
@UpdateTimestamp
|
||||||
|
@Column(name = "updated_at", nullable = true)
|
||||||
|
private LocalDateTime updatedAt; // Or Date, Timestamp
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,4 +17,6 @@ public class Provider extends BaseEntity {
|
|||||||
private String externalId;
|
private String externalId;
|
||||||
private String image;
|
private String image;
|
||||||
private String category;
|
private String category;
|
||||||
|
private String accountFieldName;
|
||||||
|
private String integrationProcessorLabel;
|
||||||
}
|
}
|
||||||
|
|||||||
21
src/main/java/zw/qantra/tm/domain/models/Recipient.java
Normal file
21
src/main/java/zw/qantra/tm/domain/models/Recipient.java
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
package zw.qantra.tm.domain.models;
|
||||||
|
|
||||||
|
import jakarta.persistence.Entity;
|
||||||
|
import lombok.*;
|
||||||
|
|
||||||
|
@Entity
|
||||||
|
@Getter
|
||||||
|
@Setter
|
||||||
|
@Builder
|
||||||
|
@AllArgsConstructor
|
||||||
|
@NoArgsConstructor
|
||||||
|
public class Recipient extends BaseEntity {
|
||||||
|
private String name;
|
||||||
|
private String email;
|
||||||
|
private String phoneNumber;
|
||||||
|
private String address;
|
||||||
|
private String account;
|
||||||
|
private String initials;
|
||||||
|
private String latestProviderLabel;
|
||||||
|
private String userId;
|
||||||
|
}
|
||||||
@@ -18,6 +18,7 @@ import java.math.BigDecimal;
|
|||||||
@NoArgsConstructor
|
@NoArgsConstructor
|
||||||
@JsonInclude(JsonInclude.Include.NON_NULL)
|
@JsonInclude(JsonInclude.Include.NON_NULL)
|
||||||
public class Transaction extends BaseEntity {
|
public class Transaction extends BaseEntity {
|
||||||
|
private String userId;
|
||||||
private String trace;
|
private String trace;
|
||||||
private BigDecimal amount;
|
private BigDecimal amount;
|
||||||
private BigDecimal charge;
|
private BigDecimal charge;
|
||||||
@@ -40,6 +41,7 @@ public class Transaction extends BaseEntity {
|
|||||||
private String debitName;
|
private String debitName;
|
||||||
private String debitCard;
|
private String debitCard;
|
||||||
private String debitRef;
|
private String debitRef;
|
||||||
|
private String debitEmail;
|
||||||
private String creditPhone;
|
private String creditPhone;
|
||||||
private String creditAccount;
|
private String creditAccount;
|
||||||
@Enumerated(EnumType.STRING)
|
@Enumerated(EnumType.STRING)
|
||||||
@@ -47,11 +49,15 @@ public class Transaction extends BaseEntity {
|
|||||||
private String creditName;
|
private String creditName;
|
||||||
private String creditCard;
|
private String creditCard;
|
||||||
private String creditRef;
|
private String creditRef;
|
||||||
|
private String creditEmail;
|
||||||
private String billClientId;
|
private String billClientId;
|
||||||
private String clientSecret;
|
private String clientSecret;
|
||||||
private String aggregatorId;
|
private String aggregatorId;
|
||||||
private String billName;
|
private String billName;
|
||||||
private String billProductName;
|
private String billProductName;
|
||||||
|
private String paymentProcessorName;
|
||||||
|
private String providerImage;
|
||||||
|
private String paymentProcessorImage;
|
||||||
@Enumerated(EnumType.STRING)
|
@Enumerated(EnumType.STRING)
|
||||||
private RequestType type;
|
private RequestType type;
|
||||||
@Enumerated(EnumType.STRING)
|
@Enumerated(EnumType.STRING)
|
||||||
@@ -60,6 +66,7 @@ public class Transaction extends BaseEntity {
|
|||||||
@Column(columnDefinition = "TEXT")
|
@Column(columnDefinition = "TEXT")
|
||||||
private String errorMessage;
|
private String errorMessage;
|
||||||
private String responseCode;
|
private String responseCode;
|
||||||
|
@Enumerated(EnumType.STRING)
|
||||||
private Status status;
|
private Status status;
|
||||||
@Column(columnDefinition = "TEXT")
|
@Column(columnDefinition = "TEXT")
|
||||||
private String targetUrl;
|
private String targetUrl;
|
||||||
|
|||||||
@@ -0,0 +1,17 @@
|
|||||||
|
package zw.qantra.tm.domain.repositories;
|
||||||
|
|
||||||
|
import org.springframework.data.jpa.repository.JpaRepository;
|
||||||
|
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
|
||||||
|
import org.springframework.stereotype.Repository;
|
||||||
|
import zw.qantra.tm.domain.models.Recipient;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
@Repository
|
||||||
|
public interface RecipientRepository extends JpaRepository<Recipient, UUID>, JpaSpecificationExecutor<Recipient> {
|
||||||
|
List<Recipient> findByNameContainingIgnoreCase(String name);
|
||||||
|
List<Recipient> findByEmailContainingIgnoreCase(String email);
|
||||||
|
List<Recipient> findByPhoneNumberContaining(String phoneNumber);
|
||||||
|
List<Recipient> findByAccountAndUserId(String account, String userId);
|
||||||
|
}
|
||||||
@@ -1,11 +1,15 @@
|
|||||||
package zw.qantra.tm.domain.repositories;
|
package zw.qantra.tm.domain.repositories;
|
||||||
|
|
||||||
import org.springframework.data.jpa.repository.JpaRepository;
|
import org.springframework.data.jpa.repository.JpaRepository;
|
||||||
|
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
|
||||||
import org.springframework.stereotype.Repository;
|
import org.springframework.stereotype.Repository;
|
||||||
|
|
||||||
|
import zw.qantra.tm.domain.enums.RequestType;
|
||||||
import zw.qantra.tm.domain.models.Transaction;
|
import zw.qantra.tm.domain.models.Transaction;
|
||||||
|
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
|
||||||
@Repository
|
@Repository
|
||||||
public interface TransactionRepository extends JpaRepository<Transaction, UUID> {
|
public interface TransactionRepository extends JpaRepository<Transaction, UUID>, JpaSpecificationExecutor<Transaction> {
|
||||||
|
Transaction findByTraceAndType(String trace, RequestType type);
|
||||||
}
|
}
|
||||||
@@ -30,6 +30,13 @@ public class ProviderService {
|
|||||||
@Value("${sbz.aggregator.url}")
|
@Value("${sbz.aggregator.url}")
|
||||||
private String aggregatorUrl;
|
private String aggregatorUrl;
|
||||||
|
|
||||||
|
public SBZProductDto getProviderProduct(UUID providerId, UUID productId) {
|
||||||
|
return getProviderProducts(providerId).stream()
|
||||||
|
.filter(product -> product.getUid().equals(productId))
|
||||||
|
.findFirst()
|
||||||
|
.orElse(null);
|
||||||
|
}
|
||||||
|
|
||||||
public List<SBZProductDto> getProviderProducts(UUID providerId) {
|
public List<SBZProductDto> getProviderProducts(UUID providerId) {
|
||||||
String token = restService.getMerchantToken();
|
String token = restService.getMerchantToken();
|
||||||
|
|
||||||
@@ -57,13 +64,15 @@ public class ProviderService {
|
|||||||
return products;
|
return products;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Object getProviders(String category) {
|
public Object getProviderByClientId(String clientId) {
|
||||||
String token = restService.getMerchantToken();
|
Provider provider = providerRepository.findByClientId(clientId);
|
||||||
|
if (provider != null) {
|
||||||
|
return ((List)getProviders(Collections.singletonList(provider))).stream().findFirst().orElse(null);
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
HttpHeaders headers = new HttpHeaders();
|
public Object getProvidersByCategory(String category) {
|
||||||
headers.setContentType(MediaType.APPLICATION_JSON);
|
|
||||||
headers.setAccept(Collections.singletonList(MediaType.APPLICATION_JSON));
|
|
||||||
headers.setBearerAuth(token);
|
|
||||||
|
|
||||||
List<Provider> existingProviders;
|
List<Provider> existingProviders;
|
||||||
if (category != null && !category.isEmpty()) {
|
if (category != null && !category.isEmpty()) {
|
||||||
@@ -72,6 +81,17 @@ public class ProviderService {
|
|||||||
existingProviders = getProviderRepository().findAll();
|
existingProviders = getProviderRepository().findAll();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return getProviders(existingProviders);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Object getProviders(List<Provider> existingProviders) {
|
||||||
|
String token = restService.getMerchantToken();
|
||||||
|
|
||||||
|
HttpHeaders headers = new HttpHeaders();
|
||||||
|
headers.setContentType(MediaType.APPLICATION_JSON);
|
||||||
|
headers.setAccept(Collections.singletonList(MediaType.APPLICATION_JSON));
|
||||||
|
headers.setBearerAuth(token);
|
||||||
|
|
||||||
List<String> existingProviderIds = existingProviders.stream()
|
List<String> existingProviderIds = existingProviders.stream()
|
||||||
.map(Provider::getClientId)
|
.map(Provider::getClientId)
|
||||||
.collect(Collectors.toList());
|
.collect(Collectors.toList());
|
||||||
@@ -100,6 +120,7 @@ public class ProviderService {
|
|||||||
provider.put("image", existingProvider.getImage());
|
provider.put("image", existingProvider.getImage());
|
||||||
provider.put("label", existingProvider.getLabel());
|
provider.put("label", existingProvider.getLabel());
|
||||||
provider.put("category", existingProvider.getCategory());
|
provider.put("category", existingProvider.getCategory());
|
||||||
|
provider.put("accountFieldName", existingProvider.getAccountFieldName());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,51 @@
|
|||||||
|
package zw.qantra.tm.domain.services;
|
||||||
|
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
import org.springframework.data.jpa.domain.Specification;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
import zw.qantra.tm.domain.models.Recipient;
|
||||||
|
import zw.qantra.tm.domain.repositories.RecipientRepository;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Optional;
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
@Service
|
||||||
|
@RequiredArgsConstructor
|
||||||
|
public class RecipientService {
|
||||||
|
@Getter
|
||||||
|
private final RecipientRepository recipientRepository;
|
||||||
|
|
||||||
|
public List<Recipient> getAllRecipients() {
|
||||||
|
return recipientRepository.findAll();
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<Recipient> getRecipient(String account, String userId) {
|
||||||
|
return recipientRepository.findByAccountAndUserId(account, userId);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Recipient save(Recipient recipient) {
|
||||||
|
return recipientRepository.save(recipient);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Recipient updateRecipient(UUID id, Recipient recipient) {
|
||||||
|
if (recipientRepository.existsById(id)) {
|
||||||
|
recipient.setId(id);
|
||||||
|
return recipientRepository.save(recipient);
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean deleteRecipient(UUID id) {
|
||||||
|
if (recipientRepository.existsById(id)) {
|
||||||
|
recipientRepository.deleteById(id);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<Recipient> searchRecipients(Specification<Recipient> specification) {
|
||||||
|
return recipientRepository.findAll(specification);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -3,23 +3,34 @@ package zw.qantra.tm.domain.services;
|
|||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
import lombok.RequiredArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
import org.springframework.data.domain.Sort;
|
||||||
|
import org.springframework.data.jpa.domain.Specification;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
import zw.qantra.tm.domain.enums.RequestType;
|
import zw.qantra.tm.domain.enums.RequestType;
|
||||||
import zw.qantra.tm.domain.enums.Status;
|
import zw.qantra.tm.domain.enums.Status;
|
||||||
|
import zw.qantra.tm.domain.models.AdditionalData;
|
||||||
import zw.qantra.tm.domain.models.Provider;
|
import zw.qantra.tm.domain.models.Provider;
|
||||||
|
import zw.qantra.tm.domain.models.Recipient;
|
||||||
import zw.qantra.tm.domain.models.Transaction;
|
import zw.qantra.tm.domain.models.Transaction;
|
||||||
import zw.qantra.tm.domain.repositories.TransactionRepository;
|
import zw.qantra.tm.domain.repositories.TransactionRepository;
|
||||||
import zw.qantra.tm.domain.services.factories.PaymentProcessorFactory;
|
import zw.qantra.tm.domain.services.factories.PaymentProcessorFactory;
|
||||||
import zw.qantra.tm.domain.services.processors.TransactionProcessorInterface;
|
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.CalculateChargesHandler;
|
||||||
|
import zw.qantra.tm.domain.services.processors.handlers.ConfirmationLogicHandler;
|
||||||
|
import zw.qantra.tm.domain.services.processors.handlers.FormattingHandler;
|
||||||
import zw.qantra.tm.domain.services.processors.handlers.LogicPipeline;
|
import zw.qantra.tm.domain.services.processors.handlers.LogicPipeline;
|
||||||
|
import zw.qantra.tm.domain.services.processors.handlers.RecipientsUpdateHandler;
|
||||||
import zw.qantra.tm.domain.services.processors.handlers.ValidationHandler;
|
import zw.qantra.tm.domain.services.processors.handlers.ValidationHandler;
|
||||||
import zw.qantra.tm.exceptions.ApiException;
|
import zw.qantra.tm.exceptions.ApiException;
|
||||||
|
import zw.qantra.tm.utils.Utils;
|
||||||
|
|
||||||
@Service
|
@Service
|
||||||
@RequiredArgsConstructor
|
@RequiredArgsConstructor
|
||||||
@@ -29,42 +40,25 @@ public class TransactionService {
|
|||||||
@Getter
|
@Getter
|
||||||
private final TransactionRepository transactionRepository;
|
private final TransactionRepository transactionRepository;
|
||||||
private final PaymentProcessorFactory paymentProcessorFactory;
|
private final PaymentProcessorFactory paymentProcessorFactory;
|
||||||
private final CalculateChargesHandler calculateChargesHandler;
|
|
||||||
private final ProviderService providerService;
|
private final ProviderService providerService;
|
||||||
|
private final ChargeService chargeService;
|
||||||
|
private final AdditionalDataService additionalDataService;
|
||||||
|
private final RecipientService recipientService;
|
||||||
|
|
||||||
public Transaction poll(UUID uuid){
|
public Transaction integration(Transaction transaction) {
|
||||||
if(!transactionRepository.existsById(uuid)){
|
transaction.setType(RequestType.INTEGRATION);
|
||||||
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 =
|
LogicPipeline<Transaction, Transaction> transactionLogic =
|
||||||
new LogicPipeline<>(calculateChargesHandler)
|
new LogicPipeline<>(new ValidationHandler());
|
||||||
.addHandler(new ValidationHandler());
|
|
||||||
transaction = transactionLogic.execute(transaction);
|
transaction = transactionLogic.execute(transaction);
|
||||||
|
|
||||||
String label = getLabel(transaction);
|
Provider provider = providerService.getProviderRepository()
|
||||||
|
.findByClientId(transaction.getBillClientId());
|
||||||
|
if(provider == null){
|
||||||
|
throw new ApiException("Provider not found for billClientId: " + transaction.getBillClientId());
|
||||||
|
}
|
||||||
|
String label = transaction.getType() + "_" +
|
||||||
|
provider.getIntegrationProcessorLabel();
|
||||||
logger.info("label: {}", label);
|
logger.info("label: {}", label);
|
||||||
|
|
||||||
TransactionProcessorInterface transactionProcessorInterface =
|
TransactionProcessorInterface transactionProcessorInterface =
|
||||||
@@ -83,9 +77,80 @@ public class TransactionService {
|
|||||||
return transaction;
|
return transaction;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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 {
|
||||||
|
// find out if the gateway tran was successful
|
||||||
|
transactionProcessorInterface.poll(transaction);
|
||||||
|
|
||||||
|
// if tran was successful deep copy transaction & push integration to the aggregator
|
||||||
|
Transaction transactionCopy = Utils.deepCopy(transaction, Transaction.class);
|
||||||
|
transactionCopy.setType(RequestType.INTEGRATION);
|
||||||
|
transactionCopy.setId(null);
|
||||||
|
integration(transactionCopy);
|
||||||
|
|
||||||
|
} 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());
|
||||||
|
|
||||||
|
// run pre transaction logic
|
||||||
|
LogicPipeline<Transaction, Transaction> preTransactionLogic =
|
||||||
|
new LogicPipeline<>(new CalculateChargesHandler(chargeService))
|
||||||
|
.addHandler(new ConfirmationLogicHandler())
|
||||||
|
.addHandler(new FormattingHandler())
|
||||||
|
.addHandler(new ValidationHandler());
|
||||||
|
transaction = preTransactionLogic.execute(transaction);
|
||||||
|
|
||||||
|
String label = getLabel(transaction);
|
||||||
|
logger.info("label: {}", label);
|
||||||
|
|
||||||
|
TransactionProcessorInterface transactionProcessorInterface =
|
||||||
|
(TransactionProcessorInterface) paymentProcessorFactory.getPaymentProcessor(label);
|
||||||
|
|
||||||
|
try {
|
||||||
|
// MAIN TRANSACTION LOGIC!
|
||||||
|
transactionProcessorInterface.process(transaction);
|
||||||
|
|
||||||
|
}catch (Exception e){
|
||||||
|
e.printStackTrace();
|
||||||
|
transaction.setStatus(Status.FAILED);
|
||||||
|
transaction.setResponseCode("01");
|
||||||
|
transaction.setErrorMessage(e.getMessage());
|
||||||
|
transactionRepository.save(transaction);
|
||||||
|
return transaction;
|
||||||
|
}
|
||||||
|
|
||||||
|
// run post transaction logic
|
||||||
|
LogicPipeline<Transaction, Transaction> postTransactionLogic =
|
||||||
|
new LogicPipeline<>(new RecipientsUpdateHandler(recipientService));
|
||||||
|
transaction = postTransactionLogic.execute(transaction);
|
||||||
|
|
||||||
|
return transaction;
|
||||||
|
}
|
||||||
|
|
||||||
private String getLabel(Transaction transaction){
|
private String getLabel(Transaction transaction){
|
||||||
String label = "";
|
String label = "";
|
||||||
if(transaction.getType() == RequestType.CONFIRM){
|
List<RequestType> list = Arrays.asList(RequestType.CONFIRM);
|
||||||
|
if(list.contains(transaction.getType())){
|
||||||
// get processor label from billClientId
|
// get processor label from billClientId
|
||||||
Provider provider = providerService.getProviderRepository()
|
Provider provider = providerService.getProviderRepository()
|
||||||
.findByClientId(transaction.getBillClientId());
|
.findByClientId(transaction.getBillClientId());
|
||||||
@@ -102,6 +167,20 @@ public class TransactionService {
|
|||||||
return label;
|
return label;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Transaction findById(UUID id) {
|
||||||
|
Transaction transaction = transactionRepository.findById(id).orElseThrow(() -> new ApiException("Transaction not found for ID: " + id));
|
||||||
|
|
||||||
|
AdditionalData additionalData = additionalDataService.getAdditionalDataRepository()
|
||||||
|
.findByTransactionId(id).orElseThrow(() -> new ApiException("Additional data not found for transaction ID: " + id));
|
||||||
|
transaction.setAdditionalData(Utils.fromJson(additionalData.getJsonString(), List.class));
|
||||||
|
|
||||||
|
return transaction;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<Transaction> findAll(Specification<Transaction> spec) {
|
||||||
|
return transactionRepository.findAll(spec, Sort.by(Sort.Direction.ASC, "createdAt"));
|
||||||
|
}
|
||||||
|
|
||||||
public Transaction save(Transaction transaction){
|
public Transaction save(Transaction transaction){
|
||||||
return transactionRepository.save(transaction);
|
return transactionRepository.save(transaction);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,98 @@
|
|||||||
|
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.LinkedHashMap;
|
||||||
|
|
||||||
|
@Service("CONFIRM_ECONET")
|
||||||
|
@RequiredArgsConstructor
|
||||||
|
public class EconetConfirmationProcessor implements TransactionProcessorInterface {
|
||||||
|
Logger logger = LoggerFactory.getLogger(EconetConfirmationProcessor.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 {
|
||||||
|
logger.info("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(aggregatorClientId)
|
||||||
|
.debitPhone(aggregatorPhone) // qantra mobile number
|
||||||
|
.debitAccount(aggregatorAccount) // qantra corporate account
|
||||||
|
.creditAccount(transaction.getCreditAccount()) // customer's phone number
|
||||||
|
.creditPhone(transaction.getCreditPhone()) // customer's contact phone number
|
||||||
|
.billName(transaction.getBillName())
|
||||||
|
.build();
|
||||||
|
|
||||||
|
String url = aggregatorUrl + "/merchant/aggregation/transaction";
|
||||||
|
|
||||||
|
LinkedHashMap response = restService.postWithToken(token, url, request, LinkedHashMap.class);
|
||||||
|
|
||||||
|
logger.info("response: {}", response.toString());
|
||||||
|
|
||||||
|
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"));
|
||||||
|
transaction.setErrorMessage((String) body.get("errorMessage"));
|
||||||
|
}
|
||||||
|
|
||||||
|
return transactionService.save(transaction);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Object reverse(Transaction transaction) {
|
||||||
|
return transaction;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Object poll(Transaction transaction) {
|
||||||
|
return transaction;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -80,6 +80,7 @@ public class ZesaConfirmationProcessor implements TransactionProcessorInterface
|
|||||||
transaction.setStatus(Status.FAILED);
|
transaction.setStatus(Status.FAILED);
|
||||||
transaction.setErrorMessage((String) body.get("message"));
|
transaction.setErrorMessage((String) body.get("message"));
|
||||||
transaction.setResponseCode((String) body.get("responseCode"));
|
transaction.setResponseCode((String) body.get("responseCode"));
|
||||||
|
transaction.setErrorMessage((String) body.get("errorMessage"));
|
||||||
}
|
}
|
||||||
|
|
||||||
return transactionService.save(transaction);
|
return transactionService.save(transaction);
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
package zw.qantra.tm.domain.services.processors.handlers;
|
package zw.qantra.tm.domain.services.processors.handlers;
|
||||||
|
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
@@ -17,11 +18,11 @@ import java.util.List;
|
|||||||
|
|
||||||
|
|
||||||
@Service
|
@Service
|
||||||
|
@RequiredArgsConstructor
|
||||||
public class CalculateChargesHandler implements LogicHandler<Transaction, Transaction> {
|
public class CalculateChargesHandler implements LogicHandler<Transaction, Transaction> {
|
||||||
Logger logger = LoggerFactory.getLogger(CalculateChargesHandler.class);
|
Logger logger = LoggerFactory.getLogger(CalculateChargesHandler.class);
|
||||||
|
|
||||||
@Autowired
|
private final ChargeService chargeService;
|
||||||
private ChargeService chargeService;
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Transaction process(Transaction transaction) {
|
public Transaction process(Transaction transaction) {
|
||||||
@@ -126,14 +127,17 @@ public class CalculateChargesHandler implements LogicHandler<Transaction, Transa
|
|||||||
|
|
||||||
// calculate total amount for ease of use later
|
// calculate total amount for ease of use later
|
||||||
transaction.setTotalAmount(
|
transaction.setTotalAmount(
|
||||||
|
transaction.getAmount().add(
|
||||||
transaction.getCharge().add(
|
transaction.getCharge().add(
|
||||||
transaction.getTax().add(
|
transaction.getTax().add(
|
||||||
transaction.getGatewayCharge())));
|
transaction.getGatewayCharge()))));
|
||||||
|
|
||||||
return transaction;
|
return transaction;
|
||||||
}
|
}
|
||||||
|
|
||||||
void applyCharge(Transaction transaction, Charge charge, BigDecimal chargeAmount) {
|
void applyCharge(Transaction transaction, Charge charge, BigDecimal chargeAmount) {
|
||||||
|
if(chargeAmount == null) return;
|
||||||
|
|
||||||
switch (charge.getChargeLabel()) {
|
switch (charge.getChargeLabel()) {
|
||||||
case FEE -> transaction.setCharge(chargeAmount);
|
case FEE -> transaction.setCharge(chargeAmount);
|
||||||
case TAX -> transaction.setTax(chargeAmount);
|
case TAX -> transaction.setTax(chargeAmount);
|
||||||
|
|||||||
@@ -0,0 +1,15 @@
|
|||||||
|
package zw.qantra.tm.domain.services.processors.handlers;
|
||||||
|
|
||||||
|
import zw.qantra.tm.domain.enums.RequestType;
|
||||||
|
import zw.qantra.tm.domain.models.Transaction;
|
||||||
|
import zw.qantra.tm.utils.Utils;
|
||||||
|
|
||||||
|
public class ConfirmationLogicHandler implements LogicHandler<Transaction, Transaction> {
|
||||||
|
@Override
|
||||||
|
public Transaction process(Transaction transaction) {
|
||||||
|
if(transaction.getType().equals(RequestType.CONFIRM)) {
|
||||||
|
transaction.setTrace(Utils.getUid());
|
||||||
|
}
|
||||||
|
return transaction;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,59 @@
|
|||||||
|
package zw.qantra.tm.domain.services.processors.handlers;
|
||||||
|
|
||||||
|
import com.google.i18n.phonenumbers.NumberParseException;
|
||||||
|
import com.google.i18n.phonenumbers.PhoneNumberUtil;
|
||||||
|
import com.google.i18n.phonenumbers.Phonenumber.PhoneNumber;
|
||||||
|
|
||||||
|
import zw.qantra.tm.domain.models.Transaction;
|
||||||
|
|
||||||
|
public class FormattingHandler implements LogicHandler<Transaction, Transaction> {
|
||||||
|
@Override
|
||||||
|
public Transaction process(Transaction transaction) {
|
||||||
|
System.out.println("processing formatting");
|
||||||
|
|
||||||
|
// strip credit account and make sure there's nothing funny
|
||||||
|
String creditAccount = transaction.getCreditAccount();
|
||||||
|
if (creditAccount != null && !creditAccount.isEmpty()) {
|
||||||
|
// Remove all non-hexadecimal characters (keep only 0-9, a-f, A-F)
|
||||||
|
String strippedAccount = creditAccount.replaceAll("[^0-9a-fA-F]", "");
|
||||||
|
|
||||||
|
// Only set if the stripped result is not empty
|
||||||
|
if (!strippedAccount.isEmpty()) {
|
||||||
|
transaction.setCreditAccount(strippedAccount);
|
||||||
|
} else {
|
||||||
|
// If stripping results in empty string, set to null
|
||||||
|
transaction.setCreditAccount(null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// sanitize phone number formatting
|
||||||
|
String debitPhoneNumber = transaction.getDebitPhone();
|
||||||
|
String creditPhoneNumber = transaction.getCreditPhone();
|
||||||
|
|
||||||
|
PhoneNumberUtil phoneUtil = PhoneNumberUtil.getInstance();
|
||||||
|
|
||||||
|
if(debitPhoneNumber != null && !debitPhoneNumber.isEmpty()){
|
||||||
|
try {
|
||||||
|
// phone must begin with '+'
|
||||||
|
PhoneNumber zimPhoneNumber = phoneUtil.parse(debitPhoneNumber, "");
|
||||||
|
String formattedPhoneNumber = phoneUtil.format(zimPhoneNumber, PhoneNumberUtil.PhoneNumberFormat.E164);
|
||||||
|
transaction.setDebitPhone(formattedPhoneNumber);
|
||||||
|
} catch (NumberParseException e) {
|
||||||
|
System.err.println("NumberParseException was thrown: " + e.toString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(creditPhoneNumber != null && !creditPhoneNumber.isEmpty()){
|
||||||
|
try {
|
||||||
|
PhoneNumber zimPhoneNumber = phoneUtil.parse(creditPhoneNumber, "");
|
||||||
|
String formattedPhoneNumber = phoneUtil.format(zimPhoneNumber, PhoneNumberUtil.PhoneNumberFormat.E164);
|
||||||
|
transaction.setCreditPhone(formattedPhoneNumber);
|
||||||
|
} catch (NumberParseException e) {
|
||||||
|
System.err.println("NumberParseException was thrown: " + e.toString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return transaction;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,55 @@
|
|||||||
|
package zw.qantra.tm.domain.services.processors.handlers;
|
||||||
|
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
import zw.qantra.tm.domain.models.Transaction;
|
||||||
|
import zw.qantra.tm.domain.enums.Status;
|
||||||
|
import zw.qantra.tm.domain.models.Recipient;
|
||||||
|
import zw.qantra.tm.domain.services.RecipientService;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
@Service
|
||||||
|
@RequiredArgsConstructor
|
||||||
|
public class RecipientsUpdateHandler implements LogicHandler<Transaction, Transaction> {
|
||||||
|
|
||||||
|
private final RecipientService recipientService;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Transaction process(Transaction transaction) {
|
||||||
|
System.out.println("processing recipients");
|
||||||
|
|
||||||
|
if(transaction.getStatus() == Status.SUCCESS){
|
||||||
|
List<Recipient> recipients = recipientService.getRecipient(transaction.getCreditAccount(), transaction.getUserId());
|
||||||
|
|
||||||
|
Recipient recipient = null;
|
||||||
|
if(recipients.size() > 0){
|
||||||
|
recipient = recipients.get(0);
|
||||||
|
}else{
|
||||||
|
recipient = new Recipient();
|
||||||
|
recipient.setAccount(transaction.getCreditAccount());
|
||||||
|
recipient.setUserId(transaction.getUserId());
|
||||||
|
}
|
||||||
|
|
||||||
|
recipient.setLatestProviderLabel(transaction.getProviderLabel());
|
||||||
|
if(transaction.getCreditName() != null && !transaction.getCreditName().isEmpty()){
|
||||||
|
recipient.setName(transaction.getCreditName());
|
||||||
|
}
|
||||||
|
if(transaction.getCreditEmail() != null && !transaction.getCreditEmail().isEmpty()){
|
||||||
|
recipient.setEmail(transaction.getCreditEmail());
|
||||||
|
}
|
||||||
|
if(transaction.getCreditPhone() != null && !transaction.getCreditPhone().isEmpty()){
|
||||||
|
recipient.setPhoneNumber(transaction.getCreditPhone());
|
||||||
|
}
|
||||||
|
|
||||||
|
String stringToInitial = transaction.getCreditName() != null && !transaction.getCreditName().isEmpty()
|
||||||
|
? transaction.getCreditName() : transaction.getBillName();
|
||||||
|
|
||||||
|
recipient.setInitials(stringToInitial.substring(0, 2).toUpperCase());
|
||||||
|
recipientService.save(recipient);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return transaction;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,112 @@
|
|||||||
|
package zw.qantra.tm.domain.services.processors.integrations;
|
||||||
|
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
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.LinkedHashMap;
|
||||||
|
|
||||||
|
@Service("INTEGRATION_STEWARD")
|
||||||
|
@RequiredArgsConstructor
|
||||||
|
public class StewardIntegrationProcessor implements TransactionProcessorInterface {
|
||||||
|
Logger logger = LoggerFactory.getLogger(TransactionService.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 {
|
||||||
|
logger.info("processing integration");
|
||||||
|
String token = restService.getMerchantToken();
|
||||||
|
|
||||||
|
BillPaymentDto request = BillPaymentDto.builder()
|
||||||
|
.type(RequestType.REQUEST)
|
||||||
|
.billClientId(transaction.getBillClientId())
|
||||||
|
.debitRef(transaction.getDebitRef())
|
||||||
|
.debitCurrency(transaction.getDebitCurrency())
|
||||||
|
.amount(transaction.getAmount())
|
||||||
|
.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())
|
||||||
|
.authType(transaction.getAuthType())
|
||||||
|
.trace(transaction.getTrace())
|
||||||
|
.build();
|
||||||
|
|
||||||
|
String url = aggregatorUrl + "/merchant/aggregation/transaction";
|
||||||
|
|
||||||
|
LinkedHashMap response = restService.postWithToken(token, url, request, LinkedHashMap.class);
|
||||||
|
|
||||||
|
logger.info("response: {}", response.toString());
|
||||||
|
|
||||||
|
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);
|
||||||
|
|
||||||
|
// fetch the corresponding request transaction if it exists
|
||||||
|
Transaction requestTransaction = transactionService.getTransactionRepository()
|
||||||
|
.findByTraceAndType(transaction.getTrace(), RequestType.REQUEST);
|
||||||
|
if (requestTransaction != null) {
|
||||||
|
// create a new additional data for the request transaction
|
||||||
|
AdditionalData requestAdditionalData = AdditionalData.builder()
|
||||||
|
.transaction(requestTransaction)
|
||||||
|
.jsonString(Utils.toJson(body.get("additionalData")))
|
||||||
|
.build();
|
||||||
|
additionalDataService.getAdditionalDataRepository().save(requestAdditionalData);
|
||||||
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
transaction.setStatus(Status.FAILED);
|
||||||
|
transaction.setErrorMessage((String) body.get("message"));
|
||||||
|
transaction.setResponseCode((String) body.get("responseCode"));
|
||||||
|
transaction.setErrorMessage((String) body.get("errorMessage"));
|
||||||
|
}
|
||||||
|
|
||||||
|
return transactionService.save(transaction);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Object reverse(Transaction transaction) {
|
||||||
|
return transaction;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Object poll(Transaction transaction) {
|
||||||
|
return transaction;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -1,34 +0,0 @@
|
|||||||
package zw.qantra.tm.domain.services.processors.integrations;
|
|
||||||
|
|
||||||
import lombok.RequiredArgsConstructor;
|
|
||||||
import org.springframework.beans.factory.annotation.Value;
|
|
||||||
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("REQUEST_ZESA")
|
|
||||||
@RequiredArgsConstructor
|
|
||||||
public class ZesaIntegrationProcessor implements TransactionProcessorInterface {
|
|
||||||
private final RestService restService;
|
|
||||||
|
|
||||||
@Value("${sbz.aggregator.url}")
|
|
||||||
private String aggregatorUrl;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Object process(Transaction transaction) throws Exception {
|
|
||||||
|
|
||||||
return transaction;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Object reverse(Transaction transaction) {
|
|
||||||
return transaction;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Object poll(Transaction transaction) {
|
|
||||||
return transaction;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -14,6 +14,8 @@ import zw.qantra.tm.domain.services.processors.TransactionProcessorInterface;
|
|||||||
import zw.qantra.tm.rest.RestService;
|
import zw.qantra.tm.rest.RestService;
|
||||||
import zw.qantra.tm.utils.Utils;
|
import zw.qantra.tm.utils.Utils;
|
||||||
|
|
||||||
|
import java.math.BigDecimal;
|
||||||
|
import java.math.BigInteger;
|
||||||
import java.nio.charset.StandardCharsets;
|
import java.nio.charset.StandardCharsets;
|
||||||
import java.security.MessageDigest;
|
import java.security.MessageDigest;
|
||||||
import java.security.NoSuchAlgorithmException;
|
import java.security.NoSuchAlgorithmException;
|
||||||
@@ -40,10 +42,13 @@ public class MPGSWebPaymentProcessor implements TransactionProcessorInterface {
|
|||||||
logger.info("processing transaction");
|
logger.info("processing transaction");
|
||||||
String token = restService.getMerchantToken();
|
String token = restService.getMerchantToken();
|
||||||
|
|
||||||
|
// send total less gateway charges
|
||||||
|
BigDecimal totalAmount = transaction.getAmount().add(transaction.getTax()).add(transaction.getCharge());
|
||||||
|
|
||||||
String concat = clientId+
|
String concat = clientId+
|
||||||
encryptionKey+
|
encryptionKey+
|
||||||
transaction.getCreditPhone()+
|
transaction.getCreditPhone()+
|
||||||
transaction.getAmount();
|
totalAmount;
|
||||||
|
|
||||||
String hex = getHash(concat);
|
String hex = getHash(concat);
|
||||||
|
|
||||||
@@ -51,7 +56,7 @@ public class MPGSWebPaymentProcessor implements TransactionProcessorInterface {
|
|||||||
.clientId(clientId)
|
.clientId(clientId)
|
||||||
.clientSecret(clientSecret)
|
.clientSecret(clientSecret)
|
||||||
.phone(transaction.getCreditPhone())
|
.phone(transaction.getCreditPhone())
|
||||||
.amount(transaction.getAmount().toString())
|
.amount(totalAmount.toString())
|
||||||
.currency(transaction.getDebitCurrency().toString())
|
.currency(transaction.getDebitCurrency().toString())
|
||||||
.hash(hex)
|
.hash(hex)
|
||||||
.authType("WEB")
|
.authType("WEB")
|
||||||
@@ -59,7 +64,7 @@ public class MPGSWebPaymentProcessor implements TransactionProcessorInterface {
|
|||||||
.action("PAYMENT")
|
.action("PAYMENT")
|
||||||
.sandbox(true)
|
.sandbox(true)
|
||||||
.paymentProcessorLabel("MPGS")
|
.paymentProcessorLabel("MPGS")
|
||||||
.responseUrl("https://www.google.com")
|
.responseUrl("https://stewardbank.co.zw")
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
HttpHeaders headers = new HttpHeaders();
|
HttpHeaders headers = new HttpHeaders();
|
||||||
|
|||||||
@@ -12,6 +12,11 @@ import java.security.NoSuchAlgorithmException;
|
|||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
|
||||||
public class Utils {
|
public class Utils {
|
||||||
|
public static <T> T deepCopy(Object object, Class<T> clazz) {
|
||||||
|
String json = toJson(object);
|
||||||
|
return fromJson(json, clazz);
|
||||||
|
}
|
||||||
|
|
||||||
public static String hashPassword(String password) {
|
public static String hashPassword(String password) {
|
||||||
try {
|
try {
|
||||||
// Create a MessageDigest instance for SHA-256
|
// Create a MessageDigest instance for SHA-256
|
||||||
|
|||||||
@@ -14,11 +14,15 @@ spring.datasource.url=jdbc:postgresql://localhost:5432/qpay?useLegacyDatetimeCod
|
|||||||
spring.datasource.username=postgres
|
spring.datasource.username=postgres
|
||||||
spring.datasource.password=password
|
spring.datasource.password=password
|
||||||
|
|
||||||
sbz.aggregator.url=http://192.168.16.29:24050/v1
|
|
||||||
|
sbz.merchant.url=http://192.168.16.29:24050/v1
|
||||||
|
# sbz.merchant.url=https://localhost:24000/v1
|
||||||
|
# sbz.merchant.url=https://api.stewardpay.co.zw/lab/v2
|
||||||
|
sbz.aggregator.url=${sbz.merchant.url}
|
||||||
sbz.aggregator.client-id=steward_pay
|
sbz.aggregator.client-id=steward_pay
|
||||||
sbz.aggregator.client-secret=XjkbBAJeJCnAplYDTbp5xOjeyySVnYGp
|
sbz.aggregator.client-secret=XjkbBAJeJCnAplYDTbp5xOjeyySVnYGp
|
||||||
sbz.aggregator.phone=263773591219
|
sbz.aggregator.phone=263773591219
|
||||||
sbz.aggregator.account=1046737845
|
sbz.aggregator.account=1046737845
|
||||||
sbz.aggregator.encryption-key=735470ce-8efb-4c0f-ba3f-7298f805ab33
|
sbz.aggregator.encryption-key=735470ce-8efb-4c0f-ba3f-7298f805ab33
|
||||||
|
|
||||||
steward.payment.processor.url=http://192.168.16.29:24050/v1
|
steward.payment.processor.url=${sbz.merchant.url}
|
||||||
|
|||||||
Reference in New Issue
Block a user