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

Refactor session complete payment #1067

Merged
merged 13 commits into from
Jun 11, 2019
Merged
Show file tree
Hide file tree
Changes from 7 commits
Commits
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
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
import com.stripe.android.PaymentSessionData;
import com.stripe.android.Stripe;
import com.stripe.android.StripeError;
import com.stripe.android.model.Address;
import com.stripe.android.model.Customer;
import com.stripe.android.model.PaymentIntent;
import com.stripe.android.model.PaymentMethod;
Expand Down Expand Up @@ -97,6 +98,8 @@ protected void onCreate(@Nullable Bundle savedInstanceState) {
mProgressBar = findViewById(R.id.progress_bar);
mCartItemLayout = findViewById(R.id.cart_list_items);

setupPaymentSession();

addCartItems();

mConfirmPaymentButton = findViewById(R.id.btn_purchase);
Expand All @@ -112,8 +115,6 @@ protected void onCreate(@Nullable Bundle savedInstanceState) {
new AttemptPurchaseCustomerRetrievalListener(
PaymentActivity.this))));

setupPaymentSession();

mConfirmPaymentButton.setEnabled(mPaymentSession.getPaymentSessionData()
.isPaymentReadyToCharge());

Expand Down Expand Up @@ -149,6 +150,19 @@ private boolean isShippingInfoValid(@NonNull ShippingInformation shippingInfo) {
Locale.US.getCountry().equals(shippingInfo.getAddress().getCountry());
}

@NonNull
private ShippingInformation getExampleShippingInfo() {
final Address address = new Address.Builder()
.setCity("San Francisco")
.setCountry("US")
.setLine1("123 Market St")
.setLine2("#345")
.setPostalCode("94107")
.setState("CA")
.build();
return new ShippingInformation(address, "Fake Name", "(555) 555-5555");
}

/*
* Cleaning up all Rx subscriptions in onDestroy.
*/
Expand All @@ -174,7 +188,7 @@ public void onSuccess(@NonNull PaymentAuthResult result) {

@Override
public void onError(@NonNull Exception e) {
finishPayment();
displayError(e.getMessage());
mshafrir-stripe marked this conversation as resolved.
Show resolved Hide resolved
}
});

Expand All @@ -184,7 +198,7 @@ public void onError(@NonNull Exception e) {
}

