Skip to content

Commit

Permalink
Release 1.4.1
Browse files Browse the repository at this point in the history
  • Loading branch information
adyen-git-manager committed Jul 14, 2017
1 parent 66316dd commit 534293d
Show file tree
Hide file tree
Showing 52 changed files with 540 additions and 234 deletions.
Binary file removed adyen-core/core-1.0.0.aar
Binary file not shown.
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
import com.adyen.core.internals.PaymentTrigger;
import com.adyen.core.models.PaymentMethod;
import com.adyen.core.models.PaymentResponse;
import com.adyen.core.models.paymentdetails.InputDetail;
import com.adyen.core.models.paymentdetails.PaymentDetails;

import org.json.JSONException;
Expand All @@ -39,7 +40,7 @@ class PaymentBroadcastReceivers {
public void completionWithPaymentMethod(@NonNull final PaymentMethod selectedPaymentMethod) {
paymentStateHandler.setPaymentMethod(selectedPaymentMethod);

if (!selectedPaymentMethod.getRequiredFields().isEmpty()) {
if (!(selectedPaymentMethod.getInputDetails() == null || selectedPaymentMethod.getInputDetails().isEmpty())) {
paymentStateHandler.getPaymentProcessorStateMachine().onTrigger(
PaymentTrigger.PAYMENT_DETAILS_REQUIRED);
} else {
Expand All @@ -58,21 +59,23 @@ public void completionWithPaymentData(@NonNull final byte[] paymentSetupData) {
PaymentTrigger.PAYMENT_DATA_PROVIDED);
} catch (final JSONException jsonException) {
Log.e(TAG, "Provided payment data response is invalid", jsonException);
paymentStateHandler.setPaymentErrorThrowableAndTriggerError(jsonException);
paymentStateHandler.setPaymentErrorThrowableAndTriggerError(
new Exception("Provided payment data response is invalid", jsonException));
}
}
};


private PaymentDetailsCallback paymentDetailsCallback = new PaymentDetailsCallback() {
@Override
public void completionWithPaymentDetails(@NonNull Map<String, Object> paymentDetails) {
public void completionWithPaymentDetails(PaymentDetails paymentDetails) {
paymentStateHandler.setPaymentDetails(paymentDetails);
paymentStateHandler.getPaymentProcessorStateMachine().onTrigger(PaymentTrigger.PAYMENT_DETAILS_PROVIDED);
}

@Override
public void completionWithPaymentDetails(PaymentDetails paymentDetails) {
paymentStateHandler.setPaymentDetails(paymentDetails.toMap());
public void completionWithPaymentDetails(@NonNull Map<String, Object> paymentDetails) {
paymentStateHandler.setPaymentDetails(paymentDetails);
paymentStateHandler.getPaymentProcessorStateMachine().onTrigger(PaymentTrigger.PAYMENT_DETAILS_PROVIDED);
}
};
Expand Down Expand Up @@ -117,13 +120,15 @@ public void onReceive(final Context context, final Intent intent) {
Log.e(TAG, "androidPayInfoListener failed: " + errorMessage);
paymentStateHandler.setPaymentErrorThrowableAndTriggerError(new Throwable(errorMessage));
} else {
final Map<String, Object> inputFields = paymentStateHandler.getPaymentMethod().getRequiredFields();
PaymentDetails paymentDetails = new PaymentDetails(paymentStateHandler.getPaymentMethod().getInputDetails());
if (androidPayToken != null) {
for (final String key : inputFields.keySet()) {
inputFields.put(key, androidPayToken);
for (InputDetail inputDetail : paymentDetails.getInputDetails()) {
if (inputDetail.getType() == InputDetail.Type.AndroidPayToken) {
inputDetail.fill(androidPayToken);
}
}
}
paymentDetailsCallback.completionWithPaymentDetails(PaymentDetails.fromMap(inputFields));
paymentDetailsCallback.completionWithPaymentDetails(paymentDetails);
}
LocalBroadcastManager.getInstance(context).unregisterReceiver(this);
}
Expand Down
33 changes: 28 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 @@ -26,6 +26,8 @@
import com.adyen.core.models.PaymentMethod;
import com.adyen.core.models.PaymentRequestResult;
import com.adyen.core.models.PaymentResponse;
import com.adyen.core.models.paymentdetails.InputDetail;
import com.adyen.core.models.paymentdetails.PaymentDetails;
import com.adyen.core.utils.AsyncHttpClient;
import com.adyen.core.utils.Util;

Expand Down Expand Up @@ -77,7 +79,8 @@ class PaymentStateHandler implements State.StateChangeListener {
private PaymentProcessorStateMachine paymentProcessorStateMachine;
private PaymentBroadcastReceivers paymentBroadcastReceivers;

private Map<String, Object> paymentDetails;
private PaymentDetails paymentDetails;
@Deprecated private Map<String, Object> requiredFieldsPaymentDetails;

PaymentStateHandler(Context context, PaymentRequest paymentRequest,
@NonNull final PaymentRequestListener paymentRequestListener,
Expand Down Expand Up @@ -194,7 +197,7 @@ private void requestPaymentMethodDetails() {
paymentBroadcastReceivers.getAndroidPayInfoListener(), androidPayIntentFilter);

for (PaymentRequestDetailsListener detailsListener : paymentRequestDetailsListeners) {
detailsListener.onPaymentDetailsRequired(paymentRequest, paymentMethod.getRequiredFields(),
detailsListener.onPaymentDetailsRequired(paymentRequest, paymentMethod.getInputDetails(),
paymentBroadcastReceivers.getPaymentDetailsCallback());
}
}
Expand Down Expand Up @@ -324,9 +327,16 @@ private void initiatePayment(@NonNull final HttpResponseCallback httpResponseCal
paymentRequestPostData.put("paymentData", paymentResponse.getPaymentData());
paymentRequestPostData.put("paymentMethodData", paymentMethod.getPaymentMethodData());

JSONObject jsonDetails = Util.mapToJson(this.paymentDetails);
JSONObject jsonDetails = new JSONObject();

if (paymentDetails != null) {
jsonDetails = paymentDetailsToJson(paymentDetails);
} else if (requiredFieldsPaymentDetails != null) {
jsonDetails = Util.mapToJson(requiredFieldsPaymentDetails);
}

if (sdkHandlesUI()) {
if (paymentDetails == null) {
if (paymentDetails == null && requiredFieldsPaymentDetails == null) {
jsonDetails = new JSONObject();
}
Log.d(TAG, "Return url is going to be overridden by SDK");
Expand Down Expand Up @@ -446,10 +456,14 @@ public void completionWithUri(@NonNull Uri uri) {
}
};

void setPaymentDetails(Map<String, Object> paymentDetails) {
void setPaymentDetails(PaymentDetails paymentDetails) {
this.paymentDetails = paymentDetails;
}

void setPaymentDetails(Map<String, Object> paymentDetails) {
this.requiredFieldsPaymentDetails = paymentDetails;
}

void deletePreferredPaymentMethod(final PaymentMethod paymentMethod, final DeletePreferredPaymentMethodListener listener) {
Log.d(TAG, "deletePreferredPaymentMethod()");
if (paymentMethod == null) {
Expand Down Expand Up @@ -503,8 +517,17 @@ public void onFailure(Throwable e) {
}
});
} catch (JSONException e) {
Log.e(TAG, "Deletion of preferred payment method has failed", e);
listener.onFail();
}
}

private static JSONObject paymentDetailsToJson(@NonNull PaymentDetails paymentDetails) throws JSONException {
JSONObject jsonObject = new JSONObject();
for (InputDetail inputDetail : paymentDetails.getInputDetails()) {
jsonObject.put(inputDetail.getKey(), inputDetail.getValue());
}
return jsonObject;
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ public interface PaymentDetailsCallback {
* The callback which is called when payment details are provided by the client.
* @param paymentDetails payment details which are provided by the client.
*/
@Deprecated
void completionWithPaymentDetails(@NonNull Map<String, Object> paymentDetails);

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,11 @@

import com.adyen.core.PaymentRequest;
import com.adyen.core.models.PaymentMethod;
import com.adyen.core.models.paymentdetails.InputDetail;
import com.adyen.core.models.paymentdetails.PaymentDetails;

import java.util.Collection;
import java.util.List;
import java.util.Map;

/**
* Listener for listening to detailed events from {@link PaymentRequest}.
Expand Down Expand Up @@ -54,11 +56,13 @@ void onRedirectRequired(@NonNull PaymentRequest paymentRequest, @NonNull String
* This callback will only be triggered if the selected payment method requires additional details.
*
* @param paymentRequest {@link PaymentRequest} reference.
* @param requiredFields The details that have to be provided by the shopper.
* @param inputDetails The collection of {@link InputDetail} that have to be provided by the shopper.
* @param callback {@link PaymentDetailsCallback} instance in order to inform {@link PaymentRequest}
* about the required fields.
* {@link PaymentDetailsCallback} needs to be called with an instance of {@link PaymentDetails} that
* is to be created using the {@link InputDetail} collection.
*/
void onPaymentDetailsRequired(@NonNull PaymentRequest paymentRequest, @NonNull Map<String, Object> requiredFields,
void onPaymentDetailsRequired(@NonNull PaymentRequest paymentRequest, @NonNull Collection<InputDetail> inputDetails,
@NonNull PaymentDetailsCallback callback);

}
83 changes: 38 additions & 45 deletions adyen-core/src/main/java/com/adyen/core/models/PaymentMethod.java
Original file line number Diff line number Diff line change
@@ -1,14 +1,16 @@
package com.adyen.core.models;

import android.support.annotation.NonNull;
import android.support.annotation.Nullable;

import com.adyen.core.models.paymentdetails.InputDetail;

import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
Expand Down Expand Up @@ -43,7 +45,7 @@ public static class Type {

// Optional fields.
private Configuration configuration;
@NonNull private HashMap<String, Object> requiredFields = new HashMap<>(); // These are the fields that are required for incomplete payment

// methods (e.g. encrypted card data).
private Card card;

Expand All @@ -52,13 +54,16 @@ public static class Type {

private String logoUrl;

// An exception for iDEAL. Actually issuers is another type of a required field.
private List<Issuer> issuers;
private Collection<InputDetail> inputDetails;

private PaymentMethod() {

}

public Collection<InputDetail> getInputDetails() {
return this.inputDetails;
}

static PaymentMethod createPaymentMethod(final JSONObject paymentMethodJSON, final String logoBaseUrl)
throws JSONException {
return createPaymentMethod(paymentMethodJSON, logoBaseUrl, false);
Expand All @@ -77,7 +82,7 @@ static PaymentMethod createPaymentMethod(final JSONObject paymentMethodJSON, fin

final JSONArray inputDetails = paymentMethodJSON.optJSONArray("inputDetails");
if (inputDetails != null) {
paymentMethod.requiredFields = parseFieldsForPaymentMethodDetails(paymentMethod, inputDetails);
paymentMethod.inputDetails = parseInputDetails(inputDetails);
}

if (!paymentMethodJSON.isNull("card")) {
Expand Down Expand Up @@ -109,37 +114,23 @@ static PaymentMethod createContainerPaymentMethod(final JSONObject paymentMethod

final JSONArray inputDetails = paymentMethodJSON.optJSONArray("inputDetails");
if (inputDetails != null) {
paymentMethod.requiredFields = parseFieldsForPaymentMethodDetails(paymentMethod, inputDetails);
paymentMethod.inputDetails = parseInputDetails(inputDetails);
}

return paymentMethod;
}

private static HashMap<String, Object> parseFieldsForPaymentMethodDetails(final PaymentMethod paymentMethod,
final JSONArray requiredFields)
throws JSONException {
final HashMap<String, Object> requiredFieldsMap = new HashMap<>();
for (int r = 0; r < requiredFields.length(); r++) {
final JSONObject field = requiredFields.optJSONObject(r);
private static Collection<InputDetail> parseInputDetails(final JSONArray inputDetailsJson) throws JSONException {
Collection<InputDetail> inputDetails = new ArrayList<>();
for (int r = 0; r < inputDetailsJson.length(); r++) {
final JSONObject field = inputDetailsJson.optJSONObject(r);

if (field != null) {
if ("idealIssuer".equals(field.optString("key"))) {
final List<Issuer> listOfIssuers = new ArrayList<>();
// This payment method has a list of issuers; we need to parse this list.

final JSONArray issuers = field.optJSONArray("items");
if (issuers != null) {
for (int p = 0; p < issuers.length(); p++) {
final JSONObject issuerJSONObject = issuers.optJSONObject(p);
final Issuer issuer = new Issuer(issuerJSONObject);
listOfIssuers.add(issuer);
}
paymentMethod.issuers = listOfIssuers;
}
}
requiredFieldsMap.put(field.getString("key"), null);
InputDetail inputDetail = InputDetail.fromJson(field);
inputDetails.add(InputDetail.fromJson(field));
}
}
return requiredFieldsMap;
return inputDetails;
}

/**
Expand Down Expand Up @@ -203,28 +194,12 @@ public List<PaymentMethod> getMemberPaymentMethods() {
return memberPaymentMethods;
}

/**
* Get a list of issuers if an issuer selection is required.
* @return A list of issuers if the payment method requires selection of an issuer.
*/
public @Nullable List<Issuer> getIssuers() {
return issuers;
}

/**
* Get the required fields that need to be filled to use this payment method.
* @return A map that contains the required fields, which need to be filled by the shopper/merchant.
*/
public @NonNull Map<String, Object> getRequiredFields() {
return new HashMap<>(requiredFields);
}

/**
* The method to determine if a redirect is required for this payment method.
* @return True if a redirect is required, otherwise false
*/
public boolean isRedirectMethod() {
return requiredFields.isEmpty();
return (this.inputDetails == null || this.inputDetails.isEmpty()) && !this.isOneClick;
}

/**
Expand Down Expand Up @@ -330,4 +305,22 @@ public boolean equals(Object obj) {
}
return ((PaymentMethod) obj).getPaymentMethodData().equals(this.paymentMethodData);
}

@Override
public int hashCode() {
return this.paymentMethodData.hashCode();
}

/**
* Legacy method to get the deprecated requiredFields map.
* @return Map<String, Object> that can be filled out and passed to the old interface.
*/
@Deprecated
public Map<String, Object> getRequiredFieldsMap() {
Map<String, Object> requiredFields = new HashMap<>();
for (InputDetail inputDetail : inputDetails) {
requiredFields.put(inputDetail.getKey(), null);
}
return requiredFields;
}
}
Original file line number Diff line number Diff line change
@@ -1,19 +1,19 @@
package com.adyen.core.models.paymentdetails;

import java.util.Collection;

/**
* PaymentDetails class for one click credit card payments if only the CVC code is required.
*/
public class CVCOnlyPaymentDetails extends PaymentDetails {

private static final String CARD_DETAILS_CVC = "cardDetails.cvc";
public static final String CARD_DETAILS_CVC = "cardDetails.cvc";

/**
* Create PaymentDetails for recurring one click credit card payment.
* @param cvc The cvc code collected from the user.
*/
public CVCOnlyPaymentDetails(final String cvc) {
map.put(CARD_DETAILS_CVC, cvc);
public CVCOnlyPaymentDetails(Collection<InputDetail> inputDetails) {
super(inputDetails);
}

public boolean fillCvc(final String cvc) {
return super.fill(CARD_DETAILS_CVC, cvc);
}
}
Loading

0 comments on commit 534293d

Please sign in to comment.