braintree / braintree-android-drop-in

Braintree Drop-In SDK for Android
https://developers.braintreepayments.com/guides/drop-in/android/v2
MIT License
124 stars 79 forks source link

Issue while integrating in A Fragment #40

Closed ravdeepsingh22 closed 7 years ago

ravdeepsingh22 commented 7 years ago

General information

Issue description

Hello I need help with Android Integration inside a fragment , It is working fine when the code is implemented in an Activity but in My Case , i need to implement it in a Fragment .

I am trying to call the dropin ui from a Fragment but unable to do so.

Steps i followed :- 1) I fetched the braintree token using get_braintree_token(rootview.getContext()) .

2) After getting token i passed it to onBraintreeSubmit(braintreeToken ,viewb) 3) When it reaches startActivityForResult() in onBraintreeSubmit function ,The BrainTree UI is not inflated .It directly moves to onActivityResult() with resultcode 1 and some random Request code . I have written my functions Below.

public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {

rootview = inflater.inflate(R.layout.fragment_map, container, false);
get_braintree_token(rootview.getContext());
return rootview;
}
public void get_braintree_token(final Context viewb)
{

StringRequest stringRequest = new StringRequest(Request.Method.GET, "My server URL",
    new Response.Listener<String>() {
                    @Override
                    public void onResponse(String response) {
                        // Display the first 500 characters of the response string.
                        braintreeToken = response.toString();
                        Log.e("Braintreetoken","token is:"+braintreeToken);

                        onBraintreeSubmit(braintreeToken, viewb);

                    }
                }, new Response.ErrorListener() {
            @Override
            public void onErrorResponse(VolleyError error) {
                braintreeToken = null;
            }
        });
// Add the request to the RequestQueue.
        requestQueue.add(stringRequest);

    }

public void onBraintreeSubmit(String token, Context c) {
        Log.e("tokenreceived",token);
        DropInRequest dropInRequest = new  DropInRequest();

        dropInRequest.clientToken(token);
        Intent drop = dropInRequest.getIntent(c);
        startActivityForResult(drop, BRAINTREE_REQUEST_CODE);
    }

    @Override
    public void onActivityResult(int requestCode, int resultCode, Intent data) {
        if (requestCode == BRAINTREE_REQUEST_CODE) {
            if (resultCode == 1) {
                DropInResult result = data.getParcelableExtra(DropInResult.EXTRA_DROP_IN_RESULT);
                // use the result to update your UI and send the payment method nonce to your server
            } else if (resultCode == Activity.RESULT_CANCELED) {
                // the user canceled
            } else {
                // handle errors here, an exception may be available in
                Exception error = (Exception) data.getSerializableExtra(DropInActivity.EXTRA_ERROR);
            }
        }
    } 
sdcoffey commented 7 years ago

Hey @ravdeepsingh22,

The only reason that would occur is if there were a problem with your authorization. In onActivityResult, you can check the error returned in the intent like so:

@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
   if (requestCode == BRAINTREE_REQUEST_CODE) {
       if (resultCode == RESULT_OK) {
            DropInResult result = data.getParcelableExtra(DropInResult.EXTRA_DROP_IN_RESULT);
            // Do something with the result
        } else if (resultCode != RESULT_CANCELED) { // There was an error
            Exception dropinException = (Exception) data.getSerializableExtra(DropInActivity.EXTRA_ERROR); 
        }
   }
}

In your code, it looks like you're passing the result of the service call to get a client token directly to dropinRequest.clientToken(). Are you forgetting to unwrap it perhaps? In any case, see what that error value is and we can debug this further!

lkorth commented 7 years ago

