diff --git a/src/main/kotlin/com/android/trisolarisserver/config/PayuSettingsSchemaFix.kt b/src/main/kotlin/com/android/trisolarisserver/config/PayuSettingsSchemaFix.kt index d0c4c71..eba221e 100644 --- a/src/main/kotlin/com/android/trisolarisserver/config/PayuSettingsSchemaFix.kt +++ b/src/main/kotlin/com/android/trisolarisserver/config/PayuSettingsSchemaFix.kt @@ -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") + } } } diff --git a/src/main/kotlin/com/android/trisolarisserver/controller/PayuQrPayments.kt b/src/main/kotlin/com/android/trisolarisserver/controller/PayuQrPayments.kt index 78ad7a9..b68efe9 100644 --- a/src/main/kotlin/com/android/trisolarisserver/controller/PayuQrPayments.kt +++ b/src/main/kotlin/com/android/trisolarisserver/controller/PayuQrPayments.kt @@ -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 -> diff --git a/src/main/kotlin/com/android/trisolarisserver/controller/PayuSettingsController.kt b/src/main/kotlin/com/android/trisolarisserver/controller/PayuSettingsController.kt index 4c80532..836f00b 100644 --- a/src/main/kotlin/com/android/trisolarisserver/controller/PayuSettingsController.kt +++ b/src/main/kotlin/com/android/trisolarisserver/controller/PayuSettingsController.kt @@ -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() 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 5b4aba9..8b3f0d7 100644 --- a/src/main/kotlin/com/android/trisolarisserver/controller/dto/PayuDtos.kt +++ b/src/main/kotlin/com/android/trisolarisserver/controller/dto/PayuDtos.kt @@ -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( 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 9aff7f1..4a24ab1 100644 --- a/src/main/kotlin/com/android/trisolarisserver/models/payment/PayuSettings.kt +++ b/src/main/kotlin/com/android/trisolarisserver/models/payment/PayuSettings.kt @@ -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,