Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[v7 Beta] Create DropInLauncher #468

Open
wants to merge 20 commits into
base: v7_beta
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 19 commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
7118268
Rename DropInIntentData to DropInLaunchIntent.
sshropshire Mar 27, 2024
257d30e
Remove deprecated DropInClient methods.
sshropshire Mar 27, 2024
e6a98ac
Rename DropInLifecycleObserver to DropInLauncher.
sshropshire Mar 27, 2024
7a70517
Extract DropInLauncher success and error handling logic from DropInCl…
sshropshire Mar 27, 2024
7ca4634
Remove invalidateClientToken() method.
sshropshire Mar 27, 2024
7ad19eb
Remove DropInClient#getAuthorization() internal call.
sshropshire Mar 27, 2024
3247387
Fix DropInLauncherUnitTest.
sshropshire Mar 27, 2024
7978016
Migrate DropInClient to using context.
sshropshire Mar 27, 2024
4ae9532
Migrate fetch method to a RecentPaymentMethodsClient.
sshropshire Mar 27, 2024
4f85b19
Remove DropInClient and fix broken imports.
sshropshire Mar 27, 2024
9d00464
Fix unit tests.
sshropshire Mar 27, 2024
6457aa5
Remove DropInClientParams class.
sshropshire Mar 27, 2024
6810ac7
Add class and constructor documentation to RecentPaymentMethodsClient.
sshropshire Mar 27, 2024
1a842ce
Provide documentation for DropInLauncherCallback.
sshropshire Mar 27, 2024
8220458
Rename DropInLaunchIntent to DropInLaunchInput and make it package pr…
sshropshire Mar 27, 2024
e0658c3
Add place authorization string in DropInRequest.
sshropshire Apr 3, 2024
7bdd2ac
Revert "Add place authorization string in DropInRequest."
sshropshire Apr 3, 2024
618d3f8
Add TODO.
sshropshire Apr 3, 2024
821b249
Update CHANGELOG.
sshropshire Apr 3, 2024
1977a95
Rename launchDropIn to start on DropInLauncher.
sshropshire Apr 8, 2024
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
7 changes: 7 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,12 @@
# Braintree Android Drop-In Release Notes

## unreleased

* Breaking Changes
* Remove `DropInClient` and replace it with `DropInLauncher`
* Add `DropInLauncherCallback` to receive a result from `DropInActivity` via the Activity Result API
* Create `RecentPaymentMethodsClient` with `fetchMostRecentPaymentMethod()`

## 6.15.0