Additionally if the Activity that contains your Fragment that you are using to start Drop-in is using a launchMode that is not the default of standard you will imediatlly receive a call to onActivityResult with result code 1 (Activity#RESULT_FIRST_USER). See https://stackoverflow.com/questions/8960072/onactivityresult-with-launchmode-singletask for more information.

lkorth commented 7 years ago

@ravdeepsingh22 we haven't heard back from you so I'm going to close this issue.

If you are still having problems, please comment and we will reopen it and follow up.

Esseme commented 6 years ago

I am facing a somewhat similar issue. The Drop-in UI pops up. I have set up the Debit card & Paypal options. The Debit Card option works fine onClick. The Paypal option simply loads for a while and nothing loads up onClick. I have followed this guide to setup. I donot any error in the logcat but I am stuck. Below is a snippet of my implementation:

public class FinalPaymentReportFragment extends DialogFragment {
    private static final String TAG = FinalPaymentReportFragment.class.getSimpleName();
    //TODO Use clientToken picked from the api instead of hard-coded one
    private String clientToken = "CLIENT_TOKEN";
    private final int REQUEST_CODE = 1;

    @NonNull
    @Override
    public Dialog onCreateDialog(Bundle savedInstanceState) {
        final AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());

        LayoutInflater inflater = getActivity().getLayoutInflater();
        View view = inflater.inflate(R.layout.fragment_report_payment_final, null);
        ButterKnife.bind(this, view);
        builder.setView(view);
        builder.setNegativeButton(getActivity().getString(R.string.cancel_account), new DialogInterface.OnClickListener() {
            @Override
            public void onClick(DialogInterface dialogInterface, int i) {
                dialogInterface.cancel();
            }
        });
        builder.setPositiveButton(getActivity().getString(R.string.confirm), new DialogInterface.OnClickListener() {
            @Override
            public void onClick(DialogInterface dialogInterface, int i) {
                doPositiveClick();
            }
        });
        return builder.create();
    }

    //BrainTreeSubmit Method
    public void onBraintreeSubmit(View v) {
        DropInRequest dropInRequest = new DropInRequest()
                .clientToken(clientToken);
        startActivityForResult(dropInRequest.getIntent(getActivity()), REQUEST_CODE);
    }

    @Override
    public void onActivityResult(int requestCode, int resultCode, Intent data) {
        if (requestCode == REQUEST_CODE) {
            if (resultCode == Activity.RESULT_OK) {
                DropInResult result = data.getParcelableExtra(DropInResult.EXTRA_DROP_IN_RESULT);
                String paymentNonce = result.getPaymentMethodNonce().getNonce();
                Log.d(TAG, "The PaymentNonce is " + paymentNonce);
                sendPaymentNonceToserver(paymentNonce);
                // use the result to update your UI and send the payment method nonce to your server
            } else if (resultCode == Activity.RESULT_CANCELED) {
                // the user canceled
                Log.d(TAG, "The user canceled the payment ");
            } else if (resultCode != Activity.RESULT_CANCELED) {
                Exception dropinException = (Exception) data.getSerializableExtra(DropInActivity.EXTRA_ERROR);
                Log.d("Drop-in Exception", "The exception is " + dropinException.getLocalizedMessage());
            } else {
                // handle errors here, an exception may be available in
                Exception error = (Exception) data.getSerializableExtra(DropInActivity.EXTRA_ERROR);
                Log.d(TAG, "The mu-error is " + error.getMessage());
            }
        }
    }

    private void doPositiveClick(){
        DropInRequest dropInRequest = new DropInRequest()
                .clientToken(clientToken);
        startActivityForResult(dropInRequest.getIntent(getActivity()), REQUEST_CODE);
    }

    //Method To send PaymentNonce To Server
    private void sendPaymentNonceToserver(String paymentNonce){
        //TODO Add Logic to send the payment nonce to the backend
        RequestParams params = new RequestParams("NONCE", paymentNonce);
        AsyncHttpClient client = new AsyncHttpClient();
        //TODO use an actual url to send the Nonce to the backend
        client.post("Server Post Url for the Nonce", params, new TextHttpResponseHandler() {
            @Override
            public void onFailure(int statusCode, Header[] headers, String responseString, Throwable throwable) {
                Log.d(TAG, "Error: Failed to talk to server ");
                Log.d(TAG, "The error is " + throwable.getMessage());

            }

            @Override
            public void onSuccess(int statusCode, Header[] headers, String responseString) {
                Log.d(TAG, "Good things happening " + "the response string is "+ responseString);

            }
        });
    }

}

