Preyea Regmi
4 years ago
26 changed files with 187 additions and 1566 deletions
-
BIN.idea/caches/build_file_checksums.ser
-
1app/build.gradle
-
138app/src/main/java/com/gmeremit/online/gmeremittance_native/customwidgets/passwordpromptdialog/PasswordPromptDialog.java
-
7app/src/main/java/com/gmeremit/online/gmeremittance_native/domesticremit/send/presenter/DomesticRemitPresenterImpl.java
-
6app/src/main/java/com/gmeremit/online/gmeremittance_native/domesticremit/send/presenter/DomesticRemitPresenterInterface.java
-
51app/src/main/java/com/gmeremit/online/gmeremittance_native/domesticremit/send/view/DomesticRemitActivity.java
-
41app/src/main/java/com/gmeremit/online/gmeremittance_native/loginV2/view/LoginV2Activity.java
-
39app/src/main/java/com/gmeremit/online/gmeremittance_native/resendV2/presenter/resend/ReSendMoneyV2Presenter.java
-
4app/src/main/java/com/gmeremit/online/gmeremittance_native/resendV2/presenter/resend/ReSendMoneyV2PresenterInterface.java
-
56app/src/main/java/com/gmeremit/online/gmeremittance_native/resendV2/view/ReSendMoneyV2Activity.java
-
2app/src/main/java/com/gmeremit/online/gmeremittance_native/security/auth/GMEUserPasswordPromptBottomSheetDialog.java
-
9app/src/main/java/com/gmeremit/online/gmeremittance_native/sendmoneyV2/presenter/SendMoneyV2PresenterInterface.java
-
63app/src/main/java/com/gmeremit/online/gmeremittance_native/sendmoneyV2/view/SendMoneyV2Activity.java
-
73app/src/main/java/com/gmeremit/online/gmeremittance_native/topup/local/presenter/topup/LocalTopUpPresenter.java
-
7app/src/main/java/com/gmeremit/online/gmeremittance_native/topup/local/presenter/topup/LocalTopUpPresenterInterface.java
-
66app/src/main/java/com/gmeremit/online/gmeremittance_native/topup/local/view/topup/LocalTopUpActivity.java
-
6app/src/main/java/com/gmeremit/online/gmeremittance_native/transactionpasspromt/PasswordPromptListener.java
-
29app/src/main/java/com/gmeremit/online/gmeremittance_native/transactionpasspromt/gateway/TransactionPasswordPromptV2Gateway.java
-
16app/src/main/java/com/gmeremit/online/gmeremittance_native/transactionpasspromt/presenter/TransactionPasswordPromptV2InteractorInterface.java
-
273app/src/main/java/com/gmeremit/online/gmeremittance_native/transactionpasspromt/presenter/TransactionPasswordPromptV2Presenter.java
-
46app/src/main/java/com/gmeremit/online/gmeremittance_native/transactionpasspromt/presenter/TransactionPasswordPromptV2PresenterInterface.java
-
240app/src/main/java/com/gmeremit/online/gmeremittance_native/transactionpasspromt/view/TransactionBiometricPromptDialog.java
-
453app/src/main/java/com/gmeremit/online/gmeremittance_native/transactionpasspromt/view/TransactionPasswordPromptActivity.java
-
22app/src/main/res/layout/activity_domestic_remit.xml
-
19app/src/main/res/layout/activity_login_v2.xml
-
26app/src/main/res/values/styles.xml
@ -1,138 +0,0 @@ |
|||||
package com.gmeremit.online.gmeremittance_native.customwidgets.passwordpromptdialog; |
|
||||
|
|
||||
import android.app.Dialog; |
|
||||
import android.content.Context; |
|
||||
import android.content.DialogInterface; |
|
||||
import android.os.Bundle; |
|
||||
import androidx.appcompat.app.AlertDialog; |
|
||||
import android.util.Log; |
|
||||
import android.view.View; |
|
||||
import android.view.Window; |
|
||||
import android.view.WindowManager; |
|
||||
import android.view.inputmethod.InputMethodManager; |
|
||||
import android.widget.EditText; |
|
||||
import android.widget.TextView; |
|
||||
|
|
||||
import androidx.fragment.app.DialogFragment; |
|
||||
|
|
||||
import com.gmeremit.online.gmeremittance_native.R; |
|
||||
import com.gmeremit.online.gmeremittance_native.transactionpasspromt.PasswordPromptListener; |
|
||||
|
|
||||
public class PasswordPromptDialog extends DialogFragment implements View.OnClickListener { |
|
||||
|
|
||||
|
|
||||
private EditText passwordEditText; |
|
||||
|
|
||||
private TextView okButton,cancelButton; |
|
||||
private PasswordPromptListener listener; |
|
||||
|
|
||||
|
|
||||
@Override |
|
||||
public Dialog onCreateDialog(Bundle savedInstanceState) { |
|
||||
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity()); |
|
||||
View view = getActivity().getLayoutInflater().inflate(R.layout.dialog_password_prompt, null); |
|
||||
|
|
||||
passwordEditText = view.findViewById(R.id.login_password); |
|
||||
cancelButton = view.findViewById(R.id.btn_cancel); |
|
||||
okButton=view.findViewById(R.id.btn_ok); |
|
||||
|
|
||||
builder.setView(view); |
|
||||
initialize(); |
|
||||
|
|
||||
Dialog d= builder.create(); |
|
||||
d.getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_VISIBLE); |
|
||||
|
|
||||
return d; |
|
||||
|
|
||||
|
|
||||
} |
|
||||
|
|
||||
private void initialize() { |
|
||||
cancelButton.setOnClickListener(this); |
|
||||
setCancelable(false); |
|
||||
okButton.setOnClickListener(this); |
|
||||
|
|
||||
|
|
||||
} |
|
||||
|
|
||||
public void setListener(PasswordPromptListener listener) { |
|
||||
this.listener = listener; |
|
||||
} |
|
||||
|
|
||||
|
|
||||
|
|
||||
@Override |
|
||||
public void onStart() { |
|
||||
super.onStart(); |
|
||||
Window window = getDialog().getWindow(); |
|
||||
if (window != null) { |
|
||||
// window.setLayout(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT); |
|
||||
window.setBackgroundDrawableResource(R.drawable.ic_rounded_white_bg_with_inset); |
|
||||
|
|
||||
} |
|
||||
} |
|
||||
|
|
||||
@Override |
|
||||
public void onResume() { |
|
||||
super.onResume(); |
|
||||
// showKeyBoard(passwordEditText); |
|
||||
|
|
||||
} |
|
||||
|
|
||||
@Override |
|
||||
public void onClick(View v) { |
|
||||
switch (v.getId()) { |
|
||||
case R.id.btn_cancel: |
|
||||
hideKeyboard(); |
|
||||
dismiss(); |
|
||||
if(listener!=null) |
|
||||
listener.onCancelled(); |
|
||||
break; |
|
||||
case R.id.btn_ok: |
|
||||
hideKeyboard(); |
|
||||
dismiss(); |
|
||||
if(listener!=null) |
|
||||
listener.onPasswordSubmit(passwordEditText.getText().toString()); |
|
||||
break; |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
@Override |
|
||||
public void onDismiss(DialogInterface dialog) { |
|
||||
super.onDismiss(dialog); |
|
||||
cancelButton.setOnClickListener(null); |
|
||||
|
|
||||
} |
|
||||
|
|
||||
|
|
||||
|
|
||||
|
|
||||
|
|
||||
public void hideKeyboard() { |
|
||||
// Check if no view has focus: |
|
||||
try { |
|
||||
View view = getActivity().getCurrentFocus(); |
|
||||
|
|
||||
InputMethodManager inputManager = (InputMethodManager) getActivity().getSystemService(Context.INPUT_METHOD_SERVICE); |
|
||||
inputManager.hideSoftInputFromWindow(view.getWindowToken(), InputMethodManager.HIDE_NOT_ALWAYS); |
|
||||
} |
|
||||
catch(Exception ex) |
|
||||
{ |
|
||||
|
|
||||
} |
|
||||
|
|
||||
} |
|
||||
|
|
||||
@SuppressWarnings("HardCodedStringLiteral") |
|
||||
public void showKeyBoard(View view) { |
|
||||
try { |
|
||||
InputMethodManager imm = (InputMethodManager) view.getContext().getSystemService(Context.INPUT_METHOD_SERVICE); |
|
||||
imm.showSoftInput(view, InputMethodManager.SHOW_IMPLICIT); |
|
||||
Log.d("GMEEXCEPTION", "Keyboard shown"); |
|
||||
} catch (NullPointerException e) { |
|
||||
Log.d("GMEEXCEPTION", "Null pointer while showing keyboard"); |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
|
|
||||
} |
|
@ -1,6 +0,0 @@ |
|||||
package com.gmeremit.online.gmeremittance_native.transactionpasspromt; |
|
||||
|
|
||||
public interface PasswordPromptListener { |
|
||||
void onPasswordSubmit(String password); |
|
||||
void onCancelled(); |
|
||||
} |
|
@ -1,29 +0,0 @@ |
|||||
package com.gmeremit.online.gmeremittance_native.transactionpasspromt.gateway; |
|
||||
|
|
||||
import com.gmeremit.online.gmeremittance_native.GmeApplication; |
|
||||
import com.gmeremit.online.gmeremittance_native.base.PrefKeys; |
|
||||
import com.gmeremit.online.gmeremittance_native.base.PrivilegedGateway; |
|
||||
import com.gmeremit.online.gmeremittance_native.transactionpasspromt.presenter.TransactionPasswordPromptV2InteractorInterface; |
|
||||
import com.gmeremit.online.gmeremittance_native.utils.https.HttpClientV2; |
|
||||
import com.google.gson.JsonObject; |
|
||||
|
|
||||
import io.reactivex.Observable; |
|
||||
import okhttp3.ResponseBody; |
|
||||
|
|
||||
import static com.gmeremit.online.gmeremittance_native.base.PrefKeys.APP_FINGER_PRINT_ENABLED; |
|
||||
import static com.gmeremit.online.gmeremittance_native.base.PrefKeys.APP_USER_SECRET_KEY; |
|
||||
|
|
||||
public class TransactionPasswordPromptV2Gateway extends PrivilegedGateway implements TransactionPasswordPromptV2InteractorInterface.TransactionPasswordPromptV2GatewayInterface { |
|
||||
|
|
||||
|
|
||||
@Override |
|
||||
public Observable<ResponseBody> requestOtp(String auth, String Uid,String amount,String kftcId) { |
|
||||
JsonObject jsonObject=new JsonObject(); |
|
||||
jsonObject.addProperty("kftcId",kftcId); |
|
||||
jsonObject.addProperty("amount",amount); |
|
||||
jsonObject.addProperty("userId",Uid); |
|
||||
|
|
||||
return HttpClientV2.getInstance().requestOTPForSendMoney(auth,jsonObject); |
|
||||
} |
|
||||
|
|
||||
} |
|
@ -1,16 +0,0 @@ |
|||||
package com.gmeremit.online.gmeremittance_native.transactionpasspromt.presenter; |
|
||||
|
|
||||
import com.gmeremit.online.gmeremittance_native.base.BaseInteractorInterface; |
|
||||
import com.gmeremit.online.gmeremittance_native.base.PrivilegedGatewayInterface; |
|
||||
|
|
||||
import io.reactivex.Observable; |
|
||||
import okhttp3.ResponseBody; |
|
||||
|
|
||||
public interface TransactionPasswordPromptV2InteractorInterface extends BaseInteractorInterface { |
|
||||
|
|
||||
interface TransactionPasswordPromptV2GatewayInterface extends PrivilegedGatewayInterface |
|
||||
{ |
|
||||
Observable<ResponseBody> requestOtp(String auth, String Uid,String amount,String kftc); |
|
||||
|
|
||||
} |
|
||||
} |
|
@ -1,273 +0,0 @@ |
|||||
package com.gmeremit.online.gmeremittance_native.transactionpasspromt.presenter; |
|
||||
|
|
||||
import android.os.Build; |
|
||||
import android.security.keystore.KeyPermanentlyInvalidatedException; |
|
||||
import android.util.Log; |
|
||||
|
|
||||
import com.gmeremit.online.gmeremittance_native.R; |
|
||||
import com.gmeremit.online.gmeremittance_native.base.BasePresenter; |
|
||||
import com.gmeremit.online.gmeremittance_native.customwidgets.CustomAlertDialog; |
|
||||
import com.gmeremit.online.gmeremittance_native.utils.Constants; |
|
||||
import com.gmeremit.online.gmeremittance_native.utils.https.GenericApiObserverResponseV2; |
|
||||
import com.gmeremit.online.gmeremittance_native.utils.https.GenericResponseDataModel; |
|
||||
import com.gmeremit.online.gmeremittance_native.utils.https.MessageResponseDataModel; |
|
||||
import com.gmeremit.online.gmeremittance_native.security.utils.SecurityUtils; |
|
||||
import com.mtramin.rxfingerprint.data.BiometricExceptions; |
|
||||
import com.mtramin.rxfingerprint.data.FingerprintDecryptionResult; |
|
||||
|
|
||||
import java.util.concurrent.TimeUnit; |
|
||||
|
|
||||
import io.reactivex.Observable; |
|
||||
import io.reactivex.android.schedulers.AndroidSchedulers; |
|
||||
import io.reactivex.disposables.CompositeDisposable; |
|
||||
import io.reactivex.disposables.Disposable; |
|
||||
import io.reactivex.observers.DisposableObserver; |
|
||||
import io.reactivex.schedulers.Schedulers; |
|
||||
|
|
||||
public class TransactionPasswordPromptV2Presenter extends BasePresenter implements TransactionPasswordPromptV2PresenterInterface, TransactionPasswordPromptV2InteractorInterface { |
|
||||
|
|
||||
private final TransactionPasswordPromptV2PresenterInterface.TransactionPasswordPromptV2ContractInterface view; |
|
||||
private final TransactionPasswordPromptV2InteractorInterface.TransactionPasswordPromptV2GatewayInterface gateway; |
|
||||
private final CompositeDisposable compositeDisposable; |
|
||||
private final String selectedPaymentType; |
|
||||
private long updateCountdownValue; |
|
||||
private String selectedAmount; |
|
||||
private String selectedKftcId; |
|
||||
private Disposable fingerPrintScanningSubscription; |
|
||||
private boolean isKeyPermanentlyInvalidated = false; |
|
||||
|
|
||||
public TransactionPasswordPromptV2Presenter(TransactionPasswordPromptV2PresenterInterface.TransactionPasswordPromptV2ContractInterface view,TransactionPasswordPromptV2InteractorInterface.TransactionPasswordPromptV2GatewayInterface gateway, String paymentType) { |
|
||||
this.view = view; |
|
||||
this.gateway = gateway; |
|
||||
this.compositeDisposable = new CompositeDisposable(); |
|
||||
this.updateCountdownValue = -1; |
|
||||
this.selectedKftcId = ""; |
|
||||
this.selectedAmount = ""; |
|
||||
this.selectedPaymentType = paymentType; |
|
||||
|
|
||||
} |
|
||||
|
|
||||
|
|
||||
@Override |
|
||||
public void getOtp() { |
|
||||
if (updateCountdownValue == -1) { |
|
||||
this.compositeDisposable.add( |
|
||||
this.gateway.requestOtp(this.gateway.getAuth(), this.gateway.getUserID(), selectedAmount, selectedKftcId) |
|
||||
.doOnSubscribe(disposable -> view.showProgressBar(true, getStringfromStringId(R.string.requesting_otp_text))) |
|
||||
.doFinally(() -> view.showProgressBar(false, "")) |
|
||||
.subscribeOn(Schedulers.io()) |
|
||||
.observeOn(AndroidSchedulers.mainThread()) |
|
||||
.subscribeWith(new ResendRequestObserver()) |
|
||||
); |
|
||||
} else { |
|
||||
view.showResendRequestView(false); |
|
||||
view.startCountdownView(updateCountdownValue); |
|
||||
} |
|
||||
|
|
||||
} |
|
||||
|
|
||||
@Override |
|
||||
public void updateCountdown(long millisUntilFinished) { |
|
||||
this.updateCountdownValue = millisUntilFinished; |
|
||||
} |
|
||||
|
|
||||
@Override |
|
||||
public long getLatestCountDownValue() { |
|
||||
return updateCountdownValue; |
|
||||
} |
|
||||
|
|
||||
@Override |
|
||||
public void updateSelectedAmount(String selectedAmount) { |
|
||||
if (selectedAmount == null) |
|
||||
selectedAmount = ""; |
|
||||
this.selectedAmount = selectedAmount; |
|
||||
} |
|
||||
|
|
||||
@Override |
|
||||
public void updateSelectedKftcId(String selectedKftcId) { |
|
||||
if (selectedKftcId == null) |
|
||||
selectedKftcId = ""; |
|
||||
this.selectedKftcId = selectedKftcId; |
|
||||
} |
|
||||
|
|
||||
@Override |
|
||||
public boolean checkIfUserHasEnabledBiometricAuth() { |
|
||||
return false; |
|
||||
// return SecurityUtils.checkFingerPrintUsablity(view.getContext()) && gateway.isFingerPrintAuthEnabled() && gateway.getPersistedUserId() != null && gateway.getPersistedUserPwd() != null; |
|
||||
} |
|
||||
|
|
||||
|
|
||||
@Override |
|
||||
public void startObservingFingerPrintIfRequired(boolean action) { |
|
||||
if (!checkIfUserHasEnabledBiometricAuth()) { |
|
||||
view.addFingerprintIcon(false); |
|
||||
return; |
|
||||
} |
|
||||
if (!action) { |
|
||||
view.clearImageView(); |
|
||||
if (fingerPrintScanningSubscription != null && !fingerPrintScanningSubscription.isDisposed()) |
|
||||
fingerPrintScanningSubscription.dispose(); |
|
||||
} else { |
|
||||
view.addFingerprintIcon(true); |
|
||||
fingerPrintScanningSubscription = authenticateFingerprint().subscribeWith(new FingerprintDecResultObserver()); |
|
||||
compositeDisposable.add(fingerPrintScanningSubscription); |
|
||||
} |
|
||||
|
|
||||
|
|
||||
} |
|
||||
|
|
||||
private Observable<FingerprintDecResult> authenticateFingerprint() { |
|
||||
return Observable.zip(Observable.fromCallable(gateway::getPersistedUserId), |
|
||||
Observable.fromCallable(gateway::getPersistedSecretKey) |
|
||||
.flatMap(storedKey -> decryptFromKeyStore(storedKey).flatMap(decAesKey -> SecurityUtils.decryptUsingAES(gateway.getPersistedUserPwd(), decAesKey))) |
|
||||
.subscribeOn(Schedulers.io()), |
|
||||
FingerprintDecResult::new) |
|
||||
.doOnSubscribe(subs -> { |
|
||||
view.animateFingerPrintAppearAnimationIfRequired(true); |
|
||||
}) |
|
||||
.observeOn(AndroidSchedulers.mainThread()); |
|
||||
} |
|
||||
|
|
||||
private Observable<String> decryptFromKeyStore(String data) { |
|
||||
return SecurityUtils.decryptUsingKeyStore(view.getContext(),null, data) |
|
||||
.flatMap(authentication -> { |
|
||||
switch (authentication.getResult()) { |
|
||||
case FAILED: |
|
||||
return io.reactivex.Observable.error(new SecurityUtils.FailedFingerPrintException(getStringfromStringId(R.string.fingerprint_not_recognized))); |
|
||||
case HELP: |
|
||||
return io.reactivex.Observable.error(new SecurityUtils.SensorNotReadyException(authentication.getMessage())); |
|
||||
case AUTHENTICATED: |
|
||||
return Observable.just(authentication); |
|
||||
default: |
|
||||
return io.reactivex.Observable.error(new Throwable(authentication.getMessage())); |
|
||||
} |
|
||||
}) |
|
||||
.observeOn(AndroidSchedulers.mainThread()) |
|
||||
.retryWhen(errors -> errors.flatMap( |
|
||||
error -> { |
|
||||
if (error instanceof BiometricExceptions.BiometricAuthFailedException) { |
|
||||
view.addFingerprintIcon(false); |
|
||||
// view.addSecureIcon(); |
|
||||
} else if (error instanceof SecurityUtils.FailedFingerPrintException || error instanceof SecurityUtils.SensorNotReadyException) { |
|
||||
view.animateFingerPrintAppearAnimationIfRequired(true); |
|
||||
view.showToastMessage(error.getMessage()); |
|
||||
return Observable.timer(100, TimeUnit.MILLISECONDS); |
|
||||
} |
|
||||
return Observable.error(error); |
|
||||
} |
|
||||
)) |
|
||||
.map(FingerprintDecryptionResult::getDecrypted); |
|
||||
|
|
||||
|
|
||||
} |
|
||||
|
|
||||
|
|
||||
@Override |
|
||||
public boolean checkIfRequiredOTPScreen() { |
|
||||
return "autodebit".equalsIgnoreCase(selectedPaymentType); |
|
||||
} |
|
||||
|
|
||||
@Override |
|
||||
public void verifyTxnType() { |
|
||||
if (checkIfRequiredOTPScreen()) { |
|
||||
view.setupAutoDebitTxnPasswordPromptView(); |
|
||||
view.addFingerprintIcon(false); |
|
||||
} else { |
|
||||
view.setupWalletTxnPasswordPromptView(); |
|
||||
if (checkIfUserHasEnabledBiometricAuth()) |
|
||||
view.addFingerprintIcon(true); |
|
||||
else view.addFingerprintIcon(false); |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
|
|
||||
class ResendRequestObserver extends GenericApiObserverResponseV2<MessageResponseDataModel> { |
|
||||
|
|
||||
@Override |
|
||||
protected void onSuccess(GenericResponseDataModel<MessageResponseDataModel> response) { |
|
||||
if (response.getErrorCode().equalsIgnoreCase(Constants.SUCCESS_CODE_V2)) { |
|
||||
view.showPopUpMessage(response.getMsg(), CustomAlertDialog.AlertType.SUCCESS, alertType -> { |
|
||||
view.showResendRequestView(false); |
|
||||
view.startCountdownView(120000); |
|
||||
}); |
|
||||
} else { |
|
||||
view.showPopUpMessage(response.getMsg(), CustomAlertDialog.AlertType.FAILED, alertType -> { |
|
||||
view.showResendRequestView(true); |
|
||||
}); |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
@Override |
|
||||
public void onFailed(String message) { |
|
||||
view.showPopUpMessage(message, CustomAlertDialog.AlertType.FAILED, alertType -> view.exitView()); |
|
||||
} |
|
||||
|
|
||||
@Override |
|
||||
protected void onConnectionNotEstablished(String message) { |
|
||||
view.showPopUpMessage(message, CustomAlertDialog.AlertType.NO_INTERNET, null); |
|
||||
view.showResendRequestView(true); |
|
||||
|
|
||||
} |
|
||||
|
|
||||
@Override |
|
||||
protected void unauthorizedAccess(String message) { |
|
||||
gateway.clearAllUserData(); |
|
||||
view.showPopUpMessage(message, CustomAlertDialog.AlertType.ALERT, alertType -> view.logout()); |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
public class FingerprintDecResult { |
|
||||
String userId; |
|
||||
String userPwd; |
|
||||
|
|
||||
public FingerprintDecResult(String userId, String userPwd) { |
|
||||
this.userId = userId; |
|
||||
this.userPwd = userPwd; |
|
||||
} |
|
||||
|
|
||||
public String getUserId() { |
|
||||
return userId; |
|
||||
} |
|
||||
|
|
||||
public String getUserPwd() { |
|
||||
return userPwd; |
|
||||
} |
|
||||
|
|
||||
@Override |
|
||||
public String toString() { |
|
||||
return "UserCredentialDecryptionResultDTO{" + |
|
||||
"userId='" + userId + '\'' + |
|
||||
", userPwd='" + userPwd + '\'' + |
|
||||
'}'; |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
public class FingerprintDecResultObserver extends DisposableObserver<FingerprintDecResult> { |
|
||||
|
|
||||
@Override |
|
||||
public void onNext(FingerprintDecResult fingerprintDecResult) { |
|
||||
Log.d(SecurityUtils.TAG, "Success : " + fingerprintDecResult.toString()); |
|
||||
|
|
||||
view.onBiometricAuthSuccess(fingerprintDecResult.getUserPwd()); |
|
||||
|
|
||||
} |
|
||||
|
|
||||
@Override |
|
||||
public void onError(Throwable e) { |
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && e instanceof KeyPermanentlyInvalidatedException) |
|
||||
{ |
|
||||
view.addFingerprintIcon(false); |
|
||||
gateway.flushBiometricData(); |
|
||||
view.showPopUpMessage(getStringfromStringId(R.string.fingerprint_changed_externally),CustomAlertDialog.AlertType.ALERT,null); |
|
||||
} |
|
||||
|
|
||||
Log.d(SecurityUtils.TAG, "Failed : " + e.getMessage()); |
|
||||
|
|
||||
} |
|
||||
|
|
||||
@Override |
|
||||
public void onComplete() { |
|
||||
|
|
||||
} |
|
||||
} |
|
||||
} |
|
@ -1,46 +0,0 @@ |
|||||
package com.gmeremit.online.gmeremittance_native.transactionpasspromt.presenter; |
|
||||
|
|
||||
import android.content.Context; |
|
||||
|
|
||||
import com.gmeremit.online.gmeremittance_native.base.BaseContractInterface; |
|
||||
import com.gmeremit.online.gmeremittance_native.base.BasePresenterInterface; |
|
||||
|
|
||||
public interface TransactionPasswordPromptV2PresenterInterface extends BasePresenterInterface { |
|
||||
void getOtp(); |
|
||||
|
|
||||
void updateCountdown(long millisUntilFinished); |
|
||||
|
|
||||
long getLatestCountDownValue(); |
|
||||
|
|
||||
void updateSelectedAmount(String selectedAmount); |
|
||||
|
|
||||
void updateSelectedKftcId(String selectedKftcId); |
|
||||
|
|
||||
boolean checkIfUserHasEnabledBiometricAuth(); |
|
||||
|
|
||||
|
|
||||
void startObservingFingerPrintIfRequired(boolean action); |
|
||||
|
|
||||
boolean checkIfRequiredOTPScreen(); |
|
||||
|
|
||||
void verifyTxnType(); |
|
||||
|
|
||||
|
|
||||
interface TransactionPasswordPromptV2ContractInterface extends BaseContractInterface { |
|
||||
void startCountdownView(long durationMillisecond); |
|
||||
void showResendRequestView(boolean action); |
|
||||
|
|
||||
Context getContext(); |
|
||||
|
|
||||
void onBiometricAuthSuccess(String decPassword); |
|
||||
|
|
||||
void animateFingerPrintAppearAnimationIfRequired(boolean action); |
|
||||
|
|
||||
void setupAutoDebitTxnPasswordPromptView(); |
|
||||
void setupWalletTxnPasswordPromptView(); |
|
||||
void addFingerprintIcon(boolean action); |
|
||||
|
|
||||
void clearImageView(); |
|
||||
|
|
||||
} |
|
||||
} |
|
@ -1,240 +0,0 @@ |
|||||
package com.gmeremit.online.gmeremittance_native.transactionpasspromt.view; |
|
||||
|
|
||||
import android.app.Dialog; |
|
||||
import android.content.SharedPreferences; |
|
||||
import android.os.Build; |
|
||||
import android.os.Bundle; |
|
||||
import android.os.Handler; |
|
||||
import android.security.keystore.KeyPermanentlyInvalidatedException; |
|
||||
|
|
||||
import androidx.vectordrawable.graphics.drawable.AnimatedVectorDrawableCompat; |
|
||||
import androidx.appcompat.app.AlertDialog; |
|
||||
|
|
||||
import android.util.Log; |
|
||||
import android.view.Gravity; |
|
||||
import android.view.View; |
|
||||
import android.widget.ImageView; |
|
||||
import android.widget.TextView; |
|
||||
import android.widget.Toast; |
|
||||
|
|
||||
import androidx.fragment.app.DialogFragment; |
|
||||
|
|
||||
import com.gmeremit.online.gmeremittance_native.GmeApplication; |
|
||||
import com.gmeremit.online.gmeremittance_native.R; |
|
||||
import com.gmeremit.online.gmeremittance_native.base.PrefKeys; |
|
||||
import com.gmeremit.online.gmeremittance_native.security.utils.SecurityUtils; |
|
||||
import com.mtramin.rxfingerprint.data.BiometricExceptions; |
|
||||
import com.mtramin.rxfingerprint.data.FingerprintDecryptionResult; |
|
||||
|
|
||||
import java.util.concurrent.TimeUnit; |
|
||||
|
|
||||
import io.reactivex.Observable; |
|
||||
import io.reactivex.android.schedulers.AndroidSchedulers; |
|
||||
import io.reactivex.disposables.CompositeDisposable; |
|
||||
import io.reactivex.disposables.Disposable; |
|
||||
import io.reactivex.observers.DisposableObserver; |
|
||||
import io.reactivex.schedulers.Schedulers; |
|
||||
|
|
||||
public class TransactionBiometricPromptDialog extends DialogFragment { |
|
||||
|
|
||||
|
|
||||
private AnimatedVectorDrawableCompat fingerPrintAVDCompat; |
|
||||
private ImageView passwordPromptImageView; |
|
||||
private Disposable fingerPrintScanningSubscription; |
|
||||
private CompositeDisposable compositeDisposable; |
|
||||
private BiometricPromptResultListener listener; |
|
||||
private View cancelTxt; |
|
||||
|
|
||||
|
|
||||
@Override |
|
||||
public Dialog onCreateDialog(Bundle savedInstanceState) { |
|
||||
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity()); |
|
||||
View view = getActivity().getLayoutInflater().inflate(R.layout.dialog_password_prompt_v2, null); |
|
||||
passwordPromptImageView = view.findViewById(R.id.passwordPromptImageView); |
|
||||
cancelTxt = view.findViewById(R.id.cancel_txt); |
|
||||
builder.setView(view); |
|
||||
Dialog dialog = builder.create(); |
|
||||
try { |
|
||||
dialog.getWindow().setBackgroundDrawableResource(R.drawable.ic_rounded_white); |
|
||||
|
|
||||
} catch (NullPointerException e) { |
|
||||
|
|
||||
} |
|
||||
initialize(); |
|
||||
return dialog; |
|
||||
|
|
||||
} |
|
||||
|
|
||||
private void initialize() { |
|
||||
this.compositeDisposable = new CompositeDisposable(); |
|
||||
fingerPrintAVDCompat = AnimatedVectorDrawableCompat.create(getActivity(), R.drawable.avd_fp); |
|
||||
|
|
||||
} |
|
||||
|
|
||||
public void setResultListener(BiometricPromptResultListener listener) { |
|
||||
this.listener = listener; |
|
||||
} |
|
||||
|
|
||||
@Override |
|
||||
public void onStart() { |
|
||||
super.onStart(); |
|
||||
startObservingFingerPrintIfRequired(true); |
|
||||
cancelTxt.setOnClickListener(new View.OnClickListener() { |
|
||||
@Override |
|
||||
public void onClick(View v) { |
|
||||
dismiss(); |
|
||||
} |
|
||||
}); |
|
||||
} |
|
||||
|
|
||||
@Override |
|
||||
public void onStop() { |
|
||||
super.onStop(); |
|
||||
startObservingFingerPrintIfRequired(false); |
|
||||
cancelTxt.setOnClickListener(null); |
|
||||
} |
|
||||
|
|
||||
public void animateFingerPrintAppearAnimationIfRequired(boolean action) { |
|
||||
if (action) { |
|
||||
if (fingerPrintAVDCompat != null && !fingerPrintAVDCompat.isRunning()) { |
|
||||
passwordPromptImageView.setImageDrawable(fingerPrintAVDCompat); |
|
||||
fingerPrintAVDCompat.start(); |
|
||||
} |
|
||||
} else { |
|
||||
passwordPromptImageView.setImageDrawable(null); |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
public void startObservingFingerPrintIfRequired(boolean action) { |
|
||||
|
|
||||
if (!action) { |
|
||||
if (fingerPrintScanningSubscription != null && !fingerPrintScanningSubscription.isDisposed()) |
|
||||
fingerPrintScanningSubscription.dispose(); |
|
||||
} else { |
|
||||
animateFingerPrintAppearAnimationIfRequired(true); |
|
||||
fingerPrintScanningSubscription = authenticateFingerprint().subscribeWith(new FingerprintDecResultObserver()); |
|
||||
compositeDisposable.add(fingerPrintScanningSubscription); |
|
||||
} |
|
||||
|
|
||||
|
|
||||
} |
|
||||
|
|
||||
private Observable<FingerprintDecResult> authenticateFingerprint() { |
|
||||
return Observable.zip(Observable.fromCallable(() -> GmeApplication.getStorage().getString(PrefKeys.APP_USER_ID_SECRET_KEY, null)), |
|
||||
Observable.fromCallable(() -> GmeApplication.getStorage().getString(PrefKeys.APP_SECRET_KEY, null)) |
|
||||
.flatMap(storedKey -> decryptFromKeyStore(storedKey).flatMap(decAesKey -> SecurityUtils.decryptUsingAES(GmeApplication.getStorage().getString(PrefKeys.APP_USER_SECRET_KEY, null), decAesKey))) |
|
||||
.subscribeOn(Schedulers.io()), |
|
||||
FingerprintDecResult::new) |
|
||||
.doOnSubscribe(subs -> { |
|
||||
animateFingerPrintAppearAnimationIfRequired(true); |
|
||||
}) |
|
||||
.observeOn(AndroidSchedulers.mainThread()); |
|
||||
} |
|
||||
|
|
||||
private Observable<String> decryptFromKeyStore(String data) { |
|
||||
return SecurityUtils.decryptUsingKeyStore(getActivity(),null, data) |
|
||||
.flatMap(authentication -> { |
|
||||
switch (authentication.getResult()) { |
|
||||
case FAILED: |
|
||||
return io.reactivex.Observable.error(new SecurityUtils.FailedFingerPrintException(getString(R.string.fingerprint_not_recognized))); |
|
||||
case HELP: |
|
||||
return io.reactivex.Observable.error(new SecurityUtils.SensorNotReadyException(authentication.getMessage())); |
|
||||
case AUTHENTICATED: |
|
||||
return Observable.just(authentication); |
|
||||
default: |
|
||||
return io.reactivex.Observable.error(new Throwable(authentication.getMessage())); |
|
||||
} |
|
||||
}) |
|
||||
.observeOn(AndroidSchedulers.mainThread()) |
|
||||
.retryWhen(errors -> errors.flatMap( |
|
||||
error -> { |
|
||||
if (error instanceof SecurityUtils.FailedFingerPrintException || error instanceof SecurityUtils.SensorNotReadyException) { |
|
||||
animateFingerPrintAppearAnimationIfRequired(true); |
|
||||
showToastMessage(error.getMessage()); |
|
||||
return Observable.timer(100, TimeUnit.MILLISECONDS); |
|
||||
} |
|
||||
return Observable.error(error); |
|
||||
} |
|
||||
)) |
|
||||
.map(FingerprintDecryptionResult::getDecrypted); |
|
||||
|
|
||||
|
|
||||
} |
|
||||
|
|
||||
private void showToastMessage(String message) { |
|
||||
Toast toast = Toast.makeText(getActivity(), message, Toast.LENGTH_SHORT); |
|
||||
TextView v = (TextView) toast.getView().findViewById(android.R.id.message); |
|
||||
if (v != null) v.setGravity(Gravity.CENTER); |
|
||||
toast.show(); |
|
||||
} |
|
||||
|
|
||||
public class FingerprintDecResult { |
|
||||
String userId; |
|
||||
String userPwd; |
|
||||
|
|
||||
public FingerprintDecResult(String userId, String userPwd) { |
|
||||
this.userId = userId; |
|
||||
this.userPwd = userPwd; |
|
||||
} |
|
||||
|
|
||||
public String getUserId() { |
|
||||
return userId; |
|
||||
} |
|
||||
|
|
||||
public String getUserPwd() { |
|
||||
return userPwd; |
|
||||
} |
|
||||
|
|
||||
@Override |
|
||||
public String toString() { |
|
||||
return "UserCredentialDecryptionResultDTO{" + |
|
||||
"userId='" + userId + '\'' + |
|
||||
", userPwd='" + userPwd + '\'' + |
|
||||
'}'; |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
public class FingerprintDecResultObserver extends DisposableObserver<FingerprintDecResult> { |
|
||||
|
|
||||
@Override |
|
||||
public void onNext(FingerprintDecResult fingerprintDecResult) { |
|
||||
dismiss(); |
|
||||
if (listener != null) |
|
||||
listener.onBiometricAuthSuccess(fingerprintDecResult.getUserPwd()); |
|
||||
|
|
||||
} |
|
||||
|
|
||||
@Override |
|
||||
public void onError(Throwable e) { |
|
||||
|
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && e instanceof KeyPermanentlyInvalidatedException) { |
|
||||
|
|
||||
SharedPreferences.Editor editor = GmeApplication.getStorage().edit(); |
|
||||
editor.putString(PrefKeys.APP_USER_ID_SECRET_KEY, null); |
|
||||
editor.putBoolean(PrefKeys.APP_FINGER_PRINT_ENABLED, false); |
|
||||
editor.putString(PrefKeys.APP_USER_SECRET_KEY, null); |
|
||||
editor.putString(PrefKeys.APP_SECRET_KEY, null); |
|
||||
editor.apply(); |
|
||||
|
|
||||
showToastMessage(getString(R.string.fingerprint_changed_externally)); |
|
||||
} else if (e instanceof BiometricExceptions.BiometricAuthFailedException) { |
|
||||
showToastMessage(e.getMessage()); |
|
||||
new Handler().postDelayed(TransactionBiometricPromptDialog.this::dismiss, 200); |
|
||||
} |
|
||||
|
|
||||
Log.d(SecurityUtils.TAG, "Failed : " + e.getMessage()); |
|
||||
|
|
||||
} |
|
||||
|
|
||||
@Override |
|
||||
public void onComplete() { |
|
||||
|
|
||||
} |
|
||||
} |
|
||||
|
|
||||
|
|
||||
public interface BiometricPromptResultListener { |
|
||||
void onBiometricAuthSuccess(String decResult); |
|
||||
} |
|
||||
|
|
||||
} |
|
@ -1,453 +0,0 @@ |
|||||
package com.gmeremit.online.gmeremittance_native.transactionpasspromt.view; |
|
||||
|
|
||||
import android.annotation.SuppressLint; |
|
||||
import android.app.Activity; |
|
||||
import android.content.Context; |
|
||||
import android.content.Intent; |
|
||||
import android.content.pm.ActivityInfo; |
|
||||
import android.graphics.Rect; |
|
||||
import android.os.Build; |
|
||||
import android.os.Bundle; |
|
||||
import android.os.CountDownTimer; |
|
||||
import android.os.Handler; |
|
||||
import androidx.vectordrawable.graphics.drawable.AnimatedVectorDrawableCompat; |
|
||||
import androidx.core.content.ContextCompat; |
|
||||
import androidx.core.view.GestureDetectorCompat; |
|
||||
import androidx.appcompat.app.AppCompatDelegate; |
|
||||
import android.text.Spannable; |
|
||||
import android.text.SpannableString; |
|
||||
import android.text.style.ForegroundColorSpan; |
|
||||
import android.view.GestureDetector; |
|
||||
import android.view.MotionEvent; |
|
||||
import android.view.View; |
|
||||
import android.view.ViewGroup; |
|
||||
import android.view.Window; |
|
||||
import android.widget.FrameLayout; |
|
||||
import android.widget.ImageView; |
|
||||
import android.widget.RelativeLayout; |
|
||||
import android.widget.TextView; |
|
||||
|
|
||||
import com.gmeremit.online.gmeremittance_native.R; |
|
||||
import com.gmeremit.online.gmeremittance_native.base.BaseActivity; |
|
||||
import com.gmeremit.online.gmeremittance_native.customwidgets.GmeErrorTextView; |
|
||||
import com.gmeremit.online.gmeremittance_native.transactionpasspromt.gateway.TransactionPasswordPromptV2Gateway; |
|
||||
import com.gmeremit.online.gmeremittance_native.transactionpasspromt.presenter.TransactionPasswordPromptV2Presenter; |
|
||||
import com.gmeremit.online.gmeremittance_native.transactionpasspromt.presenter.TransactionPasswordPromptV2PresenterInterface; |
|
||||
import com.gmeremit.online.gmeremittance_native.security.securitykeypad.SecurityKeyboardManager; |
|
||||
import com.gmeremit.online.gmeremittance_native.security.securitykeypad.SecurityKeyboardView; |
|
||||
import com.gmeremit.online.gmeremittance_native.security.securitykeypad.SecurityKeypadRequestParamBuilder; |
|
||||
import com.softsecurity.transkey.TransKeyActivity; |
|
||||
|
|
||||
import java.util.Locale; |
|
||||
|
|
||||
import butterknife.BindView; |
|
||||
import butterknife.ButterKnife; |
|
||||
|
|
||||
public class TransactionPasswordPromptActivity extends BaseActivity implements SecurityKeyboardView.SecurityKeyboardFocusStateListener, TransactionPasswordPromptV2PresenterInterface.TransactionPasswordPromptV2ContractInterface, View.OnClickListener { |
|
||||
|
|
||||
static { |
|
||||
AppCompatDelegate.setCompatVectorFromResourcesEnabled(true); |
|
||||
} |
|
||||
|
|
||||
public static final String OTP_COUNTDOWN_VALUE = "bundleCountdownValue"; |
|
||||
SecurityKeyboardManager securityKeyboardManager; |
|
||||
|
|
||||
@BindView(R.id.securityKeyboard) |
|
||||
SecurityKeyboardView securityKeyboardView; |
|
||||
|
|
||||
@BindView(R.id.keypadContainer) |
|
||||
FrameLayout keypadContainer; |
|
||||
|
|
||||
@BindView(R.id.keypadBallon) |
|
||||
RelativeLayout ballonView; |
|
||||
|
|
||||
@BindView(R.id.title) |
|
||||
TextView title; |
|
||||
|
|
||||
@BindView(R.id.resend_request) |
|
||||
TextView resendRequest; |
|
||||
|
|
||||
@BindView(R.id.rootView) |
|
||||
View rootView; |
|
||||
|
|
||||
@BindView(R.id.passwordPromptImageView) |
|
||||
ImageView passwordPromptImageView; |
|
||||
|
|
||||
@BindView(R.id.orTextView) |
|
||||
TextView orTextView; |
|
||||
|
|
||||
|
|
||||
@BindView(R.id.passwordErrorTxt) |
|
||||
GmeErrorTextView passwordErrorTxt; |
|
||||
private SecurityKeypadListener securityKeypadListener; |
|
||||
private GestureDetectorCompat gestureDetector; |
|
||||
private TransactionPasswordPromptActivityGestureDetector myViewGestureDetector; |
|
||||
|
|
||||
|
|
||||
public static final String TRANSACTION_PWD_ENC_DATA = "bundleKeyEncData"; |
|
||||
public static final String PAYMENT_TYPE_BUNDLE_KEY = "bundleKeyPaymentType"; |
|
||||
public static final String SELECTED_AMT_FOR_OTP_BUNDLE_KEY = "bundleKeySelectedAmtOtp"; |
|
||||
public static final String SELECTED_KFTC_ID_FOR_OTP_BUNDLE_KEY = "bundleKeySelectedKFTCId"; |
|
||||
// private String paymentType; |
|
||||
private TransactionPasswordPromptV2PresenterInterface presenter; |
|
||||
private CountDownTimer countDownTimer; |
|
||||
private AnimatedVectorDrawableCompat fingerPrintAVDCompat; |
|
||||
|
|
||||
|
|
||||
@Override |
|
||||
protected void onCreate(Bundle savedInstanceState) { |
|
||||
enableActivityToTakeScreenShot(false); |
|
||||
super.onCreate(savedInstanceState); |
|
||||
setContentView(R.layout.activity_transaction_password_prompt); |
|
||||
ButterKnife.bind(this); |
|
||||
setUpWindowWithInsets(); |
|
||||
preInit(); |
|
||||
init(); |
|
||||
performDefaultAction(savedInstanceState); |
|
||||
} |
|
||||
|
|
||||
private void setUpWindowWithInsets() { |
|
||||
if (Build.VERSION.SDK_INT == Build.VERSION_CODES.O||Build.VERSION.SDK_INT==Build.VERSION_CODES.O_MR1) { |
|
||||
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED); |
|
||||
} else { |
|
||||
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT); |
|
||||
} |
|
||||
|
|
||||
Window window = getWindow(); |
|
||||
if (window != null) { |
|
||||
window.getAttributes().windowAnimations = R.style.SlideInAnimation; |
|
||||
window.setBackgroundDrawableResource(R.drawable.ic_rounded_password_prompt_activity_bg); |
|
||||
window.setLayout(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT); |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
private void preInit() { |
|
||||
presenter = new TransactionPasswordPromptV2Presenter(this,new TransactionPasswordPromptV2Gateway(), getIntent().getStringExtra(PAYMENT_TYPE_BUNDLE_KEY)); |
|
||||
if (presenter.checkIfRequiredOTPScreen()) { |
|
||||
presenter.updateCountdown(getIntent().getLongExtra(OTP_COUNTDOWN_VALUE, -1)); |
|
||||
presenter.updateSelectedAmount(getIntent().getStringExtra(SELECTED_AMT_FOR_OTP_BUNDLE_KEY)); |
|
||||
presenter.updateSelectedKftcId(getIntent().getStringExtra(SELECTED_KFTC_ID_FOR_OTP_BUNDLE_KEY)); |
|
||||
} |
|
||||
else |
|
||||
resendRequest.setVisibility(View.GONE); |
|
||||
} |
|
||||
|
|
||||
private void init() { |
|
||||
securityKeyboardView.setKeyboardContainerView(keypadContainer); |
|
||||
securityKeyboardView.setKeyboardBallonView(ballonView); |
|
||||
securityKeypadListener = new SecurityKeypadListener(); |
|
||||
myViewGestureDetector = new TransactionPasswordPromptActivityGestureDetector(); |
|
||||
gestureDetector = new GestureDetectorCompat(this, myViewGestureDetector); |
|
||||
|
|
||||
try { |
|
||||
securityKeyboardManager = new SecurityKeyboardManager(this); |
|
||||
SecurityKeypadRequestParamBuilder request = new SecurityKeypadRequestParamBuilder(this); |
|
||||
request.disableKeyPadEffect(false); |
|
||||
presenter.verifyTxnType(); |
|
||||
} catch (Exception e) { |
|
||||
e.printStackTrace(); |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
|
|
||||
private void performDefaultAction(Bundle savedInstanceState) { |
|
||||
securityKeyboardManager.showKeyboard(); |
|
||||
if (presenter.checkIfRequiredOTPScreen()) { |
|
||||
new Handler().postDelayed(() -> { |
|
||||
presenter.getOtp(); |
|
||||
}, 400); |
|
||||
} |
|
||||
|
|
||||
} |
|
||||
|
|
||||
|
|
||||
@Override |
|
||||
public boolean dispatchTouchEvent(MotionEvent ev) { |
|
||||
return (securityKeyboardView.checkIfTouchIntersectKeypadLayout(ev) || gestureDetector.onTouchEvent(ev) || super.dispatchTouchEvent(ev)); |
|
||||
|
|
||||
} |
|
||||
|
|
||||
private boolean checkIfTouchOutsiedRootView(float x, float y) { |
|
||||
int posX = (int) x; |
|
||||
int posY = (int) y; |
|
||||
|
|
||||
int[] rootViewLeftAndTopCoordinates = new int[2]; |
|
||||
rootView.getLocationOnScreen(rootViewLeftAndTopCoordinates); |
|
||||
Rect rootViewBoundRect = new Rect(rootViewLeftAndTopCoordinates[0], rootViewLeftAndTopCoordinates[1], |
|
||||
rootViewLeftAndTopCoordinates[0] + rootView.getMeasuredWidth(), |
|
||||
rootViewLeftAndTopCoordinates[1] + rootView.getMeasuredHeight()); |
|
||||
|
|
||||
return !rootViewBoundRect.contains(posX, posY); |
|
||||
} |
|
||||
|
|
||||
@Override |
|
||||
protected void onStart() { |
|
||||
super.onStart(); |
|
||||
securityKeyboardView.setSecurityKeyboardFocusStateListener(this); |
|
||||
if (presenter.checkIfRequiredOTPScreen()) |
|
||||
resendRequest.setOnClickListener(this); |
|
||||
else |
|
||||
presenter.startObservingFingerPrintIfRequired(true); |
|
||||
} |
|
||||
|
|
||||
@Override |
|
||||
protected void onStop() { |
|
||||
super.onStop(); |
|
||||
securityKeyboardView.setSecurityKeyboardFocusStateListener(null); |
|
||||
if (presenter.checkIfRequiredOTPScreen()) |
|
||||
resendRequest.setOnClickListener(null); |
|
||||
else |
|
||||
presenter.startObservingFingerPrintIfRequired(false); |
|
||||
} |
|
||||
|
|
||||
@Override |
|
||||
protected void onResume() { |
|
||||
super.onResume(); |
|
||||
} |
|
||||
|
|
||||
@Override |
|
||||
protected void onPause() { |
|
||||
super.onPause(); |
|
||||
|
|
||||
} |
|
||||
|
|
||||
@SuppressLint("NewApi") |
|
||||
@Override |
|
||||
public void animateFingerPrintAppearAnimationIfRequired(boolean action) { |
|
||||
if (action) { |
|
||||
if (fingerPrintAVDCompat != null && !fingerPrintAVDCompat.isRunning()) { |
|
||||
passwordPromptImageView.setImageDrawable(fingerPrintAVDCompat); |
|
||||
fingerPrintAVDCompat.start(); |
|
||||
} |
|
||||
|
|
||||
} else { |
|
||||
passwordPromptImageView.setImageDrawable(null); |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
@Override |
|
||||
public void setupAutoDebitTxnPasswordPromptView() { |
|
||||
SecurityKeypadRequestParamBuilder request = new SecurityKeypadRequestParamBuilder(this); |
|
||||
request.disableKeyPadEffect(false); |
|
||||
request.setKeypadType(TransKeyActivity.mTK_TYPE_KEYPAD_NUMBER); |
|
||||
request.setHintString(getString(R.string.otp_password_hint_text)); |
|
||||
title.setText(getString(R.string.enter_otp_password_text)); |
|
||||
request.setMaxLength(4); |
|
||||
ballonView.setVisibility(View.INVISIBLE); |
|
||||
securityKeyboardManager.bindWithSecurityWidgetView(securityKeyboardView) |
|
||||
.setBallonView(ballonView) |
|
||||
.setKeyboardContainer(keypadContainer) |
|
||||
.setRequestParams(request) |
|
||||
.setActionListener(securityKeypadListener) |
|
||||
.build(); |
|
||||
} |
|
||||
|
|
||||
@Override |
|
||||
public void setupWalletTxnPasswordPromptView() { |
|
||||
SecurityKeypadRequestParamBuilder request = new SecurityKeypadRequestParamBuilder(this); |
|
||||
request.disableKeyPadEffect(false); |
|
||||
request.setHintString(getString(R.string.password_text)); |
|
||||
title.setText(getString(R.string.enter_login_password_text)); |
|
||||
resendRequest.setVisibility(View.INVISIBLE); |
|
||||
securityKeyboardManager.bindWithSecurityWidgetView(securityKeyboardView) |
|
||||
.setBallonView(ballonView) |
|
||||
.setKeyboardContainer(keypadContainer) |
|
||||
.setRequestParams(request) |
|
||||
.setActionListener(securityKeypadListener) |
|
||||
.build(); |
|
||||
} |
|
||||
|
|
||||
@Override |
|
||||
public void addFingerprintIcon(boolean action) { |
|
||||
if (action) { |
|
||||
orTextView.setVisibility(View.VISIBLE); |
|
||||
passwordPromptImageView.setImageResource(0); |
|
||||
passwordPromptImageView.setImageDrawable(null); |
|
||||
if (fingerPrintAVDCompat == null) |
|
||||
fingerPrintAVDCompat = AnimatedVectorDrawableCompat.create(this, R.drawable.avd_fp); |
|
||||
} else { |
|
||||
orTextView.setVisibility(View.GONE); |
|
||||
fingerPrintAVDCompat = null; |
|
||||
passwordPromptImageView.setImageResource(0); |
|
||||
passwordPromptImageView.setImageDrawable(null); |
|
||||
passwordPromptImageView.setImageResource(R.drawable.ic_penny_test_pending); |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
@Override |
|
||||
public void clearImageView() { |
|
||||
passwordPromptImageView.setImageResource(0); |
|
||||
passwordPromptImageView.setImageDrawable(null); |
|
||||
} |
|
||||
|
|
||||
@Override |
|
||||
public void onSecurityViewRecievedFocus() { |
|
||||
if (securityKeyboardManager != null && !securityKeyboardManager.isKeyboardVisible()) |
|
||||
securityKeyboardManager.showKeyboard(); |
|
||||
} |
|
||||
|
|
||||
@Override |
|
||||
public void onSecurityViewLostFocus() { |
|
||||
|
|
||||
} |
|
||||
|
|
||||
@Override |
|
||||
public void startCountdownView(long durationMillisecond) { |
|
||||
countDownTimer = new CountDownTimer(durationMillisecond, 1000) { |
|
||||
|
|
||||
int redColor = ContextCompat.getColor(TransactionPasswordPromptActivity.this, R.color.colorPrimary); |
|
||||
int grayColor = ContextCompat.getColor(TransactionPasswordPromptActivity.this, R.color.darkgray2); |
|
||||
|
|
||||
@Override |
|
||||
public void onTick(long millisUntilFinished) { |
|
||||
presenter.updateCountdown(millisUntilFinished); |
|
||||
int seconds = (int) (millisUntilFinished / 1000); |
|
||||
|
|
||||
int hours = seconds / (60 * 60); |
|
||||
int tempMint = (seconds - (hours * 60 * 60)); |
|
||||
int minutes = tempMint / 60; |
|
||||
seconds = tempMint - (minutes * 60); |
|
||||
|
|
||||
String timeRemaining = String.format(Locale.US, "%02d", minutes) |
|
||||
+ ":" + String.format(Locale.US, "%02d", seconds); |
|
||||
|
|
||||
Spannable tryInText = new SpannableString(getString(R.string.resend_code_text)); |
|
||||
tryInText.setSpan(new ForegroundColorSpan(grayColor), 0, tryInText.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); |
|
||||
resendRequest.setText(tryInText); |
|
||||
|
|
||||
Spannable timeText = new SpannableString(" " + timeRemaining); |
|
||||
timeText.setSpan(new ForegroundColorSpan(redColor), 0, timeText.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); |
|
||||
|
|
||||
resendRequest.append(timeText); |
|
||||
} |
|
||||
|
|
||||
@Override |
|
||||
public void onFinish() { |
|
||||
showResendRequestView(true); |
|
||||
presenter.updateCountdown(-1); |
|
||||
} |
|
||||
|
|
||||
|
|
||||
}; |
|
||||
countDownTimer.start(); |
|
||||
} |
|
||||
|
|
||||
private void updateIntentOnCanellationAndFinish() { |
|
||||
boolean result = presenter.checkIfRequiredOTPScreen(); |
|
||||
if (result) { |
|
||||
Intent backIntent = new Intent(); |
|
||||
setResult(RESULT_CANCELED, backIntent); |
|
||||
backIntent.putExtra(OTP_COUNTDOWN_VALUE, presenter.getLatestCountDownValue()); |
|
||||
} |
|
||||
finish(); |
|
||||
} |
|
||||
|
|
||||
@Override |
|
||||
public void showResendRequestView(boolean action) { |
|
||||
if (resendRequest.getVisibility() != View.VISIBLE) |
|
||||
resendRequest.setVisibility(View.VISIBLE); |
|
||||
if (action) { |
|
||||
if (countDownTimer != null) |
|
||||
countDownTimer.cancel(); |
|
||||
presenter.updateCountdown(-1); |
|
||||
resendRequest.setText(getString(R.string.resend_request_text)); |
|
||||
resendRequest.setOnClickListener(this); |
|
||||
|
|
||||
} else { |
|
||||
resendRequest.setText(""); |
|
||||
resendRequest.setOnClickListener(null); |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
@Override |
|
||||
public Context getContext() { |
|
||||
return this; |
|
||||
} |
|
||||
|
|
||||
@Override |
|
||||
public void onBiometricAuthSuccess(String decPassword) { |
|
||||
Intent returnIntent = new Intent(); |
|
||||
returnIntent.putExtra(TRANSACTION_PWD_ENC_DATA, decPassword); |
|
||||
setResult(Activity.RESULT_OK, returnIntent); |
|
||||
finish(); |
|
||||
} |
|
||||
|
|
||||
|
|
||||
@Override |
|
||||
public void onBackPressed() { |
|
||||
updateIntentOnCanellationAndFinish(); |
|
||||
} |
|
||||
|
|
||||
@Override |
|
||||
public void onClick(View v) { |
|
||||
switch (v.getId()) { |
|
||||
case R.id.resend_request: |
|
||||
this.presenter.getOtp(); |
|
||||
break; |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
class SecurityKeypadListener implements SecurityKeyboardManager.SecurityKeyboardActionListenerFacade { |
|
||||
@Override |
|
||||
public void done(Intent intent) { |
|
||||
String encData = intent.getStringExtra(TransKeyActivity.mTK_PARAM_SECURE_DATA); |
|
||||
if (validateStringNotEmpty(encData)) { |
|
||||
passwordErrorTxt.setErrorText(null); |
|
||||
Intent returnIntent = new Intent(); |
|
||||
returnIntent.putExtra(TRANSACTION_PWD_ENC_DATA, encData); |
|
||||
setResult(Activity.RESULT_OK, returnIntent); |
|
||||
finish(); |
|
||||
} else { |
|
||||
if (presenter.checkIfRequiredOTPScreen()) |
|
||||
passwordErrorTxt.setErrorText(getString(R.string.otp_empty_error)); |
|
||||
else |
|
||||
passwordErrorTxt.setErrorText(getString(R.string.password_empty_error)); |
|
||||
if (securityKeyboardManager != null && !securityKeyboardManager.isKeyboardVisible()) |
|
||||
securityKeyboardManager.showKeyboard(); |
|
||||
} |
|
||||
|
|
||||
|
|
||||
} |
|
||||
|
|
||||
@Override |
|
||||
public void cancel(Intent intent) { |
|
||||
updateIntentOnCanellationAndFinish(); |
|
||||
} |
|
||||
|
|
||||
private boolean validateStringNotEmpty(String data) { |
|
||||
return (data != null && data.length() > 0); |
|
||||
|
|
||||
} |
|
||||
|
|
||||
@Override |
|
||||
public void input(int i) { |
|
||||
|
|
||||
} |
|
||||
|
|
||||
@Override |
|
||||
public void minTextSizeCallback() { |
|
||||
|
|
||||
} |
|
||||
|
|
||||
@Override |
|
||||
public void maxTextSizeCallback() { |
|
||||
|
|
||||
} |
|
||||
} |
|
||||
|
|
||||
class TransactionPasswordPromptActivityGestureDetector extends GestureDetector.SimpleOnGestureListener { |
|
||||
@Override |
|
||||
public boolean onSingleTapUp(MotionEvent e) { |
|
||||
if (e.getAction() == MotionEvent.ACTION_UP) { |
|
||||
|
|
||||
boolean hasToucheOutsideTheView = checkIfTouchOutsiedRootView(e.getX(), e.getY()); |
|
||||
if (hasToucheOutsideTheView) |
|
||||
updateIntentOnCanellationAndFinish(); |
|
||||
return hasToucheOutsideTheView; |
|
||||
} |
|
||||
return super.onSingleTapUp(e); |
|
||||
} |
|
||||
|
|
||||
|
|
||||
} |
|
||||
} |
|
Write
Preview
Loading…
Cancel
Save
Reference in new issue