Align PayU QR request with docs
Some checks failed
build-and-deploy / build-deploy (push) Failing after 29s

This commit is contained in:
androidlover5842
2026-01-30 05:30:08 +05:30
parent 38c0a0ec9a
commit e5c2abc317
5 changed files with 87 additions and 8 deletions

View File

@@ -28,11 +28,40 @@ class PayuSettingsSchemaFix(
salt_32 varchar,
salt_256 varchar,
base_url varchar not null,
success_url varchar not null,
failure_url varchar not null,
use_salt_256 boolean not null default true,
updated_at timestamptz not null
)
""".trimIndent()
)
}
val hasSuccessUrl = jdbcTemplate.queryForObject(
"""
select count(*)
from information_schema.columns
where table_name = 'payu_settings'
and column_name = 'success_url'
""".trimIndent(),
Int::class.java
) ?: 0
if (hasSuccessUrl == 0) {
logger.info("Adding payu_settings.success_url column")
jdbcTemplate.execute("alter table payu_settings add column success_url varchar")
}
val hasFailureUrl = jdbcTemplate.queryForObject(
"""
select count(*)
from information_schema.columns
where table_name = 'payu_settings'
and column_name = 'failure_url'
""".trimIndent(),
Int::class.java
) ?: 0
if (hasFailureUrl == 0) {
logger.info("Adding payu_settings.failure_url column")
jdbcTemplate.execute("alter table payu_settings add column failure_url varchar")
}
}
}

View File

@@ -77,14 +77,15 @@ class PayuQrPayments(
val productInfo = "Booking $bookingId"
val firstname = request.customerName?.trim()?.ifBlank { null } ?: "Guest"
val email = request.customerEmail?.trim()?.ifBlank { null } ?: "guest@example.com"
val phone = request.customerPhone?.trim()?.ifBlank { null } ?: ""
val phone = request.customerPhone?.trim()?.ifBlank { null }
?: throw ResponseStatusException(HttpStatus.BAD_REQUEST, "customerPhone required")
val amount = String.format("%.2f", pending.toDouble())
val udf1 = bookingId.toString()
val udf2 = propertyId.toString()
val udf3 = ""
val udf4 = ""
val udf5 = ""
val udf3 = request.udf3?.trim()?.ifBlank { "" } ?: ""
val udf4 = request.udf4?.trim()?.ifBlank { "" } ?: ""
val udf5 = request.udf5?.trim()?.ifBlank { "" } ?: ""
val hash = sha512(
listOf(
settings.merchantKey,
@@ -116,15 +117,32 @@ class PayuQrPayments(
add("firstname", firstname)
add("email", email)
add("phone", phone)
add("surl", settings.successUrl)
add("furl", settings.failureUrl)
add("pg", "DBQR")
add("bankcode", "UPIDBQR")
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("txn_s2s_flow", "4")
add("s2s_client_ip", "127.0.0.1")
add("s2s_device_info", "TrisolarisServer")
request.expiryMinutes?.let { add("expiry_time", it.toString()) }
val clientIp = request.clientIp?.trim()?.ifBlank { null }
?: throw ResponseStatusException(HttpStatus.BAD_REQUEST, "clientIp required")
val deviceInfo = request.deviceInfo?.trim()?.ifBlank { null }
?: 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()) }
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) }
request.state?.trim()?.ifBlank { null }?.let { add("state", it) }
request.country?.trim()?.ifBlank { null }?.let { add("country", it) }
request.zipcode?.trim()?.ifBlank { null }?.let { add("zipcode", it) }
}
val requestPayload = form.entries.joinToString("&") { entry ->

View File

@@ -53,6 +53,10 @@ class PayuSettingsController(
throw ResponseStatusException(HttpStatus.BAD_REQUEST, "merchantKey required")
}
val baseUrl = request.baseUrl?.trim()?.ifBlank { null } ?: "https://secure.payu.in/_payment"
val successUrl = request.successUrl?.trim()?.ifBlank { null }
?: throw ResponseStatusException(HttpStatus.BAD_REQUEST, "successUrl required")
val failureUrl = request.failureUrl?.trim()?.ifBlank { null }
?: throw ResponseStatusException(HttpStatus.BAD_REQUEST, "failureUrl required")
val existing = payuSettingsRepo.findByPropertyId(propertyId)
val updated = if (existing == null) {
PayuSettings(
@@ -61,6 +65,8 @@ class PayuSettingsController(
salt32 = request.salt32?.trim()?.ifBlank { null },
salt256 = request.salt256?.trim()?.ifBlank { null },
baseUrl = baseUrl,
successUrl = successUrl,
failureUrl = failureUrl,
useSalt256 = request.useSalt256 ?: true,
updatedAt = OffsetDateTime.now()
)
@@ -69,6 +75,8 @@ class PayuSettingsController(
if (request.salt32 != null) existing.salt32 = request.salt32.trim().ifBlank { null }
if (request.salt256 != null) existing.salt256 = request.salt256.trim().ifBlank { null }
existing.baseUrl = baseUrl
existing.successUrl = successUrl
existing.failureUrl = failureUrl
if (request.useSalt256 != null) existing.useSalt256 = request.useSalt256
existing.updatedAt = OffsetDateTime.now()
existing
@@ -83,6 +91,8 @@ private fun PayuSettings.toResponse(): PayuSettingsResponse {
propertyId = propertyId,
merchantKey = merchantKey,
baseUrl = baseUrl,
successUrl = successUrl,
failureUrl = failureUrl,
useSalt256 = useSalt256,
hasSalt32 = !salt32.isNullOrBlank(),
hasSalt256 = !salt256.isNullOrBlank()

View File

@@ -7,6 +7,8 @@ data class PayuSettingsUpsertRequest(
val salt32: String? = null,
val salt256: String? = null,
val baseUrl: String? = null,
val successUrl: String? = null,
val failureUrl: String? = null,
val useSalt256: Boolean? = null
)
@@ -14,6 +16,8 @@ data class PayuSettingsResponse(
val propertyId: UUID,
val merchantKey: String,
val baseUrl: String,
val successUrl: String,
val failureUrl: String,
val useSalt256: Boolean,
val hasSalt32: Boolean,
val hasSalt256: Boolean
@@ -23,7 +27,19 @@ data class PayuQrGenerateRequest(
val customerName: String? = null,
val customerEmail: String? = null,
val customerPhone: String? = null,
val expiryMinutes: Int? = 30
val expiryMinutes: Int? = null,
val expirySeconds: Int? = null,
val clientIp: String? = null,
val deviceInfo: String? = null,
val address1: String? = null,
val address2: String? = null,
val city: String? = null,
val state: String? = null,
val country: String? = null,
val zipcode: String? = null,
val udf3: String? = null,
val udf4: String? = null,
val udf5: String? = null
)
data class PayuQrGenerateResponse(

View File

@@ -40,6 +40,12 @@ class PayuSettings(
@Column(name = "base_url", nullable = false)
var baseUrl: String = "https://secure.payu.in/_payment",
@Column(name = "success_url", nullable = false)
var successUrl: String,
@Column(name = "failure_url", nullable = false)
var failureUrl: String,
@Column(name = "use_salt_256", nullable = false)
var useSalt256: Boolean = true,