I added the code snippet below to the Android Manifest so as to enable Paypal:

<activity android:name="com.braintreepayments.api.BraintreeBrowserSwitchActivity"
            android:launchMode="singleTask">
            <intent-filter>
                <action android:name="android.intent.action.VIEW" ></action>
                <category android:name="android.intent.category.DEFAULT" ></category>
                <category android:name="android.intent.category.BROWSABLE" ></category>
                <data android:scheme="${applicationId}.braintree" ></data>
            </intent-filter>
        </activity>

Where could I be going wrong?

quinnjn commented 6 years ago

@Esseme can you create a new issue with this problem and we can diagnose it there? You can tag the issue if you feel it is relevant.

I don't want to spam other listeners on this old thread with new comments.

harshaanagha commented 6 years ago

DropInRequest dropInRequest = new DropInRequest() .clientToken(token); startActivityForResult(dropInRequest.getIntent(getContext()), REQUEST_CODE);

If am selecting Creditcard option getting success as result if am selection paypal then am getting error payment methode nonce more than once showing.

@Override public void onActivityResult(int requestCode, int resultCode, Intent data) { if (requestCode == REQUEST_CODE) { if (resultCode == RESULT_OK) { DropInResult result = data.getParcelableExtra(DropInResult.EXTRA_DROP_IN_RESULT); PaymentMethodNonce nonce = result.getPaymentMethodNonce(); //String deviceData = result.getDeviceData(); String strNonce = nonce.getNonce(); HashMap paramsHash = new HashMap<>(); paramsHash.put("amount", "250"); paramsHash.put("nonce", strNonce); sendPayments(paramsHash); } else if (resultCode == RESULT_CANCELED) { Toast.makeText(getContext(), "User Cancelled", Toast.LENGTH_LONG).show(); } else { Exception error = (Exception) data.getSerializableExtra(DropInActivity.EXTRA_ERROR); Log.d("EDMT_ERROR", error.toString()); } } else if (requestCode == REQUEST_CODE_PAYPAL) { if (resultCode == RESULT_OK) { try { /DropInResult result = data.getParcelableExtra(DropInResult.EXTRA_DROP_IN_RESULT); PaymentMethodNonce nonce = result.getPaymentMethodNonce();/

                BraintreeFragment mBraintreeFragment = BraintreeFragment.newInstance(getActivity(), token);
                /*
                mBraintreeFragment.addListener(braintreeSuccessListener);
                mBraintreeFragment.addListener(braintreeErrorListener);
                mBraintreeFragment.addListener(braintreeCancelListener);
                */
                PayPalRequest request = new PayPalRequest("150")
                        .currencyCode("USD");
                final HashMap paramsHash = new HashMap<>();
                paramsHash.put("amount", request.getAmount());
                PayPal.requestBillingAgreement(mBraintreeFragment, request);
                //PayPalAccountNonce payPalAccountNonce;
                mBraintreeFragment.addListener(new PaymentMethodNonceCreatedListener() {
                    @Override
                    public void onPaymentMethodNonceCreated(PaymentMethodNonce paymentMethodNonce) {
                        //PayPalAccountNonce payPalAccountNonce = (PayPalAccountNonce) paymentMethodNonce;
                        //String nonce = payPalAccountNonce.getNonce();
                        Log.d("paymentMethodNonce :", paymentMethodNonce.toString());
                        String nonce = paymentMethodNonce.getNonce();
                        if (paymentMethodNonce instanceof PayPalAccountNonce) {
                            PayPalAccountNonce payPalAccountNonce = (PayPalAccountNonce) paymentMethodNonce;
                            // Access additional information
                            String email = payPalAccountNonce.getEmail();
                            Log.d("email", email);
                            String firstName = payPalAccountNonce.getFirstName();
                            Log.d("firstName", firstName);
                            String lastName = payPalAccountNonce.getLastName();
                            Log.d("lastName", lastName);
                            String phone = payPalAccountNonce.getPhone();
                            Log.d("phone", phone);
                            // See PostalAddress.java for details
                            PostalAddress billingAddress = payPalAccountNonce.getBillingAddress();
                            Log.d("billingAddress", billingAddress.toString());
                            PostalAddress shippingAddress = payPalAccountNonce.getShippingAddress();
                            Log.d("shippingAddress", shippingAddress.toString());
                        }
                        paramsHash.put("nonce", nonce);
                    }
                });
                //PaymentMethodNonce nonce = listener.get();
                //PayPalAccountNonce payPalAccountNonce = (PayPalAccountNonce)listener;
                //String nonce = payPalAccountNonce.getNonce();
                sendPayments(paramsHash);
            } catch (InvalidArgumentException e) {
                // There was an issue with your authorization string.
            }
        } else if (resultCode == RESULT_CANCELED) {
            Toast.makeText(getContext(), "User Cancelled", Toast.LENGTH_LONG).show();
        } else {
            Exception error = (Exception) data.getSerializableExtra(DropInActivity.EXTRA_ERROR);
            Log.d("EDMT_ERROR", error.toString());
        }
    } else {
        Toast.makeText(getContext(), "other option selected", Toast.LENGTH_LONG).show();
    }

}

