Skip to content

Commit a525e44

Browse files
cmaierFabtron
andauthored
Refactor payment method meta data and add a qr code generator (#154)
- Slightly refactor PaymentSelectionHelper.java and add QrCodeGenerator - Add logging extensions - Remove logging class from ui-toolkit --------- Co-authored-by: Fabian Bender <[email protected]>
1 parent b9b24ea commit a525e44

File tree

6 files changed

+150
-70
lines changed

6 files changed

+150
-70
lines changed

core/src/main/java/io/snabble/sdk/Environment.kt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ package io.snabble.sdk
33
/**
44
* Enum describing the environment the app is using
55
*/
6-
enum class Environment(domain: String) {
6+
enum class Environment(val domain: String) {
77
TESTING("snabble-testing.io"),
88
STAGING("snabble-staging.io"),
99
PRODUCTION("snabble.io");
@@ -31,4 +31,4 @@ enum class Environment(domain: String) {
3131
return TESTING
3232
}
3333
}
34-
}
34+
}

ui-toolkit/src/main/kotlin/io/snabble/sdk/utils/Logging.kt renamed to core/src/main/java/io/snabble/sdk/extensions/Logging.kt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
1-
package io.snabble.sdk.utils
1+
package io.snabble.sdk.extensions
22

33
import android.util.Log
44

55
@Deprecated("Only for debugging", replaceWith = ReplaceWith("this"))
66
fun <T> T.xx(msg: String? = null, tag: String = "xx", throwable: Throwable? = null): T {
7-
Log.d(tag, "${msg ?: ""} <$this>", throwable)
7+
Log.d(tag, "${msg ?: ""}<$this>", throwable)
88
return this
99
}
1010

ui/src/main/java/io/snabble/sdk/ui/cart/PaymentSelectionHelper.java

Lines changed: 17 additions & 66 deletions
Original file line numberDiff line numberDiff line change
@@ -10,14 +10,14 @@
1010
import androidx.lifecycle.LiveData;
1111
import androidx.lifecycle.MutableLiveData;
1212

13+
import org.jetbrains.annotations.NotNull;
14+
1315
import java.io.Serializable;
1416
import java.lang.ref.WeakReference;
1517
import java.util.ArrayList;
1618
import java.util.Collections;
17-
import java.util.HashMap;
1819
import java.util.HashSet;
1920
import java.util.List;
20-
import java.util.Map;
2121
import java.util.Set;
2222

2323
import io.snabble.sdk.PaymentMethod;
@@ -29,6 +29,7 @@
2929
import io.snabble.sdk.payment.PaymentCredentials;
3030
import io.snabble.sdk.payment.PaymentCredentialsStore;
3131
import io.snabble.sdk.ui.R;
32+
import io.snabble.sdk.ui.payment.PaymentMethodMetaDataHelper;
3233
import io.snabble.sdk.utils.GsonHolder;
3334

