Auto-fetch PayU payment link tokens
All checks were successful
build-and-deploy / build-deploy (push) Successful in 36s

This commit is contained in:
androidlover5842
2026-01-30 08:06:32 +05:30
parent 92b023cb5b
commit a3257e4827
5 changed files with 109 additions and 11 deletions

View File

@@ -23,6 +23,7 @@ import org.springframework.web.bind.annotation.RequestMapping
import org.springframework.web.bind.annotation.RestController
import org.springframework.web.client.RestTemplate
import org.springframework.web.server.ResponseStatusException
import java.time.OffsetDateTime
import java.util.UUID
@RestController
@@ -116,9 +117,11 @@ class PayuPaymentLinksController(
}
request.expiryDate?.trim()?.ifBlank { null }?.let { body["expiryDate"] = it }
val accessToken = resolveAccessToken(settings)
settingsRepo.save(settings)
val headers = HttpHeaders().apply {
contentType = MediaType.APPLICATION_JSON
set("Authorization", "Bearer ${settings.accessToken}")
set("Authorization", "Bearer $accessToken")
set("merchantId", settings.merchantId)
}
val entity = HttpEntity(body, headers)
@@ -145,6 +148,60 @@ class PayuPaymentLinksController(
}
}
private fun resolveAccessToken(settings: com.android.trisolarisserver.models.payment.PayuPaymentLinkSettings): String {
val now = OffsetDateTime.now()
val existing = settings.accessToken?.trim()?.ifBlank { null }
val expiresAt = settings.tokenExpiresAt
if (existing != null && expiresAt != null && expiresAt.isAfter(now.plusSeconds(60))) {
return existing
}
val clientId = settings.clientId?.trim()?.ifBlank { null }
val clientSecret = settings.clientSecret?.trim()?.ifBlank { null }
if (clientId == null || clientSecret == null) {
throw ResponseStatusException(HttpStatus.BAD_REQUEST, "Payment link client credentials missing")
}
val tokenResponse = fetchAccessToken(settings.isTest, clientId, clientSecret)
settings.accessToken = tokenResponse.accessToken
settings.tokenExpiresAt = now.plusSeconds(tokenResponse.expiresIn.toLong())
return tokenResponse.accessToken
}
private data class TokenResponse(val accessToken: String, val expiresIn: Int)
private fun fetchAccessToken(isTest: Boolean, clientId: String, clientSecret: String): TokenResponse {
val url = if (isTest) {
"https://uat-accounts.payu.in/oauth/token"
} else {
"https://accounts.payu.in/oauth/token"
}
val form = org.springframework.util.LinkedMultiValueMap<String, String>().apply {
add("client_id", clientId)
add("client_secret", clientSecret)
add("grant_type", "client_credentials")
add("scope", "create_payment_links")
}
val headers = HttpHeaders().apply {
contentType = MediaType.APPLICATION_FORM_URLENCODED
}
val entity = HttpEntity(form, headers)
val response = restTemplate.postForEntity(url, entity, String::class.java)
val body = response.body ?: ""
if (!response.statusCode.is2xxSuccessful) {
throw ResponseStatusException(HttpStatus.BAD_GATEWAY, "PayU token request failed")
}
return try {
val node = objectMapper.readTree(body)
val token = node.path("access_token").asText(null)
val expiresIn = node.path("expires_in").asInt(0)
if (token.isNullOrBlank() || expiresIn <= 0) {
throw IllegalStateException("Token missing")
}
TokenResponse(token, expiresIn)
} catch (ex: Exception) {
throw ResponseStatusException(HttpStatus.BAD_GATEWAY, "PayU token parse failed")
}
}
private fun extractPaymentLink(body: String): String? {
if (body.isBlank()) return null
return try {