Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[hotfix]opi same device support #35

Merged
merged 8 commits into from
Jul 15, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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