3435
public class PaymentSelectionHelper {
@@ -41,17 +42,13 @@ public static PaymentSelectionHelper getInstance() {
4142
public static class Entry implements Serializable {
4243
String text;
4344
String hint;
44-
transient int iconResId;
45+
public transient int iconResId;
4546
public PaymentCredentials paymentCredentials;
4647
public PaymentMethod paymentMethod;
4748
boolean isAvailable;
4849
boolean isAdded = true;
4950
}
5051

51-
private final Map<PaymentMethod, Integer> icons = new HashMap<>();
52-
private final Map<PaymentMethod, String> names = new HashMap<>();
53-
private final List<PaymentMethod> paymentMethodsSortPriority = new ArrayList<>();
54-
5552
private final Application application;
5653
private final MutableLiveData<Entry> selectedEntry;
5754
private Project project;
@@ -63,6 +60,9 @@ public static class Entry implements Serializable {
6360
private PaymentCredentials lastAddedPaymentCredentials;
6461
private boolean googlePayIsReady = false;
6562

63+
@NotNull
64+
private PaymentMethodMetaDataHelper metaDataHelper;
65+
6666
private final ShoppingCart.ShoppingCartListener shoppingCartListener =
6767
new ShoppingCart.SimpleShoppingCartListener() {
6868
@Override
@@ -74,56 +74,7 @@ public void onChanged(ShoppingCart list) {
7474
private PaymentSelectionHelper() {
7575
application = Snabble.getInstance().getApplication();
7676

77-
icons.put(PaymentMethod.DE_DIRECT_DEBIT, R.drawable.snabble_ic_payment_select_sepa);
78-
icons.put(PaymentMethod.VISA, R.drawable.snabble_ic_payment_select_visa);
79-
icons.put(PaymentMethod.MASTERCARD, R.drawable.snabble_ic_payment_select_mastercard);
80-
icons.put(PaymentMethod.AMEX, R.drawable.snabble_ic_payment_select_amex);
81-
icons.put(PaymentMethod.PAYDIREKT, R.drawable.snabble_ic_payment_select_paydirekt);
82-
icons.put(PaymentMethod.TEGUT_EMPLOYEE_CARD, R.drawable.snabble_ic_payment_select_tegut);
83-
icons.put(PaymentMethod.LEINWEBER_CUSTOMER_ID, R.drawable.snabble_ic_payment_select_leinweber);
84-
icons.put(PaymentMethod.CUSTOMERCARD_POS, R.drawable.snabble_ic_payment_select_pos);
85-
icons.put(PaymentMethod.GATEKEEPER_TERMINAL, R.drawable.snabble_ic_payment_select_sco);
86-
icons.put(PaymentMethod.QRCODE_POS, R.drawable.snabble_ic_payment_select_pos);
87-
icons.put(PaymentMethod.QRCODE_OFFLINE, R.drawable.snabble_ic_payment_select_pos);
88-
icons.put(PaymentMethod.POST_FINANCE_CARD, R.drawable.snabble_ic_payment_select_postfinance);
89-
icons.put(PaymentMethod.TWINT, R.drawable.snabble_ic_payment_select_twint);
90-
icons.put(PaymentMethod.GOOGLE_PAY, R.drawable.snabble_ic_payment_select_gpay);
91-
icons.put(PaymentMethod.PAYONE_SEPA, R.drawable.snabble_ic_payment_select_sepa);
92-
icons.put(PaymentMethod.EXTERNAL_BILLING, R.drawable.ic_snabble_external_billing);
93-
94-
names.put(PaymentMethod.DE_DIRECT_DEBIT, "SEPA-Lastschrift");
95-
names.put(PaymentMethod.VISA, "VISA");
96-
names.put(PaymentMethod.MASTERCARD, "Mastercard");
97-
names.put(PaymentMethod.AMEX, "American Express");
98-
names.put(PaymentMethod.PAYDIREKT, "Paydirekt");
99-
names.put(PaymentMethod.TEGUT_EMPLOYEE_CARD, "Tegut... Mitarbeiterkarte");
100-
names.put(PaymentMethod.LEINWEBER_CUSTOMER_ID, "Leinweber Rechnungskauf");
101-
names.put(PaymentMethod.GATEKEEPER_TERMINAL, application.getString(R.string.Snabble_Payment_payAtSCO));
102-
names.put(PaymentMethod.QRCODE_POS, application.getString(R.string.Snabble_Payment_payAtCashDesk));
103-
names.put(PaymentMethod.CUSTOMERCARD_POS, application.getString(R.string.Snabble_Payment_payAtCashDesk));
104-
names.put(PaymentMethod.QRCODE_OFFLINE, application.getString(R.string.Snabble_Payment_payAtCashDesk));
105-
names.put(PaymentMethod.POST_FINANCE_CARD, "PostFinance Card");
106-
names.put(PaymentMethod.TWINT, "Twint");
107-
names.put(PaymentMethod.GOOGLE_PAY, "Google Pay");
108-
names.put(PaymentMethod.PAYONE_SEPA, "SEPA-Lastschrift");
109-
names.put(PaymentMethod.EXTERNAL_BILLING, application.getString(R.string.Snabble_Payment_ExternalBilling_title));
110-
111-
paymentMethodsSortPriority.add(PaymentMethod.GOOGLE_PAY);
112-
paymentMethodsSortPriority.add(PaymentMethod.DE_DIRECT_DEBIT);
113-
paymentMethodsSortPriority.add(PaymentMethod.VISA);
114-
paymentMethodsSortPriority.add(PaymentMethod.MASTERCARD);
115-
paymentMethodsSortPriority.add(PaymentMethod.AMEX);
116-
paymentMethodsSortPriority.add(PaymentMethod.TWINT);
117-
paymentMethodsSortPriority.add(PaymentMethod.POST_FINANCE_CARD);
118-
paymentMethodsSortPriority.add(PaymentMethod.PAYDIREKT);
119-
paymentMethodsSortPriority.add(PaymentMethod.PAYONE_SEPA);
120-
paymentMethodsSortPriority.add(PaymentMethod.GATEKEEPER_TERMINAL);
121-
paymentMethodsSortPriority.add(PaymentMethod.EXTERNAL_BILLING);
122-
paymentMethodsSortPriority.add(PaymentMethod.TEGUT_EMPLOYEE_CARD);
123-
paymentMethodsSortPriority.add(PaymentMethod.LEINWEBER_CUSTOMER_ID);
124-
paymentMethodsSortPriority.add(PaymentMethod.CUSTOMERCARD_POS);
125-
paymentMethodsSortPriority.add(PaymentMethod.QRCODE_POS);
126-
paymentMethodsSortPriority.add(PaymentMethod.QRCODE_OFFLINE);
77+
metaDataHelper = new PaymentMethodMetaDataHelper(application);
12778

12879
selectedEntry = new MutableLiveData<>();
12980

@@ -185,7 +136,7 @@ private void update() {
185136
Entry lastEntry = null;
186137
if (last != null) {
187138
lastEntry = GsonHolder.get().fromJson(last, Entry.class);
188-
Integer iconResId = icons.get(lastEntry.paymentMethod);
139+
Integer iconResId = metaDataHelper.iconFor(lastEntry.paymentMethod);
189140
if (iconResId != null) {
190141
lastEntry.iconResId = iconResId;
191142
}
@@ -292,11 +243,11 @@ private void updateEntries() {
292243
for (PaymentMethod paymentMethod : projectPaymentMethods) {
293244
if (paymentMethod.isOfflineMethod()) {
294245
final Entry e = new Entry();
295-
e.text = names.get(paymentMethod);
246+
e.text = metaDataHelper.labelFor(paymentMethod);
296247
e.paymentMethod = paymentMethod;
297248
e.isAvailable = true;
298249

299-
Integer iconResId = icons.get(paymentMethod);
250+
Integer iconResId = metaDataHelper.iconFor(paymentMethod);
300251
if (iconResId != null) {
301252
e.iconResId = iconResId;
302253
entries.add(e);
@@ -338,7 +289,7 @@ private void updateEntries() {
338289
continue;
339290
}
340291

341-
e.text = names.get(e.paymentMethod);
292+
e.text = metaDataHelper.labelFor(e.paymentMethod);
342293
e.paymentCredentials = pc;
343294

344295
if (availablePaymentMethodsList.contains(e.paymentMethod)) {
@@ -356,7 +307,7 @@ private void updateEntries() {
356307
continue;
357308
}
358309

359-
Integer iconResId = icons.get(e.paymentMethod);
310+
Integer iconResId = metaDataHelper.iconFor(e.paymentMethod);
360311
if (iconResId != null) {
361312
e.iconResId = iconResId;
362313
entries.add(e);
@@ -383,7 +334,7 @@ private void updateEntries() {
383334

384335
final Entry e = new Entry();
385336

386-
e.text = names.get(pm);
337+
e.text = metaDataHelper.labelFor(pm);
387338
e.paymentMethod = pm;
388339
e.isAvailable = true;
389340
e.isAdded = !pm.isRequiringCredentials();
@@ -392,16 +343,16 @@ private void updateEntries() {
392343
e.hint = application.getString(R.string.Snabble_Shoppingcart_noPaymentData);
393344
}
394345

395-
Integer iconResId = icons.get(pm);
346+
Integer iconResId = metaDataHelper.iconFor(pm);
396347
if (iconResId != null) {
397348
e.iconResId = iconResId;
398349
entries.add(e);
399350
}
400351
}
401352

402353
Collections.sort(entries, (o1, o2) -> {
403-
int p1 = paymentMethodsSortPriority.indexOf(o1.paymentMethod);
404-
int p2 = paymentMethodsSortPriority.indexOf(o2.paymentMethod);
354+
int p1 = metaDataHelper.indexOf(o1.paymentMethod);
355+
int p2 = metaDataHelper.indexOf(o2.paymentMethod);
405356

406357
return Integer.compare(p1, p2);
407358
});
Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
package io.snabble.sdk.ui.payment
2+
3+
import android.content.Context
4+
import androidx.annotation.DrawableRes
5+
import io.snabble.sdk.PaymentMethod
6+
import io.snabble.sdk.PaymentMethod.AMEX
7+
import io.snabble.sdk.PaymentMethod.CUSTOMERCARD_POS
8+
import io.snabble.sdk.PaymentMethod.DE_DIRECT_DEBIT
9+
import io.snabble.sdk.PaymentMethod.EXTERNAL_BILLING
10+
import io.snabble.sdk.PaymentMethod.GATEKEEPER_TERMINAL
11+
import io.snabble.sdk.PaymentMethod.GOOGLE_PAY
12+
import io.snabble.sdk.PaymentMethod.LEINWEBER_CUSTOMER_ID
13+
import io.snabble.sdk.PaymentMethod.MASTERCARD
14+
import io.snabble.sdk.PaymentMethod.PAYDIREKT
15+
import io.snabble.sdk.PaymentMethod.PAYONE_SEPA
16+
import io.snabble.sdk.PaymentMethod.POST_FINANCE_CARD
17+
import io.snabble.sdk.PaymentMethod.QRCODE_OFFLINE
18+
import io.snabble.sdk.PaymentMethod.QRCODE_POS
19+
import io.snabble.sdk.PaymentMethod.TEGUT_EMPLOYEE_CARD
20+
import io.snabble.sdk.PaymentMethod.TWINT
21+
import io.snabble.sdk.PaymentMethod.VISA
22+
import io.snabble.sdk.ui.R.drawable.ic_snabble_external_billing
23+
import io.snabble.sdk.ui.R.drawable.snabble_ic_payment_select_amex
24+
import io.snabble.sdk.ui.R.drawable.snabble_ic_payment_select_gpay
25+
import io.snabble.sdk.ui.R.drawable.snabble_ic_payment_select_leinweber
26+
import io.snabble.sdk.ui.R.drawable.snabble_ic_payment_select_mastercard
27+
import io.snabble.sdk.ui.R.drawable.snabble_ic_payment_select_paydirekt
28+
import io.snabble.sdk.ui.R.drawable.snabble_ic_payment_select_pos
29+
import io.snabble.sdk.ui.R.drawable.snabble_ic_payment_select_postfinance
30+
import io.snabble.sdk.ui.R.drawable.snabble_ic_payment_select_sco
31+
import io.snabble.sdk.ui.R.drawable.snabble_ic_payment_select_sepa
32+
import io.snabble.sdk.ui.R.drawable.snabble_ic_payment_select_tegut
33+
import io.snabble.sdk.ui.R.drawable.snabble_ic_payment_select_twint
34+
import io.snabble.sdk.ui.R.drawable.snabble_ic_payment_select_visa
35+
import io.snabble.sdk.ui.R.string.Snabble_Payment_ExternalBilling_title
36+
import io.snabble.sdk.ui.R.string.Snabble_Payment_payAtCashDesk
37+
import io.snabble.sdk.ui.R.string.Snabble_Payment_payAtSCO
38+
39+
class PaymentMethodMetaDataHelper(
40+
val context: Context
41+
) {
42+
43+
private val paymentMethodsMetaData: Map<PaymentMethod, PaymentMethodMetaData> = mapOf(
44+
GOOGLE_PAY withMeta ("Google Pay" to snabble_ic_payment_select_gpay),
45+
DE_DIRECT_DEBIT withMeta ("SEPA-Lastschrift" to snabble_ic_payment_select_sepa),
46+
VISA withMeta ("VISA" to snabble_ic_payment_select_visa),
47+
MASTERCARD withMeta ("Mastercard" to snabble_ic_payment_select_mastercard),
48+
AMEX withMeta ("American Express" to snabble_ic_payment_select_amex),
49+
TWINT withMeta ("Twint" to snabble_ic_payment_select_twint),
50+
POST_FINANCE_CARD withMeta ("PostFinance Card" to snabble_ic_payment_select_postfinance),
51+
PAYDIREKT withMeta ("Paydirekt" to snabble_ic_payment_select_paydirekt),
52+
PAYONE_SEPA withMeta ("SEPA-Lastschrift" to snabble_ic_payment_select_sepa),
53+
GATEKEEPER_TERMINAL withMeta (Snabble_Payment_payAtSCO.resolved to snabble_ic_payment_select_sco),
54+
EXTERNAL_BILLING withMeta (Snabble_Payment_ExternalBilling_title.resolved to ic_snabble_external_billing),
55+
TEGUT_EMPLOYEE_CARD withMeta ("Tegut... Mitarbeiterkarte" to snabble_ic_payment_select_tegut),
56+
LEINWEBER_CUSTOMER_ID withMeta ("Leinweber Rechnungskauf" to snabble_ic_payment_select_leinweber),
57+
CUSTOMERCARD_POS withMeta (Snabble_Payment_payAtCashDesk.resolved to snabble_ic_payment_select_pos),
58+
QRCODE_POS withMeta (Snabble_Payment_payAtCashDesk.resolved to snabble_ic_payment_select_pos),
59+
QRCODE_OFFLINE withMeta (Snabble_Payment_payAtCashDesk.resolved to snabble_ic_payment_select_pos),
60+
)
61+
62+
@DrawableRes
63+
fun iconFor(paymentMethod: PaymentMethod): Int? = paymentMethodsMetaData[paymentMethod]?.iconResId
64+
65+
fun labelFor(paymentMethod: PaymentMethod): String? = paymentMethodsMetaData[paymentMethod]?.label
66+
67+
fun indexOf(paymentMethod: PaymentMethod): Int = paymentMethodsMetaData.keys.indexOf(paymentMethod)
68+
69+
private val Int.resolved: String get() = context.getString(this)
70+
71+
private infix fun <T> T.withMeta(that: Pair<String, Int>): Pair<T, PaymentMethodMetaData> =
72+
Pair(this, PaymentMethodMetaData(iconResId = that.second, label = that.first))
73+
}
74+
75+
data class PaymentMethodMetaData(
76+
@DrawableRes val iconResId: Int,
77+
val label: String
78+
)

utils/build.gradle.kts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,7 @@ dependencies {
6363
implementation(libs.gson)
6464
implementation(libs.squareup.okhttp3.okhttp)
6565
implementation(libs.squareup.okhttp3.tls)
66+
implementation(libs.google.zxing.core)
6667

6768
// for testing
6869
testImplementation(libs.junit)
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
package io.snabble.sdk.utils
2+
3+
import android.graphics.Bitmap
4+
import android.graphics.Color
5+
import com.google.zxing.BarcodeFormat
6+
import com.google.zxing.EncodeHintType
7+
import com.google.zxing.qrcode.QRCodeWriter
8+
import com.google.zxing.qrcode.decoder.ErrorCorrectionLevel
9+
10+
class QrCodeGenerator {
11+
12+
fun generateQrCodeFrom(token: String): Bitmap {
13+
val hintMap: Map<EncodeHintType, Any> = mapOf(
14+
EncodeHintType.ERROR_CORRECTION to ErrorCorrectionLevel.L,
15+
EncodeHintType.MARGIN to 0
16+
)
17+
val qrCodeWriter = QRCodeWriter()
18+
val bitMapMatrix = qrCodeWriter.encode(
19+
token,
20+
BarcodeFormat.QR_CODE,
21+
QR_CODE_WIDTH,
22+
QR_CODE_HEIGHT,
23+
hintMap
24+
)
25+
26+
val width = bitMapMatrix.width
27+
val height = bitMapMatrix.height
28+
29+
val pixels = IntArray(width * height)
30+
for (y in 0 until height) {
31+
for (x in 0 until width) {
32+
pixels[y * width + x] =
33+
if (bitMapMatrix.get(x, y)) Color.BLACK else Color.TRANSPARENT
34+
}
35+
}
36+
37+
val bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888)
38+
bitmap.setPixels(pixels, 0, width, 0, 0, width, height)
39+
return bitmap
40+
}
41+
42+
companion object {
43+
44+
private const val QR_CODE_WIDTH = 400
45+
private const val QR_CODE_HEIGHT = 400
46+
47+
fun generateQrCode(token: String) =
48+
QrCodeGenerator().generateQrCodeFrom(token)
49+
}
50+
}

0 commit comments

Comments
 (0)