diff --git a/core/src/main/java/com/hyperwallet/android/Hyperwallet.java b/core/src/main/java/com/hyperwallet/android/Hyperwallet.java index d0eecf36..0dac0141 100644 --- a/core/src/main/java/com/hyperwallet/android/Hyperwallet.java +++ b/core/src/main/java/com/hyperwallet/android/Hyperwallet.java @@ -307,6 +307,34 @@ public void updateBankCard(@NonNull final HyperwalletBankCard bankCard, performRestTransaction(builder, listener); } + /** + * Updates the {@link PayPalAccount} for the User associated with the authentication token returned from + * {@link HyperwalletAuthenticationTokenProvider#retrieveAuthenticationToken(HyperwalletAuthenticationTokenListener)}. + * + *

To identify the {@code PayPalAccount} that is going to be updated, the transfer method token must be + * set as part of the {@code PayPalAccount} object passed in.

+ * + *

The {@link HyperwalletListener} that is passed in to this method invocation will receive the responses from + * processing the request.

+ * + *

This function will requests a new authentication token via {@link HyperwalletAuthenticationTokenProvider} + * if the current one is expired or about to expire.

+ * + * @param payPalAccount the {@code PayPalAccount} to be created; must not be null + * @param listener the callback handler of responses from the Hyperwallet platform; must not be null + */ + public void updatePayPalAccount(@NonNull final PayPalAccount payPalAccount, + @NonNull final HyperwalletListener listener) { + PathFormatter pathFormatter = new PathFormatter("users/{0}/paypal-accounts/{1}", + payPalAccount.getField(HyperwalletTransferMethod.TransferMethodFields.TOKEN)); + + RestTransaction.Builder builder = new RestTransaction.Builder<>(PUT, pathFormatter, + new TypeReference() { + }, listener).jsonModel(payPalAccount); + + performRestTransaction(builder, listener); + } + /** * Deactivates the {@link HyperwalletBankAccount} linked to the transfer method token specified. The * {@code HyperwalletBankAccount} being deactivated must belong to the User that is associated with the diff --git a/core/src/main/java/com/hyperwallet/android/model/PayPalAccount.java b/core/src/main/java/com/hyperwallet/android/model/PayPalAccount.java index c658316c..59c84d5a 100644 --- a/core/src/main/java/com/hyperwallet/android/model/PayPalAccount.java +++ b/core/src/main/java/com/hyperwallet/android/model/PayPalAccount.java @@ -42,7 +42,7 @@ public class PayPalAccount extends HyperwalletTransferMethod { /** - * Constructor to build bank card, based on json object + * Constructor to build PayPal Account, based on json object */ public PayPalAccount(@NonNull JSONObject jsonObject) throws JSONException { super(jsonObject); diff --git a/core/src/test/java/com/hyperwallet/android/HyperwalletTestSuite.java b/core/src/test/java/com/hyperwallet/android/HyperwalletTestSuite.java index 27b1182e..efd821d2 100644 --- a/core/src/test/java/com/hyperwallet/android/HyperwalletTestSuite.java +++ b/core/src/test/java/com/hyperwallet/android/HyperwalletTestSuite.java @@ -13,6 +13,7 @@ import com.hyperwallet.android.transfermethod.HyperwalletRetrieveTransferMethodConfigurationKeysTest; import com.hyperwallet.android.transfermethod.HyperwalletUpdateBankAccountTest; import com.hyperwallet.android.transfermethod.HyperwalletUpdateBankCardTest; +import com.hyperwallet.android.transfermethod.HyperwalletUpdatePayPalAccountTest; import org.junit.runner.RunWith; import org.junit.runners.Suite; @@ -27,6 +28,7 @@ HyperwalletGetBankCardTest.class, HyperwalletUpdateBankAccountTest.class, HyperwalletUpdateBankCardTest.class, + HyperwalletUpdatePayPalAccountTest.class, HyperwalletDeactivateBankAccountTest.class, HyperwalletDeactivateBankCardTest.class, HyperwalletListTransferMethodsTest.class, diff --git a/core/src/test/java/com/hyperwallet/android/transfermethod/HyperwalletUpdatePayPalAccountTest.java b/core/src/test/java/com/hyperwallet/android/transfermethod/HyperwalletUpdatePayPalAccountTest.java new file mode 100644 index 00000000..004331e2 --- /dev/null +++ b/core/src/test/java/com/hyperwallet/android/transfermethod/HyperwalletUpdatePayPalAccountTest.java @@ -0,0 +1,147 @@ +package com.hyperwallet.android.transfermethod; + +import static org.hamcrest.CoreMatchers.is; +import static org.hamcrest.CoreMatchers.notNullValue; +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.hasSize; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.never; +import static org.mockito.Mockito.verify; + +import static com.hyperwallet.android.model.HyperwalletTransferMethod.TransferMethodFields.CREATED_ON; +import static com.hyperwallet.android.model.HyperwalletTransferMethod.TransferMethodFields.EMAIL; +import static com.hyperwallet.android.model.HyperwalletTransferMethod.TransferMethodFields.STATUS; +import static com.hyperwallet.android.model.HyperwalletTransferMethod.TransferMethodFields.TOKEN; +import static com.hyperwallet.android.model.HyperwalletTransferMethod.TransferMethodFields.TRANSFER_METHOD_COUNTRY; +import static com.hyperwallet.android.model.HyperwalletTransferMethod.TransferMethodFields.TRANSFER_METHOD_CURRENCY; +import static com.hyperwallet.android.model.HyperwalletTransferMethod.TransferMethodFields.TYPE; +import static com.hyperwallet.android.model.HyperwalletTransferMethod.TransferMethodTypes.PAYPAL_ACCOUNT; + +import com.hyperwallet.android.Hyperwallet; +import com.hyperwallet.android.exception.HyperwalletException; +import com.hyperwallet.android.exception.HyperwalletRestException; +import com.hyperwallet.android.listener.HyperwalletListener; +import com.hyperwallet.android.model.HyperwalletError; +import com.hyperwallet.android.model.HyperwalletErrors; +import com.hyperwallet.android.model.PayPalAccount; +import com.hyperwallet.android.rule.HyperwalletExternalResourceManager; +import com.hyperwallet.android.rule.HyperwalletMockWebServer; +import com.hyperwallet.android.rule.HyperwalletSdkMock; + +import org.junit.Rule; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.ArgumentCaptor; +import org.mockito.Captor; +import org.mockito.Mock; +import org.mockito.junit.MockitoJUnit; +import org.mockito.junit.MockitoRule; +import org.robolectric.RobolectricTestRunner; + +import java.net.HttpURLConnection; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.TimeUnit; + +import okhttp3.mockwebserver.RecordedRequest; + +@RunWith(RobolectricTestRunner.class) +public class HyperwalletUpdatePayPalAccountTest { + @Rule + public HyperwalletMockWebServer mServer = new HyperwalletMockWebServer(); + @Rule + public HyperwalletSdkMock mSdkMock = new HyperwalletSdkMock(mServer); + @Rule + public HyperwalletExternalResourceManager mExternalResourceManager = new HyperwalletExternalResourceManager(); + @Rule + public MockitoRule mMockito = MockitoJUnit.rule(); + + @Mock + private HyperwalletListener mListener; + + @Captor + private ArgumentCaptor mPayPalAccountCaptor; + @Captor + private ArgumentCaptor mExceptionCaptor; + + private final CountDownLatch mAwait = new CountDownLatch(1); + + @Test + public void testUpdatePayPalAccount_withSuccess() throws InterruptedException { + String responseBody = mExternalResourceManager.getResourceContent("paypal_account_update_response.json"); + mServer.mockResponse().withHttpResponseCode(HttpURLConnection.HTTP_OK).withBody(responseBody).mock(); + + final PayPalAccount payPalAccount = new PayPalAccount + .Builder() + .email("jsmith2@paypal.com") + .token("trm-ac5727ac-8fe7-42fb-b69d-977ebdd7b48b") + .build(); + + assertThat(payPalAccount.getField(EMAIL), is("jsmith2@paypal.com")); + assertThat(payPalAccount.getField(TOKEN), is("trm-ac5727ac-8fe7-42fb-b69d-977ebdd7b48b")); + + Hyperwallet.getDefault().updatePayPalAccount(payPalAccount, mListener); + mAwait.await(50, TimeUnit.MILLISECONDS); + + RecordedRequest recordedRequest = mServer.getRequest(); + verify(mListener).onSuccess(mPayPalAccountCaptor.capture()); + verify(mListener, never()).onFailure(any(HyperwalletException.class)); + + PayPalAccount payPalAccountResponse = mPayPalAccountCaptor.getValue(); + assertThat(payPalAccountResponse, is(notNullValue())); + + assertThat(recordedRequest.getPath(), + is("/rest/v3/users/usr-fbfd5848-60d0-43c5-8462-099c959b49c7/paypal-accounts/trm-ac5727ac-8fe7-42fb" + + "-b69d-977ebdd7b48b")); + + assertThat(payPalAccountResponse.getField(TOKEN), is("trm-ac5727ac-8fe7-42fb-b69d-977ebdd7b48b")); + assertThat(payPalAccountResponse.getField(STATUS), is("ACTIVATED")); + assertThat(payPalAccountResponse.getField(TYPE), is(PAYPAL_ACCOUNT)); + assertThat(payPalAccountResponse.getField(EMAIL), is("jsmith2@paypal.com")); + assertThat(payPalAccountResponse.getField(TRANSFER_METHOD_CURRENCY), is("USD")); + assertThat(payPalAccountResponse.getField(TRANSFER_METHOD_COUNTRY), is("US")); + assertThat(payPalAccountResponse.getField(CREATED_ON), is("2019-01-09T22:50:14")); + } + + @Test + public void testUpdatePayPalAccount_withValidationError() throws InterruptedException { + + String responseBody = mExternalResourceManager.getResourceContentError( + "paypal_account_update_error_response.json"); + mServer.mockResponse().withHttpResponseCode(HttpURLConnection.HTTP_BAD_REQUEST).withBody(responseBody).mock(); + + final PayPalAccount payPalAccount = new PayPalAccount + .Builder() + .email("00G0G1ema.com") + .token("trm-56b976c5-26b2-42fa-87cf-14b3366673c6") + .build(); + + assertThat(payPalAccount.getField(EMAIL), is("00G0G1ema.com")); + assertThat(payPalAccount.getField(TOKEN), + is("trm-56b976c5-26b2-42fa-87cf-14b3366673c6")); + + Hyperwallet.getDefault().updatePayPalAccount(payPalAccount, mListener); + mAwait.await(50, TimeUnit.MILLISECONDS); + + RecordedRequest recordedRequest = mServer.getRequest(); + verify(mListener, never()).onSuccess(any(PayPalAccount.class)); + verify(mListener).onFailure(mExceptionCaptor.capture()); + + HyperwalletException hyperwalletException = mExceptionCaptor.getValue(); + assertThat(hyperwalletException, is(notNullValue())); + assertThat(((HyperwalletRestException) hyperwalletException).getHttpCode(), + is(HttpURLConnection.HTTP_BAD_REQUEST)); + + assertThat(recordedRequest.getPath(), + is("/rest/v3/users/usr-fbfd5848-60d0-43c5-8462-099c959b49c7/paypal-accounts/trm-56b976c5-26b2-42fa-87cf" + + "-14b3366673c6")); + + HyperwalletErrors hyperwalletErrors = hyperwalletException.getHyperwalletErrors(); + assertThat(hyperwalletErrors, is(notNullValue())); + assertThat(hyperwalletErrors.getErrors(), hasSize(1)); + + HyperwalletError hyperwalletError1 = hyperwalletErrors.getErrors().get(0); + assertThat(hyperwalletError1.getCode(), is("CONSTRAINT_VIOLATIONS")); + assertThat(hyperwalletError1.getFieldName(), is("email")); + assertThat(hyperwalletError1.getMessage(), is("Invalid Email")); + } +} diff --git a/core/src/test/resources/errors/paypal_account_update_error_response.json b/core/src/test/resources/errors/paypal_account_update_error_response.json new file mode 100644 index 00000000..408baab1 --- /dev/null +++ b/core/src/test/resources/errors/paypal_account_update_error_response.json @@ -0,0 +1,9 @@ +{ + "errors": [ + { + "message": "Invalid Email", + "fieldName": "email", + "code": "CONSTRAINT_VIOLATIONS" + } + ] +} \ No newline at end of file diff --git a/core/src/test/resources/paypal_account_update_response.json b/core/src/test/resources/paypal_account_update_response.json new file mode 100644 index 00000000..a157c0a0 --- /dev/null +++ b/core/src/test/resources/paypal_account_update_response.json @@ -0,0 +1,17 @@ +{ + "token": "trm-ac5727ac-8fe7-42fb-b69d-977ebdd7b48b", + "type": "PAYPAL_ACCOUNT", + "status": "ACTIVATED", + "createdOn": "2019-01-09T22:50:14", + "transferMethodCountry": "US", + "transferMethodCurrency": "USD", + "email": "jsmith2@paypal.com", + "links": [ + { + "params": { + "rel": "self" + }, + "href": "https://api.sandbox.hyperwallet.com/rest/v3/users/usr-c4292f1a-866f-4310-a289-b916853939de/paypal-accounts/trm-ac5727ac-8fe7-42fb-b69d-977ebdd7b48b" + } + ] +} \ No newline at end of file