Skip to content

Commit

Permalink
Release 1.5.0
Browse files Browse the repository at this point in the history
  • Loading branch information
adyen-git-manager committed Aug 4, 2017
1 parent 534293d commit 3b1d246
Show file tree
Hide file tree
Showing 85 changed files with 13,379 additions and 361 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,4 @@
/build
/captures
.idea
api_configuration.xml
30 changes: 25 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@ This README provides the usage manual for the SDK itself. For the full documenta
To integrate the Adyen SDK into your project, import the **core** or **ui** module by adding one of the following lines to your build.gradle file.

```
compile 'com.adyen.checkout:core:1.0.6'
compile 'com.adyen.checkout:ui:1.0.6'
compile 'com.adyen.checkout:core:1.4.1'
compile 'com.adyen.checkout:ui:1.4.1'
```

To give you as much flexibility as possible, our Android SDK can be integrated in two ways:
Expand Down Expand Up @@ -137,9 +137,29 @@ This method is called only if payment details are required. For example, if Cred

```java
@Override
public void onPaymentDetailsRequired(@NonNull final PaymentRequest paymentRequest, @NonNull final Map<String, Object> requiredFields, @NonNull final PaymentDetailsCallback callback) {
// For different payment methods different UI might be required. It is suggested to check selected method via paymentRequest.getPaymentMethod() and display UI accordingly.
// When all payment details are retrieved, SDK should be notified via PaymentDetailsCallback.
public void onPaymentDetailsRequired(@NonNull final PaymentRequest paymentRequest, @NonNull final Collection<InputDetail> inputDetails, @NonNull final PaymentDetailsCallback callback) {
// For different payment methods different UI might be required. It is suggested to check selected method via paymentRequest.getPaymentMethod() and display UI accordingly.
// When all payment details are retrieved, SDK should be notified via PaymentDetailsCallback.
if (PaymentMethod.Type.CARD.equals(paymentRequest.getPaymentMethod().getType())) {
Card card = new Card();
card.setNumber("4111111111111111");
card.setCardHolderName("checkout shopper");
card.setCvc("737");
card.setExpiryMonth("10");
card.setExpiryYear("2020");
card.setGenerationTime(new Date());

try {
//Create PaymentDetails object from the inputDetails and fill them with the shopper input.
//Then call callback.completionWithPaymentDetails.
CreditCardPaymentDetails creditCardPaymentDetails = new CreditCardPaymentDetails(inputDetails);
creditCardPaymentDetails.fillCardToken(card.serialize(paymentRequest.getPublicKey()));
creditCardPaymentDetails.fillStoreDetails(true);
callback.completionWithPaymentDetails(creditCardPaymentDetails);
} catch (EncrypterException e) {
e.printStackTrace();
}
}
}
```

Expand Down
4 changes: 2 additions & 2 deletions adyen-core/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -49,8 +49,8 @@ dependencies {
compile "com.android.support:support-annotations:${rootProject.supportAnnotationsVersion}"
compile 'com.android.support:customtabs:25.3.1'

compile 'io.reactivex:rxjava:1.1.6'
compile 'io.reactivex:rxandroid:1.2.1'
compile 'io.reactivex.rxjava2:rxjava:2.1.2'
compile 'io.reactivex.rxjava2:rxandroid:2.0.1'

compile 'com.adyen.cse:adyen-cse:1.0.2'
}
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ static String getToken(final Context context, final PaymentStateHandler paymentS
Settings.Secure.ANDROID_ID);
deviceInfo.put("deviceFingerprintVersion", DEVICE_FINGER_PRINT_VERSION);
deviceInfo.put("platform", "android");
deviceInfo.put("apiVersion", "2");
deviceInfo.put("apiVersion", "3");
deviceInfo.put("osVersion", Build.VERSION.SDK_INT);
deviceInfo.put("sdkVersion", SDK_VERSION);
deviceInfo.put("deviceIdentifier", androidId);
Expand Down
18 changes: 13 additions & 5 deletions adyen-core/src/main/java/com/adyen/core/PaymentStateHandler.java
Original file line number Diff line number Diff line change
Expand Up @@ -41,8 +41,8 @@
import java.util.List;
import java.util.Map;