* Refresh vaulted payment methods list after 3DS is canceled (fixes #455)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,6 @@
import android.content.DialogInterface.OnClickListener;
import android.content.Intent;
import android.os.Bundle;
import android.text.TextUtils;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
import android.widget.ArrayAdapter;
Expand All @@ -16,13 +14,6 @@
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.app.ActivityCompat.OnRequestPermissionsResultCallback;

import com.braintreepayments.api.DropInClient;
import com.braintreepayments.demo.models.ClientToken;

import retrofit.Callback;
import retrofit.RetrofitError;
import retrofit.client.Response;

@SuppressWarnings("deprecation")
public abstract class BaseActivity extends AppCompatActivity implements OnRequestPermissionsResultCallback,
ActionBar.OnNavigationListener {
Expand Down
64 changes: 50 additions & 14 deletions Demo/src/main/java/com/braintreepayments/demo/MainActivity.java
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import static android.view.View.GONE;
import static android.view.View.VISIBLE;

import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.os.Bundle;
Expand All @@ -16,7 +17,8 @@
import androidx.cardview.widget.CardView;

import com.braintreepayments.api.CardNonce;
import com.braintreepayments.api.DropInClient;
import com.braintreepayments.api.ClientTokenCallback;
import com.braintreepayments.api.DropInLauncher;
import com.braintreepayments.api.DropInListener;
import com.braintreepayments.api.DropInPaymentMethod;
import com.braintreepayments.api.DropInRequest;
Expand All @@ -26,6 +28,7 @@
import com.braintreepayments.api.PayPalAccountNonce;
import com.braintreepayments.api.PaymentMethodNonce;
import com.braintreepayments.api.PostalAddress;
import com.braintreepayments.api.RecentPaymentMethodsClient;
import com.braintreepayments.api.ThreeDSecureAdditionalInformation;
import com.braintreepayments.api.ThreeDSecurePostalAddress;
import com.braintreepayments.api.ThreeDSecureRequest;
Expand All @@ -36,6 +39,8 @@
import com.google.android.gms.wallet.TransactionInfo;
import com.google.android.gms.wallet.WalletConstants;

import java.lang.ref.WeakReference;

public class MainActivity extends BaseActivity implements DropInListener {

private static final String KEY_NONCE = "nonce";
Expand All @@ -53,17 +58,32 @@ public class MainActivity extends BaseActivity implements DropInListener {
private Button addPaymentMethodButton;
private Button purchaseButton;

private DropInClient dropInClient;
private RecentPaymentMethodsClient recentPaymentMethodsClient;

private boolean purchased = false;

private SharedPreferences.OnSharedPreferenceChangeListener sharedPreferenceChangeListener;

private DemoClientTokenProvider clientTokenProvider;

private String authString;

private final DropInLauncher dropInLauncher = new DropInLauncher(this, (dropInResult) -> {
Exception error = dropInResult.getError();
if (error != null) {
onDropInFailure(error);
} else {
onDropInSuccess(dropInResult);
}
});

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main_activity);

clientTokenProvider = new DemoClientTokenProvider(this);

paymentMethod = findViewById(R.id.payment_method);
paymentMethodIcon = findViewById(R.id.payment_method_icon);
paymentMethodTitle = findViewById(R.id.payment_method_title);
Expand Down Expand Up @@ -120,18 +140,33 @@ private void registerSharedPreferencesListener() {

private void configureDropInClient() {
if (Settings.useTokenizationKey(this)) {
String tokenizationKey = Settings.getEnvironmentTokenizationKey(this);
dropInClient = new DropInClient(this, tokenizationKey);
dropInClient.setListener(this);
authString = Settings.getEnvironmentTokenizationKey(this);
addPaymentMethodButton.setVisibility(VISIBLE);
} else {
dropInClient = new DropInClient(this, new DemoClientTokenProvider(this));
dropInClient.setListener(this);
dropInClient.fetchMostRecentPaymentMethod(this, (dropInResult, error) -> {
if (dropInResult != null) {
handleDropInResult(dropInResult);
} else {
addPaymentMethodButton.setVisibility(VISIBLE);
Context appContext = getApplicationContext();
WeakReference<MainActivity> activityRef = new WeakReference<>(this);
clientTokenProvider.getClientToken(new ClientTokenCallback() {
@Override
public void onSuccess(@NonNull String clientToken) {
MainActivity activity = activityRef.get();
if (activity != null) {
authString = clientToken;
recentPaymentMethodsClient = new RecentPaymentMethodsClient(appContext, clientToken);
activity.addPaymentMethodButton.setVisibility(VISIBLE);

recentPaymentMethodsClient.fetchMostRecentPaymentMethod(activity, (dropInResult, error) -> {
if (dropInResult != null) {
handleDropInResult(dropInResult);
} else {
addPaymentMethodButton.setVisibility(VISIBLE);
}
});
}
}

@Override
public void onFailure(@NonNull Exception e) {
onDropInFailure(e);
}
});
}
Expand All @@ -152,7 +187,8 @@ public void launchDropIn(View v) {
dropInRequest.setThreeDSecureRequest(demoThreeDSecureRequest());
}

dropInClient.launchDropIn(dropInRequest);
// TODO: make auth string a required DropInRequest constructor parameter
dropInLauncher.launchDropIn(authString, dropInRequest);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This reads a little odd to me since it's like the inverse of one another, not sure if something like this would make it feel less awward:

Suggested change
dropInLauncher.launchDropIn(authString, dropInRequest);
dropInLauncher.start(authString, dropInRequest);

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah def that's a good call. It aligns nicely with our SDKs as a whole. I'll do this in a separate commit to make sure all occurrences are renamed.

}

private ThreeDSecureRequest demoThreeDSecureRequest() {
Expand Down Expand Up @@ -191,7 +227,7 @@ public void purchase(View v) {

public void handleDropInResult(DropInResult result) {
if (result.getPaymentMethodType() == null
|| result.getPaymentMethodType() == DropInPaymentMethod.GOOGLE_PAY) {
|| result.getPaymentMethodType() == DropInPaymentMethod.GOOGLE_PAY) {
// google pay doesn't have a payment method nonce to display; fallback to OG ui
addPaymentMethodButton.setVisibility(VISIBLE);
} else {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
package com.braintreepayments.api;

import static com.braintreepayments.api.DropInLauncher.EXTRA_AUTHORIZATION;
import static com.braintreepayments.api.DropInLauncher.EXTRA_AUTHORIZATION_ERROR;
import static com.braintreepayments.api.DropInLauncher.EXTRA_CHECKOUT_REQUEST;
import static com.braintreepayments.api.DropInLauncher.EXTRA_CHECKOUT_REQUEST_BUNDLE;

import android.content.Intent;
import android.os.Bundle;

Expand Down Expand Up @@ -65,18 +70,17 @@ protected void onCreate(Bundle savedInstanceState) {
Intent intent = getIntent();

Exception error =
(Exception) intent.getSerializableExtra(DropInClient.EXTRA_AUTHORIZATION_ERROR);
(Exception) intent.getSerializableExtra(EXTRA_AUTHORIZATION_ERROR);
if (error != null) {
// echo back error to merchant via activity result
finishDropInWithError(error);
return;
}

if (dropInInternalClient == null) {
String authorization = intent.getStringExtra(DropInClient.EXTRA_AUTHORIZATION);
String sessionId = intent.getStringExtra(DropInClient.EXTRA_SESSION_ID);
String authorization = intent.getStringExtra(EXTRA_AUTHORIZATION);
DropInRequest dropInRequest = getDropInRequest(intent);
dropInInternalClient = new DropInInternalClient(this, authorization, sessionId, dropInRequest);
dropInInternalClient = new DropInInternalClient(this, authorization, dropInRequest);
}

alertPresenter = new AlertPresenter();
Expand Down Expand Up @@ -120,9 +124,9 @@ void finishDropInWithError(Exception e) {
}

private DropInRequest getDropInRequest(Intent intent) {
Bundle bundle = intent.getParcelableExtra(DropInClient.EXTRA_CHECKOUT_REQUEST_BUNDLE);
Bundle bundle = intent.getParcelableExtra(EXTRA_CHECKOUT_REQUEST_BUNDLE);
bundle.setClassLoader(DropInRequest.class.getClassLoader());
return bundle.getParcelable(DropInClient.EXTRA_CHECKOUT_REQUEST);
return bundle.getParcelable(EXTRA_CHECKOUT_REQUEST);
}

@VisibleForTesting
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@
package com.braintreepayments.api;

import static com.braintreepayments.api.DropInClient.EXTRA_AUTHORIZATION;
import static com.braintreepayments.api.DropInClient.EXTRA_CHECKOUT_REQUEST;
import static com.braintreepayments.api.DropInClient.EXTRA_CHECKOUT_REQUEST_BUNDLE;
import static com.braintreepayments.api.DropInClient.EXTRA_SESSION_ID;
import static com.braintreepayments.api.DropInLauncher.EXTRA_AUTHORIZATION;
import static com.braintreepayments.api.DropInLauncher.EXTRA_CHECKOUT_REQUEST;
import static com.braintreepayments.api.DropInLauncher.EXTRA_CHECKOUT_REQUEST_BUNDLE;
import static com.braintreepayments.api.DropInResult.EXTRA_ERROR;

import android.content.Context;
Expand All @@ -15,16 +14,15 @@
import androidx.annotation.Nullable;
import androidx.appcompat.app.AppCompatActivity;

class DropInActivityResultContract extends ActivityResultContract<DropInIntentData, DropInResult> {
class DropInActivityResultContract extends ActivityResultContract<DropInLaunchInput, DropInResult> {

@NonNull
@Override
public Intent createIntent(@NonNull Context context, DropInIntentData input) {
public Intent createIntent(@NonNull Context context, DropInLaunchInput input) {
Bundle dropInRequestBundle = new Bundle();
dropInRequestBundle.putParcelable(EXTRA_CHECKOUT_REQUEST, input.getDropInRequest());
return new Intent(context, DropInActivity.class)
.putExtra(EXTRA_CHECKOUT_REQUEST_BUNDLE, dropInRequestBundle)
.putExtra(EXTRA_SESSION_ID, input.getSessionId())
.putExtra(EXTRA_AUTHORIZATION, input.getAuthorization().toString());
}

Expand Down
Loading
Loading