2016-04-08 49 views
-1

我正在使用braintree api来获取应用程序中添加卡的付款。它的工作原理罚款,有时甚至死机。BraintreeHttpClient.setBaseUrl(java.lang.String)null对象引用

这是我的堆栈跟踪,

E/AndroidRuntime: FATAL EXCEPTION: Thread-833 
                  Process: cl.tempclick, PID: 29509 
                  java.lang.NullPointerException: Attempt to invoke virtual method 'com.braintreepayments.api.internal.HttpClient com.braintreepayments.api.internal.BraintreeHttpClient.setBaseUrl(java.lang.String)' on a null object reference 
                   at com.braintreepayments.api.BraintreeFragment.setConfiguration(BraintreeFragment.java:488) 
                   at com.braintreepayments.api.BraintreeFragment$5.onConfigurationFetched(BraintreeFragment.java:415) 
                   at com.braintreepayments.api.ConfigurationManager.getConfiguration(ConfigurationManager.java:46) 
                   at com.braintreepayments.api.BraintreeFragment.fetchConfiguration(BraintreeFragment.java:412) 
                   at com.braintreepayments.api.BraintreeFragment.waitForConfiguration(BraintreeFragment.java:458) 
                   at com.braintreepayments.api.TokenizationClient.tokenize(TokenizationClient.java:72) 
                   at com.braintreepayments.api.Card.tokenize(Card.java:29) 
                   at cl.tk.ui.activities.sub_activity.AddPayment$UIThreadHandler$1.run(AddPayment.java:364) 
                   at java.lang.Thread.run(Thread.java:818) 

这是我的代码的活动,

package cl.tk.ui.activities.sub_activity; 

import android.content.BroadcastReceiver; 
import android.content.Context; 
import android.content.DialogInterface; 
import android.content.Intent; 
import android.content.IntentFilter; 
import android.os.Bundle; 
import android.os.Handler; 
import android.os.Message; 
import android.support.v4.content.ContextCompat; 
import android.support.v4.content.LocalBroadcastManager; 
import android.support.v7.app.AppCompatActivity; 
import android.view.MotionEvent; 
import android.view.View; 
import android.widget.Button; 
import android.widget.ImageView; 
import android.widget.TextView; 

import com.braintreepayments.api.BraintreeFragment; 
import com.braintreepayments.api.exceptions.InvalidArgumentException; 
import com.braintreepayments.api.interfaces.PaymentMethodNonceCreatedListener; 
import com.braintreepayments.api.models.CardBuilder; 
import com.braintreepayments.api.models.PaymentMethodNonce; 

import cl.tk.R; 
import cl.tk.controllers.constants.Constants; 
import cl.tk.controllers.constants.Enums_String; 
import cl.tk.controllers.listeners.ProcessedResult; 
import cl.tk.controllers.rest_api.RetrofitAdapters; 
import cl.tk.ui.activities.Register; 
import cl.tk.ui.fragments.dialog.DTDialog; 
import cl.tk.ui.iBAPViews.editext.pattern.PatternedEditText; 
import cl.tk.utility.CreditCard; 
import cl.tk.utility.CustomException; 
import cl.tek.utility.GeneralFunctions; 
import cl.tk.utility.MonthYearPicker; 
import cl.tk.utility.Validation; 
import cl.tk.utility.fonts.FontsManager; 
import retrofit.Callback; 
import retrofit.RetrofitError; 
import retrofit.client.Response; 


public class AddPayment extends AppCompatActivity implements  View.OnClickListener,View.OnTouchListener, ProcessedResult,PaymentMethodNonceCreatedListener 
{ 
private Handler uiThreadHandler; 
private TextView tvExpiryDate; 
//private EditText edCvv,ed_cardHOlderName,edZip; 
private PatternedEditText edCardNumber; 
private MonthYearPicker myp; 
private String mClientToken=null; 
private CreditCard creditCard =null; 

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

    uiThreadHandler = new UIThreadHandler(); 
    initialze(); 

    downloadBraintreeTOken(); 
} 

