Updates and payments additions
This commit is contained in:
100
src/main/java/com/test/payment/models/DatabaseSchema.java
Normal file
100
src/main/java/com/test/payment/models/DatabaseSchema.java
Normal file
@@ -0,0 +1,100 @@
|
||||
package com.test.payment.models;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* The database schema as code — executed statement-by-statement at startup by
|
||||
* DatabaseSchemaInitializer (replaces the old classpath schema.sql).
|
||||
*/
|
||||
public final class DatabaseSchema {
|
||||
|
||||
private DatabaseSchema() {
|
||||
}
|
||||
|
||||
public static final List<String> STATEMENTS = List.of(
|
||||
"""
|
||||
CREATE TABLE IF NOT EXISTS provider_tokens (
|
||||
id BIGINT AUTO_INCREMENT PRIMARY KEY,
|
||||
provider VARCHAR(20) NOT NULL,
|
||||
access_token VARCHAR(512) NOT NULL,
|
||||
expires_at TIMESTAMP NOT NULL,
|
||||
created_at TIMESTAMP NOT NULL
|
||||
)
|
||||
""",
|
||||
"""
|
||||
CREATE TABLE IF NOT EXISTS payment_initiations (
|
||||
id BIGINT AUTO_INCREMENT PRIMARY KEY,
|
||||
provider VARCHAR(20) NOT NULL,
|
||||
phone_number VARCHAR(15) NOT NULL,
|
||||
amount DECIMAL(10,2) NOT NULL,
|
||||
account_reference VARCHAR(50),
|
||||
transaction_desc VARCHAR(100),
|
||||
status VARCHAR(20) NOT NULL,
|
||||
created_at TIMESTAMP NOT NULL,
|
||||
updated_at TIMESTAMP
|
||||
)
|
||||
""",
|
||||
"""
|
||||
CREATE INDEX IF NOT EXISTS idx_initiations_status_created
|
||||
ON payment_initiations (status, created_at)
|
||||
""",
|
||||
// One response per initiation (UNIQUE on initiation_id enforces the 1:1 link).
|
||||
// provider_reference is the ID used for callbacks/status checks
|
||||
// (M-Pesa CheckoutRequestID, Airtel transaction id, MTN X-Reference-Id).
|
||||
"""
|
||||
CREATE TABLE IF NOT EXISTS payment_responses (
|
||||
id BIGINT AUTO_INCREMENT PRIMARY KEY,
|
||||
initiation_id BIGINT NOT NULL UNIQUE,
|
||||
provider VARCHAR(20) NOT NULL,
|
||||
provider_reference VARCHAR(100) UNIQUE,
|
||||
secondary_reference VARCHAR(100),
|
||||
response_code VARCHAR(30),
|
||||
response_description VARCHAR(255),
|
||||
customer_message VARCHAR(255),
|
||||
created_at TIMESTAMP NOT NULL,
|
||||
CONSTRAINT fk_response_initiation FOREIGN KEY (initiation_id) REFERENCES payment_initiations (id)
|
||||
)
|
||||
""",
|
||||
// One callback per initiation (UNIQUE on initiation_id enforces the 1:1 link)
|
||||
"""
|
||||
CREATE TABLE IF NOT EXISTS payment_callbacks (
|
||||
id BIGINT AUTO_INCREMENT PRIMARY KEY,
|
||||
initiation_id BIGINT NOT NULL UNIQUE,
|
||||
provider VARCHAR(20) NOT NULL,
|
||||
provider_reference VARCHAR(100),
|
||||
result_code VARCHAR(30),
|
||||
result_desc VARCHAR(255),
|
||||
receipt_number VARCHAR(50),
|
||||
amount DECIMAL(10,2),
|
||||
phone_number VARCHAR(15),
|
||||
transaction_date VARCHAR(20),
|
||||
raw_payload CLOB,
|
||||
created_at TIMESTAMP NOT NULL,
|
||||
CONSTRAINT fk_callback_initiation FOREIGN KEY (initiation_id) REFERENCES payment_initiations (id)
|
||||
)
|
||||
""",
|
||||
// Consolidated transaction record, written when an initiation reaches a
|
||||
// terminal state (SUCCESS/FAILED). UNIQUE initiation_id: one per initiation.
|
||||
"""
|
||||
CREATE TABLE IF NOT EXISTS transactions (
|
||||
id BIGINT AUTO_INCREMENT PRIMARY KEY,
|
||||
initiation_id BIGINT NOT NULL UNIQUE,
|
||||
provider VARCHAR(20) NOT NULL,
|
||||
provider_reference VARCHAR(100),
|
||||
secondary_reference VARCHAR(100),
|
||||
phone_number VARCHAR(15),
|
||||
amount DECIMAL(10,2),
|
||||
account_reference VARCHAR(50),
|
||||
status VARCHAR(20) NOT NULL,
|
||||
result_code VARCHAR(30),
|
||||
result_desc VARCHAR(255),
|
||||
receipt_number VARCHAR(50),
|
||||
transaction_date VARCHAR(20),
|
||||
resolved_by VARCHAR(20),
|
||||
created_at TIMESTAMP NOT NULL,
|
||||
updated_at TIMESTAMP,
|
||||
CONSTRAINT fk_transaction_initiation FOREIGN KEY (initiation_id) REFERENCES payment_initiations (id)
|
||||
)
|
||||
"""
|
||||
);
|
||||
}
|
||||
@@ -1,25 +0,0 @@
|
||||
package com.test.payment.models;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
@Data
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
public class MpesaResponse {
|
||||
|
||||
@JsonProperty("MerchantRequestID")
|
||||
private String merchantRequestID;
|
||||
|
||||
@JsonProperty("ResponseCode")
|
||||
private String responseCode;
|
||||
@JsonProperty("CheckoutRequestID")
|
||||
private String checkoutRequestId;
|
||||
@JsonProperty("CustomerMessage")
|
||||
private String customerMessage;
|
||||
@JsonProperty("ResponseDescription")
|
||||
private String responseDescription;
|
||||
|
||||
}
|
||||
33
src/main/java/com/test/payment/models/PaymentCallback.java
Normal file
33
src/main/java/com/test/payment/models/PaymentCallback.java
Normal file
@@ -0,0 +1,33 @@
|
||||
package com.test.payment.models;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
import org.springframework.data.annotation.Id;
|
||||
import org.springframework.data.relational.core.mapping.Table;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
@Data
|
||||
@Builder
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
@Table("PAYMENT_CALLBACKS")
|
||||
public class PaymentCallback {
|
||||
|
||||
@Id
|
||||
private Long id;
|
||||
private Long initiationId;
|
||||
private String provider;
|
||||
private String providerReference;
|
||||
private String resultCode;
|
||||
private String resultDesc;
|
||||
private String receiptNumber;
|
||||
private BigDecimal amount;
|
||||
private String phoneNumber;
|
||||
private String transactionDate;
|
||||
private String rawPayload;
|
||||
private LocalDateTime createdAt;
|
||||
}
|
||||
30
src/main/java/com/test/payment/models/PaymentInitiation.java
Normal file
30
src/main/java/com/test/payment/models/PaymentInitiation.java
Normal file
@@ -0,0 +1,30 @@
|
||||
package com.test.payment.models;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
import org.springframework.data.annotation.Id;
|
||||
import org.springframework.data.relational.core.mapping.Table;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
@Data
|
||||
@Builder
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
@Table("PAYMENT_INITIATIONS")
|
||||
public class PaymentInitiation {
|
||||
|
||||
@Id
|
||||
private Long id;
|
||||
private String provider;
|
||||
private String phoneNumber;
|
||||
private BigDecimal amount;
|
||||
private String accountReference;
|
||||
private String transactionDesc;
|
||||
private String status;
|
||||
private LocalDateTime createdAt;
|
||||
private LocalDateTime updatedAt;
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
package com.test.payment.models;
|
||||
|
||||
public enum PaymentProviderType {
|
||||
MPESA,
|
||||
AIRTEL,
|
||||
MTN
|
||||
}
|
||||
@@ -1,12 +0,0 @@
|
||||
package com.test.payment.models;
|
||||
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
@Data
|
||||
public class PaymentRequest {
|
||||
private long phoneNumber;
|
||||
private int amount;
|
||||
private String accountReference;
|
||||
private String transactionDesc;
|
||||
}
|
||||
35
src/main/java/com/test/payment/models/PaymentResponse.java
Normal file
35
src/main/java/com/test/payment/models/PaymentResponse.java
Normal file
@@ -0,0 +1,35 @@
|
||||
package com.test.payment.models;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
import org.springframework.data.annotation.Id;
|
||||
import org.springframework.data.relational.core.mapping.Table;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
/**
|
||||
* The provider's answer to an initiation. providerReference is the ID later used
|
||||
* for callbacks and status checks (M-Pesa CheckoutRequestID, Airtel transaction id,
|
||||
* MTN X-Reference-Id); secondaryReference is any additional provider ID
|
||||
* (M-Pesa MerchantRequestID).
|
||||
*/
|
||||
@Data
|
||||
@Builder
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
@Table("PAYMENT_RESPONSES")
|
||||
public class PaymentResponse {
|
||||
|
||||
@Id
|
||||
private Long id;
|
||||
private Long initiationId;
|
||||
private String provider;
|
||||
private String providerReference;
|
||||
private String secondaryReference;
|
||||
private String responseCode;
|
||||
private String responseDescription;
|
||||
private String customerMessage;
|
||||
private LocalDateTime createdAt;
|
||||
}
|
||||
25
src/main/java/com/test/payment/models/ProviderToken.java
Normal file
25
src/main/java/com/test/payment/models/ProviderToken.java
Normal file
@@ -0,0 +1,25 @@
|
||||
package com.test.payment.models;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
import org.springframework.data.annotation.Id;
|
||||
import org.springframework.data.relational.core.mapping.Table;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
@Data
|
||||
@Builder
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
@Table("PROVIDER_TOKENS")
|
||||
public class ProviderToken {
|
||||
|
||||
@Id
|
||||
private Long id;
|
||||
private String provider;
|
||||
private String accessToken;
|
||||
private LocalDateTime expiresAt;
|
||||
private LocalDateTime createdAt;
|
||||
}
|
||||
@@ -1,23 +1,42 @@
|
||||
package com.test.payment.models;
|
||||
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
import org.springframework.data.annotation.Id;
|
||||
import org.springframework.data.relational.core.mapping.*;
|
||||
import org.springframework.data.relational.core.mapping.Table;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
/**
|
||||
* Consolidated record written when a payment attempt reaches a terminal state
|
||||
* (SUCCESS or FAILED) — one row per initiation, whatever path resolved it
|
||||
* (callback, status query, immediate rejection, or reconciliation timeout).
|
||||
*/
|
||||
@Data
|
||||
@Builder
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
@Table("transactions")
|
||||
@Table("TRANSACTIONS")
|
||||
public class Transaction {
|
||||
|
||||
@Id
|
||||
private String id;
|
||||
private long phoneNumber;
|
||||
private long amount;
|
||||
private Long id;
|
||||
private Long initiationId;
|
||||
private String provider;
|
||||
private String providerReference;
|
||||
private String secondaryReference;
|
||||
private String phoneNumber;
|
||||
private BigDecimal amount;
|
||||
private String accountReference;
|
||||
private String status;
|
||||
private String checkoutRequestId;
|
||||
private String resultCode;
|
||||
private String resultDesc;
|
||||
private String receiptNumber;
|
||||
private String transactionDate;
|
||||
private String resolvedBy;
|
||||
private LocalDateTime createdAt;
|
||||
private LocalDateTime updatedAt;
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
package com.test.payment.models;
|
||||
|
||||
public enum TransactionStatus {
|
||||
PENDING,
|
||||
SUCCESS,
|
||||
FAILED
|
||||
}
|
||||
Reference in New Issue
Block a user