11package io .snabble .sdk ;
22
33import androidx .annotation .NonNull ;
4+ import androidx .lifecycle .LiveData ;
5+ import androidx .lifecycle .MutableLiveData ;
46
57import java .util .ArrayList ;
68import java .util .Collection ;
@@ -105,7 +107,9 @@ public enum State {
105107 */
106108 NO_SHOP
107109 }
108-
110+
111+ public static final int INVALID_PRICE = -1 ;
112+
109113 private final Project project ;
110114 private final CheckoutApi checkoutApi ;
111115 private final ShoppingCart shoppingCart ;
@@ -119,6 +123,9 @@ public enum State {
119123 private final List <OnCheckoutStateChangedListener > checkoutStateListeners = new CopyOnWriteArrayList <>();
120124 private final List <OnFulfillmentUpdateListener > fulfillmentUpdateListeners = new CopyOnWriteArrayList <>();
121125
126+ private MutableLiveData <Checkout .State > checkoutState = new MutableLiveData <>();
127+ private MutableLiveData <CheckoutApi .Fulfillment []> fulfillmentState = new MutableLiveData <>();
128+
122129 private State lastState = Checkout .State .NONE ;
123130 private State state = Checkout .State .NONE ;
124131
@@ -279,6 +286,7 @@ public void checkout(long timeout, boolean allowFallbackAfterTimeout) {
279286 shop = project .getCheckedInShop ();
280287 paymentOriginCandidateHelper .reset ();
281288 redeemedCoupons = null ;
289+ fulfillmentState .setValue (null );
282290
283291 notifyStateChanged (Checkout .State .HANDSHAKING );
284292
@@ -392,16 +400,20 @@ public void success(CheckoutApi.CheckoutProcessResponse checkoutProcessResponse,
392400 rawCheckoutProcess = rawResponse ;
393401
394402 if (!handleProcessResponse ()) {
395- boolean allChecksOk = runChecks (checkoutProcessResponse );
403+ boolean allChecksOk = areAllChecksSucceeded (checkoutProcessResponse );
396404
397405 if (allChecksOk ) {
398406 if (checkoutProcessResponse .paymentState == CheckoutApi .State .PROCESSING ) {
399407 Logger .d ("Processing payment..." );
400408 notifyStateChanged (Checkout .State .PAYMENT_PROCESSING );
401409 } else {
402410 Logger .d ("Waiting for approval..." );
403- notifyStateChanged (Checkout .State .WAIT_FOR_APPROVAL );
411+ if (paymentMethod != PaymentMethod .GOOGLE_PAY ) {
412+ notifyStateChanged (Checkout .State .WAIT_FOR_APPROVAL );
413+ }
404414 }
415+ } else {
416+ notifyStateChanged (Checkout .State .WAIT_FOR_APPROVAL );
405417 }
406418
407419 if (!paymentMethod .isOfflineMethod ()) {
@@ -443,19 +455,19 @@ public void error() {
443455 });
444456 }
445457
446- private boolean runChecks (CheckoutApi .CheckoutProcessResponse checkoutProcessResponse ) {
458+ private boolean areAllChecksSucceeded (CheckoutApi .CheckoutProcessResponse checkoutProcessResponse ) {
447459 boolean allChecksOk = true ;
448460
449461 if (checkoutProcessResponse .checks != null ) {
450462 for (CheckoutApi .Check check : checkoutProcessResponse .checks ) {
451- if (check .type == null || check .state == null ) {
452- continue ;
453- }
454-
455463 if (check .state == CheckoutApi .State .FAILED ) {
456464 return false ;
457465 }
458466
467+ if (check .type == null ) {
468+ continue ;
469+ }
470+
459471 if (check .performedBy == CheckoutApi .Performer .APP ) {
460472 if (check .type == CheckoutApi .CheckType .MIN_AGE ) {
461473 Logger .d ("Verifying age..." );
@@ -484,6 +496,18 @@ private boolean runChecks(CheckoutApi.CheckoutProcessResponse checkoutProcessRes
484496 return allChecksOk ;
485497 }
486498
499+ private boolean hasStillPendingChecks (CheckoutApi .CheckoutProcessResponse checkoutProcessResponse ) {
500+ if (checkoutProcessResponse .checks != null ) {
501+ for (CheckoutApi .Check check : checkoutProcessResponse .checks ) {
502+ if (check .state == CheckoutApi .State .PENDING ) {
503+ return true ;
504+ }
505+ }
506+ }
507+
508+ return false ;
509+ }
510+
487511 private boolean areAllFulfillmentsClosed () {
488512 if (checkoutProcess == null || checkoutProcess .fulfillments == null ) {
489513 return true ;
@@ -568,6 +592,7 @@ public void error() {
568592 });
569593
570594 if (state == Checkout .State .WAIT_FOR_APPROVAL
595+ || state == State .VERIFYING_PAYMENT_METHOD
571596 || state == State .REQUEST_PAYMENT_AUTHORIZATION_TOKEN
572597 || state == Checkout .State .PAYMENT_PROCESSING
573598 || (state == State .PAYMENT_APPROVED && !areAllFulfillmentsClosed ())) {
@@ -578,7 +603,11 @@ public void error() {
578603 private boolean handleProcessResponse () {
579604 if (checkoutProcess .aborted ) {
580605 Logger .d ("Payment aborted" );
581- notifyStateChanged (Checkout .State .PAYMENT_ABORTED );
606+ if (hasAnyFulfillmentFailed ()) {
607+ notifyStateChanged (State .PAYMENT_PROCESSING_ERROR );
608+ } else {
609+ notifyStateChanged (Checkout .State .PAYMENT_ABORTED );
610+ }
582611 return true ;
583612 }
584613
@@ -622,27 +651,19 @@ private boolean handleProcessResponse() {
622651 || checkoutProcess .paymentState == CheckoutApi .State .UNAUTHORIZED ) {
623652 if (hasAnyFulfillmentFailed ()) {
624653 checkoutApi .abort (checkoutProcess , null );
625- notifyStateChanged (State .PAYMENT_ABORTED );
654+ notifyStateChanged (State .PAYMENT_PROCESSING );
626655 notifyFulfillmentDone ();
627- return true ;
656+ return false ;
628657 }
629658
630- if (!runChecks (checkoutProcess )) {
631- Logger .d ("Payment denied by supervisor" );
632- shoppingCart .generateNewUUID ();
633- notifyStateChanged (Checkout .State .DENIED_BY_SUPERVISOR );
659+ if (hasStillPendingChecks (checkoutProcess )) {
660+ notifyStateChanged (State .WAIT_FOR_APPROVAL );
634661 }
635662
636- if (checkoutProcess . supervisorApproval != null && ! checkoutProcess . supervisorApproval ) {
663+ if (! areAllChecksSucceeded ( checkoutProcess ) ) {
637664 Logger .d ("Payment denied by supervisor" );
638665 shoppingCart .generateNewUUID ();
639666 notifyStateChanged (Checkout .State .DENIED_BY_SUPERVISOR );
640- return true ;
641- } else if (checkoutProcess .paymentApproval != null && !checkoutProcess .paymentApproval ) {
642- Logger .d ("Payment denied by payment provider" );
643- shoppingCart .generateNewUUID ();
644- notifyStateChanged (Checkout .State .DENIED_BY_PAYMENT_PROVIDER );
645- return true ;
646667 }
647668 } else if (checkoutProcess .paymentState == CheckoutApi .State .PROCESSING ) {
648669 notifyStateChanged (State .PAYMENT_PROCESSING );
@@ -762,10 +783,7 @@ public int getPriceToPay() {
762783 public int getVerifiedOnlinePrice () {
763784 try {
764785 if (checkoutProcess != null ) {
765- return checkoutProcess .checkoutInfo .get ("price" )
766- .getAsJsonObject ()
767- .get ("price" )
768- .getAsInt ();
786+ return checkoutProcess .pricing .price .price ;
769787 }
770788 } catch (Exception e ) {
771789 return -1 ;
@@ -861,6 +879,14 @@ public interface OnCheckoutStateChangedListener {
861879 void onStateChanged (State state );
862880 }
863881
882+ public LiveData <State > getCheckoutState () {
883+ return checkoutState ;
884+ }
885+
886+ public LiveData <CheckoutApi .Fulfillment []> getFulfillmentState () {
887+ return fulfillmentState ;
888+ }
889+
864890 public void addOnCheckoutStateChangedListener (OnCheckoutStateChangedListener listener ) {
865891 if (!checkoutStateListeners .contains (listener )) {
866892 checkoutStateListeners .add (listener );
@@ -882,6 +908,8 @@ private void notifyStateChanged(final State state, boolean repeat) {
882908 this .state = state ;
883909
884910 Dispatch .mainThread (() -> {
911+ checkoutState .setValue (state );
912+
885913 for (OnCheckoutStateChangedListener checkoutStateListener : checkoutStateListeners ) {
886914 checkoutStateListener .onStateChanged (state );
887915 }
@@ -910,6 +938,12 @@ private void notifyFulfillmentUpdate() {
910938 for (OnFulfillmentUpdateListener checkoutStateListener : fulfillmentUpdateListeners ) {
911939 checkoutStateListener .onFulfillmentUpdated ();
912940 }
941+
942+ if (checkoutProcess != null ) {
943+ fulfillmentState .setValue (checkoutProcess .fulfillments );
944+ } else {
945+ fulfillmentState .setValue (null );
946+ }
913947 });
914948 }
915949
@@ -918,6 +952,12 @@ private void notifyFulfillmentDone() {
918952 for (OnFulfillmentUpdateListener checkoutStateListener : fulfillmentUpdateListeners ) {
919953 checkoutStateListener .onFulfillmentDone ();
920954 }
955+
956+ if (checkoutProcess != null ) {
957+ fulfillmentState .setValue (checkoutProcess .fulfillments );
958+ } else {
959+ fulfillmentState .setValue (null );
960+ }
921961 });
922962 }
923963}
0 commit comments