Skip to content

Commit a5b3547

Browse files
authored
Fix npe caused by required project in the PaymentStatusView (#166)
Fixed crash of the checkout activity caused of an npe in the payment status view if the user opens the app and is not checked in anymore.
1 parent 1ff5bdd commit a5b3547

File tree

2 files changed

+42
-29
lines changed

2 files changed

+42
-29
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ All notable changes to this project will be documented in this file.
2121
* The UI event for paydirekt changed from SHOW_PAYDIREKT_INPUT to SHOW_GIROPAY_INPUT
2222
* ### Fixed
2323
* ui: Fixed crash caused by missing project id when calling the PaydirektInputFragment via the PaymentInputViewHelper
24+
* ui: Fixed crash caused by npe in the PaymentStatusView
2425

2526
## [0.71.8]
2627
### Changed

ui/src/main/java/io/snabble/sdk/ui/checkout/PaymentStatusView.kt

Lines changed: 41 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,14 @@ import android.view.View
1010
import android.view.ViewGroup
1111
import android.view.inputmethod.InputMethodManager
1212
import android.webkit.URLUtil
13-
import android.widget.*
13+
import android.widget.Button
14+
import android.widget.EditText
15+
import android.widget.FrameLayout
16+
import android.widget.ImageView
17+
import android.widget.LinearLayout
18+
import android.widget.ProgressBar
19+
import android.widget.RadioButton
20+
import android.widget.TextView
1421
import androidx.activity.OnBackPressedCallback
1522
import androidx.core.view.isVisible
1623
import androidx.core.widget.addTextChangedListener
@@ -19,7 +26,13 @@ import androidx.lifecycle.LifecycleOwner
1926
import com.airbnb.lottie.LottieAnimationView
2027
import com.google.android.material.button.MaterialButton
2128
import com.google.android.material.textfield.TextInputLayout
22-
import io.snabble.sdk.*
29+
import io.snabble.sdk.BarcodeFormat
30+
import io.snabble.sdk.FulfillmentState
31+
import io.snabble.sdk.PaymentMethod
32+
import io.snabble.sdk.Project
33+
import io.snabble.sdk.ReceiptInfo
34+
import io.snabble.sdk.Receipts
35+
import io.snabble.sdk.Snabble
2336
import io.snabble.sdk.checkout.Checkout
2437
import io.snabble.sdk.checkout.CheckoutState
2538
import io.snabble.sdk.checkout.Fulfillment
@@ -73,8 +86,8 @@ class PaymentStatusView @JvmOverloads constructor(
7386
private var fulfillmentContainer = findViewById<LinearLayout>(R.id.fulfillment_container)
7487

7588
private var isStopped: Boolean = false
76-
private lateinit var project: Project
77-
private lateinit var checkout: Checkout
89+
private var project: Project? = null
90+
private var checkout: Checkout? = null
7891

7992
private val backPressedCallback = object : OnBackPressedCallback(true) {
8093
override fun handleOnBackPressed() {
@@ -94,19 +107,20 @@ class PaymentStatusView @JvmOverloads constructor(
94107
clipChildren = false
95108

96109
if (!isInEditMode) {
97-
project = requireNotNull(Snabble.checkedInProject.value)
98-
checkout = project.checkout
110+
project = Snabble.checkedInProject.value
111+
checkout = project?.checkout
99112

100113
Snabble.checkedInProject.observeView(this) {
101-
project = requireNotNull(it)
102-
checkout = project.checkout
114+
project = it
115+
checkout = project?.checkout
103116
}
104117

105118
update()
106119
}
107120
}
108121

109122
private fun update() {
123+
val project = project ?: return
110124
paymentOriginCandidateHelper = PaymentOriginCandidateHelper(project)
111125
paymentOriginCandidateHelper.addPaymentOriginCandidateAvailableListener(this)
112126

@@ -116,24 +130,22 @@ class PaymentStatusView @JvmOverloads constructor(
116130

117131
if (state == CheckoutState.PAYMENT_APPROVED) {
118132
ignoreStateChanges = true
119-
checkout.reset()
133+
checkout?.reset()
120134
requireFragmentActivity().finish()
121135

122-
if (state == CheckoutState.PAYMENT_APPROVED) {
123-
executeUiAction(SnabbleUI.Event.SHOW_CHECKOUT_DONE)
124-
}
136+
executeUiAction(SnabbleUI.Event.SHOW_CHECKOUT_DONE)
125137

126138
project.coupons.update()
127139
} else {
128-
checkout.abort()
140+
checkout?.abort()
129141
}
130142
}
131143

132-
checkout.state.observeView(this) {
144+
checkout?.state?.observeView(this) {
133145
onStateChanged(it)
134146
}
135147

136-
checkout.fulfillmentState.observeView(this) {
148+
checkout?.fulfillmentState?.observeView(this) {
137149
onFulfillmentStateChanged(it)
138150
}
139151

@@ -175,7 +187,7 @@ class PaymentStatusView @JvmOverloads constructor(
175187
}
176188

177189
private fun createAddIbanIntent() =
178-
if (project.paymentMethodDescriptors.any { it.paymentMethod == PaymentMethod.PAYONE_SEPA }) {
190+
if (project?.paymentMethodDescriptors?.any { it.paymentMethod == PaymentMethod.PAYONE_SEPA } == true) {
179191
PayoneSepaActivity.newIntent(context, paymentOriginCandidate)
180192
} else {
181193
SEPACardInputActivity.newIntent(context, paymentOriginCandidate)
@@ -207,7 +219,7 @@ class PaymentStatusView @JvmOverloads constructor(
207219
}
208220

209221
private fun sendRating(rating: String) {
210-
project.events.analytics("rating", rating, ratingMessage ?: "")
222+
project?.events?.analytics("rating", rating, ratingMessage ?: "")
211223
Telemetry.event(Telemetry.Event.Rating, rating)
212224
ratingTitle.setText(R.string.Snabble_PaymentStatus_Ratings_thanksForFeedback)
213225
ratingLayoutGroup.isVisible = false
@@ -249,16 +261,16 @@ class PaymentStatusView @JvmOverloads constructor(
249261
successAnimation.playAnimation()
250262
progress.isVisible = false
251263
payment.state = PaymentStatusItemView.State.SUCCESS
252-
val checkoutProcess = checkout.checkoutProcess
264+
val checkoutProcess = checkout?.checkoutProcess
253265
if (checkoutProcess?.orderId != null) {
254-
startPollingForReceipts(checkout.checkoutProcess?.orderId)
266+
startPollingForReceipts(checkout?.checkoutProcess?.orderId)
255267
} else {
256268
receipt.state = PaymentStatusItemView.State.NOT_EXECUTED
257269
}
258270
back.text = resources.getString(R.string.Snabble_PaymentStatus_close)
259271
backPressedCallback.isEnabled = false
260272
ratingCardLayout.isVisible = true
261-
paymentOriginCandidateHelper.startPollingIfLinkIsAvailable(checkout.checkoutProcess)
273+
paymentOriginCandidateHelper.startPollingIfLinkIsAvailable(checkout?.checkoutProcess)
262274
}
263275

264276
CheckoutState.PAYMENT_PROCESSING_ERROR -> {
@@ -287,16 +299,16 @@ class PaymentStatusView @JvmOverloads constructor(
287299
}
288300

289301
CheckoutState.REQUEST_PAYMENT_AUTHORIZATION_TOKEN -> {
290-
val price = checkout.verifiedOnlinePrice
302+
val price = checkout?.verifiedOnlinePrice ?: -1
291303
if (price != -1) {
292-
val googlePayHelper = project.googlePayHelper
304+
val googlePayHelper = project?.googlePayHelper
293305
if (googlePayHelper != null) {
294306
googlePayHelper.requestPayment(price)
295307
} else {
296-
checkout.abort()
308+
checkout?.abort()
297309
}
298310
} else {
299-
checkout.abort()
311+
checkout?.abort()
300312
}
301313
}
302314

@@ -307,7 +319,7 @@ class PaymentStatusView @JvmOverloads constructor(
307319
}
308320

309321
private fun checkForExitToken() {
310-
checkout.checkoutProcess?.exitToken?.let {
322+
checkout?.checkoutProcess?.exitToken?.let {
311323
if (it.value != null && it.format != null) {
312324
val format = BarcodeFormat.parse(it.format)
313325
if (format != null) {
@@ -336,7 +348,7 @@ class PaymentStatusView @JvmOverloads constructor(
336348
payment.state = PaymentStatusItemView.State.FAILED
337349
payment.setText(resources.getString(R.string.Snabble_PaymentStatus_Payment_error))
338350
payment.setAction(resources.getString(R.string.Snabble_PaymentStatus_Payment_tryAgain)) {
339-
project.shoppingCart.generateNewUUID()
351+
project?.shoppingCart?.generateNewUUID()
340352
requireFragmentActivity().finish()
341353
}
342354
title.text = resources.getString(R.string.Snabble_PaymentStatus_Title_error)
@@ -354,8 +366,8 @@ class PaymentStatusView @JvmOverloads constructor(
354366
}
355367

356368
paymentOriginCandidateHelper.addPaymentOriginCandidateAvailableListener(this)
357-
if (checkout.state.value == CheckoutState.PAYMENT_APPROVED) {
358-
paymentOriginCandidateHelper.startPollingIfLinkIsAvailable(checkout.checkoutProcess)
369+
if (checkout?.state?.value == CheckoutState.PAYMENT_APPROVED) {
370+
paymentOriginCandidateHelper.startPollingIfLinkIsAvailable(checkout?.checkoutProcess)
359371
}
360372
}
361373

@@ -367,7 +379,7 @@ class PaymentStatusView @JvmOverloads constructor(
367379
override fun onStart(owner: LifecycleOwner) {
368380
startPollingForPaymentOriginCandidate()
369381

370-
onStateChanged(checkout.state.value)
382+
onStateChanged(checkout?.state?.value)
371383
isStopped = false
372384
}
373385

0 commit comments

Comments
 (0)