Derive PayU return URLs from property
Some checks failed
build-and-deploy / build-deploy (push) Failing after 30s
Some checks failed
build-and-deploy / build-deploy (push) Failing after 30s
This commit is contained in:
@@ -28,40 +28,11 @@ class PayuSettingsSchemaFix(
|
|||||||
salt_32 varchar,
|
salt_32 varchar,
|
||||||
salt_256 varchar,
|
salt_256 varchar,
|
||||||
base_url varchar not null,
|
base_url varchar not null,
|
||||||
success_url varchar not null,
|
|
||||||
failure_url varchar not null,
|
|
||||||
use_salt_256 boolean not null default true,
|
use_salt_256 boolean not null default true,
|
||||||
updated_at timestamptz not null
|
updated_at timestamptz not null
|
||||||
)
|
)
|
||||||
""".trimIndent()
|
""".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")
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -117,8 +117,8 @@ class PayuQrPayments(
|
|||||||
add("firstname", firstname)
|
add("firstname", firstname)
|
||||||
add("email", email)
|
add("email", email)
|
||||||
add("phone", phone)
|
add("phone", phone)
|
||||||
add("surl", settings.successUrl)
|
add("surl", buildReturnUrl(propertyId, true))
|
||||||
add("furl", settings.failureUrl)
|
add("furl", buildReturnUrl(propertyId, false))
|
||||||
add("pg", "DBQR")
|
add("pg", "DBQR")
|
||||||
add("bankcode", "UPIDBQR")
|
add("bankcode", "UPIDBQR")
|
||||||
add("hash", hash)
|
add("hash", hash)
|
||||||
@@ -191,6 +191,11 @@ class PayuQrPayments(
|
|||||||
?: throw ResponseStatusException(HttpStatus.BAD_REQUEST, "PayU salt missing")
|
?: 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 {
|
private fun sha512(input: String): String {
|
||||||
val bytes = MessageDigest.getInstance("SHA-512").digest(input.toByteArray())
|
val bytes = MessageDigest.getInstance("SHA-512").digest(input.toByteArray())
|
||||||
return bytes.joinToString("") { "%02x".format(it) }
|
return bytes.joinToString("") { "%02x".format(it) }
|
||||||
|
|||||||
@@ -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.
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -53,10 +53,6 @@ class PayuSettingsController(
|
|||||||
throw ResponseStatusException(HttpStatus.BAD_REQUEST, "merchantKey required")
|
throw ResponseStatusException(HttpStatus.BAD_REQUEST, "merchantKey required")
|
||||||
}
|
}
|
||||||
val baseUrl = request.baseUrl?.trim()?.ifBlank { null } ?: "https://secure.payu.in/_payment"
|
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 existing = payuSettingsRepo.findByPropertyId(propertyId)
|
||||||
val updated = if (existing == null) {
|
val updated = if (existing == null) {
|
||||||
PayuSettings(
|
PayuSettings(
|
||||||
@@ -65,8 +61,6 @@ class PayuSettingsController(
|
|||||||
salt32 = request.salt32?.trim()?.ifBlank { null },
|
salt32 = request.salt32?.trim()?.ifBlank { null },
|
||||||
salt256 = request.salt256?.trim()?.ifBlank { null },
|
salt256 = request.salt256?.trim()?.ifBlank { null },
|
||||||
baseUrl = baseUrl,
|
baseUrl = baseUrl,
|
||||||
successUrl = successUrl,
|
|
||||||
failureUrl = failureUrl,
|
|
||||||
useSalt256 = request.useSalt256 ?: true,
|
useSalt256 = request.useSalt256 ?: true,
|
||||||
updatedAt = OffsetDateTime.now()
|
updatedAt = OffsetDateTime.now()
|
||||||
)
|
)
|
||||||
@@ -75,8 +69,6 @@ class PayuSettingsController(
|
|||||||
if (request.salt32 != null) existing.salt32 = request.salt32.trim().ifBlank { null }
|
if (request.salt32 != null) existing.salt32 = request.salt32.trim().ifBlank { null }
|
||||||
if (request.salt256 != null) existing.salt256 = request.salt256.trim().ifBlank { null }
|
if (request.salt256 != null) existing.salt256 = request.salt256.trim().ifBlank { null }
|
||||||
existing.baseUrl = baseUrl
|
existing.baseUrl = baseUrl
|
||||||
existing.successUrl = successUrl
|
|
||||||
existing.failureUrl = failureUrl
|
|
||||||
if (request.useSalt256 != null) existing.useSalt256 = request.useSalt256
|
if (request.useSalt256 != null) existing.useSalt256 = request.useSalt256
|
||||||
existing.updatedAt = OffsetDateTime.now()
|
existing.updatedAt = OffsetDateTime.now()
|
||||||
existing
|
existing
|
||||||
@@ -91,8 +83,6 @@ private fun PayuSettings.toResponse(): PayuSettingsResponse {
|
|||||||
propertyId = propertyId,
|
propertyId = propertyId,
|
||||||
merchantKey = merchantKey,
|
merchantKey = merchantKey,
|
||||||
baseUrl = baseUrl,
|
baseUrl = baseUrl,
|
||||||
successUrl = successUrl,
|
|
||||||
failureUrl = failureUrl,
|
|
||||||
useSalt256 = useSalt256,
|
useSalt256 = useSalt256,
|
||||||
hasSalt32 = !salt32.isNullOrBlank(),
|
hasSalt32 = !salt32.isNullOrBlank(),
|
||||||
hasSalt256 = !salt256.isNullOrBlank()
|
hasSalt256 = !salt256.isNullOrBlank()
|
||||||
|
|||||||
@@ -7,8 +7,6 @@ data class PayuSettingsUpsertRequest(
|
|||||||
val salt32: String? = null,
|
val salt32: String? = null,
|
||||||
val salt256: String? = null,
|
val salt256: String? = null,
|
||||||
val baseUrl: String? = null,
|
val baseUrl: String? = null,
|
||||||
val successUrl: String? = null,
|
|
||||||
val failureUrl: String? = null,
|
|
||||||
val useSalt256: Boolean? = null
|
val useSalt256: Boolean? = null
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -16,8 +14,6 @@ data class PayuSettingsResponse(
|
|||||||
val propertyId: UUID,
|
val propertyId: UUID,
|
||||||
val merchantKey: String,
|
val merchantKey: String,
|
||||||
val baseUrl: String,
|
val baseUrl: String,
|
||||||
val successUrl: String,
|
|
||||||
val failureUrl: String,
|
|
||||||
val useSalt256: Boolean,
|
val useSalt256: Boolean,
|
||||||
val hasSalt32: Boolean,
|
val hasSalt32: Boolean,
|
||||||
val hasSalt256: Boolean
|
val hasSalt256: Boolean
|
||||||
|
|||||||
@@ -40,12 +40,6 @@ class PayuSettings(
|
|||||||
@Column(name = "base_url", nullable = false)
|
@Column(name = "base_url", nullable = false)
|
||||||
var baseUrl: String = "https://secure.payu.in/_payment",
|
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)
|
@Column(name = "use_salt_256", nullable = false)
|
||||||
var useSalt256: Boolean = true,
|
var useSalt256: Boolean = true,
|
||||||
|
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ internal object PublicEndpoints {
|
|||||||
private val roomTypeImages = Regex("^/properties/[^/]+/room-types/[^/]+/images$")
|
private val roomTypeImages = Regex("^/properties/[^/]+/room-types/[^/]+/images$")
|
||||||
private val iconPngFile = Regex("^/icons/png/[^/]+$")
|
private val iconPngFile = Regex("^/icons/png/[^/]+$")
|
||||||
private val payuWebhook = Regex("^/properties/[^/]+/payu/webhook$")
|
private val payuWebhook = Regex("^/properties/[^/]+/payu/webhook$")
|
||||||
|
private val payuReturn = Regex("^/properties/[^/]+/payu/return/(success|failure)$")
|
||||||
|
|
||||||
fun isPublic(request: HttpServletRequest): Boolean {
|
fun isPublic(request: HttpServletRequest): Boolean {
|
||||||
val path = request.requestURI
|
val path = request.requestURI
|
||||||
@@ -25,6 +26,7 @@ internal object PublicEndpoints {
|
|||||||
|| (roomTypes.matches(path) && method == "GET")
|
|| (roomTypes.matches(path) && method == "GET")
|
||||||
|| roomTypeImages.matches(path)
|
|| roomTypeImages.matches(path)
|
||||||
|| (payuWebhook.matches(path) && method == "POST")
|
|| (payuWebhook.matches(path) && method == "POST")
|
||||||
|
|| (payuReturn.matches(path) && method == "GET")
|
||||||
|| (path == "/image-tags" && method == "GET")
|
|| (path == "/image-tags" && method == "GET")
|
||||||
|| path == "/icons/png"
|
|| path == "/icons/png"
|
||||||
|| iconPngFile.matches(path)
|
|| iconPngFile.matches(path)
|
||||||
|
|||||||
Reference in New Issue
Block a user