Auto-fetch PayU payment link tokens
All checks were successful
build-and-deploy / build-deploy (push) Successful in 36s
All checks were successful
build-and-deploy / build-deploy (push) Successful in 36s
This commit is contained in:
@@ -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 {
|
||||
|
||||
Reference in New Issue
Block a user