private void downloadBraintreeTOken() 
{ 
    RetrofitAdapters.get().getBraintreeToken(new Callback<Response>() { 
     @Override 
     public void success(Response response, Response response2) { 
      parseResult(response); 
     } 

     @Override 
     public void failure(RetrofitError error) { 
      uiThreadHandler.sendEmptyMessage(Constants.ActivityBasicsCode.HIDEDIALOG); 
      Message message = uiThreadHandler.obtainMessage(Constants.ActivityBasicsCode.SHOWTOAST); 
      message.obj = error.getLocalizedMessage(); 
      uiThreadHandler.sendMessage(message); 
     } 
    }); 
} 

private void initialze() 
{ 
    GeneralFunctions.setToolbarMsgIconHide(this, Constants.ToolbarConstants.PAYMENTS, true); 

    Button buttonAdd=GeneralFunctions.findViewByIdAndCast(this,R.id.payment_bt_addCard); 
    buttonAdd.setOnClickListener(this); 
    GeneralFunctions.setColorSelector(ContextCompat.getColor(this, R.color.color175), ContextCompat.getColor(this, R.color.color1A9), buttonAdd); 

    TextView tv_defult=GeneralFunctions.findViewByIdAndCast(this,R.id.payment_ct_default); 
    tv_defult.setOnClickListener(this); 

    FontsManager.initFormAssets(this, Enums_String.FontsNameLato.SEMIBOLD.toString()); 
    FontsManager.changeFonts(tv_defult); 

    edCardNumber=GeneralFunctions.findViewByIdAndCast(this,R.id.payment_ed_cardNumber); 
    tvExpiryDate=GeneralFunctions.findViewByIdAndCast(this,R.id.payment_tv_expiryDate); 
    tvExpiryDate.setOnTouchListener(this); 

    myp = new MonthYearPicker(this); 
    myp.build(new DialogInterface.OnClickListener() { 
     @Override 
     public void onClick(DialogInterface dialog, int which) { 
      tvExpiryDate.setText(myp.getSelectedMonth() + 1 + "/" + myp.getSelectedYear()); 
     } 
    }, null); 
} 

@Override 
protected void onResume() { 
    super.onResume(); 
    IntentFilter filter = new IntentFilter(Enums_String.LocalReceiver.INTERENT.toString()); 
    LocalBroadcastManager.getInstance(this).registerReceiver(mMessageReceiver, filter); 
} 

@Override 
protected void onPause() { 
    super.onPause(); 
    LocalBroadcastManager.getInstance(this).unregisterReceiver(mMessageReceiver); 
} 

@Override 
public void onClick(View v) { 
    switch (v.getId()) 
    { 
     case R.id.payment_bt_addCard: 
      uiThreadHandler.sendEmptyMessage(Constants.ActivityBasicsCode.VALIDATION); 
      break; 
    } 
} 

@Override 
public boolean onTouch(View v, MotionEvent event) { 
    if(event.getAction() == MotionEvent.ACTION_UP) 
    { 
     if(v.getId()==R.id.payment_tv_expiryDate) 
     { 
      if(myp.pickerDialog != null && !myp.pickerDialog.isShowing()) 
       myp.pickerDialog.dismiss(); 
      myp.show(); 
     } 
     return true; 
    } 
    return false; 
} 

@Override 
public <IResponse, IMethod, IExtra> void processedResult(IResponse iResponse, IMethod iMethod, IExtra iExtra) { 

} 


@Override 
public <IResponse, IMethod> void processedResult(IResponse iResponse, IMethod iMethod) { 
    switch (iMethod.toString()) 
    { 
     case Constants.CallbackConstants.VIEW_ERROR: { 
      Message message = uiThreadHandler.obtainMessage(Constants.ActivityBasicsCode.SETERROR); 
      message.obj=iResponse; 
      uiThreadHandler.sendMessage(message); 
     } 
     break; 
     case Constants.CallbackConstants.BACK: 
      finish(); 
      break; 
    } 
} 

@Override 
public void onPaymentMethodNonceCreated(final PaymentMethodNonce paymentMethodNonce) { 

} 


private void setError(String errorMsg) { 
    if (errorMsg.equalsIgnoreCase("cardNumber")) 
     GeneralFunctions.setError(null,String.format(getString(R.string.ed_error_invalid),edCardNumber.getTag().toString()),edCardNumber); 
    else if (errorMsg.equalsIgnoreCase("cardDate")) 
     GeneralFunctions.setError(null,String.format(getString(R.string.ed_error_invalid),tvExpiryDate.getTag().toString()),tvExpiryDate); 
} 



