fix razorpay qr credit log
This commit is contained in:
@@ -73,10 +73,19 @@ fun RazorpayQrScreen(
|
|||||||
LaunchedEffect(propertyId, bookingId) {
|
LaunchedEffect(propertyId, bookingId) {
|
||||||
viewModel.loadQrList(propertyId, bookingId)
|
viewModel.loadQrList(propertyId, bookingId)
|
||||||
}
|
}
|
||||||
|
LaunchedEffect(state.isCredited) {
|
||||||
|
if (state.isCredited) {
|
||||||
|
onBack()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
val isViewingQr = state.isClosed || !state.imageUrl.isNullOrBlank()
|
val isViewingQr = state.isClosed || !state.imageUrl.isNullOrBlank()
|
||||||
BackHandler(enabled = isViewingQr) {
|
val exitAndRefresh: () -> Unit = {
|
||||||
viewModel.exitQrView()
|
viewModel.exitQrView()
|
||||||
|
viewModel.loadQrList(propertyId, bookingId)
|
||||||
|
}
|
||||||
|
BackHandler(enabled = isViewingQr) {
|
||||||
|
exitAndRefresh()
|
||||||
}
|
}
|
||||||
|
|
||||||
Scaffold(
|
Scaffold(
|
||||||
@@ -86,7 +95,7 @@ fun RazorpayQrScreen(
|
|||||||
navigationIcon = {
|
navigationIcon = {
|
||||||
IconButton(onClick = {
|
IconButton(onClick = {
|
||||||
if (isViewingQr) {
|
if (isViewingQr) {
|
||||||
viewModel.exitQrView()
|
exitAndRefresh()
|
||||||
} else {
|
} else {
|
||||||
onBack()
|
onBack()
|
||||||
}
|
}
|
||||||
@@ -98,7 +107,20 @@ fun RazorpayQrScreen(
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
) { padding ->
|
) { padding ->
|
||||||
if (state.isClosed) {
|
if (state.isCredited) {
|
||||||
|
Box(
|
||||||
|
modifier = Modifier
|
||||||
|
.fillMaxSize()
|
||||||
|
.padding(padding),
|
||||||
|
contentAlignment = Alignment.Center
|
||||||
|
) {
|
||||||
|
Text(
|
||||||
|
text = "Payment received",
|
||||||
|
style = MaterialTheme.typography.titleMedium,
|
||||||
|
color = MaterialTheme.colorScheme.primary
|
||||||
|
)
|
||||||
|
}
|
||||||
|
} else if (state.isClosed) {
|
||||||
Box(
|
Box(
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.fillMaxSize()
|
.fillMaxSize()
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ data class RazorpayQrState(
|
|||||||
val currency: String? = null,
|
val currency: String? = null,
|
||||||
val imageUrl: String? = null,
|
val imageUrl: String? = null,
|
||||||
val isClosed: Boolean = false,
|
val isClosed: Boolean = false,
|
||||||
|
val isCredited: Boolean = false,
|
||||||
val paymentLink: String? = null,
|
val paymentLink: String? = null,
|
||||||
val qrList: List<com.android.trisolarispms.data.api.model.RazorpayQrListItemDto> = emptyList()
|
val qrList: List<com.android.trisolarispms.data.api.model.RazorpayQrListItemDto> = emptyList()
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -37,12 +37,14 @@ class RazorpayQrViewModel : ViewModel() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun exitQrView() {
|
fun exitQrView() {
|
||||||
|
stopQrEventStream()
|
||||||
stopQrEventPolling()
|
stopQrEventPolling()
|
||||||
_state.update {
|
_state.update {
|
||||||
it.copy(
|
it.copy(
|
||||||
qrId = null,
|
qrId = null,
|
||||||
imageUrl = null,
|
imageUrl = null,
|
||||||
isClosed = false,
|
isClosed = false,
|
||||||
|
isCredited = false,
|
||||||
error = null
|
error = null
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@@ -121,6 +123,7 @@ class RazorpayQrViewModel : ViewModel() {
|
|||||||
if (qrId.isNullOrBlank()) return
|
if (qrId.isNullOrBlank()) return
|
||||||
if (lastQrId == qrId && qrEventSource != null) return
|
if (lastQrId == qrId && qrEventSource != null) return
|
||||||
stopQrEventStream()
|
stopQrEventStream()
|
||||||
|
stopQrEventPolling()
|
||||||
lastQrId = qrId
|
lastQrId = qrId
|
||||||
val client = ApiClient.createOkHttpClient(readTimeoutSeconds = 0)
|
val client = ApiClient.createOkHttpClient(readTimeoutSeconds = 0)
|
||||||
val url = "${ApiConstants.BASE_URL}properties/$propertyId/bookings/$bookingId/payments/razorpay/qr/$qrId/events/stream"
|
val url = "${ApiConstants.BASE_URL}properties/$propertyId/bookings/$bookingId/payments/razorpay/qr/$qrId/events/stream"
|
||||||
@@ -138,10 +141,17 @@ class RazorpayQrViewModel : ViewModel() {
|
|||||||
val event = runCatching {
|
val event = runCatching {
|
||||||
gson.fromJson(data, RazorpayQrEventDto::class.java)
|
gson.fromJson(data, RazorpayQrEventDto::class.java)
|
||||||
}.getOrNull() ?: return
|
}.getOrNull() ?: return
|
||||||
if (isClosedStatus(event.status)) {
|
val status = event.status?.lowercase()
|
||||||
_state.update { it.copy(isClosed = true, imageUrl = null) }
|
val eventName = event.event?.lowercase()
|
||||||
|
if (eventName == "qr_code.credited" || status == "credited") {
|
||||||
|
_state.update { it.copy(isCredited = true, imageUrl = null) }
|
||||||
stopQrEventStream()
|
stopQrEventStream()
|
||||||
stopQrEventPolling()
|
stopQrEventPolling()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if (isClosedStatus(status)) {
|
||||||
|
_state.update { it.copy(isClosed = true, imageUrl = null) }
|
||||||
|
stopQrEventStream()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -151,13 +161,16 @@ class RazorpayQrViewModel : ViewModel() {
|
|||||||
response: okhttp3.Response?
|
response: okhttp3.Response?
|
||||||
) {
|
) {
|
||||||
stopQrEventStream()
|
stopQrEventStream()
|
||||||
|
startQrEventPolling(propertyId, bookingId, qrId)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onClosed(eventSource: EventSource) {
|
override fun onClosed(eventSource: EventSource) {
|
||||||
stopQrEventStream()
|
stopQrEventStream()
|
||||||
|
startQrEventPolling(propertyId, bookingId, qrId)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
// Keep polling as a fallback in case SSE is buffered or never delivers events.
|
||||||
startQrEventPolling(propertyId, bookingId, qrId)
|
startQrEventPolling(propertyId, bookingId, qrId)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -170,6 +183,7 @@ class RazorpayQrViewModel : ViewModel() {
|
|||||||
private fun startQrEventPolling(propertyId: String, bookingId: String, qrId: String) {
|
private fun startQrEventPolling(propertyId: String, bookingId: String, qrId: String) {
|
||||||
if (qrPollJob?.isActive == true) return
|
if (qrPollJob?.isActive == true) return
|
||||||
qrPollJob = viewModelScope.launch {
|
qrPollJob = viewModelScope.launch {
|
||||||
|
var delayMs = 4000L
|
||||||
while (true) {
|
while (true) {
|
||||||
val currentQrId = state.value.qrId
|
val currentQrId = state.value.qrId
|
||||||
if (currentQrId.isNullOrBlank() || currentQrId != qrId || state.value.isClosed) {
|
if (currentQrId.isNullOrBlank() || currentQrId != qrId || state.value.isClosed) {
|
||||||
@@ -183,16 +197,22 @@ class RazorpayQrViewModel : ViewModel() {
|
|||||||
)
|
)
|
||||||
val body = response.body()
|
val body = response.body()
|
||||||
if (response.isSuccessful && body != null) {
|
if (response.isSuccessful && body != null) {
|
||||||
|
if (body.any { it.event?.lowercase() == "qr_code.credited" || it.status?.lowercase() == "credited" }) {
|
||||||
|
_state.update { it.copy(isCredited = true, imageUrl = null) }
|
||||||
|
stopQrEventStream()
|
||||||
|
break
|
||||||
|
}
|
||||||
if (body.any { isClosedStatus(it.status) }) {
|
if (body.any { isClosedStatus(it.status) }) {
|
||||||
_state.update { it.copy(isClosed = true, imageUrl = null) }
|
_state.update { it.copy(isClosed = true, imageUrl = null) }
|
||||||
stopQrEventStream()
|
stopQrEventStream()
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (_: Exception) {
|
delayMs = 4000L
|
||||||
// ignore polling errors
|
} catch (e: Exception) {
|
||||||
|
delayMs = (delayMs * 1.5).toLong().coerceAtMost(15000L)
|
||||||
}
|
}
|
||||||
delay(5000)
|
delay(delayMs)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -258,6 +278,7 @@ class RazorpayQrViewModel : ViewModel() {
|
|||||||
currency = item.currency,
|
currency = item.currency,
|
||||||
imageUrl = item.imageUrl,
|
imageUrl = item.imageUrl,
|
||||||
isClosed = status == "closed" || status == "expired" || status == "credited",
|
isClosed = status == "closed" || status == "expired" || status == "credited",
|
||||||
|
isCredited = status == "credited",
|
||||||
error = null
|
error = null
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user