Skip to content

Commit 5fc95ba

Browse files
authored
Merge pull request #15 from snabble/customer_number_billing
Customer number billing
2 parents 2ee3585 + 3f12b37 commit 5fc95ba

File tree

12 files changed

+152
-55
lines changed

12 files changed

+152
-55
lines changed

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

Lines changed: 40 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -2,43 +2,50 @@
22

33
import com.google.gson.annotations.SerializedName;
44

5+
import java.util.List;
6+
57
public enum PaymentMethod {
68
@SerializedName("qrCodePOS")
7-
QRCODE_POS(false, false, false, false),
9+
QRCODE_POS("qrCodePOS", false, false, false, false),
810
@SerializedName("qrCodeOffline")
9-
QRCODE_OFFLINE(true, false, false, false),
11+
QRCODE_OFFLINE("qrCodeOffline", true, false, false, false),
1012
@SerializedName("deDirectDebit")
11-
DE_DIRECT_DEBIT(false, true, false, true),
13+
DE_DIRECT_DEBIT("deDirectDebit", false, true, false, true),
1214
@SerializedName("creditCardVisa")
13-
VISA(false, true, false, true),
15+
VISA("creditCardVisa", false, true, false, true),
1416
@SerializedName("creditCardMastercard")
15-
MASTERCARD(false, true, false, true),
17+
MASTERCARD("creditCardMastercard", false, true, false, true),
1618
@SerializedName("creditCardAmericanExpress")
17-
AMEX(false, true, false, true),
19+
AMEX("creditCardAmericanExpress", false, true, false, true),
20+
@SerializedName("externalBilling")
21+
TEGUT_EMPLOYEE_CARD("externalBilling", false, true, true, true),
1822
@SerializedName("externalBilling")
19-
TEGUT_EMPLOYEE_CARD(false, true, true, true),
23+
LEINWEBER_CUSTOMER_ID("externalBilling", false, true, true, true),
2024
@SerializedName("customerCardPOS")
21-
CUSTOMERCARD_POS(false, false, false, false),
25+
CUSTOMERCARD_POS("customerCardPOS", false, false, false, false),
2226
@SerializedName("gatekeeperTerminal")
23-
GATEKEEPER_TERMINAL(false, false, false, false),
27+
GATEKEEPER_TERMINAL("gatekeeperTerminal", false, false, false, false),
2428
@SerializedName("paydirektOneKlick")
25-
PAYDIREKT(false, true, false, true),
29+
PAYDIREKT("paydirektOneKlick", false, true, false, true),
2630
@SerializedName("postFinanceCard")
27-
POST_FINANCE_CARD(false, true, false, true),
31+
POST_FINANCE_CARD("postFinanceCard", false, true, false, true),
2832
@SerializedName("twint")
29-
TWINT(false, true, false, true),
33+
TWINT("twint", false, true, false, true),
3034
@SerializedName("googlePay")
31-
GOOGLE_PAY(false, false, false, false);
35+
GOOGLE_PAY("googlePay", false, false, false, false);
3236

37+
private final String id;
3338
private final boolean requiresCredentials;
3439
private final boolean isOfflineMethod;
3540
private final boolean showOnlyIfCredentialsArePresent;
3641
private final boolean needsAbortConfirmation;
3742

38-
PaymentMethod(boolean isOfflineMethod,
43+
PaymentMethod(String id,
44+
boolean isOfflineMethod,
3945
boolean requiresCredentials,
4046
boolean showOnlyIfCredentialsArePresent,
4147
boolean needsAbortConfirmation) {
48+
this.id = id;
4249
this.isOfflineMethod = isOfflineMethod;
4350
this.requiresCredentials = requiresCredentials;
4451
this.showOnlyIfCredentialsArePresent = showOnlyIfCredentialsArePresent;
@@ -64,30 +71,32 @@ public boolean needsAbortConfirmation() {
6471
public static PaymentMethod fromString(String value) {
6572
PaymentMethod[] values = values();
6673
for (PaymentMethod pm : values) {
67-
try {
68-
SerializedName serializedName = PaymentMethod.class.getField(pm.name()).getAnnotation(SerializedName.class);
69-
if (serializedName != null) {
70-
String name = serializedName.value();
71-
if (name.equals(value)) {
72-
return pm;
73-
}
74-
}
75-
} catch (NoSuchFieldException e) {
76-
e.printStackTrace();
74+
if (pm.id.equals(value)) {
75+
return pm;
7776
}
7877
}
7978

8079
return null;
8180
}
82-
83-
public String id() {
84-
try {
85-
SerializedName serializedName = PaymentMethod.class.getField(name()).getAnnotation(SerializedName.class);
86-
if (serializedName != null) {
87-
return serializedName.value();
81+
public static PaymentMethod fromIdAndOrigin(String id, List<String> origin) {
82+
PaymentMethod[] values = values();
83+
for (PaymentMethod pm : values) {
84+
if(pm.id.equals(id) && pm.id.equals(TEGUT_EMPLOYEE_CARD.id)) {
85+
switch(origin.get(0)) {
86+
case "tegutEmployeeID":
87+
return TEGUT_EMPLOYEE_CARD;
88+
case "leinweberCustomerID":
89+
return LEINWEBER_CUSTOMER_ID;
90+
}
91+
} else if (pm.id.equals(id)) {
92+
return pm;
8893
}
89-
} catch (Exception ignored) {}
94+
}
9095

9196
return null;
9297
}
98+
99+
public String getId() {
100+
return id;
101+
}
93102
}

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

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,10 @@ data class PaymentMethodDescriptor(
44
val id: String,
55
val links: Map<String, Link>?,
66
val providerName: String,
7-
val acceptedOriginTypes: List<String>
7+
val acceptedOriginTypes: List<String>?
88
) {
99
val paymentMethod: PaymentMethod
10-
get() {
11-
return PaymentMethod.fromString(id)!!
12-
}
10+
get() = PaymentMethod.fromIdAndOrigin(id, acceptedOriginTypes)!!
1311
}
1412

1513
data class Link(

core/src/main/java/io/snabble/sdk/payment/PaymentCredentials.java

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@ public enum Type {
4848
CREDIT_CARD_PSD2(null, true, Arrays.asList(PaymentMethod.VISA, PaymentMethod.MASTERCARD, PaymentMethod.AMEX)),
4949
PAYDIREKT(null, false, Collections.singletonList(PaymentMethod.PAYDIREKT)),
5050
TEGUT_EMPLOYEE_CARD("tegutEmployeeID", false, Collections.singletonList(PaymentMethod.TEGUT_EMPLOYEE_CARD)),
51+
LEINWEBER_CUSTOMER_ID("leinweberCustomerID", false, Collections.singletonList(PaymentMethod.LEINWEBER_CUSTOMER_ID)),
5152
DATATRANS("datatransAlias", true, Arrays.asList(PaymentMethod.TWINT, PaymentMethod.POST_FINANCE_CARD)),
5253
DATATRANS_CREDITCARD("datatransCreditCardAlias", true, Arrays.asList(PaymentMethod.VISA, PaymentMethod.MASTERCARD, PaymentMethod.AMEX)),
5354
PAYONE_CREDITCARD(null, true, Arrays.asList(PaymentMethod.VISA, PaymentMethod.MASTERCARD, PaymentMethod.AMEX));
@@ -152,6 +153,10 @@ private static class TegutEmployeeCard {
152153
private String cardNumber;
153154
}
154155

156+
private static class LeinweberCustomerId {
157+
private String cardNumber;
158+
}
159+
155160
private String obfuscatedId;
156161
// comes from previously saved data on deserialization - was used in encrypt() from old code
157162
private boolean isKeyStoreEncrypted;
@@ -467,6 +472,41 @@ public static PaymentCredentials fromTegutEmployeeCard(String obfuscatedId, Stri
467472
return pc;
468473
}
469474

475+
public static PaymentCredentials fromLeinweberCustomerId(String obfuscatedId, String cardNumber, String projectId) {
476+
if (cardNumber == null || cardNumber.length() != 6) {
477+
return null;
478+
}
479+
480+
PaymentCredentials pc = new PaymentCredentials();
481+
pc.generateId();
482+
pc.type = Type.LEINWEBER_CUSTOMER_ID;
483+
484+
List<X509Certificate> certificates = Snabble.getInstance().getPaymentSigningCertificates();
485+
if (certificates.size() == 0) {
486+
return null;
487+
}
488+
489+
pc.obfuscatedId = obfuscatedId;
490+
491+
X509Certificate certificate = certificates.get(0);
492+
493+
LeinweberCustomerId data = new LeinweberCustomerId();
494+
data.cardNumber = cardNumber;
495+
String json = GsonHolder.get().toJson(data, LeinweberCustomerId.class);
496+
497+
pc.rsaEncryptedData = pc.rsaEncrypt(certificate, json.getBytes());
498+
pc.signature = pc.sha256Signature(certificate);
499+
pc.brand = Brand.UNKNOWN;
500+
pc.appId = Snabble.getInstance().getConfig().appId;
501+
pc.projectId = projectId;
502+
503+
if (pc.rsaEncryptedData == null) {
504+
return null;
505+
}
506+
507+
return pc;
508+
}
509+
470510
public Type getType() {
471511
if (type == null) { // backwards compatibility
472512
return Type.SEPA;
@@ -708,6 +748,8 @@ public PaymentMethod getPaymentMethod() {
708748
return PaymentMethod.DE_DIRECT_DEBIT;
709749
} else if (type == Type.TEGUT_EMPLOYEE_CARD) {
710750
return PaymentMethod.TEGUT_EMPLOYEE_CARD;
751+
} else if (type == Type.LEINWEBER_CUSTOMER_ID) {
752+
return PaymentMethod.LEINWEBER_CUSTOMER_ID;
711753
} else if (type == Type.PAYDIREKT) {
712754
return PaymentMethod.PAYDIREKT;
713755
} else if (type == Type.CREDIT_CARD_PSD2

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

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
import java.io.Serializable;
1313
import java.lang.ref.WeakReference;
1414
import java.util.ArrayList;
15+
import java.util.Arrays;
1516
import java.util.Collections;
1617
import java.util.HashMap;
1718
import java.util.HashSet;
@@ -77,6 +78,7 @@ private PaymentSelectionHelper() {
7778
icons.put(PaymentMethod.AMEX, R.drawable.snabble_ic_payment_select_amex);
7879
icons.put(PaymentMethod.PAYDIREKT, R.drawable.snabble_ic_payment_select_paydirekt);
7980
icons.put(PaymentMethod.TEGUT_EMPLOYEE_CARD, R.drawable.snabble_ic_payment_select_tegut);
81+
icons.put(PaymentMethod.LEINWEBER_CUSTOMER_ID, R.drawable.snabble_ic_payment_select_leinweber);
8082
icons.put(PaymentMethod.CUSTOMERCARD_POS, R.drawable.snabble_ic_payment_select_pos);
8183
icons.put(PaymentMethod.GATEKEEPER_TERMINAL, R.drawable.snabble_ic_payment_select_sco);
8284
icons.put(PaymentMethod.QRCODE_POS, R.drawable.snabble_ic_payment_select_pos);
@@ -91,6 +93,7 @@ private PaymentSelectionHelper() {
9193
names.put(PaymentMethod.AMEX, "American Express");
9294
names.put(PaymentMethod.PAYDIREKT, "Paydirekt");
9395
names.put(PaymentMethod.TEGUT_EMPLOYEE_CARD, "Tegut... Mitarbeiterkarte");
96+
names.put(PaymentMethod.LEINWEBER_CUSTOMER_ID, "Leinweber Rechnungskauf");
9497
names.put(PaymentMethod.GATEKEEPER_TERMINAL, context.getString(R.string.Snabble_Payment_payAtSCO));
9598
names.put(PaymentMethod.QRCODE_POS, context.getString(R.string.Snabble_Payment_payAtCashDesk));
9699
names.put(PaymentMethod.CUSTOMERCARD_POS, context.getString(R.string.Snabble_Payment_payAtCashDesk));
@@ -109,6 +112,7 @@ private PaymentSelectionHelper() {
109112
paymentMethodsSortPriority.add(PaymentMethod.PAYDIREKT);
110113
paymentMethodsSortPriority.add(PaymentMethod.GATEKEEPER_TERMINAL);
111114
paymentMethodsSortPriority.add(PaymentMethod.TEGUT_EMPLOYEE_CARD);
115+
paymentMethodsSortPriority.add(PaymentMethod.LEINWEBER_CUSTOMER_ID);
112116
paymentMethodsSortPriority.add(PaymentMethod.CUSTOMERCARD_POS);
113117
paymentMethodsSortPriority.add(PaymentMethod.QRCODE_POS);
114118
paymentMethodsSortPriority.add(PaymentMethod.QRCODE_OFFLINE);
@@ -228,7 +232,7 @@ private void updateGooglePayIsReadyToPay() {
228232
GooglePayHelper googlePayHelper = project.getGooglePayHelper();
229233
if (googlePayHelper != null) {
230234
for (CheckoutApi.PaymentMethodInfo info : availablePaymentMethods) {
231-
if (info.id.equals(PaymentMethod.GOOGLE_PAY.id())) {
235+
if (info.id.equals(PaymentMethod.GOOGLE_PAY.getId())) {
232236
googlePayHelper.setUseTestEnvironment(info.isTesting);
233237
break;
234238
}
@@ -293,7 +297,9 @@ private void updateEntries() {
293297

294298
List<PaymentMethod> availablePaymentMethodsList = new ArrayList<>();
295299
for (final CheckoutApi.PaymentMethodInfo paymentMethodInfo : availablePaymentMethods) {
296-
PaymentMethod paymentMethod = PaymentMethod.fromString(paymentMethodInfo.id);
300+
String[] origins = paymentMethodInfo.acceptedOriginTypes;
301+
if(origins == null) origins = new String[0];
302+
PaymentMethod paymentMethod = PaymentMethod.fromIdAndOrigin(paymentMethodInfo.id, Arrays.asList(origins));
297303
if (paymentMethod == PaymentMethod.GOOGLE_PAY && googlePayIsReady) {
298304
availablePaymentMethodsList.add(paymentMethod);
299305
} else if (paymentMethod != PaymentMethod.GOOGLE_PAY) {
@@ -304,8 +310,6 @@ private void updateEntries() {
304310
Set<PaymentMethod> addedCredentialPaymentMethods = new HashSet<>();
305311

306312
for (final PaymentCredentials pc : Snabble.getInstance().getPaymentCredentialsStore().getAllWithoutKeyStoreValidation()) {
307-
final Entry e = new Entry();
308-
309313
if (!pc.isAvailableInCurrentApp()) {
310314
continue;
311315
}
@@ -314,6 +318,7 @@ private void updateEntries() {
314318
continue;
315319
}
316320

321+
final Entry e = new Entry();
317322
e.paymentMethod = pc.getPaymentMethod();
318323
if (e.paymentMethod == null || !pc.isAvailableInCurrentApp()) {
319324
continue;
@@ -349,7 +354,7 @@ private void updateEntries() {
349354
continue;
350355
}
351356

352-
if (pm == PaymentMethod.TEGUT_EMPLOYEE_CARD) {
357+
if (pm.isShowOnlyIfCredentialsArePresent()) {
353358
continue;
354359
}
355360

Lines changed: 22 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,27 @@
11
package io.snabble.sdk.ui.payment
22

33
import io.snabble.sdk.PaymentMethod
4+
import io.snabble.sdk.PaymentMethodDescriptor
45
import io.snabble.sdk.ui.R
56

6-
fun PaymentMethod.icon() = when(this) {
7-
PaymentMethod.QRCODE_POS -> R.drawable.snabble_ic_payment_select_pos
8-
PaymentMethod.QRCODE_OFFLINE -> R.drawable.snabble_ic_payment_select_pos
9-
PaymentMethod.DE_DIRECT_DEBIT -> R.drawable.snabble_ic_payment_select_sepa
10-
PaymentMethod.VISA -> R.drawable.snabble_ic_payment_select_visa
11-
PaymentMethod.MASTERCARD -> R.drawable.snabble_ic_mastercard
12-
PaymentMethod.AMEX -> R.drawable.snabble_ic_amex
13-
PaymentMethod.POST_FINANCE_CARD -> R.drawable.snabble_ic_payment_select_postfinance
14-
PaymentMethod.TWINT -> R.drawable.snabble_ic_payment_select_twint
15-
PaymentMethod.TEGUT_EMPLOYEE_CARD -> R.drawable.snabble_ic_payment_select_tegut
16-
PaymentMethod.CUSTOMERCARD_POS -> R.drawable.snabble_ic_payment_select_pos
17-
PaymentMethod.GATEKEEPER_TERMINAL -> R.drawable.snabble_ic_payment_select_sco
18-
PaymentMethod.PAYDIREKT -> R.drawable.snabble_ic_payment_select_paydirekt
19-
PaymentMethod.GOOGLE_PAY -> R.drawable.snabble_ic_payment_select_gpay
20-
}
7+
val PaymentMethodDescriptor.icon: Int
8+
get() = when(id) {
9+
PaymentMethod.QRCODE_POS.id -> R.drawable.snabble_ic_payment_select_pos
10+
PaymentMethod.QRCODE_OFFLINE.id -> R.drawable.snabble_ic_payment_select_pos
11+
PaymentMethod.DE_DIRECT_DEBIT.id -> R.drawable.snabble_ic_payment_select_sepa
12+
PaymentMethod.VISA.id -> R.drawable.snabble_ic_payment_select_visa
13+
PaymentMethod.MASTERCARD.id -> R.drawable.snabble_ic_mastercard
14+
PaymentMethod.AMEX.id -> R.drawable.snabble_ic_amex
15+
PaymentMethod.POST_FINANCE_CARD.id -> R.drawable.snabble_ic_payment_select_postfinance
16+
PaymentMethod.TWINT.id -> R.drawable.snabble_ic_payment_select_twint
17+
PaymentMethod.CUSTOMERCARD_POS.id -> R.drawable.snabble_ic_payment_select_pos
18+
PaymentMethod.GATEKEEPER_TERMINAL.id -> R.drawable.snabble_ic_payment_select_sco
19+
PaymentMethod.PAYDIREKT.id -> R.drawable.snabble_ic_payment_select_paydirekt
20+
PaymentMethod.GOOGLE_PAY.id -> R.drawable.snabble_ic_payment_select_gpay
21+
"externalBilling" -> when(acceptedOriginTypes?.first()) {
22+
"tegutEmployeeID" -> R.drawable.snabble_ic_payment_select_tegut
23+
"leinweberCustomerID" -> R.drawable.snabble_ic_payment_select_leinweber
24+
else -> 0
25+
}
26+
else -> 0
27+
}
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
<vector xmlns:android="http://schemas.android.com/apk/res/android"
2+
android:width="24dp"
3+
android:height="24dp"
4+
android:viewportWidth="24"
5+
android:viewportHeight="24">
6+
<path
7+
android:pathData="M4,0L20,0A4,4 0,0 1,24 4L24,20A4,4 0,0 1,20 24L4,24A4,4 0,0 1,0 20L0,4A4,4 0,0 1,4 0z"
8+
android:fillColor="#fff"/>
9+
<path
10+
android:pathData="m17.3078,18.8811 l-10.3078,0.0481 2.1601,-13.9255 4.3469,-0.0037 -1.6462,10.6612 5.9396,0.0185z"
11+
android:fillColor="#003b93"/>
12+
</vector>
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
<vector xmlns:android="http://schemas.android.com/apk/res/android"
2+
android:width="24dp"
3+
android:height="24dp"
4+
android:viewportWidth="24"
5+
android:viewportHeight="24">
6+
<path
7+
android:pathData="M4,0L20,0A4,4 0,0 1,24 4L24,20A4,4 0,0 1,20 24L4,24A4,4 0,0 1,0 20L0,4A4,4 0,0 1,4 0z"
8+
android:fillColor="#003b93"/>
9+
<path
10+
android:pathData="m17.3078,18.8811 l-10.3078,0.0481 2.1601,-13.9255 4.3469,-0.0037 -1.6462,10.6612 5.9396,0.0185z"
11+
android:fillColor="#fff"/>
12+
</vector>

ui/src/main/res/values-de/strings.xml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,7 @@
8989
<string name="Snabble.Payment.PostFinanceCard.error">Bei der Verarbeitung deiner Postfinance-Card ist ein Fehler aufgetreten</string>
9090
<string name="Snabble.Payment.presentCode">Halte diesen Code an einem Snabble-Monitor vor oder zeige ihn einem Mitarbeiter, um deinen Einkauf zu bestätigen.</string>
9191
<string name="Snabble.Payment.rejected">Einkauf abgelehnt</string>
92+
<string name="Snabble.Payment.rejectedHint">Dein Einkauf wurde abgelehnt. Bitte überprüfe deinen Warenkorb und starte den Bezahlvorgang erneut.</string>
9293
<string name="Snabble.Payment.SEPA.hint">Hinweis: Um dich und unsere Händler vor Missbrauch zu schützen, wird sich der Händler bei deiner ersten Zahlung per SEPA-Lastschrift deine Bankkarte zeigen lassen.</string>
9394
<string name="Snabble.Payment.SEPA.IBAN">IBAN</string>
9495
<string name="Snabble.Payment.SEPA.InvalidIBAN">Die eingegebene IBAN ist ungültig.</string>
@@ -124,6 +125,7 @@
124125
<string name="Snabble.PaymentStatus.AddDebitCard.message">Möchtest du die Daten deiner girocard sicher in der App speichern, um deinen nächsten Einkauf per Lastschrift zu bezahlen? Die Karte kannst du zukünftig im Geldbeutel lassen.</string>
125126
<string name="Snabble.PaymentStatus.back">Zurück</string>
126127
<string name="Snabble.PaymentStatus.close">Schließen</string>
128+
<string name="Snabble.PaymentStatus.DebitCardAdded.message">Wir haben deine Karte erfolgreich verifiziert. Ab sofort kannst du per SEPA-Lastschrift bezahlen. Deine girocard kannst du zukünftig im Geldbeutel lassen.</string>
127129
<string name="Snabble.PaymentStatus.ExitCode.title">Ausgangs-Code</string>
128130
<string name="Snabble.PaymentStatus.Fulfillment.title">Lieferung</string>
129131
<string name="Snabble.PaymentStatus.Payment.error">Deine Zahlung konnte nicht durchgeführt werden. Versuche es erneut oder wähle ein anderes Bezahlverfahren.</string>

ui/src/main/res/values-en/strings.xml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,7 @@
8989
<string name="Snabble.Payment.PostFinanceCard.error">There was an error processing your postfinance card</string>
9090
<string name="Snabble.Payment.presentCode">Show this code at a Snabble monitor or to a cashier to confirm your purchase.</string>
9191
<string name="Snabble.Payment.rejected">Purchase denied</string>
92+
<string name="Snabble.Payment.rejectedHint">Your purchase was denied. Please check your cart and start the checkout again.</string>
9293
<string name="Snabble.Payment.SEPA.hint">Note: In order to protect you and our merchants against misuse, the merchant will have your bank card shown on your first payment by SEPA direct debit.</string>
9394
<string name="Snabble.Payment.SEPA.IBAN">IBAN</string>
9495
<string name="Snabble.Payment.SEPA.InvalidIBAN">Please enter a valid IBAN.</string>
@@ -124,6 +125,7 @@
124125
<string name="Snabble.PaymentStatus.AddDebitCard.message">Would you like to store your girocard data securely in the app so that you can pay for your next purchase by direct debit? You can leave your card in your wallet in the future.</string>
125126
<string name="Snabble.PaymentStatus.back">Back</string>
126127
<string name="Snabble.PaymentStatus.close">Close</string>
128+
<string name="Snabble.PaymentStatus.DebitCardAdded.message">We have successfully verified your card. You can now pay by SEPA direct debit. You can leave your girocard in your wallet in the future.</string>
127129
<string name="Snabble.PaymentStatus.ExitCode.title">Exit-Code</string>
128130
<string name="Snabble.PaymentStatus.Fulfillment.title">Fulfillment</string>
129131
<string name="Snabble.PaymentStatus.Payment.error">Your payment could not be processed. Try again or choose another payment method.</string>

0 commit comments

Comments
 (0)