import rx.Observable;
import rx.functions.Action1;
import io.reactivex.Observable;
import io.reactivex.functions.Consumer;

import static com.adyen.core.constants.Constants.PaymentRequest.ADYEN_UI_FINALIZE_INTENT;
import static com.adyen.core.constants.Constants.PaymentRequest.PAYMENT_DETAILS_PROVIDED_INTENT;
Expand Down Expand Up @@ -257,9 +257,9 @@ private void fetchPaymentMethods() {
this.preferredPaymentMethods = paymentResponse.getPreferredPaymentMethods();
Observable<List<PaymentMethod>> listObservable = ModuleAvailabilityUtil.filterPaymentMethods(context,
unfilteredPaymentMethods);
listObservable.subscribe(new Action1<List<PaymentMethod>>() {
listObservable.subscribe(new Consumer<List<PaymentMethod>>() {
@Override
public void call(List<PaymentMethod> filteredPaymentMethods) {
public void accept(List<PaymentMethod> filteredPaymentMethods) {
filteredPaymentMethods.removeAll(Collections.singleton(null));
PaymentStateHandler.this.filteredPaymentMethodsList.clear();
PaymentStateHandler.this.filteredPaymentMethodsList.addAll(filteredPaymentMethods);
Expand Down Expand Up @@ -525,7 +525,15 @@ public void onFailure(Throwable e) {
private static JSONObject paymentDetailsToJson(@NonNull PaymentDetails paymentDetails) throws JSONException {
JSONObject jsonObject = new JSONObject();
for (InputDetail inputDetail : paymentDetails.getInputDetails()) {
jsonObject.put(inputDetail.getKey(), inputDetail.getValue());
if (inputDetail.getInputDetails() != null && !inputDetail.getInputDetails().isEmpty()) {
JSONObject recursiveDetailJson = new JSONObject();
for (InputDetail recursiveDetail : inputDetail.getInputDetails()) {
recursiveDetailJson.put(recursiveDetail.getKey(), recursiveDetail.getValue());
}
jsonObject.put(inputDetail.getKey(), recursiveDetailJson);
} else {
jsonObject.put(inputDetail.getKey(), inputDetail.getValue());
}
}
return jsonObject;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,12 @@

import java.util.List;

import rx.Observable;
import rx.Subscriber;
import rx.android.schedulers.AndroidSchedulers;
import rx.functions.Func1;
import rx.schedulers.Schedulers;
import io.reactivex.Observable;
import io.reactivex.ObservableEmitter;
import io.reactivex.ObservableOnSubscribe;
import io.reactivex.functions.Function;
import io.reactivex.schedulers.Schedulers;
import io.reactivex.android.schedulers.AndroidSchedulers;

/**
*
Expand Down Expand Up @@ -48,36 +49,34 @@ public static PaymentMethodService getModulePaymentService(@NonNull PaymentModul
public static Observable<List<PaymentMethod>> filterPaymentMethods(
@NonNull final Context context, @NonNull List<PaymentMethod> unfilteredPaymentMethods) {

return Observable.from(unfilteredPaymentMethods).concatMap(
new Func1<PaymentMethod, Observable<PaymentMethod>>() {
return Observable.fromIterable(unfilteredPaymentMethods).concatMap(
new Function<PaymentMethod, Observable<PaymentMethod>>() {
@Override
public Observable<PaymentMethod> call(final PaymentMethod paymentMethod) {
return Observable.create(new Observable.OnSubscribe<PaymentMethod>() {
public Observable<PaymentMethod> apply(final PaymentMethod paymentMethod) {
return Observable.create(new ObservableOnSubscribe<PaymentMethod>() {
@Override
public void call(final Subscriber<? super PaymentMethod> subscriber) {
public void subscribe(final ObservableEmitter<PaymentMethod> subscriber) {
isPaymentMethodAvailable(context, paymentMethod,
new PaymentMethodAvailabilityCallback() {
@Override
public void onSuccess(boolean isAvailable) {
if (!subscriber.isUnsubscribed() && isAvailable) {
if (!subscriber.isDisposed() && isAvailable) {
subscriber.onNext(paymentMethod);
} else {
subscriber.onNext(null);
}
subscriber.onCompleted();
subscriber.onComplete();
}

@Override
public void onFail(Throwable e) {
subscriber.onNext(null);
subscriber.onCompleted();
subscriber.onComplete();
}
});
}
});
}
})
.toList()
.toObservable()
.subscribeOn(Schedulers.newThread())
.observeOn(AndroidSchedulers.mainThread());
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,17 @@ public class CreditCardPaymentDetails extends PaymentDetails {

public static final String ADDITIONAL_DATA_CARD = "additionalData.card.encrypted.json";
public static final String STORE_DETAILS = "storeDetails";
public static final String INSTALLMENTS = "installments";
public static final String BILLING_ADDRESS = "billingAddress";

public enum AddressKey {
street,
houseNumberOrName,
city,
country,
postalCode,
stateOrProvince;
}

public CreditCardPaymentDetails(Collection<InputDetail> inputDetails) {
super(inputDetails);
Expand All @@ -23,4 +34,86 @@ public boolean fillStoreDetails(final boolean storeDetails) {
return super.fill(STORE_DETAILS, storeDetails);
}

public boolean fillNumberOfInstallments(final short numberOfInstallments) {
return super.fill(INSTALLMENTS, String.valueOf(numberOfInstallments));
}

public boolean fillbillingAddressStreet(String street) {
for (InputDetail inputDetail : getInputDetails()) {
if (inputDetail.getKey().equals(BILLING_ADDRESS)) {
for (InputDetail addressDetail : inputDetail.getInputDetails()) {
if (addressDetail.getKey().equals(AddressKey.street.name())) {
return addressDetail.fill(street);
}
}
}
}
return false;
}

public boolean fillbillingAddressHouseNumberOrName(String houseNumberOrName) {
for (InputDetail inputDetail : getInputDetails()) {
if (inputDetail.getKey().equals(BILLING_ADDRESS)) {
for (InputDetail addressDetail : inputDetail.getInputDetails()) {
if (addressDetail.getKey().equals(AddressKey.houseNumberOrName.name())) {
return addressDetail.fill(houseNumberOrName);
}
}
}
}
return false;
}

public boolean fillbillingAddressCity(String city) {
for (InputDetail inputDetail : getInputDetails()) {
if (inputDetail.getKey().equals(BILLING_ADDRESS)) {
for (InputDetail addressDetail : inputDetail.getInputDetails()) {
if (addressDetail.getKey().equals(AddressKey.city.name())) {
return addressDetail.fill(city);
}
}
}
}
return false;
}

public boolean fillbillingAddressCountry(String country) {
for (InputDetail inputDetail : getInputDetails()) {
if (inputDetail.getKey().equals(BILLING_ADDRESS)) {
for (InputDetail addressDetail : inputDetail.getInputDetails()) {
if (addressDetail.getKey().equals(AddressKey.country.name())) {
return addressDetail.fill(country);
}
}
}
}
return false;
}

public boolean fillbillingAddressPostalCode(String postalCode) {
for (InputDetail inputDetail : getInputDetails()) {
if (inputDetail.getKey().equals(BILLING_ADDRESS)) {
for (InputDetail addressDetail : inputDetail.getInputDetails()) {
if (addressDetail.getKey().equals(AddressKey.postalCode.name())) {
return addressDetail.fill(postalCode);
}
}
}
}
return false;
}

public boolean fillbillingAddressStateOrProvince(String stateOrProvince) {
for (InputDetail inputDetail : getInputDetails()) {
if (inputDetail.getKey().equals(BILLING_ADDRESS)) {
for (InputDetail addressDetail : inputDetail.getInputDetails()) {
if (addressDetail.getKey().equals(AddressKey.stateOrProvince.name())) {
return addressDetail.fill(stateOrProvince);
}
}
}
}
return false;
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@ public final class InputDetail implements Serializable {
private boolean optional = true;
private ArrayList<Item> items = new ArrayList<>();

private ArrayList<InputDetail> inputDetails;

private InputDetail() {

}
Expand All @@ -39,23 +41,49 @@ public boolean fill(boolean value) {
}

public boolean isFilled() {
return !StringUtils.isEmptyOrNull(value);
if (inputDetails != null && !inputDetails.isEmpty()) {
for (InputDetail inputDetail : inputDetails) {
if (!inputDetail.isFilled()) {
return false;
}
}
return true;
} else {
return !StringUtils.isEmptyOrNull(value);
}
}

public static InputDetail fromJson(@NonNull final JSONObject jsonObject) throws JSONException {
InputDetail inputDetail = new InputDetail();
inputDetail.key = jsonObject.getString("key");
inputDetail.optional = jsonObject.optBoolean("optional", false);
inputDetail.type = Type.fromString(jsonObject.getString("type"));
inputDetail.value = jsonObject.optString("value");
if (inputDetail.type == Type.Select) {
JSONArray jsonItems = jsonObject.getJSONArray("items");
for (int i = 0; i < jsonItems.length(); i++) {
inputDetail.items.add(Item.fromJson(jsonItems.getJSONObject(i)));
}
}
if (jsonObject.has("inputDetails")) {
JSONArray jsonObjectInputDetails = jsonObject.getJSONArray("inputDetails");
for (int i = 0; i < jsonObjectInputDetails.length(); i++) {
inputDetail.addInputDetail(fromJson(jsonObjectInputDetails.getJSONObject(i)));
}
}
return inputDetail;
}

private void addInputDetail(InputDetail inputDetail) {
if (inputDetails == null) {
this.inputDetails = new ArrayList<>();
}
inputDetails.add(inputDetail);
}

public ArrayList<InputDetail> getInputDetails() {
return inputDetails;
}

public String getKey() {
return key;
Expand Down Expand Up @@ -87,7 +115,7 @@ public enum Type implements Serializable {
AndroidPayToken("androidPayToken"), // A token used by a wallet
SamsungPayToken("samsungPayToken"), // A token used by a wallet
Cvc("cvc"), //A field to enter CVC code
Address("Address"),
Address("address"),
Unknown("Unknown");

private String apiField;
Expand Down Expand Up @@ -123,7 +151,7 @@ private Item() {
static Item fromJson(@NonNull final JSONObject jsonObject) throws JSONException {
Item item = new Item();
item.id = jsonObject.getString("id");
item.imageUrl = jsonObject.getString("imageUrl");
item.imageUrl = jsonObject.optString("imageUrl");
item.name = jsonObject.getString("name");
return item;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,18 +4,28 @@
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;

import com.adyen.core.PaymentRequest;
import com.adyen.core.interfaces.PaymentDetailsCallback;

import java.io.Serializable;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;

/**
* Class for collecting the required PaymentDetails from the shopper to make the payment.
* This is the generic {@Link PaymentDetails} class that can handle all payment methods.
* For convenience, several more specific subclasses of this class are provided.
*/
public class PaymentDetails implements Serializable {

@NonNull private Map<String, InputDetail> inputDetails = new HashMap<>();

/**
* This class should be instantiated using the inputDetails received from
* {@link com.adyen.core.interfaces.PaymentRequestDetailsListener#onPaymentDetailsRequired(PaymentRequest, Collection, PaymentDetailsCallback)}.
* @param inputDetails InputDetails obtained from the SDK.
*/
public PaymentDetails(Collection<InputDetail> inputDetails) {
for (InputDetail inputDetail : inputDetails) {
this.inputDetails.put(inputDetail.getKey(), inputDetail);
Expand Down
Loading

0 comments on commit 3b1d246

Please sign in to comment.