trying to fix qr
All checks were successful
build-and-deploy / build-deploy (push) Successful in 35s

This commit is contained in:
androidlover5842
2026-01-30 12:56:42 +05:30
parent 669ebf96e3
commit b4c119e8ad
5 changed files with 71 additions and 8 deletions

View File

@@ -31,10 +31,30 @@ class PayuQrRequestSchemaFix(
status varchar not null,
request_payload text,
response_payload text,
expiry_at timestamptz,
created_at timestamptz not null
)
""".trimIndent()
)
} else {
val hasExpiryAt = jdbcTemplate.queryForObject(
"""
select count(*)
from information_schema.columns
where table_name = 'payu_qr_request'
and column_name = 'expiry_at'
""".trimIndent(),
Int::class.java
) ?: 0
if (hasExpiryAt == 0) {
logger.info("Adding expiry_at to payu_qr_request table")
jdbcTemplate.execute(
"""
alter table payu_qr_request
add column expiry_at timestamptz
""".trimIndent()
)
}
}
}
}

View File

@@ -4,6 +4,7 @@ import com.android.trisolarisserver.component.PropertyAccess
import com.android.trisolarisserver.controller.dto.PaymentCreateRequest
import com.android.trisolarisserver.controller.dto.PaymentResponse
import com.android.trisolarisserver.db.repo.BookingRepo
import com.android.trisolarisserver.models.booking.BookingStatus
import com.android.trisolarisserver.models.booking.Payment
import com.android.trisolarisserver.models.booking.PaymentMethod
import com.android.trisolarisserver.models.property.Role
@@ -105,6 +106,12 @@ class Payments(
if (booking.property.id != propertyId) {
throw ResponseStatusException(HttpStatus.NOT_FOUND, "Booking not found for property")
}
if (booking.status != BookingStatus.OPEN && booking.status != BookingStatus.CHECKED_IN) {
throw ResponseStatusException(
HttpStatus.BAD_REQUEST,
"Cash payments can only be deleted for OPEN or CHECKED_IN bookings"
)
}
val payment = paymentRepo.findById(paymentId).orElseThrow {
ResponseStatusException(HttpStatus.NOT_FOUND, "Payment not found")
}

View File

@@ -41,6 +41,7 @@ class PayuQrPayments(
private val payuQrRequestRepo: PayuQrRequestRepo,
private val restTemplate: RestTemplate
) {
private val defaultExpirySeconds = 30 * 60
@PostMapping("/qr")
@Transactional
@@ -79,6 +80,31 @@ class PayuQrPayments(
throw ResponseStatusException(HttpStatus.CONFLICT, "Amount exceeds pending")
}
val amountLong = requestedAmount ?: pending
val expirySeconds = request.expirySeconds
?: request.expiryMinutes?.let { it * 60 }
?: defaultExpirySeconds
val existing = payuQrRequestRepo.findTopByBookingIdAndAmountAndCurrencyAndStatusOrderByCreatedAtDesc(
bookingId,
amountLong,
booking.property.currency,
PayuQrStatus.SENT
)
if (existing != null) {
val expiryAt = existing.expiryAt
val responsePayload = existing.responsePayload
if (expiryAt != null && !responsePayload.isNullOrBlank()) {
val now = OffsetDateTime.now()
if (now.isBefore(expiryAt)) {
return PayuQrGenerateResponse(
txnid = existing.txnid,
amount = amountLong,
currency = booking.property.currency,
payuResponse = responsePayload
)
}
}
}
val txnid = "QR${bookingId.toString().substring(0, 8)}${System.currentTimeMillis()}"
val productInfo = "Booking $bookingId"
@@ -132,9 +158,9 @@ class PayuQrPayments(
add("hash", hash)
add("udf1", udf1)
add("udf2", udf2)
if (udf3.isNotBlank()) add("udf3", udf3)
if (udf4.isNotBlank()) add("udf4", udf4)
if (udf5.isNotBlank()) add("udf5", udf5)
add("udf3", udf3) // always
add("udf4", udf4) // always
add("udf5", udf5) // always
add("txn_s2s_flow", "4")
val clientIp = request.clientIp?.trim()?.ifBlank { null }
?: extractClientIp(httpRequest)
@@ -143,9 +169,7 @@ class PayuQrPayments(
?: throw ResponseStatusException(HttpStatus.BAD_REQUEST, "deviceInfo required")
add("s2s_client_ip", clientIp)
add("s2s_device_info", deviceInfo)
val expirySeconds = request.expirySeconds
?: request.expiryMinutes?.let { it * 60 }
expirySeconds?.let { add("expiry_time", it.toString()) }
add("expiry_time", expirySeconds.toString())
request.address1?.trim()?.ifBlank { null }?.let { add("address1", it) }
request.address2?.trim()?.ifBlank { null }?.let { add("address2", it) }
request.city?.trim()?.ifBlank { null }?.let { add("city", it) }
@@ -158,6 +182,8 @@ class PayuQrPayments(
entry.value.joinToString("&") { value -> "${entry.key}=$value" }
}
val createdAt = OffsetDateTime.now()
val expiryAt = createdAt.plusSeconds(expirySeconds.toLong())
val record = payuQrRequestRepo.save(
PayuQrRequest(
property = booking.property,
@@ -167,7 +193,8 @@ class PayuQrPayments(
currency = booking.property.currency,
status = PayuQrStatus.CREATED,
requestPayload = requestPayload,
createdAt = OffsetDateTime.now()
expiryAt = expiryAt,
createdAt = createdAt
)
)
@@ -214,7 +241,7 @@ class PayuQrPayments(
}
private fun sha512(input: String): String {
val bytes = MessageDigest.getInstance("SHA-512").digest(input.toByteArray())
val bytes = MessageDigest.getInstance("SHA-512").digest(input.toByteArray(Charsets.UTF_8))
return bytes.joinToString("") { "%02x".format(it) }
}

View File

@@ -50,6 +50,9 @@ class PayuQrRequest(
@Column(name = "response_payload", columnDefinition = "text")
var responsePayload: String? = null,
@Column(name = "expiry_at", columnDefinition = "timestamptz")
var expiryAt: OffsetDateTime? = null,
@Column(name = "created_at", nullable = false, columnDefinition = "timestamptz")
val createdAt: OffsetDateTime = OffsetDateTime.now()
)

View File

@@ -6,4 +6,10 @@ import java.util.UUID
interface PayuQrRequestRepo : JpaRepository<PayuQrRequest, UUID> {
fun findByBookingId(bookingId: UUID): List<PayuQrRequest>
fun findTopByBookingIdAndAmountAndCurrencyAndStatusOrderByCreatedAtDesc(
bookingId: UUID,
amount: Long,
currency: String,
status: com.android.trisolarisserver.models.payment.PayuQrStatus
): PayuQrRequest?
}