Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 26 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,32 @@
# Changelog
All notable changes to this project will be documented in this file.

## [0.33.0-beta04]

### Changes
- Mark all kotlin fragments as open

## [0.33.0-beta03]

### Changes
- Small bugfixes

## [0.33.0-beta02]

### Fixed
- PaymentOptionsView not always updating
- Improved layout of PaymentOptionsView

## [0.33.0-beta01]

### Breaking Changes
- Added support for PSD2 credit cards. This requires that existing credit cards are invalidated, which
can be checked using PaymentCredentialsStore.hasRemovedOldCreditCards()
- 2 new views and there respective fragments related to the new credit card flow have been added: PaymentOptionsView and ProjectPaymentOptionsView.
ProjectCredentialsListView should not be used as a Overview anymore, the new recommended entry point is now PaymentOptionsView.
- SnabbleUI.Callback now provides data as a Bundle. This bundle is mostly used for fragment arguments.
- EVENT_PRODUCT_CONFIRMATION_HIDE now provides its ShoppingCart.Item in the Bundle as a Serializable "cartItem".

## [0.32.11]

### Fixed
Expand Down
4 changes: 2 additions & 2 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ buildscript {

dependencies {
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
classpath 'com.android.tools.build:gradle:4.1.1'
classpath 'com.android.tools.build:gradle:4.1.2'
classpath 'gradle.plugin.com.github.jlouns:gradle-cross-platform-exec-plugin:0.5.0'
classpath "gradle.plugin.gmazzo:sqlite-plugin:0.2"
}
Expand All @@ -29,7 +29,7 @@ allprojects {
}

project.ext {
sdkVersion='0.32.11'
sdkVersion='0.33.0-beta04'
versionCode=1

compileSdkVersion=30
Expand Down
6 changes: 5 additions & 1 deletion core/src/main/java/io/snabble/sdk/Brand.kt
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,8 @@ package io.snabble.sdk
data class Brand(
val id: String,
val name: String,
)
) : Comparable<Brand> {
override fun compareTo(other: Brand) = compareValuesBy(this, other,
{ it.id },
)
}
2 changes: 1 addition & 1 deletion core/src/main/java/io/snabble/sdk/CheckoutApi.java
Original file line number Diff line number Diff line change
Expand Up @@ -491,7 +491,7 @@ public void createPaymentProcess(final String id,
checkoutProcessRequest.paymentInformation.originType = paymentCredentials.getType().getOriginType();
checkoutProcessRequest.paymentInformation.encryptedOrigin = data;

if (paymentCredentials.getType() == PaymentCredentials.Type.CREDIT_CARD) {
if (paymentCredentials.getType() == PaymentCredentials.Type.CREDIT_CARD_PSD2) {
Date date = new Date(paymentCredentials.getValidTo());
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy/MM/dd");
checkoutProcessRequest.paymentInformation.validUntil = simpleDateFormat.format(date);
Expand Down
4 changes: 4 additions & 0 deletions core/src/main/java/io/snabble/sdk/Project.java
Original file line number Diff line number Diff line change
Expand Up @@ -354,6 +354,10 @@ public String getProductByCodeUrl() {
return urls.get("resolvedProductLookUp");
}

public String getTelecashVaultItemsUrl() {
return urls.get("telecashVaultItems");
}

public BarcodeFormat[] getSupportedBarcodeFormats() {
return supportedBarcodeFormats;
}
Expand Down
58 changes: 45 additions & 13 deletions core/src/main/java/io/snabble/sdk/payment/PaymentCredentials.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

import android.util.Base64;

import androidx.annotation.Nullable;

import java.io.InputStream;
import java.security.cert.CertPath;
import java.security.cert.CertPathValidator;
Expand All @@ -13,7 +15,6 @@
import java.security.cert.X509Certificate;
import java.security.spec.AlgorithmParameterSpec;
import java.security.spec.MGF1ParameterSpec;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;

Expand All @@ -22,6 +23,7 @@
import javax.crypto.spec.PSource;

import io.snabble.sdk.PaymentMethod;
import io.snabble.sdk.Project;
import io.snabble.sdk.R;
import io.snabble.sdk.Snabble;
import io.snabble.sdk.utils.GsonHolder;
Expand All @@ -30,20 +32,28 @@

public class PaymentCredentials {
public enum Type {
SEPA(null),
CREDIT_CARD(null),
PAYDIREKT(null),
TEGUT_EMPLOYEE_CARD("tegutEmployeeID");
SEPA(null, Collections.singletonList(PaymentMethod.DE_DIRECT_DEBIT)),
// legacy credit card type, not used anymore.
CREDIT_CARD(null, Arrays.asList(PaymentMethod.VISA, PaymentMethod.MASTERCARD, PaymentMethod.AMEX)),
CREDIT_CARD_PSD2(null, Arrays.asList(PaymentMethod.VISA, PaymentMethod.MASTERCARD, PaymentMethod.AMEX)),
PAYDIREKT(null, Collections.singletonList(PaymentMethod.PAYDIREKT)),
TEGUT_EMPLOYEE_CARD("tegutEmployeeID", Collections.singletonList(PaymentMethod.TEGUT_EMPLOYEE_CARD));

private String originType;
private List<PaymentMethod> paymentMethods;

Type(String originType) {
Type(String originType, List<PaymentMethod> paymentMethods) {
this.originType = originType;
this.paymentMethods = paymentMethods;
}

public String getOriginType() {
return originType;
}

public List<PaymentMethod> getPaymentMethods() {
return paymentMethods;
}
}

public enum Brand {
Expand All @@ -60,6 +70,8 @@ private static class SepaData {

private static class CreditCardData {
private String hostedDataID;
private String schemeTransactionID;
private String projectID;
private String hostedDataStoreID;
private String cardType;
}
Expand Down Expand Up @@ -94,6 +106,7 @@ private static class TegutEmployeeCard {
private Brand brand;
private String appId;
private String id;
private String projectId;
private Map<String, String> additionalData;

private PaymentCredentials() {
Expand Down Expand Up @@ -139,12 +152,18 @@ public static PaymentCredentials fromSEPA(String name, String iban) {
return pc;
}

public static PaymentCredentials fromCreditCardData(String name, Brand brand, String obfuscatedId,
String expirationMonth, String expirationYear,
String hostedDataId, String storeId) {
public static PaymentCredentials fromCreditCardData(String name,
Brand brand,
String projectId,
String obfuscatedId,
String expirationMonth,
String expirationYear,
String hostedDataId,
String schemeTransactionId,
String storeId) {
PaymentCredentials pc = new PaymentCredentials();
pc.generateId();
pc.type = Type.CREDIT_CARD;
pc.type = Type.CREDIT_CARD_PSD2;

List<X509Certificate> certificates = Snabble.getInstance().getPaymentSigningCertificates();
if (certificates.size() == 0) {
Expand All @@ -159,6 +178,8 @@ public static PaymentCredentials fromCreditCardData(String name, Brand brand, St

CreditCardData creditCardData = new CreditCardData();
creditCardData.hostedDataID = hostedDataId;
creditCardData.projectID = projectId;
creditCardData.schemeTransactionID = schemeTransactionId;
creditCardData.hostedDataStoreID = storeId;

switch (brand) {
Expand All @@ -183,6 +204,7 @@ public static PaymentCredentials fromCreditCardData(String name, Brand brand, St
pc.signature = pc.sha256Signature(certificate);
pc.brand = brand;
pc.appId = Snabble.getInstance().getConfig().appId;
pc.projectId = projectId;

try {
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("MM/yyyy");
Expand Down Expand Up @@ -245,7 +267,7 @@ public static PaymentCredentials fromPaydirekt(PaydirektAuthorizationData author
return pc;
}

public static PaymentCredentials fromTegutEmployeeCard(String obfuscatedId, String cardNumber) {
public static PaymentCredentials fromTegutEmployeeCard(String obfuscatedId, String cardNumber, String projectId) {
if (cardNumber == null || cardNumber.length() != 19
|| (!cardNumber.startsWith("9280001621")
&& !cardNumber.startsWith("9280001625")
Expand Down Expand Up @@ -274,6 +296,7 @@ public static PaymentCredentials fromTegutEmployeeCard(String obfuscatedId, Stri
pc.signature = pc.sha256Signature(certificate);
pc.brand = Brand.UNKNOWN;
pc.appId = Snabble.getInstance().getConfig().appId;
pc.projectId = projectId;
pc.canBypassKeyStore = true;

if (pc.encryptedData == null) {
Expand All @@ -299,6 +322,11 @@ public Brand getBrand() {
return brand;
}

@Nullable
public String getProjectId() {
return projectId;
}

public String getAppId() {
return appId;
}
Expand Down Expand Up @@ -447,13 +475,17 @@ private String sha256Signature(X509Certificate certificate) {
}

public boolean validate() {
if (type == Type.CREDIT_CARD) {
if (type == Type.CREDIT_CARD_PSD2) {
Date date = new Date(validTo);
if (date.getTime() < System.currentTimeMillis()) {
return false;
}
}

if (type == Type.CREDIT_CARD) {
return false;
}

List<X509Certificate> certificates = Snabble.getInstance().getPaymentSigningCertificates();
for (X509Certificate cert : certificates) {
if (sha256Signature(cert).equals(signature)) {
Expand Down Expand Up @@ -500,7 +532,7 @@ public Map<String, String> getAdditionalData() {
public PaymentMethod getPaymentMethod() {
if (getType() == PaymentCredentials.Type.SEPA) {
return PaymentMethod.DE_DIRECT_DEBIT;
} else if (type == PaymentCredentials.Type.CREDIT_CARD) {
} else if (type == Type.CREDIT_CARD_PSD2) {
switch (getBrand()) {
case VISA: return PaymentMethod.VISA;
case AMEX: return PaymentMethod.AMEX;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ public class PaymentCredentialsStore {
private class Data {
private List<PaymentCredentials> credentialsList;
private String id;
private boolean removedOldCreditCards;
private boolean isKeyguarded;
}

Expand Down Expand Up @@ -129,6 +130,13 @@ public String id() {
return data.id;
}

/**
* @return true if old credit cards before v0.33.0 were added and therefore rendered unusable and deleted
*/
public boolean hasRemovedOldCreditCards() {
return data.removedOldCreditCards;
}

public void add(PaymentCredentials credentials) {
if (credentials == null) {
return;
Expand Down Expand Up @@ -220,6 +228,11 @@ private void validate() {
if (credentials != null) {
if (!credentials.validate()) {
removals.add(credentials);

if (credentials.getType() == PaymentCredentials.Type.CREDIT_CARD) {
data.removedOldCreditCards = true;
}

changed = true;
} else {
// app id's were not stored in old versions, if its not there assume the
Expand Down
2 changes: 2 additions & 0 deletions sample/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,8 @@
<activity android:name=".CreditCardInputActivity" />
<activity android:name=".PaydirektInputActivity" />
<activity android:name=".PaymentCredentialsListActivity" />
<activity android:name=".PaymentOptionsActivity" />
<activity android:name=".ProjectPaymentOptionsActivity" />
<activity android:name=".CheckoutCustomerCardActivity" />
<activity android:name=".CheckoutOfflineActivity" />
<activity android:name=".CheckoutGatekeeperActivity" />
Expand Down
1 change: 0 additions & 1 deletion sample/src/main/java/io/snabble/testapp/App.java
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,6 @@ public void onCreate() {
// if you are using a light mode theme, disable night mode resources
// this seems like a bug in android
AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_NO);

}

public void initBlocking() {
Expand Down
Loading