Skip to content

Commit

Permalink
Merge pull request #493 from Adyen/develop
Browse files Browse the repository at this point in the history
Release 4.2.0
  • Loading branch information
jreij authored Sep 22, 2021
2 parents 9cf0235 + 24408f8 commit 22f051b
Show file tree
Hide file tree
Showing 46 changed files with 959 additions and 104 deletions.
18 changes: 3 additions & 15 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,11 +27,11 @@ If you are upgrading from 3.x.x to a current release, check out our [migration g
Import the Component module for the Payment Method you want to use by adding it to your `build.gradle` file.
For example, for the Drop-in solution you should add:
```groovy
implementation "com.adyen.checkout:drop-in:4.1.1"
implementation "com.adyen.checkout:drop-in:4.2.0"
```
For a Credit Card component you should add:
```groovy
implementation "com.adyen.checkout:card:4.1.1"
implementation "com.adyen.checkout:card:4.2.0"
```

### Client Key
Expand Down Expand Up @@ -183,21 +183,9 @@ cardComponent.observe(this) { paymentComponentState ->

## ProGuard

If you use ProGuard or R8, the following rules should be enough to maintain all expected functionality.
If you use ProGuard or R8, you do not need to manually add any rules, as they are automatically embedded in the artifacts.
Please let us know if you find any issues.

```
-keep class com.adyen.checkout.core.model.** { * ;}
-keep class com.adyen.checkout.components.model.** { *; }
-keep class com.adyen.threeds2.** { *; }
-keepclassmembers public class * implements com.adyen.checkout.components.PaymentComponent {
public <init>(...);
}
-keepclassmembers public class * implements com.adyen.checkout.components.ActionComponent {
public <init>(...);
}
```

## See also

* [Android Documentation][docs.android]
Expand Down
13 changes: 12 additions & 1 deletion RELEASE_NOTES.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,5 +8,16 @@
[//]: # ( # Deprecated)
[//]: # ( - Configurations public constructor are deprecated, please use each Configuration's builder to make a Configuration object)

## Added
- Dual-branded card flow: shoppers can now select their card's brand when two brands are detected.
- Ability to store BCMC cards.
- Support for new Activity Result API.
- Ability to stop observing components.
- 3DS2 SDK version in `CardComponent`'s output.
- Read list of supported card networks for Google Pay from the payment methods API response.

## Fixed
- Address Visibility in Card Component configuration not being reflected on UI.
- Crash caused by having stored payment methods none of which is Ecommerce.
- Google Pay Component will not include `TotalPrice` in its output, if `TotalPriceStatus` is set to `NOT_CURRENTLY_KNOWN`.
- Issue in Drop-in when multiple payment methods have the same type.
- Missing default BCMC configuration in Drop-in.
3 changes: 3 additions & 0 deletions bcmc/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,9 @@ dependencies {
// Checkout
api project(":card")

// If 3DS2 SDK is present.
compileOnly "com.adyen.threeds:adyen-3ds2:$adyen3ds2_version"

// Dependencies
implementation "com.google.android.material:material:$material_version"

Expand Down
11 changes: 10 additions & 1 deletion bcmc/src/main/java/com/adyen/checkout/bcmc/BcmcComponent.kt
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ import com.adyen.checkout.core.log.Logger
import com.adyen.checkout.cse.CardEncrypter
import com.adyen.checkout.cse.UnencryptedCard
import com.adyen.checkout.cse.exception.EncryptionException
import com.adyen.threeds2.ThreeDS2Service
import kotlinx.coroutines.launch

private val TAG = LogUtil.getTag()
Expand Down Expand Up @@ -78,7 +79,8 @@ class BcmcComponent(
Logger.v(TAG, "onInputDataChanged")
return BcmcOutputData(
validateCardNumber(inputData.cardNumber),
validateExpiryDate(inputData.expiryDate)
validateExpiryDate(inputData.expiryDate),
inputData.isStorePaymentSelected
)
}

Expand Down Expand Up @@ -121,8 +123,15 @@ class BcmcComponent(
encryptedCardNumber = encryptedCard.encryptedCardNumber
encryptedExpiryMonth = encryptedCard.encryptedExpiryMonth
encryptedExpiryYear = encryptedCard.encryptedExpiryYear
try {
threeDS2SdkVersion = ThreeDS2Service.INSTANCE.sdkVersion
} catch (e: ClassNotFoundException) {
Logger.e(TAG, "threeDS2SdkVersion not set because 3DS2 SDK is not present in project.")
}
}
paymentComponentData.paymentMethod = cardPaymentMethod
paymentComponentData.setStorePaymentMethod(outputData.isStoredPaymentMethodEnabled)
paymentComponentData.shopperReference = configuration.shopperReference
return GenericComponentState(paymentComponentData, true, true)
}

Expand Down
50 changes: 50 additions & 0 deletions bcmc/src/main/java/com/adyen/checkout/bcmc/BcmcConfiguration.java
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,12 @@
import android.os.Parcelable;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;

import com.adyen.checkout.components.base.BaseConfigurationBuilder;
import com.adyen.checkout.components.base.Configuration;
import com.adyen.checkout.core.api.Environment;
import com.adyen.checkout.core.util.ParcelUtils;

import java.util.Locale;

Expand All @@ -25,6 +27,9 @@
*/
public class BcmcConfiguration extends Configuration {

private final String mShopperReference;
private final boolean mShowStorePaymentField;

public static final Parcelable.Creator<BcmcConfiguration> CREATOR = new Parcelable.Creator<BcmcConfiguration>() {
public BcmcConfiguration createFromParcel(@NonNull Parcel in) {
return new BcmcConfiguration(in);
Expand All @@ -37,22 +42,41 @@ public BcmcConfiguration[] newArray(int size) {

BcmcConfiguration(@NonNull Builder builder) {
super(builder.getBuilderShopperLocale(), builder.getBuilderEnvironment(), builder.getBuilderClientKey());

mShopperReference = builder.mShopperReference;
mShowStorePaymentField = builder.mBuilderShowStorePaymentField;
}

BcmcConfiguration(@NonNull Parcel in) {
super(in);
mShopperReference = in.readString();
mShowStorePaymentField = ParcelUtils.readBoolean(in);
}

@Override
public void writeToParcel(@NonNull Parcel dest, int flags) {
super.writeToParcel(dest, flags);
dest.writeString(mShopperReference);
ParcelUtils.writeBoolean(dest, mShowStorePaymentField);
}

@Nullable
public String getShopperReference() {
return mShopperReference;
}

public boolean isStorePaymentFieldVisible() {
return mShowStorePaymentField;
}

/**
* Builder to create a {@link BcmcConfiguration}.
*/
public static final class Builder extends BaseConfigurationBuilder<BcmcConfiguration> {

private boolean mBuilderShowStorePaymentField = false;
private String mShopperReference;

/**
* Constructor of Card Configuration Builder with default values.
*
Expand Down Expand Up @@ -90,6 +114,32 @@ public Builder setEnvironment(@NonNull Environment builderEnvironment) {
return (Builder) super.setEnvironment(builderEnvironment);
}

/**
* Set if the option to store the card for future payments should be shown as an input field.
*
* @param showStorePaymentField {@link Boolean}
* @return {@link BcmcConfiguration.Builder}
*/
@NonNull
public BcmcConfiguration.Builder setShowStorePaymentField(boolean showStorePaymentField) {
mBuilderShowStorePaymentField = showStorePaymentField;
return this;
}

/**
* Set the unique reference for the shopper doing this transaction.
* This value will simply be passed back to you in the {@link com.adyen.checkout.components.model.payments.request.PaymentComponentData}
* for convenience.
*
* @param shopperReference The unique shopper reference
* @return {@link BcmcConfiguration.Builder}
*/
@NonNull
public BcmcConfiguration.Builder setShopperReference(@NonNull String shopperReference) {
mShopperReference = shopperReference;
return this;
}

/**
* Build {@link BcmcConfiguration} object from {@link BcmcConfiguration.Builder} inputs.
*
Expand Down
9 changes: 9 additions & 0 deletions bcmc/src/main/java/com/adyen/checkout/bcmc/BcmcInputData.java
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
public final class BcmcInputData implements InputData {
private String mCardNumber = "";
private ExpiryDate mExpiryDate = ExpiryDate.EMPTY_DATE;
private boolean mIsStorePaymentSelected = false;

@NonNull
public String getCardNumber() {
Expand All @@ -34,4 +35,12 @@ public ExpiryDate getExpiryDate() {
public void setExpiryDate(@NonNull ExpiryDate expiryDate) {
mExpiryDate = expiryDate;
}

public boolean isStorePaymentSelected() {
return mIsStorePaymentSelected;
}

public void setStorePaymentSelected(boolean storePaymentSelected) {
mIsStorePaymentSelected = storePaymentSelected;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -18,13 +18,16 @@ public final class BcmcOutputData implements OutputData {

private final FieldState<String> mCardNumberField;
private final FieldState<ExpiryDate> mExpiryDateField;
private final boolean mIsStoredPaymentMethodEnabled;

BcmcOutputData(
@NonNull FieldState<String> cardNumberField,
@NonNull FieldState<ExpiryDate> expiryDateField
@NonNull FieldState<ExpiryDate> expiryDateField,
boolean isStoredPaymentMethodEnabled
) {
mCardNumberField = cardNumberField;
mExpiryDateField = expiryDateField;
mIsStoredPaymentMethodEnabled = isStoredPaymentMethodEnabled;
}

@NonNull
Expand All @@ -37,6 +40,10 @@ public FieldState<ExpiryDate> getExpiryDateField() {
return mExpiryDateField;
}

public boolean isStoredPaymentMethodEnabled() {
return mIsStoredPaymentMethodEnabled;
}

@Override
public boolean isValid() {
return mCardNumberField.getValidation().isValid()
Expand Down
24 changes: 22 additions & 2 deletions bcmc/src/main/java/com/adyen/checkout/bcmc/BcmcView.java
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.annotation.StringRes;
import androidx.appcompat.widget.SwitchCompat;
import androidx.lifecycle.LifecycleOwner;
import androidx.lifecycle.Observer;

Expand All @@ -26,10 +27,10 @@
import com.adyen.checkout.components.GenericComponentState;
import com.adyen.checkout.components.api.ImageLoader;
import com.adyen.checkout.components.model.payments.request.CardPaymentMethod;
import com.adyen.checkout.components.ui.FieldState;
import com.adyen.checkout.components.ui.Validation;
import com.adyen.checkout.components.ui.view.AdyenLinearLayout;
import com.adyen.checkout.components.ui.view.RoundCornerImageView;
import com.adyen.checkout.components.ui.FieldState;
import com.google.android.material.textfield.TextInputLayout;

/**
Expand All @@ -47,6 +48,8 @@ public final class BcmcView
private TextInputLayout mExpiryDateInput;
private TextInputLayout mCardNumberInput;

private SwitchCompat mSwitchStorePaymentMethod;

private final BcmcInputData mCardInputData = new BcmcInputData();

private ImageLoader mImageLoader;
Expand All @@ -73,7 +76,7 @@ public BcmcView(@NonNull Context context, @Nullable AttributeSet attrs, int defS

@Override
protected void initLocalizedStrings(@NonNull Context localizedContext) {
final int[] myAttrs = {android.R.attr.hint};
int[] myAttrs = {android.R.attr.hint};
TypedArray typedArray;

// Card Number
Expand All @@ -85,6 +88,12 @@ protected void initLocalizedStrings(@NonNull Context localizedContext) {
typedArray = localizedContext.obtainStyledAttributes(R.style.AdyenCheckout_Card_ExpiryDateInput, myAttrs);
mExpiryDateInput.setHint(typedArray.getString(0));
typedArray.recycle();

// Store Switch
myAttrs = new int[] {android.R.attr.text};
typedArray = localizedContext.obtainStyledAttributes(R.style.AdyenCheckout_Card_StorePaymentSwitch, myAttrs);
mSwitchStorePaymentMethod.setText(typedArray.getString(0));
typedArray.recycle();
}

@Override
Expand All @@ -93,6 +102,7 @@ public void initView() {

initCardNumberInput();
initExpiryDateInput();
initStorePaymentMethodSwitch();
}

@Override
Expand Down Expand Up @@ -215,4 +225,14 @@ private void initExpiryDateInput() {
}
});
}

private void initStorePaymentMethodSwitch() {
mSwitchStorePaymentMethod = findViewById(R.id.switch_storePaymentMethod);

mSwitchStorePaymentMethod.setVisibility(getComponent().getConfiguration().isStorePaymentFieldVisible() ? VISIBLE : GONE);
mSwitchStorePaymentMethod.setOnCheckedChangeListener((buttonView, isChecked) -> {
mCardInputData.setStorePaymentSelected(isChecked);
notifyInputDataChanged();
});
}
}
34 changes: 26 additions & 8 deletions bcmc/src/main/res/layout/bcmc_view.xml
Original file line number Diff line number Diff line change
Expand Up @@ -32,16 +32,28 @@
tools:ignore="RequiredSize" />
</com.google.android.material.textfield.TextInputLayout>

<LinearLayout
android:id="@+id/cardBrandLogo_container_parent"
style="@style/AdyenCheckout.Card.BrandRecognitionLogoContainerGroup"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal">

<com.adyen.checkout.components.ui.view.RoundCornerImageView
android:id="@+id/cardBrandLogo_imageView"
style="@style/AdyenCheckout.Card.BrandRecognitionLogo"
android:layout_width="@dimen/brand_logo_width"
android:layout_height="@dimen/brand_logo_height"
app:strokeColor="@color/stroke_color"
app:strokeWidth="0dp">
<FrameLayout
android:id="@+id/cardBrandLogo_container"
style="@style/AdyenCheckout.Card.BrandRecognitionLogoContainer"
android:layout_width="wrap_content"
android:layout_height="wrap_content">

</com.adyen.checkout.components.ui.view.RoundCornerImageView>
<com.adyen.checkout.components.ui.view.RoundCornerImageView
android:id="@+id/cardBrandLogo_imageView"
style="@style/AdyenCheckout.Card.BrandRecognitionLogo"
android:layout_width="@dimen/brand_logo_width"
android:layout_height="@dimen/brand_logo_height"
app:strokeColor="@color/stroke_color"
app:strokeWidth="0dp" />
</FrameLayout>
</LinearLayout>
</FrameLayout>

<com.google.android.material.textfield.TextInputLayout
Expand All @@ -59,4 +71,10 @@
tools:ignore="RequiredSize" />
</com.google.android.material.textfield.TextInputLayout>

<androidx.appcompat.widget.SwitchCompat
android:id="@+id/switch_storePaymentMethod"
style="@style/AdyenCheckout.Card.StorePaymentSwitch"
android:layout_width="match_parent"
android:layout_height="wrap_content" />

</merge>
2 changes: 1 addition & 1 deletion build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ allprojects {
// just for example app, don't need to increment
ext.version_code = 1
// The version_name format is "major.minor.patch(-(alpha|beta|rc)[0-9]{2}){0,1}" (e.g. 3.0.0, 3.1.1-alpha04 or 3.1.4-rc01 etc).
ext.version_name = "4.1.1"
ext.version_name = "4.2.0"

// Code quality
ext.ktlint_version = '0.40.0'
Expand Down
3 changes: 3 additions & 0 deletions card/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,9 @@ dependencies {
api project(':ui-core')
api project(':cse')

// If 3DS2 SDK is present.
compileOnly "com.adyen.threeds:adyen-3ds2:$adyen3ds2_version"

// Dependencies
implementation "com.google.android.material:material:$material_version"

Expand Down
Loading

0 comments on commit 22f051b

Please sign in to comment.