private void sendPayments(final HashMap<String, String> paramsHashLoc) { RequestQueue queue = Volley.newRequestQueue(getActivity()); StringRequest stringRequest = new StringRequest(Request.Method.POST, APIUrl.API_CHECK_OUT, new com.android.volley.Response.Listener() { @Override public void onResponse(String response) { Toast.makeText(getContext(), "res:" + response.toString(), Toast.LENGTH_LONG).show(); if (response.toString().contains("success")) { Toast.makeText(getContext(), "Trasaction successful", Toast.LENGTH_LONG).show(); pay.setVisibility(View.GONE); } else { Log.e("error response",response.toString()); Toast.makeText(getContext(), "Trasaction failed", Toast.LENGTH_LONG).show();

                    }
                    Log.d("EDMT_Log", response.toString());
                }
            }, new com.android.volley.Response.ErrorListener() {
        @Override
        public void onErrorResponse(VolleyError error) {
            Log.d("EDMT_ERROR", error.toString());
        }
    }) {
        @Override
        protected Map<String, String> getParams() throws AuthFailureError {
            if (paramsHashLoc == null)
                return null;
            Map<String, String> params = new HashMap<>();
            for (String key : params.keySet()) {
                params.put(key, paramsHashLoc.get(key));
            }
            return paramsHashLoc;
        }

        @Override
        public Map<String, String> getHeaders() throws AuthFailureError {
            Map<String, String> params = new HashMap<>();
            params.put("Content-Type", "application/x-www-form-urlencoded");
            return params;
        }
    };
    queue.add(stringRequest);
}
aries255 commented 5 years ago

DropInRequest dropInRequest = new DropInRequest() .clientToken(token); startActivityForResult(dropInRequest.getIntent(getContext()), REQUEST_CODE);

If am selecting Creditcard option getting success as result if am selection paypal then am getting error payment methode nonce more than once showing.

