Skip to content

Commit

Permalink
Merge pull request #35 from tillhub/msirok/hotfix/OPI_same_device_sup…
Browse files Browse the repository at this point in the history
…port

[hotfix]opi same device support
  • Loading branch information
SloInfinity authored Jul 15, 2024
2 parents 4bd02a8 + adda876 commit fcfa330
Show file tree
Hide file tree
Showing 19 changed files with 371 additions and 203 deletions.
4 changes: 3 additions & 1 deletion gradle/libs.versions.toml
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ junit = "4.13.2"
mockk = "1.13.8"
kotest = "5.8.0"

lifecycle = "2.7.0"
lifecycle = "2.8.3"
lifecycle-runtime-ktx = "2.7.0"
activity-compose = "1.8.2"
compose-bom = "2024.02.02"
Expand Down Expand Up @@ -55,6 +55,7 @@ androidx-lifecycle-runtime = { group = "androidx.lifecycle", name = "lifecycle-r
androidx-lifecycle-viewmodel = { group = "androidx.lifecycle", name = "lifecycle-viewmodel-ktx", version.ref = "lifecycle" }
androidx-lifecycle-livedata = { group = "androidx.lifecycle", name = "lifecycle-livedata-ktx", version.ref = "lifecycle" }
androidx-lifecycle-compiler = { group = "androidx.lifecycle", name = "lifecycle-compiler", version.ref = "lifecycle" }
androidx-lifecycle-service = { group = "androidx.lifecycle", name = "lifecycle-service", version.ref = "lifecycle" }
lifecycle-runtime-ktx = { group = "androidx.lifecycle", name = "lifecycle-runtime-ktx", version.ref = "lifecycle-runtime-ktx" }

# Lavego
Expand Down Expand Up @@ -96,6 +97,7 @@ lifecycle = [
"androidx.lifecycle.viewmodel",
"androidx.lifecycle.livedata",
"androidx.lifecycle.compiler",
"androidx.lifecycle.service",
]
lavego = [
"lavego.sale.sdk",
Expand Down
5 changes: 1 addition & 4 deletions payment-engine/build.gradle.kts
Original file line number Diff line number Diff line change
@@ -1,6 +1,3 @@
import io.gitlab.arturbosch.detekt.Detekt
import io.gitlab.arturbosch.detekt.DetektCreateBaselineTask

plugins {
alias(libs.plugins.androidLibrary)
alias(libs.plugins.kotlinAndroid)
Expand Down Expand Up @@ -95,7 +92,7 @@ afterEvaluate {
create<MavenPublication>("payment-engine") {
groupId = "de.tillhub.paymentengine"
artifactId = "payment-engine"
version = "2.0.8"
version = "2.1.0"

from(components.getByName("release"))
}
Expand Down
8 changes: 8 additions & 0 deletions payment-engine/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@
package="de.tillhub.paymentengine">

<uses-permission android:name="android.permission.REORDER_TASKS" />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE"/>
<uses-permission android:name="android.permission.POST_NOTIFICATIONS" />

<application
android:networkSecurityConfig="@xml/network_security_config">
Expand All @@ -12,6 +14,12 @@
android:exported="false"
tools:node="merge" />

<service
android:name="de.tillhub.paymentengine.opi.OPIService"
android:exported="false"
android:foregroundServiceType="shortService"
tools:node="merge" />

<activity
android:name=".zvt.ui.CardPaymentActivity"
android:windowSoftInputMode="adjustResize"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import de.tillhub.paymentengine.data.Terminal
import de.tillhub.paymentengine.helper.TerminalConfig
import de.tillhub.paymentengine.helper.TerminalConfigImpl
import de.tillhub.paymentengine.helper.toISOString
import de.tillhub.paymentengine.opi.common.withOPIContext
import de.tillhub.paymentengine.opi.communication.OPIChannel0
import de.tillhub.paymentengine.opi.communication.OPIChannel1
import de.tillhub.paymentengine.opi.communication.OPIChannelFactory
Expand Down Expand Up @@ -97,9 +98,9 @@ internal class OPIChannelControllerImpl(
}
}

override suspend fun login() {
override suspend fun login() = withOPIContext {
// If the state is not Idle, then we should drop the new request
if (_operationState.value !is OPIOperationStatus.Idle) return
if (_operationState.value !is OPIOperationStatus.Idle) return@withOPIContext

_operationState.value = OPIOperationStatus.Pending.Login

Expand Down Expand Up @@ -130,7 +131,7 @@ internal class OPIChannelControllerImpl(
message = "Channel 0 request object could not be converted to XML.",
error = e
)
return
return@withOPIContext
}

// setup C0 communication
Expand All @@ -140,7 +141,7 @@ internal class OPIChannelControllerImpl(

// here the app waits for the channel 0 socket to connect to the terminal.
while (!channel0.isConnected) {
delay(CONNECTION_WAIT_DELAY)
delay(WAIT_DELAY)
}

channel0.sendMessage(xml) { responseXml ->
Expand Down Expand Up @@ -176,47 +177,48 @@ internal class OPIChannelControllerImpl(
}
}

override suspend fun initiateCardPayment(amount: BigDecimal, currency: ISOAlphaCurrency) {
// If the state is not LoggedIn, then we should drop the new request
if (_operationState.value !is OPIOperationStatus.LoggedIn) return

_operationState.value = OPIOperationStatus.Pending.Operation(terminalConfig.timeNow())

// checks if the controller is initialized
if (initialized) {
// setup C1 communication, it has to be setup before C0,
// because once C0 request is sent, C1 needs to handle the intermediate communication
handleChannel1Communication()

val payload = CardServiceRequest(
applicationSender = terminal.saleConfig.applicationName,
popId = terminal.saleConfig.poiId,
requestId = requestIdFactory.generateRequestId(),
requestType = ServiceRequestType.CARD_PAYMENT.value,
workstationId = terminal.saleConfig.saleId,
posData = PosData(terminalConfig.timeNow().toISOString()),
totalAmount = TotalAmount(
value = amount.setScale(2),
currency = currency.value
override suspend fun initiateCardPayment(amount: BigDecimal, currency: ISOAlphaCurrency) =
withOPIContext {
// If the state is not LoggedIn, then we should drop the new request
if (_operationState.value !is OPIOperationStatus.LoggedIn) return@withOPIContext

_operationState.value = OPIOperationStatus.Pending.Operation(terminalConfig.timeNow())

// checks if the controller is initialized
if (initialized) {
// setup C1 communication, it has to be setup before C0,
// because once C0 request is sent, C1 needs to handle the intermediate communication
handleChannel1Communication()

val payload = CardServiceRequest(
applicationSender = terminal.saleConfig.applicationName,
popId = terminal.saleConfig.poiId,
requestId = requestIdFactory.generateRequestId(),
requestType = ServiceRequestType.CARD_PAYMENT.value,
workstationId = terminal.saleConfig.saleId,
posData = PosData(terminalConfig.timeNow().toISOString()),
totalAmount = TotalAmount(
value = amount.setScale(2),
currency = currency.value
)
)
)

val requestConverter = converterFactory.newDtoToStringConverter<CardServiceRequest>()
val responseConverter = converterFactory.newStringToDtoConverter(
clazz = CardServiceResponse::class.java
)
val requestConverter = converterFactory.newDtoToStringConverter<CardServiceRequest>()
val responseConverter = converterFactory.newStringToDtoConverter(
clazz = CardServiceResponse::class.java
)

// setup C0 communication
handleC0Communication(payload, requestConverter, responseConverter)
} else {
// in case the controller is not initialized set the state to `Error.NotInitialised`
_operationState.value = OPIOperationStatus.Error.NotInitialised
// setup C0 communication
handleC0Communication(payload, requestConverter, responseConverter)
} else {
// in case the controller is not initialized set the state to `Error.NotInitialised`
_operationState.value = OPIOperationStatus.Error.NotInitialised
}
}
}

override suspend fun initiatePaymentReversal(stan: String) {
override suspend fun initiatePaymentReversal(stan: String) = withOPIContext {
// If the state is not LoggedIn, then we should drop the new request
if (_operationState.value !is OPIOperationStatus.LoggedIn) return
if (_operationState.value !is OPIOperationStatus.LoggedIn) return@withOPIContext

_operationState.value = OPIOperationStatus.Pending.Operation(terminalConfig.timeNow())

Expand Down Expand Up @@ -249,47 +251,49 @@ internal class OPIChannelControllerImpl(
}
}

override suspend fun initiatePartialRefund(amount: BigDecimal, currency: ISOAlphaCurrency) {
// If the state is not LoggedIn, then we should drop the new request
if (_operationState.value !is OPIOperationStatus.LoggedIn) return

_operationState.value = OPIOperationStatus.Pending.Operation(terminalConfig.timeNow())

// checks if the controller is initialized
if (initialized) {
// setup C1 communication, it has to be setup before C0,
// because once C0 request is sent, C1 needs to handle the intermediate communication
handleChannel1Communication()

val payload = CardServiceRequest(
applicationSender = terminal.saleConfig.applicationName,
popId = terminal.saleConfig.poiId,
requestId = requestIdFactory.generateRequestId(),
requestType = ServiceRequestType.PAYMENT_REFUND.value,
workstationId = terminal.saleConfig.saleId,
posData = PosData(terminalConfig.timeNow().toISOString()),
totalAmount = TotalAmount(
value = amount.setScale(2),
currency = currency.value
override suspend fun initiatePartialRefund(amount: BigDecimal, currency: ISOAlphaCurrency) =
withOPIContext {
// If the state is not LoggedIn, then we should drop the new request
if (_operationState.value !is OPIOperationStatus.LoggedIn) return@withOPIContext

_operationState.value = OPIOperationStatus.Pending.Operation(terminalConfig.timeNow())

// checks if the controller is initialized
if (initialized) {
// setup C1 communication, it has to be setup before C0,
// because once C0 request is sent, C1 needs to handle the intermediate communication
handleChannel1Communication()

val payload = CardServiceRequest(
applicationSender = terminal.saleConfig.applicationName,
popId = terminal.saleConfig.poiId,
requestId = requestIdFactory.generateRequestId(),
requestType = ServiceRequestType.PAYMENT_REFUND.value,
workstationId = terminal.saleConfig.saleId,
posData = PosData(terminalConfig.timeNow().toISOString()),
totalAmount = TotalAmount(
value = amount.setScale(2),
currency = currency.value
)
)
)

val requestConverter = converterFactory.newDtoToStringConverter<CardServiceRequest>()
val responseConverter = converterFactory.newStringToDtoConverter(
clazz = CardServiceResponse::class.java
)
val requestConverter = converterFactory
.newDtoToStringConverter<CardServiceRequest>()
val responseConverter = converterFactory.newStringToDtoConverter(
clazz = CardServiceResponse::class.java
)

// setup C0 communication
handleC0Communication(payload, requestConverter, responseConverter)
} else {
// in case the controller is not initialized set the state to `Error.NotInitialised`
_operationState.value = OPIOperationStatus.Error.NotInitialised
// setup C0 communication
handleC0Communication(payload, requestConverter, responseConverter)
} else {
// in case the controller is not initialized set the state to `Error.NotInitialised`
_operationState.value = OPIOperationStatus.Error.NotInitialised
}
}
}

override suspend fun initiateReconciliation() {
override suspend fun initiateReconciliation() = withOPIContext {
// If the state is not LoggedIn, then we should drop the new request
if (_operationState.value !is OPIOperationStatus.LoggedIn) return
if (_operationState.value !is OPIOperationStatus.LoggedIn) return@withOPIContext

_operationState.value = OPIOperationStatus.Pending.Operation(terminalConfig.timeNow())

Expand Down Expand Up @@ -440,7 +444,7 @@ internal class OPIChannelControllerImpl(

// here the app waits for the channel 0 socket to connect to the terminal.
while (!channel0.isConnected) {
delay(CONNECTION_WAIT_DELAY)
delay(WAIT_DELAY)
}

channel0.sendMessage(xml) { responseXml ->
Expand Down Expand Up @@ -492,6 +496,7 @@ internal class OPIChannelControllerImpl(
if (_operationState.value is OPIOperationStatus.Result) {
Timber.tag("OPI_CHANNEL_CONTROLLER")
.d("Operation done, error ignored.\nError: $message\n$error")
return
}

_operationState.value = OPIOperationStatus.Error.Communication(message, error)
Expand Down Expand Up @@ -538,6 +543,6 @@ internal class OPIChannelControllerImpl(
}

companion object {
private const val CONNECTION_WAIT_DELAY = 100L
private const val WAIT_DELAY = 100L
}
}
Loading

0 comments on commit fcfa330

Please sign in to comment.