private void updateConfirmPaymentButton() {
long price = mStoreCart.getTotalPrice();
final long price = mPaymentSession.getPaymentSessionData().getCartTotal();
mshafrir-stripe marked this conversation as resolved.
Show resolved Hide resolved

mConfirmPaymentButton.setText(String.format(Locale.ENGLISH,
"Pay %s", StoreUtils.getPriceString(price, null)));
Expand Down Expand Up @@ -218,7 +232,7 @@ private void addLineItems(@NonNull String currencySymbol, @NonNull StoreLineItem

private void setupTotalPriceView(@NonNull View view, @NonNull String currencySymbol) {
final TextView[] itemViews = getItemViews(view);
final long totalPrice = mStoreCart.getTotalPrice() + mShippingCosts;
final long totalPrice = mPaymentSession.getPaymentSessionData().getCartTotal();
itemViews[0].setText(getString(R.string.checkout_total_cost_label));
final String price = PayWithGoogleUtils.getPriceString(totalPrice,
mStoreCart.getCurrency());
Expand Down Expand Up @@ -258,37 +272,26 @@ private TextView[] getItemViews(@NonNull View view) {
}

@NonNull
private Map<String, Object> createCapturePaymentParams(
long price,
@NonNull String paymentMethodId,
@NonNull String customerId,
@Nullable ShippingInformation shippingInformation) {
private Map<String, Object> createCapturePaymentParams(@NonNull PaymentSessionData data,
@NonNull String customerId) {
final AbstractMap<String, Object> params = new HashMap<>();
params.put("amount", Long.toString(price));
params.put("payment_method", paymentMethodId);
params.put("amount", Long.toString(data.getCartTotal()));
params.put("payment_method", Objects.requireNonNull(data.getPaymentMethod()).id);
params.put("customer_id", customerId);
params.put("shipping", shippingInformation != null ? shippingInformation.toMap() : null);
params.put("shipping", data.getShippingInformation() != null ?
data.getShippingInformation().toMap() : null);
params.put("return_url", "stripe://payment-auth-return");
return params;
}

private void capturePayment(@NonNull String customerId) {
final long price = mStoreCart.getTotalPrice() + mShippingCosts;

final PaymentMethod paymentMethod =
mPaymentSession.getPaymentSessionData().getPaymentMethod();

if (paymentMethod == null) {
if (mPaymentSession.getPaymentSessionData().getPaymentMethod() == null) {
displayError("No payment method selected");
return;
}

final ShippingInformation shippingInformation = mPaymentSession.getPaymentSessionData()
.getShippingInformation();

final Observable<ResponseBody> stripeResponse = mService.capturePayment(
createCapturePaymentParams(price, Objects.requireNonNull(paymentMethod.id),
customerId, shippingInformation));
createCapturePaymentParams(mPaymentSession.getPaymentSessionData(), customerId));
mCompositeDisposable.add(stripeResponse
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
Expand All @@ -315,7 +318,7 @@ private void processPaymentIntent(@NonNull PaymentIntent paymentIntent) {
confirmPaymentIntent(Objects.requireNonNull(paymentIntent.getId()));
return;
}

mPaymentSession.onCompleted();
Copy link
Collaborator

Choose a reason for hiding this comment

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

Are there states the PaymentIntent can be in where we shouldn't call onCompleted? In other words, should we only do this if PaymentIntent's status is succeeded? Also, should we move this call into finishPayment()?

finishPayment();
}

Expand Down Expand Up @@ -348,7 +351,9 @@ private void finishPayment() {
private void setupPaymentSession() {
mPaymentSession = new PaymentSession(this);
mPaymentSession.init(new PaymentSessionListenerImpl(this),
new PaymentSessionConfig.Builder().build());
new PaymentSessionConfig.Builder()
.setPrepopulatedShippingInfo(getExampleShippingInfo()).build());
mshafrir-stripe marked this conversation as resolved.
Show resolved Hide resolved
mPaymentSession.setCartTotal(mStoreCart.getTotalPrice());
}

private void startLoading() {
Expand Down Expand Up @@ -393,6 +398,7 @@ private void onPaymentSessionDataChanged(@NonNull PaymentSessionData data) {
if (data.getShippingMethod() != null) {
mEnterShippingInfo.setText(data.getShippingMethod().getLabel());
mShippingCosts = data.getShippingMethod().getAmount();
mPaymentSession.setCartTotal(mStoreCart.getTotalPrice() + mShippingCosts);
addCartItems();
updateConfirmPaymentButton();
}
Expand Down

This file was deleted.

This file was deleted.

19 changes: 3 additions & 16 deletions stripe/src/main/java/com/stripe/android/PaymentSession.java
Original file line number Diff line number Diff line change
Expand Up @@ -65,23 +65,10 @@ public PaymentSession(@NonNull Activity hostActivity) {
}

/**
* Complete a payment using the given provider.
* @param provider a {@link PaymentCompletionProvider} that connects to a server and completes
* a charge on a background thread.
* Notify this payment session that it is complete
*/
public void completePayment(@NonNull PaymentCompletionProvider provider) {
Copy link
Collaborator

Choose a reason for hiding this comment

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

I wonder if we still need to call onPaymentSessionDataChanged()? Probably not because this is not an async task, but worth calling out.

provider.completePayment(mPaymentSessionData,
new PaymentResultListener() {
@Override
public void onPaymentResult(@NonNull @PaymentResult String paymentResult) {
mPaymentSessionData.setPaymentResult(paymentResult);
mCustomerSession.resetUsageTokens();
if (mPaymentSessionListener != null) {
mPaymentSessionListener
.onPaymentSessionDataChanged(mPaymentSessionData);
}
}
});
public void onCompleted() {
mCustomerSession.resetUsageTokens();
}

/**
Expand Down
24 changes: 2 additions & 22 deletions stripe/src/main/java/com/stripe/android/PaymentSessionData.java
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,6 @@ public class PaymentSessionData implements Parcelable {
private long mCartTotal = 0L;
private boolean mIsPaymentReadyToCharge;
private long mShippingTotal = 0L;
@NonNull @PaymentResultListener.PaymentResult private String mPaymentResult =
PaymentResultListener.INCOMPLETE;
@Nullable private ShippingInformation mShippingInformation;
@Nullable private ShippingMethod mShippingMethod;
@Nullable private PaymentMethod mPaymentMethod;
Expand All @@ -43,17 +41,6 @@ public long getCartTotal() {
return mCartTotal;
}

/**
* Get the payment result for this PaymentSession.
*
* @return the current payment result for this session, or INCOMPLETE if not yet finished
*/
@NonNull
@PaymentResultListener.PaymentResult
public String getPaymentResult() {
return mPaymentResult;
}

/**
* Get the whether the all the payment data is ready for making a charge. This can be used to
* set a buy button to enabled for prompt a user to fill in more information.
Expand Down Expand Up @@ -127,10 +114,6 @@ void setCartTotal(long cartTotal) {
mCartTotal = cartTotal;
}

void setPaymentResult(@NonNull @PaymentResultListener.PaymentResult String result) {
mPaymentResult = result;
}

void setPaymentMethod(@Nullable PaymentMethod paymentMethod) {
mPaymentMethod = paymentMethod;
}
Expand Down Expand Up @@ -169,14 +152,13 @@ private boolean typedEquals(@NonNull PaymentSessionData data) {
&& ObjectUtils.equals(mShippingTotal, data.mShippingTotal)
&& ObjectUtils.equals(mShippingInformation, data.mShippingInformation)
&& ObjectUtils.equals(mShippingMethod, data.mShippingMethod)
&& ObjectUtils.equals(mPaymentMethod, data.mPaymentMethod)
&& ObjectUtils.equals(mPaymentResult, data.mPaymentResult);
&& ObjectUtils.equals(mPaymentMethod, data.mPaymentMethod);
}

@Override
public int hashCode() {
return ObjectUtils.hash(mCartTotal, mIsPaymentReadyToCharge, mPaymentMethod,
mShippingTotal, mPaymentResult, mShippingInformation, mShippingMethod);
mShippingTotal, mShippingInformation, mShippingMethod);
}

/************** Parcelable *********************/
Expand All @@ -189,7 +171,6 @@ public int describeContents() {
public void writeToParcel(Parcel parcel, int i) {
parcel.writeLong(mCartTotal);
parcel.writeInt(mIsPaymentReadyToCharge ? 1 : 0);
parcel.writeString(mPaymentResult);
parcel.writeString(mPaymentMethod != null ? mPaymentMethod.toJson().toString() : null);
parcel.writeParcelable(mShippingInformation, i);
parcel.writeParcelable(mShippingMethod, i);
Expand All @@ -211,7 +192,6 @@ public PaymentSessionData[] newArray(int size) {
private PaymentSessionData(@NonNull Parcel in) {
mCartTotal = in.readLong();
mIsPaymentReadyToCharge = in.readInt() == 1;
mPaymentResult = PaymentSessionUtils.paymentResultFromString(in.readString());
mPaymentMethod = PaymentMethod.fromString(in.readString());
mShippingInformation = in.readParcelable(ShippingInformation.class.getClassLoader());
mShippingMethod = in.readParcelable(ShippingMethod.class.getClassLoader());
Expand Down

This file was deleted.

16 changes: 2 additions & 14 deletions stripe/src/test/java/com/stripe/android/PaymentSessionTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -277,20 +277,8 @@ public void completePayment_withLoggedActions_clearsLoggingTokensAndSetsResult()
assertEquals(2, loggingTokens.size());

reset(mPaymentSessionListener);
paymentSession.completePayment(new PaymentCompletionProvider() {
@Override
public void completePayment(@NonNull PaymentSessionData data,
@NonNull PaymentResultListener listener) {
listener.onPaymentResult(PaymentResultListener.SUCCESS);
}
});

ArgumentCaptor<PaymentSessionData> dataArgumentCaptor =
ArgumentCaptor.forClass(PaymentSessionData.class);
verify(mPaymentSessionListener).onPaymentSessionDataChanged(dataArgumentCaptor.capture());
PaymentSessionData capturedData = dataArgumentCaptor.getValue();
assertNotNull(capturedData);
assertEquals(PaymentResultListener.SUCCESS, capturedData.getPaymentResult());

paymentSession.onCompleted();
assertTrue(customerSession.getProductUsageTokens().isEmpty());
}

Expand Down