private class UIThreadHandler extends Handler { 
    @Override 
    public void handleMessage(Message msg) 
    { 
     switch (msg.what) { 
      case Constants.ActivityBasicsCode.CARDERROR: 
       GeneralFunctions.setError((CustomException)msg.obj,null,null); 
       break; 
      case Constants.ActivityBasicsCode.SETERROR: 
       setError(msg.obj.toString()); 
       break; 
      case Constants.ActivityBasicsCode.SHOWTOAST: 
      { 
       String text=(String)msg.obj; 
       GeneralFunctions.showToast(text,AddPayment.this); 
      } 
      break; 
      case Constants.ActivityBasicsCode.HIDEDIALOG: 
       GeneralFunctions.hideProgressDialog(Constants.DialogConstants.Transparent, AddPayment.this); 
       break; 
      case Constants.ActivityBasicsCode.SHOWDIALOG: 
      { 
       DTDialog dtDialog=DTDialog.newInstance(); 
       GeneralFunctions.showProgressDialog(dtDialog, Constants.DialogConstants.Transparent, AddPayment.this); 
      }break; 
      case Constants.ActivityBasicsCode.VALIDATION: { 
       new Thread(new Runnable() { 
        @Override 
        public void run() 
        { 
         try { 
          if(Validation.validate(AddPayment.this)) { 
           creditCard = new CreditCard(GeneralFunctions.getText(edCardNumber),GeneralFunctions.getText(tvExpiryDate),AddPayment.this); 

           boolean validation = creditCard.validateCard(); 
           if (validation) { 
            if(mClientToken==null) { 
             downloadBraintreeTOken(); 
             Message message = uiThreadHandler.obtainMessage(Constants.ActivityBasicsCode.SHOWTOAST); 
             message.obj = getString(R.string.toast_payment_token); 
             uiThreadHandler.sendMessage(message); 
             return; 
            } 
            BraintreeFragment braintreeFragment= BraintreeFragment.newInstance(AddPayment.this, mClientToken); 

            if(null==braintreeFragment) 
            { 
             Message message = uiThreadHandler.obtainMessage(Constants.ActivityBasicsCode.SHOWTOAST); 
             message.obj = getString(R.string.toast_payment_fragment); 
             uiThreadHandler.sendMessage(message); 
             uiThreadHandler.sendEmptyMessage(Constants.ActivityBasicsCode.SHOWDIALOG); 
            } 
            else { 
             CardBuilder cardBuilder = new CardBuilder() 
               .cardNumber(creditCard.getNumber().replaceAll("-", "").trim()) 
               .expirationDate(creditCard.getExpriyDate()); 
             com.braintreepayments.api.Card.tokenize(braintreeFragment, cardBuilder); //On this line my app crashes randomly 
            } 
           } 
          } 
         }catch (CustomException e) 
         { 
          Message message = uiThreadHandler.obtainMessage(Constants.ActivityBasicsCode.CARDERROR); 
          message.obj=e; 
          uiThreadHandler.sendMessage(message); 
         } catch (InvalidArgumentException e) { 
          e.printStackTrace(); 
         } 
        } 
       }).start(); 
       break; 
      } 
     } 
     super.handleMessage(msg); 
    } 
} 

}

这是我的gradle这个版本, compile'c​​om.braintreepayments.api:braintree:2. +'

回答

0

完全披露:我为Braintree工作。

您是refreshing the client token every time you go through the checkout process as required?我发现如果它是空的,你只能从服务器上下载Braintree标记。

没有深入了解您的CreditCard类或其validateCard方法,另一种可能性可能是您传递到Card.tokenize的CardBuilder对象可能不完整。

如果您仍然遇到问题,请联系Braintree support以帮助您调试集成。

+0

是的,首先我从onCreate()服务器上下载braintree令牌,然后再次检查,如果它为空,那么再次尝试下载令牌....并且卡完好形成....崩溃次数更少。 – TheReprator

+0

我们发现了问题并发布了修复程序。请将您的Android v.zero SDK版本升级到2.2.4。欲了解更多信息,请看这里:https://github.com/braintree/braintree_android/issues/89 –

相关问题