From 461e94edd0539d602ac7ff0ab4fbed1e36a840ab Mon Sep 17 00:00:00 2001 From: androidlover5842 Date: Fri, 30 Jan 2026 05:53:06 +0530 Subject: [PATCH] Derive PayU return URLs from property --- .../config/PayuSettingsSchemaFix.kt | 29 ------------------- .../controller/PayuQrPayments.kt | 9 ++++-- .../controller/PayuReturnController.kt | 26 +++++++++++++++++ .../controller/PayuSettingsController.kt | 10 ------- .../controller/dto/PayuDtos.kt | 4 --- .../models/payment/PayuSettings.kt | 6 ---- .../security/PublicEndpoints.kt | 2 ++ 7 files changed, 35 insertions(+), 51 deletions(-) create mode 100644 src/main/kotlin/com/android/trisolarisserver/controller/PayuReturnController.kt diff --git a/src/main/kotlin/com/android/trisolarisserver/config/PayuSettingsSchemaFix.kt b/src/main/kotlin/com/android/trisolarisserver/config/PayuSettingsSchemaFix.kt index eba221e..d0c4c71 100644 --- a/src/main/kotlin/com/android/trisolarisserver/config/PayuSettingsSchemaFix.kt +++ b/src/main/kotlin/com/android/trisolarisserver/config/PayuSettingsSchemaFix.kt @@ -28,40 +28,11 @@ 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") - } } } diff --git a/src/main/kotlin/com/android/trisolarisserver/controller/PayuQrPayments.kt b/src/main/kotlin/com/android/trisolarisserver/controller/PayuQrPayments.kt index b68efe9..ca9cd4d 100644 --- a/src/main/kotlin/com/android/trisolarisserver/controller/PayuQrPayments.kt +++ b/src/main/kotlin/com/android/trisolarisserver/controller/PayuQrPayments.kt @@ -117,8 +117,8 @@ class PayuQrPayments( add("firstname", firstname) add("email", email) add("phone", phone) - add("surl", settings.successUrl) - add("furl", settings.failureUrl) + add("surl", buildReturnUrl(propertyId, true)) + add("furl", buildReturnUrl(propertyId, false)) add("pg", "DBQR") add("bankcode", "UPIDBQR") add("hash", hash) @@ -191,6 +191,11 @@ class PayuQrPayments( ?: throw ResponseStatusException(HttpStatus.BAD_REQUEST, "PayU salt missing") } + private fun buildReturnUrl(propertyId: UUID, success: Boolean): String { + val path = if (success) "success" else "failure" + return "https://api.hoteltrisolaris.in/properties/$propertyId/payu/return/$path" + } + private fun sha512(input: String): String { val bytes = MessageDigest.getInstance("SHA-512").digest(input.toByteArray()) return bytes.joinToString("") { "%02x".format(it) } diff --git a/src/main/kotlin/com/android/trisolarisserver/controller/PayuReturnController.kt b/src/main/kotlin/com/android/trisolarisserver/controller/PayuReturnController.kt new file mode 100644 index 0000000..86d4355 --- /dev/null +++ b/src/main/kotlin/com/android/trisolarisserver/controller/PayuReturnController.kt @@ -0,0 +1,26 @@ +package com.android.trisolarisserver.controller + +import org.springframework.http.HttpStatus +import org.springframework.web.bind.annotation.GetMapping +import org.springframework.web.bind.annotation.PathVariable +import org.springframework.web.bind.annotation.RequestMapping +import org.springframework.web.bind.annotation.ResponseStatus +import org.springframework.web.bind.annotation.RestController +import java.util.UUID + +@RestController +@RequestMapping("/properties/{propertyId}/payu/return") +class PayuReturnController { + + @GetMapping("/success") + @ResponseStatus(HttpStatus.NO_CONTENT) + fun success(@PathVariable propertyId: UUID) { + // PayU redirect target; no-op. + } + + @GetMapping("/failure") + @ResponseStatus(HttpStatus.NO_CONTENT) + fun failure(@PathVariable propertyId: UUID) { + // PayU redirect target; no-op. + } +} diff --git a/src/main/kotlin/com/android/trisolarisserver/controller/PayuSettingsController.kt b/src/main/kotlin/com/android/trisolarisserver/controller/PayuSettingsController.kt index 836f00b..4c80532 100644 --- a/src/main/kotlin/com/android/trisolarisserver/controller/PayuSettingsController.kt +++ b/src/main/kotlin/com/android/trisolarisserver/controller/PayuSettingsController.kt @@ -53,10 +53,6 @@ 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( @@ -65,8 +61,6 @@ 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() ) @@ -75,8 +69,6 @@ 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 @@ -91,8 +83,6 @@ private fun PayuSettings.toResponse(): PayuSettingsResponse { propertyId = propertyId, merchantKey = merchantKey, baseUrl = baseUrl, - successUrl = successUrl, - failureUrl = failureUrl, useSalt256 = useSalt256, hasSalt32 = !salt32.isNullOrBlank(), hasSalt256 = !salt256.isNullOrBlank() diff --git a/src/main/kotlin/com/android/trisolarisserver/controller/dto/PayuDtos.kt b/src/main/kotlin/com/android/trisolarisserver/controller/dto/PayuDtos.kt index 8b3f0d7..b65f44f 100644 --- a/src/main/kotlin/com/android/trisolarisserver/controller/dto/PayuDtos.kt +++ b/src/main/kotlin/com/android/trisolarisserver/controller/dto/PayuDtos.kt @@ -7,8 +7,6 @@ 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 ) @@ -16,8 +14,6 @@ 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 diff --git a/src/main/kotlin/com/android/trisolarisserver/models/payment/PayuSettings.kt b/src/main/kotlin/com/android/trisolarisserver/models/payment/PayuSettings.kt index 4a24ab1..9aff7f1 100644 --- a/src/main/kotlin/com/android/trisolarisserver/models/payment/PayuSettings.kt +++ b/src/main/kotlin/com/android/trisolarisserver/models/payment/PayuSettings.kt @@ -40,12 +40,6 @@ 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, diff --git a/src/main/kotlin/com/android/trisolarisserver/security/PublicEndpoints.kt b/src/main/kotlin/com/android/trisolarisserver/security/PublicEndpoints.kt index 3d78caa..abef703 100644 --- a/src/main/kotlin/com/android/trisolarisserver/security/PublicEndpoints.kt +++ b/src/main/kotlin/com/android/trisolarisserver/security/PublicEndpoints.kt @@ -11,6 +11,7 @@ internal object PublicEndpoints { private val roomTypeImages = Regex("^/properties/[^/]+/room-types/[^/]+/images$") private val iconPngFile = Regex("^/icons/png/[^/]+$") private val payuWebhook = Regex("^/properties/[^/]+/payu/webhook$") + private val payuReturn = Regex("^/properties/[^/]+/payu/return/(success|failure)$") fun isPublic(request: HttpServletRequest): Boolean { val path = request.requestURI @@ -25,6 +26,7 @@ internal object PublicEndpoints { || (roomTypes.matches(path) && method == "GET") || roomTypeImages.matches(path) || (payuWebhook.matches(path) && method == "POST") + || (payuReturn.matches(path) && method == "GET") || (path == "/image-tags" && method == "GET") || path == "/icons/png" || iconPngFile.matches(path)