@override public void onActivityResult(int requestCode, int resultCode, Intent data) { if (requestCode == REQUEST_CODE) { if (resultCode == RESULT_OK) { DropInResult result = data.getParcelableExtra(DropInResult.EXTRA_DROP_IN_RESULT); PaymentMethodNonce nonce = result.getPaymentMethodNonce(); //String deviceData = result.getDeviceData(); String strNonce = nonce.getNonce(); HashMap paramsHash = new HashMap<>(); paramsHash.put("amount", "250"); paramsHash.put("nonce", strNonce); sendPayments(paramsHash); } else if (resultCode == RESULT_CANCELED) { Toast.makeText(getContext(), "User Cancelled", Toast.LENGTH_LONG).show(); } else { Exception error = (Exception) data.getSerializableExtra(DropInActivity.EXTRA_ERROR); Log.d("EDMT_ERROR", error.toString()); } } else if (requestCode == REQUEST_CODE_PAYPAL) { if (resultCode == RESULT_OK) { try { /_DropInResult result = data.getParcelableExtra(DropInResult.EXTRA_DROP_INRESULT); PaymentMethodNonce nonce = result.getPaymentMethodNonce();/

                BraintreeFragment mBraintreeFragment = BraintreeFragment.newInstance(getActivity(), token);
                /*
                mBraintreeFragment.addListener(braintreeSuccessListener);
                mBraintreeFragment.addListener(braintreeErrorListener);
                mBraintreeFragment.addListener(braintreeCancelListener);
                */
                PayPalRequest request = new PayPalRequest("150")
                        .currencyCode("USD");
                final HashMap paramsHash = new HashMap<>();
                paramsHash.put("amount", request.getAmount());
                PayPal.requestBillingAgreement(mBraintreeFragment, request);
                //PayPalAccountNonce payPalAccountNonce;
                mBraintreeFragment.addListener(new PaymentMethodNonceCreatedListener() {
                    @Override
                    public void onPaymentMethodNonceCreated(PaymentMethodNonce paymentMethodNonce) {
                        //PayPalAccountNonce payPalAccountNonce = (PayPalAccountNonce) paymentMethodNonce;
                        //String nonce = payPalAccountNonce.getNonce();
                        Log.d("paymentMethodNonce :", paymentMethodNonce.toString());
                        String nonce = paymentMethodNonce.getNonce();
                        if (paymentMethodNonce instanceof PayPalAccountNonce) {
                            PayPalAccountNonce payPalAccountNonce = (PayPalAccountNonce) paymentMethodNonce;
                            // Access additional information
                            String email = payPalAccountNonce.getEmail();
                            Log.d("email", email);
                            String firstName = payPalAccountNonce.getFirstName();
                            Log.d("firstName", firstName);
                            String lastName = payPalAccountNonce.getLastName();
                            Log.d("lastName", lastName);
                            String phone = payPalAccountNonce.getPhone();
                            Log.d("phone", phone);
                            // See PostalAddress.java for details
                            PostalAddress billingAddress = payPalAccountNonce.getBillingAddress();
                            Log.d("billingAddress", billingAddress.toString());
                            PostalAddress shippingAddress = payPalAccountNonce.getShippingAddress();
                            Log.d("shippingAddress", shippingAddress.toString());
                        }
                        paramsHash.put("nonce", nonce);
                    }
                });
                //PaymentMethodNonce nonce = listener.get();
                //PayPalAccountNonce payPalAccountNonce = (PayPalAccountNonce)listener;
                //String nonce = payPalAccountNonce.getNonce();
                sendPayments(paramsHash);
            } catch (InvalidArgumentException e) {
                // There was an issue with your authorization string.
            }
        } else if (resultCode == RESULT_CANCELED) {
            Toast.makeText(getContext(), "User Cancelled", Toast.LENGTH_LONG).show();
        } else {
            Exception error = (Exception) data.getSerializableExtra(DropInActivity.EXTRA_ERROR);
            Log.d("EDMT_ERROR", error.toString());
        }
    } else {
        Toast.makeText(getContext(), "other option selected", Toast.LENGTH_LONG).show();
    }

}

private void sendPayments(final HashMap<String, String> paramsHashLoc) { RequestQueue queue = Volley.newRequestQueue(getActivity()); StringRequest stringRequest = new StringRequest(Request.Method.POST, APIUrl.API_CHECK_OUT, new com.android.volley.Response.Listener() { @override public void onResponse(String response) { Toast.makeText(getContext(), "res:" + response.toString(), Toast.LENGTH_LONG).show(); if (response.toString().contains("success")) { Toast.makeText(getContext(), "Trasaction successful", Toast.LENGTH_LONG).show(); pay.setVisibility(View.GONE); } else { Log.e("error response",response.toString()); Toast.makeText(getContext(), "Trasaction failed", Toast.LENGTH_LONG).show();

                    }
                    Log.d("EDMT_Log", response.toString());
                }
            }, new com.android.volley.Response.ErrorListener() {
        @Override
        public void onErrorResponse(VolleyError error) {
            Log.d("EDMT_ERROR", error.toString());
        }
    }) {
        @Override
        protected Map<String, String> getParams() throws AuthFailureError {
            if (paramsHashLoc == null)
                return null;
            Map<String, String> params = new HashMap<>();
            for (String key : params.keySet()) {
                params.put(key, paramsHashLoc.get(key));
            }
            return paramsHashLoc;
        }

        @Override
        public Map<String, String> getHeaders() throws AuthFailureError {
            Map<String, String> params = new HashMap<>();
            params.put("Content-Type", "application/x-www-form-urlencoded");
            return params;
        }
    };
    queue.add(stringRequest);
}

