Skip to content

Commit 191ee5d

Browse files
committed
Merge branch 'new-payment-status' into 0.52.x
2 parents 892d08c + abce97c commit 191ee5d

File tree

91 files changed

+1038
-396
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

91 files changed

+1038
-396
lines changed

core/src/main/java/io/snabble/sdk/Checkout.java

Lines changed: 66 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
package io.snabble.sdk;
22

33
import androidx.annotation.NonNull;
4+
import androidx.lifecycle.LiveData;
5+
import androidx.lifecycle.MutableLiveData;
46

57
import java.util.ArrayList;
68
import 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
}

core/src/main/java/io/snabble/sdk/CheckoutApi.java

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -286,19 +286,17 @@ public String getSelfLink() {
286286

287287
public static class CheckoutProcessResponse {
288288
public Map<String, Href> links;
289-
public Boolean supervisorApproval;
290-
public Boolean paymentApproval;
291289
public Check[] checks;
292290
@SerializedName("orderID")
293291
public String orderId;
294292
public boolean aborted;
295-
public JsonObject checkoutInfo;
296293
public PaymentMethod paymentMethod;
297294
public boolean modified;
298295
public PaymentInformation paymentInformation;
299296
public JsonObject paymentPreauthInformation;
300297
public ExitToken exitToken;
301298
public State paymentState;
299+
public Pricing pricing;
302300
public PaymentResult paymentResult;
303301
public Fulfillment[] fulfillments;
304302

@@ -319,6 +317,10 @@ public String getAuthorizePaymentLink() {
319317
}
320318
}
321319

320+
public static class Pricing {
321+
Price price;
322+
}
323+
322324
public interface CheckoutInfoResult {
323325
void success(SignedCheckoutInfo signedCheckoutInfo, int onlinePrice, PaymentMethodInfo[] availablePaymentMethods);
324326
void noShop();

core/src/main/java/io/snabble/sdk/googlepay/GooglePayHelper.kt

Lines changed: 10 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -139,20 +139,15 @@ class GooglePayHelper(
139139
fun isReadyToPay(isReadyToPayListener: IsReadyToPayListener) {
140140
val request = IsReadyToPayRequest.fromJson(GsonHolder.get().toJson(isReadyToPayRequest()))
141141

142-
val googlePayClient = googlePayClient
143-
if (googlePayClient != null) {
144-
val task = googlePayClient.isReadyToPay(request)
145-
task.addOnCompleteListener { completedTask ->
146-
try {
147-
completedTask.getResult(ApiException::class.java)?.let {
148-
isReadyToPayListener.isReadyToPay(it)
149-
}
150-
} catch (exception: ApiException) {
151-
isReadyToPayListener.isReadyToPay(false)
142+
val task = googlePayClient.isReadyToPay(request)
143+
task.addOnCompleteListener { completedTask ->
144+
try {
145+
completedTask.getResult(ApiException::class.java)?.let {
146+
isReadyToPayListener.isReadyToPay(it)
152147
}
148+
} catch (exception: ApiException) {
149+
isReadyToPayListener.isReadyToPay(false)
153150
}
154-
} else {
155-
isReadyToPayListener.isReadyToPay(false)
156151
}
157152
}
158153

@@ -177,13 +172,9 @@ class GooglePayHelper(
177172

178173
val request = PaymentDataRequest.fromJson(GsonHolder.get().toJson(paymentDataRequestJson))
179174
val googlePayClient = googlePayClient
180-
if (request != null && googlePayClient != null) {
181-
val task = googlePayClient.loadPaymentData(request)
182-
AutoResolveHelper.resolveTask(task, activity, requestCode)
183-
return true
184-
}
185-
186-
return false
175+
val task = googlePayClient.loadPaymentData(request)
176+
AutoResolveHelper.resolveTask(task, activity, requestCode)
177+
return true
187178
}
188179

189180
fun onActivityResult(resultCode: Int, data: Intent?) {

java-sample/src/main/AndroidManifest.xml

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -35,13 +35,12 @@
3535
<activity android:name=".PaydirektInputActivity" />
3636
<activity android:name=".PaymentCredentialsListActivity" />
3737
<activity android:name=".PaymentOptionsActivity" />
38+
<activity android:name=".PaymentStatusActivity" />
3839
<activity android:name=".ProjectPaymentOptionsActivity" />
3940
<activity android:name=".CheckoutCustomerCardActivity" />
4041
<activity android:name=".CheckoutOfflineActivity" />
4142
<activity android:name=".CheckoutGatekeeperActivity" />
4243
<activity android:name=".CheckoutOnlineActivity" />
4344
<activity android:name=".CheckoutPOSActivity" />
44-
<activity android:name=".PaymentFailureActivity" />
45-
<activity android:name=".PaymentSuccessActivity" />
4645
</application>
4746
</manifest>

java-sample/src/main/java/io/snabble/testapp/BaseActivity.java

Lines changed: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,9 @@
1212

1313
import io.snabble.sdk.codes.ScannedCode;
1414
import io.snabble.sdk.ui.SnabbleUI;
15+
import io.snabble.sdk.ui.checkout.PaymentStatusView;
16+
import io.snabble.sdk.ui.integration.ProjectPaymentOptionsFragment;
17+
import io.snabble.sdk.ui.integration.SelfScanningFragment;
1518
import io.snabble.sdk.ui.integration.ZebraSupport;
1619
import io.snabble.sdk.ui.scanner.ProductResolver;
1720

@@ -125,11 +128,11 @@ public void execute(SnabbleUI.Action action, Bundle args) {
125128
case SHOW_CHECKOUT_POINT_OF_SALE:
126129
showCheckoutQRCodePOS();
127130
break;
128-
case SHOW_PAYMENT_FAILURE:
129-
showPaymentFailure();
131+
case SHOW_PAYMENT_STATUS:
132+
showPaymentStatus();
130133
break;
131-
case SHOW_PAYMENT_SUCCESS:
132-
showPaymentSuccess();
134+
case SHOW_PAYMENT_DONE:
135+
showPaymentDone();
133136
break;
134137
case SHOW_SEPA_CARD_INPUT:
135138
showSEPACardInput();
@@ -196,14 +199,14 @@ public void showCheckoutQRCodePOS() {
196199
startActivity(intent);
197200
}
198201

199-
public void showPaymentSuccess() {
200-
Intent intent = new Intent(this, PaymentSuccessActivity.class);
202+
public void showPaymentDone() {
203+
Intent intent = new Intent(this, MainActivity.class);
201204
intent.addFlags(Intent.FLAG_ACTIVITY_NO_HISTORY);
202205
startActivity(intent);
203206
}
204207

205-
public void showPaymentFailure() {
206-
Intent intent = new Intent(this, PaymentFailureActivity.class);
208+
public void showPaymentStatus() {
209+
Intent intent = new Intent(this, PaymentStatusActivity.class);
207210
intent.addFlags(Intent.FLAG_ACTIVITY_NO_HISTORY);
208211
startActivity(intent);
209212
}

java-sample/src/main/java/io/snabble/testapp/PaymentFailureActivity.java

Lines changed: 0 additions & 13 deletions
This file was deleted.
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
package io.snabble.testapp;
2+
3+
import androidx.fragment.app.Fragment;
4+
5+
import io.snabble.sdk.ui.integration.PaymentStatusFragment;
6+
7+
public class PaymentStatusActivity extends BaseActivity{
8+
@Override
9+
public Fragment onCreateFragment() {
10+
return new PaymentStatusFragment();
11+
}
12+
}
13+

0 commit comments

Comments
 (0)