Skip to content
This repository has been archived by the owner on Jan 3, 2024. It is now read-only.

Commit

Permalink
[5.0.0] Big Breaking Android Refactoring
Browse files Browse the repository at this point in the history
  • Loading branch information
ngoryachev authored and isnifer committed Mar 20, 2018
1 parent 36a3c1f commit d3a31a0
Show file tree
Hide file tree
Showing 18 changed files with 1,271 additions and 722 deletions.
3 changes: 2 additions & 1 deletion android/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,8 @@ dependencies {
compile 'com.facebook.react:react-native:+'
compile 'com.android.support:support-v4:26.1.0'
compile 'com.android.support:appcompat-v7:26.1.0'
compile 'com.google.android.gms:play-services-wallet:10.+'
compile 'com.google.android.gms:play-services-wallet:11.8.0'
compile 'com.google.firebase:firebase-core:11.8.0'
compile 'com.stripe:stripe-android:6.0.0'
compile 'com.github.tipsi:CreditCardEntry:1.4.8.10'
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -145,7 +145,7 @@ public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) {
try {
currentMonth = view.getCreditCard().getExpMonth();
}catch (Exception e){
if(charSequence.length() == 0)
if (charSequence.length() == 0)
currentMonth = 0;
}
try {
Expand Down
237 changes: 237 additions & 0 deletions android/src/main/java/com/gettipsi/stripe/GoogleApiPayFlowImpl.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,237 @@
package com.gettipsi.stripe;

import android.app.Activity;
import android.content.Intent;
import android.support.annotation.NonNull;

import com.facebook.react.bridge.Promise;
import com.facebook.react.bridge.ReadableMap;
import com.gettipsi.stripe.util.ArgCheck;
import com.gettipsi.stripe.util.Converters;
import com.gettipsi.stripe.util.Fun0;
import com.google.android.gms.common.api.ApiException;
import com.google.android.gms.common.api.Status;
import com.google.android.gms.tasks.OnCompleteListener;
import com.google.android.gms.tasks.Task;
import com.google.android.gms.wallet.AutoResolveHelper;
import com.google.android.gms.wallet.CardRequirements;
import com.google.android.gms.wallet.IsReadyToPayRequest;
import com.google.android.gms.wallet.PaymentData;
import com.google.android.gms.wallet.PaymentDataRequest;
import com.google.android.gms.wallet.PaymentMethodTokenizationParameters;
import com.google.android.gms.wallet.PaymentsClient;
import com.google.android.gms.wallet.ShippingAddressRequirements;
import com.google.android.gms.wallet.TransactionInfo;
import com.google.android.gms.wallet.Wallet;
import com.google.android.gms.wallet.WalletConstants;
import com.stripe.android.BuildConfig;
import com.stripe.android.model.Token;

import java.util.Arrays;
import java.util.Collection;

import static com.gettipsi.stripe.util.Converters.convertTokenToWritableMap;
import static com.gettipsi.stripe.util.Converters.getAllowedShippingCountryCodes;
import static com.gettipsi.stripe.util.Converters.getBillingAddress;
import static com.gettipsi.stripe.util.Converters.putExtraToTokenMap;
import static com.gettipsi.stripe.util.PayParams.BILLING_ADDRESS_REQUIRED;
import static com.gettipsi.stripe.util.PayParams.CURRENCY_CODE;
import static com.gettipsi.stripe.util.PayParams.SHIPPING_ADDRESS_REQUIRED;
import static com.gettipsi.stripe.util.PayParams.TOTAL_PRICE;

/**
* Created by ngoriachev on 13/03/2018.
* see https://developers.google.com/pay/api/tutorial
*/
public final class GoogleApiPayFlowImpl extends PayFlow {

private static final String TAG = GoogleApiPayFlowImpl.class.getSimpleName();
private static final int LOAD_PAYMENT_DATA_REQUEST_CODE = 100500;

private PaymentsClient mPaymentsClient;
private Promise payPromise;

public GoogleApiPayFlowImpl(@NonNull Fun0<Activity> activityProvider) {
super(activityProvider);
}

private PaymentsClient createPaymentsClient(@NonNull Activity activity) {
return Wallet.getPaymentsClient(
activity,
new Wallet.WalletOptions.Builder().setEnvironment(getEnvironment()).build());
}

private void isReadyToPay(@NonNull Activity activity, @NonNull final Promise promise) {
ArgCheck.nonNull(activity);
ArgCheck.nonNull(promise);

IsReadyToPayRequest request =
IsReadyToPayRequest.newBuilder()
.addAllowedPaymentMethod(WalletConstants.PAYMENT_METHOD_CARD)
.addAllowedPaymentMethod(WalletConstants.PAYMENT_METHOD_TOKENIZED_CARD)
.build();
mPaymentsClient = createPaymentsClient(activity);
Task<Boolean> task = mPaymentsClient.isReadyToPay(request);
task.addOnCompleteListener(
new OnCompleteListener<Boolean>() {
public void onComplete(Task<Boolean> task) {
try {
boolean result = task.getResult(ApiException.class);
promise.resolve(result);
} catch (ApiException exception) {
promise.reject(TAG, String.format("Error, statusCode: %d", exception.getStatusCode()));
}
}
});
}

private PaymentMethodTokenizationParameters createPaymentMethodTokenizationParameters() {
return PaymentMethodTokenizationParameters.newBuilder()
.setPaymentMethodTokenizationType(WalletConstants.PAYMENT_METHOD_TOKENIZATION_TYPE_PAYMENT_GATEWAY)
.addParameter("gateway", "stripe")
.addParameter("stripe:publishableKey", getPublishableKey())
.addParameter("stripe:version", BuildConfig.VERSION_NAME)
.build();
}

private PaymentDataRequest createPaymentDataRequest(ReadableMap payParams) {
final String estimatedTotalPrice = payParams.getString(TOTAL_PRICE);
final String currencyCode = payParams.getString(CURRENCY_CODE);
final boolean billingAddressRequired = Converters.getValue(payParams, BILLING_ADDRESS_REQUIRED, false);
final Boolean shippingAddressRequired = Converters.getValue(payParams, SHIPPING_ADDRESS_REQUIRED, false);
final Collection<String> allowedCountryCodes = getAllowedShippingCountryCodes(payParams);

return createPaymentDataRequest(estimatedTotalPrice, currencyCode, billingAddressRequired, shippingAddressRequired, allowedCountryCodes);
}

private PaymentDataRequest createPaymentDataRequest(@NonNull final String totalPrice,
@NonNull final String currencyCode,
final boolean billingAddressRequired,
final boolean shippingAddressRequired,
@NonNull final Collection<String> countryCodes
) {

ArgCheck.isDouble(totalPrice);
ArgCheck.notEmptyString(currencyCode);

PaymentDataRequest.Builder builder = PaymentDataRequest.newBuilder();
builder.setTransactionInfo(
TransactionInfo.newBuilder()
.setTotalPriceStatus(WalletConstants.TOTAL_PRICE_STATUS_ESTIMATED)
.setTotalPrice(totalPrice)
.setCurrencyCode(currencyCode)
.build());

builder
.setCardRequirements(
CardRequirements.newBuilder()
.addAllowedCardNetworks(
Arrays.asList(
WalletConstants.CARD_NETWORK_AMEX,
WalletConstants.CARD_NETWORK_DISCOVER,
WalletConstants.CARD_NETWORK_VISA,
WalletConstants.CARD_NETWORK_MASTERCARD))
.setBillingAddressRequired(billingAddressRequired)
.build())
.addAllowedPaymentMethod(WalletConstants.PAYMENT_METHOD_CARD)
.addAllowedPaymentMethod(WalletConstants.PAYMENT_METHOD_TOKENIZED_CARD)
.setShippingAddressRequired(shippingAddressRequired);

if (countryCodes.size() > 0) {
builder.setShippingAddressRequirements(
ShippingAddressRequirements.newBuilder()
.addAllowedCountryCodes(countryCodes)
.build());
}

builder.setPaymentMethodTokenizationParameters(createPaymentMethodTokenizationParameters());
return builder.build();
}

private void startPaymentRequest(@NonNull Activity activity, @NonNull PaymentDataRequest request) {
ArgCheck.nonNull(activity);
ArgCheck.nonNull(request);

mPaymentsClient = createPaymentsClient(activity);

AutoResolveHelper.resolveTask(
mPaymentsClient.loadPaymentData(request),
activity,
LOAD_PAYMENT_DATA_REQUEST_CODE);
}

@Override
public void paymentRequestWithAndroidPay(@NonNull ReadableMap payParams, @NonNull Promise promise) {
ArgCheck.nonNull(payParams);
ArgCheck.nonNull(promise);

Activity activity = activityProvider.call();
if (activity == null) {
promise.reject(TAG, NO_CURRENT_ACTIVITY_MSG);
return;
}

this.payPromise = promise;
startPaymentRequest(activity, createPaymentDataRequest(payParams));
}

@Override
public void deviceSupportsAndroidPay(@NonNull Promise promise) {
Activity activity = activityProvider.call();
if (activity == null) {
promise.reject(TAG, NO_CURRENT_ACTIVITY_MSG);
return;
}

if (!isPlayServicesAvailable(activity)) {
promise.reject(TAG, PLAY_SERVICES_ARE_NOT_AVAILABLE_MSG);
return;
}

isReadyToPay(activity, promise);
}

public boolean onActivityResult(Activity activity, int requestCode, int resultCode, Intent data) {
if (payPromise == null) {
return false;
}

switch (requestCode) {
case LOAD_PAYMENT_DATA_REQUEST_CODE:
switch (resultCode) {
case Activity.RESULT_OK:
PaymentData paymentData = PaymentData.getFromIntent(data);
ArgCheck.nonNull(paymentData);
String tokenJson = paymentData.getPaymentMethodToken().getToken();
Token token = Token.fromString(tokenJson);
if (token == null) {
payPromise.reject(TAG, JSON_PARSING_ERROR_MSG);
} else {
payPromise.resolve(putExtraToTokenMap(
convertTokenToWritableMap(token),
getBillingAddress(paymentData),
paymentData.getShippingAddress()));
}
break;
case Activity.RESULT_CANCELED:
payPromise.reject(TAG, PURCHASE_CANCELLED_MSG);
break;
case AutoResolveHelper.RESULT_ERROR:
Status status = AutoResolveHelper.getStatusFromIntent(data);
// Log the status for debugging.
// Generally, there is no need to show an error to
// the user as the Google Pay API will do that.
payPromise.reject(TAG, status.getStatusMessage());
break;

default:
// Do nothing.
}
payPromise = null;
return true;
}

return false;
}

}
Loading

0 comments on commit d3a31a0

Please sign in to comment.