Hello. Can I get the full source code of this? How to make work the Paypal function in the dropin request!

FarethIs commented 5 years ago

I have a problem about Tokenization Key or client token was invalid for Braintree. Below is my coding for credit/debit card.

public class CartActivity extends AppCompatActivity implements RecyclerItemTouchHelperListener {

private static final int PAYMENT_REQUEST_CODE = 7777 ;
RecyclerView recycler_cart;
Button btn_place_order;

List<Cart> cartList = new ArrayList<>();

CompositeDisposable compositeDisposable;

CartAdapter cartAdapter;

RelativeLayout rootLayout;

IAndroidFootballTicketAPI mService;
IAndroidFootballTicketAPI mServiceScalars;

//Global String
String token,amount;
HashMap<String,String> params;

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

    compositeDisposable = new CompositeDisposable();

    mService = Common.getAPI();
    mServiceScalars = Common.getScalarsAPI();

    recycler_cart = (RecyclerView)findViewById(R.id.recycler_cart);
    recycler_cart.setLayoutManager(new LinearLayoutManager(this));
    recycler_cart.setHasFixedSize(true);

    ItemTouchHelper.SimpleCallback simpleCallback = new RecyclerItemTouchHelper(0, ItemTouchHelper.LEFT,this);
    new ItemTouchHelper(simpleCallback).attachToRecyclerView(recycler_cart);

    btn_place_order = (Button)findViewById(R.id.btn_place_order);
    btn_place_order.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            placeOrder();
        }
    });

    rootLayout = (RelativeLayout)findViewById(R.id.rootLayout);

    loadCartItems();

    loadToken();
}

private void loadToken() {

    final android.app.AlertDialog waitingDialog = new SpotsDialog(CartActivity.this);
    waitingDialog.show();
    waitingDialog.setMessage("Please wait...");

    AsyncHttpClient client = new AsyncHttpClient();
    client.get(Common.API_TOKEN_URL, new TextHttpResponseHandler() {
        @Override
        public void onFailure(int statusCode, Header[] headers, String responseString, Throwable throwable) {
            waitingDialog.dismiss();
            btn_place_order.setEnabled(false);

            Toast.makeText(CartActivity.this, throwable.getMessage(), Toast.LENGTH_SHORT).show();
        }

        @Override
        public void onSuccess(int statusCode, Header[] headers, String responseString) {
            waitingDialog.dismiss();

            token = responseString;
            btn_place_order.setEnabled(true);
        }
    });
}

private void placeOrder() {

    if (Common.currentUser != null) {
        //Create dialog
        AlertDialog.Builder builder = new AlertDialog.Builder(this);
        builder.setTitle("Submit Order");

        View submit_order_layout = LayoutInflater.from(this).inflate(R.layout.submit_order_layout, null);

        //Event
        builder.setView(submit_order_layout);
        builder.setNegativeButton("CANCEL", new DialogInterface.OnClickListener() {
            @Override
            public void onClick(DialogInterface dialog, int which) {
                dialog.dismiss();
            }
        }).setPositiveButton("SUBMIT", new DialogInterface.OnClickListener() {
            @Override
            public void onClick(DialogInterface dialog, int which) {

                //Payment
                DropInRequest dropInRequest = new DropInRequest().clientToken(token);
                startActivityForResult(dropInRequest.getIntent(CartActivity.this), PAYMENT_REQUEST_CODE);

            }
        });

        builder.show();
    }
    else
    {
        //Require Login
        AlertDialog.Builder builder = new AlertDialog.Builder(CartActivity.this);
        builder.setTitle("NOT LOGIN ?");
        builder.setMessage("Please login or register account to submit order");
        builder.setNegativeButton("CANCEL", new DialogInterface.OnClickListener() {
            @Override
            public void onClick(DialogInterface dialog, int which) {
                dialog.dismiss();
            }
        }).setPositiveButton("OK", new DialogInterface.OnClickListener() {
            @Override
            public void onClick(DialogInterface dialog, int which) {
                dialog.dismiss();
                startActivity(new Intent(CartActivity.this,MainActivity.class));
                finish();
            }
        }).show();
    }
}

