package com.taoke.autopay.android.service;
|
|
import android.accessibilityservice.AccessibilityService;
|
import android.content.ClipData;
|
import android.content.ClipboardManager;
|
import android.content.Context;
|
import android.content.Intent;
|
import android.os.Handler;
|
import android.os.Message;
|
import android.text.TextUtils;
|
import android.util.Log;
|
import android.util.Pair;
|
import android.view.accessibility.AccessibilityEvent;
|
import android.view.accessibility.AccessibilityNodeInfo;
|
import android.widget.Toast;
|
|
import androidx.annotation.NonNull;
|
import androidx.core.view.accessibility.AccessibilityNodeInfoCompat;
|
|
import com.apkfuns.logutils.LogUtils;
|
import com.taoke.autopay.android.App;
|
import com.taoke.autopay.android.Constant;
|
import com.taoke.autopay.android.RxBus;
|
import com.taoke.autopay.android.data.local.LocalStore;
|
import com.taoke.autopay.android.data.local.entity.TaskQueueInfo;
|
import com.taoke.autopay.android.data.network.RestAPI;
|
import com.taoke.autopay.android.data.network.entity.Order;
|
import com.taoke.autopay.android.ui.MainActivity;
|
import com.taoke.autopay.android.utils.accessibility.AccessibilityNodeInfoUtils;
|
import com.taoke.autopay.android.utils.accessibility.AccessibilityServiceCompatUtils;
|
import com.taoke.autopay.android.utils.accessibility.ClassNameNodeFilter;
|
import com.taoke.autopay.android.utils.accessibility.NodeFilter;
|
import com.taoke.autopay.android.utils.accessibility.TextContainsNodeFilter;
|
import com.taoke.autopay.android.utils.accessibility.TextNodeFilter;
|
|
import java.util.HashMap;
|
import java.util.Map;
|
import java.util.concurrent.TimeUnit;
|
import java.util.regex.Matcher;
|
import java.util.regex.Pattern;
|
|
import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers;
|
import io.reactivex.rxjava3.core.Single;
|
import io.reactivex.rxjava3.disposables.Disposable;
|
import io.reactivex.rxjava3.schedulers.Schedulers;
|
import io.reactivex.rxjava3.subjects.PublishSubject;
|
import io.reactivex.rxjava3.subjects.Subject;
|
import timber.log.Timber;
|
|
public class ZfbJob extends AbstractJob {
|
|
private static final String TAG = "ZfbJob";
|
private int extraState = 0; // 辅助判断当前执行的位置
|
|
private final Order order;
|
private final Integer payTimes;
|
private final Integer payedTimes;
|
private final String personalPayPwd;
|
private final String businessPayPwd;
|
private int index = 0;
|
|
private final Subject<Pair<AccessibilityService, AccessibilityEvent>> subject = PublishSubject.create();
|
|
private Disposable mDisposableTimeout;
|
private Disposable mDisposable;
|
private Disposable mDisposableClipboardTimeout;
|
|
public ZfbJob(Order order) {
|
this.order = order;
|
this.payTimes = LocalStore.getInstance().getPayTimes();
|
this.payedTimes = LocalStore.getInstance().getPayedTimes();
|
this.personalPayPwd = LocalStore.getInstance().getPersonalPayPwd();
|
this.businessPayPwd = LocalStore.getInstance().getBusinessPayPwd();
|
}
|
|
/**
|
* 向UI界面发送消息
|
*
|
* @param info
|
*/
|
private void sendUIMsg(TaskQueueInfo info) {
|
Context context = App.getInstance();
|
Intent intent = new Intent(context, MainActivity.class);
|
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
intent.putExtra("data", info);
|
context.startActivity(intent);
|
}
|
|
// 支付宝粘贴板弹出超时处理
|
private Handler timehOutHndler = new Handler(new Handler.Callback() {
|
@Override
|
public boolean handleMessage(@NonNull Message msg) {
|
if (extraState == 0) {
|
// 还没识别到粘贴板数据
|
}
|
return false;
|
}
|
});
|
|
@Override
|
public void start() {
|
LogUtils.tag(TAG).i("支付任务启动:" + this.order.id);
|
// 延时1秒启动,防止上一个任务还没处理完成
|
try {
|
Thread.sleep(1000);
|
} catch (InterruptedException e) {
|
throw new RuntimeException(e);
|
}
|
|
extraState = 0;
|
mDisposableTimeout = Single
|
.just(true)
|
.delay(40, TimeUnit.SECONDS)
|
.subscribe(aBoolean -> notifyCancel()); // 一分钟超时,自动取消。
|
mDisposableClipboardTimeout = Single
|
.just(true)
|
.delay(15, TimeUnit.SECONDS)
|
.subscribe(aBoolean -> {
|
if (extraState == 0) {
|
LogUtils.tag(TAG).w("支付宝粘贴板弹出超时");
|
notifyCancel();
|
}
|
});// 任务启动到支付宝粘贴板推荐弹出超时时间
|
mDisposable = subject
|
.debounce(2, TimeUnit.SECONDS)
|
.observeOn(AndroidSchedulers.mainThread())
|
.subscribe(pair -> {
|
AccessibilityService service = pair.first;
|
AccessibilityNodeInfoCompat rootNodeInfoCompat = AccessibilityServiceCompatUtils.getRootInActiveWindow(service);
|
CharSequence orderNo = AccessibilityNodeInfoUtils.getNodeText(AccessibilityNodeInfoUtils.searchFromBfs(service, rootNodeInfoCompat, new TextContainsNodeFilter("-抖音电商-")));
|
|
CharSequence orderStatus = AccessibilityNodeInfoUtils.getNodeText(AccessibilityNodeInfoUtils.searchFromBfs(service, rootNodeInfoCompat, new TextNodeFilter("订单已取消")));
|
if (orderStatus == null) {
|
orderStatus = AccessibilityNodeInfoUtils.getNodeText(AccessibilityNodeInfoUtils.searchFromBfs(service, rootNodeInfoCompat, new TextNodeFilter("已支付")));
|
}
|
if (orderNo == null) {
|
return;
|
}
|
final CharSequence fOrderStatus = orderStatus;
|
// 订单编号提取
|
String orderNoStr = "";
|
Pattern pattern = Pattern.compile("\\d+"); // 匹配连续的数字
|
Matcher matcher = pattern.matcher(orderNo.toString());
|
while (matcher.find()) {
|
String number = matcher.group(); // 获取匹配到的数字字符串
|
if (number.length() > 10) {
|
orderNoStr = number;
|
break;
|
}
|
}
|
if (TextUtils.isEmpty(orderNoStr)) {
|
return;
|
}
|
LogUtils.tag(TAG).i("找到订单号:" + orderNoStr);
|
// 设置订单编号接口
|
if (Constant.TEST) {
|
AccessibilityNodeInfoCompat btnPay = AccessibilityNodeInfoUtils
|
.searchFromBfs(service, rootNodeInfoCompat, new TextNodeFilter("完成本次付款").and(new ClassNameNodeFilter("android.widget.Button")));
|
if (btnPay != null) { // 没找到支付按钮,为空这表示失效过期了
|
LogUtils.tag(TAG).i("找到完成本次付款按钮");
|
extraState = 2;
|
btnPay.performAction(AccessibilityNodeInfoCompat.ACTION_CLICK);
|
}
|
} else {
|
Disposable mDisposable = RestAPI.getInstance().apiService()
|
.setOrderNo(
|
String.valueOf(LocalStore.getInstance().getUser().id),
|
order.id,
|
orderNoStr, orderStatus != null ? orderStatus.toString() : ""
|
)
|
.subscribeOn(Schedulers.io())
|
.observeOn(AndroidSchedulers.mainThread())
|
.subscribe(objectResponseData -> {
|
if (fOrderStatus != null) {
|
LogUtils.tag(TAG).i("订单状态:" + fOrderStatus);
|
// 已支付或者已取消,都视为处理成功
|
notifyFinish();
|
return;
|
}
|
if (objectResponseData.code == 0) {
|
AccessibilityNodeInfoCompat btnPay = AccessibilityNodeInfoUtils
|
.searchFromBfs(service, rootNodeInfoCompat, new TextNodeFilter("完成本次付款").and(new ClassNameNodeFilter("android.widget.Button")));
|
if (btnPay != null) { // 没找到支付按钮,为空这表示失效过期了
|
LogUtils.tag(TAG).i("找到完成本次付款按钮");
|
extraState = 2;
|
btnPay.performAction(AccessibilityNodeInfoCompat.ACTION_CLICK);
|
// 防止弹出不是好友
|
Single
|
.just(true)
|
.delay(5, TimeUnit.SECONDS)
|
.subscribe(aBoolean -> {
|
if(extraState==2){
|
AccessibilityNodeInfoUtils
|
.getSelfOrMatchingAncestor(
|
service,
|
AccessibilityNodeInfoUtils.searchFromBfs(service, rootNodeInfoCompat, new TextNodeFilter("继续支付")),
|
AccessibilityNodeInfoUtils.FILTER_CLICKABLE)
|
.performAction(AccessibilityNodeInfoCompat.ACTION_CLICK);
|
}
|
});// 任务启动到支付宝粘贴板推荐弹出超时时间
|
|
}
|
} else {
|
notifyCancel();
|
Toast.makeText(service.getApplicationContext(), objectResponseData.message, Toast.LENGTH_SHORT).show();
|
}
|
},
|
throwable -> {
|
notifyCancel();
|
Toast.makeText(service.getApplicationContext(), throwable.getMessage(), Toast.LENGTH_SHORT).show();
|
});
|
}
|
});
|
|
// 下面代码避免内存泄漏和设置自动运行结果
|
addJobListener(new JobListener() {
|
@Override
|
public void onCancelled() { // 目前超过设置的次数后,后续任务也会执行这个取消方法
|
// 100表示任务终止
|
extraState = 100;
|
sendUIMsg(new TaskQueueInfo(TaskQueueInfo.STATE_JOB_FINISH));
|
mDisposableTimeout.dispose();
|
mDisposableClipboardTimeout.dispose();
|
mDisposable.dispose();
|
removeJobListener(this);
|
// 调用设置结果接口
|
RestAPI.getInstance().apiService()
|
.setPayResult(
|
String.valueOf(LocalStore.getInstance().getUser().id),
|
order.id,
|
false
|
)
|
.subscribeOn(Schedulers.io())
|
.observeOn(AndroidSchedulers.mainThread())
|
.subscribe();
|
LogUtils.tag(TAG).i("支付取消");
|
LogUtils.getLog2FileConfig().flushAsync();
|
}
|
|
@Override
|
public void onFinished() {
|
extraState = 100;
|
sendUIMsg(new TaskQueueInfo(TaskQueueInfo.STATE_JOB_FINISH));
|
mDisposableTimeout.dispose();
|
mDisposableClipboardTimeout.dispose();
|
mDisposable.dispose();
|
removeJobListener(this);
|
// 调用设置结果接口
|
RestAPI.getInstance().apiService()
|
.setPayResult(
|
String.valueOf(LocalStore.getInstance().getUser().id),
|
order.id,
|
true
|
)
|
.subscribeOn(Schedulers.io())
|
.observeOn(AndroidSchedulers.mainThread())
|
.subscribe();
|
// 成功次数加一
|
Integer times = LocalStore.getInstance().getPayedTimes();
|
times += 1;
|
LocalStore.getInstance().putPayedTimes(times);
|
LogUtils.tag(TAG).i("支付完成");
|
LogUtils.getLog2FileConfig().flushAsync();
|
}
|
|
@Override
|
public void onPayCountLimit() {
|
extraState = 100;
|
mDisposableTimeout.dispose();
|
mDisposableClipboardTimeout.dispose();
|
mDisposable.dispose();
|
removeJobListener(this);
|
// 通知页面弹出更改支付宝
|
sendUIMsg(new TaskQueueInfo(TaskQueueInfo.STATE_PAY_COUNT_LIMIT));
|
LogUtils.tag(TAG).i("支付次数受限");
|
LogUtils.getLog2FileConfig().flushAsync();
|
}
|
});
|
|
// 判断是否超过设置的支付次数
|
if (payedTimes >= payTimes) {
|
notifyPayCountLimit();
|
return;
|
}
|
|
Context context = App.getInstance();
|
ClipboardManager clipboard = (ClipboardManager) context.getSystemService(Context.CLIPBOARD_SERVICE);
|
if (clipboard != null) {
|
clipboard.setPrimaryClip(ClipData.newPlainText("label", order.key));
|
}
|
try {
|
Thread.sleep(100);
|
} catch (InterruptedException e) {
|
throw new RuntimeException(e);
|
}
|
|
// context.startActivity(context.getPackageManager().getLaunchIntentForPackage("com.eg.android.AlipayGphone"));
|
//下面这个是直接打开支付宝首页,但是没有测试。上面一句代码打开支付宝,但是可能不是首页,是上一次的支付宝页面。要保证每次流程正确,可能需要像下面这样打开。
|
LogUtils.tag(TAG).i("启动支付宝:" + this.order.id);
|
context.startActivity(new Intent()
|
.setAction(Intent.ACTION_MAIN)
|
.addCategory(Intent.CATEGORY_HOME)
|
.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED | Intent.FLAG_ACTIVITY_CLEAR_TOP)
|
.setClassName("com.eg.android.AlipayGphone", "com.eg.android.AlipayGphone.AlipayLogin"));
|
}
|
|
private Map<String, AccessibilityNodeInfoCompat> getPersonPwdInput(AccessibilityService service, AccessibilityNodeInfoCompat rootNodeInfoCompat) {
|
Map<String, AccessibilityNodeInfoCompat> numMap = new HashMap<>();
|
// 获取密码输入按钮
|
String[] nums = new String[]{"0", "1", "2", "3", "4", "5", "6", "7", "8", "9"};
|
for (String n : nums) {
|
AccessibilityNodeInfoCompat one = AccessibilityNodeInfoUtils
|
.getSelfOrMatchingAncestor(
|
service,
|
AccessibilityNodeInfoUtils.searchFromBfs(service, rootNodeInfoCompat, new TextNodeFilter(n)),
|
AccessibilityNodeInfoUtils.FILTER_CLICKABLE);
|
if (one != null) {
|
if (one.getText() != null && one.getText().toString().equalsIgnoreCase(n)) {
|
Timber.tag("doWithEvent").d("数字按钮:" + one.getText());
|
numMap.put(n, one);
|
}
|
}
|
}
|
return numMap;
|
}
|
|
|
/**
|
* 获取字母输入键盘(简版)
|
* @param service
|
* @param rootNodeInfoCompat
|
* @return
|
*/
|
private Map<String, AccessibilityNodeInfoCompat> getCompanyPwdInput(AccessibilityService service, AccessibilityNodeInfoCompat rootNodeInfoCompat) {
|
AccessibilityNodeInfoCompat one = AccessibilityNodeInfoUtils
|
.getSelfOrMatchingAncestor(
|
service,
|
AccessibilityNodeInfoUtils.searchFromBfs(service, rootNodeInfoCompat, new TextNodeFilter("123")),
|
new ClassNameNodeFilter("android.widget.TextView"));
|
if (one == null || !"123".equalsIgnoreCase(one.getText() + "")) {
|
return null;
|
}
|
|
Map<String, AccessibilityNodeInfoCompat> numMap = new HashMap<>();
|
// 获取密码输入按钮
|
String[] nums = new String[]{"a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z"};
|
for (String n : nums) {
|
one = AccessibilityNodeInfoUtils
|
.getSelfOrMatchingAncestor(
|
service,
|
AccessibilityNodeInfoUtils.searchFromBfs(service, rootNodeInfoCompat, new TextNodeFilter(n)),
|
new ClassNameNodeFilter("android.widget.TextView"));
|
if (one != null) {
|
if (one.getText() != null && one.getText().toString().equalsIgnoreCase(n)) {
|
Timber.tag("doWithEvent").d("字母按钮:" + one.getText());
|
numMap.put(n, one.getParent());
|
}
|
}
|
}
|
return numMap;
|
}
|
|
|
/**
|
* 获取字母输入键盘
|
* @param service
|
* @param rootNodeInfoCompat
|
* @return
|
*/
|
private Map<String, AccessibilityNodeInfoCompat> getLetterKeyboard(AccessibilityService service, AccessibilityNodeInfoCompat rootNodeInfoCompat) {
|
AccessibilityNodeInfoCompat one = AccessibilityNodeInfoUtils
|
.getSelfOrMatchingAncestor(
|
service,
|
AccessibilityNodeInfoUtils.searchFromBfs(service, rootNodeInfoCompat, new TextNodeFilter("123")),
|
new ClassNameNodeFilter("android.widget.TextView"));
|
if (one == null || !"123".equalsIgnoreCase(one.getText() + "")) {
|
return null;
|
}
|
|
AccessibilityNodeInfoCompat keyboardNode = AccessibilityNodeInfoUtils
|
.searchFromBfs(
|
service,
|
rootNodeInfoCompat,
|
new NodeFilter() {
|
@Override
|
public boolean accept(Context context, AccessibilityNodeInfoCompat node) {
|
return node.getChildCount() >= 33;
|
}
|
});
|
|
if (keyboardNode != null) {
|
Map<String, AccessibilityNodeInfoCompat> lettersMap = new HashMap<>();
|
int count = keyboardNode.getChildCount();
|
// !表示大小写切换 @表示退格键
|
String letters = "qwertyuiopasdfghjkl!zxcvbnm@";
|
for (int i = 1; i < count; i++) {
|
AccessibilityNodeInfoCompat info = keyboardNode.getChild(i);
|
if (letters.length() > i) {
|
lettersMap.put(String.valueOf(letters.charAt(i-1)), info);
|
}
|
}
|
return lettersMap;
|
}
|
|
|
return null;
|
}
|
|
|
private AccessibilityService mAccessibilityService;
|
|
@Override
|
public void doWithEvent(AccessibilityService service, AccessibilityEvent event) {
|
this.mAccessibilityService = service;
|
AccessibilityNodeInfoCompat rootNodeInfoCompat = AccessibilityServiceCompatUtils.getRootInActiveWindow(service);
|
int eventType = event.getEventType();
|
CharSequence className = event.getClassName();
|
|
String sourceText = null;
|
if (event != null && event.getSource() != null)
|
sourceText = event.getSource().getText() + "";
|
LogUtils.tag("doWithEvent").d(String.format("【%d】【%s】【%s】【有根节点:%s】【%s】", extraState, eventType, className + "", rootNodeInfoCompat != null, sourceText));
|
// AccessibilityNodeInfoCompat testNode = AccessibilityNodeInfoUtils.searchFromBfs(service, rootNodeInfoCompat, new TextNodeFilter("p"));
|
// if (testNode != null) {
|
// Timber.tag(TAG).d("找到字母p");
|
// }
|
|
if (className != null) {
|
Timber.tag(TAG).d(className.toString());
|
}
|
if (eventType == AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED
|
&& TextUtils.equals("com.alipay.android.phone.wallet.sharetoken.ui.decode.TextTokenDecodeActivity", className)) {
|
AccessibilityNodeInfoUtils
|
.getSelfOrMatchingAncestor(
|
service,
|
AccessibilityNodeInfoUtils.searchFromBfs(service, rootNodeInfoCompat, new TextNodeFilter("去看看")),
|
AccessibilityNodeInfoUtils.FILTER_CLICKABLE)
|
.performAction(AccessibilityNodeInfoCompat.ACTION_CLICK);
|
extraState = 0;
|
LogUtils.tag(TAG).i("粘贴板弹出");
|
} else if (extraState == 0 && eventType == AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED
|
&& (TextUtils.equals("com.alipay.mobile.nebulax.integration.mpaas.activity.NebulaActivity$Main", className) || TextUtils.equals("com.alipay.mobile.nebulax.xriver.activity.XRiverActivity", className))) {
|
extraState = 1;
|
LogUtils.tag(TAG).i("达到订单页面");
|
} else if (extraState == 1
|
&& eventType == AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED
|
&& (TextUtils.equals("android.widget.ProgressBar", className) || TextUtils.equals("com.alipay.mywebview.sdk.WebView", className))) {
|
subject.onNext(new Pair<>(service, event));
|
} else if (extraState == 2 && eventType == AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED
|
&& TextUtils.equals("com.alipay.mobile.antui.dialog.AUNoticeDialog", className)) { // 不是好友,会弹出这个
|
LogUtils.tag(TAG).i("不是好友弹出框");
|
try {
|
Thread.sleep(1000);
|
} catch (InterruptedException e) {
|
throw new RuntimeException(e);
|
}
|
AccessibilityNodeInfoUtils
|
.getSelfOrMatchingAncestor(
|
service,
|
AccessibilityNodeInfoUtils.searchFromBfs(service, rootNodeInfoCompat, new TextNodeFilter("继续支付")),
|
AccessibilityNodeInfoUtils.FILTER_CLICKABLE)
|
.performAction(AccessibilityNodeInfoCompat.ACTION_CLICK);
|
} else if (extraState == 2 && TextUtils.equals("com.alipay.android.msp.ui.views.MspContainerActivity", className)) {//eventType == AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED
|
extraState = 3;
|
LogUtils.tag(TAG).i("支付页面弹出");
|
} else if (extraState == 3) {
|
AccessibilityNodeInfoCompat btnConfirm = AccessibilityNodeInfoUtils
|
.getSelfOrMatchingAncestor(
|
service,
|
AccessibilityNodeInfoUtils
|
.searchFromBfs(service, rootNodeInfoCompat, new TextNodeFilter("确认付款").and(new ClassNameNodeFilter("android.widget.TextView"))),
|
AccessibilityNodeInfoUtils.FILTER_CLICKABLE);
|
if (btnConfirm == null) { // 非免密输入,输入密码
|
LogUtils.tag(TAG).i("未找到确认付款按钮");
|
// 判断是企业支付键盘还是普通键盘
|
if (rootNodeInfoCompat != null) {
|
Map<String, AccessibilityNodeInfoCompat> numMap = getPersonPwdInput(service, rootNodeInfoCompat);
|
Map<String, AccessibilityNodeInfoCompat> letterMap = getCompanyPwdInput(service, rootNodeInfoCompat);
|
if (numMap.size() == 10) {
|
LogUtils.tag(TAG).i("找到个人支付宝键盘");
|
// 个人密码支付
|
extraState = 4;
|
for (int i = 0; i < personalPayPwd.length(); i++) {
|
numMap.get(personalPayPwd.charAt(i) + "").performAction(AccessibilityNodeInfo.ACTION_CLICK);
|
}
|
LogUtils.tag(TAG).i("个人密码输入完成");
|
extraState = 5;
|
} else if (letterMap != null && letterMap.size() > 10) {
|
if (businessPayPwd == null || TextUtils.isEmpty(businessPayPwd)) {
|
LogUtils.tag(TAG).i("尚未设置企业支付密码");
|
Toast.makeText(service.getApplicationContext(), "尚未设置企业支付密码", Toast.LENGTH_SHORT).show();
|
return;
|
}
|
LogUtils.tag(TAG).i("找到企业支付宝键盘: 数量-" + letterMap.size() + " 密码:" + businessPayPwd);
|
try {
|
for (int i = 0; i < businessPayPwd.length(); i++) {
|
String k = businessPayPwd.charAt(i) + "";
|
if(letterMap.get(k)==null){
|
throw new Exception("密码对应的键盘字母没找到");
|
}
|
}
|
|
for (int i = 0; i < businessPayPwd.length(); i++) {
|
// try {
|
// Thread.sleep(100);
|
// } catch (InterruptedException e) {
|
// throw new RuntimeException(e);
|
// }
|
letterMap.get(businessPayPwd.charAt(i) + "").performAction(AccessibilityNodeInfo.ACTION_CLICK);
|
}
|
} catch (Exception e) {
|
LogUtils.tag(TAG).e("企业支付宝密码输入出错:" + e.getMessage());
|
// 重新查找支付宝键盘
|
Map<String, AccessibilityNodeInfoCompat> allLettersMap = getLetterKeyboard(service, rootNodeInfoCompat);
|
if(allLettersMap!=null&&allLettersMap.size() >= 26){
|
LogUtils.tag(TAG).i("找到键盘26个字母组合:"+allLettersMap.size());
|
try {
|
// 超过26个字母
|
for (int i = 0; i < businessPayPwd.length(); i++) {
|
letterMap.get(businessPayPwd.charAt(i) + "").performAction(AccessibilityNodeInfo.ACTION_CLICK);
|
}
|
LogUtils.tag(TAG).e("企业支付宝全键盘密码输入完成");
|
}catch(Exception ee){
|
LogUtils.tag(TAG).e("企业支付宝全键盘密码输入出错:" + e.getMessage());
|
}
|
}
|
}
|
extraState = 4;
|
LogUtils.tag(TAG).i("企业支付宝密码输入成功");
|
Single
|
.just(true)
|
.delay(5, TimeUnit.SECONDS)
|
.subscribe(aBoolean -> {
|
LogUtils.tag(TAG).i("执行检测确定按钮");
|
// 检测确定按钮
|
AccessibilityNodeInfoCompat surePayBtn = AccessibilityNodeInfoUtils.searchFromBfs(service, rootNodeInfoCompat, new TextNodeFilter("确定"));
|
if (surePayBtn != null) {
|
LogUtils.tag(TAG).i("获取到确定按钮");
|
// 密码输入成功
|
surePayBtn.performAction(AccessibilityNodeInfo.ACTION_CLICK);
|
extraState = 5;
|
}
|
});// 任务启动到支付宝粘贴板推荐弹出超时时间
|
// 获取确认按钮
|
}
|
} else {
|
LogUtils.tag(TAG).i("根节点为空,通知支付安全受限");
|
// 支付被手机安全保护,无法获取到节点,需要回到支付宝界面才能重新开启节点
|
sendUIMsg(new TaskQueueInfo(TaskQueueInfo.STATE_PAY_SAFE_LIMIT));
|
}
|
|
} else { // 免密支付
|
// extraState = 5;
|
LogUtils.tag(TAG).i("找到确认付款按钮");
|
btnConfirm.performAction(AccessibilityNodeInfoCompat.ACTION_CLICK);
|
}
|
} else if (extraState == 4) {
|
if (rootNodeInfoCompat != null) {
|
// 密码输入完成,需要点击确认
|
AccessibilityNodeInfoCompat surePayBtn = AccessibilityNodeInfoUtils.searchFromBfs(service, rootNodeInfoCompat, new TextNodeFilter("确定"));
|
if (surePayBtn != null) {
|
LogUtils.tag(TAG).i("获取到确定按钮");
|
// 密码输入成功
|
surePayBtn.performAction(AccessibilityNodeInfo.ACTION_CLICK);
|
extraState = 5;
|
}
|
} else {
|
LogUtils.tag(TAG).i("获取确定按钮时根节点为空,通知支付安全受限");
|
// 支付被手机安全保护,无法获取到节点,需要回到支付宝界面才能重新开启节点
|
sendUIMsg(new TaskQueueInfo(TaskQueueInfo.STATE_PAY_SAFE_LIMIT));
|
}
|
} else if (extraState == 5) { // 这里可以加强判断,比如判断是否处于支付成功页面(判断是否含有成功页面的元素)。
|
try {
|
Thread.sleep(Constant.TEST ? 5000 : 1000);
|
} catch (Exception e) {
|
|
}
|
notifyFinish();
|
// if(rootNodeInfoCompat==null){
|
// // 支付被手机安全保护,无法获取到节点,需要回到支付宝界面才能重新开启节点
|
// RxBus.getInstance().send(new TaskQueueInfo(TaskQueueInfo.STATE_PAY_SAFE_LIMIT));
|
// return;
|
// }
|
//
|
// AccessibilityNodeInfoCompat resultNodeInfo = AccessibilityNodeInfoUtils.searchFromBfs(service, rootNodeInfoCompat, new TextNodeFilter("代付成功"));
|
// if(resultNodeInfo!=null){
|
// AccessibilityNodeInfoCompat finishBtn = AccessibilityNodeInfoUtils.searchFromBfs(service, rootNodeInfoCompat, new TextNodeFilter("完成"));
|
// if (finishBtn != null) {
|
// finishBtn.performAction(AccessibilityNodeInfo.ACTION_CLICK);
|
// }
|
// notifyFinish();
|
// }
|
}
|
}
|
}
|