Add PayU webhook capture per property
Some checks failed
build-and-deploy / build-deploy (push) Failing after 29s

This commit is contained in:
androidlover5842
2026-01-30 05:48:09 +05:30
parent e5c2abc317
commit 4168835d47
5 changed files with 130 additions and 0 deletions

View File

@@ -0,0 +1,36 @@
package com.android.trisolarisserver.config
import org.springframework.jdbc.core.JdbcTemplate
import org.springframework.stereotype.Component
@Component
class PayuWebhookLogSchemaFix(
private val jdbcTemplate: JdbcTemplate
) : PostgresSchemaFix(jdbcTemplate) {
override fun runPostgres(jdbcTemplate: JdbcTemplate) {
val hasTable = jdbcTemplate.queryForObject(
"""
select count(*)
from information_schema.tables
where table_name = 'payu_webhook_log'
""".trimIndent(),
Int::class.java
) ?: 0
if (hasTable == 0) {
logger.info("Creating payu_webhook_log table")
jdbcTemplate.execute(
"""
create table payu_webhook_log (
id uuid primary key,
property_id uuid not null references property(id) on delete cascade,
headers text,
payload text,
content_type varchar,
received_at timestamptz not null
)
""".trimIndent()
)
}
}
}

View File

@@ -0,0 +1,47 @@
package com.android.trisolarisserver.controller
import com.android.trisolarisserver.models.payment.PayuWebhookLog
import com.android.trisolarisserver.repo.PayuWebhookLogRepo
import com.android.trisolarisserver.repo.PropertyRepo
import jakarta.servlet.http.HttpServletRequest
import org.springframework.http.HttpStatus
import org.springframework.web.bind.annotation.PathVariable
import org.springframework.web.bind.annotation.PostMapping
import org.springframework.web.bind.annotation.RequestBody
import org.springframework.web.bind.annotation.RequestMapping
import org.springframework.web.bind.annotation.ResponseStatus
import org.springframework.web.bind.annotation.RestController
import org.springframework.web.server.ResponseStatusException
import java.time.OffsetDateTime
import java.util.UUID
@RestController
@RequestMapping("/properties/{propertyId}/payu/webhook")
class PayuWebhookCapture(
private val propertyRepo: PropertyRepo,
private val payuWebhookLogRepo: PayuWebhookLogRepo
) {
@PostMapping
@ResponseStatus(HttpStatus.NO_CONTENT)
fun capture(
@PathVariable propertyId: UUID,
@RequestBody(required = false) body: String?,
request: HttpServletRequest
) {
val property = propertyRepo.findById(propertyId).orElseThrow {
ResponseStatusException(HttpStatus.NOT_FOUND, "Property not found")
}
val headers = request.headerNames.toList().associateWith { request.getHeader(it) }
val headersText = headers.entries.joinToString("\n") { (k, v) -> "$k: $v" }
payuWebhookLogRepo.save(
PayuWebhookLog(
property = property,
headers = headersText,
payload = body,
contentType = request.contentType,
receivedAt = OffsetDateTime.now()
)
)
}
}

View File

@@ -0,0 +1,38 @@
package com.android.trisolarisserver.models.payment
import com.android.trisolarisserver.models.property.Property
import jakarta.persistence.Column
import jakarta.persistence.Entity
import jakarta.persistence.FetchType
import jakarta.persistence.GeneratedValue
import jakarta.persistence.Id
import jakarta.persistence.JoinColumn
import jakarta.persistence.ManyToOne
import jakarta.persistence.Table
import java.time.OffsetDateTime
import java.util.UUID
@Entity
@Table(name = "payu_webhook_log")
class PayuWebhookLog(
@Id
@GeneratedValue
@Column(columnDefinition = "uuid")
val id: UUID? = null,
@ManyToOne(fetch = FetchType.LAZY, optional = false)
@JoinColumn(name = "property_id", nullable = false)
var property: Property,
@Column(name = "headers", columnDefinition = "text")
var headers: String? = null,
@Column(name = "payload", columnDefinition = "text")
var payload: String? = null,
@Column(name = "content_type")
var contentType: String? = null,
@Column(name = "received_at", nullable = false, columnDefinition = "timestamptz")
val receivedAt: OffsetDateTime = OffsetDateTime.now()
)

View File

@@ -0,0 +1,7 @@
package com.android.trisolarisserver.repo
import com.android.trisolarisserver.models.payment.PayuWebhookLog
import org.springframework.data.jpa.repository.JpaRepository
import java.util.UUID
interface PayuWebhookLogRepo : JpaRepository<PayuWebhookLog, UUID>

View File

@@ -10,6 +10,7 @@ internal object PublicEndpoints {
private val roomTypes = Regex("^/properties/[^/]+/room-types$")
private val roomTypeImages = Regex("^/properties/[^/]+/room-types/[^/]+/images$")
private val iconPngFile = Regex("^/icons/png/[^/]+$")
private val payuWebhook = Regex("^/properties/[^/]+/payu/webhook$")
fun isPublic(request: HttpServletRequest): Boolean {
val path = request.requestURI
@@ -23,6 +24,7 @@ internal object PublicEndpoints {
|| (roomsByType.matches(path) && method == "GET")
|| (roomTypes.matches(path) && method == "GET")
|| roomTypeImages.matches(path)
|| (payuWebhook.matches(path) && method == "POST")
|| (path == "/image-tags" && method == "GET")
|| path == "/icons/png"
|| iconPngFile.matches(path)