//CTRL+O

@Override
protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
    if (requestCode == PAYMENT_REQUEST_CODE)
    {
        if (resultCode == RESULT_OK)
        {
            DropInResult result = data.getParcelableExtra(DropInResult.EXTRA_DROP_IN_RESULT);
            PaymentMethodNonce nonce = result.getPaymentMethodNonce();
            String strNonce = nonce.getNonce();

            if (Common.cartRepository.sumPrice() > 0)
            {
                amount = String.valueOf(Common.cartRepository.sumPrice());
                params = new HashMap<>();

                params.put("amount",amount);
                params.put("nonce",strNonce);

                sendPayment();
            }
            else
            {
                Toast.makeText(this, "Payment amount is 0", Toast.LENGTH_SHORT).show();
            }
        }
        else if (resultCode == RESULT_CANCELED)
            Toast.makeText(this, "Payment cancelled", Toast.LENGTH_SHORT).show();
        else
        {
            Exception error = (Exception)data.getSerializableExtra(DropInActivity.EXTRA_ERROR);
            Log.e("EDMT_ERROR",error.getMessage());
        }
    }
}

private void sendPayment() {

    mServiceScalars.payment(params.get("nonce"),params.get("amount"))
            .enqueue(new Callback<String>() {
                @Override
                public void onResponse(Call<String> call, Response<String> response) {
                    if (response.body().contains("Successful"))//.toString().contains
                    {
                        Toast.makeText(CartActivity.this, "Transaction successful", Toast.LENGTH_SHORT).show();

                        //Submit Order
                        compositeDisposable.add(
                                Common.cartRepository.getCartItems()
                                        .observeOn(AndroidSchedulers.mainThread())
                                        .subscribeOn(Schedulers.io())
                                        .subscribe(new Consumer<List<Cart>>() {
                                            @Override
                                            public void accept(List<Cart> carts) throws Exception {
                                                sendOrderToServer(Common.cartRepository.sumPrice(),carts);
                                            }
                                        })
                        );
                    }
                    else
                        {
                        Toast.makeText(CartActivity.this, "Transaction failed", Toast.LENGTH_SHORT).show();
                        }

                    Log.d("EDMT_INFO",response.body());
                }

                @Override
                public void onFailure(Call<String> call, Throwable t) {
                    Log.d("EDMT_INFO",t.getMessage());
                }
            });
}

private void sendOrderToServer(float sumPrice, List<Cart> carts) {
    if (carts.size() > 0)
    {
        String orderDetail = new Gson().toJson(carts);

        mService.submitOrder(sumPrice,orderDetail,Common.currentUser.getPhone())
                .enqueue(new Callback<String>() {
                    @Override
                    public void onResponse(Call<String> call, Response<String> response) {
                        Toast.makeText(CartActivity.this, "Order submit", Toast.LENGTH_SHORT).show();

                        //Clear Cart
                        Common.cartRepository.emptyCart();
                        finish();
                    }

                    @Override
                    public void onFailure(Call<String> call, Throwable t) {
                        Log.e("ERROR",t.getMessage());
                    }
                });
    }
}
FarethIs commented 5 years ago

I already try many time about the generate API Keys, and I also already put the latest API Keys in my braintree.init.php in my server